diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java index 7adac9fc..91e5e4a9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java @@ -49,21 +49,19 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class ExamList implements TemplateComposer { - private final PageService pageService; - private final ResourceService resourceService; - private final int pageSize; - - private final static LocTextKey emptySelectionTextKey = + private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION = + new LocTextKey("sebserver.exam.list.action.no.modify.privilege"); + private final static LocTextKey EMPTY_SELECTION_TEXT_KEY = new LocTextKey("sebserver.exam.info.pleaseSelect"); - private final static LocTextKey columnTitleLmsSetupKey = + private final static LocTextKey COLUMN_TITLE_KEY = new LocTextKey("sebserver.exam.list.column.lmssetup"); - private final static LocTextKey columnTitleNameKey = + private final static LocTextKey COLUMN_TITLE_NAME_KEY = new LocTextKey("sebserver.exam.list.column.name"); - private final static LocTextKey columnTitleTypeKey = + private final static LocTextKey COLUMN_TITLE_TYPE_KEY = new LocTextKey("sebserver.exam.list.column.type"); - private final static LocTextKey noModifyOfOutDatedExams = + private final static LocTextKey NO_MODIFY_OF_OUT_DATED_EXAMS = new LocTextKey("sebserver.exam.list.modify.out.dated"); - private final static LocTextKey emptyListTextKey = + private final static LocTextKey EMPTY_LIST_TEXT_KEY = new LocTextKey("sebserver.exam.list.empty"); private final TableFilterAttribute lmsFilter; @@ -72,6 +70,10 @@ public class ExamList implements TemplateComposer { private final TableFilterAttribute startTimeFilter = new TableFilterAttribute(CriteriaType.DATE, QuizData.FILTER_ATTR_START_TIME); + private final PageService pageService; + private final ResourceService resourceService; + private final int pageSize; + protected ExamList( final PageService pageService, final ResourceService resourceService, @@ -105,17 +107,17 @@ public class ExamList implements TemplateComposer { // table final EntityTable table = this.pageService.entityTableBuilder(restService.getRestCall(GetExamPage.class)) - .withEmptyMessage(emptyListTextKey) + .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) .withColumn(new ColumnDefinition<>( Domain.EXAM.ATTR_LMS_SETUP_ID, - columnTitleLmsSetupKey, + COLUMN_TITLE_KEY, examLmsSetupNameFunction(this.resourceService)) .withFilter(this.lmsFilter) .sortable()) .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_NAME, - columnTitleNameKey, + COLUMN_TITLE_NAME_KEY, Exam::getName) .withFilter(this.nameFilter) .sortable()) @@ -129,7 +131,7 @@ public class ExamList implements TemplateComposer { .sortable()) .withColumn(new ColumnDefinition<>( Domain.EXAM.ATTR_TYPE, - columnTitleTypeKey, + COLUMN_TITLE_TYPE_KEY, this::examTypeName) .sortable()) .withDefaultAction(actionBuilder @@ -142,17 +144,17 @@ public class ExamList implements TemplateComposer { actionBuilder .newAction(ActionDefinition.EXAM_IMPORT) - .publishIf(userGrant::im) // TODO iw instead of im? + .publishIf(userGrant::im) .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST) - .withSelect(table::getSelection, PageAction::applySingleSelection, emptySelectionTextKey) + .withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) .publishIf(table::hasAnyContent) .newAction(ActionDefinition.EXAM_MODIFY_FROM_LIST) .withSelect( - table::getSelection, + table.getGrantedSelection(currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION), action -> this.modifyExam(action, table), - emptySelectionTextKey) + EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> userGrant.im() && table.hasAnyContent()); } @@ -163,7 +165,7 @@ public class ExamList implements TemplateComposer { if (exam.startTime != null) { final DateTime now = DateTime.now(DateTimeZone.UTC); if (exam.startTime.isBefore(now)) { - throw new PageMessageException(noModifyOfOutDatedExams); + throw new PageMessageException(NO_MODIFY_OF_OUT_DATED_EXAMS); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java index 9bd96c0f..b3d30af8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupList.java @@ -45,6 +45,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @GuiProfile public class LmsSetupList implements TemplateComposer { + private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION = + new LocTextKey("sebserver.lmssetup.list.action.no.modify.privilege"); private static final LocTextKey EMPTY_SELECTION_TEXT_KEY = new LocTextKey("sebserver.lmssetup.info.pleaseSelect"); private static final LocTextKey ACTIVITY_TEXT_KEY = @@ -151,7 +153,9 @@ public class LmsSetupList implements TemplateComposer { .publishIf(() -> table.hasAnyContent()) .newAction(ActionDefinition.LMS_SETUP_MODIFY_FROM_LIST) - .withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) + .withSelect( + table.getGrantedSelection(currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION), + PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> userGrant.im() && table.hasAnyContent()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java index 152231d2..1f0b0c0d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigList.java @@ -47,6 +47,8 @@ import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType; @GuiProfile public class SebClientConfigList implements TemplateComposer { + private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION = + new LocTextKey("sebserver.clientconfig.list.action.no.modify.privilege"); private static final LocTextKey EMPTY_LIST_TEXT_KEY = new LocTextKey("sebserver.clientconfig.list.empty"); private static final LocTextKey TITLE_TEXT_KEY = @@ -155,7 +157,9 @@ public class SebClientConfigList implements TemplateComposer { .publishIf(() -> table.hasAnyContent()) .newAction(ActionDefinition.SEB_CLIENT_CONFIG_MODIFY_FROM_LIST) - .withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) + .withSelect( + table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION), + PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> clientConfigGrant.im() && table.hasAnyContent()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java index 320bb54b..9cf52df1 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java @@ -41,6 +41,8 @@ import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType; @GuiProfile public class SebExamConfigList implements TemplateComposer { + private static final LocTextKey NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION = + new LocTextKey("sebserver.examconfig.list.action.no.modify.privilege"); private static final LocTextKey EMPTY_LIST_TEXT_KEY = new LocTextKey("sebserver.examconfig.list.empty"); private static final LocTextKey TITLE_TEXT_KEY = @@ -148,11 +150,15 @@ public class SebExamConfigList implements TemplateComposer { .publishIf(() -> table.hasAnyContent()) .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST) - .withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) + .withSelect( + table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION), + PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> examConfigGrant.im() && table.hasAnyContent()) .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_FROM_LIST) - .withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) + .withSelect( + table.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION), + PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> examConfigGrant.im() && table.hasAnyContent()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java index d069b5f7..2706c9ef 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java @@ -13,7 +13,6 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.apache.commons.codec.binary.Hex; -import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; @@ -90,10 +89,6 @@ public class PassworFieldBuilder implements InputFieldBuilder { return; } - if (StringUtils.isBlank(pwd) && StringUtils.isBlank(confirm)) { - return; - } - if (!pwd.equals(confirm)) { passwordInputField.showError(viewContext .getI18nSupport() diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java index 2825c938..eede5917 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java @@ -17,6 +17,8 @@ import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.eclipse.swt.SWT; @@ -35,14 +37,17 @@ import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.GrantEntity; import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +import ch.ethz.seb.sebserver.gui.service.page.PageMessageException; import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon; @@ -257,6 +262,10 @@ public class EntityTable { } public Set getSelection() { + return getSelection(null); + } + + public Set getSelection(final Predicate grantCheck) { final TableItem[] selection = this.table.getSelection(); if (selection == null) { return Collections.emptySet(); @@ -264,10 +273,27 @@ public class EntityTable { return Arrays.asList(selection) .stream() + .filter(item -> grantCheck == null || grantCheck.test(getRowData(item))) .map(this::getRowDataId) .collect(Collectors.toSet()); } + public Supplier> getGrantedSelection( + final CurrentUser currentUser, + final LocTextKey denyMessage) { + + return () -> getSelection(e -> { + if (!(e instanceof GrantEntity)) { + return true; + } + if (currentUser.entityGrantCheck((GrantEntity) e).m()) { + return true; + } else { + throw new PageMessageException(denyMessage); + } + }); + } + private void createTableColumns() { for (final ColumnDefinition column : this.columns) { final TableColumn tableColumn = this.widgetFactory.tableColumnLocalized( diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java index a04957d7..bc301cba 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java @@ -80,7 +80,7 @@ public class AuthorizationServiceImpl implements AuthorizationService { // grants for seb client config addPrivilege(EntityType.SEB_CLIENT_CONFIGURATION) .forRole(UserRole.SEB_SERVER_ADMIN) - .withBasePrivilege(PrivilegeType.WRITE) + .withBasePrivilege(PrivilegeType.READ) .andForRole(UserRole.INSTITUTIONAL_ADMIN) .withInstitutionalPrivilege(PrivilegeType.WRITE) .andForRole(UserRole.EXAM_ADMIN) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java index a68139d0..b3248559 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java @@ -80,12 +80,21 @@ public interface BulkActionSupportDAO { throw new UnsupportedOperationException("Unsupported Bulk Action: " + bulkAction); } + /** This creates a collection of Results refer the given entity keys. + * + * @param keys Collection of entity keys to create Results from + * @return a collection of Results refer the given entity keys. */ static Collection> transformResult(final Collection keys) { return keys.stream() .map(key -> Result.of(key)) .collect(Collectors.toList()); } + /** This creates a list of Result refer to a given error for all given EntityKey instances. + * + * @param error the error that shall be referred by created Result's + * @param all all entity keys to create error Result for + * @return List of Result refer to a given error for all given EntityKey instances */ static List> handleBulkActionError(final Throwable error, final Set all) { return all.stream() .map(key -> Result. ofError(new BulkActionEntityException(key))) @@ -97,7 +106,7 @@ public interface BulkActionSupportDAO { * and applies the selection functions for each, collecting the resulting dependency EntityKeys * into one Set of all dependency keys for all source keys * - * + * * @param bulkAction The BulkAction that defines the source keys * @param selectionFunction a selection functions that gives all dependency keys for a given source key * @return */ diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java index 55ba826d..42ca57ed 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ConfigurationAttributeDAO.java @@ -15,6 +15,10 @@ import ch.ethz.seb.sebserver.gbl.util.Result; public interface ConfigurationAttributeDAO extends EntityDAO { + /** Use this to get all ConfigurationAttribute that are root attributes and no child + * attributes (has no parent reference). + * + * @return Collection of all ConfigurationAttribute that are root attributes */ Result> getAllRootAttributes(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/DAOLoggingSupport.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/DAOLoggingSupport.java index c86fc291..a982b63f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/DAOLoggingSupport.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/DAOLoggingSupport.java @@ -20,6 +20,12 @@ public final class DAOLoggingSupport { public static final Logger log = LoggerFactory.getLogger(DAOLoggingSupport.class); + /** Use this as a functional method on Result processing to + * log an error that is referenced by a given Result and skip further processing by + * using Result.skipOnError. + * + * @param result The given Result + * @return Stream of the results value or empty stream on error case */ public static Stream logAndSkipOnError(final Result result) { return Result.skipOnError( result.onError(error -> log.error("Unexpected error. Object processing is skipped: ", error))); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/EntityDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/EntityDAO.java index 05135b43..7ffaf6a8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/EntityDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/EntityDAO.java @@ -174,7 +174,7 @@ public interface EntityDAO { * This uses the EntityType defined by this instance to filter all EntityKey by the given type and * convert the matching EntityKey's to id's (PK's) * - * Use this if you need to transform a Collection of EntityKey into a extracted List of id's of a specified + * Use this if you need to transform a Collection of EntityKey into a extracted Set of id's of a specified * EntityType * * @param keys Collection of EntityKey of various types @@ -198,6 +198,15 @@ public interface EntityDAO { } } + /** Context based utility method to extract a set of id's (PK) from a collection of various EntityKey + * This uses the EntityType defined by this instance to filter all EntityKey by the given type and + * convert the matching EntityKey's to id's (PK's) + * + * Use this if you need to transform a Collection of EntityKey into a extracted List of id's of a specified + * EntityType + * + * @param keys Collection of EntityKey of various types + * @return List of id's (PK's) from the given key collection that match the concrete EntityType */ default List extractListOfPKs(final Collection keys) { return new ArrayList<>(extractPKsFromKeys(keys)); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java index f8a9b59c..db8919d6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java @@ -12,6 +12,7 @@ import org.joda.time.DateTime; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; @@ -177,7 +178,7 @@ public class FilterMap extends POSTMapper { } public static String toSQLWildcard(final String text) { - return (text == null) ? null : "%" + text + "%"; + return (text == null) ? null : Constants.PERCENTAGE + text + Constants.PERCENTAGE; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/OrientationDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/OrientationDAO.java index 0448e5e0..73f82c4d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/OrientationDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/OrientationDAO.java @@ -16,6 +16,10 @@ import ch.ethz.seb.sebserver.gbl.util.Result; public interface OrientationDAO extends EntityDAO { + /** Use this to delete all Orientation of a defined template. + * + * @param templateId the template identifier (PK) + * @return Collection of all EntityKey of Orientations that has been deleted */ Result> deleteAllOfTemplate(Long templateId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java index 4b371778..9d9c9db2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java @@ -48,7 +48,7 @@ public interface LmsAPIService { /** This can be used to test an LmsSetup connection parameter without saving or heaving * an already persistent version of an LmsSetup. - * + * * @param lmsSetup * @return */ LmsSetupTestResult testAdHoc(LmsSetup lmsSetup); @@ -76,7 +76,6 @@ public interface LmsAPIService { return q -> { final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name)); final boolean startTimeFilter = (from == null) || (q.startTime != null && q.startTime.isAfter(from)); -// final boolean endTimeFilter = (now == null) || (q.endTime != null && q.endTime.isAfter(now)); return nameFilter && startTimeFilter /* && endTimeFilter */; }; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationValueValidator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationValueValidator.java index b4625c61..6f6ca107 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationValueValidator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationValueValidator.java @@ -12,16 +12,32 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; +/** Defines a validator for validating ConfigurationValue model instances */ public interface ConfigurationValueValidator { public static final String MESSAGE_VALUE_OBJECT_NAME = "examConfigValue"; + /** The name of the validator. + * Can be used within the validator field of an ConfigurationAttribute (SQL: configuration_attribute table) + * to force a Validator to validate attribute values of a certain ConfigurationAttribute. + * + * @return name of the validator */ String name(); + /** Indicates if a ConfigurationValue is validated by this concrete validator. + * + * @param value ConfigurationValue instance + * @param attribute ConfigurationAttribute instance + * @return */ boolean validate( ConfigurationValue value, ConfigurationAttribute attribute); + /** Default convenient method to handle validation exception if validation failed. + * + * @param value ConfigurationValue instance + * @param attribute ConfigurationAttribute instance + * @throws FieldValidationException the FieldValidationException that is created and thrown */ default void throwValidationError( final ConfigurationValue value, final ConfigurationAttribute attribute) throws FieldValidationException { @@ -31,6 +47,11 @@ public interface ConfigurationValueValidator { this.createErrorMessage(value, attribute)); } + /** Default convenient method to to create an error message in case of validation failure. + * + * @param value ConfigurationValue instance + * @param attribute ConfigurationAttribute instance + * @return error message */ default String createErrorMessage( final ConfigurationValue value, final ConfigurationAttribute attribute) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java index 8efa1c25..ba4f8cae 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebClientConfigService.java @@ -38,16 +38,39 @@ public interface SebClientConfigService { " \r\n" + " \r\n"; + /** Get the server URL prefix in form of; + * [scheme{http|https}]://[server-address{DNS-name|IP}]:[port] + * + * E.g.: https://seb.server.ch:8080 + * + * @return the server URL prefix */ String getServerURL(); + /** Indicates if there is any SebClientConfiguration for a specified institution. + * + * @param institutionId the institution identifier + * @return true if there is any SebClientConfiguration for a specified institution. False otherwise */ boolean hasSebClientConfigurationForInstitution(Long institutionId); + /** Use this to auto-generate a SebClientConfiguration for a specified institution. + * clientName and clientSecret are randomly generated. + * + * @param institutionId the institution identifier + * @return the created SebClientConfig */ Result autoCreateSebClientConfigurationForInstitution(Long institutionId); + /** Use this to export a specified SebClientConfiguration within a given OutputStream. + * + * @param out OutputStream to write the export to + * @param modelId the model identifier of the SebClientConfiguration to export */ void exportSebClientConfiguration( OutputStream out, final String modelId); + /** Use this to get a encoded clientSecret for the SebClientConfiguration with specified clientId/clientName. + * + * @param clientId the clientId/clientName + * @return encoded clientSecret for that SebClientConfiguration with clientId or null of not existing */ Result getEncodedClientSecret(String clientId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigCryptor.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigCryptor.java index 8e2a55ab..25c8f2a1 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigCryptor.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigCryptor.java @@ -41,6 +41,13 @@ public interface SebConfigCryptor { final InputStream input, final SebConfigEncryptionContext context); + /** Decrypt an incoming cipher data stream to an outgoing plain text data stream + * + * IMPORTANT: This must run in a separated thread + * + * @param output the output stream to write the plain text data to + * @param input the input stream to read the cipher text from + * @param context the SebConfigEncryptionContext to access strategy specific data needed for encryption */ @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) void decrypt( final OutputStream output, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigEncryptionService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigEncryptionService.java index 848eca22..8b628e7c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigEncryptionService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebConfigEncryptionService.java @@ -52,11 +52,21 @@ public interface SebConfigEncryptionService { } + /** This can be used to stream incoming plain text data to encrypted cipher data output stream. + * + * @param output the output data stream to write the cipher text to + * @param input the input stream to read the plain text from + * @param context the SebConfigEncryptionContext to access strategy specific data needed for encryption */ void streamEncrypted( final OutputStream output, final InputStream input, SebConfigEncryptionContext context); + /** This can be used to stream incoming cipher data to decrypted plain text data output stream. + * + * @param output the output data stream to write encrypted plain text to + * @param input the input stream to read the cipher text from + * @param context the SebConfigEncryptionContext to access strategy specific data needed for encryption */ void streamDecrypted( final OutputStream output, final InputStream input, diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 689baea2..22a04457 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -163,6 +163,7 @@ sebserver.lmssetup.type.MOODLE=Moodle sebserver.lmssetup.type.OPEN_EDX=Open edX sebserver.lmssetup.list.actions=Selected LMS Setup +sebserver.lmssetup.list.action.no.modify.privilege=No Access: A LMS Setup from other institution cannot be modified. sebserver.lmssetup.list.empty=No LMS Setup has been found. Please adapt the filter or create a new LMS Setup sebserver.lmssetup.list.title=Learning Management System Setups sebserver.lmssetup.list.column.institution=Institution @@ -170,6 +171,7 @@ sebserver.lmssetup.list.column.name=Name sebserver.lmssetup.list.column.type=LMS Type sebserver.lmssetup.list.column.active=Active + sebserver.lmssetup.action.list=LMS Setup sebserver.lmssetup.action.form=LMS Setup sebserver.lmssetup.action.new=New LMS Setup @@ -243,6 +245,7 @@ sebserver.exam.list.column.type=Type sebserver.exam.list.empty=No Exams has been found. Please adapt the filter or import one from Quiz sebserver.exam.list.modify.out.dated=Running or finished exams cannot be modified. +sebserver.exam.list.action.no.modify.privilege=No Access: An Exam from other institution cannot be modified. sebserver.exam.action.list=Exam sebserver.exam.action.list.view=View Exam @@ -348,6 +351,7 @@ sebserver.clientconfig.list.column.name=Name sebserver.clientconfig.list.column.date=Creation Date sebserver.clientconfig.list.column.active=Active sebserver.clientconfig.info.pleaseSelect=Please Select a client configuration first +sebserver.clientconfig.list.action.no.modify.privilege=No Access: A SEB Client Configuration from other institution cannot be modified. sebserver.clientconfig.form.title.new=New Client Configuration sebserver.clientconfig.form.title=SEB Client Configuration @@ -379,6 +383,7 @@ sebserver.examconfig.list.actions=Selected Configuration sebserver.examconfig.list.empty=There is currently no SEB-Exam configuration available. Please create a new one sebserver.examconfig.info.pleaseSelect=Please Select an exam configuration first +sebserver.examconfig.list.action.no.modify.privilege=No Access: An Exam Configuration from other institution cannot be modified. sebserver.examconfig.action.list.new=New Exam Configuration sebserver.examconfig.action.list.view=View Configuration