[full-ci] standalone graph service with LDAP (#5199)

* standalone graph service with LDAP

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* no panic on PATCH and DELETE

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* fix apitoken yaml key

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* update user, fix response codes

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* fix group creation return code

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* remove unknown user property

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* fix create return code checks in graph feature context

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* updating uses 200 OK when returning a body

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* revert user statusCreated change for now

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* revert return code changes

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2022-12-12 12:46:10 +01:00
committed by GitHub
parent 4123c7e2d8
commit d359a7c2cf
9 changed files with 157 additions and 124 deletions
+82 -77
View File
@@ -158,28 +158,28 @@ func (g Graph) PostUser(w http.ResponseWriter, r *http.Request) {
return
}
// All users get the user role by default currently.
// to all new users for now, as create Account request does not have any role field
if g.roleService == nil {
// log as error, admin needs to do something about it
logger.Error().Str("id", *u.Id).Msg("could not create user: role service not configured")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not assign role to account: roleService not configured")
return
}
if _, err = g.roleService.AssignRoleToUser(r.Context(), &settings.AssignRoleToUserRequest{
AccountUuid: *u.Id,
RoleId: settingssvc.BundleUUIDRoleUser,
}); err != nil {
// log as error, admin eventually needs to do something
logger.Error().Err(err).Str("id", *u.Id).Str("role", settingssvc.BundleUUIDRoleUser).Msg("could not create user: role assignment failed")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "role assignment failed")
return
// assign roles if possible
if g.roleService != nil {
// All users get the user role by default currently.
// to all new users for now, as create Account request does not have any role field
if _, err = g.roleService.AssignRoleToUser(r.Context(), &settings.AssignRoleToUserRequest{
AccountUuid: *u.Id,
RoleId: settingssvc.BundleUUIDRoleUser,
}); err != nil {
// log as error, admin eventually needs to do something
logger.Error().Err(err).Str("id", *u.Id).Str("role", settingssvc.BundleUUIDRoleUser).Msg("could not create user: role assignment failed")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "role assignment failed")
return
}
}
currentUser := revactx.ContextMustGetUser(r.Context())
g.publishEvent(events.UserCreated{Executant: currentUser.Id, UserID: *u.Id})
e := events.UserCreated{UserID: *u.Id}
if currentUser, ok := revactx.ContextGetUser(r.Context()); ok {
e.Executant = currentUser.GetId()
}
g.publishEvent(e)
render.Status(r, http.StatusOK)
render.Status(r, http.StatusOK) // FIXME 201 should return 201 created
render.JSON(w, r, u)
}
@@ -307,65 +307,69 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
return
}
currentUser := revactx.ContextMustGetUser(r.Context())
if currentUser.GetId().GetOpaqueId() == user.GetId() {
logger.Debug().Msg("could not delete user: self deletion forbidden")
errorcode.NotAllowed.Render(w, r, http.StatusForbidden, "self deletion forbidden")
return
}
logger.Debug().
Str("user", user.GetId()).
Msg("calling list spaces with user filter to fetch the personal space for deletion")
opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T")
f := listStorageSpacesUserFilter(user.GetId())
lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
Opaque: opaque,
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{f},
})
if err != nil {
// transport error, log as error
logger.Error().Err(err).Msg("could not fetch spaces: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not fetch spaces for deletion, aborting")
return
}
for _, sp := range lspr.GetStorageSpaces() {
if !(sp.SpaceType == "personal" && sp.Owner.Id.OpaqueId == user.GetId()) {
continue
e := events.UserDeleted{UserID: user.GetId()}
if currentUser, ok := revactx.ContextGetUser(r.Context()); ok {
if currentUser.GetId().GetOpaqueId() == user.GetId() {
logger.Debug().Msg("could not delete user: self deletion forbidden")
errorcode.NotAllowed.Render(w, r, http.StatusForbidden, "self deletion forbidden")
return
}
// TODO: check if request contains a homespace and if, check if requesting user has the privilege to
// delete it and make sure it is not deleting its own homespace
// needs modification of the cs3api
e.Executant = currentUser.GetId()
}
// Deleting a space a two step process (1. disabling/trashing, 2. purging)
// Do the "disable/trash" step only if the space is not marked as trashed yet:
if _, ok := sp.Opaque.Map["trashed"]; !ok {
if g.gatewayClient != nil {
logger.Debug().
Str("user", user.GetId()).
Msg("calling list spaces with user filter to fetch the personal space for deletion")
opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T")
f := listStorageSpacesUserFilter(user.GetId())
lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
Opaque: opaque,
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{f},
})
if err != nil {
// transport error, log as error
logger.Error().Err(err).Msg("could not fetch spaces: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not fetch spaces for deletion, aborting")
return
}
for _, sp := range lspr.GetStorageSpaces() {
if !(sp.SpaceType == "personal" && sp.Owner.Id.OpaqueId == user.GetId()) {
continue
}
// TODO: check if request contains a homespace and if, check if requesting user has the privilege to
// delete it and make sure it is not deleting its own homespace
// needs modification of the cs3api
// Deleting a space a two step process (1. disabling/trashing, 2. purging)
// Do the "disable/trash" step only if the space is not marked as trashed yet:
if _, ok := sp.Opaque.Map["trashed"]; !ok {
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,
},
})
if err != nil {
logger.Error().Err(err).Msg("could not disable homespace: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not disable homespace, aborting")
return
}
}
purgeFlag := utils.AppendPlainToOpaque(nil, "purge", "")
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Opaque: purgeFlag,
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,
},
})
if err != nil {
logger.Error().Err(err).Msg("could not disable homespace: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not disable homespace, aborting")
// transport error, log as error
logger.Error().Err(err).Msg("could not delete homespace: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not delete homespace, aborting")
return
}
break
}
purgeFlag := utils.AppendPlainToOpaque(nil, "purge", "")
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Opaque: purgeFlag,
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,
},
})
if err != nil {
// transport error, log as error
logger.Error().Err(err).Msg("could not delete homespace: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not delete homespace, aborting")
return
}
break
}
logger.Debug().Str("id", user.GetId()).Msg("calling delete user on backend")
@@ -382,7 +386,7 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
}
}
g.publishEvent(events.UserDeleted{Executant: currentUser.Id, UserID: user.GetId()})
g.publishEvent(e)
render.Status(r, http.StatusNoContent)
render.NoContent(w, r)
@@ -443,15 +447,16 @@ func (g Graph) PatchUser(w http.ResponseWriter, r *http.Request) {
return
}
currentUser := revactx.ContextMustGetUser(r.Context())
g.publishEvent(
events.UserFeatureChanged{
Executant: currentUser.Id,
UserID: nameOrID,
Features: features,
},
)
render.Status(r, http.StatusOK)
e := events.UserFeatureChanged{
UserID: nameOrID,
Features: features,
}
if currentUser, ok := revactx.ContextGetUser(r.Context()); ok {
e.Executant = currentUser.GetId()
}
g.publishEvent(e)
render.Status(r, http.StatusOK) // TODO StatusNoContent when prefer=minimal is used
render.JSON(w, r, u)
}