SEBSERV-497 institution feature

This commit is contained in:
anhefti 2024-01-29 13:10:32 +01:00
parent 69334cc5d4
commit 52192619fd
18 changed files with 111 additions and 53 deletions

View file

@ -15,11 +15,45 @@ public class UserFeatures {
public static final String ATTR_FEATURE_PRIVILEGES = "featurePrivileges";
public enum Feature {
INSTITUTION("admin.institution"),
SCREEN_PROCTORING("seb.screenProctoring"),
ADMIN_INSTITUTION("admin.institution"),
ADMIN_USER_ADMINISTRATION("admin.user.administration"),
ADMIN_USER_ACCOUNT("admin.user.account"),
ADMIN_AUDIT_LOGS("admin.auditlogs"),
CONFIG_CONNECTION_CONFIGURATION("config.connection.configuration"),
CONFIG_EXAM_CONFIGURATION("config.exam.configuration"),
CONFIG_TEMPLATE("config.template"),
CONFIG_CERTIFICATE("config.certificate"),
LMS_SETUP( "lms.setup"),
LMS_SETUP_TEST("lms.setup.type.MOCKUP"),
LMS_SETUP_MOODLE("lms.setup.type.moodle"),
LMS_SETUP_MOODLE_PLUGIN("lms.setup.type.moodle.plugin"),
LMS_SETUP_OPEN_EDX("lms.setup.type.openedx"),
LMS_SETUP_ANS("lms.setup.type.ans"),
LMS_SETUP_OPEN_OLAT("lms.setup.type.openolat"),
EXAM_ASK("exam.ask"),
EXAM_SEB_RESTRICTION( "exam.seb.restriction"),
EXAM_LIVE_PROCTORING("exam.seb.liveProctoring"),
EXAM_SCREEN_PROCTORING("exam.seb.screenProctoring"),
EXAM_INDICATORS("exam.monitoring.indicators"),
EXAM_SEB_CLIENT_GROUPS("exam.seb.clientgroups"),
EXAM_TEMPLATE("exam.template"),
MONITORING_RUNNING_EXAMS("monitoring.running.exams"),
MONITORING_RUNNING_EXAM_DETAIL_VIEW("monitoring.running.exam.detailview"),
MONITORING_RUNNING_EXAM_DETAIL_VIEW_LOG_EXPORT("monitoring.running.exam.detailview.logexport"),
//more? ...
MONITORING_RUNNING_EXAM_QUIT_ALL("monitoring.running.exam.quitall"),
MONITORING_RUNNING_EXAM_LOCKSCREEN("monitoring.running.exam.lockscreen"),
// more? ...
MONITORING_FINISHED_EXAMS("monitoring.finished.exams"),
MONITORING_OVERALL_LOG_EXPORT("monitoring.overall.export"),
LIVE_PROCTORING("seb.liveProctoring"),
TEST_LMS("lms.type.MOCKUP"),
EXAM_NO_LMS("exam.noLMS"),
;

View file

@ -8,6 +8,8 @@
package ch.ethz.seb.sebserver.gui;
import ch.ethz.seb.sebserver.gbl.Constants;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@ -29,6 +31,8 @@ public class GuiServiceInfo {
private final String contextPath;
private final UriComponentsBuilder internalServerURIBuilder;
private final UriComponentsBuilder externalServerURIBuilder;
private final boolean isLightSetup;
private final boolean distributedSetup;
private final boolean multilingualGUI;
@ -41,6 +45,7 @@ public class GuiServiceInfo {
@Value("${sebserver.gui.http.external.port}") final String externalPort,
@Value("${sebserver.gui.entrypoint:/gui}") final String entryPoint,
@Value("${server.servlet.context-path:/}") final String contextPath,
@Value("${sebserver.webservice.light.setup:false}") final boolean lightSetup,
@Value("${sebserver.webservice.distributed:false}") final boolean distributedSetup,
@Value("${sebserver.gui.multilingual:false}") final boolean multilingualGUI) {
@ -77,6 +82,7 @@ public class GuiServiceInfo {
this.externalServerURIBuilder.path(contextPath);
}
this.isLightSetup = lightSetup;
this.distributedSetup = distributedSetup;
this.multilingualGUI = multilingualGUI;
}
@ -117,6 +123,9 @@ public class GuiServiceInfo {
return this.externalServerURIBuilder.cloneBuilder();
}
public boolean isLightSetup() {
return this.isLightSetup;
}
public boolean isDistributedSetup() {
return this.distributedSetup;
}

View file

@ -8,6 +8,7 @@
package ch.ethz.seb.sebserver.gui.content.activity;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.swt.SWT;
@ -104,29 +105,32 @@ public class ActivitiesPane implements TemplateComposer {
ActivityDefinition.SEB_ADMINISTRATION.displayName);
// Institution
// If current user has SEB Server Admin role, show the Institution list
if (userInfo.hasRole(UserRole.SEB_SERVER_ADMIN)) {
// institutions (list) as root
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
sebAdmin,
ActivityDefinition.INSTITUTION.displayName);
injectActivitySelection(
institutions,
actionBuilder
.newAction(ActionDefinition.INSTITUTION_VIEW_LIST)
.create());
} else if (userInfo.hasRole(UserRole.INSTITUTIONAL_ADMIN)) {
// otherwise show the form of the institution for current user
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
sebAdmin,
ActivityDefinition.INSTITUTION.displayName);
injectActivitySelection(
institutions,
actionBuilder.newAction(ActionDefinition.INSTITUTION_VIEW_FORM)
.withEntityKey(userInfo.institutionId, EntityType.INSTITUTION)
.withAttribute(AttributeKeys.READ_ONLY, "true")
.create());
if (currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)) {
// If current user has SEB Server Admin role, show the Institution list
if (userInfo.hasRole(UserRole.SEB_SERVER_ADMIN)) {
// institutions (list) as root
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
sebAdmin,
ActivityDefinition.INSTITUTION.displayName);
injectActivitySelection(
institutions,
actionBuilder
.newAction(ActionDefinition.INSTITUTION_VIEW_LIST)
.create());
} else if (userInfo.hasRole(UserRole.INSTITUTIONAL_ADMIN)) {
// otherwise show the form of the institution for current user
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
sebAdmin,
ActivityDefinition.INSTITUTION.displayName);
injectActivitySelection(
institutions,
actionBuilder.newAction(ActionDefinition.INSTITUTION_VIEW_FORM)
.withEntityKey(userInfo.institutionId, EntityType.INSTITUTION)
.withAttribute(AttributeKeys.READ_ONLY, "true")
.create());
}
}
// User Account

View file

@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.content.admin;
import java.util.Locale;
import java.util.function.BooleanSupplier;
import ch.ethz.seb.sebserver.gbl.model.user.*;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.tomcat.util.buf.StringUtils;
import org.eclipse.swt.widgets.Composite;
@ -26,11 +27,6 @@ import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
@ -169,7 +165,7 @@ public class UserAccountForm implements TemplateComposer {
Domain.USER.ATTR_LANGUAGE,
Locale.ENGLISH.getLanguage())
.addFieldIf(
isSEBAdmin,
() -> isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> FormBuilder.singleSelection(
Domain.USER.ATTR_INSTITUTION_ID,
FORM_INSTITUTION_TEXT_KEY,

View file

@ -8,9 +8,9 @@
package ch.ethz.seb.sebserver.gui.content.admin;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
@ -142,7 +142,7 @@ public class UserAccountList implements TemplateComposer {
pageContext.getParent(),
TITLE_TEXT_KEY);
final BooleanSupplier isSEBAdmin = () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
final boolean isSEBAdmin = currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
// table
@ -150,9 +150,9 @@ public class UserAccountList implements TemplateComposer {
restService.getRestCall(GetUserAccountPage.class))
.withEmptyMessage(EMPTY_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin.getAsBoolean() ? Domain.USER.ATTR_INSTITUTION_ID : Domain.USER.ATTR_NAME)
.withDefaultSort(isSEBAdmin ? Domain.USER.ATTR_INSTITUTION_ID : Domain.USER.ATTR_NAME)
.withColumnIf(
isSEBAdmin,
() -> isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<>(
Domain.USER.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY,

View file

@ -14,6 +14,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.apache.tomcat.util.buf.StringUtils;
import org.eclipse.swt.widgets.Composite;
import org.slf4j.Logger;
@ -193,7 +194,7 @@ public class UserActivityLogs implements TemplateComposer {
? UserActivityLog.FILTER_ATTR_INSTITUTION
: UserActivityLog.ATTR_USER_NAME)
.withColumnIf(
isSEBAdmin,
() -> isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<>(
UserActivityLog.FILTER_ATTR_INSTITUTION,
INSTITUTION_TEXT_KEY,

View file

@ -8,6 +8,7 @@
package ch.ethz.seb.sebserver.gui.content.configs;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
@ -112,11 +113,11 @@ public class ConfigTemplateList implements TemplateComposer {
ConfigurationType.TEMPLATE.name())
.withEmptyMessage(EMPTY_TEMPLATE_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin
.withDefaultSort(isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.CONFIGURATION_NODE.ATTR_NAME)
.withColumnIf(
() -> isSEBAdmin,
() -> isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY,

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.content.configs;
import java.util.function.Function;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.eclipse.swt.widgets.Composite;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@ -128,7 +129,7 @@ public class SEBClientConfigList implements TemplateComposer {
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME)
.withColumnIf(
() -> isSEBAdmin,
() -> isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY,

View file

@ -8,6 +8,7 @@
package ch.ethz.seb.sebserver.gui.content.configs;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
@ -140,11 +141,11 @@ public class SEBExamConfigList implements TemplateComposer {
ConfigurationType.EXAM_CONFIG.name())
.withEmptyMessage(EMPTY_CONFIG_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin
.withDefaultSort(isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.CONFIGURATION_NODE.ATTR_NAME)
.withColumnIf(
() -> isSEBAdmin,
() -> isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY,

View file

@ -8,7 +8,7 @@
package ch.ethz.seb.sebserver.gui.content.exam;
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.SCREEN_PROCTORING;
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.EXAM_SCREEN_PROCTORING;
import java.util.*;
import java.util.function.Function;
@ -251,7 +251,7 @@ public class ExamForm implements TemplateComposer {
.map(ProctoringServiceSettings::getEnableProctoring)
.getOr(false);
final boolean spsFeatureEnabled = currentUser.isFeatureEnabled(SCREEN_PROCTORING);
final boolean spsFeatureEnabled = currentUser.isFeatureEnabled(EXAM_SCREEN_PROCTORING);
final boolean screenProctoringEnabled = readonly && spsFeatureEnabled && this.restService
.getBuilder(GetScreenProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)

View file

@ -15,6 +15,7 @@ import java.util.function.BiConsumer;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.widgets.Composite;
@ -171,12 +172,12 @@ public class ExamList implements TemplateComposer {
.withPaging(this.pageSize)
.withRowDecorator(decorateOnExamConsistency(this.pageService))
.withStaticFilter(Exam.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
.withDefaultSort(isSEBAdmin.getAsBoolean()
.withDefaultSort(isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
? Domain.EXAM.ATTR_INSTITUTION_ID
: Domain.EXAM.ATTR_LMS_SETUP_ID)
.withColumnIf(
isSEBAdmin,
() -> isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<Exam>(
Domain.EXAM.ATTR_INSTITUTION_ID,
COLUMN_TITLE_INSTITUTION_KEY,

View file

@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.content.exam;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
@ -128,12 +129,12 @@ public class ExamTemplateList implements TemplateComposer {
this.pageService.entityTableBuilder(restService.getRestCall(GetExamTemplatePage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin.getAsBoolean()
.withDefaultSort(isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
? Domain.EXAM_TEMPLATE.ATTR_INSTITUTION_ID
: Domain.EXAM_TEMPLATE.ATTR_NAME)
.withColumnIf(
isSEBAdmin,
() -> isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<ExamTemplate>(
Domain.EXAM_TEMPLATE.ATTR_INSTITUTION_ID,
COLUMN_TITLE_INSTITUTION_KEY,

View file

@ -14,6 +14,7 @@ import java.util.Set;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
@ -187,7 +188,7 @@ public class LmsSetupForm implements TemplateComposer {
String.valueOf(lmsSetup.getLmsType()))
.addFieldIf(
isSEBAdmin,
() -> isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> FormBuilder.singleSelection(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
FORM_INSTITUTION_TEXT_KEY,

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.content.exam;
import java.util.function.Function;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
@ -122,9 +123,11 @@ public class LmsSetupList implements TemplateComposer {
this.pageService.entityTableBuilder(restService.getRestCall(GetLmsSetupPage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withDefaultSort(isSEBAdmin ? Domain.LMS_SETUP.ATTR_INSTITUTION_ID : Domain.LMS_SETUP.ATTR_NAME)
.withDefaultSort(isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION)
? Domain.LMS_SETUP.ATTR_INSTITUTION_ID
: Domain.LMS_SETUP.ATTR_NAME)
.withColumnIf(
() -> isSEBAdmin,
() -> isSEBAdmin && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<>(
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY,

View file

@ -14,6 +14,7 @@ import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.stream.Collectors;
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
@ -192,7 +193,7 @@ public class QuizLookupList implements TemplateComposer {
.withPaging(this.pageSize)
.withColumnIf(
isSEBAdmin,
() -> isSEBAdmin.getAsBoolean() && currentUser.isFeatureEnabled(UserFeatures.Feature.ADMIN_INSTITUTION),
() -> new ColumnDefinition<QuizData>(
QuizData.QUIZ_ATTR_INSTITUTION_ID,
INSTITUTION_TEXT_KEY,

View file

@ -8,7 +8,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
public interface FeatureService {
public static final String FEATURE_CONFIG_PREFIX = "sebserver.feature.";
String FEATURE_CONFIG_PREFIX = "sebserver.feature.";
/** Get all feature flags for current user.
*

View file

@ -75,3 +75,5 @@ sebserver.feature.seb.screenProctoring.bundled.url=http://localhost:8090
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username=SEBServerAPIAccount
sebserver.feature.admin.institution.enabled=false

View file

@ -2571,3 +2571,5 @@ sebserver.seblogs.delete.form.info=This will delete all SEB client logs from the
sebserver.seblogs.delete.action.delete=Delete All Logs
sebserver.seblogs.delete.confirm.title=Deletion Successful
sebserver.seblogs.delete.confirm.message={0} SEB client logs where successfully deleted.<br/><br/>And there where {1} errors.
sebserver.features.lightsetup.fullversion.message=MOCKUP_TEXT: This feature is not available within this SEB Server (light) setup. To use this feature you need a full version SEB Server setup. Please read more about SEB Server setups in the <a href="..." target="blank">SEB Server installation guide</a>