adjust API and tests and bugfix

This commit is contained in:
anhefti 2019-01-26 17:52:05 +01:00
parent f5d461157e
commit 8e9cf8741d
29 changed files with 940 additions and 785 deletions

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gbl;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.apache.commons.lang3.BooleanUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public class POSTMapper {
protected final MultiValueMap<String, String> params;
public POSTMapper(final MultiValueMap<String, String> params) {
super();
this.params = params;
}
public String getString(final String name) {
return this.params.getFirst(name);
}
public Long getLong(final String name) {
final String value = this.params.getFirst(name);
if (value == null) {
return null;
}
return Long.parseLong(value);
}
public Integer getInteger(final String name) {
final String value = this.params.getFirst(name);
if (value == null) {
return null;
}
return Integer.parseInt(value);
}
public Locale getLocale(final String name) {
final String value = this.params.getFirst(name);
if (value == null) {
return null;
}
return Locale.forLanguageTag(value);
}
public boolean getBoolean(final String name) {
return BooleanUtils.toBoolean(this.params.getFirst(name));
}
public Boolean getBooleanObject(final String name) {
return BooleanUtils.toBooleanObject(this.params.getFirst(name));
}
public Integer getBooleanAsInteger(final String name) {
final Boolean booleanObject = getBooleanObject(name);
if (booleanObject == null) {
return null;
}
return BooleanUtils.toIntegerObject(booleanObject);
}
public DateTimeZone getDateTimeZone(final String name) {
final String value = this.params.getFirst(name);
if (value == null) {
return null;
}
try {
return DateTimeZone.forID(value);
} catch (final Exception e) {
return null;
}
}
public Set<String> getStringSet(final String name) {
final List<String> list = this.params.get(name);
if (list == null) {
return Collections.emptySet();
}
return Utils.immutableSetOf(list);
}
public <T extends Enum<T>> T getEnum(final String name, final Class<T> type) {
final String value = this.params.getFirst(name);
if (value == null) {
return null;
}
try {
return Enum.valueOf(type, value);
} catch (final Exception e) {
return null;
}
}
public DateTime getDateTime(final String name) {
final String value = this.params.getFirst(name);
if (value == null) {
return null;
}
return Utils.toDateTime(value);
}
}

View file

@ -12,7 +12,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
public interface Entity extends ModelIdAware {
public static final String FILTER_ATTR_INSTITUTION = "institution";
public static final String FILTER_ATTR_INSTITUTION = Domain.ATTR_INSTITUTION_ID;
public static final String FILTER_ATTR_ACTIVE = "active";
public static final String FILTER_ATTR_NAME = "name";

View file

@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Activatable;
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
@ -133,6 +134,24 @@ public final class Exam implements GrantEntity, Activatable {
: Collections.emptyList();
}
public Exam(final String modelId, final QuizData quizData, final POSTMapper mapper) {
this.id = (modelId != null) ? Long.parseLong(modelId) : null;
this.institutionId = mapper.getLong(EXAM.ATTR_INSTITUTION_ID);
this.lmsSetupId = mapper.getLong(EXAM.ATTR_LMS_SETUP_ID);
this.externalId = mapper.getString(EXAM.ATTR_EXTERNAL_ID);
this.name = quizData.name;
this.description = quizData.description;
this.status = mapper.getEnum(EXAM.ATTR_STATUS, ExamStatus.class);
this.startTime = quizData.startTime;
this.endTime = quizData.endTime;
this.startURL = mapper.getString(EXAM.ATTR_INSTITUTION_ID);
this.type = mapper.getEnum(EXAM.ATTR_TYPE, ExamType.class);
this.owner = mapper.getString(EXAM.ATTR_OWNER);
this.active = mapper.getBooleanObject(EXAM.ATTR_ACTIVE);
this.supporter = mapper.getStringSet(EXAM.ATTR_SUPPORTER);
}
@Override
public EntityType entityType() {
return EntityType.EXAM;

View file

@ -13,6 +13,7 @@ import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Activatable;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Domain.INSTITUTION;
@ -53,6 +54,14 @@ public final class Institution implements GrantEntity, Activatable {
this.active = active;
}
public Institution(final String modelId, final POSTMapper mapper) {
this.id = (modelId != null) ? Long.parseLong(modelId) : null;
this.name = mapper.getString(INSTITUTION.ATTR_NAME);
this.urlSuffix = mapper.getString(INSTITUTION.ATTR_URL_SUFFIX);
this.logoImage = mapper.getString(INSTITUTION.ATTR_LOGO_IMAGE);
this.active = mapper.getBooleanObject(INSTITUTION.ATTR_ACTIVE);
}
@Override
public EntityType entityType() {
return EntityType.INSTITUTION;

View file

@ -15,6 +15,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Activatable;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Domain.INSTITUTION;
@ -103,6 +104,20 @@ public final class LmsSetup implements GrantEntity, Activatable {
this.active = (active != null) ? active : Boolean.FALSE;
}
public LmsSetup(final String modelId, final POSTMapper mapper) {
this.id = (modelId != null) ? Long.parseLong(modelId) : null;
this.institutionId = mapper.getLong(LMS_SETUP.ATTR_INSTITUTION_ID);
this.name = mapper.getString(LMS_SETUP.ATTR_NAME);
this.lmsType = mapper.getEnum(LMS_SETUP.ATTR_LMS_TYPE, LmsType.class);
this.lmsAuthName = mapper.getString(LMS_SETUP.ATTR_LMS_CLIENTNAME);
this.lmsAuthSecret = mapper.getString(LMS_SETUP.ATTR_LMS_CLIENTSECRET);
this.lmsApiUrl = mapper.getString(LMS_SETUP.ATTR_LMS_URL);
this.lmsRestApiToken = mapper.getString(LMS_SETUP.ATTR_LMS_REST_API_TOKEN);
this.sebAuthName = mapper.getString(LMS_SETUP.ATTR_SEB_CLIENTNAME);
this.sebAuthSecret = mapper.getString(LMS_SETUP.ATTR_SEB_CLIENTSECRET);
this.active = mapper.getBooleanObject(LMS_SETUP.ATTR_ACTIVE);
}
@Override
public EntityType entityType() {
return EntityType.LMS_SETUP;

View file

@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Domain.USER;
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
@ -46,6 +47,7 @@ public final class UserMod implements GrantEntity {
public final String name;
/** The internal user name */
@NotNull
@Size(min = 3, max = 255, message = "user:username:size:{min}:{max}:${validatedValue}")
@JsonProperty(USER.ATTR_USERNAME)
public final String username;
@ -56,10 +58,12 @@ public final class UserMod implements GrantEntity {
public final String email;
/** The users locale */
@NotNull
@JsonProperty(USER.ATTR_LOCALE)
public final Locale locale;
/** The users time zone */
@NotNull
@JsonProperty(USER.ATTR_TIMEZONE)
public final DateTimeZone timeZone;
@ -116,6 +120,19 @@ public final class UserMod implements GrantEntity {
this.roles = userInfo.roles;
}
public UserMod(final String modelId, final POSTMapper postAttrMapper) {
this.uuid = modelId;
this.institutionId = postAttrMapper.getLong(USER.ATTR_INSTITUTION_ID);
this.newPassword = postAttrMapper.getString(ATTR_NAME_NEW_PASSWORD);
this.retypedNewPassword = postAttrMapper.getString(ATTR_NAME_RETYPED_NEW_PASSWORD);
this.name = postAttrMapper.getString(USER.ATTR_NAME);
this.username = postAttrMapper.getString(USER.ATTR_USERNAME);
this.email = postAttrMapper.getString(USER.ATTR_EMAIL);
this.locale = postAttrMapper.getLocale(USER.ATTR_LOCALE);
this.timeZone = postAttrMapper.getDateTimeZone(USER.ATTR_TIMEZONE);
this.roles = postAttrMapper.getStringSet(USER_ROLE.REFERENCE_NAME);
}
@Override
public String getModelId() {
return this.uuid;

View file

@ -119,7 +119,11 @@ public final class Result<T> {
public <U> Result<U> map(final Function<? super T, ? extends U> mapf) {
if (this.error == null) {
try {
return Result.of(mapf.apply(this.value));
final U result = mapf.apply(this.value);
if (result instanceof Result) {
throw new IllegalArgumentException("Use flatMap instead!");
}
return Result.of(result);
} catch (final Throwable t) {
return Result.ofError(t);
}

View file

@ -22,6 +22,9 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import ch.ethz.seb.sebserver.gbl.Constants;
public final class Utils {
@ -139,4 +142,17 @@ public final class Utils {
return toDateTime(dateString).getMillis();
}
public static String toJsonArray(final String string) {
if (string == null) {
return null;
}
final List<String> asList = Arrays.asList(StringUtils.split(string, Constants.LIST_SEPARATOR_CHAR));
try {
return new ObjectMapper().writeValueAsString(asList);
} catch (final JsonProcessingException e) {
return string;
}
}
}

View file

@ -79,15 +79,15 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
});
}
Result<T> createNew(M data);
/** Use this to save/modify an entity.
* If the model identifier from given modified entity data is null or not exists already, a new entity is created.
* If the model identifier is available and matches an existing entity, all entity data that are
* not null on modified entity data instance are updated within the existing entity.
*
* @param modified modified data instance containing all data that should be modified
* @param modelId the model id of the entity to save
* @param data entity instance containing all data that should be saved
* @return A Result of the entity instance where the successfully saved/modified entity data is available or a
* reported exception on error case */
Result<T> save(M modified);
Result<T> save(String modelId, M data);
/** Use this to delete a set Entity by a Collection of EntityKey
*

View file

@ -8,27 +8,20 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.LocaleUtils;
import org.joda.time.DateTime;
import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.JodaTimeTypeResolver;
public class FilterMap {
public class FilterMap extends POSTMapper {
public final Map<String, String> params;
public FilterMap(final Map<String, String> params) {
super();
this.params = Utils.immutableMapOf(params);
public FilterMap(final MultiValueMap<String, String> params) {
super(params);
}
public Integer getActiveAsInt() {
@ -95,55 +88,8 @@ public class FilterMap {
return getSQLWildcard(Indicator.FILTER_ATTR_NAME);
}
public String getString(final String name) {
return this.params.get(name);
}
public String getSQLWildcard(final String name) {
return toSQLWildcard(this.params.get(name));
}
public Long getLong(final String name) {
final String value = this.params.get(name);
if (value == null) {
return null;
}
return Long.parseLong(value);
}
public Integer getInteger(final String name) {
final String value = this.params.get(name);
if (value == null) {
return null;
}
return Integer.parseInt(value);
}
public Locale getLocale(final String name) {
final String value = this.params.get(name);
if (value == null) {
return null;
}
return LocaleUtils.toLocale(name);
}
public boolean getBoolean(final String name) {
return BooleanUtils.toBoolean(this.params.get(name));
}
public Boolean getBooleanObject(final String name) {
return BooleanUtils.toBooleanObject(this.params.get(name));
}
public Integer getBooleanAsInteger(final String name) {
final Boolean booleanObject = getBooleanObject(name);
if (booleanObject == null) {
return null;
}
return BooleanUtils.toIntegerObject(booleanObject);
return toSQLWildcard(this.params.getFirst(name));
}
public static String toSQLWildcard(final String text) {

View file

@ -14,4 +14,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSuppor
public interface InstitutionDAO
extends ActivatableEntityDAO<Institution, Institution>, BulkActionSupportDAO<Institution> {
boolean exists(String name);
}

View file

@ -157,18 +157,58 @@ public class ExamDAOImpl implements ExamDAO {
@Override
@Transactional
public Result<Exam> save(final Exam exam) {
if (exam == null) {
return Result.ofError(new NullPointerException("exam has null-reference"));
}
public Result<Exam> save(final String modelId, final Exam exam) {
return Result.tryCatch(() -> {
final ExamRecord examRecord = new ExamRecord(
exam.id,
null, null, null, null,
(exam.supporter != null)
? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR)
: null,
(exam.type != null) ? exam.type.name() : null,
(exam.status != null) ? exam.status.name() : null,
BooleanUtils.toIntegerObject(exam.active));
return (exam.id == null)
? insert(exam)
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback)
: update(exam)
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
this.examRecordMapper.updateByPrimaryKeySelective(examRecord);
return this.examRecordMapper.selectByPrimaryKey(exam.id);
})
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@Transactional
public Result<Exam> createNew(final Exam exam) {
return Result.tryCatch(() -> {
// fist check if it is not already existing
final List<ExamRecord> records = this.examRecordMapper.selectByExample()
.where(ExamRecordDynamicSqlSupport.lmsSetupId, isEqualTo(exam.lmsSetupId))
.and(ExamRecordDynamicSqlSupport.externalId, isEqualTo(exam.externalId))
.build()
.execute();
// if there is already an existing imported exam for the quiz, this is returned
if (records != null && records.size() > 0) {
return records.get(0);
}
final ExamRecord examRecord = new ExamRecord(
null,
exam.institutionId,
exam.lmsSetupId,
exam.externalId,
this.userService.getCurrentUser().uuid(),
null,
null,
null,
BooleanUtils.toInteger(false));
this.examRecordMapper.updateByPrimaryKeySelective(examRecord);
return this.examRecordMapper.selectByPrimaryKey(exam.id);
})
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@ -237,54 +277,6 @@ public class ExamDAOImpl implements ExamDAO {
}).flatMap(this::toDomainModel);
}
private Result<ExamRecord> insert(final Exam exam) {
return Result.tryCatch(() -> {
// fist check if it is not already existing
final List<ExamRecord> records = this.examRecordMapper.selectByExample()
.where(ExamRecordDynamicSqlSupport.lmsSetupId, isEqualTo(exam.lmsSetupId))
.and(ExamRecordDynamicSqlSupport.externalId, isEqualTo(exam.externalId))
.build()
.execute();
// if there is already an existing imported exam for the quiz, this is returned
if (records != null && records.size() > 0) {
return records.get(0);
}
final ExamRecord examRecord = new ExamRecord(
null,
exam.institutionId,
exam.lmsSetupId,
exam.externalId,
this.userService.getCurrentUser().uuid(),
null,
null,
null,
BooleanUtils.toInteger(false));
this.examRecordMapper.updateByPrimaryKeySelective(examRecord);
return this.examRecordMapper.selectByPrimaryKey(exam.id);
});
}
private Result<ExamRecord> update(final Exam exam) {
return Result.tryCatch(() -> {
final ExamRecord examRecord = new ExamRecord(
exam.id,
null, null, null, null,
(exam.supporter != null)
? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR)
: null,
(exam.type != null) ? exam.type.name() : null,
(exam.status != null) ? exam.status.name() : null,
BooleanUtils.toIntegerObject(exam.active));
this.examRecordMapper.updateByPrimaryKeySelective(examRecord);
return this.examRecordMapper.selectByPrimaryKey(exam.id);
});
}
private Result<Collection<EntityKey>> allIdsOfInstitution(final EntityKey institutionKey) {
return Result.tryCatch(() -> {
return this.examRecordMapper.selectIdsByExample()

View file

@ -143,18 +143,56 @@ public class IndicatorDAOImpl implements IndicatorDAO {
@Override
@Transactional
public Result<Indicator> save(final Indicator modified) {
if (modified == null) {
return Result.ofError(new NullPointerException("Indicator has null-reference"));
}
public Result<Indicator> save(final String modelId, final Indicator modified) {
return Result.tryCatch(() -> {
return (modified.id != null)
? update(modified)
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback)
: createNew(modified)
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
final IndicatorRecord newRecord = new IndicatorRecord(
modified.id,
null,
modified.type.name(),
modified.name,
modified.defaultColor);
this.indicatorRecordMapper.updateByPrimaryKeySelective(newRecord);
// update also the thresholds
this.thresholdRecordMapper.deleteByExample()
.where(ThresholdRecordDynamicSqlSupport.indicatorId, isEqualTo(modified.id))
.build()
.execute();
modified.thresholds
.stream()
.map(threshold -> new ThresholdRecord(
null,
modified.id,
new BigDecimal(threshold.value),
threshold.color))
.forEach(this.thresholdRecordMapper::insert);
return this.indicatorRecordMapper.selectByPrimaryKey(modified.id);
})
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@Transactional
public Result<Indicator> createNew(final Indicator modified) {
return Result.tryCatch(() -> {
final IndicatorRecord newRecord = new IndicatorRecord(
null,
modified.examId,
modified.type.name(),
modified.name,
modified.defaultColor);
this.indicatorRecordMapper.insert(newRecord);
return newRecord;
})
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@ -263,50 +301,4 @@ public class IndicatorDAOImpl implements IndicatorDAO {
}
private Result<IndicatorRecord> createNew(final Indicator indicator) {
return Result.tryCatch(() -> {
final IndicatorRecord newRecord = new IndicatorRecord(
null,
indicator.examId,
indicator.type.name(),
indicator.name,
indicator.defaultColor);
this.indicatorRecordMapper.insert(newRecord);
return newRecord;
});
}
private Result<IndicatorRecord> update(final Indicator indicator) {
return Result.tryCatch(() -> {
final IndicatorRecord newRecord = new IndicatorRecord(
indicator.id,
null,
indicator.type.name(),
indicator.name,
indicator.defaultColor);
this.indicatorRecordMapper.updateByPrimaryKeySelective(newRecord);
// update also the thresholds
this.thresholdRecordMapper.deleteByExample()
.where(ThresholdRecordDynamicSqlSupport.indicatorId, isEqualTo(indicator.id))
.build()
.execute();
indicator.thresholds
.stream()
.map(threshold -> new ThresholdRecord(
null,
indicator.id,
new BigDecimal(threshold.value),
threshold.color))
.forEach(this.thresholdRecordMapper::insert);
return this.indicatorRecordMapper.selectByPrimaryKey(indicator.id);
});
}
}

View file

@ -8,8 +8,7 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent;
import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import java.util.Collection;
import java.util.Collections;
@ -19,6 +18,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
@ -55,6 +55,21 @@ public class InstitutionDAOImpl implements InstitutionDAO {
return EntityType.INSTITUTION;
}
@Override
@Transactional(readOnly = true)
public boolean exists(final String name) {
if (StringUtils.isBlank(name)) {
return false;
}
final Long count = this.institutionRecordMapper.countByExample()
.where(InstitutionRecordDynamicSqlSupport.name, isEqualTo(name))
.build()
.execute();
return count != null && count.longValue() > 0;
}
@Override
@Transactional(readOnly = true)
public Result<Institution> byPK(final Long id) {
@ -113,18 +128,39 @@ public class InstitutionDAOImpl implements InstitutionDAO {
@Override
@Transactional
public Result<Institution> save(final Institution institution) {
if (institution == null) {
return Result.ofError(new NullPointerException("institution has null-reference"));
}
public Result<Institution> save(final String modelId, final Institution institution) {
return Result.tryCatch(() -> {
return (institution.id != null)
? update(institution)
.flatMap(InstitutionDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback)
: createNew(institution)
.flatMap(InstitutionDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
final InstitutionRecord newRecord = new InstitutionRecord(
institution.id,
institution.name,
institution.urlSuffix,
null,
institution.logoImage);
this.institutionRecordMapper.updateByPrimaryKeySelective(newRecord);
return this.institutionRecordMapper.selectByPrimaryKey(institution.id);
})
.flatMap(InstitutionDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@Transactional
public Result<Institution> createNew(final Institution institution) {
return Result.tryCatch(() -> {
final InstitutionRecord newRecord = new InstitutionRecord(
null,
institution.name,
institution.urlSuffix,
BooleanUtils.toInteger(false),
institution.logoImage);
this.institutionRecordMapper.insert(newRecord);
return newRecord;
})
.flatMap(InstitutionDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@ -201,35 +237,6 @@ public class InstitutionDAOImpl implements InstitutionDAO {
});
}
private Result<InstitutionRecord> createNew(final Institution institution) {
return Result.tryCatch(() -> {
final InstitutionRecord newRecord = new InstitutionRecord(
null,
institution.name,
institution.urlSuffix,
BooleanUtils.toInteger(false),
institution.logoImage);
this.institutionRecordMapper.insert(newRecord);
return newRecord;
});
}
private Result<InstitutionRecord> update(final Institution institution) {
return Result.tryCatch(() -> {
final InstitutionRecord newRecord = new InstitutionRecord(
institution.id,
institution.name,
institution.urlSuffix,
null,
institution.logoImage);
this.institutionRecordMapper.updateByPrimaryKeySelective(newRecord);
return this.institutionRecordMapper.selectByPrimaryKey(institution.id);
});
}
private static Result<Institution> toDomainModel(final InstitutionRecord record) {
return Result.tryCatch(() -> new Institution(
record.getId(),

View file

@ -121,18 +121,52 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
@Override
@Transactional
public Result<LmsSetup> save(final LmsSetup lmsSetup) {
if (lmsSetup == null) {
return Result.ofError(new NullPointerException("lmsSetup has null-reference"));
}
public Result<LmsSetup> save(final String modelId, final LmsSetup lmsSetup) {
return Result.tryCatch(() -> {
return (lmsSetup.id != null)
? update(lmsSetup)
.flatMap(LmsSetupDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback)
: createNew(lmsSetup)
.flatMap(LmsSetupDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
final LmsSetupRecord newRecord = new LmsSetupRecord(
lmsSetup.id,
lmsSetup.institutionId,
lmsSetup.name,
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
lmsSetup.lmsApiUrl,
lmsSetup.lmsAuthName,
lmsSetup.lmsAuthSecret,
lmsSetup.lmsRestApiToken,
lmsSetup.sebAuthName,
lmsSetup.sebAuthSecret,
null);
this.lmsSetupRecordMapper.updateByPrimaryKeySelective(newRecord);
return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id);
})
.flatMap(LmsSetupDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@Transactional
public Result<LmsSetup> createNew(final LmsSetup lmsSetup) {
return Result.tryCatch(() -> {
final LmsSetupRecord newRecord = new LmsSetupRecord(
null,
lmsSetup.institutionId,
lmsSetup.name,
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
lmsSetup.lmsApiUrl,
lmsSetup.lmsAuthName,
lmsSetup.lmsAuthSecret,
lmsSetup.lmsRestApiToken,
lmsSetup.sebAuthName,
lmsSetup.sebAuthSecret,
BooleanUtils.toInteger(false));
this.lmsSetupRecordMapper.insert(newRecord);
return newRecord;
})
.flatMap(LmsSetupDAOImpl::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@ -242,46 +276,4 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
BooleanUtils.toBooleanObject(record.getActive())));
}
private Result<LmsSetupRecord> createNew(final LmsSetup lmsSetup) {
return Result.tryCatch(() -> {
final LmsSetupRecord newRecord = new LmsSetupRecord(
null,
lmsSetup.institutionId,
lmsSetup.name,
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
lmsSetup.lmsApiUrl,
lmsSetup.lmsAuthName,
lmsSetup.lmsAuthSecret,
lmsSetup.lmsRestApiToken,
lmsSetup.sebAuthName,
lmsSetup.sebAuthSecret,
BooleanUtils.toInteger(false));
this.lmsSetupRecordMapper.insert(newRecord);
return newRecord;
});
}
private Result<LmsSetupRecord> update(final LmsSetup lmsSetup) {
return Result.tryCatch(() -> {
final LmsSetupRecord newRecord = new LmsSetupRecord(
lmsSetup.id,
lmsSetup.institutionId,
lmsSetup.name,
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
lmsSetup.lmsApiUrl,
lmsSetup.lmsAuthName,
lmsSetup.lmsAuthSecret,
lmsSetup.lmsRestApiToken,
lmsSetup.sebAuthName,
lmsSetup.sebAuthSecret,
null);
this.lmsSetupRecordMapper.updateByPrimaryKeySelective(newRecord);
return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id);
});
}
}

View file

@ -317,14 +317,20 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
@Transactional(readOnly = true)
public Result<Collection<UserActivityLog>> loadEntities(final Collection<EntityKey> keys) {
// TODO Auto-generated method stub
return null;
return Result.ofTODO();
}
@Override
@Transactional
public Result<UserActivityLog> save(final UserActivityLog modified) {
public Result<UserActivityLog> save(final String modelId, final UserActivityLog modified) {
// TODO Auto-generated method stub
return null;
return Result.ofTODO();
}
@Override
public Result<UserActivityLog> createNew(final UserActivityLog data) {
// TODO Auto-generated method stub
return Result.ofTODO();
}
@Override

View file

@ -176,18 +176,65 @@ public class UserDaoImpl implements UserDAO {
@Override
@Transactional
public Result<UserInfo> save(final UserMod userMod) {
if (userMod == null) {
return Result.ofError(new NullPointerException("userMod has null-reference"));
}
public Result<UserInfo> createNew(final UserMod userMod) {
return Result.tryCatch(() -> {
return (userMod.uuid != null)
? updateUser(userMod)
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback)
: createNewUser(userMod)
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
if (!userMod.newPasswordMatch()) {
throw new APIMessageException(ErrorMessage.PASSWORD_MISSMATCH);
}
final UserRecord recordToSave = new UserRecord(
null,
userMod.institutionId,
UUID.randomUUID().toString(),
userMod.name,
userMod.username,
this.userPasswordEncoder.encode(userMod.getNewPassword()),
userMod.email,
userMod.locale.toLanguageTag(),
userMod.timeZone.getID(),
BooleanUtils.toInteger(false));
this.userRecordMapper.insert(recordToSave);
final Long newUserPK = recordToSave.getId();
final UserRecord newRecord = this.userRecordMapper
.selectByPrimaryKey(newUserPK);
insertRolesForUser(newUserPK, userMod.roles);
return newRecord;
})
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@Transactional
public Result<UserInfo> save(final String modelId, final UserMod userMod) {
return recordByUUID(modelId)
.map(record -> {
final boolean changePWD = userMod.passwordChangeRequest();
if (changePWD && !userMod.newPasswordMatch()) {
throw new APIMessageException(ErrorMessage.PASSWORD_MISSMATCH);
}
final UserRecord newRecord = new UserRecord(
record.getId(),
null,
null,
userMod.name,
userMod.username,
(changePWD) ? this.userPasswordEncoder.encode(userMod.getNewPassword()) : null,
userMod.email,
userMod.locale.toLanguageTag(),
userMod.timeZone.getID(),
null);
this.userRecordMapper.updateByPrimaryKeySelective(newRecord);
updateRolesForUser(record.getId(), userMod.roles);
return this.userRecordMapper.selectByPrimaryKey(record.getId());
})
.flatMap(this::toDomainModel)
.onErrorDo(TransactionHandler::rollback);
}
@Override
@ -302,59 +349,6 @@ public class UserDaoImpl implements UserDAO {
});
}
private Result<UserRecord> updateUser(final UserMod userMod) {
return recordByUUID(userMod.uuid)
.map(record -> {
final boolean changePWD = userMod.passwordChangeRequest();
if (changePWD && !userMod.newPasswordMatch()) {
throw new APIMessageException(ErrorMessage.PASSWORD_MISSMATCH);
}
final UserRecord newRecord = new UserRecord(
record.getId(),
null,
null,
userMod.name,
userMod.username,
(changePWD) ? this.userPasswordEncoder.encode(userMod.getNewPassword()) : null,
userMod.email,
userMod.locale.toLanguageTag(),
userMod.timeZone.getID(),
null);
this.userRecordMapper.updateByPrimaryKeySelective(newRecord);
updateRolesForUser(record.getId(), userMod.roles);
return this.userRecordMapper.selectByPrimaryKey(record.getId());
});
}
private Result<UserRecord> createNewUser(final UserMod userMod) {
return Result.tryCatch(() -> {
if (!userMod.newPasswordMatch()) {
throw new APIMessageException(ErrorMessage.PASSWORD_MISSMATCH);
}
final UserRecord newRecord = new UserRecord(
null,
userMod.institutionId,
UUID.randomUUID().toString(),
userMod.name,
userMod.username,
this.userPasswordEncoder.encode(userMod.getNewPassword()),
userMod.email,
userMod.locale.toLanguageTag(),
userMod.timeZone.getID(),
BooleanUtils.toInteger(false));
this.userRecordMapper.insert(newRecord);
final Long newUserId = newRecord.getId();
insertRolesForUser(newUserId, userMod.roles);
return newRecord;
});
}
private void updateRolesForUser(final Long userId, @NotNull final Set<String> roles) {
// first delete old roles
this.roleRecordMapper.deleteByExample()

View file

@ -8,72 +8,31 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.validation;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.validation.DirectFieldBindingResult;
import org.springframework.validation.Validator;
import com.fasterxml.jackson.databind.ObjectReader;
import ch.ethz.seb.sebserver.gbl.JSONMapper;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
@Service
@WebServiceProfile
public class BeanValidationService {
private final Validator validator;
private final JSONMapper jsonMapper;
public BeanValidationService(
final Validator validator,
final JSONMapper jsonMapper) {
public BeanValidationService(final Validator validator) {
this.validator = validator;
this.jsonMapper = jsonMapper;
}
public <T> void validateBean(final T bean) {
public <T> Result<T> validateBean(final T bean) {
final DirectFieldBindingResult errors = new DirectFieldBindingResult(bean, "");
this.validator.validate(bean, errors);
if (errors.hasErrors()) {
throw new BeanValidationException(errors);
}
}
public <T, M> M validateNewBean(final Map<String, String> params, final Class<M> type) {
M result = null;
try {
final String stringValue = this.jsonMapper.writeValueAsString(params);
result = this.jsonMapper.readValue(stringValue, type);
} catch (final Exception e) {
throw new RuntimeException("Unexpected error: ", e);
return Result.ofError(new BeanValidationException(errors));
}
if (result != null) {
validateBean(result);
}
return result;
}
public <T, M> M validateModifiedBean(final T bean, final Map<String, String> params, final Class<M> type) {
M result = null;
try {
final String stringValue = this.jsonMapper.writeValueAsString(bean);
final String paramsString = this.jsonMapper.writeValueAsString(params);
result = this.jsonMapper.readValue(stringValue, type);
final ObjectReader updater = this.jsonMapper.readerForUpdating(result);
result = updater.readValue(paramsString);
} catch (final Exception e) {
throw new RuntimeException("Unexpected error: ", e);
}
if (result != null) {
validateBean(result);
}
return result;
return Result.of(bean);
}
}

View file

@ -1,75 +0,0 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.LocaleUtils;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public class APIParamsMap {
public final Map<String, String> params;
public APIParamsMap(final Map<String, String> params) {
super();
this.params = Utils.immutableMapOf(params);
}
public String getString(final String name) {
return this.params.get(name);
}
public Long getLong(final String name) {
final String value = this.params.get(name);
if (value == null) {
return null;
}
return Long.parseLong(value);
}
public Integer getInteger(final String name) {
final String value = this.params.get(name);
if (value == null) {
return null;
}
return Integer.parseInt(value);
}
public Locale getLocale(final String name) {
final String value = this.params.get(name);
if (value == null) {
return null;
}
return LocaleUtils.toLocale(name);
}
public boolean getBoolean(final String name) {
return BooleanUtils.toBoolean(this.params.get(name));
}
public Boolean getBooleanObject(final String name) {
return BooleanUtils.toBooleanObject(this.params.get(name));
}
public Integer getBooleanAsInteger(final String name) {
final Boolean booleanObject = getBooleanObject(this.params.get(name));
if (booleanObject == null) {
return null;
}
return BooleanUtils.toIntegerObject(booleanObject);
}
}

View file

@ -10,7 +10,6 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -19,6 +18,7 @@ import javax.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
@ -28,6 +28,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
@ -82,6 +83,10 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.addUsersInstitutionDefaultPropertySupport(binder);
}
// ******************
// * GET (all)
// ******************
@RequestMapping(
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
@ -95,11 +100,13 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
@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,
@RequestParam final Map<String, String> allRequestParams) {
@RequestParam final MultiValueMap<String, String> allRequestParams) {
checkReadPrivilege(institutionId);
final FilterMap filterMap = new FilterMap(allRequestParams);
allRequestParams.putIfAbsent(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(institutionId));
allRequestParams.putIfAbsent(
Entity.FILTER_ATTR_INSTITUTION,
Arrays.asList(String.valueOf(institutionId)));
return this.paginationService.getPage(
pageNumber,
@ -110,17 +117,27 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
() -> getAll(filterMap)).getOrThrow();
}
@RequestMapping(path = "/names", method = RequestMethod.GET)
// ******************
// * GET (names)
// ******************
@RequestMapping(
path = "/names",
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public Collection<EntityKeyAndName> getNames(
@RequestParam(
name = Entity.FILTER_ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam final Map<String, String> allRequestParams) {
@RequestParam final MultiValueMap<String, String> allRequestParams) {
checkReadPrivilege(institutionId);
final FilterMap filterMap = new FilterMap(allRequestParams);
allRequestParams.putIfAbsent(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(institutionId));
allRequestParams.putIfAbsent(
Entity.FILTER_ATTR_INSTITUTION,
Arrays.asList(String.valueOf(institutionId)));
return getAll(filterMap)
.getOrThrow()
@ -129,116 +146,34 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.collect(Collectors.toList());
}
@RequestMapping(path = "/{id}", method = RequestMethod.GET)
public T getBy(@PathVariable final String id) {
// ******************
// * GET (single)
// ******************
@RequestMapping(
path = "/{modelId}",
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public T getBy(@PathVariable final String modelId) {
return this.entityDAO
.byModelId(id)
.byModelId(modelId)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.READ_ONLY))
.getOrThrow();
}
// ******************
// * GET (list)
// ******************
@RequestMapping(
method = RequestMethod.POST,
path = "/list",
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public T create(
@RequestParam final Map<String, String> allRequestParams,
@RequestParam(
name = Entity.FILTER_ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
this.authorizationGrantService.checkHasAnyPrivilege(
EntityType.INSTITUTION,
PrivilegeType.WRITE);
allRequestParams.putIfAbsent(Domain.ATTR_INSTITUTION_ID, String.valueOf(institutionId));
final M modifyData = this.beanValidationService.validateNewBean(
allRequestParams,
modifiedDataType());
final M _modifyData = beforeSave(modifyData);
return this.checkIsNew(modifyData)
.flatMap(entity -> this.entityDAO.save(_modifyData))
.flatMap(entity -> this.userActivityLogDAO.log(ActivityType.CREATE, entity))
.flatMap(entity -> notifySave(_modifyData, entity))
.getOrThrow();
}
@RequestMapping(
method = RequestMethod.PUT,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public T savePut(@Valid @RequestBody final M modifyData) {
final M _modifyData = beforeSave(modifyData);
return this.authorizationGrantService.checkGrantOnEntity(_modifyData, PrivilegeType.MODIFY)
.flatMap(entity -> this.entityDAO.save(_modifyData))
.flatMap(entity -> this.userActivityLogDAO.log(ActivityType.MODIFY, entity))
.flatMap(entity -> notifySave(_modifyData, entity))
.getOrThrow();
}
protected M beforeSave(final M modifyData) {
return modifyData;
}
@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 Map<String, String> allRequestParams,
@RequestParam(
name = Entity.FILTER_ATTR_INSTITUTION,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
final T model = this.entityDAO
.byModelId(id)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.MODIFY))
.getOrThrow();
allRequestParams.putIfAbsent(Domain.ATTR_INSTITUTION_ID, String.valueOf(institutionId));
final M modifyData = this.beanValidationService.validateModifiedBean(
model,
allRequestParams,
modifiedDataType());
final M _modifyData = beforeSave(modifyData);
return this.entityDAO.save(_modifyData)
.flatMap(entity -> this.userActivityLogDAO.log(ActivityType.MODIFY, entity))
.flatMap(entity -> notifySave(_modifyData, entity))
.getOrThrow();
}
@RequestMapping(path = "/{id}", method = RequestMethod.DELETE)
public EntityProcessingReport hardDelete(@PathVariable final String id) {
final EntityType entityType = this.entityDAO.entityType();
final BulkAction bulkAction = new BulkAction(
Type.HARD_DELETE,
entityType,
new EntityKey(id, entityType));
return this.entityDAO.byModelId(id)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.WRITE))
.flatMap(entity -> this.bulkActionService.createReport(bulkAction))
.getOrThrow();
}
@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))
@ -253,8 +188,110 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.collect(Collectors.toList());
}
protected Result<T> notifySave(final M modifyData, final T entity) {
return Result.of(entity);
// ******************
// * POST (create)
// ******************
@RequestMapping(
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public T create(
@RequestParam final MultiValueMap<String, String> allRequestParams,
@RequestParam(
name = Domain.ATTR_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
// check write privilege for requested institution and concrete entityType
this.authorizationGrantService.checkPrivilege(
this.entityDAO.entityType(),
PrivilegeType.WRITE,
institutionId);
allRequestParams.putIfAbsent(
Domain.ATTR_INSTITUTION_ID,
Arrays.asList(String.valueOf(institutionId)));
final M requestModel = this.createNew(new POSTMapper(allRequestParams));
return this.beanValidationService.validateBean(requestModel)
.flatMap(this.entityDAO::createNew)
.flatMap(entity -> this.userActivityLogDAO.log(ActivityType.CREATE, entity))
.flatMap(entity -> this.notifySaved(requestModel, entity))
.getOrThrow();
}
// ****************
// * PUT (save)
// ****************
@RequestMapping(
path = "/{modelId}",
method = RequestMethod.PUT,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public T savePut(
@PathVariable final String modelId,
@Valid @RequestBody final M modifyData) {
return this.beanValidationService.validateBean(modifyData)
.flatMap(m -> this.authorizationGrantService.checkGrantOnEntity(m, PrivilegeType.MODIFY))
.flatMap(m -> this.entityDAO.save(modelId, m))
.flatMap(e -> this.userActivityLogDAO.log(ActivityType.MODIFY, e))
.flatMap(e -> notifySaved(modifyData, e))
.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)
// ******************
@RequestMapping(
path = "/{id}",
method = RequestMethod.DELETE,
produces = MediaType.APPLICATION_JSON_VALUE)
public EntityProcessingReport hardDelete(@PathVariable final String id) {
final EntityType entityType = this.entityDAO.entityType();
final BulkAction bulkAction = new BulkAction(
Type.HARD_DELETE,
entityType,
new EntityKey(id, entityType));
return this.entityDAO.byModelId(id)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.WRITE))
.flatMap(entity -> this.bulkActionService.createReport(bulkAction))
.getOrThrow();
}
protected void checkReadPrivilege(final Long institutionId) {
@ -272,16 +309,14 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
return this.entityDAO.allMatching(filterMap, grantFilter);
}
protected Result<T> notifySaved(final M modifyData, final T entity) {
return Result.of(entity);
}
protected abstract M createNew(POSTMapper postParams);
protected abstract Class<M> modifiedDataType();
protected abstract SqlTable getSQLTableOfEntity();
private Result<M> checkIsNew(final M entity) {
if (entity.getModelId() == null) {
return Result.of(entity);
} else {
return Result
.ofError(new IllegalAPIArgumentException("Request model has already an identifier but should not"));
}
}
}

View file

@ -9,25 +9,39 @@
package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
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.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
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;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils;
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;
@ -38,6 +52,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@WebServiceProfile
@ -47,6 +63,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
private final ExamDAO examDAO;
private final IndicatorDAO indicatorDAO;
private final LmsAPIService lmsAPIService;
public ExamAdministrationController(
final AuthorizationGrantService authorizationGrantService,
@ -54,8 +71,9 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
final ExamDAO examDAO,
final PaginationService paginationService,
final BulkActionService bulkActionService,
final BeanValidationService beanValidationService,
final IndicatorDAO indicatorDAO,
final BeanValidationService beanValidationService) {
final LmsAPIService lmsAPIService) {
super(authorizationGrantService,
bulkActionService,
@ -66,6 +84,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
this.examDAO = examDAO;
this.indicatorDAO = indicatorDAO;
this.lmsAPIService = lmsAPIService;
}
@Override
@ -92,7 +111,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
@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,
@RequestParam final Map<String, String> allRequestParams) {
@RequestParam final MultiValueMap<String, String> allRequestParams) {
checkReadPrivilege(institutionId);
@ -139,77 +158,111 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
}
}
// @RequestMapping(path = "/{examId}/indicator", method = RequestMethod.GET)
// public Collection<Indicator> getIndicatorOfExam(@PathVariable final Long examId) {
// // check read-only grant on Exam
// this.examDAO.byPK(examId)
// .map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.READ_ONLY))
// .getOrThrow();
@RequestMapping(path = "/{examId}/indicator", method = RequestMethod.GET)
public Collection<Indicator> getIndicatorOfExam(@PathVariable final Long examId) {
// check read-only grant on Exam
this.examDAO.byPK(examId)
.map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.READ_ONLY))
.getOrThrow();
return this.indicatorDAO.allForExam(examId)
.getOrThrow();
}
@RequestMapping(path = "/{examId}/indicator/{indicatorId}", method = RequestMethod.DELETE)
public Collection<Indicator> deleteIndicatorOfExam(
@PathVariable final Long examId,
@PathVariable(required = false) final Long indicatorId) {
// check write grant on Exam
this.examDAO.byPK(examId)
.map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.WRITE))
.getOrThrow();
final Set<EntityKey> toDelete = (indicatorId != null)
? this.indicatorDAO.allForExam(examId)
.getOrThrow()
.stream()
.map(ind -> new EntityKey(String.valueOf(ind.id), EntityType.INDICATOR))
.collect(Collectors.toSet())
: Utils.immutableSetOf(new EntityKey(String.valueOf(indicatorId), EntityType.INDICATOR));
this.indicatorDAO.delete(toDelete);
return this.indicatorDAO.allForExam(examId)
.getOrThrow();
}
@RequestMapping(path = "/{examId}/indicator", method = RequestMethod.POST)
public Indicator addNewIndicatorToExam(
@PathVariable final Long examId,
@Valid @RequestBody final Indicator indicator) {
// check write grant on Exam
this.examDAO.byPK(examId)
.flatMap(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.WRITE))
.getOrThrow();
if (indicator.id != null) {
return this.indicatorDAO.byPK(indicator.id)
.getOrThrow();
}
return this.indicatorDAO
.createNew(indicator)
.getOrThrow();
}
@RequestMapping(path = "/{examId}/indicator/{id}", method = RequestMethod.PUT)
public Indicator putIndicatorForExam(
@PathVariable final String id,
@Valid @RequestBody final Indicator indicator) {
// check modify grant on Exam
this.examDAO.byPK(indicator.examId)
.flatMap(e -> this.authorizationGrantService.checkGrantOnEntity(e, PrivilegeType.MODIFY))
.getOrThrow();
return this.indicatorDAO
.save(id, indicator)
.getOrThrow();
}
// @RequestMapping(path = "/{examId}/indicator/{id}", method = RequestMethod.PATCH)
// public Indicator patchSaveIndicatorForExam(
// @PathVariable final Long examId,
// @Valid @RequestBody final Indicator indicator) {
//
// return this.indicatorDAO.allForExam(examId)
// .getOrThrow();
// }
// // check modify grant on Exam
// this.examDAO.byPK(examId)
// .map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.MODIFY))
// .getOrThrow();
//
// @RequestMapping(path = "/{examId}/indicator/delete/{indicatorId}", method = RequestMethod.DELETE)
// public Collection<Indicator> deleteIndicatorOfExam(
// @PathVariable final Long examId,
// @PathVariable(required = false) final Long indicatorId) {
//
// // check write grant on Exam
// this.examDAO.byPK(examId)
// .map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.WRITE))
// .getOrThrow();
//
// final Set<EntityKey> toDelete = (indicatorId != null)
// ? this.indicatorDAO.allForExam(examId)
// .getOrThrow()
// .stream()
// .map(ind -> new EntityKey(String.valueOf(ind.id), EntityType.INDICATOR))
// .collect(Collectors.toSet())
// : Utils.immutableSetOf(new EntityKey(String.valueOf(indicatorId), EntityType.INDICATOR));
//
// this.indicatorDAO.delete(toDelete);
//
// return this.indicatorDAO.allForExam(examId)
// .getOrThrow();
// }
//
// @RequestMapping(path = "/{examId}/indicator/new", method = RequestMethod.POST)
// public Indicator addNewIndicatorToExam(
// @PathVariable final Long examId,
// @Valid @RequestBody final Indicator indicator) {
//
// // check write grant on Exam
// this.examDAO.byPK(examId)
// .flatMap(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.WRITE))
// .getOrThrow();
//
// if (indicator.id != null) {
// return this.indicatorDAO.byPK(indicator.id)
// .getOrThrow();
// }
//
// return this.indicatorDAO
// .save(indicator)
// .getOrThrow();
// }
//
// @RequestMapping(path = "/{examId}/indicator/save", method = RequestMethod.PUT)
// public Indicator saveIndicatorForExam(
// @PathVariable final Long examId,
// @Valid @RequestBody final Indicator indicator) {
//
// // check modify grant on Exam
// this.examDAO.byPK(examId)
// .map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.MODIFY))
// .getOrThrow();
//
// return this.indicatorDAO.save(new Indicator(
// indicator.id,
// examId,
// indicator.name,
// indicator.type,
// indicator.defaultColor,
// indicator.thresholds)).getOrThrow();
// }
// return this.indicatorDAO.save(new Indicator(
// indicator.id,
// examId,
// indicator.name,
// indicator.type,
// indicator.defaultColor,
// indicator.thresholds)).getOrThrow();
// }
@Override
protected Exam createNew(final POSTMapper postParams) {
final Long lmsSetupId = postParams.getLong(LMS_SETUP.ATTR_ID);
final String quizId = postParams.getString(QuizData.QUIZ_ATTR_ID);
final LmsAPITemplate lmsAPITemplate = this.lmsAPIService
.createLmsAPITemplate(lmsSetupId)
.getOrThrow();
final QuizData quiz = lmsAPITemplate.getQuizzes(new HashSet<>(Arrays.asList(quizId)))
.iterator()
.next()
.getOrThrow();
return new Exam(null, quiz, postParams);
}
}

View file

@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport;
@ -69,4 +70,13 @@ public class InstitutionController extends ActivatableEntityController<Instituti
return this.institutionDAO.byPK(institutionId).getOrThrow();
}
@Override
protected Institution createNew(final POSTMapper postParams) {
final Institution institution = new Institution(null, postParams);
if (this.institutionDAO.exists(institution.name)) {
throw new IllegalAPIArgumentException("institution:name:unique:" + institution.name);
}
return institution;
}
}

View file

@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -98,4 +99,9 @@ public class LmsSetupController extends ActivatableEntityController<LmsSetup, Lm
}
}
@Override
protected LmsSetup createNew(final POSTMapper postParams) {
return new LmsSetup(null, postParams);
}
}

View file

@ -87,31 +87,4 @@ public class QuizImportController {
: this.defaultPageSize);
}
// @RequestMapping(path = "/import", method = RequestMethod.POST)
// public Collection<Exam> importExam(
// @RequestParam(name = LMS_SETUP.ATTR_ID, required = true) final Long lmsSetupId,
// @RequestParam(name = QuizData.QUIZ_ATTR_ID, required = true) final String quizId) {
//
// this.authorizationGrantService.checkHasAnyPrivilege(
// EntityType.EXAM,
// PrivilegeType.WRITE);
//
// final LmsAPITemplate lmsAPITemplate = this.lmsAPIService
// .createLmsAPITemplate(lmsSetupId)
// .getOrThrow();
//
// final Set<String> ids = new HashSet<>(Arrays.asList(
// StringUtils.split(quizId, Constants.LIST_SEPARATOR_CHAR)));
//
// return lmsAPITemplate.getQuizzes(ids)
// .stream()
// .map(result -> result.flatMap(quiz -> this.examDAO.importFromQuizData(
// lmsAPITemplate.lmsSetup().institutionId,
// lmsSetupId,
// quiz)))
// .flatMap(Result::skipOnError)
// .peek(exam -> this.userActivityLogDAO.log(ActivityType.IMPORT, exam))
// .collect(Collectors.toList());
// }
}

View file

@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -29,7 +30,7 @@ import ch.ethz.seb.sebserver.webservice.weblayer.oauth.RevokeTokenEndpoint;
@WebServiceProfile
@RestController
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + RestAPI.ENDPOINT_USER_ACCOUNT)
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + RestAPI.ENDPOINT_USER_ACCOUNT)
public class UserAccountController extends ActivatableEntityController<UserInfo, UserMod> {
private final ApplicationEventPublisher applicationEventPublisher;
@ -71,7 +72,7 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
}
@Override
protected Result<UserInfo> notifySave(final UserMod userData, final UserInfo userInfo) {
protected Result<UserInfo> notifySaved(final UserMod userData, final UserInfo userInfo) {
// handle password change; revoke access tokens if password has changed
if (userData.passwordChangeRequest() && userData.newPasswordMatch()) {
this.applicationEventPublisher.publishEvent(
@ -80,4 +81,9 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
return Result.of(userInfo);
}
@Override
protected UserMod createNew(final POSTMapper postParams) {
return new UserMod(null, postParams);
}
}

View file

@ -7,11 +7,12 @@ spring.datasource.initialization-mode=always
spring.datasource.url=jdbc:mariadb://localhost:6603/SEBServer?useSSL=false&createDatabaseIfNotExist=true
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.platform=dev
spring.datasource.hikari.max-lifetime=600000
sebserver.webservice.api.admin.endpoint=/admin-api/**
sebserver.webservice.api.admin.endpoint=/admin-api/v1/**
sebserver.webservice.api.admin.accessTokenValiditySeconds=1800
sebserver.webservice.api.admin.refreshTokenValiditySeconds=-1
sebserver.webservice.api.exam.endpoint=/exam-api/**
sebserver.webservice.api.exam.endpoint=/exam-api/v1/**
sebserver.webservice.api.exam.accessTokenValiditySeconds=1800
sebserver.webservice.api.exam.refreshTokenValiditySeconds=-1

View file

@ -81,7 +81,7 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
final APIMessage errorMessage = new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(RestAPI.ENDPOINT_INSTITUTION)
.withAttribute("institution", "2") // try to hack
.withAttribute("institutionId", "2") // try to hack
.withExpectedStatus(HttpStatus.FORBIDDEN)
.getAsObject(new TypeReference<APIMessage>() {
});
@ -124,7 +124,7 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
@Test
public void createNewInstitution() throws Exception {
// create new institution with seb-admin
final Institution institution = new RestAPITestHelper()
Institution institution = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(RestAPI.ENDPOINT_INSTITUTION)
.withMethod(HttpMethod.POST)
@ -151,12 +151,11 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
.getAsObject(new TypeReference<APIMessage>() {
});
// and predefined id should not be possible
// and name for institution must be unique
errorMessage = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(RestAPI.ENDPOINT_INSTITUTION)
.withMethod(HttpMethod.POST)
.withAttribute("id", "123")
.withAttribute("name", "new institution")
.withAttribute("urlSuffix", "new_inst")
.withAttribute("active", "false")
@ -166,6 +165,22 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
assertNotNull(errorMessage);
assertEquals("1010", errorMessage.messageCode);
// and predefined id should be ignored
institution = new RestAPITestHelper()
.withAccessToken(getSebAdminAccess())
.withPath(RestAPI.ENDPOINT_INSTITUTION)
.withMethod(HttpMethod.POST)
.withAttribute("id", "123")
.withAttribute("name", "newer institution")
.withAttribute("urlSuffix", "new_inst")
.withAttribute("active", "false")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Institution>() {
});
assertNotNull(institution);
assertEquals("newer institution", institution.name);
}
// @Test

View file

@ -33,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.Domain;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityKeyAndName;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
@ -90,6 +91,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
public void getUserInfoWithUUID() throws Exception {
final String sebAdminAccessToken = getSebAdminAccess();
String contentAsString = this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminAccessToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
@ -108,6 +110,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String adminInstitution2AccessToken = getAdminInstitution2Access();
contentAsString = this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user1")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + adminInstitution2AccessToken))
.andExpect(status().isForbidden())
.andReturn().getResponse().getContentAsString();
@ -124,7 +127,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
public void institutionalAdminNotAllowedToSeeUsersOfOtherInstitution() throws Exception {
new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2")
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT + "?institutionId=2")
.withExpectedStatus(HttpStatus.FORBIDDEN)
.getAsString();
}
@ -148,7 +151,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
userInfos = new RestAPITestHelper()
.withAccessToken(getAdminInstitution2Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withAttribute("institution", "2")
.withAttribute("institutionId", "2")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Page<UserInfo>>() {
});
@ -165,8 +168,8 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
userInfos = new RestAPITestHelper()
.withAccessToken(getAdminInstitution2Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withAttribute("institution", "2")
.withAttribute("active", "true")
.withAttribute(Entity.FILTER_ATTR_INSTITUTION, "2")
.withAttribute(Entity.FILTER_ATTR_ACTIVE, "true")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Page<UserInfo>>() {
});
@ -181,8 +184,8 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
userInfos = new RestAPITestHelper()
.withAccessToken(getAdminInstitution2Access())
.withPath(RestAPI.ENDPOINT_USER_ACCOUNT)
.withAttribute("institution", "2")
.withAttribute("active", "false")
.withAttribute(Entity.FILTER_ATTR_INSTITUTION, "2")
.withAttribute(Entity.FILTER_ATTR_ACTIVE, "false")
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Page<UserInfo>>() {
});
@ -222,7 +225,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String token = getSebAdminAccess();
final Page<UserInfo> userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?institution=2")
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -264,7 +267,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
Page<UserInfo> userInfos = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT
+ "?page_number=1&page_size=3&institution=2")
+ "?page_number=1&page_size=3&institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -282,7 +285,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
userInfos = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT
+ "?page_number=2&page_size=3&institution=2")
+ "?page_number=2&page_size=3&institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -301,7 +304,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
userInfos = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT
+ "?page_number=3&page_size=3&institution=2")
+ "?page_number=3&page_size=3&institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -320,7 +323,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
userInfos = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT
+ "?page_number=1&page_size=3&sort_order=DESCENDING&institution=2")
+ "?page_number=1&page_size=3&sort_order=DESCENDING&institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -363,7 +366,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
public void getAllUserInfoWithOnlyActive() throws Exception {
final String token = getSebAdminAccess();
final Page<UserInfo> userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?active=true&institution=2")
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?active=true&institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -395,9 +398,10 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
// expecting one for institution 2
userInfos = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?active=false&institution=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "?active=false&institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserInfo>>() {
@ -436,13 +440,15 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
@Test
public void createUserTest() throws Exception {
final String token = getSebAdminAccess();
final UserInfo createdUser = this.jsonMapper.readValue(
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param(Domain.USER.ATTR_NAME, "NewTestUser")
.param(Domain.USER.ATTR_USERNAME, "NewTestUser")
.param(Domain.USER.ATTR_LOCALE, Locale.ENGLISH.toLanguageTag())
.param(Domain.USER.ATTR_TIMEZONE, DateTimeZone.UTC.getID())
.param(UserMod.ATTR_NAME_NEW_PASSWORD, "12345678")
.param(UserMod.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
.andExpect(status().isOk())
@ -456,6 +462,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
// get newly created user and check equality
final UserInfo createdUserGet = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + createdUser.uuid)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -551,6 +558,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String token = getSebAdminAccess();
final UserInfo user = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user7")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -565,7 +573,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
// change userName, email and roles
final UserMod modifyUser = new UserMod(new UserInfo(
user.getUuid(),
null,
user.getInstitutionId(),
user.getName(),
"newUser1",
@ -578,7 +586,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String modifyUserJson = this.jsonMapper.writeValueAsString(modifyUser);
UserInfo modifiedUserResult = this.jsonMapper.readValue(
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + user.getUuid())
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(modifyUserJson))
@ -597,6 +605,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
// double check by getting the user by UUID
modifiedUserResult = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + modifiedUserResult.uuid)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -610,39 +619,39 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
assertEquals("[EXAM_ADMIN, EXAM_SUPPORTER]", String.valueOf(modifiedUserResult.roles));
}
@Test
public void modifyUserWithPOSTMethod() throws Exception {
final String token = getSebAdminAccess();
final UserInfo modifiedUser = this.jsonMapper.readValue(
this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param("name", "PostModifyTest"))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<UserInfo>() {
});
assertNotNull(modifiedUser);
assertEquals("PostModifyTest", modifiedUser.name);
// check validation
final Collection<APIMessage> errors = this.jsonMapper.readValue(
this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param("name", "P"))
.andExpect(status().isBadRequest())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<APIMessage>>() {
});
assertNotNull(errors);
assertFalse(errors.isEmpty());
final APIMessage error = errors.iterator().next();
assertEquals("1200", error.messageCode);
}
// @Test
// public void modifyUserWithPOSTMethod() throws Exception {
// final String token = getSebAdminAccess();
//
// final UserInfo modifiedUser = this.jsonMapper.readValue(
// this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
// .header("Authorization", "Bearer " + token)
// .contentType(MediaType.APPLICATION_FORM_URLENCODED)
// .param("name", "PostModifyTest"))
// .andExpect(status().isOk())
// .andReturn().getResponse().getContentAsString(),
// new TypeReference<UserInfo>() {
// });
//
// assertNotNull(modifiedUser);
// assertEquals("PostModifyTest", modifiedUser.name);
//
// // check validation
// final Collection<APIMessage> errors = this.jsonMapper.readValue(
// this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
// .header("Authorization", "Bearer " + token)
// .contentType(MediaType.APPLICATION_FORM_URLENCODED)
// .param("name", "P"))
// .andExpect(status().isBadRequest())
// .andReturn().getResponse().getContentAsString(),
// new TypeReference<Collection<APIMessage>>() {
// });
//
// assertNotNull(errors);
// assertFalse(errors.isEmpty());
// final APIMessage error = errors.iterator().next();
// assertEquals("1200", error.messageCode);
// }
@Test
public void testOwnerModifyPossibleForExamAdmin() throws Exception {
@ -658,7 +667,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final UserMod modifiedUser = new UserMod(examAdmin, null, null);
final String modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + modifiedUser.uuid)
.header("Authorization", "Bearer " + examAdminToken1)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(modifiedUserJson))
@ -680,21 +689,13 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
.andExpect(status().isForbidden())
.andReturn().getResponse().getContentAsString();
this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param(Domain.USER.ATTR_INSTITUTION_ID, "2")
.param(Domain.USER.ATTR_NAME, "NewTestUser"))
.andExpect(status().isForbidden())
.andReturn().getResponse().getContentAsString();
final UserInfo userInfo = new UserInfo(
null, 2L, "NewTestUser", "NewTestUser",
"", true, Locale.CANADA, DateTimeZone.UTC,
new HashSet<>(Arrays.asList(UserRole.EXAM_ADMIN.name())));
final UserMod newUser = new UserMod(userInfo, "12345678", "12345678");
final String newUserJson = this.jsonMapper.writeValueAsString(newUser);
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/NewTestUser")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(newUserJson))
@ -716,23 +717,13 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
.andExpect(status().isForbidden())
.andReturn().getResponse().getContentAsString();
this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user3")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param(Domain.USER.ATTR_INSTITUTION_ID, "2")
.param(Domain.USER.ATTR_NAME, "NewTestUser")
.param(UserMod.ATTR_NAME_NEW_PASSWORD, "12345678")
.param(UserMod.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
.andExpect(status().isForbidden())
.andReturn().getResponse().getContentAsString();
final UserInfo userInfo = new UserInfo(
null, 2L, "NewTestUser", "NewTestUser",
"", true, Locale.CANADA, DateTimeZone.UTC,
new HashSet<>(Arrays.asList(UserRole.EXAM_ADMIN.name())));
final UserMod newUser = new UserMod(userInfo, "12345678", "12345678");
final String newUserJson = this.jsonMapper.writeValueAsString(newUser);
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/NewTestUser")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(newUserJson))
@ -749,6 +740,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String sebAdminToken = getSebAdminAccess();
final UserInfo examAdmin1 = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -761,7 +753,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
"newPassword");
final String modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + modifiedUser.uuid)
.header("Authorization", "Bearer " + sebAdminToken)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(modifiedUserJson))
@ -795,6 +787,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
final String sebAdminToken = getSebAdminAccess();
final UserInfo examAdmin1 = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -809,7 +802,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
String modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
List<APIMessage> messages = this.jsonMapper.readValue(
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + modifiedUser.uuid)
.header("Authorization", "Bearer " + sebAdminToken)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(modifiedUserJson))
@ -831,7 +824,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
messages = this.jsonMapper.readValue(
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
this.mockMvc.perform(put(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + modifiedUser.uuid)
.header("Authorization", "Bearer " + sebAdminToken)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(modifiedUserJson))
@ -997,7 +990,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
// all active of institution 2
usersPage = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/all/active?institution=2")
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/all/active?institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
@ -1011,9 +1004,10 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
// all inactive of institution 2
usersPage = this.jsonMapper.readValue(
this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/all/inactive?institution=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/all/inactive?institutionId=2")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserInfo>>() {
@ -1025,14 +1019,16 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
}
@Test
public void testGeneralInEndpoint() throws Exception {
public void testGeneralListEndpoint() 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))
.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/list?ids=user1,user2,user6,user7")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<UserInfo>>() {
@ -1046,8 +1042,10 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
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))
.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/list?ids=user1,user2,user6,user7")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + instAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Collection<UserInfo>>() {
@ -1066,6 +1064,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
Collection<EntityKeyAndName> names = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/names")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + sebAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -1083,6 +1082,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
names = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/names")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + instAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -1100,6 +1100,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
names = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/names?active=true")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + instAdminToken))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -1113,6 +1114,44 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
+ "EntityIdAndName [entityType=USER, id=user7, name=User]]", names.toString());
}
// @Test
// public void createWithRoleAddRoleDeleteRole() throws Exception {
// final String token = getSebAdminAccess();
// UserInfo createdUser = this.jsonMapper.readValue(
// this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT)
// .header("Authorization", "Bearer " + token)
// .contentType(MediaType.APPLICATION_FORM_URLENCODED)
// .param(Domain.USER.ATTR_NAME, "NewTestUser")
// .param(Domain.USER.ATTR_USERNAME, "NewTestUser")
// .param(Domain.USER.ATTR_LOCALE, Locale.ENGLISH.toLanguageTag())
// .param(Domain.USER.ATTR_TIMEZONE, DateTimeZone.UTC.getID())
// .param(UserMod.ATTR_NAME_NEW_PASSWORD, "12345678")
// .param(UserMod.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
// .andExpect(status().isOk())
// .andReturn().getResponse().getContentAsString(),
// new TypeReference<UserInfo>() {
// });
//
// assertNotNull(createdUser);
// assertEquals("NewTestUser", createdUser.name);
// assertEquals("[]", String.valueOf(createdUser.roles));
//
// // add two roles
// createdUser = this.jsonMapper.readValue(
// this.mockMvc.perform(patch(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/" + createdUser.uuid)
// .header("Authorization", "Bearer " + token)
// .contentType(MediaType.APPLICATION_FORM_URLENCODED)
// .param(USER_ROLE.REFERENCE_NAME, "EXAM_SUPPORTER", "EXAM_ADMIN"))
// .andExpect(status().isOk())
// .andReturn().getResponse().getContentAsString(),
// new TypeReference<UserInfo>() {
// });
//
// assertNotNull(createdUser);
// assertEquals("NewTestUser", createdUser.name);
// assertEquals("[]", String.valueOf(createdUser.roles));
// }
private UserInfo getUserInfo(final String name, final Collection<UserInfo> infos) {
try {
return infos

View file

@ -47,7 +47,7 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
// for a user in another institution, the institution has to be defined
Page<UserActivityLog> logs = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?user=user4&institution=2")
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?user=user4&institutionId=2")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -82,7 +82,7 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
final String token = getSebAdminAccess();
Page<UserActivityLog> logs = this.jsonMapper.readValue(
this.mockMvc.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institution=2&from=" + sec2)
get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institutionId=2&from=" + sec2)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -94,7 +94,7 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
logs = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institution=2&from="
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institutionId=2&from="
+ sec2 + "&to=" + sec4)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
@ -107,9 +107,10 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
logs = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institution=2&from=" + sec2
+ "&to=" + sec5)
.header("Authorization", "Bearer " + token))
.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institutionId=2&from=" + sec2
+ "&to=" + sec5)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserActivityLog>>() {
@ -120,9 +121,10 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
logs = this.jsonMapper.readValue(
this.mockMvc
.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institution=2&from=" + sec2
+ "&to=" + sec6)
.header("Authorization", "Bearer " + token))
.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "?institutionId=2&from=" + sec2
+ "&to=" + sec6)
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
new TypeReference<Page<UserActivityLog>>() {
@ -165,7 +167,7 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
this.mockMvc
.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG
+ "?institution=2&activity_types=CREATE,MODIFY")
+ "?institutionId=2&activity_types=CREATE,MODIFY")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),
@ -209,7 +211,7 @@ public class UserActivityLogAPITest extends AdministrationAPIIntegrationTester {
this.mockMvc
.perform(
get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG
+ "?entity_types=INSTITUTION,EXAM&institution=2")
+ "?entity_types=INSTITUTION,EXAM&institutionId=2")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(),