SEBSERV-497 new impl and prepare for role based features
This commit is contained in:
parent
aec6bd6c04
commit
7ffef0938f
24 changed files with 325 additions and 235 deletions
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gbl;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.CollectingStrategy;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||
|
||||
@Deprecated // we need another more flexible feature service that also take new User Role and Privileges into account
|
||||
// SEBSERV-497
|
||||
public interface FeatureService {
|
||||
|
||||
String FEATURE_SETTINGS_PREFIX = "sebserver.feature.";
|
||||
|
||||
enum ConfigurableFeature {
|
||||
SCREEN_PROCTORING("seb.screenProctoring"),
|
||||
INSTITUTION("admin.institution"),
|
||||
REMOTE_PROCTORING("seb.remoteProctoring"),
|
||||
TEST_LMS("lms.testLMS"),
|
||||
EXAM_NO_LMS("exam.noLMS"),
|
||||
LIGHT_SETUP("setup.light")
|
||||
|
||||
;
|
||||
|
||||
final String namespace;
|
||||
|
||||
ConfigurableFeature(final String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isEnabled(ConfigurableFeature feature);
|
||||
|
||||
boolean isEnabled(LmsType LmsType);
|
||||
|
||||
boolean isEnabled(ProctoringServerType proctoringServerType);
|
||||
|
||||
boolean isEnabled(CollectingStrategy collectingRoomStrategy);
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ch.ethz.seb.sebserver.gbl;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.CollectingStrategy;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@WebServiceProfile
|
||||
@Deprecated // we need another more flexible feature service that also take new User Role and Privileges into account
|
||||
// SEBSERV-497
|
||||
public class FeatureServiceImpl implements FeatureService {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
public FeatureServiceImpl(final Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(final LmsType LmsType) {
|
||||
return this.environment.getProperty(toConfigName(
|
||||
FEATURE_SETTINGS_PREFIX + LmsType.class.getSimpleName() + "."
|
||||
+ LmsType.name()),
|
||||
Boolean.class,
|
||||
Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(final CollectingStrategy collectingRoomStrategy) {
|
||||
return this.environment.getProperty(toConfigName(
|
||||
FEATURE_SETTINGS_PREFIX + CollectingStrategy.class.getSimpleName() + "."
|
||||
+ collectingRoomStrategy.name()),
|
||||
Boolean.class,
|
||||
Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(final ProctoringServerType proctoringServerType) {
|
||||
return this.environment.getProperty(toConfigName(
|
||||
FEATURE_SETTINGS_PREFIX + ProctoringServerType.class.getSimpleName() + "."
|
||||
+ proctoringServerType.name()),
|
||||
Boolean.class,
|
||||
Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(final ConfigurableFeature feature) {
|
||||
return this.environment.getProperty(toConfigName(
|
||||
FEATURE_SETTINGS_PREFIX + feature.namespace + ".enabled"),
|
||||
Boolean.class,
|
||||
Boolean.FALSE);
|
||||
}
|
||||
|
||||
private String toConfigName(final String key) {
|
||||
return key.replaceAll("_", "-");
|
||||
}
|
||||
|
||||
}
|
|
@ -66,6 +66,8 @@ public final class API {
|
|||
public static final String LOGIN_PATH_SEGMENT = "/loglogin";
|
||||
public static final String LOGOUT_PATH_SEGMENT = "/loglogout";
|
||||
|
||||
public static final String FEATURES_PATH_SEGMENT = "/features";
|
||||
|
||||
public static final String INFO_ENDPOINT = "/info";
|
||||
public static final String INFO_PARAM_INST_SUFFIX = "urlSuffix";
|
||||
public static final String INFO_INST_PATH_SEGMENT = "/institution";
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package ch.ethz.seb.sebserver.gbl.model.user;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class UserFeatures {
|
||||
|
||||
public static final String ATTR_DEFAULT = "missingFeatureDefault";
|
||||
public static final String ATTR_FEATURE_PRIVILEGES = "featurePrivileges";
|
||||
|
||||
public enum Feature {
|
||||
INSTITUTION("admin.institution"),
|
||||
SCREEN_PROCTORING("seb.screenProctoring"),
|
||||
|
||||
LIVE_PROCTORING("seb.liveProctoring"),
|
||||
TEST_LMS("lms.type.MOCKUP"),
|
||||
EXAM_NO_LMS("exam.noLMS"),
|
||||
|
||||
;
|
||||
|
||||
public final String featureName;
|
||||
|
||||
Feature(final String featureName) {
|
||||
this.featureName = featureName;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonProperty(Domain.USER.ATTR_ID)
|
||||
public final String userId;
|
||||
@JsonProperty(ATTR_DEFAULT)
|
||||
public final Boolean missingFeatureDefault;
|
||||
@JsonProperty(ATTR_FEATURE_PRIVILEGES)
|
||||
public final Map<String, Boolean> featurePrivileges;
|
||||
|
||||
@JsonCreator
|
||||
public UserFeatures(
|
||||
@JsonProperty(Domain.USER.ATTR_ID) final String userId,
|
||||
@JsonProperty(ATTR_DEFAULT) final Boolean missingFeatureDefault,
|
||||
@JsonProperty(ATTR_FEATURE_PRIVILEGES) final Map<String, Boolean> featurePrivileges) {
|
||||
|
||||
this.userId = userId;
|
||||
this.missingFeatureDefault = missingFeatureDefault;
|
||||
this.featurePrivileges = Utils.immutableMapOf(featurePrivileges);
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public Boolean getMissingFeatureDefault() {
|
||||
return missingFeatureDefault;
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getFeaturePrivileges() {
|
||||
return featurePrivileges;
|
||||
}
|
||||
|
||||
public boolean isFeatureEnabled(final Feature feature) {
|
||||
return featurePrivileges.getOrDefault(feature.featureName, missingFeatureDefault);
|
||||
}
|
||||
|
||||
public boolean isFeatureEnabled(final String featureName) {
|
||||
return featurePrivileges.getOrDefault(featureName, missingFeatureDefault);
|
||||
}
|
||||
}
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gbl.FeatureService.ConfigurableFeature.LIGHT_SETUP;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -35,10 +32,7 @@ public class GuiServiceInfo {
|
|||
private final boolean distributedSetup;
|
||||
private final boolean multilingualGUI;
|
||||
|
||||
public final FeatureService featureService;
|
||||
|
||||
public GuiServiceInfo(
|
||||
final FeatureService featureService,
|
||||
@Value("${sebserver.version:--}") final String sebServerVersion,
|
||||
@Value("${server.address}") final String internalServer,
|
||||
@Value("${server.port}") final String internalPort,
|
||||
|
@ -50,7 +44,6 @@ public class GuiServiceInfo {
|
|||
@Value("${sebserver.webservice.distributed:false}") final boolean distributedSetup,
|
||||
@Value("${sebserver.gui.multilingual:false}") final boolean multilingualGUI) {
|
||||
|
||||
this.featureService = featureService;
|
||||
if (StringUtils.isBlank(externalScheme)) {
|
||||
throw new RuntimeException("Missing mandatory inital parameter sebserver.gui.http.external.servername");
|
||||
}
|
||||
|
@ -88,10 +81,6 @@ public class GuiServiceInfo {
|
|||
this.multilingualGUI = multilingualGUI;
|
||||
}
|
||||
|
||||
public boolean isLightSetup() {
|
||||
return this.featureService.isEnabled(LIGHT_SETUP);
|
||||
}
|
||||
|
||||
public String getExternalScheme() {
|
||||
return this.externalScheme;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gbl.FeatureService.ConfigurableFeature.SCREEN_PROCTORING;
|
||||
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.SCREEN_PROCTORING;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.*;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -124,7 +123,6 @@ public class ExamForm implements TemplateComposer {
|
|||
private final ExamIndicatorsList examIndicatorsList;
|
||||
private final ExamClientGroupList examClientGroupList;
|
||||
private final ExamCreateClientConfigPopup examCreateClientConfigPopup;
|
||||
private final FeatureService featureService;
|
||||
|
||||
protected ExamForm(
|
||||
final PageService pageService,
|
||||
|
@ -137,8 +135,7 @@ public class ExamForm implements TemplateComposer {
|
|||
final ExamFormConfigs examFormConfigs,
|
||||
final ExamIndicatorsList examIndicatorsList,
|
||||
final ExamClientGroupList examClientGroupList,
|
||||
final ExamCreateClientConfigPopup examCreateClientConfigPopup,
|
||||
final FeatureService featureService) {
|
||||
final ExamCreateClientConfigPopup examCreateClientConfigPopup) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
|
@ -152,7 +149,6 @@ public class ExamForm implements TemplateComposer {
|
|||
this.examIndicatorsList = examIndicatorsList;
|
||||
this.examClientGroupList = examClientGroupList;
|
||||
this.examCreateClientConfigPopup = examCreateClientConfigPopup;
|
||||
this.featureService = featureService;
|
||||
|
||||
this.consistencyMessageMapping = new HashMap<>();
|
||||
this.consistencyMessageMapping.put(
|
||||
|
@ -255,7 +251,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.map(ProctoringServiceSettings::getEnableProctoring)
|
||||
.getOr(false);
|
||||
|
||||
final boolean spsFeatureEnabled = this.featureService.isEnabled(SCREEN_PROCTORING);
|
||||
final boolean spsFeatureEnabled = currentUser.isFeatureEnabled(SCREEN_PROCTORING);
|
||||
final boolean screenProctoringEnabled = readonly && spsFeatureEnabled && this.restService
|
||||
.getBuilder(GetScreenProctoringSettings.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
|
|
|
@ -8,14 +8,13 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gbl.FeatureService.ConfigurableFeature.EXAM_NO_LMS;
|
||||
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.EXAM_NO_LMS;
|
||||
import static ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys.NEW_EXAM_NO_LMS;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
@ -149,7 +148,6 @@ public class ExamList implements TemplateComposer {
|
|||
final CurrentUser currentUser = this.resourceService.getCurrentUser();
|
||||
final RestService restService = this.resourceService.getRestService();
|
||||
final I18nSupport i18nSupport = this.resourceService.getI18nSupport();
|
||||
final FeatureService featureService = this.pageService.getFeatureService();
|
||||
|
||||
// content page layout with title
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
|
@ -286,7 +284,7 @@ public class ExamList implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.EXAM_NEW)
|
||||
.withAttribute(NEW_EXAM_NO_LMS, Constants.TRUE_STRING)
|
||||
.publishIf(() -> userGrant.iw() && featureService.isEnabled(EXAM_NO_LMS))
|
||||
.publishIf(() -> userGrant.iw() && currentUser.isFeatureEnabled(EXAM_NO_LMS))
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gbl.FeatureService.ConfigurableFeature.SCREEN_PROCTORING;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -20,7 +18,6 @@ import java.util.function.BooleanSupplier;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
|
@ -112,7 +109,6 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
private final MonitoringExamSearchPopup monitoringExamSearchPopup;
|
||||
private final SEBSendLockPopup sebSendLockPopup;
|
||||
private final MonitoringProctoringService monitoringProctoringService;
|
||||
private final FeatureService featureService;
|
||||
private final boolean distributedSetup;
|
||||
private final long pollInterval;
|
||||
|
||||
|
@ -125,7 +121,6 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
final SEBSendLockPopup sebSendLockPopup,
|
||||
final MonitoringProctoringService monitoringProctoringService,
|
||||
final GuiServiceInfo guiServiceInfo,
|
||||
final FeatureService featureService,
|
||||
@Value("${sebserver.gui.webservice.poll-interval:2000}") final long pollInterval) {
|
||||
|
||||
this.serverPushService = serverPushService;
|
||||
|
@ -139,7 +134,6 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
this.distributedSetup = guiServiceInfo.isDistributedSetup();
|
||||
this.monitoringExamSearchPopup = monitoringExamSearchPopup;
|
||||
this.sebSendLockPopup = sebSendLockPopup;
|
||||
this.featureService = featureService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -321,9 +315,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
final PageActionBuilder actionBuilder = this.pageService
|
||||
.pageActionBuilder(pageContext.clearEntityKeys());
|
||||
|
||||
final boolean spsFeatureEnabled = this.featureService.isEnabled(SCREEN_PROCTORING);
|
||||
final boolean proctoringEnabled = spsFeatureEnabled &&
|
||||
proctoringSettings != null &&
|
||||
final boolean proctoringEnabled = proctoringSettings != null &&
|
||||
BooleanUtils.toBoolean(proctoringSettings.enableProctoring);
|
||||
final boolean screenProctoringEnabled = screenProctoringSettings != null &&
|
||||
BooleanUtils.toBoolean(screenProctoringSettings.enableScreenProctoring);
|
||||
|
|
|
@ -92,7 +92,8 @@ import ch.ethz.seb.sebserver.gui.service.session.MonitoringEntry;
|
|||
@Service
|
||||
@GuiProfile
|
||||
/** Defines functionality to get resources or functions of resources to feed e.g. selection or
|
||||
* combo-box content. */
|
||||
* combo-box content.
|
||||
* */
|
||||
public class ResourceService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ResourceService.class);
|
||||
|
@ -139,8 +140,6 @@ public class ResourceService {
|
|||
public static final String EXAM_PROCTORING_FEATURES_PREFIX = "sebserver.exam.proctoring.form.features.";
|
||||
public static final String VDI_TYPE_PREFIX = "sebserver.clientconfig.form.vditype.";
|
||||
|
||||
private static final String DISABLE_LMS_FLAG = "sebserver.gui.webservice.lms.disable.";
|
||||
|
||||
public static final EnumSet<AttributeType> ATTRIBUTE_TYPES_NOT_DISPLAYED = EnumSet.of(
|
||||
AttributeType.LABEL,
|
||||
AttributeType.COMPOSITE_TABLE,
|
||||
|
@ -159,7 +158,6 @@ public class ResourceService {
|
|||
private final I18nSupport i18nSupport;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
private final EnumSet<LmsType> disabledLmsTypes;
|
||||
|
||||
protected ResourceService(
|
||||
final I18nSupport i18nSupport,
|
||||
|
@ -170,13 +168,6 @@ public class ResourceService {
|
|||
this.i18nSupport = i18nSupport;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
|
||||
this.disabledLmsTypes = EnumSet.noneOf(LmsType.class);
|
||||
final List<LmsType> disabled = Arrays.asList(LmsType.values()).stream()
|
||||
.filter(lmsType -> lmsType.features.isEmpty() ||
|
||||
environment.getProperty(DISABLE_LMS_FLAG + lmsType.name(), Boolean.class, false) == true)
|
||||
.collect(Collectors.toList());
|
||||
this.disabledLmsTypes.addAll(disabled);
|
||||
}
|
||||
|
||||
public I18nSupport getI18nSupport() {
|
||||
|
@ -206,7 +197,7 @@ public class ResourceService {
|
|||
|
||||
public List<Tuple<String>> lmsTypeResources() {
|
||||
return Arrays.stream(LmsType.values())
|
||||
.filter(lmsType -> !this.disabledLmsTypes.contains(lmsType))
|
||||
.filter(lmsType -> this.currentUser.isFeatureEnabled("lms.type." + lmsType.name()))
|
||||
.map(lmsType -> new Tuple<>(
|
||||
lmsType.name(),
|
||||
this.i18nSupport.getText(LMSSETUP_TYPE_PREFIX + lmsType.name(), lmsType.name())))
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.ScrolledComposite;
|
||||
|
@ -76,8 +75,6 @@ public interface PageService {
|
|||
|
||||
Cryptor getCryptor();
|
||||
|
||||
FeatureService getFeatureService();
|
||||
|
||||
/** Get the WidgetFactory service
|
||||
*
|
||||
* @return the WidgetFactory service */
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.function.Supplier;
|
|||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -89,7 +88,6 @@ public class PageServiceImpl implements PageService {
|
|||
private final ResourceService resourceService;
|
||||
private final CurrentUser currentUser;
|
||||
private final ServerPushService serverPushService;
|
||||
private final FeatureService featureService;
|
||||
|
||||
public PageServiceImpl(
|
||||
final Cryptor cryptor,
|
||||
|
@ -98,8 +96,7 @@ public class PageServiceImpl implements PageService {
|
|||
final PolyglotPageService polyglotPageService,
|
||||
final ResourceService resourceService,
|
||||
final CurrentUser currentUser,
|
||||
final ServerPushService serverPushService,
|
||||
final FeatureService featureService) {
|
||||
final ServerPushService serverPushService) {
|
||||
|
||||
this.cryptor = cryptor;
|
||||
this.jsonMapper = jsonMapper;
|
||||
|
@ -108,7 +105,6 @@ public class PageServiceImpl implements PageService {
|
|||
this.resourceService = resourceService;
|
||||
this.currentUser = currentUser;
|
||||
this.serverPushService = serverPushService;
|
||||
this.featureService = featureService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -116,11 +112,6 @@ public class PageServiceImpl implements PageService {
|
|||
return this.cryptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureService getFeatureService() {
|
||||
return this.featureService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WidgetFactory getWidgetFactory() {
|
||||
return this.widgetFactory;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetUserFeatures extends RestCall<UserFeatures> {
|
||||
|
||||
public GetUserFeatures() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_SINGLE,
|
||||
EntityType.USER,
|
||||
new TypeReference<UserFeatures>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.USER_ACCOUNT_ENDPOINT + API.CURRENT_USER_PATH_SEGMENT + API.FEATURES_PATH_SEGMENT);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
@ -47,6 +48,8 @@ public class CurrentUser {
|
|||
private final AuthorizationContextHolder authorizationContextHolder;
|
||||
private SEBServerAuthorizationContext authContext = null;
|
||||
private Map<RoleTypeKey, Privilege> privileges = null;
|
||||
|
||||
private UserFeatures features = null;
|
||||
private final Map<String, String> attributes;
|
||||
private final ProctoringGUIService proctoringGUIService;
|
||||
|
||||
|
@ -192,6 +195,7 @@ public class CurrentUser {
|
|||
|
||||
this.proctoringGUIService.clear();
|
||||
this.privileges = null;
|
||||
this.features = null;
|
||||
|
||||
if (isAvailable()) {
|
||||
if (this.authContext.logout()) {
|
||||
|
@ -272,6 +276,42 @@ public class CurrentUser {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isFeatureEnabled(final UserFeatures.Feature feature) {
|
||||
loadFeatures();
|
||||
return this.features != null && this.features.isFeatureEnabled(feature);
|
||||
}
|
||||
|
||||
public boolean isFeatureEnabled(final String featureName) {
|
||||
loadFeatures();
|
||||
return this.features != null && this.features.isFeatureEnabled(featureName);
|
||||
}
|
||||
|
||||
private void loadFeatures() {
|
||||
if (this.features != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateContext();
|
||||
if (this.authContext != null) {
|
||||
try {
|
||||
final WebserviceURIService webserviceURIService =
|
||||
this.authorizationContextHolder.getWebserviceURIService();
|
||||
this.features = this.authContext.getRestTemplate()
|
||||
.exchange(
|
||||
webserviceURIService.getURIBuilder()
|
||||
.path(API.USER_ACCOUNT_ENDPOINT + API.CURRENT_USER_PATH_SEGMENT + API.FEATURES_PATH_SEGMENT)
|
||||
.toUriString(),
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
UserFeatures.class)
|
||||
.getBody();
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to load user feature privileges: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Wrapper can be used for base and institutional grant checks for a specified EntityType */
|
||||
public class GrantCheck {
|
||||
private final EntityType entityType;
|
||||
|
|
|
@ -8,20 +8,14 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice;
|
||||
|
||||
import static ch.ethz.seb.sebserver.gbl.FeatureService.ConfigurableFeature.LIGHT_SETUP;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.FeatureService;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.SPSAPIAccessData;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.FeatureService;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -66,6 +60,7 @@ public class WebserviceInfo {
|
|||
private final String discoveryEndpoint;
|
||||
private final String contextPath;
|
||||
|
||||
private final boolean isLightSetup;
|
||||
private final String serverURLPrefix;
|
||||
private final boolean isDistributed;
|
||||
private final String webserviceUUID;
|
||||
|
@ -76,6 +71,7 @@ public class WebserviceInfo {
|
|||
private final Set<String> activeProfiles;
|
||||
|
||||
private final WebserviceInfoDAO webserviceInfoDAO;
|
||||
private final FeatureService featureService;
|
||||
private boolean isMaster = false;
|
||||
|
||||
@Value("${sebserver.webservice.api.admin.accessTokenValiditySeconds:3600}")
|
||||
|
@ -85,18 +81,16 @@ public class WebserviceInfo {
|
|||
@Value("${sebserver.webservice.api.exam.accessTokenValiditySeconds:43200}")
|
||||
private int examAPITokenValiditySeconds;
|
||||
|
||||
public final FeatureService featureService;
|
||||
|
||||
private final ScreenProctoringServiceBundle screenProctoringServiceBundle;
|
||||
|
||||
public WebserviceInfo(
|
||||
final WebserviceInfoDAO webserviceInfoDAO,
|
||||
final FeatureService featureService,
|
||||
final Environment environment,
|
||||
final Cryptor cryptor,
|
||||
final FeatureService featureService) {
|
||||
final Cryptor cryptor) {
|
||||
|
||||
this.featureService = featureService;
|
||||
this.webserviceInfoDAO = webserviceInfoDAO;
|
||||
this.featureService = featureService;
|
||||
this.sebServerVersion = environment.getRequiredProperty(VERSION_KEY);
|
||||
this.testProperty = environment.getProperty(WEB_SERVICE_TEST_PROPERTY, "NOT_AVAILABLE");
|
||||
this.httpScheme = environment.getRequiredProperty(WEB_SERVICE_HTTP_SCHEME_KEY);
|
||||
|
@ -135,6 +129,9 @@ public class WebserviceInfo {
|
|||
}
|
||||
this.serverURLPrefix = builder.toUriString();
|
||||
|
||||
this.isLightSetup = BooleanUtils.toBoolean(environment.getProperty(
|
||||
"sebserver.webservice.light.setup",
|
||||
Constants.FALSE_STRING));
|
||||
this.isDistributed = BooleanUtils.toBoolean(environment.getProperty(
|
||||
"sebserver.webservice.distributed",
|
||||
Constants.FALSE_STRING));
|
||||
|
@ -180,8 +177,11 @@ public class WebserviceInfo {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isLightSetup() {
|
||||
return this.featureService.isEnabled(LIGHT_SETUP);
|
||||
public Map<String, Boolean> configuredFeatures() {
|
||||
return Arrays.stream(UserFeatures.Feature.values()).collect(Collectors.toMap(
|
||||
f -> f.featureName,
|
||||
featureService::isEnabledByConfig
|
||||
));
|
||||
}
|
||||
|
||||
public boolean isMaster() {
|
||||
|
@ -276,7 +276,7 @@ public class WebserviceInfo {
|
|||
|
||||
/** Get the server URL prefix in the form of;
|
||||
* [scheme{http|https}]://[server-address{DNS-name|IP}]:[port]
|
||||
*
|
||||
* <p>
|
||||
* E.g.: https://seb.server.ch:8080
|
||||
*
|
||||
* @return the server URL prefix */
|
||||
|
@ -284,6 +284,9 @@ public class WebserviceInfo {
|
|||
return this.serverURLPrefix;
|
||||
}
|
||||
|
||||
public boolean isLightSetup() {
|
||||
return this.isLightSetup;
|
||||
}
|
||||
public boolean isDistributed() {
|
||||
return this.isDistributed;
|
||||
}
|
||||
|
|
|
@ -121,10 +121,11 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
|
|||
this.environment.getProperty("sebserver.webservice.distributed.connectionUpdate", "2000"));
|
||||
}
|
||||
|
||||
if (this.webserviceInfo.isLightSetup()) {
|
||||
SEBServerInit.INIT_LOGGER.info("----> ");
|
||||
SEBServerInit.INIT_LOGGER.info("----> SEB Server light setup enabled");
|
||||
}
|
||||
SEBServerInit.INIT_LOGGER.info("----> ");
|
||||
SEBServerInit.INIT_LOGGER.info("----> Configured Features:");
|
||||
this.webserviceInfo.configuredFeatures().entrySet().stream().forEach(entry -> {
|
||||
SEBServerInit.INIT_LOGGER.info("----> {} --> {}", entry.getKey(), entry.getValue());
|
||||
});
|
||||
|
||||
SEBServerInit.INIT_LOGGER.info("----> ");
|
||||
SEBServerInit.INIT_LOGGER.info("----> Working with ping service: {}",
|
||||
|
|
|
@ -18,13 +18,14 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
||||
|
||||
/** A service to check authorization grants for a given user for entity-types and -instances
|
||||
*
|
||||
* <p>
|
||||
* If there is one or more GrantEntity objects within an authenticated user-request, this service
|
||||
* can be used check the authenticated user access grant within the object. Check if a given user
|
||||
* has write, modify or even read rights on an entity instance or on an entity type. */
|
||||
|
@ -40,17 +41,19 @@ public interface AuthorizationService {
|
|||
* @return all registered Privileges */
|
||||
Collection<Privilege> getAllPrivileges();
|
||||
|
||||
|
||||
|
||||
/** Check grant on privilege type for specified EntityType and for the given user and institution.
|
||||
*
|
||||
* <p>
|
||||
* This makes a privilege grant check for every UserRole given. The first found successful grant
|
||||
* will immediately return true
|
||||
*
|
||||
* <p>
|
||||
* The privilege grant check function always checks first the base privilege with no institutional or owner grant.
|
||||
* If user has a grant on base privileges this returns true without checking further institutional or owner grant
|
||||
* If user has no base privilege grant the function checks further grants, first the institutional grant, where
|
||||
* the institution id and the users institution id must match and further more the owner grant, where ownerId
|
||||
* and the users id must match.
|
||||
*
|
||||
* <p>
|
||||
* see Privilege.hasGrant for more information how the overall grant function works
|
||||
*
|
||||
* @param privilegeType The privilege type to check
|
||||
|
@ -71,7 +74,7 @@ public interface AuthorizationService {
|
|||
Set<UserRole> userRoles);
|
||||
|
||||
/** Check grant for a given privilege type and entity type for the current user.
|
||||
*
|
||||
* <p>
|
||||
* NOTE: This only checks the base privilege grant because there is no Entity specific information
|
||||
*
|
||||
* @param privilegeType the privilege type to check
|
||||
|
@ -109,11 +112,11 @@ public interface AuthorizationService {
|
|||
|
||||
/** Check base privilege grant and institutional privilege grant for a given privilege type
|
||||
* on a given entity type.
|
||||
*
|
||||
* <p>
|
||||
* If the question is similar like this:
|
||||
* "Has the current user that belongs to institution A the right to create an entity of
|
||||
* type X on institution B", then this is the answer, use:
|
||||
*
|
||||
* <p>
|
||||
* hasPrivilege(PrivilegeType.WRITE, EntityType.X, B)
|
||||
*
|
||||
* @param privilegeType the privilege type to check
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
||||
public interface FeatureService {
|
||||
|
||||
public static final String FEATURE_CONFIG_PREFIX = "sebserver.feature.";
|
||||
|
||||
/** Get all feature flags for current user.
|
||||
*
|
||||
* @return UserFeatures all feature flags for current user */
|
||||
Result<UserFeatures> getCurrentUserFeatures();
|
||||
|
||||
Map<UserFeatures.Feature, Boolean> getUserRoleDefaults(UserRole role);
|
||||
|
||||
boolean isEnabledByConfig(final UserFeatures.Feature feature);
|
||||
}
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
|||
|
||||
import java.security.Principal;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
||||
|
@ -29,10 +30,10 @@ public interface UserService {
|
|||
SEBServerUser getCurrentUser();
|
||||
|
||||
/** Extracts the internal SEBServerUser from a given Principal.
|
||||
*
|
||||
* <p>
|
||||
* This is attended to apply some known strategies to extract the internal user from Principal. If there is no
|
||||
* internal user found on the given Principal, a IllegalArgumentException is thrown.
|
||||
*
|
||||
* <p>
|
||||
* If there is certainly a internal user within the given Principal but no strategy that finds it, this method can
|
||||
* be extended with the needed strategy.
|
||||
*
|
||||
|
@ -54,7 +55,7 @@ public interface UserService {
|
|||
|
||||
/** Used to set authentication on different thread.
|
||||
*
|
||||
* @param authentication */
|
||||
* @param authentication the Authentication context*/
|
||||
void setAuthenticationIfAbsent(Authentication authentication);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.FeatureService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@WebServiceProfile
|
||||
public class FeatureServiceImpl implements FeatureService {
|
||||
|
||||
private final Environment environment;
|
||||
private final UserService userService;
|
||||
private final UserDAO userDAO;
|
||||
|
||||
public FeatureServiceImpl(
|
||||
final Environment environment,
|
||||
final UserService userService,
|
||||
final UserDAO userDAO) {
|
||||
|
||||
this.environment = environment;
|
||||
this.userService = userService;
|
||||
this.userDAO = userDAO;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Result<UserFeatures> getCurrentUserFeatures() {
|
||||
return Result.tryCatch(() -> {
|
||||
final String userId = userService.getCurrentUser().getUserInfo().uuid;
|
||||
final EnumSet<Feature> userEnabledFeatures = getUserEnabledFeatures(userId);
|
||||
final Map<String, Boolean> features = Arrays.stream(Feature.values()).collect(Collectors.toMap(
|
||||
f -> f.featureName,
|
||||
f -> isEnabledByConfig(f) && userEnabledFeatures.contains(f)
|
||||
));
|
||||
|
||||
return new UserFeatures(userId, true, features);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Feature, Boolean> getUserRoleDefaults(final UserRole role) {
|
||||
// TODO implement this when user role based features are available
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public EnumSet<Feature> getUserEnabledFeatures(final String userId) {
|
||||
// TODO implement this when user role based features are available
|
||||
return EnumSet.allOf(Feature.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByConfig(final Feature feature) {
|
||||
final String configName = getConfigName(feature);
|
||||
try {
|
||||
return this.environment.getProperty(configName, Boolean.class, false)
|
||||
|| this.environment.getProperty(configName + ".enabled", Boolean.class);
|
||||
} catch (final Exception e) {
|
||||
// NOTE: for now if there is not explicitly disabled from config, the feature is considered enabled
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private String getConfigName(final Feature feature) {
|
||||
return getConfigName(feature.featureName);
|
||||
}
|
||||
|
||||
private String getConfigName(final String featureName) {
|
||||
return FEATURE_CONFIG_PREFIX + featureName;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,9 @@ import java.util.List;
|
|||
import javax.validation.Valid;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.*;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Pair;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.FeatureService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ScreenProctoringService;
|
||||
import org.mybatis.dynamic.sql.SqlTable;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
@ -38,12 +40,6 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
|
||||
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.UserLogActivityType;
|
||||
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.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
|
||||
|
@ -66,6 +62,8 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
|||
private final PasswordEncoder userPasswordEncoder;
|
||||
private final ScreenProctoringService screenProctoringService;
|
||||
|
||||
private final FeatureService featureService;
|
||||
|
||||
public UserAccountController(
|
||||
final UserDAO userDAO,
|
||||
final AuthorizationService authorization,
|
||||
|
@ -75,6 +73,7 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
|||
final ApplicationEventPublisher applicationEventPublisher,
|
||||
final BeanValidationService beanValidationService,
|
||||
final ScreenProctoringService screenProctoringService,
|
||||
final FeatureService featureService,
|
||||
@Qualifier(WebSecurityConfig.USER_PASSWORD_ENCODER_BEAN_NAME) final PasswordEncoder userPasswordEncoder) {
|
||||
|
||||
super(authorization,
|
||||
|
@ -87,6 +86,7 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
|||
this.userDAO = userDAO;
|
||||
this.userPasswordEncoder = userPasswordEncoder;
|
||||
this.screenProctoringService = screenProctoringService;
|
||||
this.featureService = featureService;
|
||||
}
|
||||
|
||||
@RequestMapping(path = API.CURRENT_USER_PATH_SEGMENT, method = RequestMethod.GET)
|
||||
|
@ -97,6 +97,14 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
|||
.getUserInfo();
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.CURRENT_USER_PATH_SEGMENT + API.FEATURES_PATH_SEGMENT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public UserFeatures getCurrentUserFeatures() {
|
||||
return this.featureService.getCurrentUserFeatures().getOrThrow();
|
||||
}
|
||||
|
||||
@RequestMapping(path = API.LOGIN_PATH_SEGMENT, method = RequestMethod.POST)
|
||||
public void logLogin() {
|
||||
this.userActivityLogDAO.logLogin(this.authorization
|
||||
|
|
|
@ -68,7 +68,8 @@ springdoc.swagger-ui.oauth.clientSecret=${sebserver.password}
|
|||
#springdoc.default-consumes-media-type=application/x-www-form-urlencoded
|
||||
springdoc.paths-to-exclude=/exam-api,/exam-api/discovery,/sebserver/error,/sebserver/check,/oauth,/exam-api/v1/*
|
||||
|
||||
|
||||
# features
|
||||
sebserver.feature.seb.screenProctoring.enabled=true
|
||||
sebserver.feature.seb.screenProctoring.bundled=true
|
||||
sebserver.feature.seb.screenProctoring.bundled.url=http://localhost:8090
|
||||
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
|
||||
|
|
|
@ -28,6 +28,3 @@ logging.level.com.zaxxer.hikari=INFO
|
|||
sebserver.http.client.connect-timeout=15000
|
||||
sebserver.http.client.connection-request-timeout=10000
|
||||
sebserver.http.client.read-timeout=60000
|
||||
|
||||
# features
|
||||
sebserver.feature.seb.screenProctoring.enabled=true
|
|
@ -38,6 +38,7 @@ sebserver.webservice.api.admin.clientSecret=${sebserver.password}
|
|||
sebserver.webservice.internalSecret=${sebserver.password}
|
||||
|
||||
### webservice setup configuration
|
||||
sebserver.webservice.light.setup=false
|
||||
sebserver.webservice.forceMaster=false
|
||||
sebserver.webservice.distributed=false
|
||||
sebserver.webservice.distributed.updateInterval=2000
|
||||
|
@ -92,4 +93,17 @@ sebserver.webservice.api.exam.indicator.thresholds=[{"value":5000.0,"color":"ffc
|
|||
sebserver.webservice.configtemplate.examconfig.default.name=__startDate__ __examName__
|
||||
sebserver.webservice.configtemplate.examconfig.default.description=This has automatically been created from the exam template: __examTemplateName__ at: __currentDate__
|
||||
|
||||
# features
|
||||
sebserver.feature.admin.institution.enabled=true
|
||||
sebserver.feature.seb.liveProctoring.enabled=true
|
||||
sebserver.feature.lms.type.MOCKUP.enabled=true
|
||||
sebserver.feature.exam.noLMS.enabled=true
|
||||
|
||||
sebserver.feature.seb.screenProctoring.enabled=false
|
||||
sebserver.feature.seb.screenProctoring.bundled=true
|
||||
sebserver.feature.seb.screenProctoring.bundled.url=sps-service:8090
|
||||
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
|
||||
sebserver.feature.seb.screenProctoring.bundled.clientPassword=${sps.sebserver.client.secret}
|
||||
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username=SEBServerAPIAccount
|
||||
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.password=${sps.sebserver.password}
|
||||
|
||||
|
|
|
@ -62,20 +62,3 @@ security.require-ssl=false
|
|||
# Disable this if a redirect is done by a reverse proxy for example
|
||||
sebserver.ssl.redirect.enabled=false
|
||||
sebserver.ssl.redirect.html.port=8080
|
||||
|
||||
# features
|
||||
sebserver.feature.setup.light.enabled=false
|
||||
sebserver.feature.admin.institution.enabled=true
|
||||
sebserver.feature.seb.remoteProctoring.enabled=true
|
||||
sebserver.feature.lms.testLMS.enabled=true
|
||||
sebserver.feature.exam.noLMS.enabled=true
|
||||
|
||||
sebserver.feature.seb.screenProctoring.enabled=false
|
||||
sebserver.feature.seb.screenProctoring.bundled=true
|
||||
sebserver.feature.seb.screenProctoring.bundled.url=sps-service:8090
|
||||
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
|
||||
sebserver.feature.seb.screenProctoring.bundled.clientPassword=${sps.sebserver.client.secret}
|
||||
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username=SEBServerAPIAccount
|
||||
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.password=${sps.sebserver.password}
|
||||
|
||||
sebserver.feature.CollectingRoomStrategy.SEB-GROUP=false
|
||||
|
|
Loading…
Reference in a new issue