From d2d3d3f8642b32bd10cfbae18802add1de365f48 Mon Sep 17 00:00:00 2001 From: anhefti Date: Mon, 28 Nov 2022 16:37:26 +0100 Subject: [PATCH] SEBSERV-335 feature complete --- .../seb/sebserver/gbl/model/exam/Exam.java | 2 - .../gui/content/action/ActionDefinition.java | 5 ++ .../exam/AddSecurityKeyGrantPopup.java | 51 +++++++++++++-- .../content/exam/ExamSignatureKeyForm.java | 4 +- .../monitoring/SignatureKeyGrantPopup.java | 4 +- .../seckey/GrantAppSignatureKey.java} | 10 +-- .../seckey/SaveAppSignatureKeySettings.java | 2 +- .../exam/impl/ExamAdminServiceImpl.java | 2 + .../institution/SecurityKeyService.java | 11 +--- .../impl/SecurityKeyServiceImpl.java | 63 +++++++++++++------ .../api/ExamAdministrationController.java | 30 ++++----- .../api/ExamMonitoringController.java | 24 ------- src/main/resources/messages.properties | 3 + 13 files changed, 125 insertions(+), 86 deletions(-) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/{session/GrantClientConnectionSecurityKey.java => exam/seckey/GrantAppSignatureKey.java} (81%) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Exam.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Exam.java index 8157715c..2d3eaf96 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Exam.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/Exam.java @@ -31,8 +31,6 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; import ch.ethz.seb.sebserver.gbl.model.GrantEntity; -import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; -import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; import ch.ethz.seb.sebserver.gbl.util.Utils; @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java index 7bdbc575..681afd54 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java @@ -425,6 +425,11 @@ public enum ActionDefinition { ImageIcon.NO_SHIELD, PageStateDefinitionImpl.SECURITY_KEY_EDIT, ActionCategory.FORM), + EXAM_RELOAD_SECURITY_KEY_VIEW( + new LocTextKey("sebserver.exam.signaturekey.action.edit"), + ImageIcon.SHIELD, + PageStateDefinitionImpl.SECURITY_KEY_EDIT, + ActionCategory.FORM), EXAM_SECURITY_KEY_SAVE_SETTINGS( new LocTextKey("sebserver.exam.signaturekey.action.save"), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/AddSecurityKeyGrantPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/AddSecurityKeyGrantPopup.java index 6b40b5dc..325748e7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/AddSecurityKeyGrantPopup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/AddSecurityKeyGrantPopup.java @@ -27,16 +27,18 @@ import ch.ethz.seb.sebserver.gbl.model.institution.AppSignatureKeyInfo; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.util.Utils; +import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.form.FormBuilder; import ch.ethz.seb.sebserver.gui.form.FormHandle; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer; import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageService; +import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent; import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetClientConnections; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GrantClientConnectionSecurityKey; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.seckey.GrantAppSignatureKey; import ch.ethz.seb.sebserver.gui.table.ColumnDefinition; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @@ -55,6 +57,11 @@ public class AddSecurityKeyGrantPopup { private static final LocTextKey TITLE_TEXT_FORM_TAG = new LocTextKey("sebserver.exam.signaturekey.seb.add.tag"); + private static final LocTextKey TABLE_TITLE = + new LocTextKey("sebserver.exam.signaturekey.list.title"); + private static final LocTextKey TABLE_TITLE_TOOLTIP = + new LocTextKey("sebserver.exam.signaturekey.list.title" + Constants.TOOLTIP_TEXT_KEY_SUFFIX); + private static final LocTextKey TABLE_COLUMN_NAME = new LocTextKey("sebserver.exam.signaturekey.list.name"); private static final LocTextKey TABLE_COLUMN_INFO = @@ -77,6 +84,7 @@ public class AddSecurityKeyGrantPopup { action.pageContext().getParent().getShell(), this.pageService.getWidgetFactory()); dialog.setDialogWidth(800); + //dialog.setDialogHeight(600); final Predicate> applyGrant = formHandle -> applyGrant( pageContext, @@ -144,7 +152,17 @@ public class AddSecurityKeyGrantPopup { .withQueryParam(API.PARAM_MODEL_ID_LIST, clientConnectionIds) .call() .onSuccess(connections -> { - final List list = new ArrayList<>(); + + widgetFactory.addFormSubContextHeader( + formContext.getParent(), + TABLE_TITLE, + TABLE_TITLE_TOOLTIP); + + final List list = new ArrayList<>(this.pageService + .getRestService() + .getBuilder(GetClientConnections.class) + .withQueryParam(API.PARAM_MODEL_ID_LIST, clientConnectionIds) + .call().getOrThrow()); this.pageService.staticListTableBuilder(list, EntityType.CLIENT_CONNECTION) .withPaging(10) @@ -165,7 +183,8 @@ public class AddSecurityKeyGrantPopup { TABLE_COLUMN_STATUS, row -> this.pageService.getResourceService() .localizedClientConnectionStatusName(row.getStatus())) - .widthProportion(1)); + .widthProportion(1)) + .compose(formContext); }); @@ -184,15 +203,35 @@ public class AddSecurityKeyGrantPopup { final Long connectioId = appSignatureKeyInfo.connectionIds.keySet().iterator().next(); - return this.pageService + final boolean hasValue = this.pageService .getRestService() - .getBuilder(GrantClientConnectionSecurityKey.class) + .getBuilder(GrantAppSignatureKey.class) .withURIVariable(API.PARAM_PARENT_MODEL_ID, String.valueOf(appSignatureKeyInfo.examId)) .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(connectioId)) .withFormBinding(formHandle.getFormBinding()) .call() - .onError(formHandle::handleError) + .onError(error -> { + if (error.getMessage().contains("\"messageCode\":\"1010\"")) { + pageContext.publishInfo(new LocTextKey("sebserver.monitoring.signaturegrant.message.granted")); + } else { + formHandle.handleError(error); + } + }) .hasValue(); + + if (hasValue) { + + final PageContext reloadContext = pageContext.withEntityKey(pageContext.getParentEntityKey()); + final PageAction action = this.pageService.pageActionBuilder(reloadContext) + .newAction(ActionDefinition.EXAM_RELOAD_SECURITY_KEY_VIEW) + .create(); + this.pageService.firePageEvent( + new ActionEvent(action), + action.pageContext()); + + } + + return hasValue; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamSignatureKeyForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamSignatureKeyForm.java index ad7d9e09..bd2a189c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamSignatureKeyForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ExamSignatureKeyForm.java @@ -68,8 +68,6 @@ public class ExamSignatureKeyForm implements TemplateComposer { new LocTextKey("sebserver.exam.signaturekey.keylist.key"); private static final LocTextKey APP_SIG_KEY_LIST_NUM_CLIENTS = new LocTextKey("sebserver.exam.signaturekey.keylist.clients"); - private static final LocTextKey APP_SIG_KEY_LIST_CLIENT_IDS = - new LocTextKey("sebserver.exam.signaturekey.keylist.clientids"); private static final LocTextKey APP_SIG_KEY_LIST_EMPTY_SELECTION_TEXT_KEY = new LocTextKey("sebserver.exam.signaturekey.keylist.pleaseSelect"); @@ -78,7 +76,7 @@ public class ExamSignatureKeyForm implements TemplateComposer { private static final LocTextKey GRANT_LIST_TITLE_TOOLTIP = new LocTextKey("sebserver.exam.signaturekey.grantlist.title" + Constants.TOOLTIP_TEXT_KEY_SUFFIX); private static final LocTextKey GRANT_LIST_EMPTY_LIST_TEXT_KEY = - new LocTextKey("sebserver.exam.signaturekey.grantlist..empty"); + new LocTextKey("sebserver.exam.signaturekey.grantlist.empty"); private static final LocTextKey GRANT_LIST_KEY = new LocTextKey("sebserver.exam.signaturekey.grantlist.key"); private static final LocTextKey GRANT_LIST_TAG = diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/SignatureKeyGrantPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/SignatureKeyGrantPopup.java index f1924593..d0074640 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/SignatureKeyGrantPopup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/monitoring/SignatureKeyGrantPopup.java @@ -29,7 +29,7 @@ import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GrantClientConnectionSecurityKey; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.seckey.GrantAppSignatureKey; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; @Lazy @@ -131,7 +131,7 @@ public class SignatureKeyGrantPopup { return this.pageService .getRestService() - .getBuilder(GrantClientConnectionSecurityKey.class) + .getBuilder(GrantAppSignatureKey.class) .withURIVariable(API.PARAM_PARENT_MODEL_ID, examKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, connectionKey.modelId) .withFormBinding(formHandle.getFormBinding()) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GrantClientConnectionSecurityKey.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/GrantAppSignatureKey.java similarity index 81% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GrantClientConnectionSecurityKey.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/GrantAppSignatureKey.java index 6dfd14c7..3e872ce8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GrantClientConnectionSecurityKey.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/GrantAppSignatureKey.java @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session; +package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.seckey; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpMethod; @@ -24,9 +24,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class GrantClientConnectionSecurityKey extends RestCall { +public class GrantAppSignatureKey extends RestCall { - public GrantClientConnectionSecurityKey() { + public GrantAppSignatureKey() { super(new TypeKey<>( CallType.GET_SINGLE, EntityType.SEB_SECURITY_KEY_REGISTRY, @@ -34,9 +34,9 @@ public class GrantClientConnectionSecurityKey extends RestCall { }), HttpMethod.POST, MediaType.APPLICATION_FORM_URLENCODED, - API.EXAM_MONITORING_ENDPOINT + + API.EXAM_ADMINISTRATION_ENDPOINT + API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + - API.EXAM_MONITORING_SIGNATURE_KEY_ENDPOINT + + API.EXAM_ADMINISTRATION_SEB_SECURITY_KEY_GRANTS_PATH_SEGMENT + API.MODEL_ID_VAR_PATH_SEGMENT); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/SaveAppSignatureKeySettings.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/SaveAppSignatureKeySettings.java index 73e0ee98..d6364a7d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/SaveAppSignatureKeySettings.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/exam/seckey/SaveAppSignatureKeySettings.java @@ -33,7 +33,7 @@ public class SaveAppSignatureKeySettings extends RestCall { new TypeReference() { }), HttpMethod.POST, - MediaType.APPLICATION_JSON, + MediaType.APPLICATION_FORM_URLENCODED, API.EXAM_ADMINISTRATION_ENDPOINT + API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + API.EXAM_ADMINISTRATION_SEB_SECURITY_KEY_INFO_PATH_SEGMENT); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java index e9c3a246..2c0646d4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java @@ -111,6 +111,8 @@ public class ExamAdminServiceImpl implements ExamAdminService { .error("Failed to store ADDITIONAL_ATTR_STATISTICAL_GRANT_COUNT_THRESHOLD: ", error)); } + this.examDAO.setModified(examId); + }).flatMap(v -> this.examDAO.byPK(examId)); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/SecurityKeyService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/SecurityKeyService.java index 8f0757d1..f1270cd8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/SecurityKeyService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/SecurityKeyService.java @@ -42,12 +42,6 @@ public interface SecurityKeyService { * @return Result refer to the list of security key registry entries or to an error when happened */ Result> getSecurityKeyEntries(Long institutionId, Long examId, KeyType type); - /** Register a new security key entry in the registry. - * - * @param key The security key data - * @return Result refer to the newly created and stored security key entry or to an error when happened */ - Result registerSecurityKey(SecurityKey key); - /** Register SEB client connection App-Signature-Key as a new global security key registry entry * This is equivalent to make a global grant for specified App-Signature-Key of given SEB client connection. * @@ -57,15 +51,14 @@ public interface SecurityKeyService { * @return Result refer to the newly created security key entry or to an error when happened */ Result registerGlobalAppSignatureKey(Long institutionId, Long connectionId, String tag); - /** Register SEB client connection App-Signature-Key as a new exam based security key registry entry - * This is equivalent to make a exam specific grant for specified App-Signature-Key of given SEB client connection. + /** Grants an App-Signature-Key sent by a SEB client and register it within the granted key registry * * @param institutionId The institution identifier * @param examId The exam identifier for the exam based grant * @param connectionId The client connection identifier * @param tag A Tag for user identification of the grant within the registry * @return Result refer to the newly created security key entry or to an error when happened */ - Result registerExamAppSignatureKey(Long institutionId, Long examId, Long connectionId, String tag); + Result grantAppSignatureKey(Long institutionId, Long examId, Long connectionId, String tag); /** Used to apply a SEB client App-signature-Key check for a given App-Signature-Key sent by the SEB. * Note: This also stores the given App-Signature-Key sent by SEB if not already stored for the SEB connection. diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/impl/SecurityKeyServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/impl/SecurityKeyServiceImpl.java index a03a3374..bea367a0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/impl/SecurityKeyServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/institution/impl/SecurityKeyServiceImpl.java @@ -26,7 +26,9 @@ import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; import ch.ethz.seb.sebserver.gbl.api.EntityType; +import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.institution.AppSignatureKeyInfo; @@ -121,6 +123,12 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { final Long connectionId, final String tag) { + if (StringUtils.isEmpty(tag)) { + throw new FieldValidationException( + Domain.SEB_SECURITY_KEY_REGISTRY.ATTR_TAG, + "securityKeyGrant:tag:mandatory"); + } + if (log.isDebugEnabled()) { log.debug("Register app-signature-key global grant. ConnectionId: {} tag: {}", connectionId, @@ -138,12 +146,18 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { } @Override - public Result registerExamAppSignatureKey( + public Result grantAppSignatureKey( final Long institutionId, final Long examId, final Long connectionId, final String tag) { + if (StringUtils.isEmpty(tag)) { + throw new FieldValidationException( + Domain.SEB_SECURITY_KEY_REGISTRY.ATTR_TAG, + "securityKeyGrant:tag:notNull"); + } + if (log.isDebugEnabled()) { log.debug("Register app-signature-key exam grant. Exam: {} connectionId: {} tag: {}", examId, @@ -239,11 +253,11 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { } } - @Override - public Result registerSecurityKey(final SecurityKey key) { - return this.encryptInternal(key) - .flatMap(this.securityKeyRegistryDAO::createNew); - } +// @Override +// public Result registerSecurityKey(final SecurityKey key) { +// return this.encryptInternal(key) +// .flatMap(this.securityKeyRegistryDAO::createNew); +// } @Override public Result deleteSecurityKeyGrant(final Long keyId) { @@ -366,7 +380,9 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { final Long examId, final String decryptedSignature) { - System.out.println("****************** statisticalCheck: " + decryptedSignature); + if (log.isDebugEnabled()) { + log.debug("Apply statistical security check update for exam {}", examId); + } // if there is no exam known yet, no statistical check can be applied if (examId == null) { @@ -378,8 +394,7 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { // TODO if cert encryption is available check if exam has defined cert for decryption final Certificate cert = null; - final int matches = this.clientConnectionDAO - .getAllActiveConnectionTokens(examId) + final int matches = this.clientConnectionDAO.getConnectionTokens(examId) .map(tokens -> tokens.stream() .map(this.examSessionCacheService::getClientConnection) .filter(cc -> matchOtherClientConnection(cc.clientConnection, decryptedSignature, cert)) @@ -410,12 +425,20 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { return false; // NOTE: not supported yet } + if (cc.status != ConnectionStatus.ACTIVE && cc.status != ConnectionStatus.CLOSED) { + return false; + } + + if (log.isDebugEnabled()) { + log.debug("Apply statistical security check update for client connection {}", cc); + } + return Objects.equals( decryptedSignature, decryptStoredSignatureForConnection(cc)); } catch (final Exception e) { - log.warn("Failed to get and decrypt app signature key for client connection: {}", cc, e); + log.warn("Failed to apply statistical security check update for client connection: {}", cc, e); return false; } } @@ -501,16 +524,16 @@ public class SecurityKeyServiceImpl implements SecurityKeyService { .getOr(1); } - private Result encryptInternal(final SecurityKey key) { - return Result.tryCatch(() -> new SecurityKey( - key.id, - key.institutionId, - key.keyType, - Utils.toString(this.cryptor.encrypt(key.key).getOrThrow()), - key.tag, - key.examId, - key.examTemplateId)); - } +// private Result encryptInternal(final SecurityKey key) { +// return Result.tryCatch(() -> new SecurityKey( +// key.id, +// key.institutionId, +// key.keyType, +// Utils.toString(this.cryptor.encrypt(key.key).getOrThrow()), +// key.tag, +// key.examId, +// key.examTemplateId)); +// } private Collection getKeysForRead(final Collection keys) { return keys.stream() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java index 6636b87b..9702d63a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java @@ -17,14 +17,12 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.mybatis.dynamic.sql.SqlTable; import org.springframework.http.MediaType; -import org.springframework.util.MultiValueMap; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -216,7 +214,7 @@ public class ExamAdministrationController extends EntityController { path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + API.EXAM_ADMINISTRATION_SEB_SECURITY_KEY_INFO_PATH_SEGMENT, method = RequestMethod.POST, - produces = MediaType.APPLICATION_JSON_VALUE) + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public void saveAppSignatureKeySettings( @PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId, @RequestParam( @@ -258,28 +256,32 @@ public class ExamAdministrationController extends EntityController { } @RequestMapping( - path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT - + API.EXAM_ADMINISTRATION_SEB_SECURITY_KEY_GRANTS_PATH_SEGMENT, + path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + + API.EXAM_ADMINISTRATION_SEB_SECURITY_KEY_GRANTS_PATH_SEGMENT + + API.MODEL_ID_VAR_PATH_SEGMENT, method = RequestMethod.POST, + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public SecurityKey newSecurityGrant( - @PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId, + public SecurityKey grantAppSignatureKey( @RequestParam( name = API.PARAM_INSTITUTION_ID, required = true, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, - @RequestParam final MultiValueMap allRequestParams, - final HttpServletRequest request) { + @PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId, + @PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long connectionId, + @RequestParam(name = Domain.SEB_SECURITY_KEY_REGISTRY.ATTR_TAG, required = false) final String tagName) { this.checkWritePrivilege(institutionId); + return this.examDAO.byPK(examId) .flatMap(this::checkReadAccess) - .flatMap(exam -> { - final POSTMapper postMap = new POSTMapper(allRequestParams, request.getQueryString()) - .putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); - return this.securityKeyService.registerSecurityKey(new SecurityKey(postMap)); - }) + .flatMap(exam -> this.securityKeyService.grantAppSignatureKey( + institutionId, + examId, + connectionId, + tagName)) .flatMap(this.userActivityLogDAO::logCreate) + .onSuccess(key -> this.securityKeyService.updateAppSignatureKeyGrants(examId)) .getOrThrow(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java index 0cb6f692..81c790e9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java @@ -462,30 +462,6 @@ public class ExamMonitoringController { } } - @RequestMapping( - path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + - API.EXAM_MONITORING_SIGNATURE_KEY_ENDPOINT + - API.MODEL_ID_VAR_PATH_SEGMENT, - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - public SecurityKey grantAppSignatureKey( - @RequestParam( - name = API.PARAM_INSTITUTION_ID, - required = true, - defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, - @PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long examId, - @PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long connectionId, - @RequestParam(name = Domain.SEB_SECURITY_KEY_REGISTRY.ATTR_TAG, required = true) final String tagName) { - - checkPrivileges(institutionId, examId); - - return this.securityKeyService - .registerExamAppSignatureKey(institutionId, examId, connectionId, tagName) - .onSuccess(key -> this.securityKeyService.updateAppSignatureKeyGrants(examId)) - .getOrThrow(); - } - @RequestMapping( path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT + API.EXAM_MONITORING_SIGNATURE_KEY_ENDPOINT + diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index e94f86be..94572174 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -819,10 +819,13 @@ sebserver.exam.signaturekey.keylist.clientids.tooltip=List of SEB Client session sebserver.exam.signaturekey.keylist.pleaseSelect=Please select an App Signature Key from the list. sebserver.exam.signaturekey.seb.title=App Signature Key +sebserver.exam.signaturekey.seb.add.title=Grant App Signature Key sebserver.exam.signaturekey.seb.add.info=Please set a meaningful Tag Name and use OK to confirm this security key as granted. sebserver.exam.signaturekey.seb.add.signature=Key Hash sebserver.exam.signaturekey.seb.add.tag=Tag Name +sebserver.exam.signaturekey.list.title=SEB client connections +sebserver.exam.signaturekey.list.title.tooltip=List of SEB client connections with this App Signature Key sebserver.exam.signaturekey.list.name=SEB Session ID sebserver.exam.signaturekey.list.info=SEB Client Info sebserver.exam.signaturekey.list.status=Connection Status