@@ -20,6 +20,7 @@ package auth
20
20
21
21
import (
22
22
"context"
23
+ "path/filepath"
23
24
"strings"
24
25
"time"
25
26
@@ -78,77 +79,136 @@ func expandAndVerifyScope(ctx context.Context, req interface{}, tokenScope map[s
78
79
return nil
79
80
}
80
81
81
- case strings .HasPrefix (k , "lightweight" ):
82
- if err = resolveLightweightScope (ctx , ref , tokenScope [k ], user , client , mgr ); err == nil {
83
- return nil
84
- }
85
82
}
86
83
log .Err (err ).Msgf ("error resolving reference %s under scope %+v" , ref .String (), k )
87
84
}
88
85
89
- } else if ref , ok := extractShareRef (req ); ok {
90
- // It's a share ref
91
- // The request might be coming from a share created for a lightweight account
92
- // after the token was minted.
93
- log .Info ().Msgf ("resolving share reference against received shares to verify token scope %+v" , ref .String ())
94
- for k := range tokenScope {
95
- if strings .HasPrefix (k , "lightweight" ) {
96
- // Check if this ID is cached
97
- key := "lw:" + user .Id .OpaqueId + scopeDelimiter + ref .GetId ().OpaqueId
98
- if _ , err := scopeExpansionCache .Get (key ); err == nil {
99
- return nil
100
- }
86
+ }
101
87
102
- shares , err := client .ListReceivedShares (ctx , & collaboration.ListReceivedSharesRequest {})
103
- if err != nil || shares .Status .Code != rpc .Code_CODE_OK {
104
- log .Warn ().Err (err ).Msg ("error listing received shares" )
105
- continue
106
- }
107
- for _ , s := range shares .Shares {
108
- shareKey := "lw:" + user .Id .OpaqueId + scopeDelimiter + s .Share .Id .OpaqueId
109
- _ = scopeExpansionCache .SetWithExpire (shareKey , nil , scopeCacheExpiration * time .Second )
110
-
111
- if ref .GetId () != nil && ref .GetId ().OpaqueId == s .Share .Id .OpaqueId {
112
- return nil
113
- }
114
- if key := ref .GetKey (); key != nil && (utils .UserEqual (key .Owner , s .Share .Owner ) || utils .UserEqual (key .Owner , s .Share .Creator )) &&
115
- utils .ResourceIDEqual (key .ResourceId , s .Share .ResourceId ) && utils .GranteeEqual (key .Grantee , s .Share .Grantee ) {
116
- return nil
117
- }
118
- }
119
- }
120
- }
88
+ if checkLightweightScope (ctx , req , tokenScope , client ) {
89
+ return nil
121
90
}
122
91
123
92
return errtypes .PermissionDenied ("access to resource not allowed within the assigned scope" )
124
93
}
125
94
126
- func resolveLightweightScope ( ctx context. Context , ref * provider. Reference , scope * authpb.Scope , user * userpb. User , client gateway. GatewayAPIClient , mgr token. Manager ) error {
127
- // Check if this ref is cached
128
- key := "lw:" + user . Id . OpaqueId + scopeDelimiter + getRefKey ( ref )
129
- if _ , err := scopeExpansionCache . Get ( key ); err == nil {
130
- return nil
95
+ func hasLightweightScope ( tokenScope map [ string ] * authpb.Scope ) bool {
96
+ for scope := range tokenScope {
97
+ if strings . HasPrefix ( scope , "lightweight" ) {
98
+ return true
99
+ }
131
100
}
101
+ return false
102
+ }
132
103
133
- shares , err := client . ListReceivedShares ( ctx , & collaboration. ListReceivedSharesRequest {})
134
- if err != nil || shares . Status . Code != rpc . Code_CODE_OK {
135
- return errtypes . InternalError ( "error listing received shares" )
104
+ func checkLightweightScope ( ctx context. Context , req interface {}, tokenScope map [ string ] * authpb. Scope , client gateway. GatewayAPIClient ) bool {
105
+ if ! hasLightweightScope ( tokenScope ) {
106
+ return false
136
107
}
137
108
138
- for _ , share := range shares .Shares {
139
- shareKey := "lw:" + user .Id .OpaqueId + scopeDelimiter + resourceid .OwnCloudResourceIDWrap (share .Share .ResourceId )
140
- _ = scopeExpansionCache .SetWithExpire (shareKey , nil , scopeCacheExpiration * time .Second )
109
+ switch r := req .(type ) {
110
+ // Viewer role
111
+ case * registry.GetStorageProvidersRequest :
112
+ return true
113
+ case * provider.StatRequest :
114
+ return true
115
+ case * provider.ListContainerRequest :
116
+ return hasPermissions (ctx , client , r .GetRef (), & provider.ResourcePermissions {
117
+ ListContainer : true ,
118
+ })
119
+ case * provider.InitiateFileDownloadRequest :
120
+ return hasPermissions (ctx , client , r .GetRef (), & provider.ResourcePermissions {
121
+ InitiateFileDownload : true ,
122
+ })
123
+ case * appprovider.OpenInAppRequest :
124
+ return hasPermissions (ctx , client , & provider.Reference {ResourceId : r .ResourceInfo .Id }, & provider.ResourcePermissions {
125
+ InitiateFileDownload : true ,
126
+ })
127
+ case * gateway.OpenInAppRequest :
128
+ return hasPermissions (ctx , client , r .GetRef (), & provider.ResourcePermissions {
129
+ InitiateFileDownload : true ,
130
+ })
141
131
142
- if ref .ResourceId != nil && utils .ResourceIDEqual (share .Share .ResourceId , ref .ResourceId ) {
143
- return nil
132
+ // Editor role
133
+ case * provider.CreateContainerRequest :
134
+ parent , err := parentOfResource (ctx , client , r .GetRef ())
135
+ if err != nil {
136
+ return false
137
+ }
138
+ return hasPermissions (ctx , client , parent , & provider.ResourcePermissions {
139
+ CreateContainer : true ,
140
+ })
141
+ case * provider.TouchFileRequest :
142
+ parent , err := parentOfResource (ctx , client , r .GetRef ())
143
+ if err != nil {
144
+ return false
144
145
}
145
- if ok , err := checkIfNestedResource (ctx , ref , share .Share .ResourceId , client , mgr ); err == nil && ok {
146
- _ = scopeExpansionCache .SetWithExpire (key , nil , scopeCacheExpiration * time .Second )
147
- return nil
146
+ return hasPermissions (ctx , client , parent , & provider.ResourcePermissions {
147
+ InitiateFileDownload : true ,
148
+ })
149
+ case * provider.DeleteRequest :
150
+ return hasPermissions (ctx , client , r .GetRef (), & provider.ResourcePermissions {
151
+ InitiateFileDownload : true ,
152
+ })
153
+ case * provider.MoveRequest :
154
+ return hasPermissions (ctx , client , r .Source , & provider.ResourcePermissions {
155
+ InitiateFileDownload : true ,
156
+ }) && hasPermissions (ctx , client , r .Destination , & provider.ResourcePermissions {
157
+ InitiateFileUpload : true ,
158
+ })
159
+ case * provider.InitiateFileUploadRequest :
160
+ parent , err := parentOfResource (ctx , client , r .GetRef ())
161
+ if err != nil {
162
+ return false
148
163
}
164
+ return hasPermissions (ctx , client , parent , & provider.ResourcePermissions {
165
+ InitiateFileUpload : true ,
166
+ })
149
167
}
150
168
151
- return errtypes .PermissionDenied ("request is not for a nested resource" )
169
+ return false
170
+ }
171
+
172
+ func parentOfResource (ctx context.Context , client gateway.GatewayAPIClient , ref * provider.Reference ) (* provider.Reference , error ) {
173
+ if utils .IsAbsolutePathReference (ref ) {
174
+ parent := filepath .Dir (ref .GetPath ())
175
+ info , err := stat (ctx , client , & provider.Reference {Path : parent })
176
+ if err != nil {
177
+ return nil , err
178
+ }
179
+ return & provider.Reference {ResourceId : info .Id }, nil
180
+ }
181
+
182
+ info , err := stat (ctx , client , ref )
183
+ if err != nil {
184
+ return nil , err
185
+ }
186
+ return & provider.Reference {ResourceId : info .ParentId }, nil
187
+ }
188
+
189
+ func stat (ctx context.Context , client gateway.GatewayAPIClient , ref * provider.Reference ) (* provider.ResourceInfo , error ) {
190
+ statRes , err := client .Stat (ctx , & provider.StatRequest {
191
+ Ref : ref ,
192
+ })
193
+
194
+ switch {
195
+ case err != nil :
196
+ return nil , err
197
+ case statRes .Status .Code == rpc .Code_CODE_NOT_FOUND :
198
+ return nil , errtypes .NotFound (statRes .Status .Message )
199
+ case statRes .Status .Code != rpc .Code_CODE_OK :
200
+ return nil , errtypes .InternalError (statRes .Status .Message )
201
+ }
202
+
203
+ return statRes .Info , nil
204
+ }
205
+
206
+ func hasPermissions (ctx context.Context , client gateway.GatewayAPIClient , ref * provider.Reference , permissionSet * provider.ResourcePermissions ) bool {
207
+ info , err := stat (ctx , client , ref )
208
+ if err != nil {
209
+ return false
210
+ }
211
+ return utils .HasPermissions (info .PermissionSet , permissionSet )
152
212
}
153
213
154
214
func resolvePublicShare (ctx context.Context , ref * provider.Reference , scope * authpb.Scope , client gateway.GatewayAPIClient , mgr token.Manager ) error {
@@ -329,16 +389,6 @@ func extractRef(req interface{}, tokenScope map[string]*authpb.Scope) (*provider
329
389
return nil , false
330
390
}
331
391
332
- func extractShareRef (req interface {}) (* collaboration.ShareReference , bool ) {
333
- switch v := req .(type ) {
334
- case * collaboration.GetReceivedShareRequest :
335
- return v .GetRef (), true
336
- case * collaboration.UpdateReceivedShareRequest :
337
- return & collaboration.ShareReference {Spec : & collaboration.ShareReference_Id {Id : v .GetShare ().GetShare ().GetId ()}}, true
338
- }
339
- return nil , false
340
- }
341
-
342
392
func getRefKey (ref * provider.Reference ) string {
343
393
if ref .Path != "" {
344
394
return ref .Path
0 commit comments