more javadoc

This commit is contained in:
anhefti 2019-03-14 22:31:20 +01:00
parent d404498475
commit 6e020b8e6f
31 changed files with 205 additions and 57 deletions

View file

@ -13,18 +13,29 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
/** Defines generic interface for all types of Entity. */
public interface Entity extends ModelIdAware {
public static final String FILTER_ATTR_INSTITUTION = API.PARAM_INSTITUTION_ID;
public static final String FILTER_ATTR_ACTIVE = "active";
public static final String FILTER_ATTR_NAME = "name";
/** Get the type of the entity.
*
* @return the type of the entity */
@JsonIgnore
EntityType entityType();
/** Get the name of the entity
*
* @return the name of the entity */
@JsonIgnore
String getName();
/** Get an unique EntityKey for the entity consisting of the model identifier of the entity
* and the type of the entity.
*
* @return unique EntityKey for the entity */
@JsonIgnore
default EntityKey getEntityKey() {
final String modelId = getModelId();
@ -34,6 +45,10 @@ public interface Entity extends ModelIdAware {
return new EntityKey(modelId, entityType());
}
/** Creates an EntityName instance from a given Entity.
*
* @param entity The Entity instance
* @return EntityName instance created form given Entity */
public static EntityName toName(final Entity entity) {
return new EntityName(
entity.entityType(),

View file

@ -17,17 +17,25 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
/** A EntityKey uniquely identifies a domain entity within the SEB Server's domain model.
* A EntityKey consists of the model identifier of a domain entity and the type of the entity. */
public class EntityKey implements Serializable {
private static final long serialVersionUID = -2368065921846821061L;
/** The model identifier of the entity */
@JsonProperty(value = "modelId", required = true)
@NotNull
public final String modelId;
/** The type of the entity */
@JsonProperty(value = "entityType", required = true)
@NotNull
public final EntityType entityType;
/** pre-calculated hash value. Since EntityKey is fully immutable this is a valid optimization */
private final int hash;
@JsonCreator
public EntityKey(
@JsonProperty(value = "modelId", required = true) final String modelId,
@ -42,31 +50,41 @@ public class EntityKey implements Serializable {
this.modelId = modelId;
this.entityType = entityType;
final int prime = 31;
int result = 1;
result = prime * result + ((this.entityType == null) ? 0 : this.entityType.hashCode());
result = prime * result + ((this.modelId == null) ? 0 : this.modelId.hashCode());
this.hash = result;
}
public EntityKey(
final Long pk,
final EntityType entityType) {
this.modelId = String.valueOf(pk);
this.entityType = entityType;
this(String.valueOf(pk), entityType);
if (pk == null) {
throw new IllegalArgumentException("modelId has null reference");
}
}
/** Get the model identifier of this EntityKey
*
* @return the model identifier of this EntityKey */
public String getModelId() {
return this.modelId;
}
/** Get the entity type EntityKey
*
* @return the model identifier of this EntityKey */
public EntityType getEntityType() {
return this.entityType;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.entityType == null) ? 0 : this.entityType.hashCode());
result = prime * result + ((this.modelId == null) ? 0 : this.modelId.hashCode());
return result;
return this.hash;
}
@Override

View file

@ -10,8 +10,12 @@ package ch.ethz.seb.sebserver.gbl.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
/** Interface for all domain model objects that has a model identifier */
public interface ModelIdAware {
/** Get the model identifier of the domain model object
*
* @return the model identifier of the domain model object */
@JsonIgnore
String getModelId();

View file

@ -84,6 +84,12 @@ public final class Result<T> {
return this.error != null ? errorHandler.apply(this.error) : this.value;
}
/** Use this to get the referenced result element or on error case, use the given error handler
* to handle the error and use a given supplier to get an alternative element for further processing
*
* @param errorHandler the error handler to handle an error if happened
* @param supplier supplies an alternative result element on error case
* @return returns the referenced result element or the alternative element given by the supplier on error */
public T get(final Consumer<Throwable> errorHandler, final Supplier<T> supplier) {
if (this.error != null) {
errorHandler.accept(this.error);
@ -93,6 +99,9 @@ public final class Result<T> {
}
}
/** Apply a given error handler that consumes the error if there is one.
*
* @param errorHandler the error handler */
public void handleError(final Consumer<Throwable> errorHandler) {
if (this.error != null) {
errorHandler.accept(this.error);
@ -120,6 +129,9 @@ public final class Result<T> {
return this.value;
}
/** Get the referenced result element or in error case, throws the referenced error
*
* @return the referenced result element */
public T getOrThrow() {
if (this.error != null) {
if (this.error instanceof RuntimeException) {
@ -145,6 +157,9 @@ public final class Result<T> {
return this.error;
}
/** Indicates whether this Result refers to an error or not.
*
* @return true if this Result refers to an error */
public boolean hasError() {
return this.error != null;
}
@ -210,9 +225,14 @@ public final class Result<T> {
}
}
public Result<T> onErrorDo(final Consumer<Throwable> block) {
/** Uses a given error handler to apply an error if there is one and returning itself again
* for further processing.
*
* @param errorHandler the error handler
* @return self reference */
public Result<T> onErrorDo(final Consumer<Throwable> errorHandler) {
if (this.error != null) {
block.accept(this.error);
errorHandler.accept(this.error);
}
return this;
}

View file

@ -8,9 +8,12 @@
package ch.ethz.seb.sebserver.gbl.util;
/** A tuple of two elements of the same type */
public class Tuple<T> {
/** The first element of the tuple */
public final T _1;
/** The second element of the tuple */
public final T _2;
public Tuple(final T _1, final T _2) {

View file

@ -29,12 +29,20 @@ import ch.ethz.seb.sebserver.gbl.Constants;
public final class Utils {
/** Get an immutable List from a Collection of elements
*
* @param collection Collection of elements
* @return immutable List */
public static <T> List<T> immutableListOf(final Collection<T> collection) {
return (collection != null)
? Collections.unmodifiableList(new ArrayList<>(collection))
: Collections.emptyList();
}
/** Get a immutable Collection from a Collection of elements
*
* @param collection Collection of elements
* @return immutable Collection */
public static <T> Collection<T> immutableCollectionOf(final Collection<T> collection) {
return (collection != null)
? Collections.unmodifiableCollection(collection)
@ -53,10 +61,18 @@ public final class Utils {
return Collections.unmodifiableCollection(Arrays.asList(values));
}
/** Get a immutable Set from a Collection of elements
*
* @param collection Collection of elements
* @return immutable Set */
public static <T> Set<T> immutableSetOf(final Collection<T> collection) {
return immutableSetOf(new HashSet<>(collection));
}
/** Get a immutable Set from a Set of elements
*
* @param set Set of elements
* @return immutable Set */
public static <T> Set<T> immutableSetOf(final Set<T> set) {
return (set != null)
? Collections.unmodifiableSet(set)

View file

@ -15,8 +15,11 @@ public class PermissionDeniedException extends RuntimeException {
private static final long serialVersionUID = 5333137812363042580L;
/** The EntityType of the denied permission check */
public final EntityType entityType;
/** The PrivilegeType of the denied permission check */
public final PrivilegeType privilegeType;
/** The user identifier of the denied permission check */
public final String userId;
public PermissionDeniedException(

View file

@ -1,6 +1,6 @@
/*
* 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/.
@ -8,16 +8,20 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.client;
/** Defines a simple data bean holding (encrypted) client credentials */
public final class ClientCredentials {
/** The client id or client name parameter */
public final String clientId;
/** The client secret parameter */
public final String secret;
/** An client access token if supported */
public final String accessToken;
public ClientCredentials(
final String clientId,
final String secret,
final String clientId,
final String secret,
final String accessToken) {
this.clientId = clientId;
this.secret = secret;
this.accessToken = accessToken;

View file

@ -16,7 +16,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.ModelIdAware;
import ch.ethz.seb.sebserver.gbl.util.Result;
/** Interface of a DAO for an Entity that has activation feature.
/** Interface of a Data Access Object for an Entity that has activation feature.
*
* @param <T> the type of Entity */
public interface ActivatableEntityDAO<T extends Entity, M extends ModelIdAware> extends EntityDAO<T, M> {

View file

@ -24,6 +24,10 @@ import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.model.ModelIdAware;
import ch.ethz.seb.sebserver.gbl.util.Result;
/** Defines generic interface for all Entity based Data Access Objects
*
* @param <T> The specific type of the Entity domain model
* @param <M> The specific type of the Entity domain model to create a new Entity */
public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
/** Get the entity type for a concrete EntityDAO implementation.
@ -34,7 +38,7 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
/** Use this to get an Entity instance of concrete type by database identifier/primary-key (PK)
*
* @param id the data base identifier of the entity
* @return Result refer the Entity instance with the specified database identifier or refer to an error if
* @return Result referring the Entity instance with the specified database identifier or refer to an error if
* happened */
Result<T> byPK(Long id);
@ -44,7 +48,7 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
* but usually they are the same.
*
* @param id the model identifier
* @return Result refer the Entity instance with the specified model identifier or refer to an error if
* @return Result referring the Entity instance with the specified model identifier or refer to an error if
* happened */
@Transactional(readOnly = true)
default Result<T> byModelId(final String id) {
@ -53,12 +57,20 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
}).flatMap(this::byPK);
}
Result<Collection<T>> loadEntities(Collection<EntityKey> keys);
/** Get a collection of all entities for the given Set of entity keys.
*
* @param keys the Set of EntityKey to get the Entity's for
* @return Result referring the collection or an error if happened */
Result<Collection<T>> byEntityKeys(Set<EntityKey> keys);
/** Get a collection of all EntityName for the given Set of EntityKey.
*
* @param keys the Set of EntityKey to get the EntityName's for
* @return Result referring the collection or an error if happened */
@Transactional(readOnly = true)
default Result<Collection<EntityName>> loadEntityNames(final Collection<EntityKey> keys) {
default Result<Collection<EntityName>> getEntityNames(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
return loadEntities(keys)
return byEntityKeys(keys)
.getOrThrow()
.stream()
.map(entity -> new EntityName(
@ -69,27 +81,56 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
});
}
/** Create a new Entity from the given entity domain model data.
*
* @param data The entity domain model data
* @return Result referring to the newly created Entity or an error if happened */
Result<T> createNew(M data);
/** Use this to save/modify an entity.
*
* @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
* @return A Result referring the entity instance where the successfully saved/modified entity data is available or
* a
* reported exception on error case */
Result<T> save(T data);
/** Use this to delete a set Entity by a Collection of EntityKey
*
* @param all The Collection of EntityKey to delete
* @return Result of a collection of all entities that has been deleted or refer to an error if
* @return Result referring a collection of all entities that has been deleted or refer to an error if
* happened */
Result<Collection<EntityKey>> delete(Set<EntityKey> all);
/** Get a (unordered) collection of all Entities that matches the given filter criteria.
* The possible filter criteria for a specific Entity type is defined by the entity type.
*
* This adds filtering in SQL level by creating the select where clause from related
* filter criteria of the specific Entity type. If the filterMap contains a value for
* a particular filter criteria the value is extracted from the map and added to the where
* clause of the SQL select statement.
*
* @param filterMap FilterMap instance containing all the relevant filter criteria
* @return Result referring to collection of all matching entities or an error if happened */
@Transactional(readOnly = true)
default Result<Collection<T>> allMatching(final FilterMap filterMap) {
return allMatching(filterMap, e -> true);
}
/** Get a (unordered) collection of all Entities that matches a given filter criteria
* and a given predicate.
*
* The possible filter criteria for a specific Entity type is defined by the entity type.
* This adds filtering in SQL level by creating the select where clause from related
* filter criteria of the specific Entity type. If the filterMap contains a value for
* a particular filter criteria the value is extracted from the map and added to the where
* clause of the SQL select statement.
*
* The predicate is applied after the SQL query by filtering the resulting list with the
* predicate after on the SQL query result, before returning.
*
* @param filterMap FilterMap instance containing all the relevant filter criteria
* @return Result referring to collection of all matching entities or an error if happened */
Result<Collection<T>> allMatching(FilterMap filterMap, Predicate<T> predicate);
/** Context based utility method to extract an expected single resource entry form a Collection of specified type.

View file

@ -11,10 +11,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
/** Concrete EntityDAO interface of Exam entities */
public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSupportDAO<Exam> {
// Result<Exam> importFromQuizData(Long institutionId, Long lmsSetupId, QuizData quizData);
//
// Result<Exam> byQuizId(String quizId);
}

View file

@ -22,6 +22,12 @@ import ch.ethz.seb.sebserver.gbl.model.institution.SebClientConfig;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.JodaTimeTypeResolver;
/** A Map containing various filter criteria from a certain API request.
* This is used as a data object that can be used to collect API request parameter
* data on one side and supply filter criteria based access to concrete Entity filtering
* on the other side.
*
* All text based filter criteria are used as SQL wildcard's */
public class FilterMap extends POSTMapper {
public FilterMap() {

View file

@ -14,8 +14,13 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
/** Concrete EntityDAO interface of Indicator entities */
public interface IndicatorDAO extends EntityDAO<Indicator, Indicator>, BulkActionSupportDAO<Indicator> {
/** Get a collection of all Indicator entities for a specified exam.
*
* @param examId the Exam identifier to get the Indicators for
* @return Result referring to the collection of Indicators of an Exam or to an error if happened */
Result<Collection<Indicator>> allForExam(Long examId);
}

View file

@ -11,9 +11,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
public interface InstitutionDAO
extends ActivatableEntityDAO<Institution, Institution>, BulkActionSupportDAO<Institution> {
boolean exists(String name);
/** Concrete EntityDAO interface of Institution entities */
public interface InstitutionDAO extends
ActivatableEntityDAO<Institution, Institution>,
BulkActionSupportDAO<Institution> {
}

View file

@ -13,7 +13,13 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials;
/** Concrete EntityDAO interface of LmsSetup entities */
public interface LmsSetupDAO extends ActivatableEntityDAO<LmsSetup, LmsSetup>, BulkActionSupportDAO<LmsSetup> {
/** Get the configured ClientCredentials for a given LmsSetup.
* The ClientCredentials are still encoded as they are on DB storage
*
* @param lmsSetupId the identifier of the LmsSetup to get the ClientCredentials for
* @return the configured ClientCredentials for a given LmsSetup */
Result<ClientCredentials> getLmsAPIAccessCredentials(String lmsSetupId);
}

View file

@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
/** Thrown by Data Access Object if an requested Entity or other requested resource wasn't found */
@ResponseStatus(HttpStatus.NOT_FOUND)
public final class ResourceNotFoundException extends RuntimeException {

View file

@ -13,10 +13,16 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials;
/** Concrete EntityDAO interface of SebClientConfig entities */
public interface SebClientConfigDAO extends
ActivatableEntityDAO<SebClientConfig, SebClientConfig>,
BulkActionSupportDAO<SebClientConfig> {
/** Get the configured ClientCredentials for a given SebClientConfig.
* The ClientCredentials are still encoded as they are on DB storage
*
* @param modelId the model identifier of the SebClientConfig to get the ClientCredentials for
* @return the configured ClientCredentials for a given SebClientConfig */
Result<ClientCredentials> getSebClientCredentials(String modelId);
}

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import org.springframework.transaction.interceptor.TransactionInterceptor;
/** Defines some static Spring based transaction handling functionality for rollback handling */
public interface TransactionHandler {
/** Use this to mark the current transaction within the calling thread as "to rollback".

View file

@ -17,6 +17,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
/** Concrete EntityDAO interface of UserActivityLog entities */
public interface UserActivityLogDAO extends
EntityDAO<UserActivityLog, UserActivityLog>,
UserRelatedEntityDAO<UserActivityLog> {

View file

@ -13,8 +13,7 @@ import java.util.Collection;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.util.Result;
/** Interface for a DAo handling an Entity with relations to an user (account)
*
/** Interface for all Data Access Objects handling an Entity with relations to an user (account)
*
* @param <T> the concrete type of the Entity */
public interface UserRelatedEntityDAO<T extends Entity> {

View file

@ -285,7 +285,7 @@ public class ExamDAOImpl implements ExamDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<Exam>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<Exam>> byEntityKeys(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractPKsFromKeys(keys);
return this.examRecordMapper.selectByExample()

View file

@ -105,7 +105,7 @@ public class IndicatorDAOImpl implements IndicatorDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<Indicator>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<Indicator>> byEntityKeys(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractPKsFromKeys(keys);

View file

@ -56,21 +56,6 @@ 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) {
@ -248,7 +233,7 @@ public class InstitutionDAOImpl implements InstitutionDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<Institution>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<Institution>> byEntityKeys(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractPKsFromKeys(keys);

View file

@ -252,7 +252,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<LmsSetup>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<LmsSetup>> byEntityKeys(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractPKsFromKeys(keys);

View file

@ -223,7 +223,7 @@ public class SebClientConfigDAOImpl implements SebClientConfigDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<SebClientConfig>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<SebClientConfig>> byEntityKeys(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractPKsFromKeys(keys);

View file

@ -317,7 +317,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<UserActivityLog>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<UserActivityLog>> byEntityKeys(final Set<EntityKey> keys) {
// TODO Auto-generated method stub
return Result.ofTODO();
}

View file

@ -343,7 +343,7 @@ public class UserDAOImpl implements UserDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<UserInfo>> loadEntities(final Collection<EntityKey> keys) {
public Result<Collection<UserInfo>> byEntityKeys(final Set<EntityKey> keys) {
return Result.tryCatch(() -> {
final List<Long> ids = extractPKsFromKeys(keys);

View file

@ -22,6 +22,11 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO;
/** This service can be used to 'manually' validate a Bean that is annotated within bean
* validation annotations.
*
* On validation error BeanValidationException is used to collect all validation issues
* and report them within the Result. */
@Service
@WebServiceProfile
public class BeanValidationService {
@ -41,6 +46,14 @@ public class BeanValidationService {
dao -> dao));
}
/** Validates a given bean that is annotated with Java bean validation annotations
*
* On validation error BeanValidationException is used to collect all validation issues
* and report them within the Result.
*
* @param bean the Bean to validate
* @return Result referring the Bean if there are no validation issues or to a BeanValidationException
* containing the collected validation issues */
public <T> Result<T> validateBean(final T bean) {
final DirectFieldBindingResult errors = new DirectFieldBindingResult(bean, "");
this.validator.validate(bean, errors);
@ -51,6 +64,10 @@ public class BeanValidationService {
return Result.of(bean);
}
/** Indicates whether the Entity of a given EntityKey is currently active or not.
*
* @param entityKey the EntityKey of the Entity to check
* @return true if the Entity of a given EntityKey is currently active */
public boolean isActive(final EntityKey entityKey) {
final ActivatableEntityDAO<?, ?> activatableEntityDAO = this.activatableDAOs.get(entityKey.entityType);
if (activatableEntityDAO == null) {

View file

@ -240,10 +240,10 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
return Arrays.asList(StringUtils.split(modelIds, Constants.LIST_SEPARATOR_CHAR))
.stream()
.map(modelId -> new EntityKey(modelId, this.entityDAO.entityType()))
.collect(Collectors.toList());
.collect(Collectors.toSet());
})
.flatMap(this.entityDAO::loadEntities)
.flatMap(this.entityDAO::byEntityKeys)
.getOrThrow()
.stream()
.filter(this.authorization::hasReadonlyGrant)

View file

@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
/** Spring MVC controller that defines a revoke token endpoint */
@Controller
@WebServiceProfile
public class RevokeTokenEndpoint {

View file

@ -27,6 +27,7 @@ sebserver.form.validation.fieldError.username.notunique=This Username is already
sebserver.form.validation.fieldError.password.wrong=Old password is wrong
sebserver.form.validation.fieldError.password.mismatch=Re-typed password don't match new password
sebserver.form.validation.fieldError.invalidURL=The input does not match the URL pattern.
sebserver.form.validation.fieldError.exists=This name already exists. Please choose another.
sebserver.error.unexpected=Unexpected Error
sebserver.page.message=Information
sebserver.dialog.confirm.title=Confirmation