Skip to content

Commit

Permalink
Restricter: New restriction user/B (#859)
Browse files Browse the repository at this point in the history
* Restricter: New restriction user/B

Fixes #818
  • Loading branch information
ostcar authored Feb 27, 2024
1 parent 4490784 commit 9eea68a
Show file tree
Hide file tree
Showing 6 changed files with 492 additions and 51 deletions.
78 changes: 77 additions & 1 deletion internal/restrict/collection/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
// Y has the OML can_manage_users or higher.
// There exists a committee where Y has the CML can_manage and X is in committee/user_ids.
// X is in a group of a meeting where Y has user.can_see.
// There exists a meeting where Y has the CML can_manage for the meeting's committee X is in meeting/user_ids.
// There is a related object:
// There exists a motion which Y can see and X is a submitter/supporter.
// There exists an option which Y can see and X is the linked content object.
Expand All @@ -32,6 +31,13 @@ import (
//
// Mode A: Y can see X.
//
// Mode B:
//
// Y==X
// Y has the OML can_manage_users or higher.
// There exists a committee where Y has the CML can_manage and X is in committee/user_ids.
// X is in a group of a meeting where Y has user.can_see_sensitive_data.
//
// Mode D: Y can see these fields if at least one condition is true:
//
// Y has the OML can_manage_users or higher.
Expand Down Expand Up @@ -67,6 +73,8 @@ func (u User) Modes(mode string) FieldRestricter {
switch mode {
case "A":
return u.see
case "B":
return u.modeB
case "D":
return u.modeD
case "E":
Expand Down Expand Up @@ -303,6 +311,74 @@ func (User) RequiredObjects(ctx context.Context, ds *dsfetch.Fetch) []UserRequir
}
}

func (u User) modeB(ctx context.Context, ds *dsfetch.Fetch, userIDs ...int) ([]int, error) {
requestUserID, err := perm.RequestUserFromContext(ctx)
if err != nil {
return nil, fmt.Errorf("getting request user: %w", err)
}

isUserManager, err := perm.HasOrganizationManagementLevel(ctx, ds, requestUserID, perm.OMLCanManageUsers)
if err != nil {
return nil, fmt.Errorf("check organization management level: %w", err)
}

if isUserManager {
return userIDs, nil
}

// Precalculated list of userIDs, that the user can see.
allowedUserIDs := set.New[int]()
if requestUserID != 0 {
allowedUserIDs.Add(requestUserID)

// Get all userIDs of committees, where the request user is manager.
commiteeIDs, err := perm.ManagementLevelCommittees(ctx, ds, requestUserID)
if err != nil {
return nil, fmt.Errorf("getting committee ids: %w", err)
}

for _, committeeID := range commiteeIDs {
userIDs, err := ds.Committee_UserIDs(committeeID).Value(ctx)
if err != nil {
return nil, fmt.Errorf("fetching users from committee %d: %w", committeeID, err)
}
allowedUserIDs.Add(userIDs...)
}

}

return eachCondition(userIDs, func(otherUserID int) (bool, error) {
if allowedUserIDs.Has(otherUserID) {
return true, nil
}

// Check if the user is in a meeting, where the request user can
// user.can_see_sensitive_data.
otherUserMeetingUserIDs, err := ds.User_MeetingUserIDs(otherUserID).Value(ctx)
if err != nil {
return false, fmt.Errorf("fetch meeting ids from requested user %d: %w", otherUserID, err)
}

for _, meetingUserID := range otherUserMeetingUserIDs {
meetingID, err := ds.MeetingUser_MeetingID(meetingUserID).Value(ctx)
if err != nil {
return false, fmt.Errorf("getting meeting: %w", err)
}

perms, err := perm.FromContext(ctx, meetingID)
if err != nil {
return false, fmt.Errorf("checking permissions of meeting %d: %w", meetingID, err)
}

if perms.Has(perm.UserCanSeeSensitiveData) {
return true, nil
}
}

return false, nil
})
}

func (User) modeD(ctx context.Context, ds *dsfetch.Fetch, userIDs ...int) ([]int, error) {
requestUser, err := perm.RequestUserFromContext(ctx)
if err != nil {
Expand Down
Loading

0 comments on commit 9eea68a

Please sign in to comment.