-
Notifications
You must be signed in to change notification settings - Fork 9
/
restrict.go
123 lines (105 loc) · 3.13 KB
/
restrict.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
package user
import (
"encoding/json"
"fmt"
"github.com/OpenSlides/openslides3-autoupdate-service/internal/restricter"
)
// Restrict handels restrictions of users/user elements.
func Restrict(r restricter.HasPermer) restricter.ElementFunc {
littleDataFields := []string{
"id",
"username",
"title",
"first_name",
"last_name",
"structure_level",
"number",
"about_me",
"groups_id",
"is_present",
"is_committee",
"vote_weight",
"gender",
}
manyDataFields := append(littleDataFields, "email", "last_email_send", "comment", "is_active", "auth_type", "vote_delegated_to_id", "vote_delegated_from_users_id")
allDataFields := append(manyDataFields, "default_password")
ownDataFields := append(littleDataFields, "email", "gender", "vote_delegated_to_id", "vote_delegated_from_users_id")
return func(uid int, element json.RawMessage) (json.RawMessage, error) {
var user struct {
ID int `json:"id"`
}
if err := json.Unmarshal(element, &user); err != nil {
return nil, fmt.Errorf("unmarshal user id: %w", err)
}
if r.HasPerm(uid, "users.can_see_name") {
if r.HasPerm(uid, "users.can_see_extra_data") {
if r.HasPerm(uid, "users.can_manage") {
return filter(element, allDataFields)
}
return filter(element, manyDataFields)
}
// no can_see_extra_data
if user.ID == uid {
return filter(element, ownDataFields)
}
return filter(element, littleDataFields)
} else if user.ID == uid {
// no can_see but own data
return filter(element, ownDataFields)
}
// Registered users can see there delegated users.
if uid != 0 {
// Get the users `vote_delegated_from_users_id`.
var requestUser struct {
VoteDelegationIds []int `json:"vote_delegated_from_users_id"`
}
if err := r.Get("users/user", uid, &requestUser); err != nil {
return nil, fmt.Errorf("fetching and unmarshalling user: %w", err)
}
// The user.ID is required, if it is in VoteDelegationIds.
for _, id := range requestUser.VoteDelegationIds {
if id == user.ID {
return filter(element, littleDataFields)
}
}
}
for _, perm := range r.UserRequired(user.ID) {
if !r.HasPerm(uid, perm) {
continue
}
return filter(element, littleDataFields)
}
return nil, nil
}
}
// PersonalNoteRestrict is the restricter for users/personal_note.
func PersonalNoteRestrict(uid int, data json.RawMessage) (json.RawMessage, error) {
if uid == 0 {
return nil, nil
}
var element struct {
UserID int `json:"user_id"`
}
if err := json.Unmarshal(data, &element); err != nil {
return nil, fmt.Errorf("decoding personal element: %w", err)
}
if element.UserID != uid {
return nil, nil
}
return data, nil
}
func filter(value json.RawMessage, fields []string) (json.RawMessage, error) {
var allData map[string]json.RawMessage
if err := json.Unmarshal(value, &allData); err != nil {
return nil, fmt.Errorf("unmarshall data: %w", err)
}
filteredData := make(map[string]json.RawMessage, len(fields))
for _, k := range fields {
filteredData[k] = allData[k]
}
filtered, err := json.Marshal(filteredData)
if err != nil {
return nil, fmt.Errorf("remarshal data: %w", err)
}
return filtered, nil
}