-
Notifications
You must be signed in to change notification settings - Fork 21
/
mediafile.go
168 lines (136 loc) · 4.65 KB
/
mediafile.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package collection
import (
"context"
"fmt"
"strconv"
"strings"
"github.com/OpenSlides/openslides-autoupdate-service/internal/restrict/perm"
"github.com/OpenSlides/openslides-autoupdate-service/pkg/datastore/dsfetch"
)
// Mediafile handels permissions for the collection mediafile.
//
// Mediafiles can be seen if:
//
// The mediafile belongs to the organization (decided by owner_id) and the user has organization management permissions.
// The user is admin in a meeting and published_to_meetings_in_organization_id is not null.
// The user can see any of the meeting mediafiles of the mediafile.
// The field token is set to any non empty value.
//
// Mode A: The user can see the mediafile.
type Mediafile struct{}
// Name returns the collection name.
func (m Mediafile) Name() string {
return "mediafile"
}
// MeetingID returns the meetingID for the object.
func (m Mediafile) MeetingID(ctx context.Context, ds *dsfetch.Fetch, id int) (int, bool, error) {
genericOwnerID, err := ds.Mediafile_OwnerID(id).Value(ctx)
if err != nil {
return 0, false, fmt.Errorf("fetching owner_id of mediafile %d: %w", id, err)
}
collection, rawID, found := strings.Cut(genericOwnerID, "/")
if !found {
// TODO LAST ERROR
return 0, false, fmt.Errorf("invalid ownerID: %s", genericOwnerID)
}
if collection != "meeting" {
return 0, false, nil
}
ownerID, err := strconv.Atoi(rawID)
if err != nil {
// TODO LAST ERROR
return 0, false, fmt.Errorf("invalid id part of ownerID: %s", genericOwnerID)
}
return ownerID, true, nil
}
// Modes returns the field modes for the collection mediafile.
func (m Mediafile) Modes(mode string) FieldRestricter {
switch mode {
case "A":
return m.see
}
return nil
}
func (m Mediafile) see(ctx context.Context, ds *dsfetch.Fetch, mediafileIDs ...int) ([]int, error) {
requestUser, err := perm.RequestUserFromContext(ctx)
if err != nil {
return nil, fmt.Errorf("getting request user: %w", err)
}
hasManagementLevel, err := perm.HasOrganizationManagementLevel(ctx, ds, requestUser, perm.OMLCanManageOrganization)
if err != nil {
return nil, fmt.Errorf("getting organization management level: %w", err)
}
isMeetingAdmin, err := isAdminInAnyMeeting(ctx, ds)
if err != nil {
return nil, fmt.Errorf("checking if user is meeting admin: %w", err)
}
return eachContentObjectCollection(ctx, ds.Mediafile_OwnerID, mediafileIDs, func(collection string, ownerID int, ids []int) ([]int, error) {
// ownerID can be a meetingID or the organizationID
if collection == "organization" && hasManagementLevel {
return ids, nil
}
return eachCondition(ids, func(mediafileID int) (bool, error) {
token, err := ds.Mediafile_Token(mediafileID).Value(ctx)
if err != nil {
return false, fmt.Errorf("getting mediafile token: %w", err)
}
if token != "" {
return true, nil
}
published, err := ds.Mediafile_PublishedToMeetingsInOrganizationID(mediafileID).Value(ctx)
if err != nil {
return false, fmt.Errorf("getting published to meetings in organization: %w", err)
}
if !published.Null() && isMeetingAdmin {
return true, nil
}
if published.Null() && collection == "organization" {
return false, nil
}
meetingMediafileIDs, err := ds.Mediafile_MeetingMediafileIDs(mediafileID).Value(ctx)
if err != nil {
return false, fmt.Errorf("getting meeting mediafile ids: %w", err)
}
canSeeMeetingMediafile, err := Collection(ctx, MeetingMediafile{}.Name()).Modes("A")(ctx, ds, meetingMediafileIDs...)
if err != nil {
return false, fmt.Errorf("can see meeting mediafile of mediafile %d: %w", mediafileID, err)
}
if len(canSeeMeetingMediafile) >= 1 {
return true, nil
}
return false, nil
})
})
}
func isAdminInAnyMeeting(ctx context.Context, ds *dsfetch.Fetch) (bool, error) {
userID, err := perm.RequestUserFromContext(ctx)
if err != nil {
return false, fmt.Errorf("getting request user: %w", err)
}
if userID == 0 {
return false, nil
}
meetingUserIDs, err := ds.User_MeetingUserIDs(userID).Value(ctx)
if err != nil {
return false, fmt.Errorf("getting meeting_user objects: %w", err)
}
for _, muid := range meetingUserIDs {
groupIDs, err := ds.MeetingUser_GroupIDs(muid).Value(ctx)
if err != nil {
return false, fmt.Errorf("getting groupIDs of user: %w", err)
}
adminGroups := make([]dsfetch.Maybe[int], len(groupIDs))
for i := 0; i < len(groupIDs); i++ {
ds.Group_AdminGroupForMeetingID(groupIDs[i]).Lazy(&adminGroups[i])
}
if err := ds.Execute(ctx); err != nil {
return false, fmt.Errorf("checking for admin groups: %w", err)
}
for _, isAdmin := range adminGroups {
if _, ok := isAdmin.Value(); ok {
return true, nil
}
}
}
return false, nil
}