SEBSERV-6 #finished InstitutionController implementation

This commit is contained in:
anhefti 2019-01-10 12:04:46 +01:00
parent 87f51aae65
commit ffeb663351
10 changed files with 275 additions and 75 deletions

View file

@ -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.Activatable;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Domain.INSTITUTION; 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.gbl.model.EntityType;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
public final class Institution implements GrantEntity, Activatable { 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) @JsonProperty(Domain.ATTR_ID)
public final Long id; public final Long id;
@ -108,4 +109,8 @@ public final class Institution implements GrantEntity, Activatable {
+ ", active=" + this.active + "]"; + ", active=" + this.active + "]";
} }
public static EntityIdAndName toName(final Institution institution) {
return new EntityIdAndName(String.valueOf(institution.id), institution.name);
}
} }

View file

@ -10,20 +10,37 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.activation;
import java.util.Collection; import java.util.Collection;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; 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.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.ActivatableEntityDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
@Service @Service
@WebServiceProfile @WebServiceProfile
public class EntityActivationService { public class EntityActivationService {
private final Collection<ActivatableEntityDAO<?>> activatableEntityDAOs; private final Collection<ActivatableEntityDAO<?>> activatableEntityDAOs;
private final ApplicationEventPublisher applicationEventPublisher;
private final UserActivityLogDAO userActivityLogDAO;
public EntityActivationService(
final Collection<ActivatableEntityDAO<?>> activatableEntityDAOs,
final ApplicationEventPublisher applicationEventPublisher,
final UserActivityLogDAO userActivityLogDAO) {
public EntityActivationService(final Collection<ActivatableEntityDAO<?>> activatableEntityDAOs) {
this.activatableEntityDAOs = activatableEntityDAOs; this.activatableEntityDAOs = activatableEntityDAOs;
this.applicationEventPublisher = applicationEventPublisher;
this.userActivityLogDAO = userActivityLogDAO;
}
public ApplicationEventPublisher getApplicationEventPublisher() {
return this.applicationEventPublisher;
} }
@EventListener(EntityActivationEvent.class) @EventListener(EntityActivationEvent.class)
@ -37,4 +54,33 @@ public class EntityActivationService {
} }
} }
public <T extends Entity> Result<T> 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 <T extends Entity> Result<T> publishEvent(final T entity, final boolean activated) {
this.applicationEventPublisher.publishEvent(new EntityActivationEvent(entity, activated));
return Result.of(entity);
}
@SuppressWarnings("unchecked")
private <T extends Entity> ActivatableEntityDAO<T> getDAOForEntity(final T entity) {
for (final ActivatableEntityDAO<?> dao : this.activatableEntityDAOs) {
if (dao.entityType() == entity.entityType()) {
return (ActivatableEntityDAO<T>) dao;
}
}
return null;
}
} }

View file

@ -13,6 +13,7 @@ import java.util.Collection;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -36,9 +37,14 @@ public class UserServiceImpl implements UserService {
} }
private final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies; private final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies;
private final ApplicationEventPublisher applicationEventPublisher;
public UserServiceImpl(
final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies,
final ApplicationEventPublisher applicationEventPublisher) {
public UserServiceImpl(final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies) {
this.extractStrategies = extractStrategies; this.extractStrategies = extractStrategies;
this.applicationEventPublisher = applicationEventPublisher;
} }
@Override @Override

View file

@ -16,7 +16,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
/** Interface of a DAO for an Entity that has activation feature. /** Interface of a DAO for an Entity that has activation feature.
* *
* @param <T> the concrete Entity type */ * @param <T> the concrete Entity type */
public interface ActivatableEntityDAO<T> { public interface ActivatableEntityDAO<T extends Entity> extends EntityDAO<T> {
/** Get a Collection of all active Entity instances for a concrete entity-domain. /** Get a Collection of all active Entity instances for a concrete entity-domain.
* *
@ -35,7 +35,7 @@ public interface ActivatableEntityDAO<T> {
* This can be used to take action in dependency of an activation of an Entity of different type. * 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 * For example a user-account DAO want to react on a Institution activation to also activate all user
* accounts for this institution. * accounts for this institution.
* *
* @param source The source Entity that has been activated */ * @param source The source Entity that has been activated */
void notifyActivation(Entity source); void notifyActivation(Entity source);
@ -43,7 +43,7 @@ public interface ActivatableEntityDAO<T> {
* This can be used to take action in dependency of an deactivation of an Entity of different type. * 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 * For example a user-account DAO want to react on a Institution deactivation to also deactivate all user
* accounts for this institution. * accounts for this institution.
* *
* @param source The source Entity that has been deactivated */ * @param source The source Entity that has been deactivated */
void notifyDeactivation(Entity source); void notifyDeactivation(Entity source);

View file

@ -13,7 +13,7 @@ import java.util.Collection;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
public interface InstitutionDAO extends EntityDAO<Institution>, ActivatableEntityDAO<Institution> { public interface InstitutionDAO extends ActivatableEntityDAO<Institution> {
Result<Collection<Institution>> allMatching(String name, Boolean active); Result<Collection<Institution>> allMatching(String name, Boolean active);

View file

@ -49,6 +49,13 @@ public interface UserActivityLogDAO extends UserRelatedEntityDAO<UserActivityLog
* @param message the message */ * @param message the message */
void log(ActivityType activityType, EntityType entityType, String entityId, String message); void log(ActivityType activityType, EntityType entityType, String entityId, String message);
/** Creates a user activity log entry for the current user.
*
* @param activityType the activity type
* @param entityType the EntityType
* @param message the message */
<T> Result<T> log(ActivityType activityType, EntityType entityType, String entityId, String message, T data);
/** Creates a user activity log entry. /** Creates a user activity log entry.
* *
* @param user for specified SEBServerUser instance * @param user for specified SEBServerUser instance

View file

@ -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, /** 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 * save and modify user related data within UserMod and get internal user principal data
* within SEBServerUser. */ * within SEBServerUser. */
public interface UserDAO extends EntityDAO<UserInfo>, ActivatableEntityDAO<UserInfo> { public interface UserDAO extends ActivatableEntityDAO<UserInfo> {
/** Use this to get UserInfo by users UUID /** Use this to get UserInfo by users UUID
* *

View file

@ -109,6 +109,25 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
} }
} }
@Override
public <T> Result<T> 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 @Override
@Transactional @Transactional
public <E extends Entity> Result<E> log( public <E extends Entity> Result<E> log(

View file

@ -8,22 +8,33 @@
package ch.ethz.seb.sebserver.webservice.weblayer.api; package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Arrays;
import java.util.Collection; 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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; 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.EntityType;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; 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.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType; 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.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; 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;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
@WebServiceProfile @WebServiceProfile
@RestController @RestController
@ -34,51 +45,161 @@ public class InstitutionController {
private final AuthorizationGrantService authorizationGrantService; private final AuthorizationGrantService authorizationGrantService;
private final UserService userService; private final UserService userService;
private final UserActivityLogDAO userActivityLogDAO; private final UserActivityLogDAO userActivityLogDAO;
private final ApplicationEventPublisher applicationEventPublisher; private final EntityActivationService entityActivationService;
public InstitutionController( public InstitutionController(
final InstitutionDAO institutionDAO, final InstitutionDAO institutionDAO,
final AuthorizationGrantService authorizationGrantService, final AuthorizationGrantService authorizationGrantService,
final UserService userService, final UserActivityLogDAO userActivityLogDAO, final UserService userService, final UserActivityLogDAO userActivityLogDAO,
final ApplicationEventPublisher applicationEventPublisher) { final EntityActivationService entityActivationService) {
this.institutionDAO = institutionDAO; this.institutionDAO = institutionDAO;
this.authorizationGrantService = authorizationGrantService; this.authorizationGrantService = authorizationGrantService;
this.userService = userService; this.userService = userService;
this.userActivityLogDAO = userActivityLogDAO; 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) @RequestMapping(method = RequestMethod.GET)
public Collection<Institution> getAll( public Collection<Institution> 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 checkBaseReadPrivilege();
this.authorizationGrantService.checkHasAnyPrivilege(
EntityType.INSTITUTION,
PrivilegeType.READ_ONLY);
final boolean hasBasePrivilege = this.authorizationGrantService.hasBasePrivilege( if (!this.authorizationGrantService.hasBasePrivilege(
EntityType.USER, EntityType.USER,
PrivilegeType.READ_ONLY); 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();
// User has only institutional privilege, can see only the institution he/she belongs to
return Arrays.asList(getOwn());
} else { } else {
return this.institutionDAO.all(inst -> true, active).getOrThrow();
return this.institutionDAO
.all()
.getOrThrow();
} }
} }
@RequestMapping(path = "/names", method = RequestMethod.GET)
public Collection<EntityIdAndName> 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<Institution> _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);
}
} }

View file

@ -12,7 +12,6 @@ import java.util.Collection;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; 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.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport; 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.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.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
@ -48,23 +47,23 @@ public class UserAccountController {
private final AuthorizationGrantService authorizationGrantService; private final AuthorizationGrantService authorizationGrantService;
private final UserService userService; private final UserService userService;
private final UserActivityLogDAO userActivityLogDAO; private final UserActivityLogDAO userActivityLogDAO;
private final ApplicationEventPublisher applicationEventPublisher;
private final PaginationService paginationService; private final PaginationService paginationService;
private final EntityActivationService entityActivationService;
public UserAccountController( public UserAccountController(
final UserDAO userDao, final UserDAO userDao,
final AuthorizationGrantService authorizationGrantService, final AuthorizationGrantService authorizationGrantService,
final UserService userService, final UserService userService,
final UserActivityLogDAO userActivityLogDAO, final UserActivityLogDAO userActivityLogDAO,
final ApplicationEventPublisher applicationEventPublisher, final PaginationService paginationService,
final PaginationService paginationService) { final EntityActivationService entityActivationService) {
this.userDao = userDao; this.userDao = userDao;
this.authorizationGrantService = authorizationGrantService; this.authorizationGrantService = authorizationGrantService;
this.userService = userService; this.userService = userService;
this.userActivityLogDAO = userActivityLogDAO; this.userActivityLogDAO = userActivityLogDAO;
this.applicationEventPublisher = applicationEventPublisher;
this.paginationService = paginationService; this.paginationService = paginationService;
this.entityActivationService = entityActivationService;
} }
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
@ -85,7 +84,7 @@ public class UserAccountController {
return getAll(createUserFilter(institutionId, active, name, username, email, locale)); return getAll(createUserFilter(institutionId, active, name, username, email, locale));
} }
@RequestMapping(value = "/page", method = RequestMethod.GET) @RequestMapping(path = "/page", method = RequestMethod.GET)
public Page<UserInfo> getPage( public Page<UserInfo> getPage(
@RequestParam(name = UserFilter.FILTER_ATTR_INSTITUTION, required = false) final Long institutionId, @RequestParam(name = UserFilter.FILTER_ATTR_INSTITUTION, required = false) final Long institutionId,
@RequestParam(name = UserFilter.FILTER_ATTR_ACTIVE, required = false) final Boolean active, @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() { public UserInfo loggedInUser() {
return this.userService return this.userService
.getCurrentUser() .getCurrentUser()
.getUserInfo(); .getUserInfo();
} }
@RequestMapping(value = "/{uuid}", method = RequestMethod.GET) @RequestMapping(path = "/{uuid}", method = RequestMethod.GET)
public UserInfo accountInfo(@PathVariable final String uuid) { public UserInfo accountInfo(@PathVariable final String uuid) {
return this.userDao return this.userDao
.byUuid(uuid) .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) { public UserInfo createUser(@Valid @RequestBody final UserMod userData) {
return _saveUser(userData, PrivilegeType.WRITE) return _saveUser(userData, PrivilegeType.WRITE)
.getOrThrow(); .getOrThrow();
} }
@RequestMapping(value = "/save", method = RequestMethod.POST) @RequestMapping(path = "/save", method = RequestMethod.POST)
public UserInfo saveUser(@Valid @RequestBody final UserMod userData) { public UserInfo saveUser(@Valid @RequestBody final UserMod userData) {
return _saveUser(userData, PrivilegeType.MODIFY) return _saveUser(userData, PrivilegeType.MODIFY)
.getOrThrow(); .getOrThrow();
} }
@RequestMapping(value = "/{uuid}/activate", method = RequestMethod.POST) @RequestMapping(path = "/{uuid}/activate", method = RequestMethod.POST)
public UserInfo activateUser(@PathVariable final String uuid) { public UserInfo activateUser(@PathVariable final String uuid) {
return setActive(uuid, true); return setActive(uuid, true);
} }
@ -154,29 +153,33 @@ public class UserAccountController {
return setActive(uuid, false); 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) { public EntityProcessingReport deleteUser(@PathVariable final String uuid) {
return this.userDao.pkForUUID(uuid) return this.userDao.pkForUUID(uuid)
.flatMap(pk -> this.userDao.delete(pk, true)) .flatMap(pk -> this.userDao.delete(pk, true))
.map(report -> { .flatMap(report -> this.userActivityLogDAO.log(
this.userActivityLogDAO.log(ActivityType.DELETE, EntityType.USER, uuid, "soft"); ActivityType.DELETE,
return report; EntityType.USER,
}) uuid,
"soft-delete",
report))
.getOrThrow(); .getOrThrow();
} }
@RequestMapping(value = "/{uuid}/hard-delete", method = RequestMethod.DELETE) @RequestMapping(path = "/{uuid}/hard-delete", method = RequestMethod.DELETE)
public EntityProcessingReport hardDeleteUser(@PathVariable final String uuid) { public EntityProcessingReport hardDeleteUser(@PathVariable final String uuid) {
return this.userDao.pkForUUID(uuid) return this.userDao.pkForUUID(uuid)
.flatMap(pk -> this.userDao.delete(pk, false)) .flatMap(pk -> this.userDao.delete(pk, false))
.map(report -> { .flatMap(report -> this.userActivityLogDAO.log(
this.userActivityLogDAO.log(ActivityType.DELETE, EntityType.USER, uuid, "hard"); ActivityType.DELETE,
return report; EntityType.USER,
}) uuid,
"hard-delete",
report))
.getOrThrow(); .getOrThrow();
} }
@RequestMapping(value = "/{uuid}/relations", method = RequestMethod.GET) @RequestMapping(path = "/{uuid}/relations", method = RequestMethod.GET)
public EntityProcessingReport getAllUserRelatedData(@PathVariable final String uuid) { public EntityProcessingReport getAllUserRelatedData(@PathVariable final String uuid) {
return this.userDao.getAllUserData(uuid) return this.userDao.getAllUserData(uuid)
.getOrThrow(); .getOrThrow();
@ -184,18 +187,9 @@ public class UserAccountController {
private UserInfo setActive(final String uuid, final boolean active) { private UserInfo setActive(final String uuid, final boolean active) {
final ActivityType activityType = (active)
? ActivityType.ACTIVATE
: ActivityType.DEACTIVATE;
return this.userDao.byUuid(uuid) return this.userDao.byUuid(uuid)
.flatMap(userInfo -> this.authorizationGrantService.checkGrantOnEntity(userInfo, PrivilegeType.WRITE)) .flatMap(userInfo -> this.authorizationGrantService.checkGrantOnEntity(userInfo, PrivilegeType.WRITE))
.flatMap(userInfo -> this.userDao.setActive(userInfo.uuid, active)) .flatMap(userInfo -> this.entityActivationService.setActive(userInfo, active))
.map(userInfo -> {
this.applicationEventPublisher.publishEvent(new EntityActivationEvent(userInfo, active));
return userInfo;
})
.flatMap(userInfo -> this.userActivityLogDAO.log(activityType, userInfo))
.getOrThrow(); .getOrThrow();
} }
@ -209,14 +203,16 @@ public class UserAccountController {
.checkGrantOnEntity(userData, privilegeType) .checkGrantOnEntity(userData, privilegeType)
.flatMap(this.userDao::save) .flatMap(this.userDao::save)
.flatMap(userInfo -> this.userActivityLogDAO.log(activityType, userInfo)) .flatMap(userInfo -> this.userActivityLogDAO.log(activityType, userInfo))
.flatMap(userInfo -> { .flatMap(userInfo -> revokePassword(userData, userInfo));
// handle password change; revoke access tokens if password has changed }
if (userData.passwordChangeRequest() && userData.newPasswordMatch()) {
this.applicationEventPublisher.publishEvent( private Result<UserInfo> revokePassword(final UserMod userData, final UserInfo userInfo) {
new RevokeTokenEndpoint.RevokeTokenEvent(this, userInfo.username)); // handle password change; revoke access tokens if password has changed
} if (userData.passwordChangeRequest() && userData.newPasswordMatch()) {
return Result.of(userInfo); this.entityActivationService.getApplicationEventPublisher().publishEvent(
}); new RevokeTokenEndpoint.RevokeTokenEvent(this, userInfo.username));
}
return Result.of(userInfo);
} }
private Collection<UserInfo> getAll(final UserFilter userFilter) { private Collection<UserInfo> getAll(final UserFilter userFilter) {