From ffeb6633510a8a694fbf0b3c38121627f7658616 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 10 Jan 2019 12:04:46 +0100 Subject: [PATCH] SEBSERV-6 #finished InstitutionController implementation --- .../gbl/model/institution/Institution.java | 7 +- .../activation/EntityActivationService.java | 48 ++++- .../authorization/UserServiceImpl.java | 8 +- .../dao/ActivatableEntityDAO.java | 6 +- .../servicelayer/dao/InstitutionDAO.java | 2 +- .../servicelayer/dao/UserActivityLogDAO.java | 7 + .../webservice/servicelayer/dao/UserDAO.java | 2 +- .../dao/impl/UserActivityLogDAOImpl.java | 19 ++ .../weblayer/api/InstitutionController.java | 173 +++++++++++++++--- .../weblayer/api/UserAccountController.java | 78 ++++---- 10 files changed, 275 insertions(+), 75 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/Institution.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/Institution.java index ae35a0f9..ddda1853 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/Institution.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/Institution.java @@ -17,12 +17,13 @@ import com.fasterxml.jackson.annotation.JsonProperty; import ch.ethz.seb.sebserver.gbl.model.Activatable; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain.INSTITUTION; +import ch.ethz.seb.sebserver.gbl.model.EntityIdAndName; import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity; public final class Institution implements GrantEntity, Activatable { - public static final String FILTER_ATTR_ONLY_ACTIVE = "onlyActive"; + public static final String FILTER_ATTR_ACTIVE = "active"; @JsonProperty(Domain.ATTR_ID) public final Long id; @@ -108,4 +109,8 @@ public final class Institution implements GrantEntity, Activatable { + ", active=" + this.active + "]"; } + public static EntityIdAndName toName(final Institution institution) { + return new EntityIdAndName(String.valueOf(institution.id), institution.name); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/activation/EntityActivationService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/activation/EntityActivationService.java index 1def3056..5f34240b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/activation/EntityActivationService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/activation/EntityActivationService.java @@ -10,20 +10,37 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.activation; import java.util.Collection; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; +import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType; @Service @WebServiceProfile public class EntityActivationService { private final Collection> activatableEntityDAOs; + private final ApplicationEventPublisher applicationEventPublisher; + private final UserActivityLogDAO userActivityLogDAO; + + public EntityActivationService( + final Collection> activatableEntityDAOs, + final ApplicationEventPublisher applicationEventPublisher, + final UserActivityLogDAO userActivityLogDAO) { - public EntityActivationService(final Collection> activatableEntityDAOs) { this.activatableEntityDAOs = activatableEntityDAOs; + this.applicationEventPublisher = applicationEventPublisher; + this.userActivityLogDAO = userActivityLogDAO; + } + + public ApplicationEventPublisher getApplicationEventPublisher() { + return this.applicationEventPublisher; } @EventListener(EntityActivationEvent.class) @@ -37,4 +54,33 @@ public class EntityActivationService { } } + public Result setActive(final T entity, final boolean activated) { + + final ActivityType activityType = (activated) + ? ActivityType.ACTIVATE + : ActivityType.DEACTIVATE; + + return getDAOForEntity(entity) + .setActive(entity.getModelId(), activated) + .flatMap(e -> publishEvent(e, activated)) + .flatMap(e -> this.userActivityLogDAO.log(activityType, e)); + + } + + public Result publishEvent(final T entity, final boolean activated) { + this.applicationEventPublisher.publishEvent(new EntityActivationEvent(entity, activated)); + return Result.of(entity); + } + + @SuppressWarnings("unchecked") + private ActivatableEntityDAO getDAOForEntity(final T entity) { + for (final ActivatableEntityDAO dao : this.activatableEntityDAOs) { + if (dao.entityType() == entity.entityType()) { + return (ActivatableEntityDAO) dao; + } + } + + return null; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/UserServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/UserServiceImpl.java index 58ad0ccd..aa84d460 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/UserServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/UserServiceImpl.java @@ -13,6 +13,7 @@ import java.util.Collection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -36,9 +37,14 @@ public class UserServiceImpl implements UserService { } private final Collection extractStrategies; + private final ApplicationEventPublisher applicationEventPublisher; + + public UserServiceImpl( + final Collection extractStrategies, + final ApplicationEventPublisher applicationEventPublisher) { - public UserServiceImpl(final Collection extractStrategies) { this.extractStrategies = extractStrategies; + this.applicationEventPublisher = applicationEventPublisher; } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ActivatableEntityDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ActivatableEntityDAO.java index 1f50b0c3..648c306d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ActivatableEntityDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ActivatableEntityDAO.java @@ -16,7 +16,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result; /** Interface of a DAO for an Entity that has activation feature. * * @param the concrete Entity type */ -public interface ActivatableEntityDAO { +public interface ActivatableEntityDAO extends EntityDAO { /** Get a Collection of all active Entity instances for a concrete entity-domain. * @@ -35,7 +35,7 @@ public interface ActivatableEntityDAO { * This can be used to take action in dependency of an activation of an Entity of different type. * For example a user-account DAO want to react on a Institution activation to also activate all user * accounts for this institution. - * + * * @param source The source Entity that has been activated */ void notifyActivation(Entity source); @@ -43,7 +43,7 @@ public interface ActivatableEntityDAO { * This can be used to take action in dependency of an deactivation of an Entity of different type. * For example a user-account DAO want to react on a Institution deactivation to also deactivate all user * accounts for this institution. - * + * * @param source The source Entity that has been deactivated */ void notifyDeactivation(Entity source); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/InstitutionDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/InstitutionDAO.java index a95ed7da..c87ab177 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/InstitutionDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/InstitutionDAO.java @@ -13,7 +13,7 @@ import java.util.Collection; import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.util.Result; -public interface InstitutionDAO extends EntityDAO, ActivatableEntityDAO { +public interface InstitutionDAO extends ActivatableEntityDAO { Result> allMatching(String name, Boolean active); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java index 1586410e..3295d533 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserActivityLogDAO.java @@ -49,6 +49,13 @@ public interface UserActivityLogDAO extends UserRelatedEntityDAO Result log(ActivityType activityType, EntityType entityType, String entityId, String message, T data); + /** Creates a user activity log entry. * * @param user for specified SEBServerUser instance diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserDAO.java index c8387c9d..48b129be 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/UserDAO.java @@ -21,7 +21,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser /** The Data Access Object for all User related data like get user data within UserInfo, * save and modify user related data within UserMod and get internal user principal data * within SEBServerUser. */ -public interface UserDAO extends EntityDAO, ActivatableEntityDAO { +public interface UserDAO extends ActivatableEntityDAO { /** Use this to get UserInfo by users UUID * diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java index 8069a80a..16db6de9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/UserActivityLogDAOImpl.java @@ -109,6 +109,25 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO { } } + @Override + public Result log( + final ActivityType activityType, + final EntityType entityType, + final String entityId, + final String message, + final T data) { + + return Result.tryCatch(() -> { + log( + this.userService.getCurrentUser(), + activityType, + entityType, + entityId, + message); + return data; + }); + } + @Override @Transactional public Result log( diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java index b4a55a9e..ed169184 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java @@ -8,22 +8,33 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; +import java.util.Arrays; import java.util.Collection; +import java.util.stream.Collectors; -import org.springframework.context.ApplicationEventPublisher; +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import ch.ethz.seb.sebserver.gbl.model.EntityIdAndName; +import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; +import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.activation.EntityActivationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType; +import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType; @WebServiceProfile @RestController @@ -34,51 +45,161 @@ public class InstitutionController { private final AuthorizationGrantService authorizationGrantService; private final UserService userService; private final UserActivityLogDAO userActivityLogDAO; - private final ApplicationEventPublisher applicationEventPublisher; + private final EntityActivationService entityActivationService; public InstitutionController( final InstitutionDAO institutionDAO, final AuthorizationGrantService authorizationGrantService, final UserService userService, final UserActivityLogDAO userActivityLogDAO, - final ApplicationEventPublisher applicationEventPublisher) { + final EntityActivationService entityActivationService) { this.institutionDAO = institutionDAO; this.authorizationGrantService = authorizationGrantService; this.userService = userService; this.userActivityLogDAO = userActivityLogDAO; - this.applicationEventPublisher = applicationEventPublisher; + this.entityActivationService = entityActivationService; + } + + @RequestMapping(path = "/self", method = RequestMethod.GET) + public Institution getOwn() { + + checkBaseReadPrivilege(); + + final SEBServerUser currentUser = this.userService.getCurrentUser(); + final Long institutionId = currentUser.institutionId(); + return this.institutionDAO.byId(institutionId).getOrThrow(); + + } + + @RequestMapping(path = "/{id}", method = RequestMethod.GET) + public Institution getById(@PathVariable final Long id) { + + checkBaseReadPrivilege(); + + return this.institutionDAO + .byId(id) + .flatMap(inst -> this.authorizationGrantService.checkGrantOnEntity( + inst, + PrivilegeType.READ_ONLY)) + .getOrThrow(); } @RequestMapping(method = RequestMethod.GET) public Collection getAll( - @RequestParam(name = Institution.FILTER_ATTR_ONLY_ACTIVE, required = false) final Boolean onlyActive) { + @RequestParam(name = Institution.FILTER_ATTR_ACTIVE, required = false) final Boolean active) { - // fist check if current user has any privileges for this action - this.authorizationGrantService.checkHasAnyPrivilege( - EntityType.INSTITUTION, - PrivilegeType.READ_ONLY); + checkBaseReadPrivilege(); - final boolean hasBasePrivilege = this.authorizationGrantService.hasBasePrivilege( + if (!this.authorizationGrantService.hasBasePrivilege( EntityType.USER, - PrivilegeType.READ_ONLY); - - if (onlyActive == null || onlyActive) { - - return (hasBasePrivilege) - ? this.institutionDAO.allActive().getOrThrow() - : this.institutionDAO.all( - institution -> this.authorizationGrantService.hasGrant( - institution, - PrivilegeType.READ_ONLY)) - .getOrThrow(); + PrivilegeType.READ_ONLY)) { + // User has only institutional privilege, can see only the institution he/she belongs to + return Arrays.asList(getOwn()); } else { - - return this.institutionDAO - .all() - .getOrThrow(); - + return this.institutionDAO.all(inst -> true, active).getOrThrow(); } } + @RequestMapping(path = "/names", method = RequestMethod.GET) + public Collection getNames( + @RequestParam(name = Institution.FILTER_ATTR_ACTIVE, required = false) final Boolean active) { + + checkBaseReadPrivilege(); + + if (!this.authorizationGrantService.hasBasePrivilege( + EntityType.USER, + PrivilegeType.READ_ONLY)) { + + // User has only institutional privilege, can see only the institution he/she belongs to + return Arrays.asList(getOwn()) + .stream() + .map(Institution::toName) + .collect(Collectors.toList()); + + } else { + + return this.institutionDAO.all(inst -> true, active) + .getOrThrow() + .stream() + .map(Institution::toName) + .collect(Collectors.toList()); + } + } + + @RequestMapping(path = "/create", method = RequestMethod.PUT) + public Institution create(@Valid @RequestBody final Institution institution) { + return _saveInstitution(institution, PrivilegeType.WRITE) + .getOrThrow(); + } + + @RequestMapping(path = "/save", method = RequestMethod.POST) + public Institution save(@Valid @RequestBody final Institution institution) { + return _saveInstitution(institution, PrivilegeType.MODIFY) + .getOrThrow(); + } + + @RequestMapping(path = "/{id}/activate", method = RequestMethod.POST) + public Institution activate(@PathVariable final Long id) { + return setActive(id, true); + } + + @RequestMapping(value = "/{id}/deactivate", method = RequestMethod.POST) + public Institution deactivate(@PathVariable final Long id) { + return setActive(id, false); + } + + @RequestMapping(path = "/{id}/delete", method = RequestMethod.DELETE) + public EntityProcessingReport deleteUser(@PathVariable final Long id) { + return this.institutionDAO.delete(id, true) + .flatMap(report -> this.userActivityLogDAO.log( + ActivityType.DELETE, + EntityType.INSTITUTION, + String.valueOf(id), + "soft-delete", + report)) + .getOrThrow(); + } + +// TODO do we need a hard-delete for an institution? this may be dangerous? +// @RequestMapping(path = "/{id}/hard-delete", method = RequestMethod.DELETE) +// public EntityProcessingReport hardDeleteUser(@PathVariable final Long id) { +// return this.userDao.pkForUUID(uuid) +// .flatMap(pk -> this.userDao.delete(pk, false)) +// .flatMap(report -> this.userActivityLogDAO.log( +// ActivityType.DELETE, +// EntityType.USER, +// uuid, +// "hard-delete", +// report)) +// .getOrThrow(); +// } + + private Institution setActive(final Long id, final boolean active) { + + return this.institutionDAO + .byId(id) + .flatMap(inst -> this.authorizationGrantService.checkGrantOnEntity(inst, PrivilegeType.WRITE)) + .flatMap(inst -> this.entityActivationService.setActive(inst, active)) + .getOrThrow(); + } + + private Result _saveInstitution(final Institution institution, final PrivilegeType privilegeType) { + + final ActivityType activityType = (institution.id == null) + ? ActivityType.CREATE + : ActivityType.MODIFY; + + return this.authorizationGrantService + .checkGrantOnEntity(institution, privilegeType) + .flatMap(this.institutionDAO::save) + .flatMap(inst -> this.userActivityLogDAO.log(activityType, inst)); + } + + private void checkBaseReadPrivilege() { + this.authorizationGrantService.checkHasAnyPrivilege( + EntityType.INSTITUTION, + PrivilegeType.READ_ONLY); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java index e6a8b35a..e74a2308 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java @@ -12,7 +12,6 @@ import java.util.Collection; import javax.validation.Valid; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,7 +29,7 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; -import ch.ethz.seb.sebserver.webservice.servicelayer.activation.EntityActivationEvent; +import ch.ethz.seb.sebserver.webservice.servicelayer.activation.EntityActivationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; @@ -48,23 +47,23 @@ public class UserAccountController { private final AuthorizationGrantService authorizationGrantService; private final UserService userService; private final UserActivityLogDAO userActivityLogDAO; - private final ApplicationEventPublisher applicationEventPublisher; private final PaginationService paginationService; + private final EntityActivationService entityActivationService; public UserAccountController( final UserDAO userDao, final AuthorizationGrantService authorizationGrantService, final UserService userService, final UserActivityLogDAO userActivityLogDAO, - final ApplicationEventPublisher applicationEventPublisher, - final PaginationService paginationService) { + final PaginationService paginationService, + final EntityActivationService entityActivationService) { this.userDao = userDao; this.authorizationGrantService = authorizationGrantService; this.userService = userService; this.userActivityLogDAO = userActivityLogDAO; - this.applicationEventPublisher = applicationEventPublisher; this.paginationService = paginationService; + this.entityActivationService = entityActivationService; } @RequestMapping(method = RequestMethod.GET) @@ -85,7 +84,7 @@ public class UserAccountController { return getAll(createUserFilter(institutionId, active, name, username, email, locale)); } - @RequestMapping(value = "/page", method = RequestMethod.GET) + @RequestMapping(path = "/page", method = RequestMethod.GET) public Page getPage( @RequestParam(name = UserFilter.FILTER_ATTR_INSTITUTION, required = false) final Long institutionId, @RequestParam(name = UserFilter.FILTER_ATTR_ACTIVE, required = false) final Boolean active, @@ -113,14 +112,14 @@ public class UserAccountController { } - @RequestMapping(value = "/me", method = RequestMethod.GET) + @RequestMapping(path = "/me", method = RequestMethod.GET) public UserInfo loggedInUser() { return this.userService .getCurrentUser() .getUserInfo(); } - @RequestMapping(value = "/{uuid}", method = RequestMethod.GET) + @RequestMapping(path = "/{uuid}", method = RequestMethod.GET) public UserInfo accountInfo(@PathVariable final String uuid) { return this.userDao .byUuid(uuid) @@ -131,20 +130,20 @@ public class UserAccountController { } - @RequestMapping(value = "/create", method = RequestMethod.PUT) + @RequestMapping(path = "/create", method = RequestMethod.PUT) public UserInfo createUser(@Valid @RequestBody final UserMod userData) { return _saveUser(userData, PrivilegeType.WRITE) .getOrThrow(); } - @RequestMapping(value = "/save", method = RequestMethod.POST) + @RequestMapping(path = "/save", method = RequestMethod.POST) public UserInfo saveUser(@Valid @RequestBody final UserMod userData) { return _saveUser(userData, PrivilegeType.MODIFY) .getOrThrow(); } - @RequestMapping(value = "/{uuid}/activate", method = RequestMethod.POST) + @RequestMapping(path = "/{uuid}/activate", method = RequestMethod.POST) public UserInfo activateUser(@PathVariable final String uuid) { return setActive(uuid, true); } @@ -154,29 +153,33 @@ public class UserAccountController { return setActive(uuid, false); } - @RequestMapping(value = "/{uuid}/delete", method = RequestMethod.DELETE) + @RequestMapping(path = "/{uuid}/delete", method = RequestMethod.DELETE) public EntityProcessingReport deleteUser(@PathVariable final String uuid) { return this.userDao.pkForUUID(uuid) .flatMap(pk -> this.userDao.delete(pk, true)) - .map(report -> { - this.userActivityLogDAO.log(ActivityType.DELETE, EntityType.USER, uuid, "soft"); - return report; - }) + .flatMap(report -> this.userActivityLogDAO.log( + ActivityType.DELETE, + EntityType.USER, + uuid, + "soft-delete", + report)) .getOrThrow(); } - @RequestMapping(value = "/{uuid}/hard-delete", method = RequestMethod.DELETE) + @RequestMapping(path = "/{uuid}/hard-delete", method = RequestMethod.DELETE) public EntityProcessingReport hardDeleteUser(@PathVariable final String uuid) { return this.userDao.pkForUUID(uuid) .flatMap(pk -> this.userDao.delete(pk, false)) - .map(report -> { - this.userActivityLogDAO.log(ActivityType.DELETE, EntityType.USER, uuid, "hard"); - return report; - }) + .flatMap(report -> this.userActivityLogDAO.log( + ActivityType.DELETE, + EntityType.USER, + uuid, + "hard-delete", + report)) .getOrThrow(); } - @RequestMapping(value = "/{uuid}/relations", method = RequestMethod.GET) + @RequestMapping(path = "/{uuid}/relations", method = RequestMethod.GET) public EntityProcessingReport getAllUserRelatedData(@PathVariable final String uuid) { return this.userDao.getAllUserData(uuid) .getOrThrow(); @@ -184,18 +187,9 @@ public class UserAccountController { private UserInfo setActive(final String uuid, final boolean active) { - final ActivityType activityType = (active) - ? ActivityType.ACTIVATE - : ActivityType.DEACTIVATE; - return this.userDao.byUuid(uuid) .flatMap(userInfo -> this.authorizationGrantService.checkGrantOnEntity(userInfo, PrivilegeType.WRITE)) - .flatMap(userInfo -> this.userDao.setActive(userInfo.uuid, active)) - .map(userInfo -> { - this.applicationEventPublisher.publishEvent(new EntityActivationEvent(userInfo, active)); - return userInfo; - }) - .flatMap(userInfo -> this.userActivityLogDAO.log(activityType, userInfo)) + .flatMap(userInfo -> this.entityActivationService.setActive(userInfo, active)) .getOrThrow(); } @@ -209,14 +203,16 @@ public class UserAccountController { .checkGrantOnEntity(userData, privilegeType) .flatMap(this.userDao::save) .flatMap(userInfo -> this.userActivityLogDAO.log(activityType, userInfo)) - .flatMap(userInfo -> { - // handle password change; revoke access tokens if password has changed - if (userData.passwordChangeRequest() && userData.newPasswordMatch()) { - this.applicationEventPublisher.publishEvent( - new RevokeTokenEndpoint.RevokeTokenEvent(this, userInfo.username)); - } - return Result.of(userInfo); - }); + .flatMap(userInfo -> revokePassword(userData, userInfo)); + } + + private Result revokePassword(final UserMod userData, final UserInfo userInfo) { + // handle password change; revoke access tokens if password has changed + if (userData.passwordChangeRequest() && userData.newPasswordMatch()) { + this.entityActivationService.getApplicationEventPublisher().publishEvent( + new RevokeTokenEndpoint.RevokeTokenEvent(this, userInfo.username)); + } + return Result.of(userInfo); } private Collection getAll(final UserFilter userFilter) {