general entity controller and testing

This commit is contained in:
anhefti 2019-01-21 14:21:56 +01:00
parent bf45576610
commit 36b5551ac5
16 changed files with 473 additions and 384 deletions

View file

@ -11,8 +11,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.Collection;
import java.util.Set;
import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.ModelIdAware;
@ -23,13 +21,20 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
* @param <T> the concrete Entity type */
public interface ActivatableEntityDAO<T extends Entity, M extends ModelIdAware> extends EntityDAO<T, M> {
/** Get a Collection of all active Entity instances for a concrete entity-domain.
*
* @return A Result refer to a Collection of all active Entity instances for a concrete entity-domain
* or refer to an error if happened */
@Transactional(readOnly = true)
default Result<Collection<T>> allActive() {
return all(i -> true, true);
Result<Collection<T>> all(Long institutionId, Boolean active);
default Result<Collection<T>> allOfInstitution(final long institutionId, final Boolean active) {
return all(institutionId, active);
}
@Override
default Result<Collection<T>> all(final Long institutionId) {
return all(institutionId, true);
}
@Override
default Result<Collection<T>> allOfInstitution(final long institutionId) {
return all(institutionId, true);
}
/** Set all entities referred by the given Collection of EntityKey active / inactive

View file

@ -12,7 +12,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.springframework.transaction.annotation.Transactional;
@ -59,10 +58,11 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
* If you need a fast filtering implement a specific filtering in SQL level
*
* @param predicate Predicate expecting instance of type specific entity type
* @param
* @param active indicates if only active entities should be included (on SQL level). Can be null.
* @return Result of Collection of Entity that matches a given predicate. Or an exception result on error
* case */
Result<Collection<T>> all(Predicate<T> predicate, Boolean active);
Result<Collection<T>> all(Long institutionId);
/** Use this to get a Collection of all entities of concrete type that matches a given predicate.
*
@ -73,15 +73,8 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
* @param predicate Predicate expecting instance of type specific entity type
* @return Result of Collection of Entity that matches a given predicate. Or an exception result on error
* case */
default Result<Collection<T>> all(final Predicate<T> predicate) {
return all(predicate, null);
}
/** Use this to get a Collection of all active entities of concrete type
*
* @return Result of Collection of all active entities or an exception result on error case */
default Result<Collection<T>> all() {
return all(entity -> true);
default Result<Collection<T>> allOfInstitution(final long institutionId) {
return all(institutionId);
}
Result<Collection<T>> loadEntities(Collection<EntityKey> keys);

View file

@ -9,9 +9,6 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.Collection;
import java.util.function.Predicate;
import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.user.UserFilter;
@ -50,23 +47,7 @@ public interface UserDAO extends ActivatableEntityDAO<UserInfo, UserMod>, BulkAc
*
* @param filter The UserFilter instance containing all filter criteria
* @return a Result of Collection of filtered UserInfo. Or an exception result on error case */
@Transactional(readOnly = true)
default Result<Collection<UserInfo>> all(final UserFilter filter) {
return all(filter, userInfo -> true);
}
/** Use this to get a Collection of filtered UserInfo. The filter criteria
* from given UserFilter instance will be translated to SQL query and
* the filtering happens on data-base level
*
* Additional there can also given a predicate to filter UserInfo models after the SQL query
*
* NOTE: filter and predicate can be null. In this case(s) the default all methods are called
*
* @param filter The UserFilter instance containing all filter criteria
* @param predicate Predicate of UserInfo to filter the result of the SQL query afterwards
* @return a Result of Collection of filtered UserInfo. Or an exception result on error case */
Result<Collection<UserInfo>> all(UserFilter filter, Predicate<UserInfo> predicate);
Result<Collection<UserInfo>> allMatching(final UserFilter filter);
/** Use this to get a Collection containing EntityKey's of all entities that belongs to a given User.
*

View file

@ -82,7 +82,7 @@ public class ExamDAOImpl implements ExamDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<Exam>> all(final Predicate<Exam> predicate, final Boolean active) {
public Result<Collection<Exam>> all(final Long institutionId, final Boolean active) {
return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<ExamRecord>>> example =
this.examRecordMapper.selectByExample();
@ -90,6 +90,9 @@ public class ExamDAOImpl implements ExamDAO {
return (active != null)
? example
.where(
ExamRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(institutionId))
.and(
ExamRecordDynamicSqlSupport.active,
isEqualToWhenPresent(BooleanUtils.toIntegerObject(active)))
.build()

View file

@ -15,7 +15,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
@ -63,7 +62,7 @@ public class InstitutionDAOImpl implements InstitutionDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<Institution>> all(final Predicate<Institution> predicate, final Boolean active) {
public Result<Collection<Institution>> all(final Long institutionId, final Boolean active) {
return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<InstitutionRecord>>> example =
this.institutionRecordMapper.selectByExample();
@ -71,6 +70,9 @@ public class InstitutionDAOImpl implements InstitutionDAO {
final List<InstitutionRecord> records = (active != null)
? example
.where(
InstitutionRecordDynamicSqlSupport.id,
isEqualToWhenPresent(institutionId))
.and(
InstitutionRecordDynamicSqlSupport.active,
isEqualToWhenPresent(BooleanUtils.toIntegerObject(active)))
.build()
@ -80,7 +82,6 @@ public class InstitutionDAOImpl implements InstitutionDAO {
return records.stream()
.map(InstitutionDAOImpl::toDomainModel)
.flatMap(Result::skipOnError)
.filter(predicate)
.collect(Collectors.toList());
});
}

View file

@ -15,7 +15,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
@ -62,7 +61,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<LmsSetup>> all(final Predicate<LmsSetup> predicate, final Boolean active) {
public Result<Collection<LmsSetup>> all(final Long institutionId, final Boolean active) {
return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<LmsSetupRecord>>> example =
this.lmsSetupRecordMapper.selectByExample();
@ -70,6 +69,9 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
final List<LmsSetupRecord> records = (active != null)
? example
.where(
LmsSetupRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(institutionId))
.and(
LmsSetupRecordDynamicSqlSupport.active,
isEqualToWhenPresent(BooleanUtils.toIntegerObject(active)))
.build()
@ -79,7 +81,6 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
return records.stream()
.map(LmsSetupDAOImpl::toDomainModel)
.flatMap(Result::skipOnError)
.filter(predicate)
.collect(Collectors.toList());
});
}

View file

@ -255,7 +255,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<UserActivityLog>> all(final Predicate<UserActivityLog> predicate, final Boolean active) {
public Result<Collection<UserActivityLog>> all(final Long institutionId) {
return Result.tryCatch(() -> {
// first check if there is a page limitation set. Otherwise set the default
@ -263,15 +263,32 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
this.paginationService.setDefaultLimitOfNotSet(
UserActivityLogRecordDynamicSqlSupport.userActivityLogRecord);
return this.userLogRecordMapper
.selectByExample()
.build()
.execute()
.stream()
.map(UserActivityLogDAOImpl::toDomainModel)
.flatMap(Result::skipOnError)
.filter(predicate)
.collect(Collectors.toList());
if (institutionId == null) {
return this.userLogRecordMapper
.selectByExample()
.build()
.execute()
.stream()
.map(UserActivityLogDAOImpl::toDomainModel)
.flatMap(Result::skipOnError)
.collect(Collectors.toList());
} else {
return this.userLogRecordMapper
.selectByExample()
.join(UserRecordDynamicSqlSupport.userRecord)
.on(
UserRecordDynamicSqlSupport.uuid,
SqlBuilder.equalTo(UserActivityLogRecordDynamicSqlSupport.userUuid))
.where(
UserRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualTo(institutionId))
.build()
.execute()
.stream()
.map(UserActivityLogDAOImpl::toDomainModel)
.flatMap(Result::skipOnError)
.collect(Collectors.toList());
}
});
}

View file

@ -17,15 +17,12 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.validation.constraints.NotNull;
import org.apache.commons.lang3.BooleanUtils;
import org.joda.time.DateTimeZone;
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
@ -60,7 +57,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
public class UserDaoImpl implements UserDAO {
private static final Logger log = LoggerFactory.getLogger(UserDaoImpl.class);
private static final UserFilter ALL_ACTIVE_ONLY_FILTER = new UserFilter(null, null, null, null, true, null);
private final UserRecordMapper userRecordMapper;
private final RoleRecordMapper roleRecordMapper;
@ -118,43 +114,35 @@ public class UserDaoImpl implements UserDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<UserInfo>> allActive() {
return all(ALL_ACTIVE_ONLY_FILTER);
}
@Override
@Transactional(readOnly = true)
public Result<Collection<UserInfo>> all(final Predicate<UserInfo> predicate, final Boolean active) {
public Result<Collection<UserInfo>> all(final Long institutionId, final Boolean active) {
return Result.tryCatch(() -> {
final QueryExpressionDSL<MyBatis3SelectModelAdapter<List<UserRecord>>> example =
this.userRecordMapper.selectByExample();
final List<UserRecord> records = (active != null)
? example
? this.userRecordMapper.selectByExample()
.where(
UserRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(institutionId))
.and(
UserRecordDynamicSqlSupport.active,
isEqualToWhenPresent(BooleanUtils.toIntegerObject(active)))
.build()
.execute()
: example.build().execute();
: this.userRecordMapper.selectByExample()
.where(
UserRecordDynamicSqlSupport.institutionId,
isEqualToWhenPresent(institutionId))
.build()
.execute();
return records.stream()
.map(this::toDomainModel)
.flatMap(Result::skipOnError)
.filter(predicate)
.collect(Collectors.toList());
});
}
@Override
@Transactional(readOnly = true)
public Result<Collection<UserInfo>> all(final UserFilter filter, final Predicate<UserInfo> predicate) {
if (filter == null) {
return (predicate == null)
? all()
: all(predicate);
}
public Result<Collection<UserInfo>> allMatching(final UserFilter filter) {
return Result.tryCatch(() -> this.userRecordMapper.selectByExample().where(
UserRecordDynamicSqlSupport.active,
isEqualToWhenPresent(BooleanUtils.toIntegerObject(filter.active)))
@ -168,7 +156,6 @@ public class UserDaoImpl implements UserDAO {
.stream()
.map(this::toDomainModel)
.flatMap(Result::skipOnError)
.filter(predicate)
.collect(Collectors.toList()));
}

View file

@ -8,35 +8,87 @@
package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Collection;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
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.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
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.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction.Type;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
public abstract class ActivatableEntityController<T extends GrantEntity, M extends GrantEntity>
extends EntityController<T, M> {
private final ActivatableEntityDAO<T, M> activatableEntityDAO;
public ActivatableEntityController(
final AuthorizationGrantService authorizationGrantService,
final BulkActionService bulkActionService,
final EntityDAO<T, M> entityDAO,
final ActivatableEntityDAO<T, M> entityDAO,
final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService) {
super(authorizationGrantService, bulkActionService, entityDAO, userActivityLogDAO, paginationService);
this.activatableEntityDAO = entityDAO;
}
@RequestMapping(path = "/active", method = RequestMethod.GET)
public Page<T> allActive(
@RequestParam(
name = Entity.ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
@RequestParam(name = Page.ATTR_SORT_BY, required = false) final String sortBy,
@RequestParam(name = Page.ATTR_SORT_ORDER, required = false) final Page.SortOrder sortOrder) {
checkReadPrivilege(institutionId);
return this.paginationService.getPage(
pageNumber,
pageSize,
sortBy,
sortOrder,
UserRecordDynamicSqlSupport.userRecord,
() -> this.activatableEntityDAO.all(institutionId, true).getOrThrow());
}
@RequestMapping(path = "/inactive", method = RequestMethod.GET)
public Page<T> allInactive(
@RequestParam(
name = Entity.ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
@RequestParam(name = Page.ATTR_SORT_BY, required = false) final String sortBy,
@RequestParam(name = Page.ATTR_SORT_ORDER, required = false) final Page.SortOrder sortOrder) {
checkReadPrivilege(institutionId);
return this.paginationService.getPage(
pageNumber,
pageSize,
sortBy,
sortOrder,
UserRecordDynamicSqlSupport.userRecord,
() -> this.activatableEntityDAO.all(institutionId, false).getOrThrow());
}
@RequestMapping(path = "/{id}/activate", method = RequestMethod.POST)
@ -56,6 +108,11 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
return deactivate(id);
}
@Override
protected Result<Collection<T>> getAll(final Long institutionId, final Boolean active) {
return this.activatableEntityDAO.all(institutionId, active);
}
private Result<EntityProcessingReport> setActive(final String id, final boolean active) {
final EntityType entityType = this.entityDAO.entityType();
final BulkAction bulkAction = new BulkAction(

View file

@ -27,9 +27,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityKeyAndName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
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.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
@ -74,37 +72,8 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.getOrThrow();
}
@RequestMapping(path = "/all", method = RequestMethod.GET)
public Page<T> allActive(
@RequestParam(
name = Entity.ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
@RequestParam(name = Page.ATTR_SORT_BY, required = false) final String sortBy,
@RequestParam(name = Page.ATTR_SORT_ORDER, required = false) final Page.SortOrder sortOrder) {
checkReadPrivilege(institutionId);
return this.paginationService.getPage(
pageNumber,
pageSize,
sortBy,
sortOrder,
UserRecordDynamicSqlSupport.userRecord,
() -> this.entityDAO.all(entity -> true, true).getOrThrow());
}
@RequestMapping(path = "/all/in", method = RequestMethod.GET)
public Collection<T> getForIds(
@RequestParam(
name = Entity.ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = "ids", required = true) final String ids) {
checkReadPrivilege(institutionId);
@RequestMapping(path = "/in", method = RequestMethod.GET)
public Collection<T> getForIds(@RequestParam(name = "ids", required = true) final String ids) {
return Result.tryCatch(() -> {
return Arrays.asList(StringUtils.split(ids, Constants.LIST_SEPARATOR_CHAR))
.stream()
@ -112,16 +81,24 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.collect(Collectors.toList());
})
.flatMap(this.entityDAO::loadEntities)
.getOrThrow();
.getOrThrow()
.stream()
.filter(entity -> this.authorizationGrantService.hasGrant(entity, PrivilegeType.READ_ONLY))
.collect(Collectors.toList());
}
@RequestMapping(path = "/names", method = RequestMethod.GET)
public Collection<EntityKeyAndName> getNames(
@RequestParam(
name = Entity.ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = Entity.ATTR_ACTIVE, required = false) final Boolean active) {
return this.entityDAO.all(entity -> true, true)
return getAll(institutionId, active)
.getOrThrow()
.stream()
.filter(entity -> this.authorizationGrantService.hasGrant(entity, PrivilegeType.READ_ONLY))
.map(Entity::toName)
.collect(Collectors.toList());
}
@ -170,4 +147,8 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
PrivilegeType.READ_ONLY,
institutionId);
}
protected Result<Collection<T>> getAll(final Long institutionId, final Boolean active) {
return this.entityDAO.all(institutionId);
}
}

View file

@ -13,22 +13,16 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
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.Constants;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.Page.SortOrder;
@ -37,29 +31,21 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
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.ExamRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
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;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction.Type;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
@WebServiceProfile
@RestController
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + RestAPI.ENDPOINT_EXAM_ADMINISTRATION)
public class ExamAdministrationController {
public class ExamAdministrationController extends ActivatableEntityController<Exam, Exam> {
private final AuthorizationGrantService authorizationGrantService;
private final UserActivityLogDAO userActivityLogDAO;
private final ExamDAO examDAO;
private final PaginationService paginationService;
private final BulkActionService bulkActionService;
public ExamAdministrationController(
final AuthorizationGrantService authorizationGrantService,
@ -68,11 +54,8 @@ public class ExamAdministrationController {
final PaginationService paginationService,
final BulkActionService bulkActionService) {
this.authorizationGrantService = authorizationGrantService;
this.userActivityLogDAO = userActivityLogDAO;
super(authorizationGrantService, bulkActionService, examDAO, userActivityLogDAO, paginationService);
this.examDAO = examDAO;
this.paginationService = paginationService;
this.bulkActionService = bulkActionService;
}
@InitBinder
@ -96,7 +79,7 @@ public class ExamAdministrationController {
@RequestParam(name = Exam.FILTER_ATTR_TYPE, required = false) final ExamType type,
@RequestParam(name = Exam.FILTER_ATTR_OWNER, required = false) final String owner) {
checkBaseReadPrivilege(institutionId);
checkReadPrivilege(institutionId);
this.paginationService.setDefaultLimit(ExamRecordDynamicSqlSupport.examRecord);
return getExams(institutionId, lmsSetupId, active, name, from, status, type, owner);
@ -120,7 +103,7 @@ public class ExamAdministrationController {
@RequestParam(name = Page.ATTR_SORT_BY, required = false) final String sortBy,
@RequestParam(name = Page.ATTR_SORT_ORDER, required = false) final Page.SortOrder sortOrder) {
checkBaseReadPrivilege(institutionId);
checkReadPrivilege(institutionId);
// NOTE: several attributes for sorting may be originated by the QuizData from LMS not by the database
// of the SEB Server. Therefore in the case we have no or the default sorting we can use the
@ -166,46 +149,6 @@ public class ExamAdministrationController {
}
}
@RequestMapping(path = "/{id}", method = RequestMethod.GET)
public Exam byId(@PathVariable final Long id) {
return this.examDAO
.byPK(id)
.flatMap(exam -> this.authorizationGrantService.checkGrantOnEntity(
exam,
PrivilegeType.READ_ONLY))
.getOrThrow();
}
@RequestMapping(path = "/save", method = RequestMethod.POST)
public Exam save(@Valid @RequestBody final Exam exam) {
return this.authorizationGrantService
.checkGrantOnEntity(exam, PrivilegeType.MODIFY)
.flatMap(this.examDAO::save)
.flatMap(entity -> this.userActivityLogDAO.log(ActivityType.MODIFY, entity))
.getOrThrow();
}
@RequestMapping(path = "/{id}/activate", method = RequestMethod.POST)
public EntityProcessingReport activate(@PathVariable final Long id) {
return setActive(id, true)
.getOrThrow();
}
@RequestMapping(value = "/{id}/deactivate", method = RequestMethod.POST)
public EntityProcessingReport deactivate(@PathVariable final Long id) {
return setActive(id, false)
.getOrThrow();
}
private Result<EntityProcessingReport> setActive(final Long id, final boolean active) {
return this.bulkActionService.createReport(new BulkAction(
(active) ? Type.ACTIVATE : Type.DEACTIVATE,
EntityType.LMS_SETUP,
new EntityKey(id, EntityType.LMS_SETUP)));
}
private Collection<Exam> getExams(
final Long institutionId,
final Long lmsSetupId,
@ -236,11 +179,4 @@ public class ExamAdministrationController {
active).getOrThrow();
}
private void checkBaseReadPrivilege(final Long institutionId) {
this.authorizationGrantService.checkPrivilege(
EntityType.EXAM,
PrivilegeType.READ_ONLY,
institutionId);
}
}

View file

@ -33,7 +33,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
public class InstitutionController extends ActivatableEntityController<Institution, Institution> {
private final InstitutionDAO institutionDAO;
private final AuthorizationGrantService authorizationGrantService;
public InstitutionController(
final InstitutionDAO institutionDAO,
@ -43,9 +42,7 @@ public class InstitutionController extends ActivatableEntityController<Instituti
final PaginationService paginationService) {
super(authorizationGrantService, bulkActionService, institutionDAO, userActivityLogDAO, paginationService);
this.institutionDAO = institutionDAO;
this.authorizationGrantService = authorizationGrantService;
}
@RequestMapping(path = "/self", method = RequestMethod.GET)
@ -69,7 +66,7 @@ public class InstitutionController extends ActivatableEntityController<Instituti
// User has only institutional privilege, can see only the institution he/she belongs to
return Arrays.asList(getOwn());
} else {
return this.institutionDAO.all(inst -> true, active).getOrThrow();
return this.institutionDAO.all(null, active).getOrThrow();
}
}

View file

@ -10,10 +10,8 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.io.InputStream;
import java.util.Collection;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.http.HttpStatus;
@ -21,40 +19,30 @@ import org.springframework.http.MediaType;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
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.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityKeyAndName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
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;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction.Type;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
@WebServiceProfile
@RestController
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + RestAPI.ENDPOINT_LMS_SETUP)
public class LmsSetupController {
public class LmsSetupController extends ActivatableEntityController<LmsSetup, LmsSetup> {
private final LmsSetupDAO lmsSetupDAO;
private final AuthorizationGrantService authorizationGrantService;
private final UserActivityLogDAO userActivityLogDAO;
private final BulkActionService bulkActionService;
private final LmsAPIService lmsAPIService;
public LmsSetupController(
@ -62,12 +50,12 @@ public class LmsSetupController {
final AuthorizationGrantService authorizationGrantService,
final UserActivityLogDAO userActivityLogDAO,
final BulkActionService bulkActionService,
final LmsAPIService lmsAPIService) {
final LmsAPIService lmsAPIService,
final PaginationService paginationService) {
super(authorizationGrantService, bulkActionService, lmsSetupDAO, userActivityLogDAO, paginationService);
this.lmsSetupDAO = lmsSetupDAO;
this.authorizationGrantService = authorizationGrantService;
this.userActivityLogDAO = userActivityLogDAO;
this.bulkActionService = bulkActionService;
this.lmsAPIService = lmsAPIService;
}
@ -95,34 +83,6 @@ public class LmsSetupController {
.getOrThrow();
}
@RequestMapping(path = "/names", method = RequestMethod.GET)
public Collection<EntityKeyAndName> getNames(
@RequestParam(
name = LmsSetup.FILTER_ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = LmsSetup.FILTER_ATTR_NAME, required = false) final String name,
@RequestParam(name = LmsSetup.FILTER_ATTR_LMS_TYPE, required = false) final LmsType lmsType,
@RequestParam(name = LmsSetup.FILTER_ATTR_ACTIVE, required = false) final Boolean active) {
checkReadPrivilege(institutionId);
return getAll(institutionId, name, lmsType, active)
.stream()
.map(LmsSetup::toName)
.collect(Collectors.toList());
}
@RequestMapping(path = "/{id}", method = RequestMethod.GET)
public LmsSetup getById(@PathVariable final Long id) {
return this.lmsSetupDAO
.byPK(id)
.flatMap(lmsSetup -> this.authorizationGrantService.checkGrantOnEntity(
lmsSetup,
PrivilegeType.READ_ONLY))
.getOrThrow();
}
@RequestMapping(
path = "/create_seb_config/{id}",
method = RequestMethod.GET,
@ -151,89 +111,4 @@ public class LmsSetupController {
}
}
@RequestMapping(path = "/create", method = RequestMethod.PUT)
public LmsSetup create(@Valid @RequestBody final LmsSetup lmsSetup) {
return save(lmsSetup, PrivilegeType.WRITE)
.getOrThrow();
}
@RequestMapping(path = "/save", method = RequestMethod.POST)
public LmsSetup save(@Valid @RequestBody final LmsSetup lmsSetup) {
return save(lmsSetup, PrivilegeType.MODIFY)
.getOrThrow();
}
@RequestMapping(path = "/{id}/activate", method = RequestMethod.POST)
public EntityProcessingReport activate(@PathVariable final Long id) {
return setActive(id, true);
}
@RequestMapping(value = "/{id}/deactivate", method = RequestMethod.POST)
public EntityProcessingReport deactivate(@PathVariable final Long id) {
return setActive(id, false);
}
@RequestMapping(path = "/{id}/delete", method = RequestMethod.DELETE)
public EntityProcessingReport deleteUser(@PathVariable final Long id) {
checkPrivilegeForInstitution(id, PrivilegeType.WRITE);
return this.bulkActionService.createReport(new BulkAction(
Type.DEACTIVATE,
EntityType.LMS_SETUP,
new EntityKey(id, EntityType.LMS_SETUP)))
.getOrThrow();
}
@RequestMapping(path = "/{id}/hard-delete", method = RequestMethod.DELETE)
public EntityProcessingReport hardDeleteUser(@PathVariable final Long id) {
checkPrivilegeForInstitution(id, PrivilegeType.WRITE);
return this.bulkActionService.createReport(new BulkAction(
Type.HARD_DELETE,
EntityType.LMS_SETUP,
new EntityKey(id, EntityType.LMS_SETUP)))
.getOrThrow();
}
private void checkPrivilegeForInstitution(final Long lmsSetupId, final PrivilegeType type) {
this.authorizationGrantService.checkHasAnyPrivilege(
EntityType.LMS_SETUP,
type);
this.lmsSetupDAO.byPK(lmsSetupId)
.flatMap(institution -> this.authorizationGrantService.checkGrantOnEntity(
institution,
type))
.getOrThrow();
}
private EntityProcessingReport setActive(final Long id, final boolean active) {
checkPrivilegeForInstitution(id, PrivilegeType.MODIFY);
return this.bulkActionService.createReport(new BulkAction(
(active) ? Type.ACTIVATE : Type.DEACTIVATE,
EntityType.LMS_SETUP,
new EntityKey(id, EntityType.LMS_SETUP)))
.getOrThrow();
}
private Result<LmsSetup> save(final LmsSetup lmsSetup, final PrivilegeType privilegeType) {
final ActivityType activityType = (lmsSetup.id == null)
? ActivityType.CREATE
: ActivityType.MODIFY;
return this.authorizationGrantService
.checkGrantOnEntity(lmsSetup, privilegeType)
.flatMap(this.lmsSetupDAO::save)
.flatMap(exam -> this.userActivityLogDAO.log(activityType, exam));
}
private void checkReadPrivilege(final Long institutionId) {
this.authorizationGrantService.checkPrivilege(
EntityType.LMS_SETUP,
PrivilegeType.READ_ONLY,
institutionId);
}
}

View file

@ -9,6 +9,8 @@
package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.WebDataBinder;
@ -28,6 +30,7 @@ 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.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
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.bulkaction.BulkActionService;
@ -41,8 +44,6 @@ import ch.ethz.seb.sebserver.webservice.weblayer.oauth.RevokeTokenEndpoint;
public class UserAccountController extends ActivatableEntityController<UserInfo, UserMod> {
private final UserDAO userDao;
private final AuthorizationGrantService authorizationGrantService;
private final PaginationService paginationService;
private final ApplicationEventPublisher applicationEventPublisher;
public UserAccountController(
@ -55,8 +56,6 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
super(authorizationGrantService, bulkActionService, userDao, userActivityLogDAO, paginationService);
this.userDao = userDao;
this.authorizationGrantService = authorizationGrantService;
this.paginationService = paginationService;
this.applicationEventPublisher = applicationEventPublisher;
}
@ -137,17 +136,21 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
PrivilegeType.READ_ONLY)) {
return this.userDao
.all(userFilter)
.allMatching(userFilter)
.getOrThrow();
} else {
return this.userDao.all(
userFilter,
this.authorizationGrantService.getGrantFilter(
EntityType.USER,
PrivilegeType.READ_ONLY))
.getOrThrow();
final Predicate<GrantEntity> grantFilter = this.authorizationGrantService.getGrantFilter(
EntityType.USER,
PrivilegeType.READ_ONLY);
return this.userDao
.allMatching(userFilter)
.getOrThrow()
.stream()
.filter(grantFilter)
.collect(Collectors.toList());
}
}

View file

@ -9,10 +9,13 @@
package ch.ethz.seb.sebserver.webservice.integration.api;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -20,16 +23,22 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.json.JacksonJsonParser;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.SEBServer;
import ch.ethz.seb.sebserver.gbl.JSONMapper;
@ -99,12 +108,110 @@ public abstract class AdministrationAPIIntegrationTest {
return obtainAccessToken("examAdmin1", "admin");
}
// protected static class TestHelper {
//
// private Supplier<String> accessTokenSuplier;
// private String query;
// private String endpoint;
// private Object
// }
protected class RestAPITestHelper {
private String path = "";
private final Map<String, String> queryAttrs = new HashMap<>();
private String accessToken;
private HttpStatus expectedStatus;
private HttpMethod httpMethod = HttpMethod.GET;
public RestAPITestHelper withAccessToken(final String accessToken) {
this.accessToken = accessToken;
return this;
}
public RestAPITestHelper withPath(final String path) {
this.path = this.path + path;
return this;
}
public RestAPITestHelper withAttribute(final String name, final String value) {
this.queryAttrs.put(name, value);
return this;
}
public RestAPITestHelper withExpectedStatus(final HttpStatus expectedStatus) {
this.expectedStatus = expectedStatus;
return this;
}
public RestAPITestHelper withMethod(final HttpMethod httpMethod) {
this.httpMethod = httpMethod;
return this;
}
public String getAsString() throws Exception {
final ResultActions action = AdministrationAPIIntegrationTest.this.mockMvc
.perform(requestBuilder());
if (this.expectedStatus != null) {
action.andExpect(status().is(this.expectedStatus.value()));
}
return action
.andReturn()
.getResponse()
.getContentAsString();
}
public <T> T getAsObject(final TypeReference<T> ref) throws Exception {
final ResultActions action = AdministrationAPIIntegrationTest.this.mockMvc
.perform(requestBuilder());
if (this.expectedStatus != null) {
action.andExpect(status().is(this.expectedStatus.value()));
}
return AdministrationAPIIntegrationTest.this.jsonMapper.readValue(
action
.andReturn()
.getResponse()
.getContentAsString(),
ref);
}
private RequestBuilder requestBuilder() {
MockHttpServletRequestBuilder builder = get(getFullPath());
switch (this.httpMethod) {
case GET:
builder = get(getFullPath());
break;
case POST:
builder = post(getFullPath());
break;
case PUT:
builder = put(getFullPath());
break;
case DELETE:
builder = delete(getFullPath());
break;
case PATCH:
builder = patch(getFullPath());
break;
default:
get(getFullPath());
break;
}
return builder.header("Authorization", "Bearer " + this.accessToken);
}
private String getFullPath() {
final StringBuilder sb = new StringBuilder();
sb.append(AdministrationAPIIntegrationTest.this.endpoint);
sb.append(this.path);
if (!this.queryAttrs.isEmpty()) {
sb.append("?");
this.queryAttrs.entrySet()
.stream()
.reduce(
sb,
(buffer, entry) -> buffer.append(entry.getKey()).append("=").append(entry.getValue())
.append("&"),
(sb1, sb2) -> sb1.append(sb2));
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
}

View file

@ -24,6 +24,7 @@ import java.util.stream.Stream;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.jdbc.Sql;
@ -32,6 +33,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.APIMessage;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityKeyAndName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
@ -46,11 +48,11 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
@Test
public void getMyUserInfo() throws Exception {
String sebAdminAccessToken = getSebAdminAccess();
String contentAsString = this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/me")
.header("Authorization", "Bearer " + sebAdminAccessToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
String contentAsString = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT + "/me")
.withExpectedStatus(HttpStatus.OK)
.getAsString();
assertEquals(
"{\"uuid\":\"user1\","
@ -64,11 +66,11 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
+ "\"userRoles\":[\"SEB_SERVER_ADMIN\"]}",
contentAsString);
sebAdminAccessToken = getAdminInstitution1Access();
contentAsString = this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/me")
.header("Authorization", "Bearer " + sebAdminAccessToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
contentAsString = new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT + "/me")
.withExpectedStatus(HttpStatus.OK)
.getAsString();
assertEquals(
"{\"uuid\":\"user2\","
@ -119,22 +121,20 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
@Test
public void institutionalAdminNotAllowedToSeeUsersOfOtherInstitution() throws Exception {
final String token = getAdminInstitution1Access();
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2")
.header("Authorization", "Bearer " + token))
.andExpect(status().isForbidden())
.andReturn().getResponse().getContentAsString();
new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2")
.withExpectedStatus(HttpStatus.FORBIDDEN)
.getAsString();
}
@Test
public void getAllUserInfoNoFilter() throws Exception {
String token = getSebAdminAccess();
List<UserInfo> userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<List<UserInfo>>() {
List<UserInfo> userInfos = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<List<UserInfo>>() {
});
// expecting all users for a SEBAdmin except inactive.
@ -144,13 +144,12 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
assertNotNull(getUserInfo("inst1Admin", userInfos));
assertNotNull(getUserInfo("examSupporter", userInfos));
token = getAdminInstitution2Access();
userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<List<UserInfo>>() {
userInfos = new RestAPITestHelper()
.withAccessToken(getAdminInstitution2Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withAttribute("institution", "2")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<List<UserInfo>>() {
});
// expecting all users of institution 2 also inactive when active flag is not set
@ -162,13 +161,13 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
assertNotNull(getUserInfo("user1", userInfos));
//.. and without inactive, if active flag is set to true
token = getAdminInstitution2Access();
userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2&active=true")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<List<UserInfo>>() {
userInfos = new RestAPITestHelper()
.withAccessToken(getAdminInstitution2Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withAttribute("institution", "2")
.withAttribute("active", "true")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<List<UserInfo>>() {
});
assertNotNull(userInfos);
@ -178,13 +177,13 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
assertNotNull(getUserInfo("user1", userInfos));
//.. and only inactive, if active flag is set to false
token = getAdminInstitution2Access();
userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2&active=false")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<List<UserInfo>>() {
userInfos = new RestAPITestHelper()
.withAccessToken(getAdminInstitution2Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withAttribute("institution", "2")
.withAttribute("active", "false")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<List<UserInfo>>() {
});
assertNotNull(userInfos);
@ -887,6 +886,152 @@ public class UserAPITest extends AdministrationAPIIntegrationTest {
assertEquals("user6", userLog.entityId);
}
@Test
public void testGeneralAllActiveInactiveEndpoint() throws Exception {
final String sebAdminToken = getSebAdminAccess();
// all active for the own institution
Page<UserInfo> usersPage = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/active")
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserInfo>>() {
});
assertNotNull(usersPage);
assertTrue(usersPage.pageSize == 3);
assertEquals("[user1, user2, user5]", getOrderedUUIDs(usersPage.content));
// all inactive of the own institution
usersPage = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/inactive")
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserInfo>>() {
});
assertNotNull(usersPage);
assertTrue(usersPage.pageSize == 0);
assertEquals("[]", getOrderedUUIDs(usersPage.content));
// all active of institution 2
usersPage = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/active?institution=2")
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserInfo>>() {
});
assertNotNull(usersPage);
assertTrue(usersPage.pageSize == 3);
assertEquals("[user3, user4, user7]", getOrderedUUIDs(usersPage.content));
// all inactive of institution 2
usersPage = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/inactive?institution=2")
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserInfo>>() {
});
assertNotNull(usersPage);
assertTrue(usersPage.pageSize == 1);
assertEquals("[user6]", getOrderedUUIDs(usersPage.content));
}
@Test
public void testGeneralInEndpoint() throws Exception {
final String sebAdminToken = getSebAdminAccess();
// for SEB Admin it should be possible to get from different institutions
Collection<UserInfo> users = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/in?ids=user1,user2,user6,user7")
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<UserInfo>>() {
});
assertNotNull(users);
assertTrue(users.size() == 4);
assertEquals("[user1, user2, user6, user7]", getOrderedUUIDs(users));
// for an institutional admin it should only be possible to get from own institution
final String instAdminToken = getAdminInstitution2Access();
users = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/in?ids=user1,user2,user6,user7")
.header("Authorization", "Bearer " + instAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<UserInfo>>() {
});
assertNotNull(users);
assertTrue(users.size() == 2);
assertEquals("[user6, user7]", getOrderedUUIDs(users));
}
@Test
public void testGeneralNamesEndpoint() throws Exception {
final String sebAdminToken = getSebAdminAccess();
// for SEB Admin
Collection<EntityKeyAndName> names = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/names")
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<EntityKeyAndName>>() {
});
assertNotNull(names);
assertTrue(names.size() == 3);
assertEquals("[EntityIdAndName [entityType=USER, id=user1, name=SEBAdmin], "
+ "EntityIdAndName [entityType=USER, id=user2, name=Institutional1 Admin], "
+ "EntityIdAndName [entityType=USER, id=user5, name=Exam Supporter]]", names.toString());
// for an institutional admin 2
final String instAdminToken = getAdminInstitution2Access();
names = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/names")
.header("Authorization", "Bearer " + instAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<EntityKeyAndName>>() {
});
assertNotNull(names);
assertTrue(names.size() == 4);
assertEquals("[EntityIdAndName [entityType=USER, id=user3, name=Institutional2 Admin], "
+ "EntityIdAndName [entityType=USER, id=user4, name=ExamAdmin1], "
+ "EntityIdAndName [entityType=USER, id=user6, name=Deactivated], "
+ "EntityIdAndName [entityType=USER, id=user7, name=User]]", names.toString());
// for an institutional admin 2 only active
names = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/names?active=true")
.header("Authorization", "Bearer " + instAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<EntityKeyAndName>>() {
});
assertNotNull(names);
assertTrue(names.size() == 3);
assertEquals("[EntityIdAndName [entityType=USER, id=user3, name=Institutional2 Admin], "
+ "EntityIdAndName [entityType=USER, id=user4, name=ExamAdmin1], "
+ "EntityIdAndName [entityType=USER, id=user7, name=User]]", names.toString());
}
private UserInfo getUserInfo(final String name, final Collection<UserInfo> infos) {
try {
return infos