check right privileges batch actions and code cleanup
This commit is contained in:
parent
01bd5c5558
commit
6cc2f7b84b
13 changed files with 87 additions and 20 deletions
|
@ -34,10 +34,10 @@ public class BatchAction implements GrantEntity {
|
|||
|
||||
public static final String ATTR_FAILURES = "failures";
|
||||
public static final String FINISHED_FLAG = "_FINISHED";
|
||||
public static final String ACTION_ATTRIBUT_TARGET_STATE = "batchActionTargetState";
|
||||
public static final String ACTION_ATTRIBUTE_TARGET_STATE = "batchActionTargetState";
|
||||
|
||||
private static final Set<String> ACTION_ATTRIBUTES = new HashSet<>(Arrays.asList(
|
||||
ACTION_ATTRIBUT_TARGET_STATE));
|
||||
ACTION_ATTRIBUTE_TARGET_STATE));
|
||||
|
||||
@JsonProperty(BATCH_ACTION.ATTR_ID)
|
||||
public final Long id;
|
||||
|
|
|
@ -112,7 +112,7 @@ public class SEBExamConfigBatchStateChangePopup extends AbstractBatchActionWizar
|
|||
throw new IllegalArgumentException("missing " + ATTR_SELECTED_TARGET_STATE + " from pageContext");
|
||||
}
|
||||
|
||||
batchActionRequestBuilder.withFormParam(BatchAction.ACTION_ATTRIBUT_TARGET_STATE, targetStateName);
|
||||
batchActionRequestBuilder.withFormParam(BatchAction.ACTION_ATTRIBUTE_TARGET_STATE, targetStateName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,11 +18,11 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
|
||||
|
||||
/** A service to check authorization grants for a given user for entity-types and -instances
|
||||
* <p>
|
||||
|
@ -249,6 +249,34 @@ public interface AuthorizationService {
|
|||
return check(PrivilegeType.WRITE, entity);
|
||||
}
|
||||
|
||||
default <E extends GrantEntity> Result<E> checkForUser(
|
||||
final PrivilegeType privilegeType,
|
||||
final E entity,
|
||||
final String ownerId) {
|
||||
|
||||
final UserInfo userInfo = getUserService().getUser(ownerId);
|
||||
if (userInfo == null) {
|
||||
return Result.ofError(new ResourceNotFoundException(EntityType.USER, ownerId));
|
||||
}
|
||||
|
||||
if (!hasGrant(
|
||||
privilegeType,
|
||||
entity.entityType(),
|
||||
entity.getInstitutionId(),
|
||||
entity.getOwnerId(),
|
||||
userInfo.uuid,
|
||||
userInfo.institutionId,
|
||||
userInfo.getUserRoles())) {
|
||||
|
||||
throw new PermissionDeniedException(
|
||||
entity,
|
||||
privilegeType,
|
||||
getUserService().getCurrentUser().getUserInfo().uuid);
|
||||
}
|
||||
|
||||
return Result.of(entity);
|
||||
}
|
||||
|
||||
/** Checks if the current user has a specified role.
|
||||
* If not a PermissionDeniedException is thrown for the given EntityType
|
||||
*
|
||||
|
@ -274,5 +302,4 @@ public interface AuthorizationService {
|
|||
currentUser.getUserInfo());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
|||
|
||||
import java.security.Principal;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
||||
|
@ -60,4 +60,10 @@ public interface UserService {
|
|||
* @param authentication the Authentication context*/
|
||||
void setAuthenticationIfAbsent(Authentication authentication);
|
||||
|
||||
/** Gets the user for model id / uuid or null if not exists or not active
|
||||
*
|
||||
* @param userId The user uuid
|
||||
* @return UserInfo for the user
|
||||
*/
|
||||
UserInfo getUser(String userId);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ import java.util.Set;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -279,6 +283,8 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private PrivilegeBuilder addPrivilege(final EntityType entityType) {
|
||||
return new PrivilegeBuilder(entityType);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -37,6 +38,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
|||
public class UserServiceImpl implements UserService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
|
||||
private final UserDAO userDAO;
|
||||
|
||||
|
||||
public interface ExtractUserFromAuthenticationStrategy {
|
||||
|
@ -45,8 +47,11 @@ public class UserServiceImpl implements UserService {
|
|||
|
||||
private final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies;
|
||||
|
||||
public UserServiceImpl(final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies) {
|
||||
public UserServiceImpl(
|
||||
final UserDAO userDAO,
|
||||
final Collection<ExtractUserFromAuthenticationStrategy> extractStrategies) {
|
||||
|
||||
this.userDAO = userDAO;
|
||||
this.extractStrategies = extractStrategies;
|
||||
}
|
||||
|
||||
|
@ -108,6 +113,21 @@ public class UserServiceImpl implements UserService {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserInfo getUser(final String userId) {
|
||||
final UserInfo user = this.userDAO
|
||||
.byModelId(userId)
|
||||
.onError(error -> log.error("Failed to find user for id: {} error: {}", userId, error.getMessage()))
|
||||
.getOr(null);
|
||||
|
||||
if (user != null && !user.isActive()) {
|
||||
log.warn("Try to get inactive user for processing: {}", userId);
|
||||
return null;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
// 1. OAuth2Authentication strategy
|
||||
@Lazy
|
||||
@Component
|
||||
|
|
|
@ -29,7 +29,7 @@ public interface BatchActionExec {
|
|||
* This shall check whether the needed attributes are available for a proper processing of the actions.
|
||||
* This is called just before a new batch action is created and processing is started.
|
||||
*
|
||||
* @param batchAction
|
||||
* @param actionAttributes all attributes for batch action
|
||||
* @return APIMessage if there is an consistency failure */
|
||||
APIMessage checkConsistency(Map<String, String> actionAttributes);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ public interface BatchActionService {
|
|||
|
||||
/** Validates a given batch action.
|
||||
*
|
||||
* @param batchAction
|
||||
* @param batchAction the batch action data
|
||||
* @return Result refer to the BatchAction or to an error when happened */
|
||||
Result<BatchAction> validate(BatchAction batchAction);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Collection;
|
|||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -86,7 +87,7 @@ public class DeleteExamAction implements BatchActionExec {
|
|||
@Transactional
|
||||
public Result<EntityKey> doSingleAction(final String modelId, final BatchAction batchAction) {
|
||||
return this.examDAO.byModelId(modelId)
|
||||
.flatMap(this::checkWriteAccess)
|
||||
.flatMap( exam -> this.checkWriteAccess(exam, batchAction.ownerId))
|
||||
.flatMap(this::checkNoActiveSEBClientConnections)
|
||||
.flatMap(this::deleteExamDependencies)
|
||||
.flatMap(this::deleteExamWithRefs)
|
||||
|
@ -137,7 +138,7 @@ public class DeleteExamAction implements BatchActionExec {
|
|||
}
|
||||
}
|
||||
|
||||
private Result<Exam> checkWriteAccess(final Exam entity) {
|
||||
private Result<Exam> checkWriteAccess(final Exam entity, final String ownerId) {
|
||||
if (entity != null) {
|
||||
this.authorization.checkWrite(entity);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl;
|
|||
import ch.ethz.seb.sebserver.gbl.api.API.BatchActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.BatchAction;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
@ -21,7 +20,6 @@ import org.springframework.stereotype.Component;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
|
@ -58,17 +56,24 @@ public class ExamConfigDelete implements BatchActionExec {
|
|||
public Result<EntityKey> doSingleAction(final String modelId, final BatchAction batchAction) {
|
||||
return this.configurationNodeDAO
|
||||
.byModelId(modelId)
|
||||
.flatMap(examConfig -> this.authorizationService.check(PrivilegeType.MODIFY, examConfig))
|
||||
.flatMap(examConfig -> checkDeletionRequirements(examConfig))
|
||||
.flatMap(examConfig -> this.checkWriteAccess(examConfig, batchAction.ownerId))
|
||||
.flatMap(this::checkDeletionRequirements)
|
||||
.flatMap(examConfig -> this.configurationNodeDAO.delete(new HashSet<>(Arrays.asList(new EntityKey(
|
||||
modelId,
|
||||
EntityType.CONFIGURATION_NODE))))
|
||||
)
|
||||
.map(res -> res.stream().collect(Collectors.toList()).get(0));
|
||||
.map(res -> res.stream().toList().get(0));
|
||||
}
|
||||
|
||||
private Result<ConfigurationNode> checkDeletionRequirements(ConfigurationNode examConfig){
|
||||
Result<Boolean> isNotActive = this.examConfigurationMapDAO.checkNoActiveExamReferences(examConfig.id);
|
||||
private Result<ConfigurationNode> checkWriteAccess(final ConfigurationNode examConfig, final String ownerId) {
|
||||
if (examConfig != null) {
|
||||
this.authorizationService.checkWrite(examConfig);
|
||||
}
|
||||
return Result.of(examConfig);
|
||||
}
|
||||
|
||||
private Result<ConfigurationNode> checkDeletionRequirements(final ConfigurationNode examConfig){
|
||||
final Result<Boolean> isNotActive = this.examConfigurationMapDAO.checkNoActiveExamReferences(examConfig.id);
|
||||
if(!isNotActive.getOrThrow()){
|
||||
return Result.ofError(new APIMessageException(
|
||||
APIMessage.ErrorMessage.INTEGRITY_VALIDATION
|
||||
|
|
|
@ -83,7 +83,7 @@ public class ExamConfigStateChange implements BatchActionExec {
|
|||
|
||||
private ConfigurationStatus getTargetState(final Map<String, String> actionAttributes) {
|
||||
try {
|
||||
final String targetStateString = actionAttributes.get(BatchAction.ACTION_ATTRIBUT_TARGET_STATE);
|
||||
final String targetStateString = actionAttributes.get(BatchAction.ACTION_ATTRIBUTE_TARGET_STATE);
|
||||
if (StringUtils.isBlank(targetStateString)) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -245,6 +245,8 @@ sebserver.useraccount.role.EXAM_ADMIN=Exam Administrator
|
|||
sebserver.useraccount.role.EXAM_ADMIN.tooltip=An exam administrator has overall read privileges for the institution but cannot see or manage other user accounts.<br/>An exam administrator is able to create new SEB configurations and import and setup exams.
|
||||
sebserver.useraccount.role.EXAM_SUPPORTER=Exam Supporter
|
||||
sebserver.useraccount.role.EXAM_SUPPORTER.tooltip=An exam supporter can only see and edit the own user account<br/> and monitor exams for that he/she was attached by an exam administrator.
|
||||
sebserver.useraccount.role.TEACHER=Teacher
|
||||
sebserver.useraccount.role.TEACHER.tooltip=A teacher can only see and edit the own user account<br/> and monitor exams for that he/she has been imported or was attached by an exam administrator
|
||||
|
||||
sebserver.useraccount.list.empty=No user account can be found. Please adapt the filter or create a new user account
|
||||
sebserver.useraccount.list.title=User Accounts
|
||||
|
|
|
@ -4032,7 +4032,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
|
|||
.getBuilder(DoBatchAction.class)
|
||||
.withFormParam(Domain.BATCH_ACTION.ATTR_ACTION_TYPE, BatchActionType.EXAM_CONFIG_STATE_CHANGE.name())
|
||||
.withFormParam(BATCH_ACTION.ATTR_SOURCE_IDS, config.getModelId())
|
||||
.withFormParam(BatchAction.ACTION_ATTRIBUT_TARGET_STATE, ConfigurationStatus.CONSTRUCTION.name())
|
||||
.withFormParam(BatchAction.ACTION_ATTRIBUTE_TARGET_STATE, ConfigurationStatus.CONSTRUCTION.name())
|
||||
.call();
|
||||
|
||||
assertNotNull(doBatchAction);
|
||||
|
|
Loading…
Reference in a new issue