refactoring EntityController
This commit is contained in:
parent
2b3d4aa27d
commit
201e37914e
6 changed files with 107 additions and 46 deletions
|
@ -104,7 +104,7 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
||||||
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
|
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||||
.andForRole(UserRole.EXAM_ADMIN)
|
.andForRole(UserRole.EXAM_ADMIN)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
|
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||||
.withOwnerPrivilege(PrivilegeType.WRITE)
|
.withOwnerPrivilege(PrivilegeType.WRITE)
|
||||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||||
|
@ -117,7 +117,7 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
||||||
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
|
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||||
.andForRole(UserRole.EXAM_ADMIN)
|
.andForRole(UserRole.EXAM_ADMIN)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
|
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||||
.withOwnerPrivilege(PrivilegeType.WRITE)
|
.withOwnerPrivilege(PrivilegeType.WRITE)
|
||||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||||
|
|
|
@ -11,12 +11,49 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
|
||||||
|
/** Service to address bulk actions like activation or deletion where the action
|
||||||
|
* or state-change of one Entity has an effect on other entities that that has
|
||||||
|
* a relation to the source entity.
|
||||||
|
* <p>
|
||||||
|
* A bulk action for a specified entity instance will be first applied to all its dependent
|
||||||
|
* child-entities. For example if one is going to delete/deactivate a particular LMS Setup, all
|
||||||
|
* Exams imported from this LMSSetup are first deactivated and all Exam Config Mapping and
|
||||||
|
* all Client Connection are of all the Exams are deactivated first.
|
||||||
|
* <p>
|
||||||
|
* below is the relation-tree of known node-entities of the SEB Server application
|
||||||
|
* <code>
|
||||||
|
* Institution
|
||||||
|
* ____________ / | \______________
|
||||||
|
* / | \
|
||||||
|
* LMS Setup | User-Account
|
||||||
|
* | |
|
||||||
|
* Exam Configuration
|
||||||
|
* |\ /
|
||||||
|
* | Exam Config Mapping
|
||||||
|
* |
|
||||||
|
* Client Connection
|
||||||
|
* </code> */
|
||||||
public interface BulkActionService {
|
public interface BulkActionService {
|
||||||
|
|
||||||
|
/** Use this to collect all EntityKey's of all dependent entities for a given BulkAction.
|
||||||
|
*
|
||||||
|
* @param action the BulkAction defining the source entity keys and acts also as the
|
||||||
|
* dependency collector */
|
||||||
void collectDependencies(BulkAction action);
|
void collectDependencies(BulkAction action);
|
||||||
|
|
||||||
|
/** This executes a given BulkAction by first getting all dependencies and applying
|
||||||
|
* the action to that first and then applying the action to the source entities of
|
||||||
|
* the BulkAction.
|
||||||
|
*
|
||||||
|
* @param action the BulkAction that defines at least the type and the source entity keys
|
||||||
|
* @return The BulkAction containing the result of the execution */
|
||||||
Result<BulkAction> doBulkAction(BulkAction action);
|
Result<BulkAction> doBulkAction(BulkAction action);
|
||||||
|
|
||||||
|
/** Creates a EntityProcessingReport from a given BulkAction result.
|
||||||
|
* If the given BulkAction has not already been executed, it will be executed first
|
||||||
|
*
|
||||||
|
* @param action the BulkAction of a concrete type
|
||||||
|
* @return EntityProcessingReport extracted form an executed BulkAxtion */
|
||||||
Result<EntityProcessingReport> createReport(BulkAction action);
|
Result<EntityProcessingReport> createReport(BulkAction action);
|
||||||
|
|
||||||
}
|
}
|
|
@ -336,14 +336,17 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public Result<UserActivityLog> save(final UserActivityLog modified) {
|
public Result<UserActivityLog> save(final UserActivityLog modified) {
|
||||||
// TODO Auto-generated method stub
|
throw new UnsupportedOperationException();
|
||||||
return Result.ofTODO();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<UserActivityLog> createNew(final UserActivityLog data) {
|
public Result<UserActivityLog> createNew(final UserActivityLog data) {
|
||||||
// TODO Auto-generated method stub
|
return log(
|
||||||
return Result.ofTODO();
|
data.activityType,
|
||||||
|
data.entityType,
|
||||||
|
data.entityId,
|
||||||
|
data.message,
|
||||||
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -40,7 +40,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
|
||||||
* @param <T> The concrete Entity domain-model type used on all GET, PUT
|
* @param <T> The concrete Entity domain-model type used on all GET, PUT
|
||||||
* @param <M> The concrete Entity domain-model type used for POST methods (new) */
|
* @param <M> The concrete Entity domain-model type used for POST methods (new) */
|
||||||
public abstract class ActivatableEntityController<T extends GrantEntity, M extends GrantEntity>
|
public abstract class ActivatableEntityController<T extends GrantEntity, M extends GrantEntity>
|
||||||
extends GrantEntityController<T, M> {
|
extends EntityController<T, M> {
|
||||||
|
|
||||||
public ActivatableEntityController(
|
public ActivatableEntityController(
|
||||||
final AuthorizationService authorizationGrantService,
|
final AuthorizationService authorizationGrantService,
|
||||||
|
|
|
@ -55,7 +55,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
|
||||||
*
|
*
|
||||||
* @param <T> The concrete Entity domain-model type used on all GET, PUT
|
* @param <T> The concrete Entity domain-model type used on all GET, PUT
|
||||||
* @param <M> The concrete Entity domain-model type used for POST methods (new) */
|
* @param <M> The concrete Entity domain-model type used for POST methods (new) */
|
||||||
public abstract class GrantEntityController<T extends GrantEntity, M extends GrantEntity> {
|
public abstract class EntityController<T extends Entity, M extends Entity> {
|
||||||
|
|
||||||
protected final AuthorizationService authorization;
|
protected final AuthorizationService authorization;
|
||||||
protected final BulkActionService bulkActionService;
|
protected final BulkActionService bulkActionService;
|
||||||
|
@ -64,7 +64,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
protected final PaginationService paginationService;
|
protected final PaginationService paginationService;
|
||||||
protected final BeanValidationService beanValidationService;
|
protected final BeanValidationService beanValidationService;
|
||||||
|
|
||||||
protected GrantEntityController(
|
protected EntityController(
|
||||||
final AuthorizationService authorization,
|
final AuthorizationService authorization,
|
||||||
final BulkActionService bulkActionService,
|
final BulkActionService bulkActionService,
|
||||||
final EntityDAO<T, M> entityDAO,
|
final EntityDAO<T, M> entityDAO,
|
||||||
|
@ -196,7 +196,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
|
|
||||||
this.entityDAO
|
this.entityDAO
|
||||||
.byModelId(modelId)
|
.byModelId(modelId)
|
||||||
.flatMap(this.authorization::checkRead);
|
.map(this::checkReadAccess);
|
||||||
|
|
||||||
final BulkAction bulkAction = new BulkAction(
|
final BulkAction bulkAction = new BulkAction(
|
||||||
bulkActionType,
|
bulkActionType,
|
||||||
|
@ -220,7 +220,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
|
|
||||||
return this.entityDAO
|
return this.entityDAO
|
||||||
.byModelId(modelId)
|
.byModelId(modelId)
|
||||||
.flatMap(this.authorization::checkRead)
|
.flatMap(this::checkReadAccess)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
.flatMap(this.entityDAO::byEntityKeys)
|
.flatMap(this.entityDAO::byEntityKeys)
|
||||||
.getOrThrow()
|
.getOrThrow()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(this.authorization::hasReadonlyGrant)
|
.filter(this::hasReadAccess)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
|
|
||||||
final M requestModel = this.createNew(postMap);
|
final M requestModel = this.createNew(postMap);
|
||||||
|
|
||||||
return this.authorization.checkWrite(requestModel)
|
return this.checkCreateAccess(requestModel)
|
||||||
.flatMap(this::validForCreate)
|
.flatMap(this::validForCreate)
|
||||||
.flatMap(this.entityDAO::createNew)
|
.flatMap(this.entityDAO::createNew)
|
||||||
.flatMap(this.userActivityLogDAO::logCreate)
|
.flatMap(this.userActivityLogDAO::logCreate)
|
||||||
|
@ -294,7 +294,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||||
public T savePut(@Valid @RequestBody final T modifyData) {
|
public T savePut(@Valid @RequestBody final T modifyData) {
|
||||||
|
|
||||||
return this.authorization.checkModify(modifyData)
|
return this.checkModifyAccess(modifyData)
|
||||||
.flatMap(this::validForSave)
|
.flatMap(this::validForSave)
|
||||||
.flatMap(this.entityDAO::save)
|
.flatMap(this.entityDAO::save)
|
||||||
.flatMap(this.userActivityLogDAO::logModify)
|
.flatMap(this.userActivityLogDAO::logModify)
|
||||||
|
@ -302,35 +302,6 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************
|
|
||||||
// * PATCH (save)
|
|
||||||
// ******************
|
|
||||||
|
|
||||||
// NOTE: not supported yet because of difficulties on conversion of params-map to json object
|
|
||||||
// @RequestMapping(
|
|
||||||
// path = "/{id}",
|
|
||||||
// method = RequestMethod.PATCH,
|
|
||||||
// consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
|
||||||
// produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
// public T savePost(
|
|
||||||
// @PathVariable final String id,
|
|
||||||
// @RequestParam final MultiValueMap<String, String> allRequestParams,
|
|
||||||
// @RequestParam(
|
|
||||||
// name = Entity.FILTER_ATTR_INSTITUTION,
|
|
||||||
// required = true,
|
|
||||||
// defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
|
|
||||||
//
|
|
||||||
// allRequestParams.putIfAbsent(
|
|
||||||
// Domain.ATTR_INSTITUTION_ID,
|
|
||||||
// Arrays.asList(String.valueOf(institutionId)));
|
|
||||||
// final M requestModel = this.toRequestModel(null, allRequestParams);
|
|
||||||
//
|
|
||||||
// return this.entityDAO.save(id, requestModel)
|
|
||||||
// .flatMap(entity -> this.userActivityLogDAO.log(ActivityType.MODIFY, entity))
|
|
||||||
// .flatMap(entity -> notifySaved(requestModel, entity))
|
|
||||||
// .getOrThrow();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ******************
|
// ******************
|
||||||
// * DELETE (delete)
|
// * DELETE (delete)
|
||||||
// ******************
|
// ******************
|
||||||
|
@ -347,7 +318,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
new EntityKey(modelId, entityType));
|
new EntityKey(modelId, entityType));
|
||||||
|
|
||||||
return this.entityDAO.byModelId(modelId)
|
return this.entityDAO.byModelId(modelId)
|
||||||
.flatMap(this.authorization::checkWrite)
|
.flatMap(this::checkWriteAccess)
|
||||||
.flatMap(entity -> this.bulkActionService.createReport(bulkAction))
|
.flatMap(entity -> this.bulkActionService.createReport(bulkAction))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
@ -362,7 +333,7 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
protected Result<Collection<T>> getAll(final FilterMap filterMap) {
|
protected Result<Collection<T>> getAll(final FilterMap filterMap) {
|
||||||
return this.entityDAO.allMatching(
|
return this.entityDAO.allMatching(
|
||||||
filterMap,
|
filterMap,
|
||||||
this.authorization::hasReadonlyGrant);
|
this::hasReadAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Result<T> notifyCreated(final T entity) {
|
protected Result<T> notifyCreated(final T entity) {
|
||||||
|
@ -390,6 +361,56 @@ public abstract class GrantEntityController<T extends GrantEntity, M extends Gra
|
||||||
return Result.of(entity);
|
return Result.of(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Result<T> checkReadAccess(final T entity) {
|
||||||
|
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||||
|
if (grantEntity != null) {
|
||||||
|
this.authorization.checkRead(grantEntity);
|
||||||
|
}
|
||||||
|
return Result.of(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasReadAccess(final T entity) {
|
||||||
|
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||||
|
if (grantEntity != null) {
|
||||||
|
return this.authorization.hasReadonlyGrant(grantEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<T> checkModifyAccess(final T entity) {
|
||||||
|
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||||
|
if (grantEntity != null) {
|
||||||
|
this.authorization.checkModify(grantEntity);
|
||||||
|
}
|
||||||
|
return Result.of(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<T> checkWriteAccess(final T entity) {
|
||||||
|
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||||
|
if (grantEntity != null) {
|
||||||
|
this.authorization.checkWrite(grantEntity);
|
||||||
|
}
|
||||||
|
return Result.of(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<M> checkCreateAccess(final M entity) {
|
||||||
|
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||||
|
if (grantEntity != null) {
|
||||||
|
this.authorization.checkWrite(grantEntity);
|
||||||
|
}
|
||||||
|
return Result.of(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GrantEntity toGrantEntity(final Entity entity) {
|
||||||
|
if (entity instanceof GrantEntity) {
|
||||||
|
return (GrantEntity) entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Entity instance is not of type GrantEntity. "
|
||||||
|
+ "Do override the toGrantEntity method from EntityController within the specific -Controller implementation");
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract M createNew(POSTMapper postParams);
|
protected abstract M createNew(POSTMapper postParams);
|
||||||
|
|
||||||
protected abstract SqlTable getSQLTableOfEntity();
|
protected abstract SqlTable getSQLTableOfEntity();
|
|
@ -29,7 +29,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
|
||||||
@WebServiceProfile
|
@WebServiceProfile
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + API.EXAM_INDICATOR_ENDPOINT)
|
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + API.EXAM_INDICATOR_ENDPOINT)
|
||||||
public class IndicatorController extends GrantEntityController<Indicator, Indicator> {
|
public class IndicatorController extends EntityController<Indicator, Indicator> {
|
||||||
|
|
||||||
private final ExamDAO examDao;
|
private final ExamDAO examDao;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue