Merge branch 'development' of github.com:SafeExamBrowser/seb-server into SEBSERV-398
This commit is contained in:
commit
f187582a2b
35 changed files with 407 additions and 253 deletions
|
@ -27,15 +27,20 @@ public class UserFeatures {
|
||||||
CONFIG_CERTIFICATE("config.certificate"),
|
CONFIG_CERTIFICATE("config.certificate"),
|
||||||
LMS_SETUP( "lms.setup"),
|
LMS_SETUP( "lms.setup"),
|
||||||
LMS_SETUP_TEST("lms.setup.type.MOCKUP"),
|
LMS_SETUP_TEST("lms.setup.type.MOCKUP"),
|
||||||
LMS_SETUP_MOODLE("lms.setup.type.moodle"),
|
LMS_SETUP_MOODLE("lms.setup.type.MOODLE"),
|
||||||
LMS_SETUP_MOODLE_PLUGIN("lms.setup.type.moodle.plugin"),
|
LMS_SETUP_MOODLE_PLUGIN("lms.setup.type.MOODLE_PLUGIN"),
|
||||||
LMS_SETUP_OPEN_EDX("lms.setup.type.openedx"),
|
LMS_SETUP_OPEN_EDX("lms.setup.type.OPEN_EDX"),
|
||||||
LMS_SETUP_ANS("lms.setup.type.ans"),
|
LMS_SETUP_ANS("lms.setup.type.ANS_DELFT"),
|
||||||
LMS_SETUP_OPEN_OLAT("lms.setup.type.openolat"),
|
LMS_SETUP_OPEN_OLAT("lms.setup.type.OPEN_OLAT"),
|
||||||
|
|
||||||
|
QUIZ_LOOKUP("lms.quiz.lookup"),
|
||||||
|
|
||||||
|
EXAM_ADMIN("exam.administration"),
|
||||||
EXAM_ASK("exam.ask"),
|
EXAM_ASK("exam.ask"),
|
||||||
|
EXAM_CONNECTION_CONFIG("exam.connection.config"),
|
||||||
EXAM_SEB_RESTRICTION( "exam.seb.restriction"),
|
EXAM_SEB_RESTRICTION( "exam.seb.restriction"),
|
||||||
EXAM_LIVE_PROCTORING("exam.seb.liveProctoring"),
|
EXAM_LIVE_PROCTORING("exam.seb.liveProctoring"),
|
||||||
|
EXAM_NO_LMS("exam.noLMS"),
|
||||||
|
|
||||||
EXAM_SCREEN_PROCTORING("exam.seb.screenProctoring"),
|
EXAM_SCREEN_PROCTORING("exam.seb.screenProctoring"),
|
||||||
EXAM_INDICATORS("exam.monitoring.indicators"),
|
EXAM_INDICATORS("exam.monitoring.indicators"),
|
||||||
|
@ -46,16 +51,22 @@ public class UserFeatures {
|
||||||
MONITORING_RUNNING_EXAM_DETAIL_VIEW("monitoring.running.exam.detailview"),
|
MONITORING_RUNNING_EXAM_DETAIL_VIEW("monitoring.running.exam.detailview"),
|
||||||
MONITORING_RUNNING_EXAM_DETAIL_VIEW_LOG_EXPORT("monitoring.running.exam.detailview.logexport"),
|
MONITORING_RUNNING_EXAM_DETAIL_VIEW_LOG_EXPORT("monitoring.running.exam.detailview.logexport"),
|
||||||
//more? ...
|
//more? ...
|
||||||
MONITORING_RUNNING_EXAM_QUIT_ALL("monitoring.running.exam.quitall"),
|
MONITORING_RUNNING_EXAM_QUIT("monitoring.running.exam.quit"),
|
||||||
|
|
||||||
MONITORING_RUNNING_EXAM_LOCKSCREEN("monitoring.running.exam.lockscreen"),
|
MONITORING_RUNNING_EXAM_LOCKSCREEN("monitoring.running.exam.lockscreen"),
|
||||||
// more? ...
|
|
||||||
|
MONITORING_RUNNING_EXAM_CANCEL_CON("monitoring.running.exam.cancel.connection"),
|
||||||
|
|
||||||
|
MONITORING_RUNNING_EXAM_STATE_FILTER("monitoring.running.exam.state.filter"),
|
||||||
|
MONITORING_RUNNING_EXAM_ISSUE_FILTER("monitoring.running.exam.issue.filter"),
|
||||||
|
MONITORING_RUNNING_EXAM_CLIENT_FILTER("monitoring.running.exam.client.filter"),
|
||||||
|
MONITORING_RUNNING_EXAM_LIVE_PROCTORING("monitoring.running.exam.live.proctoring"),
|
||||||
|
MONITORING_RUNNING_EXAM_SCREEN_PROCTORING("monitoring.running.exam.screen.proctoring"),
|
||||||
MONITORING_FINISHED_EXAMS("monitoring.finished.exams"),
|
MONITORING_FINISHED_EXAMS("monitoring.finished.exams"),
|
||||||
MONITORING_OVERALL_LOG_EXPORT("monitoring.overall.export"),
|
MONITORING_OVERALL_LOG_EXPORT("monitoring.overall.export"),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXAM_NO_LMS("exam.noLMS"),
|
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
public final String featureName;
|
public final String featureName;
|
||||||
|
|
|
@ -67,7 +67,6 @@ public class LoginPage implements TemplateComposer {
|
||||||
this.i18nSupport = pageService.getI18nSupport();
|
this.i18nSupport = pageService.getI18nSupport();
|
||||||
this.defaultRegisterPage = defaultRegisterPage;
|
this.defaultRegisterPage = defaultRegisterPage;
|
||||||
this.registeringEnabled = BooleanUtils.toBoolean(registeringEnabled);
|
this.registeringEnabled = BooleanUtils.toBoolean(registeringEnabled);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -133,7 +132,7 @@ public class LoginPage implements TemplateComposer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.registeringEnabled) {
|
if (this.registeringEnabled && !pageService.isLightSetup()) {
|
||||||
final Button registerButton = this.widgetFactory.buttonLocalized(buttons, TEXT_REGISTER);
|
final Button registerButton = this.widgetFactory.buttonLocalized(buttons, TEXT_REGISTER);
|
||||||
gridData = new GridData(SWT.LEFT, SWT.TOP, false, false);
|
gridData = new GridData(SWT.LEFT, SWT.TOP, false, false);
|
||||||
gridData.verticalIndent = 10;
|
gridData.verticalIndent = 10;
|
||||||
|
|
|
@ -135,7 +135,9 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
|
|
||||||
// User Account
|
// User Account
|
||||||
// if current user has role seb-server admin or institutional-admin, show list
|
// if current user has role seb-server admin or institutional-admin, show list
|
||||||
if (isServerOrInstAdmin && !pageService.isSEBServerLightSetup()) {
|
if (isServerOrInstAdmin
|
||||||
|
&& !pageService.isLightSetup()
|
||||||
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_USER_ADMINISTRATION)) {
|
||||||
|
|
||||||
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
||||||
sebAdmin,
|
sebAdmin,
|
||||||
|
@ -145,15 +147,15 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
actionBuilder
|
actionBuilder
|
||||||
.newAction(ActionDefinition.USER_ACCOUNT_VIEW_LIST)
|
.newAction(ActionDefinition.USER_ACCOUNT_VIEW_LIST)
|
||||||
.create());
|
.create());
|
||||||
} else {
|
} else if (currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_USER_ACCOUNT)) {
|
||||||
// otherwise show the user account form for current user
|
// otherwise show the user account form for current user
|
||||||
final TreeItem userAccounts = pageService.isSEBServerLightSetup()
|
final TreeItem userAccounts = pageService.isLightSetup() || !currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_USER_ADMINISTRATION)
|
||||||
? this.widgetFactory.treeItemLocalized(
|
? this.widgetFactory.treeItemLocalized(
|
||||||
sebAdmin,
|
sebAdmin,
|
||||||
ActivityDefinition.USER_ACCOUNT.displayName)
|
ActivityDefinition.USER_ACCOUNT.displayName)
|
||||||
: this.widgetFactory.treeItemLocalized(
|
: this.widgetFactory.treeItemLocalized(
|
||||||
navigation,
|
navigation,
|
||||||
ActivityDefinition.USER_ACCOUNT.displayName);
|
ActivityDefinition.USER_ACCOUNT.displayName);
|
||||||
injectActivitySelection(
|
injectActivitySelection(
|
||||||
userAccounts,
|
userAccounts,
|
||||||
actionBuilder.newAction(ActionDefinition.USER_ACCOUNT_VIEW_FORM)
|
actionBuilder.newAction(ActionDefinition.USER_ACCOUNT_VIEW_FORM)
|
||||||
|
@ -165,7 +167,8 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
// User Activity Logs
|
// User Activity Logs
|
||||||
final boolean viewUserActivityLogs = this.currentUser.hasInstitutionalPrivilege(
|
final boolean viewUserActivityLogs = this.currentUser.hasInstitutionalPrivilege(
|
||||||
PrivilegeType.READ,
|
PrivilegeType.READ,
|
||||||
EntityType.USER_ACTIVITY_LOG);
|
EntityType.USER_ACTIVITY_LOG)
|
||||||
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_AUDIT_LOGS);
|
||||||
if (viewUserActivityLogs) {
|
if (viewUserActivityLogs) {
|
||||||
final TreeItem activityLogs = this.widgetFactory.treeItemLocalized(
|
final TreeItem activityLogs = this.widgetFactory.treeItemLocalized(
|
||||||
sebAdmin,
|
sebAdmin,
|
||||||
|
@ -201,13 +204,19 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
PrivilegeType.READ,
|
PrivilegeType.READ,
|
||||||
EntityType.CONFIGURATION_NODE);
|
EntityType.CONFIGURATION_NODE);
|
||||||
|
|
||||||
if ((clientConfigRead || examConfigRead) && !isSupporterOnly) {
|
final boolean connConfigEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.CONFIG_CONNECTION_CONFIGURATION);
|
||||||
|
final boolean examConfigEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.CONFIG_EXAM_CONFIGURATION);
|
||||||
|
final boolean templateEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.CONFIG_TEMPLATE);
|
||||||
|
final boolean certificatesEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.CONFIG_CERTIFICATE);
|
||||||
|
final boolean anyEnabled = connConfigEnabled || examConfigEnabled || templateEnabled || certificatesEnabled;
|
||||||
|
|
||||||
|
if (anyEnabled && (clientConfigRead || examConfigRead) && !isSupporterOnly) {
|
||||||
final TreeItem sebConfigs = this.widgetFactory.treeItemLocalized(
|
final TreeItem sebConfigs = this.widgetFactory.treeItemLocalized(
|
||||||
navigation,
|
navigation,
|
||||||
ActivityDefinition.SEB_CONFIGURATION.displayName);
|
ActivityDefinition.SEB_CONFIGURATION.displayName);
|
||||||
|
|
||||||
// SEB Client Config
|
// SEB Client Config
|
||||||
if (clientConfigRead) {
|
if (clientConfigRead && connConfigEnabled) {
|
||||||
final TreeItem clientConfig = this.widgetFactory.treeItemLocalized(
|
final TreeItem clientConfig = this.widgetFactory.treeItemLocalized(
|
||||||
sebConfigs,
|
sebConfigs,
|
||||||
ActivityDefinition.SEB_CLIENT_CONFIG.displayName);
|
ActivityDefinition.SEB_CLIENT_CONFIG.displayName);
|
||||||
|
@ -219,7 +228,7 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEB Exam Config
|
// SEB Exam Config
|
||||||
if (examConfigRead) {
|
if (examConfigRead && examConfigEnabled) {
|
||||||
final TreeItem examConfig = this.widgetFactory.treeItemLocalized(
|
final TreeItem examConfig = this.widgetFactory.treeItemLocalized(
|
||||||
sebConfigs,
|
sebConfigs,
|
||||||
ActivityDefinition.SEB_EXAM_CONFIG.displayName);
|
ActivityDefinition.SEB_EXAM_CONFIG.displayName);
|
||||||
|
@ -231,7 +240,7 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEB Exam Config Template
|
// SEB Exam Config Template
|
||||||
if (examConfigRead) {
|
if (examConfigRead && templateEnabled) {
|
||||||
final TreeItem examConfigTemplate = this.widgetFactory.treeItemLocalized(
|
final TreeItem examConfigTemplate = this.widgetFactory.treeItemLocalized(
|
||||||
sebConfigs,
|
sebConfigs,
|
||||||
ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE.displayName);
|
ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE.displayName);
|
||||||
|
@ -243,7 +252,7 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certificate management
|
// Certificate management
|
||||||
if (!isSupporterOnly) {
|
if (!isSupporterOnly && certificatesEnabled) {
|
||||||
final TreeItem examConfigTemplate = this.widgetFactory.treeItemLocalized(
|
final TreeItem examConfigTemplate = this.widgetFactory.treeItemLocalized(
|
||||||
sebConfigs,
|
sebConfigs,
|
||||||
ActivityDefinition.SEB_CERTIFICATE_MANAGEMENT.displayName);
|
ActivityDefinition.SEB_CERTIFICATE_MANAGEMENT.displayName);
|
||||||
|
@ -268,63 +277,73 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM);
|
this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM);
|
||||||
final boolean examWrite = this.currentUser.hasInstitutionalPrivilege(PrivilegeType.WRITE, EntityType.EXAM);
|
final boolean examWrite = this.currentUser.hasInstitutionalPrivilege(PrivilegeType.WRITE, EntityType.EXAM);
|
||||||
|
|
||||||
// Exam Administration
|
final boolean lmsSetupEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.LMS_SETUP);
|
||||||
final TreeItem examAdmin = this.widgetFactory.treeItemLocalized(
|
final boolean quizLookupEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.QUIZ_LOOKUP);
|
||||||
navigation,
|
final boolean examEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_ADMIN);
|
||||||
ActivityDefinition.EXAM_ADMINISTRATION.displayName);
|
final boolean examTemplateEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_TEMPLATE);
|
||||||
|
final boolean anyExamAdminEnabled = lmsSetupEnabled || quizLookupEnabled || examEnabled || examTemplateEnabled;
|
||||||
|
|
||||||
if (examRead || lmsRead) {
|
if (anyExamAdminEnabled) {
|
||||||
// LMS Setup
|
// Exam Administration
|
||||||
if (lmsRead && !isSupporterOnly) {
|
final TreeItem examAdmin = this.widgetFactory.treeItemLocalized(
|
||||||
final TreeItem lmsSetup = this.widgetFactory.treeItemLocalized(
|
navigation,
|
||||||
examAdmin,
|
ActivityDefinition.EXAM_ADMINISTRATION.displayName);
|
||||||
ActivityDefinition.LMS_SETUP.displayName);
|
|
||||||
injectActivitySelection(
|
|
||||||
lmsSetup,
|
|
||||||
actionBuilder
|
|
||||||
.newAction(ActionDefinition.LMS_SETUP_VIEW_LIST)
|
|
||||||
.create());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (examRead) {
|
if ((examRead || lmsRead) && lmsSetupEnabled) {
|
||||||
|
// LMS Setup
|
||||||
if (examWrite) {
|
if (lmsRead && !isSupporterOnly) {
|
||||||
// Quiz Discovery
|
final TreeItem lmsSetup = this.widgetFactory.treeItemLocalized(
|
||||||
final TreeItem quizDiscovery = this.widgetFactory.treeItemLocalized(
|
|
||||||
examAdmin,
|
examAdmin,
|
||||||
ActivityDefinition.QUIZ_DISCOVERY.displayName);
|
ActivityDefinition.LMS_SETUP.displayName);
|
||||||
injectActivitySelection(
|
injectActivitySelection(
|
||||||
quizDiscovery,
|
lmsSetup,
|
||||||
actionBuilder
|
actionBuilder
|
||||||
.newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
|
.newAction(ActionDefinition.LMS_SETUP_VIEW_LIST)
|
||||||
.create());
|
.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exam
|
if (examRead) {
|
||||||
final TreeItem exam = this.widgetFactory.treeItemLocalized(
|
|
||||||
examAdmin,
|
|
||||||
ActivityDefinition.EXAM.displayName);
|
|
||||||
injectActivitySelection(
|
|
||||||
exam,
|
|
||||||
actionBuilder
|
|
||||||
.newAction(ActionDefinition.EXAM_VIEW_LIST)
|
|
||||||
.create());
|
|
||||||
|
|
||||||
|
if (examWrite && quizLookupEnabled) {
|
||||||
|
// Quiz Discovery
|
||||||
|
final TreeItem quizDiscovery = this.widgetFactory.treeItemLocalized(
|
||||||
|
examAdmin,
|
||||||
|
ActivityDefinition.QUIZ_DISCOVERY.displayName);
|
||||||
|
injectActivitySelection(
|
||||||
|
quizDiscovery,
|
||||||
|
actionBuilder
|
||||||
|
.newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
|
||||||
|
.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (examEnabled) {
|
||||||
|
// Exam
|
||||||
|
final TreeItem exam = this.widgetFactory.treeItemLocalized(
|
||||||
|
examAdmin,
|
||||||
|
ActivityDefinition.EXAM.displayName);
|
||||||
|
injectActivitySelection(
|
||||||
|
exam,
|
||||||
|
actionBuilder
|
||||||
|
.newAction(ActionDefinition.EXAM_VIEW_LIST)
|
||||||
|
.create());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM_TEMPLATE)
|
||||||
|
&& examTemplateEnabled) {
|
||||||
|
// Exam Template
|
||||||
|
final TreeItem examTemplate = this.widgetFactory.treeItemLocalized(
|
||||||
|
examAdmin,
|
||||||
|
ActivityDefinition.EXAM_TEMPLATE.displayName);
|
||||||
|
injectActivitySelection(
|
||||||
|
examTemplate,
|
||||||
|
actionBuilder
|
||||||
|
.newAction(ActionDefinition.EXAM_TEMPLATE_VIEW_LIST)
|
||||||
|
.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
examAdmin.setExpanded(this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM_TEMPLATE)) {
|
|
||||||
// Exam Template
|
|
||||||
final TreeItem examTemplate = this.widgetFactory.treeItemLocalized(
|
|
||||||
examAdmin,
|
|
||||||
ActivityDefinition.EXAM_TEMPLATE.displayName);
|
|
||||||
injectActivitySelection(
|
|
||||||
examTemplate,
|
|
||||||
actionBuilder
|
|
||||||
.newAction(ActionDefinition.EXAM_TEMPLATE_VIEW_LIST)
|
|
||||||
.create());
|
|
||||||
}
|
|
||||||
|
|
||||||
examAdmin.setExpanded(this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- EXAM ADMINISTRATION ------------------------------------------------------------
|
// ---- EXAM ADMINISTRATION ------------------------------------------------------------
|
||||||
|
@ -335,12 +354,15 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
|
|
||||||
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);
|
this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN);
|
||||||
final boolean viewSEBClientLogs = this.currentUser.hasInstitutionalPrivilege(
|
final boolean viewSEBClientLogs =
|
||||||
PrivilegeType.READ,
|
currentUser.isFeatureEnabled(UserFeatures.Feature.MONITORING_OVERALL_LOG_EXPORT)
|
||||||
EntityType.EXAM) ||
|
&& ( this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM)
|
||||||
this.currentUser.get().hasRole(UserRole.EXAM_SUPPORTER);
|
|| this.currentUser.get().hasRole(UserRole.EXAM_SUPPORTER));
|
||||||
|
final boolean monitoringEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.MONITORING_RUNNING_EXAMS);
|
||||||
|
final boolean finishedEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.MONITORING_FINISHED_EXAMS);
|
||||||
|
|
||||||
if (isSupporter || viewSEBClientLogs) {
|
|
||||||
|
if (viewSEBClientLogs || monitoringEnabled || finishedEnabled) {
|
||||||
// Monitoring
|
// Monitoring
|
||||||
final TreeItem monitoring = this.widgetFactory.treeItemLocalized(
|
final TreeItem monitoring = this.widgetFactory.treeItemLocalized(
|
||||||
navigation,
|
navigation,
|
||||||
|
@ -349,24 +371,27 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
// Monitoring exams
|
// Monitoring exams
|
||||||
if (isSupporter) {
|
if (isSupporter) {
|
||||||
|
|
||||||
final TreeItem monitoringExams = this.widgetFactory.treeItemLocalized(
|
if (monitoringEnabled) {
|
||||||
monitoring,
|
final TreeItem monitoringExams = this.widgetFactory.treeItemLocalized(
|
||||||
ActivityDefinition.MONITORING_EXAMS.displayName);
|
monitoring,
|
||||||
injectActivitySelection(
|
ActivityDefinition.MONITORING_EXAMS.displayName);
|
||||||
monitoringExams,
|
injectActivitySelection(
|
||||||
actionBuilder
|
monitoringExams,
|
||||||
.newAction(ActionDefinition.RUNNING_EXAM_VIEW_LIST)
|
actionBuilder
|
||||||
.create());
|
.newAction(ActionDefinition.RUNNING_EXAM_VIEW_LIST)
|
||||||
|
.create());
|
||||||
final TreeItem clientConfig = this.widgetFactory.treeItemLocalized(
|
}
|
||||||
monitoring,
|
|
||||||
ActivityDefinition.FINISHED_EXAMS.displayName);
|
|
||||||
injectActivitySelection(
|
|
||||||
clientConfig,
|
|
||||||
actionBuilder
|
|
||||||
.newAction(ActionDefinition.FINISHED_EXAM_VIEW_LIST)
|
|
||||||
.create());
|
|
||||||
|
|
||||||
|
if (finishedEnabled) {
|
||||||
|
final TreeItem finishedExams = this.widgetFactory.treeItemLocalized(
|
||||||
|
monitoring,
|
||||||
|
ActivityDefinition.FINISHED_EXAMS.displayName);
|
||||||
|
injectActivitySelection(
|
||||||
|
finishedExams,
|
||||||
|
actionBuilder
|
||||||
|
.newAction(ActionDefinition.FINISHED_EXAM_VIEW_LIST)
|
||||||
|
.create());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEB Client Logs
|
// SEB Client Logs
|
||||||
|
@ -434,9 +459,11 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
final PageState state = this.pageService.getCurrentState();
|
final PageState state = this.pageService.getCurrentState();
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
final TreeItem item = getDefaultSelectionFor(navigation, this.currentUser);
|
final TreeItem item = getDefaultSelectionFor(navigation, this.currentUser);
|
||||||
final TreeItem actionItem = getActionItem(item);
|
if (item != null) {
|
||||||
final PageAction activityAction = getActivitySelection(actionItem);
|
final TreeItem actionItem = getActionItem(item);
|
||||||
this.pageService.executePageAction(activityAction);
|
final PageAction activityAction = getActivitySelection(actionItem);
|
||||||
|
this.pageService.executePageAction(activityAction);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
final TreeItem item = findItemByActionDefinition(
|
final TreeItem item = findItemByActionDefinition(
|
||||||
navigation.getItems(),
|
navigation.getItems(),
|
||||||
|
@ -451,7 +478,7 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
private TreeItem getDefaultSelectionFor(final Tree navigation, final CurrentUser currentUser2) {
|
private TreeItem getDefaultSelectionFor(final Tree navigation, final CurrentUser currentUser2) {
|
||||||
try {
|
try {
|
||||||
if (this.currentUser.get().hasAnyRole(UserRole.SEB_SERVER_ADMIN, UserRole.INSTITUTIONAL_ADMIN)) {
|
if (this.currentUser.get().hasAnyRole(UserRole.SEB_SERVER_ADMIN, UserRole.INSTITUTIONAL_ADMIN)) {
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
return navigation.getItem(0).getItem(1);
|
return navigation.getItem(0).getItem(1);
|
||||||
}
|
}
|
||||||
return navigation.getItem(0);
|
return navigation.getItem(0);
|
||||||
|
@ -467,7 +494,11 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
return navigation.getItem(0);
|
return navigation.getItem(0);
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
return navigation.getItem(0);
|
try {
|
||||||
|
return navigation.getItem(0);
|
||||||
|
} catch (final Exception ignored) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class InstitutionList implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,6 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
|
|
||||||
final CurrentUser currentUser = this.resourceService.getCurrentUser();
|
final CurrentUser currentUser = this.resourceService.getCurrentUser();
|
||||||
final RestService restService = this.resourceService.getRestService();
|
final RestService restService = this.resourceService.getRestService();
|
||||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||||
|
@ -108,11 +107,12 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||||
final boolean readonly = pageContext.isReadonly();
|
final boolean readonly = pageContext.isReadonly();
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
|
|
||||||
final BooleanSupplier isNew = () -> entityKey == null;
|
final BooleanSupplier isNew = () -> entityKey == null;
|
||||||
final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
|
final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
|
||||||
final BooleanSupplier isSEBAdmin = () -> user.hasRole(UserRole.SEB_SERVER_ADMIN);
|
final BooleanSupplier isSEBAdmin = () -> user.hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||||
|
final boolean newAccountPrivilege = !isLight && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_USER_ADMINISTRATION);
|
||||||
|
|
||||||
if (isLight && !readonly && isNew.getAsBoolean()) {
|
if (isLight && !readonly && isNew.getAsBoolean()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
|
@ -142,8 +142,12 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
final boolean ownAccount = user.uuid.equals(userAccount.getModelId());
|
final boolean ownAccount = user.uuid.equals(userAccount.getModelId());
|
||||||
final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(userAccount);
|
final EntityGrantCheck userGrantCheck = currentUser.entityGrantCheck(userAccount);
|
||||||
|
|
||||||
final boolean writeGrant = roleBasedEditGrant && userGrantCheck.w();
|
final boolean writeGrant = roleBasedEditGrant
|
||||||
final boolean modifyGrant = roleBasedEditGrant && userGrantCheck.m();
|
&& userGrantCheck.w()
|
||||||
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_USER_ADMINISTRATION);
|
||||||
|
final boolean modifyGrant = roleBasedEditGrant
|
||||||
|
&& userGrantCheck.m()
|
||||||
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_USER_ACCOUNT);
|
||||||
final boolean institutionalWriteGrant = currentUser.hasInstitutionalPrivilege(
|
final boolean institutionalWriteGrant = currentUser.hasInstitutionalPrivilege(
|
||||||
PrivilegeType.WRITE,
|
PrivilegeType.WRITE,
|
||||||
EntityType.USER);
|
EntityType.USER);
|
||||||
|
@ -232,7 +236,6 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
FORM_ROLES_TEXT_KEY,
|
FORM_ROLES_TEXT_KEY,
|
||||||
StringUtils.join(userAccount.getRoles(), Constants.LIST_SEPARATOR_CHAR),
|
StringUtils.join(userAccount.getRoles(), Constants.LIST_SEPARATOR_CHAR),
|
||||||
this.resourceService::userRoleResources)
|
this.resourceService::userRoleResources)
|
||||||
.visibleIf(writeGrant)
|
|
||||||
.mandatory(!readonly))
|
.mandatory(!readonly))
|
||||||
.addFieldIf(
|
.addFieldIf(
|
||||||
isNew,
|
isNew,
|
||||||
|
@ -252,11 +255,13 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
? restService.getRestCall(NewUserAccount.class)
|
? restService.getRestCall(NewUserAccount.class)
|
||||||
: restService.getRestCall(SaveUserAccount.class));
|
: restService.getRestCall(SaveUserAccount.class));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// propagate content actions to action-pane
|
// propagate content actions to action-pane
|
||||||
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
||||||
|
|
||||||
.newAction(ActionDefinition.USER_ACCOUNT_NEW)
|
.newAction(ActionDefinition.USER_ACCOUNT_NEW)
|
||||||
.publishIf(() -> institutionalWriteGrant && readonly && institutionActive)
|
.publishIf(() -> newAccountPrivilege && institutionalWriteGrant && readonly && institutionActive)
|
||||||
|
|
||||||
.newAction(ActionDefinition.USER_ACCOUNT_MODIFY)
|
.newAction(ActionDefinition.USER_ACCOUNT_MODIFY)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
|
|
@ -196,7 +196,7 @@ public class UserActivityLogs implements TemplateComposer {
|
||||||
.withColumnIf(
|
.withColumnIf(
|
||||||
() -> isSEBAdmin.getAsBoolean()
|
() -> isSEBAdmin.getAsBoolean()
|
||||||
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
||||||
&& !pageService.isSEBServerLightSetup(),
|
&& !pageService.isLightSetup(),
|
||||||
() -> new ColumnDefinition<>(
|
() -> new ColumnDefinition<>(
|
||||||
UserActivityLog.FILTER_ATTR_INSTITUTION,
|
UserActivityLog.FILTER_ATTR_INSTITUTION,
|
||||||
INSTITUTION_TEXT_KEY,
|
INSTITUTION_TEXT_KEY,
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class CertificateList implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class ConfigTemplateList implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ public class SEBClientConfigList implements TemplateComposer {
|
||||||
.withColumnIf(
|
.withColumnIf(
|
||||||
() -> isSEBAdmin
|
() -> isSEBAdmin
|
||||||
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
||||||
&& !pageService.isSEBServerLightSetup(),
|
&& !pageService.isLightSetup(),
|
||||||
() -> new ColumnDefinition<>(
|
() -> new ColumnDefinition<>(
|
||||||
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
||||||
INSTITUTION_TEXT_KEY,
|
INSTITUTION_TEXT_KEY,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Text;
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
@ -159,7 +160,7 @@ public class SEBExamConfigForm implements TemplateComposer {
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||||
final boolean isNew = entityKey == null;
|
final boolean isNew = entityKey == null;
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
|
|
||||||
// get data or create new. Handle error if happen
|
// get data or create new. Handle error if happen
|
||||||
final ConfigurationNode examConfig = (isNew)
|
final ConfigurationNode examConfig = (isNew)
|
||||||
|
@ -350,7 +351,7 @@ public class SEBExamConfigForm implements TemplateComposer {
|
||||||
.withExec(this.pageService.backToCurrentFunction())
|
.withExec(this.pageService.backToCurrentFunction())
|
||||||
.publishIf(() -> !isReadonly);
|
.publishIf(() -> !isReadonly);
|
||||||
|
|
||||||
if (isAttachedToExam && isReadonly) {
|
if (isAttachedToExam && isReadonly && currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_ADMIN)) {
|
||||||
|
|
||||||
widgetFactory.addFormSubContextHeader(
|
widgetFactory.addFormSubContextHeader(
|
||||||
content,
|
content,
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class SEBExamConfigList implements TemplateComposer {
|
||||||
TITLE_CONFIGURATION_TEXT_KEY);
|
TITLE_CONFIGURATION_TEXT_KEY);
|
||||||
|
|
||||||
final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
final PageActionBuilder pageActionBuilder =
|
final PageActionBuilder pageActionBuilder =
|
||||||
this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
|
this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ public class SEBExamConfigList implements TemplateComposer {
|
||||||
.withColumnIf(
|
.withColumnIf(
|
||||||
() -> isSEBAdmin
|
() -> isSEBAdmin
|
||||||
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
||||||
&& !pageService.isSEBServerLightSetup(),
|
&& !pageService.isLightSetup(),
|
||||||
() -> new ColumnDefinition<>(
|
() -> new ColumnDefinition<>(
|
||||||
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
||||||
INSTITUTION_TEXT_KEY,
|
INSTITUTION_TEXT_KEY,
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class ClientGroupForm implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
this.pageService.pageActionBuilder(pageContext.clearEntityKeys())
|
this.pageService.pageActionBuilder(pageContext.clearEntityKeys())
|
||||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_CANCEL_MODIFY)
|
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_CANCEL_MODIFY)
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
@ -71,10 +73,12 @@ public class ExamClientGroupList implements TemplateComposer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
final CurrentUser currentUser = pageService.getCurrentUser();
|
||||||
final Composite content = pageContext.getParent();
|
final Composite content = pageContext.getParent();
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final boolean editable = BooleanUtils.toBoolean(pageContext.getAttribute(ExamForm.ATTR_EDITABLE));
|
final boolean editable = BooleanUtils.toBoolean(pageContext.getAttribute(ExamForm.ATTR_EDITABLE));
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
|
final boolean clientGroupsEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_SEB_CLIENT_GROUPS);
|
||||||
|
|
||||||
// List of ClientGroups
|
// List of ClientGroups
|
||||||
this.widgetFactory.addFormSubContextHeader(
|
this.widgetFactory.addFormSubContextHeader(
|
||||||
|
@ -124,7 +128,7 @@ public class ExamClientGroupList implements TemplateComposer {
|
||||||
.widthProportion(3))
|
.widthProportion(3))
|
||||||
|
|
||||||
.withDefaultActionIf(
|
.withDefaultActionIf(
|
||||||
() -> editable,
|
() -> editable && clientGroupsEnabled,
|
||||||
() -> actionBuilder
|
() -> actionBuilder
|
||||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_MODIFY_FROM_LIST)
|
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_MODIFY_FROM_LIST)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
|
@ -145,7 +149,7 @@ public class ExamClientGroupList implements TemplateComposer {
|
||||||
clientGroupTable::getMultiSelection,
|
clientGroupTable::getMultiSelection,
|
||||||
PageAction::applySingleSelectionAsEntityKey,
|
PageAction::applySingleSelectionAsEntityKey,
|
||||||
CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY)
|
CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY)
|
||||||
.publishIf(() -> editable && clientGroupTable.hasAnyContent(), false)
|
.publishIf(() -> clientGroupsEnabled && editable && clientGroupTable.hasAnyContent(), false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_DELETE_FROM_LIST)
|
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_DELETE_FROM_LIST)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -153,11 +157,11 @@ public class ExamClientGroupList implements TemplateComposer {
|
||||||
clientGroupTable::getMultiSelection,
|
clientGroupTable::getMultiSelection,
|
||||||
this::deleteSelectedClientGroup,
|
this::deleteSelectedClientGroup,
|
||||||
CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY)
|
CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY)
|
||||||
.publishIf(() -> !isLight && editable && clientGroupTable.hasAnyContent(), false)
|
.publishIf(() -> clientGroupsEnabled && !isLight && editable && clientGroupTable.hasAnyContent(), false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_NEW)
|
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_NEW)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
.publishIf(() -> editable);
|
.publishIf(() -> clientGroupsEnabled && editable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PageAction deleteSelectedClientGroup(final PageAction action) {
|
private PageAction deleteSelectedClientGroup(final PageAction action) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||||
|
|
||||||
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.EXAM_SCREEN_PROCTORING;
|
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -16,6 +16,7 @@ import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.*;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.*;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -197,7 +198,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
final EntityKey entityKey = (readonly || !newExamNoLMS) ? pageContext.getEntityKey() : null;
|
final EntityKey entityKey = (readonly || !newExamNoLMS) ? pageContext.getEntityKey() : null;
|
||||||
final PageContext formContext = pageContext.withEntityKey(exam.getEntityKey());
|
final PageContext formContext = pageContext.withEntityKey(exam.getEntityKey());
|
||||||
final EntityGrantCheck entityGrantCheck = currentUser.entityGrantCheck(exam);
|
final EntityGrantCheck entityGrantCheck = currentUser.entityGrantCheck(exam);
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
final boolean modifyGrant = entityGrantCheck.m();
|
final boolean modifyGrant = entityGrantCheck.m();
|
||||||
final boolean writeGrant = entityGrantCheck.w();
|
final boolean writeGrant = entityGrantCheck.w();
|
||||||
final boolean editable = modifyGrant && (exam.getStatus() == ExamStatus.UP_COMING || exam.getStatus() == ExamStatus.RUNNING);
|
final boolean editable = modifyGrant && (exam.getStatus() == ExamStatus.UP_COMING || exam.getStatus() == ExamStatus.RUNNING);
|
||||||
|
@ -214,6 +215,11 @@ public class ExamForm implements TemplateComposer {
|
||||||
sebRestrictionAvailable &&
|
sebRestrictionAvailable &&
|
||||||
isRestricted != exam.sebRestriction &&
|
isRestricted != exam.sebRestriction &&
|
||||||
exam.status == ExamStatus.RUNNING;
|
exam.status == ExamStatus.RUNNING;
|
||||||
|
final boolean connectionConfigEnabled = currentUser.isFeatureEnabled(EXAM_CONNECTION_CONFIG);
|
||||||
|
final boolean askEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_ASK);
|
||||||
|
final boolean spsFeatureEnabled = currentUser.isFeatureEnabled(EXAM_SCREEN_PROCTORING);
|
||||||
|
final boolean lpEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_LIVE_PROCTORING);
|
||||||
|
final boolean restrictionEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_SEB_RESTRICTION);
|
||||||
|
|
||||||
// check exam consistency and inform the user if needed
|
// check exam consistency and inform the user if needed
|
||||||
Collection<APIMessage> warnings = null;
|
Collection<APIMessage> warnings = null;
|
||||||
|
@ -255,7 +261,6 @@ public class ExamForm implements TemplateComposer {
|
||||||
.map(ProctoringServiceSettings::getEnableProctoring)
|
.map(ProctoringServiceSettings::getEnableProctoring)
|
||||||
.getOr(false);
|
.getOr(false);
|
||||||
|
|
||||||
final boolean spsFeatureEnabled = currentUser.isFeatureEnabled(EXAM_SCREEN_PROCTORING);
|
|
||||||
final boolean screenProctoringEnabled = readonly && spsFeatureEnabled && this.restService
|
final boolean screenProctoringEnabled = readonly && spsFeatureEnabled && this.restService
|
||||||
.getBuilder(GetScreenProctoringSettings.class)
|
.getBuilder(GetScreenProctoringSettings.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
|
@ -306,15 +311,15 @@ public class ExamForm implements TemplateComposer {
|
||||||
.withExec(this.examCreateClientConfigPopup.exportFunction(
|
.withExec(this.examCreateClientConfigPopup.exportFunction(
|
||||||
exam.institutionId,
|
exam.institutionId,
|
||||||
exam.getName()))
|
exam.getName()))
|
||||||
.publishIf(() -> editable && readonly)
|
.publishIf(() -> connectionConfigEnabled && editable && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_SECURITY_KEY_ENABLED)
|
.newAction(ActionDefinition.EXAM_SECURITY_KEY_ENABLED)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.publishIf(() -> signatureKeyCheckEnabled && readonly)
|
.publishIf(() -> askEnabled && signatureKeyCheckEnabled && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_SECURITY_KEY_DISABLED)
|
.newAction(ActionDefinition.EXAM_SECURITY_KEY_DISABLED)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.publishIf(() -> !signatureKeyCheckEnabled && readonly)
|
.publishIf(() -> askEnabled && !signatureKeyCheckEnabled && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
|
.newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -322,7 +327,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
.withAttribute(ExamSEBRestrictionSettings.PAGE_CONTEXT_ATTR_LMS_ID, String.valueOf(exam.lmsSetupId))
|
.withAttribute(ExamSEBRestrictionSettings.PAGE_CONTEXT_ATTR_LMS_ID, String.valueOf(exam.lmsSetupId))
|
||||||
.withAttribute(PageContext.AttributeKeys.FORCE_READ_ONLY, String.valueOf(!modifyGrant || !editable))
|
.withAttribute(PageContext.AttributeKeys.FORCE_READ_ONLY, String.valueOf(!modifyGrant || !editable))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> sebRestrictionAvailable && readonly)
|
.publishIf(() -> restrictionEnabled && sebRestrictionAvailable && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_ENABLE_SEB_RESTRICTION)
|
.newAction(ActionDefinition.EXAM_ENABLE_SEB_RESTRICTION)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -341,20 +346,20 @@ public class ExamForm implements TemplateComposer {
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(this.proctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant && editable))
|
.withExec(this.proctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant && editable))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> !isLight && proctoringEnabled && readonly)
|
.publishIf(() -> lpEnabled && !isLight && proctoringEnabled && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_PROCTORING_OFF)
|
.newAction(ActionDefinition.EXAM_PROCTORING_OFF)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(this.proctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant && editable))
|
.withExec(this.proctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant && editable))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> !isLight && !proctoringEnabled && readonly)
|
.publishIf(() -> lpEnabled && !isLight && !proctoringEnabled && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SCREEN_PROCTORING_ON)
|
.newAction(ActionDefinition.SCREEN_PROCTORING_ON)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(
|
.withExec(
|
||||||
this.screenProctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant && editable))
|
this.screenProctoringSettingsPopup.settingsFunction(this.pageService, modifyGrant && editable))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> spsFeatureEnabled && screenProctoringEnabled && readonly)
|
.publishIf(() -> spsFeatureEnabled && screenProctoringEnabled && readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.SCREEN_PROCTORING_OFF)
|
.newAction(ActionDefinition.SCREEN_PROCTORING_OFF)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -501,8 +506,9 @@ public class ExamForm implements TemplateComposer {
|
||||||
final Composite content,
|
final Composite content,
|
||||||
final Exam exam) {
|
final Exam exam) {
|
||||||
|
|
||||||
|
final boolean templateEnabled = pageService.getCurrentUser().isFeatureEnabled(EXAM_TEMPLATE);
|
||||||
final I18nSupport i18nSupport = formContext.getI18nSupport();
|
final I18nSupport i18nSupport = formContext.getI18nSupport();
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
final boolean newExam = exam.id == null;
|
final boolean newExam = exam.id == null;
|
||||||
final boolean hasLMS = exam.lmsSetupId != null;
|
final boolean hasLMS = exam.lmsSetupId != null;
|
||||||
final boolean importFromLMS = newExam && hasLMS;
|
final boolean importFromLMS = newExam && hasLMS;
|
||||||
|
@ -545,7 +551,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
this.resourceService::lmsSetupResource)
|
this.resourceService::lmsSetupResource)
|
||||||
.readonly(true))
|
.readonly(true))
|
||||||
|
|
||||||
.addFieldIf(() -> !isLight && exam.id == null,
|
.addFieldIf(() -> templateEnabled && !isLight && exam.id == null,
|
||||||
() -> FormBuilder.singleSelection(
|
() -> FormBuilder.singleSelection(
|
||||||
Domain.EXAM.ATTR_EXAM_TEMPLATE_ID,
|
Domain.EXAM.ATTR_EXAM_TEMPLATE_ID,
|
||||||
FORM_EXAM_TEMPLATE_TEXT_KEY,
|
FORM_EXAM_TEMPLATE_TEXT_KEY,
|
||||||
|
@ -630,7 +636,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
DateTime.now(timeZone).plusHours(1),
|
DateTime.now(timeZone).plusHours(1),
|
||||||
Exam.ExamType.UNDEFINED,
|
Exam.ExamType.UNDEFINED,
|
||||||
null,
|
null,
|
||||||
pageService.isSEBServerLightSetup()
|
pageService.isLightSetup()
|
||||||
? Stream.of(this.pageService.getCurrentUser().get().uuid).collect(Collectors.toList())
|
? Stream.of(this.pageService.getCurrentUser().get().uuid).collect(Collectors.toList())
|
||||||
: null,
|
: null,
|
||||||
ExamStatus.UP_COMING,
|
ExamStatus.UP_COMING,
|
||||||
|
@ -811,7 +817,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||||
final POSTMapper mapper = new POSTMapper(null, null);
|
final POSTMapper mapper = new POSTMapper(null, null);
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
mapper.putIfAbsent(Domain.EXAM.ATTR_SUPPORTER, this.pageService.getCurrentUser().get().uuid);
|
mapper.putIfAbsent(Domain.EXAM.ATTR_SUPPORTER, this.pageService.getCurrentUser().get().uuid);
|
||||||
}
|
}
|
||||||
return this.restService.getBuilder(GetQuizData.class)
|
return this.restService.getBuilder(GetQuizData.class)
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
@ -88,6 +90,7 @@ public class ExamFormConfigs implements TemplateComposer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
final CurrentUser currentUser = pageService.getCurrentUser();
|
||||||
final Composite content = pageContext.getParent();
|
final Composite content = pageContext.getParent();
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final boolean editable = BooleanUtils.toBoolean(
|
final boolean editable = BooleanUtils.toBoolean(
|
||||||
|
@ -97,6 +100,7 @@ public class ExamFormConfigs implements TemplateComposer {
|
||||||
final ExamStatus examStatus = ExamStatus.valueOf(
|
final ExamStatus examStatus = ExamStatus.valueOf(
|
||||||
pageContext.getAttribute(ExamForm.ATTR_EXAM_STATUS));
|
pageContext.getAttribute(ExamForm.ATTR_EXAM_STATUS));
|
||||||
final boolean isExamRunning = examStatus == ExamStatus.RUNNING;
|
final boolean isExamRunning = examStatus == ExamStatus.RUNNING;
|
||||||
|
final boolean examConfigEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.CONFIG_EXAM_CONFIGURATION);
|
||||||
|
|
||||||
// List of SEB Configuration
|
// List of SEB Configuration
|
||||||
this.widgetFactory.addFormSubContextHeader(
|
this.widgetFactory.addFormSubContextHeader(
|
||||||
|
@ -128,7 +132,7 @@ public class ExamFormConfigs implements TemplateComposer {
|
||||||
this.resourceService::localizedExamConfigStatusName)
|
this.resourceService::localizedExamConfigStatusName)
|
||||||
.widthProportion(1))
|
.widthProportion(1))
|
||||||
.withDefaultActionIf(
|
.withDefaultActionIf(
|
||||||
() -> readGrant,
|
() -> readGrant && examConfigEnabled,
|
||||||
this::viewExamConfigPageAction)
|
this::viewExamConfigPageAction)
|
||||||
|
|
||||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||||
|
@ -156,12 +160,12 @@ public class ExamFormConfigs implements TemplateComposer {
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
.withExec(this.examToConfigBindingForm.bindFunction())
|
.withExec(this.examToConfigBindingForm.bindFunction())
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> editable && !configurationTable.hasAnyContent())
|
.publishIf(() -> examConfigEnabled && editable && !configurationTable.hasAnyContent())
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
|
.newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
.withEntityKey(configMapKey)
|
.withEntityKey(configMapKey)
|
||||||
.publishIf(() -> readGrant && configurationTable.hasAnyContent(), false)
|
.publishIf(() -> examConfigEnabled && readGrant && configurationTable.hasAnyContent(), false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
|
.newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -175,7 +179,7 @@ public class ExamFormConfigs implements TemplateComposer {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
.publishIf(() -> editable && configurationTable.hasAnyContent() && editable, false)
|
.publishIf(() -> examConfigEnabled && editable && configurationTable.hasAnyContent() && editable, false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_GET_CONFIG_KEY)
|
.newAction(ActionDefinition.EXAM_CONFIGURATION_GET_CONFIG_KEY)
|
||||||
.withSelect(
|
.withSelect(
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
@ -70,10 +72,12 @@ public class ExamIndicatorsList implements TemplateComposer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
final CurrentUser currentUser = pageService.getCurrentUser();
|
||||||
final Composite content = pageContext.getParent();
|
final Composite content = pageContext.getParent();
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final boolean editable = BooleanUtils.toBoolean(pageContext.getAttribute(ExamForm.ATTR_EDITABLE));
|
final boolean editable = BooleanUtils.toBoolean(pageContext.getAttribute(ExamForm.ATTR_EDITABLE));
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
|
final boolean indicatorEnabled = currentUser.isFeatureEnabled(UserFeatures.Feature.EXAM_INDICATORS);
|
||||||
|
|
||||||
// List of Indicators
|
// List of Indicators
|
||||||
this.widgetFactory.addFormSubContextHeader(
|
this.widgetFactory.addFormSubContextHeader(
|
||||||
|
@ -111,7 +115,7 @@ public class ExamIndicatorsList implements TemplateComposer {
|
||||||
.asMarkup()
|
.asMarkup()
|
||||||
.widthProportion(4))
|
.widthProportion(4))
|
||||||
.withDefaultActionIf(
|
.withDefaultActionIf(
|
||||||
() -> editable,
|
() -> editable && indicatorEnabled,
|
||||||
() -> actionBuilder
|
() -> actionBuilder
|
||||||
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
|
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
|
@ -132,7 +136,7 @@ public class ExamIndicatorsList implements TemplateComposer {
|
||||||
indicatorTable::getMultiSelection,
|
indicatorTable::getMultiSelection,
|
||||||
PageAction::applySingleSelectionAsEntityKey,
|
PageAction::applySingleSelectionAsEntityKey,
|
||||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||||
.publishIf(() -> editable && indicatorTable.hasAnyContent(), false)
|
.publishIf(() -> indicatorEnabled && editable && indicatorTable.hasAnyContent(), false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
|
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -140,11 +144,11 @@ public class ExamIndicatorsList implements TemplateComposer {
|
||||||
indicatorTable::getMultiSelection,
|
indicatorTable::getMultiSelection,
|
||||||
this::deleteSelectedIndicator,
|
this::deleteSelectedIndicator,
|
||||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||||
.publishIf(() -> !isLight && editable && indicatorTable.hasAnyContent(), false)
|
.publishIf(() -> indicatorEnabled && !isLight && editable && indicatorTable.hasAnyContent(), false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_INDICATOR_NEW)
|
.newAction(ActionDefinition.EXAM_INDICATOR_NEW)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
.publishIf(() -> editable);
|
.publishIf(() -> indicatorEnabled && editable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class ExamList implements TemplateComposer {
|
||||||
.withColumnIf(
|
.withColumnIf(
|
||||||
() -> isSEBAdmin.getAsBoolean()
|
() -> isSEBAdmin.getAsBoolean()
|
||||||
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
||||||
&& !pageService.isSEBServerLightSetup(),
|
&& !pageService.isLightSetup(),
|
||||||
() -> new ColumnDefinition<Exam>(
|
() -> new ColumnDefinition<Exam>(
|
||||||
Domain.EXAM.ATTR_INSTITUTION_ID,
|
Domain.EXAM.ATTR_INSTITUTION_ID,
|
||||||
COLUMN_TITLE_INSTITUTION_KEY,
|
COLUMN_TITLE_INSTITUTION_KEY,
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class ExamTemplateList implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class IndicatorForm implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
if (pageService.isSEBServerLightSetup()) {
|
if (pageService.isLightSetup()) {
|
||||||
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
pageService.applyFullVersionNote(pageContext.getParent(), pageContext);
|
||||||
this.pageService.pageActionBuilder(pageContext.clearEntityKeys())
|
this.pageService.pageActionBuilder(pageContext.clearEntityKeys())
|
||||||
.newAction(ActionDefinition.EXAM_INDICATOR_CANCEL_MODIFY)
|
.newAction(ActionDefinition.EXAM_INDICATOR_CANCEL_MODIFY)
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class LmsSetupList implements TemplateComposer {
|
||||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||||
final CurrentUser currentUser = this.resourceService.getCurrentUser();
|
final CurrentUser currentUser = this.resourceService.getCurrentUser();
|
||||||
final RestService restService = this.resourceService.getRestService();
|
final RestService restService = this.resourceService.getRestService();
|
||||||
final boolean isLight = pageService.isSEBServerLightSetup();
|
final boolean isLight = pageService.isLightSetup();
|
||||||
|
|
||||||
// content page layout with title
|
// content page layout with title
|
||||||
final Composite content = widgetFactory.defaultPageLayout(
|
final Composite content = widgetFactory.defaultPageLayout(
|
||||||
|
|
|
@ -195,7 +195,7 @@ public class QuizLookupList implements TemplateComposer {
|
||||||
.withColumnIf(
|
.withColumnIf(
|
||||||
() -> isSEBAdmin.getAsBoolean()
|
() -> isSEBAdmin.getAsBoolean()
|
||||||
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
&& currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
|
||||||
&& !pageService.isSEBServerLightSetup(),
|
&& !pageService.isLightSetup(),
|
||||||
() -> new ColumnDefinition<QuizData>(
|
() -> new ColumnDefinition<QuizData>(
|
||||||
QuizData.QUIZ_ATTR_INSTITUTION_ID,
|
QuizData.QUIZ_ATTR_INSTITUTION_ID,
|
||||||
INSTITUTION_TEXT_KEY,
|
INSTITUTION_TEXT_KEY,
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
||||||
|
|
||||||
|
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -181,6 +183,12 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final String connectionToken = pageContext.getAttribute(Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN);
|
final String connectionToken = pageContext.getAttribute(Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN);
|
||||||
|
|
||||||
|
final boolean quitEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_QUIT);
|
||||||
|
final boolean lockscreenEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_QUIT);
|
||||||
|
final boolean cancelEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_CANCEL_CON);
|
||||||
|
final boolean askEnabled = currentUser.isFeatureEnabled(EXAM_ASK);
|
||||||
|
final boolean liveProctoringEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_LIVE_PROCTORING);
|
||||||
|
|
||||||
if (connectionToken == null) {
|
if (connectionToken == null) {
|
||||||
pageContext.notifyUnexpectedError(new IllegalAccessException("connectionToken has null reference"));
|
pageContext.notifyUnexpectedError(new IllegalAccessException("connectionToken has null reference"));
|
||||||
return;
|
return;
|
||||||
|
@ -291,7 +299,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
.withParentEntityKey(parentEntityKey)
|
.withParentEntityKey(parentEntityKey)
|
||||||
.withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
|
.withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
|
||||||
.withSelect(
|
.withSelect(
|
||||||
() -> notificationTable.getMultiSelection(),
|
notificationTable::getMultiSelection,
|
||||||
action -> this.confirmNotification(action, connectionData, notificationTable),
|
action -> this.confirmNotification(action, connectionData, notificationTable),
|
||||||
|
|
||||||
NOTIFICATION_LIST_NO_SELECTION_KEY)
|
NOTIFICATION_LIST_NO_SELECTION_KEY)
|
||||||
|
@ -398,7 +406,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
return action;
|
return action;
|
||||||
})
|
})
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> isExamSupporter.getAsBoolean() &&
|
.publishIf(() -> quitEnabled && isExamSupporter.getAsBoolean() &&
|
||||||
connectionData.clientConnection.status.clientActiveStatus)
|
connectionData.clientConnection.status.clientActiveStatus)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_LOCK)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_LOCK)
|
||||||
|
@ -406,7 +414,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
.withExec(action -> this.sebSendLockPopup.show(action,
|
.withExec(action -> this.sebSendLockPopup.show(action,
|
||||||
some -> new HashSet<>(Arrays.asList(connectionToken))))
|
some -> new HashSet<>(Arrays.asList(connectionToken))))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> isExamSupporter.getAsBoolean() &&
|
.publishIf(() -> lockscreenEnabled && isExamSupporter.getAsBoolean() &&
|
||||||
connectionData.clientConnection.status.clientActiveStatus)
|
connectionData.clientConnection.status.clientActiveStatus)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_DISABLE_CONNECTION)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_DISABLE_CONNECTION)
|
||||||
|
@ -419,11 +427,11 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
: null)
|
: null)
|
||||||
.withExec(action -> this.disableClientConnection(action, clientConnectionDetails))
|
.withExec(action -> this.disableClientConnection(action, clientConnectionDetails))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(() -> isExamSupporter.getAsBoolean() &&
|
.publishIf(() -> cancelEnabled && isExamSupporter.getAsBoolean() &&
|
||||||
(connectionData.clientConnection.status.clientActiveStatus ||
|
(connectionData.clientConnection.status.clientActiveStatus ||
|
||||||
connectionData.clientConnection.status == ConnectionStatus.CLOSED));
|
connectionData.clientConnection.status == ConnectionStatus.CLOSED));
|
||||||
|
|
||||||
if (clientConnectionDetails.checkSecurityGrant) {
|
if (askEnabled && clientConnectionDetails.checkSecurityGrant) {
|
||||||
final SecurityKey securityKey = this.pageService
|
final SecurityKey securityKey = this.pageService
|
||||||
.getRestService()
|
.getRestService()
|
||||||
.getBuilder(GetClientConnectionSecurityKey.class)
|
.getBuilder(GetClientConnectionSecurityKey.class)
|
||||||
|
@ -444,7 +452,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
if (liveProctoringEnabled && connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
||||||
final ProctoringServiceSettings proctoringSettings = restService
|
final ProctoringServiceSettings proctoringSettings = restService
|
||||||
.getBuilder(GetExamProctoringSettings.class)
|
.getBuilder(GetExamProctoringSettings.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
||||||
|
|
||||||
|
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -148,6 +150,11 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
.call()
|
.call()
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
final UserInfo user = currentUser.get();
|
final UserInfo user = currentUser.get();
|
||||||
|
|
||||||
|
final boolean detailEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_DETAIL_VIEW);
|
||||||
|
final boolean quitEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_QUIT);
|
||||||
|
final boolean lockscreenEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_QUIT);
|
||||||
|
final boolean cancelEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_CANCEL_CON);
|
||||||
final boolean supporting = user.hasRole(UserRole.EXAM_SUPPORTER) &&
|
final boolean supporting = user.hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||||
exam.supporter.contains(user.uuid);
|
exam.supporter.contains(user.uuid);
|
||||||
final BooleanSupplier isExamSupporter = () -> supporting || user.hasRole(UserRole.EXAM_ADMIN);
|
final BooleanSupplier isExamSupporter = () -> supporting || user.hasRole(UserRole.EXAM_ADMIN);
|
||||||
|
@ -195,7 +202,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
guiUpdates.add(clientTable);
|
guiUpdates.add(clientTable);
|
||||||
|
|
||||||
clientTable
|
clientTable
|
||||||
.withDefaultAction(
|
.withDefaultActionIf(() -> detailEnabled,
|
||||||
actionBuilder
|
actionBuilder
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
|
@ -221,7 +228,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
.withConfirm(() -> CONFIRM_QUIT_ALL)
|
.withConfirm(() -> CONFIRM_QUIT_ALL)
|
||||||
.withExec(action -> this.quitSEBClients(action, clientTable, true))
|
.withExec(action -> this.quitSEBClients(action, clientTable, true))
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(isExamSupporter)
|
.publishIf(() -> isExamSupporter.getAsBoolean() && quitEnabled)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_QUIT_SELECTED)
|
.newAction(ActionDefinition.MONITOR_EXAM_QUIT_SELECTED)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -231,7 +238,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
action -> this.quitSEBClients(action, clientTable, false),
|
action -> this.quitSEBClients(action, clientTable, false),
|
||||||
EMPTY_ACTIVE_SELECTION_TEXT_KEY)
|
EMPTY_ACTIVE_SELECTION_TEXT_KEY)
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(isExamSupporter, false)
|
.publishIf(() -> isExamSupporter.getAsBoolean() && quitEnabled, false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_LOCK_SELECTED)
|
.newAction(ActionDefinition.MONITOR_EXAM_LOCK_SELECTED)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -240,7 +247,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
action -> this.showSEBLockActionPopup(action, clientTable),
|
action -> this.showSEBLockActionPopup(action, clientTable),
|
||||||
EMPTY_ACTIVE_SELECTION_TEXT_KEY)
|
EMPTY_ACTIVE_SELECTION_TEXT_KEY)
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(isExamSupporter, false)
|
.publishIf(() -> isExamSupporter.getAsBoolean() && lockscreenEnabled, false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
||||||
.withParentEntityKey(entityKey)
|
.withParentEntityKey(entityKey)
|
||||||
|
@ -260,7 +267,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
|
|
||||||
return copyOfPageAction;
|
return copyOfPageAction;
|
||||||
})
|
})
|
||||||
.publishIf(isExamSupporter, false)
|
.publishIf(() -> isExamSupporter.getAsBoolean() && detailEnabled, false)
|
||||||
|
|
||||||
.newAction(ActionDefinition.MONITOR_EXAM_DISABLE_SELECTED_CONNECTION)
|
.newAction(ActionDefinition.MONITOR_EXAM_DISABLE_SELECTED_CONNECTION)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -270,7 +277,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
action -> this.disableSEBClients(action, clientTable, false),
|
action -> this.disableSEBClients(action, clientTable, false),
|
||||||
EMPTY_SELECTION_TEXT_KEY)
|
EMPTY_SELECTION_TEXT_KEY)
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(isExamSupporter, false);
|
.publishIf(() -> isExamSupporter.getAsBoolean() && cancelEnabled, false);
|
||||||
|
|
||||||
if (isExamSupporter.getAsBoolean()) {
|
if (isExamSupporter.getAsBoolean()) {
|
||||||
guiUpdates.add(createFilterActions(
|
guiUpdates.add(createFilterActions(
|
||||||
|
@ -317,13 +324,16 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
final PageContext pageContext,
|
final PageContext pageContext,
|
||||||
final Composite parent) {
|
final Composite parent) {
|
||||||
|
|
||||||
|
final CurrentUser currentUser = pageService.getCurrentUser();
|
||||||
final PageActionBuilder actionBuilder = this.pageService
|
final PageActionBuilder actionBuilder = this.pageService
|
||||||
.pageActionBuilder(pageContext.clearEntityKeys());
|
.pageActionBuilder(pageContext.clearEntityKeys());
|
||||||
|
|
||||||
final boolean proctoringEnabled = proctoringSettings != null &&
|
final boolean proctoringEnabled = proctoringSettings != null
|
||||||
BooleanUtils.toBoolean(proctoringSettings.enableProctoring);
|
&& currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_LIVE_PROCTORING)
|
||||||
final boolean screenProctoringEnabled = screenProctoringSettings != null &&
|
&& BooleanUtils.toBoolean(proctoringSettings.enableProctoring);
|
||||||
BooleanUtils.toBoolean(screenProctoringSettings.enableScreenProctoring);
|
final boolean screenProctoringEnabled = screenProctoringSettings != null
|
||||||
|
&& currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_SCREEN_PROCTORING)
|
||||||
|
&& BooleanUtils.toBoolean(screenProctoringSettings.enableScreenProctoring);
|
||||||
|
|
||||||
if (!proctoringEnabled && !screenProctoringEnabled) {
|
if (!proctoringEnabled && !screenProctoringEnabled) {
|
||||||
return monitoringStatus -> {
|
return monitoringStatus -> {
|
||||||
|
@ -408,43 +418,50 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
final boolean isAskCheckEnabled,
|
final boolean isAskCheckEnabled,
|
||||||
final List<AllowedSEBVersion> allowedSEBVersions) {
|
final List<AllowedSEBVersion> allowedSEBVersions) {
|
||||||
|
|
||||||
|
final CurrentUser currentUser = pageService.getCurrentUser();
|
||||||
|
final boolean stateFilterEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_STATE_FILTER);
|
||||||
|
final boolean issueFilterEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_ISSUE_FILTER);
|
||||||
|
final boolean clientFilterEnabled = currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_CLIENT_FILTER);
|
||||||
|
|
||||||
final FilterGUIUpdate statusFilterGUIUpdate =
|
final FilterGUIUpdate statusFilterGUIUpdate =
|
||||||
new FilterGUIUpdate(this.pageService.getPolyglotPageService());
|
new FilterGUIUpdate(this.pageService.getPolyglotPageService());
|
||||||
|
|
||||||
addFilterAction(
|
if (stateFilterEnabled) {
|
||||||
monitoringStatus,
|
addFilterAction(
|
||||||
statusFilterGUIUpdate,
|
monitoringStatus,
|
||||||
actionBuilder,
|
statusFilterGUIUpdate,
|
||||||
clientTable,
|
actionBuilder,
|
||||||
ConnectionStatus.CONNECTION_REQUESTED,
|
clientTable,
|
||||||
ActionDefinition.MONITOR_EXAM_SHOW_REQUESTED_CONNECTION,
|
ConnectionStatus.CONNECTION_REQUESTED,
|
||||||
ActionDefinition.MONITOR_EXAM_HIDE_REQUESTED_CONNECTION);
|
ActionDefinition.MONITOR_EXAM_SHOW_REQUESTED_CONNECTION,
|
||||||
addFilterAction(
|
ActionDefinition.MONITOR_EXAM_HIDE_REQUESTED_CONNECTION);
|
||||||
monitoringStatus,
|
addFilterAction(
|
||||||
statusFilterGUIUpdate,
|
monitoringStatus,
|
||||||
actionBuilder,
|
statusFilterGUIUpdate,
|
||||||
clientTable,
|
actionBuilder,
|
||||||
ConnectionStatus.ACTIVE,
|
clientTable,
|
||||||
ActionDefinition.MONITOR_EXAM_SHOW_ACTIVE_CONNECTION,
|
ConnectionStatus.ACTIVE,
|
||||||
ActionDefinition.MONITOR_EXAM_HIDE_ACTIVE_CONNECTION);
|
ActionDefinition.MONITOR_EXAM_SHOW_ACTIVE_CONNECTION,
|
||||||
addFilterAction(
|
ActionDefinition.MONITOR_EXAM_HIDE_ACTIVE_CONNECTION);
|
||||||
monitoringStatus,
|
addFilterAction(
|
||||||
statusFilterGUIUpdate,
|
monitoringStatus,
|
||||||
actionBuilder,
|
statusFilterGUIUpdate,
|
||||||
clientTable,
|
actionBuilder,
|
||||||
ConnectionStatus.CLOSED,
|
clientTable,
|
||||||
ActionDefinition.MONITOR_EXAM_SHOW_CLOSED_CONNECTION,
|
ConnectionStatus.CLOSED,
|
||||||
ActionDefinition.MONITOR_EXAM_HIDE_CLOSED_CONNECTION);
|
ActionDefinition.MONITOR_EXAM_SHOW_CLOSED_CONNECTION,
|
||||||
addFilterAction(
|
ActionDefinition.MONITOR_EXAM_HIDE_CLOSED_CONNECTION);
|
||||||
monitoringStatus,
|
addFilterAction(
|
||||||
statusFilterGUIUpdate,
|
monitoringStatus,
|
||||||
actionBuilder,
|
statusFilterGUIUpdate,
|
||||||
clientTable,
|
actionBuilder,
|
||||||
ConnectionStatus.DISABLED,
|
clientTable,
|
||||||
ActionDefinition.MONITOR_EXAM_SHOW_DISABLED_CONNECTION,
|
ConnectionStatus.DISABLED,
|
||||||
ActionDefinition.MONITOR_EXAM_HIDE_DISABLED_CONNECTION);
|
ActionDefinition.MONITOR_EXAM_SHOW_DISABLED_CONNECTION,
|
||||||
|
ActionDefinition.MONITOR_EXAM_HIDE_DISABLED_CONNECTION);
|
||||||
|
}
|
||||||
|
|
||||||
if(isAskCheckEnabled){
|
if(issueFilterEnabled && isAskCheckEnabled) {
|
||||||
addIssueFilterAction(
|
addIssueFilterAction(
|
||||||
monitoringStatus,
|
monitoringStatus,
|
||||||
statusFilterGUIUpdate,
|
statusFilterGUIUpdate,
|
||||||
|
@ -455,7 +472,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
ActionDefinition.MONITOR_EXAM_HIDE_ASK_GRANTED);
|
ActionDefinition.MONITOR_EXAM_HIDE_ASK_GRANTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allowedSEBVersions != null) {
|
if(issueFilterEnabled && allowedSEBVersions != null) {
|
||||||
addIssueFilterAction(
|
addIssueFilterAction(
|
||||||
monitoringStatus,
|
monitoringStatus,
|
||||||
statusFilterGUIUpdate,
|
statusFilterGUIUpdate,
|
||||||
|
@ -466,7 +483,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
ActionDefinition.MONITOR_EXAM_HIDE_SEB_VERSION_GRANTED);
|
ActionDefinition.MONITOR_EXAM_HIDE_SEB_VERSION_GRANTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientGroups != null && !clientGroups.isEmpty()) {
|
if (clientFilterEnabled && clientGroups != null && !clientGroups.isEmpty()) {
|
||||||
clientGroups.forEach(clientGroup -> {
|
clientGroups.forEach(clientGroup -> {
|
||||||
|
|
||||||
addClientGroupFilterAction(
|
addClientGroupFilterAction(
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -64,10 +65,6 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
|
||||||
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.ClientNotification.NotificationType;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification.NotificationType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
|
|
||||||
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.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
|
@ -197,7 +194,7 @@ public class ResourceService {
|
||||||
|
|
||||||
public List<Tuple<String>> lmsTypeResources() {
|
public List<Tuple<String>> lmsTypeResources() {
|
||||||
return Arrays.stream(LmsType.values())
|
return Arrays.stream(LmsType.values())
|
||||||
.filter(lmsType -> this.currentUser.isFeatureEnabled("lms.type." + lmsType.name()))
|
.filter(lmsType -> this.currentUser.isFeatureEnabled("lms.setup.type." + lmsType.name()))
|
||||||
.map(lmsType -> new Tuple<>(
|
.map(lmsType -> new Tuple<>(
|
||||||
lmsType.name(),
|
lmsType.name(),
|
||||||
this.i18nSupport.getText(LMSSETUP_TYPE_PREFIX + lmsType.name(), lmsType.name())))
|
this.i18nSupport.getText(LMSSETUP_TYPE_PREFIX + lmsType.name(), lmsType.name())))
|
||||||
|
@ -294,8 +291,10 @@ public class ResourceService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Tuple<String>> userRoleResources() {
|
public List<Tuple<String>> userRoleResources() {
|
||||||
|
final boolean showServerAdminRole = this.currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION);
|
||||||
return UserRole.publicRolesForUser(this.currentUser.get())
|
return UserRole.publicRolesForUser(this.currentUser.get())
|
||||||
.stream()
|
.stream()
|
||||||
|
.filter(ur -> ur != UserRole.SEB_SERVER_ADMIN || showServerAdminRole)
|
||||||
.map(ur -> new Tuple3<>(
|
.map(ur -> new Tuple3<>(
|
||||||
ur.name(),
|
ur.name(),
|
||||||
this.i18nSupport.getText(USERACCOUNT_ROLE_PREFIX + ur.name()),
|
this.i18nSupport.getText(USERACCOUNT_ROLE_PREFIX + ur.name()),
|
||||||
|
|
|
@ -8,14 +8,11 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
|
package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.OrientationRecord;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -54,34 +51,41 @@ public class AttributeMapping {
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
o -> o.attributeId,
|
o -> o.attributeId,
|
||||||
Function.identity())));
|
Function.identity(),
|
||||||
|
(first, second) -> {
|
||||||
|
log.warn("*** Found duplicate orientation, use {} instead of {}", second, first);
|
||||||
|
return second;
|
||||||
|
})));
|
||||||
this.attributeIdMapping = Utils.immutableMapOf(attributes
|
this.attributeIdMapping = Utils.immutableMapOf(attributes
|
||||||
.stream()
|
.stream()
|
||||||
.filter(attr -> this.orientationAttributeMapping.containsKey(attr.id))
|
.filter(attr -> this.orientationAttributeMapping.containsKey(attr.id))
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
attr -> attr.id,
|
attr -> attr.id,
|
||||||
Function.identity())));
|
Function.identity(),
|
||||||
|
(first, second) -> second)));
|
||||||
|
|
||||||
this.attributeNameIdMapping = Utils.immutableMapOf(attributes
|
this.attributeNameIdMapping = Utils.immutableMapOf(attributes
|
||||||
.stream()
|
.stream()
|
||||||
.filter(attr -> this.orientationAttributeMapping.containsKey(attr.id))
|
.filter(attr -> this.orientationAttributeMapping.containsKey(attr.id))
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
attr -> attr.name,
|
attr -> attr.name,
|
||||||
attr -> attr.id)));
|
attr -> attr.id,
|
||||||
|
(first, second) -> second)));
|
||||||
|
|
||||||
this.orientationAttributeNameMapping = Utils.immutableMapOf(orientations
|
this.orientationAttributeNameMapping = Utils.immutableMapOf(orientations
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
o -> this.attributeIdMapping.get(o.attributeId).name,
|
o -> this.attributeIdMapping.get(o.attributeId).name,
|
||||||
Function.identity())));
|
Function.identity(),
|
||||||
|
(first, second) -> second)));
|
||||||
|
|
||||||
this.childAttributeMapping = Utils.immutableMapOf(attributes
|
this.childAttributeMapping = Utils.immutableMapOf(attributes
|
||||||
.stream()
|
.stream()
|
||||||
.filter(attr -> this.orientationAttributeMapping.containsKey(attr.id))
|
.filter(attr -> this.orientationAttributeMapping.containsKey(attr.id))
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
attr -> attr.id,
|
attr -> attr.id,
|
||||||
this::getChildAttributes)));
|
this::getChildAttributes,
|
||||||
|
(first, second) -> second)));
|
||||||
|
|
||||||
this.attributeGroupMapping = Utils.immutableMapOf(orientations
|
this.attributeGroupMapping = Utils.immutableMapOf(orientations
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -91,7 +95,8 @@ public class AttributeMapping {
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
Function.identity(),
|
Function.identity(),
|
||||||
this::getAttributesOfGroup)));
|
this::getAttributesOfGroup,
|
||||||
|
(first, second) -> second)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ConfigurationAttribute> getAttributes() {
|
public Collection<ConfigurationAttribute> getAttributes() {
|
||||||
|
|
|
@ -130,7 +130,7 @@ public interface PageService {
|
||||||
/** Indicates if SEB Server runs with SEB Server light setup
|
/** Indicates if SEB Server runs with SEB Server light setup
|
||||||
*
|
*
|
||||||
* @return true if this is a SEB Server light setup*/
|
* @return true if this is a SEB Server light setup*/
|
||||||
boolean isSEBServerLightSetup();
|
boolean isLightSetup();
|
||||||
|
|
||||||
void applyFullVersionNote(Composite content, PageContext pageContext);
|
void applyFullVersionNote(Composite content, PageContext pageContext);
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ public class PageServiceImpl implements PageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSEBServerLightSetup() {
|
public boolean isLightSetup() {
|
||||||
return this.guiServiceInfo.isLightSetup();
|
return this.guiServiceInfo.isLightSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -221,6 +222,16 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
||||||
return this.exam;
|
return this.exam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClientConnectionTable withDefaultActionIf(
|
||||||
|
final BooleanSupplier check,
|
||||||
|
final PageAction pageAction,
|
||||||
|
final PageService pageService) {
|
||||||
|
if (check.getAsBoolean()) {
|
||||||
|
return withDefaultAction(pageAction, pageService);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ClientConnectionTable withDefaultAction(final PageAction pageAction, final PageService pageService) {
|
public ClientConnectionTable withDefaultAction(final PageAction pageAction, final PageService pageService) {
|
||||||
this.table.addListener(SWT.MouseDoubleClick, event -> {
|
this.table.addListener(SWT.MouseDoubleClick, event -> {
|
||||||
final Tuple<String> selection = getSingleSelection();
|
final Tuple<String> selection = getSingleSelection();
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.datalayer.checks;
|
package ch.ethz.seb.sebserver.webservice.datalayer.checks;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||||
|
@ -68,7 +66,8 @@ public class OrientationTableDuplicatesCheck implements DBIntegrityCheck {
|
||||||
|
|
||||||
final List<Long> checkedToDelete = toDelete
|
final List<Long> checkedToDelete = toDelete
|
||||||
.stream()
|
.stream()
|
||||||
.filter(this::doubleCheck)
|
.map(this::getOldestForDeletion)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (checkedToDelete == null || checkedToDelete.isEmpty()) {
|
if (checkedToDelete == null || checkedToDelete.isEmpty()) {
|
||||||
|
@ -88,21 +87,38 @@ public class OrientationTableDuplicatesCheck implements DBIntegrityCheck {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doubleCheck(final Long id) {
|
private Long getOldestForDeletion(final Long id) {
|
||||||
try {
|
try {
|
||||||
final OrientationRecord selectByPrimaryKey = this.orientationRecordMapper.selectByPrimaryKey(id);
|
final OrientationRecord selectByPrimaryKey = this.orientationRecordMapper.selectByPrimaryKey(id);
|
||||||
final Long count = this.orientationRecordMapper.countByExample()
|
final List<OrientationRecord> records = this.orientationRecordMapper.selectByExample()
|
||||||
.where(
|
.where(
|
||||||
OrientationRecordDynamicSqlSupport.configAttributeId,
|
OrientationRecordDynamicSqlSupport.configAttributeId,
|
||||||
SqlBuilder.isEqualTo(selectByPrimaryKey.getConfigAttributeId()))
|
SqlBuilder.isEqualTo(selectByPrimaryKey.getConfigAttributeId()))
|
||||||
.and(
|
.and(
|
||||||
OrientationRecordDynamicSqlSupport.templateId,
|
OrientationRecordDynamicSqlSupport.templateId,
|
||||||
SqlBuilder.isEqualTo(selectByPrimaryKey.getTemplateId()))
|
SqlBuilder.isEqualTo(selectByPrimaryKey.getTemplateId()))
|
||||||
|
.orderBy(OrientationRecordDynamicSqlSupport.id)
|
||||||
.build()
|
.build()
|
||||||
.execute();
|
.execute();
|
||||||
return count != null && count.longValue() > 1;
|
|
||||||
|
// get latest entry of duplicates
|
||||||
|
if (records != null && records.size() > 1) {
|
||||||
|
Long result = null;
|
||||||
|
for (int i = 0; i < records.size(); i++) {
|
||||||
|
final OrientationRecord rec = records.get(i);
|
||||||
|
if (result == null) {
|
||||||
|
result = rec.getId();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (result > rec.getId()) {
|
||||||
|
result = rec.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ public class BatchActionServiceImpl implements BatchActionService {
|
||||||
this.batchActionExec
|
this.batchActionExec
|
||||||
.doSingleAction(modelId, this.batchAction)
|
.doSingleAction(modelId, this.batchAction)
|
||||||
.onError(error -> this.batchActionHandler.handleError(modelId, error))
|
.onError(error -> this.batchActionHandler.handleError(modelId, error))
|
||||||
.onSuccess(entityKey -> this.batchActionHandler.handleSuccess(entityKey));
|
.onSuccess(this.batchActionHandler::handleSuccess);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.batchActionHandler.finishUp();
|
this.batchActionHandler.finishUp();
|
||||||
|
|
|
@ -161,9 +161,9 @@ public interface ExamAdminService {
|
||||||
/** Gets invoked after an exam has been changed and saved.
|
/** Gets invoked after an exam has been changed and saved.
|
||||||
*
|
*
|
||||||
* @param exam the exam that has been changed and saved */
|
* @param exam the exam that has been changed and saved */
|
||||||
void notifyExamSaved(Exam exam);
|
Result<Exam> notifyExamSaved(Exam exam);
|
||||||
|
|
||||||
void applyQuitPassword(Exam entity);
|
Result<Exam> applyQuitPassword(Exam exam);
|
||||||
|
|
||||||
static void newExamFieldValidation(final POSTMapper postParams) {
|
static void newExamFieldValidation(final POSTMapper postParams) {
|
||||||
noLMSFieldValidation(new Exam(postParams));
|
noLMSFieldValidation(new Exam(postParams));
|
||||||
|
|
|
@ -69,6 +69,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
private final boolean appSignatureKeyEnabled;
|
private final boolean appSignatureKeyEnabled;
|
||||||
private final int defaultNumericalTrustThreshold;
|
private final int defaultNumericalTrustThreshold;
|
||||||
private final ExamConfigurationValueService examConfigurationValueService;
|
private final ExamConfigurationValueService examConfigurationValueService;
|
||||||
|
private final SEBRestrictionService sebRestrictionService;
|
||||||
|
|
||||||
protected ExamAdminServiceImpl(
|
protected ExamAdminServiceImpl(
|
||||||
final ExamDAO examDAO,
|
final ExamDAO examDAO,
|
||||||
|
@ -78,6 +79,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
final ExamConfigurationMapDAO examConfigurationMapDAO,
|
final ExamConfigurationMapDAO examConfigurationMapDAO,
|
||||||
final LmsAPIService lmsAPIService,
|
final LmsAPIService lmsAPIService,
|
||||||
final ExamConfigurationValueService examConfigurationValueService,
|
final ExamConfigurationValueService examConfigurationValueService,
|
||||||
|
final SEBRestrictionService sebRestrictionService,
|
||||||
final @Value("${sebserver.webservice.api.admin.exam.app.signature.key.enabled:false}") boolean appSignatureKeyEnabled,
|
final @Value("${sebserver.webservice.api.admin.exam.app.signature.key.enabled:false}") boolean appSignatureKeyEnabled,
|
||||||
final @Value("${sebserver.webservice.api.admin.exam.app.signature.key.numerical.threshold:2}") int defaultNumericalTrustThreshold) {
|
final @Value("${sebserver.webservice.api.admin.exam.app.signature.key.numerical.threshold:2}") int defaultNumericalTrustThreshold) {
|
||||||
|
|
||||||
|
@ -90,6 +92,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
this.examConfigurationValueService = examConfigurationValueService;
|
this.examConfigurationValueService = examConfigurationValueService;
|
||||||
this.appSignatureKeyEnabled = appSignatureKeyEnabled;
|
this.appSignatureKeyEnabled = appSignatureKeyEnabled;
|
||||||
this.defaultNumericalTrustThreshold = defaultNumericalTrustThreshold;
|
this.defaultNumericalTrustThreshold = defaultNumericalTrustThreshold;
|
||||||
|
this.sebRestrictionService = sebRestrictionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -323,16 +326,21 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyExamSaved(final Exam exam) {
|
public Result<Exam> notifyExamSaved(final Exam exam) {
|
||||||
updateAdditionalExamConfigAttributes(exam.id);
|
return Result.tryCatch(() -> {
|
||||||
this.proctoringAdminService.notifyExamSaved(exam);
|
updateAdditionalExamConfigAttributes(exam.id);
|
||||||
|
this.proctoringAdminService.notifyExamSaved(exam);
|
||||||
|
return exam;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyQuitPassword(final Exam exam) {
|
public Result<Exam> applyQuitPassword(final Exam exam) {
|
||||||
this.examConfigurationValueService
|
return this.examConfigurationValueService
|
||||||
.applyQuitPasswordToConfigs(exam.id, exam.quitPassword)
|
.applyQuitPasswordToConfigs(exam.id, exam.quitPassword)
|
||||||
.getOrThrow();
|
.flatMap(id -> this.sebRestrictionService.applySEBClientRestriction(exam))
|
||||||
|
.flatMap(e -> this.examDAO.setSEBRestriction(e.id, true))
|
||||||
|
.onError(t -> log.error("Failed to update SEB Client restriction for Exam: {}", exam, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<Exam> initAdditionalAttributesForMoodleExams(final Exam exam) {
|
private Result<Exam> initAdditionalAttributesForMoodleExams(final Exam exam) {
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@ -40,15 +39,12 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||||
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
|
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.RunningExamInfo;
|
import ch.ethz.seb.sebserver.gbl.model.session.RunningExamInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SEBClientConfigDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SEBClientConfigDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService;
|
||||||
|
@ -68,7 +64,6 @@ public class ExamAPI_V1_Controller {
|
||||||
private final SEBClientConnectionService sebClientConnectionService;
|
private final SEBClientConnectionService sebClientConnectionService;
|
||||||
private final SEBClientSessionService sebClientSessionService;
|
private final SEBClientSessionService sebClientSessionService;
|
||||||
private final SEBClientConfigDAO sebClientConfigDAO;
|
private final SEBClientConfigDAO sebClientConfigDAO;
|
||||||
private final JSONMapper jsonMapper;
|
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
|
|
||||||
protected ExamAPI_V1_Controller(
|
protected ExamAPI_V1_Controller(
|
||||||
|
@ -77,7 +72,6 @@ public class ExamAPI_V1_Controller {
|
||||||
final SEBClientConnectionService sebClientConnectionService,
|
final SEBClientConnectionService sebClientConnectionService,
|
||||||
final SEBClientSessionService sebClientSessionService,
|
final SEBClientSessionService sebClientSessionService,
|
||||||
final SEBClientConfigDAO sebClientConfigDAO,
|
final SEBClientConfigDAO sebClientConfigDAO,
|
||||||
final JSONMapper jsonMapper,
|
|
||||||
@Qualifier(AsyncServiceSpringConfig.EXAM_API_EXECUTOR_BEAN_NAME) final Executor executor) {
|
@Qualifier(AsyncServiceSpringConfig.EXAM_API_EXECUTOR_BEAN_NAME) final Executor executor) {
|
||||||
|
|
||||||
this.lmsSetupDAO = lmsSetupDAO;
|
this.lmsSetupDAO = lmsSetupDAO;
|
||||||
|
@ -85,7 +79,6 @@ public class ExamAPI_V1_Controller {
|
||||||
this.sebClientConnectionService = sebClientConnectionService;
|
this.sebClientConnectionService = sebClientConnectionService;
|
||||||
this.sebClientSessionService = sebClientSessionService;
|
this.sebClientSessionService = sebClientSessionService;
|
||||||
this.sebClientConfigDAO = sebClientConfigDAO;
|
this.sebClientConfigDAO = sebClientConfigDAO;
|
||||||
this.jsonMapper = jsonMapper;
|
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import java.util.stream.Collectors;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -669,12 +668,9 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result<Exam> notifySaved(final Exam entity) {
|
protected Result<Exam> notifySaved(final Exam entity) {
|
||||||
return Result.tryCatch(() -> {
|
return this.examAdminService.notifyExamSaved(entity)
|
||||||
this.examAdminService.notifyExamSaved(entity);
|
.flatMap(this.examAdminService::applyQuitPassword)
|
||||||
this.examAdminService.applyQuitPassword(entity);
|
.flatMap(this.examSessionService::flushCache);
|
||||||
this.examSessionService.flushCache(entity);
|
|
||||||
return entity;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,9 +23,11 @@ sebserver.webservice.distributed.updateInterval=1000
|
||||||
sebserver.webservice.distributed.connectionUpdate=2000
|
sebserver.webservice.distributed.connectionUpdate=2000
|
||||||
sebserver.webservice.clean-db-on-startup=false
|
sebserver.webservice.clean-db-on-startup=false
|
||||||
|
|
||||||
|
sebserver.init.database.integrity.try-fix=true
|
||||||
|
|
||||||
# webservice setup configuration
|
# webservice setup configuration
|
||||||
sebserver.init.adminaccount.gen-on-init=false
|
sebserver.init.adminaccount.gen-on-init=false
|
||||||
sebserver.webservice.light.setup=true
|
sebserver.webservice.light.setup=false
|
||||||
sebserver.webservice.distributed=false
|
sebserver.webservice.distributed=false
|
||||||
#sebserver.webservice.master.delay.threshold=10000
|
#sebserver.webservice.master.delay.threshold=10000
|
||||||
sebserver.webservice.http.external.scheme=http
|
sebserver.webservice.http.external.scheme=http
|
||||||
|
@ -76,5 +78,39 @@ sebserver.feature.seb.screenProctoring.bundled.url=http://localhost:8090
|
||||||
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
|
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
|
||||||
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username=SEBServerAPIAccount
|
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username=SEBServerAPIAccount
|
||||||
|
|
||||||
sebserver.feature.admin.institution.enabled=true
|
#sebserver.feature.admin.user.administration.enabled=false
|
||||||
|
#sebserver.feature.admin.user.account.enabled=false
|
||||||
|
#sebserver.feature.admin.institution.enabled=false
|
||||||
|
#sebserver.feature.admin.auditlogs.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.config.connection.configuration.enabled=false
|
||||||
|
#sebserver.feature.config.exam.configuration.enabled=false
|
||||||
|
#sebserver.feature.config.template.enabled=false
|
||||||
|
#sebserver.feature.config.certificate.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.lms.setup.type.ANS_DELFT.enabled=false
|
||||||
|
#sebserver.feature.lms.setup.type.OPEN_OLAT.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.exam.ask.enabled=false
|
||||||
|
#sebserver.feature.exam.seb.restriction.enabled=false
|
||||||
|
#sebserver.feature.exam.seb.liveProctoring.enabled=false
|
||||||
|
#sebserver.feature.exam.seb.screenProctoring.enabled=false
|
||||||
|
#sebserver.feature.exam.monitoring.indicators.enabled=false
|
||||||
|
#sebserver.feature.exam.connection.config.enabled=false
|
||||||
|
#sebserver.feature.exam.seb.clientgroups.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.exam.template.enabled=false
|
||||||
|
#sebserver.feature.exam.noLMS.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.monitoring.running.exam.quit.enabled=false
|
||||||
|
#sebserver.feature.monitoring.running.exam.lockscreen.enabled=false
|
||||||
|
#sebserver.feature.monitoring.running.exam.cancel.connection.enabled=false
|
||||||
|
#sebserver.feature.monitoring.running.exam.state.filter.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.monitoring.running.exams.enabled=false
|
||||||
|
#sebserver.feature.monitoring.finished.exams.enabled=false
|
||||||
|
#sebserver.feature.monitoring.overall.export.enabled=false
|
||||||
|
#
|
||||||
|
#sebserver.feature.lms.quiz.lookup.enabled=false
|
||||||
|
#sebserver.feature.exam.administration.enabled=false
|
||||||
|
#sebserver.feature.lms.setup.enabled=false
|
||||||
|
|
Loading…
Reference in a new issue