SEBSERV-155 implementation
This commit is contained in:
parent
7817ed48c4
commit
69c9de6d64
5 changed files with 51 additions and 39 deletions
|
@ -301,6 +301,9 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
.newAction(ActionDefinition.EXAM_VIEW_LIST)
|
.newAction(ActionDefinition.EXAM_VIEW_LIST)
|
||||||
.create());
|
.create());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM_TEMPLATE)) {
|
||||||
// Exam Template
|
// Exam Template
|
||||||
final TreeItem examTemplate = this.widgetFactory.treeItemLocalized(
|
final TreeItem examTemplate = this.widgetFactory.treeItemLocalized(
|
||||||
examAdmin,
|
examAdmin,
|
||||||
|
@ -310,7 +313,6 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
actionBuilder
|
actionBuilder
|
||||||
.newAction(ActionDefinition.EXAM_TEMPLATE_VIEW_LIST)
|
.newAction(ActionDefinition.EXAM_TEMPLATE_VIEW_LIST)
|
||||||
.create());
|
.create());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
examAdmin.setExpanded(this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN));
|
examAdmin.setExpanded(this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN));
|
||||||
|
@ -322,7 +324,8 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
// ---- MONITORING ---------------------------------------------------------------------
|
// ---- MONITORING ---------------------------------------------------------------------
|
||||||
|
|
||||||
final boolean isSupporter = this.currentUser.get().hasAnyRole(UserRole.EXAM_SUPPORTER);
|
final boolean isSupporter = this.currentUser.get().hasAnyRole(UserRole.EXAM_SUPPORTER) ||
|
||||||
|
this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN);
|
||||||
final boolean viewSEBClientLogs = this.currentUser.hasInstitutionalPrivilege(
|
final boolean viewSEBClientLogs = this.currentUser.hasInstitutionalPrivilege(
|
||||||
PrivilegeType.READ,
|
PrivilegeType.READ,
|
||||||
EntityType.EXAM) ||
|
EntityType.EXAM) ||
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
@ -32,6 +33,7 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
@ -171,6 +173,10 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
.call()
|
.call()
|
||||||
.onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error))
|
.onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
final UserInfo user = currentUser.get();
|
||||||
|
final boolean supporting = user.hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||||
|
exam.supporter.contains(user.uuid);
|
||||||
|
final BooleanSupplier isExamSupporter = () -> supporting || user.hasRole(UserRole.EXAM_ADMIN);
|
||||||
|
|
||||||
final Collection<Indicator> indicators = restService.getBuilder(GetIndicators.class)
|
final Collection<Indicator> indicators = restService.getBuilder(GetIndicators.class)
|
||||||
.withQueryParam(Indicator.FILTER_ATTR_EXAM_ID, parentEntityKey.modelId)
|
.withQueryParam(Indicator.FILTER_ATTR_EXAM_ID, parentEntityKey.modelId)
|
||||||
|
@ -260,7 +266,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
|
|
||||||
NOTIFICATION_LIST_NO_SELECTION_KEY)
|
NOTIFICATION_LIST_NO_SELECTION_KEY)
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER), false);
|
.publishIf(isExamSupporter, false);
|
||||||
|
|
||||||
_notificationTableSupplier = () -> notificationTable;
|
_notificationTableSupplier = () -> notificationTable;
|
||||||
}
|
}
|
||||||
|
@ -353,7 +359,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
actionBuilder
|
actionBuilder
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_BACK_TO_OVERVIEW)
|
.newAction(ActionDefinition.MONITOR_EXAM_BACK_TO_OVERVIEW)
|
||||||
.withEntityKey(parentEntityKey)
|
.withEntityKey(parentEntityKey)
|
||||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER))
|
.publishIf(isExamSupporter)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_QUIT)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_QUIT)
|
||||||
.withConfirm(() -> CONFIRM_QUIT)
|
.withConfirm(() -> CONFIRM_QUIT)
|
||||||
|
@ -365,7 +371,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
return action;
|
return action;
|
||||||
})
|
})
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER) &&
|
.publishIf(() -> isExamSupporter.getAsBoolean() &&
|
||||||
connectionData.clientConnection.status.clientActiveStatus);
|
connectionData.clientConnection.status.clientActiveStatus);
|
||||||
|
|
||||||
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringFeature;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
|
@ -130,6 +131,10 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
.call()
|
.call()
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
final UserInfo user = currentUser.get();
|
||||||
|
final boolean supporting = user.hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||||
|
exam.supporter.contains(user.uuid);
|
||||||
|
final BooleanSupplier isExamSupporter = () -> supporting || user.hasRole(UserRole.EXAM_ADMIN);
|
||||||
|
|
||||||
final Collection<Indicator> indicators = restService.getBuilder(GetIndicators.class)
|
final Collection<Indicator> indicators = restService.getBuilder(GetIndicators.class)
|
||||||
.withQueryParam(Indicator.FILTER_ATTR_EXAM_ID, entityKey.modelId)
|
.withQueryParam(Indicator.FILTER_ATTR_EXAM_ID, entityKey.modelId)
|
||||||
|
@ -191,8 +196,6 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
context -> clientTable.updateValues(),
|
context -> clientTable.updateValues(),
|
||||||
updateTableGUI(clientTable));
|
updateTableGUI(clientTable));
|
||||||
|
|
||||||
final BooleanSupplier isExamSupporter = () -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER);
|
|
||||||
|
|
||||||
actionBuilder
|
actionBuilder
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
||||||
|
|
|
@ -132,8 +132,6 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
||||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||||
.andForRole(UserRole.EXAM_ADMIN)
|
.andForRole(UserRole.EXAM_ADMIN)
|
||||||
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
|
||||||
.withOwnerPrivilege(PrivilegeType.MODIFY)
|
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
// grants for configuration node
|
// grants for configuration node
|
||||||
|
|
|
@ -41,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||||
|
@ -129,7 +130,8 @@ public class ExamMonitoringController {
|
||||||
this.authorization.checkRole(
|
this.authorization.checkRole(
|
||||||
institutionId,
|
institutionId,
|
||||||
EntityType.EXAM,
|
EntityType.EXAM,
|
||||||
UserRole.EXAM_SUPPORTER);
|
UserRole.EXAM_SUPPORTER,
|
||||||
|
UserRole.EXAM_ADMIN);
|
||||||
|
|
||||||
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
|
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
|
||||||
|
|
||||||
|
@ -166,19 +168,7 @@ public class ExamMonitoringController {
|
||||||
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
||||||
@RequestHeader(name = API.EXAM_MONITORING_STATE_FILTER, required = false) final String hiddenStates) {
|
@RequestHeader(name = API.EXAM_MONITORING_STATE_FILTER, required = false) final String hiddenStates) {
|
||||||
|
|
||||||
// check overall privilege
|
checkPrivileges(institutionId, examId);
|
||||||
this.authorization.checkRole(
|
|
||||||
institutionId,
|
|
||||||
EntityType.EXAM,
|
|
||||||
UserRole.EXAM_SUPPORTER);
|
|
||||||
|
|
||||||
// check running exam privilege for specified exam
|
|
||||||
if (!hasRunningExamPrivilege(examId, institutionId)) {
|
|
||||||
throw new PermissionDeniedException(
|
|
||||||
EntityType.EXAM,
|
|
||||||
PrivilegeType.READ,
|
|
||||||
this.authorization.getUserService().getCurrentUser().getUserInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
final EnumSet<ConnectionStatus> filterStates = EnumSet.noneOf(ConnectionStatus.class);
|
final EnumSet<ConnectionStatus> filterStates = EnumSet.noneOf(ConnectionStatus.class);
|
||||||
if (StringUtils.isNoneBlank(hiddenStates)) {
|
if (StringUtils.isNoneBlank(hiddenStates)) {
|
||||||
|
@ -211,20 +201,7 @@ public class ExamMonitoringController {
|
||||||
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
||||||
@PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
|
@PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
|
||||||
|
|
||||||
// check overall privilege
|
checkPrivileges(institutionId, examId);
|
||||||
this.authorization.checkRole(
|
|
||||||
institutionId,
|
|
||||||
EntityType.EXAM,
|
|
||||||
UserRole.EXAM_SUPPORTER);
|
|
||||||
|
|
||||||
// check running exam privilege for specified exam
|
|
||||||
if (!hasRunningExamPrivilege(examId, institutionId)) {
|
|
||||||
throw new PermissionDeniedException(
|
|
||||||
EntityType.EXAM,
|
|
||||||
PrivilegeType.READ,
|
|
||||||
this.authorization.getUserService().getCurrentUser().getUserInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.examSessionService
|
return this.examSessionService
|
||||||
.getConnectionData(connectionToken)
|
.getConnectionData(connectionToken)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
@ -243,6 +220,7 @@ public class ExamMonitoringController {
|
||||||
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
||||||
@Valid @RequestBody final ClientInstruction clientInstruction) {
|
@Valid @RequestBody final ClientInstruction clientInstruction) {
|
||||||
|
|
||||||
|
checkPrivileges(institutionId, examId);
|
||||||
this.sebClientInstructionService.registerInstruction(clientInstruction);
|
this.sebClientInstructionService.registerInstruction(clientInstruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +239,8 @@ public class ExamMonitoringController {
|
||||||
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId,
|
||||||
@PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
|
@PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
|
||||||
|
|
||||||
|
checkPrivileges(institutionId, examId);
|
||||||
|
|
||||||
final ClientConnectionData connection = getConnectionDataForSingleConnection(
|
final ClientConnectionData connection = getConnectionDataForSingleConnection(
|
||||||
institutionId,
|
institutionId,
|
||||||
examId,
|
examId,
|
||||||
|
@ -286,6 +266,7 @@ public class ExamMonitoringController {
|
||||||
@PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long notificationId,
|
@PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long notificationId,
|
||||||
@PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
|
@PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
|
||||||
|
|
||||||
|
checkPrivileges(institutionId, examId);
|
||||||
this.sebClientNotificationService.confirmPendingNotification(
|
this.sebClientNotificationService.confirmPendingNotification(
|
||||||
notificationId,
|
notificationId,
|
||||||
examId,
|
examId,
|
||||||
|
@ -308,6 +289,8 @@ public class ExamMonitoringController {
|
||||||
name = Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN,
|
name = Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN,
|
||||||
required = true) final String connectionToken) {
|
required = true) final String connectionToken) {
|
||||||
|
|
||||||
|
checkPrivileges(institutionId, examId);
|
||||||
|
|
||||||
if (connectionToken.contains(Constants.LIST_SEPARATOR)) {
|
if (connectionToken.contains(Constants.LIST_SEPARATOR)) {
|
||||||
final String[] tokens = StringUtils.split(connectionToken, Constants.LIST_SEPARATOR);
|
final String[] tokens = StringUtils.split(connectionToken, Constants.LIST_SEPARATOR);
|
||||||
for (int i = 0; i < tokens.length; i++) {
|
for (int i = 0; i < tokens.length; i++) {
|
||||||
|
@ -322,6 +305,23 @@ public class ExamMonitoringController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkPrivileges(final Long institutionId, final Long examId) {
|
||||||
|
// check overall privilege
|
||||||
|
this.authorization.checkRole(
|
||||||
|
institutionId,
|
||||||
|
EntityType.EXAM,
|
||||||
|
UserRole.EXAM_SUPPORTER,
|
||||||
|
UserRole.EXAM_ADMIN);
|
||||||
|
|
||||||
|
// check running exam privilege for specified exam
|
||||||
|
if (!hasRunningExamPrivilege(examId, institutionId)) {
|
||||||
|
throw new PermissionDeniedException(
|
||||||
|
EntityType.EXAM,
|
||||||
|
PrivilegeType.READ,
|
||||||
|
this.authorization.getUserService().getCurrentUser().getUserInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasRunningExamPrivilege(final Long examId, final Long institution) {
|
private boolean hasRunningExamPrivilege(final Long examId, final Long institution) {
|
||||||
return hasRunningExamPrivilege(
|
return hasRunningExamPrivilege(
|
||||||
this.examSessionService.getRunningExam(examId).getOr(null),
|
this.examSessionService.getRunningExam(examId).getOr(null),
|
||||||
|
@ -333,8 +333,10 @@ public class ExamMonitoringController {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String userId = this.authorization.getUserService().getCurrentUser().getUserInfo().uuid;
|
final UserInfo userInfo = this.authorization.getUserService().getCurrentUser().getUserInfo();
|
||||||
return exam.institutionId.equals(institution) && exam.isOwner(userId);
|
final String userId = userInfo.uuid;
|
||||||
|
return exam.institutionId.equals(institution)
|
||||||
|
&& (exam.isOwner(userId) || userInfo.hasRole(UserRole.EXAM_ADMIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue