Visitar URL original
feat: [OCISDEV-1516] allow group shares in the vault by 2403905 · Pull Request #13260 · owncloud/ocis · GitHub
Skip to content

feat: [OCISDEV-1516] allow group shares in the vault - #13260

Open
2403905 wants to merge 5 commits into
masterfrom
OCISDEV-1516/master
Open

2403905 wants to merge 5 commits into
masterfrom
OCISDEV-1516/master

Conversation

@2403905

@2403905 2403905 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor
  • web: the share dialog searches for groups in vault mode.
  • notifications, userlog: send vault notifications only to the users who hold the VaultMode permission. A group can contain other users.
  • ocis-pkg/vault: add the shared helpers for the vault checks.
  • acceptance: a group invitation to a vault resource now succeeds.

The gateway change is in owncloud/reva#787.

Group shares in the vault (Safe), from the user's point of view

The sharer

  1. In the Safe, the sharer opens the share panel of a file or a folder.
  2. The sharer types a name in the "Invite" field.
  3. The list shows people and groups. Before this change, the list showed only people.
    • The list shows only the people who have the permission to use the Safe.
    • The list shows all groups that match the name.
  4. The sharer selects a group and a role, for example "Can view". Then the sharer clicks "Share".
  5. The share has an expiration date. The default comes from the Safe settings, for example 30 days. The sharer can set a different date before the share is created. Shares to people work the same way.

A group member who has the Safe permission

  1. The member gets an email and an in-app notification. The email does not show the name of the file. It says "a shared item". The in-app notification shows the name.
  2. The member opens the Safe and logs in with MFA, as usual.
  3. The member finds the resource in "Shared with me" in the Safe. The member can use it with the selected role.

A group member who does not have the Safe permission

  • This member gets no email and no in-app notification.
  • This member cannot open the Safe, so this member cannot see the shared resource.
  • The share stays in place for the other members.

When the group changes after the share exists

  • A new member joins the group: the new member gets access through the share. To open the Safe, the member needs the Safe permission and MFA. The new member gets no notification, because the system sends notifications only when the share is created.
  • A member leaves the group: the member loses access to the shared resource.
  • A member loses the Safe permission: the member can no longer open the Safe. The share stays in place for the other members.

When the share is removed or expires

  • The members who have the Safe permission get a notification.
  • The other members get no notification.

The gateway change is in owncloud/reva#787.

Description

Related Issue

  • Fixes <issue_link>

Motivation and Context

How Has This Been Tested?

  • test environment:
  • test case 1:
  • test case 2:
  • ...

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist:

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation ticket raised:

@2403905
2403905 requested a review from a team as a code owner October 28, 2026 11:39
@2403905
2403905 requested a review from kobergj October 28, 2026 11:39
@kw-security

kw-security commented Oct 28, 2026 •

Copy link
Copy Markdown

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues
✅ Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

}

filtered := make([]*user.User, 0, len(users))
for _, u := range users {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd try to include some tracing information around here to know how much time we take to gather the information based on the number of users.
Since we don't know how many users the group will have, we might need to perform more than 1000 requests to the gateway here (the infamous "all users" group, for example), so we might need either caching or a worker pool.

for _, u := range users {
allowed, err := vault.HasVaultMode(ctx, gatewayClient, u.GetId())
if err != nil {
s.logger.Error().Err(err).Str("event", "filterVaultGrantees").Str("userId", u.GetId().GetOpaqueId()).Msg("could not check vault permission, skipped")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm for including the origin of the log message (the "filterVaultGrantees"), but I don't think it's an event. There are already events being handled, so it might be confusing.
I don't think we need that information in this case though. The log message should be good enough to point it here. The "event", "filterVaultGrantees" doesn't seem to add any valuable information here.

Just log the error with the log message and the userid.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to
if inVault {
members = s.filterVaultModeUsers(ctx, gatewayClient, members)
}


// filterVaultUsers removes the users who do not hold the VaultMode permission.
// A group can contain such users, because the gateway does not check the group members.
func (ul *UserlogService) filterVaultUsers(ctx context.Context, gwc gateway.GatewayAPIClient, users []string) []string {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking into account that this is very similar to the code in the notifications service, can we move it to a common place? The "vault.go" file seems fine if there isn't anything better.

@2403905
2403905 force-pushed the OCISDEV-1516/master branch 2 times, most recently from 7c60dca to 04f9e15 Compare October 29, 2026 06:53
Comment thread ocis-pkg/vault/vault.go Outdated
func FilterVaultModeUsers(ctx context.Context, gwc gateway.GatewayAPIClient, userIDs []*user.UserId, onError func(*user.UserId, error)) []*user.UserId {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer(tracerName).Start(ctx, "FilterVaultModeUsers")
defer span.End()
span.SetAttributes(attribute.Int("vault.users.checked", len(userIDs)))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the docs:

// Note that adding attributes at span creation using [WithAttributes] is preferred
// to calling SetAttribute later, as samplers can only consider information
// already present during span creation.

.Tracer(...).Start(ctx, "FilterVaultModeUsers", trace.WithAttributes(attribute.Int(....)))

For the allowed and failed users, we'll have to add them separately (no changes in the code)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Comment thread ocis-pkg/vault/vault.go
eg.SetLimit(maxConcurrentChecks)
for i, id := range userIDs {
eg.Go(func() error {
allowed[i], errs[i] = HasVaultMode(ctx, gwc, id)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is fine because each goroutine will write in a different memory address, but I'd rather have some confirmation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is safe. The code makes both slices at full length before the loop starts, and they never grow. Each goroutine writes only its own index, and eg.Wait() makes the writes visible before the reads. Go 1.22+ gives each loop pass its own i and id.

if err != nil {
return nil, err
}
if len(s.filterVaultModeUsers(ctx, gatewayClient, []*user.UserId{u})) == 0 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not return s.filterVaultModeUsers(ctx, gatewayClient, []*user.UserId{u})), nil?
I'd prefer to return an empty list rather than nil on a successful case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I misunderstood, but we shouldn't return if len==1 and we should go further.
It doesn't matter whether the function returns nil or an empty list because later this will all be reduced to nil anyway

func (s eventsNotifier) ensureGranteeList(ctx context.Context, executant, u *user.UserId, g *group.GroupId, inVault bool) []*user.User {
	granteeList, err := s.getGranteeList(ctx, executant, u, g, inVault)
	if err != nil {
		s.logger.Error().Err(err).Str("event", "ensureGranteeList").Msg("Could not get grantee list")
		return nil
	} else if len(granteeList) == 0 {
		return nil
	}
	return granteeList
}

2403905 and others added 4 commits October 29, 2026 13:55
- web: the share dialog searches for groups in vault mode.
- notifications, userlog: send vault notifications only to the users
  who hold the VaultMode permission. A group can contain other users.
- ocis-pkg/vault: add the shared helpers for the vault checks.
- acceptance: a group invitation to a vault resource now succeeds.

The gateway change is in owncloud/reva#787.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…embers

- Add a scenario outline for a vault resource share to a group: only the
  group members with the VaultMode permission get an in-app
  notification and can download the file. The other members get no
  notification, cannot download the file, and do not see it in the
  Shares space.
- Add a scenario outline for a vault space membership of a group, with
  the space roles Manager, Space Viewer and Space Editor. Only the group
  members with the VaultMode permission get the notification and can
  access the space. The other members cannot download the file and do
  not see the space in their drive list.
- The examples cover the roles Space Admin, Admin, User Light and User.
- Assign the role "Space Admin" to Brian in the group share scenario,
  because the default role has no VaultMode permission.
- Add NotificationContext to the apiVault suite.
- Fix the pull request number in the changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Move the VaultMode recipient filter to ocis-pkg/vault as
  FilterVaultModeUsers. The notifications and userlog services both use
  it.
- Run the checks in parallel, with at most 10 at the same time, so that
  a large group does not block the event handler.
- Add a tracing span with the number of checked, allowed and failed
  users.
- In the notifications service, check the vault permission before the
  settings and user lookups, so that a member without the permission
  costs one call only.
- Log a failed check with the user ID only, without the "event" field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss when sharing

Show a notice in the share form when a group is selected for a vault resource, and add the same information to the "Share with people" help.

Signed-off-by: Matteo <matteo.sonnenholzner@kiteworks.com>
@2403905
2403905 force-pushed the OCISDEV-1516/master branch from 04f9e15 to cd9821a Compare October 29, 2026 12:57
Samplers see only the attributes that exist at span start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@2403905
2403905 requested a review from jvillafanez November 1, 2026 17:57

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants