@@ -35,6 +35,7 @@ import (
3535 "github.com/cs3org/reva/v3"
3636 "github.com/cs3org/reva/v3/pkg/appctx"
3737 revautils "github.com/cs3org/reva/v3/pkg/cbox/utils"
38+ "github.com/cs3org/reva/v3/pkg/errtypes"
3839 "github.com/cs3org/reva/v3/pkg/user"
3940 "github.com/cs3org/reva/v3/pkg/utils/cfg"
4041 "github.com/cs3org/reva/v3/pkg/utils/list"
@@ -244,6 +245,38 @@ func (m *manager) fetchAllUserAccounts(ctx context.Context) error {
244245 return nil
245246}
246247
248+ func (m * manager ) fetchExternalUserByEmail (ctx context.Context , email string ) (* userpb.User , error ) {
249+ if email == "" || ! strings .Contains (email , "@" ) {
250+ return nil , errtypes .NotFound ("rest: external user lookup requires an email address" )
251+ }
252+
253+ log := appctx .GetLogger (ctx )
254+ url := fmt .Sprintf ("%s/api/v1.0/Identity/by_email/%s?filter=unconfirmed%%3Afalse&filter=blocked%%3Afalse&filter=disabled%%3Afalse&field=upn&field=primaryAccountEmail&field=displayName&field=uid&field=gid&field=type&field=source&field=activeUser" , m .conf .APIBaseURL , neturl .PathEscape (email ))
255+
256+ var r IdentitiesResponse
257+ if err := m .apiTokenManager .SendAPIGetRequest (ctx , url , false , & r ); err != nil {
258+ log .Error ().Err (err ).Str ("email" , email ).Msg ("rest: failed to fetch external user from authz" )
259+ return nil , err
260+ }
261+
262+ for _ , usr := range r .Data {
263+ if usr == nil || ! isExternalUserType (usr .UserType ()) {
264+ continue
265+ }
266+
267+ u , err := m .parseAndCacheUser (ctx , usr )
268+ if err != nil {
269+ log .Error ().Err (err ).Str ("email" , email ).Msg ("rest: failed to parse external user fetched from authz" )
270+ continue
271+ }
272+
273+ log .Debug ().Str ("email" , email ).Str ("opaque_id" , u .GetId ().GetOpaqueId ()).Msg ("rest: fetched and cached external user from authz" )
274+ return u , nil
275+ }
276+
277+ return nil , errtypes .NotFound ("rest: external user not found in authz" )
278+ }
279+
247280func (m * manager ) parseAndCacheUser (ctx context.Context , i * Identity ) (* userpb.User , error ) {
248281 log := appctx .GetLogger (ctx )
249282
@@ -301,7 +334,14 @@ func (m *manager) fetchExternalIdentities(ctx context.Context, email string) ([]
301334func (m * manager ) GetUser (ctx context.Context , uid * userpb.UserId , skipFetchingGroups bool ) (* userpb.User , error ) {
302335 u , err := m .fetchCachedUserDetails (ctx , uid )
303336 if err != nil {
304- return nil , err
337+ if uid == nil || ! isExternalUserType (uid .Type ) || ! strings .Contains (uid .OpaqueId , "@" ) {
338+ return nil , err
339+ }
340+
341+ u , err = m .fetchExternalUserByEmail (ctx , uid .OpaqueId )
342+ if err != nil {
343+ return nil , err
344+ }
305345 }
306346
307347 if ! skipFetchingGroups {
@@ -318,7 +358,17 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
318358func (m * manager ) GetUserByClaim (ctx context.Context , claim , value string , skipFetchingGroups bool ) (* userpb.User , error ) {
319359 u , err := m .fetchCachedUserByParam (ctx , claim , value )
320360 if err != nil {
321- return nil , err
361+ if _ , ok := err .(errtypes.Conflict ); ok {
362+ return nil , err
363+ }
364+ if (claim != "username" && claim != "mail" ) || ! strings .Contains (value , "@" ) {
365+ return nil , err
366+ }
367+
368+ u , err = m .fetchExternalUserByEmail (ctx , value )
369+ if err != nil {
370+ return nil , err
371+ }
322372 }
323373
324374 if ! skipFetchingGroups {
@@ -399,6 +449,10 @@ func isUserAnyType(user *userpb.User, types []userpb.UserType) bool {
399449 return false
400450}
401451
452+ func isExternalUserType (t userpb.UserType ) bool {
453+ return t == userpb .UserType_USER_TYPE_LIGHTWEIGHT || t == userpb .UserType_USER_TYPE_FEDERATED
454+ }
455+
402456// Group contains the information about a group.
403457type Group struct {
404458 GroupIdentifier string `json:"groupIdentifier"`
0 commit comments