SEBSERV-135 - gui implementation

This commit is contained in:
anhefti 2021-04-22 08:49:52 +02:00
parent ab8ac01e05
commit 18dce53170
19 changed files with 456 additions and 76 deletions

View file

@ -202,5 +202,6 @@ public final class API {
public static final String CERTIFICATE_ALIAS = "alias";
public static final String CERTIFICATE_FILE_TYPE = "fileType";
public static final String CERTIFICATE_PASSWORD_ATTR_NAME = "certPassword";
public static final String CERTIFICATE_ALIAS_VAR_PATH_SEGMENT = "/{" + CERTIFICATE_ALIAS + "}";
}

View file

@ -20,17 +20,17 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity;
@JsonIgnoreProperties(ignoreUnknown = true)
public class CertificateData implements Entity {
public class CertificateInfo implements Entity {
public static enum CertificateType {
UNKNOWN,
SSL_TLS,
CA,
IDENTITY
DIGITAL_SIGNATURE,
DATA_ENCIPHERMENT,
KEY_CERT_SIGN
}
public static enum CertificateFileType {
PEM("pem", "crt"),
PEM("pem", "crt", "cer"),
PKCS12("p12", "pfx");
private String[] extentions;
@ -61,22 +61,17 @@ public class CertificateData implements Entity {
@JsonProperty(ATTR_CERT_TYPE)
public final EnumSet<CertificateType> types;
@JsonProperty(ATTR_CERT_BASE_64)
public final String certBase64;
@JsonCreator
public CertificateData(
public CertificateInfo(
@JsonProperty(ATTR_ALIAS) final String alias,
@JsonProperty(ATTR_ALIAS) final DateTime validityFrom,
@JsonProperty(ATTR_ALIAS) final DateTime validityTo,
@JsonProperty(ATTR_CERT_TYPE) final EnumSet<CertificateType> types,
@JsonProperty(ATTR_CERT_BASE_64) final String certBase64) {
@JsonProperty(ATTR_CERT_TYPE) final EnumSet<CertificateType> types) {
this.alias = alias;
this.validityFrom = validityFrom;
this.validityTo = validityTo;
this.types = types;
this.certBase64 = certBase64;
}
public String getAlias() {
@ -95,10 +90,6 @@ public class CertificateData implements Entity {
return this.types;
}
public String getCertBase64() {
return this.certBase64;
}
@Override
public String getModelId() {
return this.alias;
@ -130,7 +121,7 @@ public class CertificateData implements Entity {
return false;
if (getClass() != obj.getClass())
return false;
final CertificateData other = (CertificateData) obj;
final CertificateInfo other = (CertificateInfo) obj;
if (this.alias == null) {
if (other.alias != null)
return false;

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2021 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.gui.content;
import org.eclipse.swt.widgets.Composite;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
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.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.cert.GetCertificatePage;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
import ch.ethz.seb.sebserver.gui.table.EntityTable;
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
@Lazy
@Component
@GuiProfile
public class CertificateList implements TemplateComposer {
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
new LocTextKey("sebserver.certificate.list.empty");
private static final LocTextKey TITLE_TEXT_KEY =
new LocTextKey("sebserver.certificate.list.title");
private static final LocTextKey ALIAS_TEXT_KEY =
new LocTextKey("sebserver.certificate.list.column.alias");
private static final LocTextKey VALID_FROM_KEY =
new LocTextKey("sebserver.certificate.list.column.validFrom");
private static final LocTextKey VALID_TO_KEY =
new LocTextKey("sebserver.certificate.list.column.validTo");
private static final LocTextKey TYPE_TEXT_KEY =
new LocTextKey("sebserver.certificate.list.column.type");
private final TableFilterAttribute aliasFilter = new TableFilterAttribute(
CriteriaType.TEXT,
CertificateInfo.FILTER_ATTR_ALIAS);
private final PageService pageService;
private final RestService restService;
private final CurrentUser currentUser;
private final int pageSize;
protected CertificateList(
final PageService pageService,
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
this.pageService = pageService;
this.restService = pageService.getRestService();
this.currentUser = pageService.getCurrentUser();
this.pageSize = pageSize;
}
@Override
public void compose(final PageContext pageContext) {
final Composite content = this.pageService
.getWidgetFactory()
.defaultPageLayout(
pageContext.getParent(),
TITLE_TEXT_KEY);
// table
final EntityTable<CertificateInfo> table =
this.pageService.entityTableBuilder(this.restService.getRestCall(GetCertificatePage.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withColumn(new ColumnDefinition<>(
CertificateInfo.ATTR_ALIAS,
ALIAS_TEXT_KEY,
CertificateInfo::getAlias)
.sortable()
.withFilter(this.aliasFilter))
.withColumn(new ColumnDefinition<>(
CertificateInfo.ATTR_VALIDITY_FROM,
VALID_FROM_KEY,
CertificateInfo::getValidityFrom)
.sortable())
.withColumn(new ColumnDefinition<>(
CertificateInfo.ATTR_VALIDITY_TO,
VALID_TO_KEY,
CertificateInfo::getValidityTo)
.sortable())
.withColumn(new ColumnDefinition<>(
CertificateInfo.ATTR_CERT_TYPE,
TYPE_TEXT_KEY,
this::getTypeInfo))
.withSelectionListener(this.pageService.getSelectionPublisher(
pageContext,
ActionDefinition.SEB_CERTIFICATE_REMOVE))
.compose(pageContext.copyOf(content));
}
private String getTypeInfo(final CertificateInfo certificateInfo) {
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
//i18nSupport.getText("")
// TODO
return "";
}
}

View file

@ -25,7 +25,8 @@ public enum ActionCategory {
SEB_CONFIG_TEMPLATE_LIST(new LocTextKey("sebserver.configtemplate.list.actions"), 1),
SEB_CONFIG_TEMPLATE_ATTRIBUTE_LIST(new LocTextKey("sebserver.configtemplate.attr.list.actions"), 1),
RUNNING_EXAM_LIST(new LocTextKey("sebserver.monitoring.exam.list.actions"), 1),
EXAM_MONITORING_NOTIFICATION_LIST(new LocTextKey("sebserver.monitoring.exam.connection.notificationlist.actions"),
EXAM_MONITORING_NOTIFICATION_LIST(new LocTextKey(
"sebserver.monitoring.exam.connection.notificationlist.actions"),
1),
CLIENT_EVENT_LIST(new LocTextKey("sebserver.monitoring.exam.connection.list.actions"), 1),
LOGS_USER_ACTIVITY_LIST(new LocTextKey("sebserver.userlogs.list.actions"), 1),

View file

@ -612,6 +612,20 @@ public enum ActionDefinition {
PageStateDefinitionImpl.SEB_EXAM_CONFIG_TEMPLATE_VIEW,
ActionCategory.FORM),
SEB_CERTIFICATE_LIST(
new LocTextKey("sebserver.certificate.action.list"),
PageStateDefinitionImpl.SEB_CERTIFICATE_LIST),
SEB_CERTIFICATE_IMPORT(
new LocTextKey("sebserver.certificate.action.import"),
ImageIcon.IMPORT,
PageStateDefinitionImpl.SEB_CERTIFICATE_LIST,
ActionCategory.FORM),
SEB_CERTIFICATE_REMOVE(
new LocTextKey("sebserver.certificate.action.remove"),
ImageIcon.DELETE,
PageStateDefinitionImpl.SEB_CERTIFICATE_LIST,
ActionCategory.FORM),
RUNNING_EXAM_VIEW_LIST(
new LocTextKey("sebserver.monitoring.action.list"),
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM_LIST),

View file

@ -229,6 +229,18 @@ public class ActivitiesPane implements TemplateComposer {
.create());
}
// Certificate management
if (!isSupporterOnly) {
final TreeItem examConfigTemplate = this.widgetFactory.treeItemLocalized(
sebConfigs,
ActivityDefinition.SEB_CERTIFICATE_MANAGEMENT.displayName);
injectActivitySelection(
examConfigTemplate,
actionBuilder
.newAction(ActionDefinition.SEB_CERTIFICATE_LIST)
.create());
}
sebConfigs.setExpanded(this.currentUser.get().hasAnyRole(UserRole.EXAM_ADMIN));
}

View file

@ -24,6 +24,7 @@ public enum ActivityDefinition implements Activity {
SEB_CLIENT_CONFIG(new LocTextKey("sebserver.clientconfig.list.title")),
SEB_EXAM_CONFIG(new LocTextKey("sebserver.examconfig.action.list")),
SEB_EXAM_CONFIG_TEMPLATE(new LocTextKey("sebserver.configtemplate.action.list")),
SEB_CERTIFICATE_MANAGEMENT(new LocTextKey("sebserver.certificate.action.list")),
MONITORING(new LocTextKey("sebserver.overall.activity.title.monitoring")),
MONITORING_EXAMS(new LocTextKey("sebserver.monitoring.action.list")),
SEB_CLIENT_LOGS(new LocTextKey("sebserver.logs.activity.seblogs"));

View file

@ -8,6 +8,7 @@
package ch.ethz.seb.sebserver.gui.content.activity;
import ch.ethz.seb.sebserver.gui.content.CertificateList;
import ch.ethz.seb.sebserver.gui.content.ConfigTemplateAttributeForm;
import ch.ethz.seb.sebserver.gui.content.ConfigTemplateForm;
import ch.ethz.seb.sebserver.gui.content.ConfigTemplateList;
@ -25,8 +26,8 @@ import ch.ethz.seb.sebserver.gui.content.QuizLookupList;
import ch.ethz.seb.sebserver.gui.content.SEBClientConfigForm;
import ch.ethz.seb.sebserver.gui.content.SEBClientConfigList;
import ch.ethz.seb.sebserver.gui.content.SEBClientEvents;
import ch.ethz.seb.sebserver.gui.content.SEBExamConfigList;
import ch.ethz.seb.sebserver.gui.content.SEBExamConfigForm;
import ch.ethz.seb.sebserver.gui.content.SEBExamConfigList;
import ch.ethz.seb.sebserver.gui.content.SEBSettingsForm;
import ch.ethz.seb.sebserver.gui.content.UserAccountChangePasswordForm;
import ch.ethz.seb.sebserver.gui.content.UserAccountForm;
@ -80,6 +81,9 @@ public enum PageStateDefinitionImpl implements PageStateDefinition {
ConfigTemplateAttributeForm.class,
ActivityDefinition.SEB_EXAM_CONFIG_TEMPLATE),
SEB_CERTIFICATE_LIST(Type.LIST_VIEW, CertificateList.class,
ActivityDefinition.SEB_CERTIFICATE_MANAGEMENT),
MONITORING_RUNNING_EXAM_LIST(Type.LIST_VIEW, MonitoringRunningExamList.class, ActivityDefinition.MONITORING_EXAMS),
MONITORING_RUNNING_EXAM(Type.FORM_VIEW, MonitoringRunningExam.class, ActivityDefinition.MONITORING_EXAMS),
MONITORING_CLIENT_CONNECTION(Type.FORM_VIEW, MonitoringClientConnection.class, ActivityDefinition.MONITORING_EXAMS),

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 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.gui.service.remote.webservice.api.seb.cert;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class AddCertificate extends RestCall<CertificateInfo> {
public AddCertificate() {
super(new TypeKey<>(
CallType.UNDEFINED,
EntityType.CERTIFICATE,
new TypeReference<CertificateInfo>() {
}),
HttpMethod.POST,
MediaType.APPLICATION_OCTET_STREAM,
API.CERTIFICATE_ENDPOINT);
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 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.gui.service.remote.webservice.api.seb.cert;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetCertificate extends RestCall<CertificateInfo> {
public GetCertificate() {
super(new TypeKey<>(
CallType.GET_SINGLE,
EntityType.CERTIFICATE,
new TypeReference<CertificateInfo>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.CERTIFICATE_ENDPOINT + API.CERTIFICATE_ALIAS_VAR_PATH_SEGMENT);
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 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.gui.service.remote.webservice.api.seb.cert;
import java.util.List;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetCertificateNames extends RestCall<List<EntityName>> {
public GetCertificateNames() {
super(new TypeKey<>(
CallType.GET_NAMES,
EntityType.CERTIFICATE,
new TypeReference<List<EntityName>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.CERTIFICATE_ENDPOINT + API.NAMES_PATH_SEGMENT);
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2021 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.gui.service.remote.webservice.api.seb.cert;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class GetCertificatePage extends RestCall<Page<CertificateInfo>> {
public GetCertificatePage() {
super(new TypeKey<>(
CallType.GET_PAGE,
EntityType.CERTIFICATE,
new TypeReference<Page<CertificateInfo>>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.CERTIFICATE_ENDPOINT);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2021 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.gui.service.remote.webservice.api.seb.cert;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class RemoveCertificate extends RestCall<Void> {
public RemoveCertificate() {
super(new TypeKey<>(
CallType.GET_SINGLE,
EntityType.CERTIFICATE,
new TypeReference<>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
API.CERTIFICATE_ENDPOINT + API.CERTIFICATE_ALIAS_VAR_PATH_SEGMENT);
}
}

View file

@ -10,14 +10,13 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.EnumSet;
import java.util.NoSuchElementException;
import org.joda.time.DateTime;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData.CertificateType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo.CertificateType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
import ch.ethz.seb.sebserver.gbl.util.Result;
import io.micrometer.core.instrument.util.StringUtils;
@ -27,22 +26,21 @@ public interface CertificateDAO {
Result<Certificates> getCertificates(Long institutionId);
Result<CertificateData> addCertificate(Long institutionId, String alias, Certificate certificate);
Result<CertificateInfo> addCertificate(Long institutionId, String alias, Certificate certificate);
Result<Certificates> removeCertificate(Long institutionId, String alias);
static Result<CertificateData> getDataFromCertificate(final Certificates certificates, final String alias) {
static Result<CertificateInfo> getDataFromCertificate(final Certificates certificates, final String alias) {
return Result.tryCatch(() -> {
final X509Certificate certificate = (X509Certificate) certificates.keyStore.engineGetCertificate(alias);
if (certificate != null) {
final X509Certificate cert = certificate;
return new CertificateData(
return new CertificateInfo(
extractAlias(cert, alias),
new DateTime(cert.getNotBefore()),
new DateTime(cert.getNotAfter()),
getTypes(cert),
Base64.getEncoder().encodeToString(cert.getEncoded()));
getTypes(cert));
} else {
throw new NoSuchElementException("X509Certificate with alias: " + alias);
@ -75,17 +73,17 @@ public interface CertificateDAO {
// digitalSignature
if (keyUsage[0]) {
result.add(CertificateType.SSL_TLS);
result.add(CertificateType.DIGITAL_SIGNATURE);
}
// dataEncipherment
if (keyUsage[3]) {
result.add(CertificateType.IDENTITY);
result.add(CertificateType.DATA_ENCIPHERMENT);
}
// keyCertSign
if (keyUsage[5]) {
result.add(CertificateType.CA);
result.add(CertificateType.KEY_CERT_SIGN);
}
if (result.isEmpty()) {

View file

@ -26,7 +26,7 @@ import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
@ -68,7 +68,7 @@ public class CertificateDAOImpl implements CertificateDAO {
@Override
@Transactional
public Result<CertificateData> addCertificate(
public Result<CertificateInfo> addCertificate(
final Long institutionId,
final String alias,
final Certificate certificate) {

View file

@ -14,22 +14,22 @@ import java.util.function.Predicate;
import org.apache.commons.lang3.StringUtils;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData.CertificateFileType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData.CertificateType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo.CertificateFileType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo.CertificateType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
public interface CertificateService {
Result<CertificateData> getCertificateData(Long institutionId, String alias);
Result<CertificateInfo> getCertificateInfo(Long institutionId, String alias);
Result<Collection<CertificateData>> getCertificateData(Long institutionId, FilterMap filterMap);
Result<Collection<CertificateInfo>> getCertificateInfo(Long institutionId, FilterMap filterMap);
Result<Certificates> getCertificates(Long institutionId);
Result<CertificateData> addCertificate(
Result<CertificateInfo> addCertificate(
Long institutionId,
CertificateFileType certificateFileType,
String alias,
@ -37,19 +37,21 @@ public interface CertificateService {
Result<Certificates> removeCertificate(Long institutionId, String alias);
Result<Collection<CertificateData>> toCertificateData(Certificates certificates);
Result<Collection<CertificateInfo>> toCertificateInfo(Certificates certificates);
default Predicate<CertificateData> createFilter(final FilterMap filterMap) {
final String aliasFilter = filterMap.getString(CertificateData.FILTER_ATTR_ALIAS);
Result<String> getBase64Encoded(Long institutionId, String alias);
default Predicate<CertificateInfo> createFilter(final FilterMap filterMap) {
final String aliasFilter = filterMap.getString(CertificateInfo.FILTER_ATTR_ALIAS);
final CertificateType typeFilter = filterMap.getEnum(
CertificateData.FILTER_ATTR_TYPE,
CertificateInfo.FILTER_ATTR_TYPE,
CertificateType.class);
return certificateData -> {
return certificateInfo -> {
if (StringUtils.isNotBlank(aliasFilter) &&
!certificateData.alias.contains(aliasFilter)) {
!certificateInfo.alias.contains(aliasFilter)) {
return false;
}
if (typeFilter != null && !certificateData.types.contains(typeFilter)) {
if (typeFilter != null && !certificateInfo.types.contains(typeFilter)) {
return false;
}

View file

@ -9,8 +9,11 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import java.io.InputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -18,8 +21,8 @@ import java.util.stream.Collectors;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData.CertificateFileType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo.CertificateFileType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
@ -39,7 +42,7 @@ public class CertificateServiceImpl implements CertificateService {
}
@Override
public Result<CertificateData> getCertificateData(final Long institutionId, final String alias) {
public Result<CertificateInfo> getCertificateInfo(final Long institutionId, final String alias) {
return this.certificateDAO
.getCertificates(institutionId)
@ -47,7 +50,7 @@ public class CertificateServiceImpl implements CertificateService {
}
@Override
public Result<Collection<CertificateData>> getCertificateData(
public Result<Collection<CertificateInfo>> getCertificateInfo(
final Long institutionId,
final FilterMap filterMap) {
@ -64,7 +67,7 @@ public class CertificateServiceImpl implements CertificateService {
}
@Override
public Result<CertificateData> addCertificate(
public Result<CertificateInfo> addCertificate(
final Long institutionId,
final CertificateFileType certificateFileType,
final String alias,
@ -83,13 +86,29 @@ public class CertificateServiceImpl implements CertificateService {
}
@Override
public Result<Collection<CertificateData>> toCertificateData(final Certificates certificates) {
public Result<Collection<CertificateInfo>> toCertificateInfo(final Certificates certificates) {
return Result.tryCatch(() -> getDataFromCertificates(certificates));
}
private Collection<CertificateData> getDataFromCertificates(
@Override
public Result<String> getBase64Encoded(final Long institutionId, final String alias) {
return this.certificateDAO
.getCertificates(institutionId)
.map(certs -> certs.keyStore.engineGetCertificate(alias))
.map(this::getBase64Encoded);
}
private String getBase64Encoded(final Certificate cert) {
try {
return Base64.getEncoder().encodeToString(cert.getEncoded());
} catch (final CertificateEncodingException e) {
throw new RuntimeException();
}
}
private Collection<CertificateInfo> getDataFromCertificates(
final Certificates certificates,
final Predicate<CertificateData> predicate) {
final Predicate<CertificateInfo> predicate) {
return certificates.aliases
.stream()
@ -99,7 +118,7 @@ public class CertificateServiceImpl implements CertificateService {
.collect(Collectors.toList());
}
private Collection<CertificateData> getDataFromCertificates(final Certificates certificates) {
private Collection<CertificateInfo> getDataFromCertificates(final Certificates certificates) {
return getDataFromCertificates(certificates, data -> true);
}

View file

@ -39,9 +39,8 @@ import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateData.CertificateFileType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.CertificateInfo.CertificateFileType;
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
@ -117,7 +116,7 @@ public class CertificateController {
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public Page<CertificateData> getPage(
public Page<CertificateInfo> getPage(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
@ -131,8 +130,8 @@ public class CertificateController {
checkReadPrivilege(institutionId);
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
final Collection<CertificateData> certificates = this.certificateService
.getCertificateData(institutionId, filterMap)
final Collection<CertificateInfo> certificates = this.certificateService
.getCertificateInfo(institutionId, filterMap)
.getOrThrow();
return this.paginationService.buildPageFromList(
@ -160,7 +159,7 @@ public class CertificateController {
checkReadPrivilege(institutionId);
return this.certificateService
.getCertificateData(
.getCertificateInfo(
institutionId,
new FilterMap(allRequestParams, request.getQueryString()))
.getOrThrow()
@ -170,19 +169,19 @@ public class CertificateController {
}
@RequestMapping(
path = API.MODEL_ID_VAR_PATH_SEGMENT,
path = API.CERTIFICATE_ALIAS_VAR_PATH_SEGMENT,
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public CertificateData getBy(
public CertificateInfo getAlias(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@PathVariable final String modelId) {
@PathVariable final String alias) {
return this.certificateService
.getCertificateData(institutionId, modelId)
.getCertificateInfo(institutionId, alias)
.getOrThrow();
}
@ -190,7 +189,7 @@ public class CertificateController {
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public Certificates loadCertificate(
public CertificateInfo loadCertificate(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
@ -212,8 +211,7 @@ public class CertificateController {
inputStream = new BufferedInputStream(request.getInputStream());
return this.certificateService.addCertificate(institutionId, certificateFileType, alias, inputStream)
.map(certData -> this.userActivityLogDAO.log(UserLogActivityType.IMPORT, certData))
.flatMap(certData -> this.certificateService.getCertificates(institutionId))
.flatMap(certData -> this.userActivityLogDAO.log(UserLogActivityType.IMPORT, certData))
.getOrThrow();
} catch (final Exception e) {
@ -226,21 +224,20 @@ public class CertificateController {
}
@RequestMapping(
path = API.CERTIFICATE_ALIAS_VAR_PATH_SEGMENT,
method = RequestMethod.DELETE,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public Certificates deleteCertificate(
public void deleteCertificate(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestHeader(
name = API.CERTIFICATE_ALIAS,
required = true) final String alias) {
@PathVariable final String alias) {
this.checkWritePrivilege(institutionId);
return this.certificateService.removeCertificate(institutionId, alias)
this.certificateService.removeCertificate(institutionId, alias)
.getOrThrow();
}
@ -258,15 +255,15 @@ public class CertificateController {
institutionId);
}
private static Function<Collection<CertificateData>, List<CertificateData>> pageSort(final String sort) {
private static Function<Collection<CertificateInfo>, List<CertificateInfo>> pageSort(final String sort) {
return certificates -> {
final List<CertificateData> list = certificates.stream().collect(Collectors.toList());
final List<CertificateInfo> list = certificates.stream().collect(Collectors.toList());
if (StringUtils.isBlank(sort)) {
return list;
}
final String sortBy = PageSortOrder.decode(sort);
if (sortBy.equals(CertificateData.FILTER_ATTR_ALIAS)) {
if (sortBy.equals(CertificateInfo.FILTER_ATTR_ALIAS)) {
list.sort(Comparator.comparing(cert -> cert.alias));
}

View file

@ -1533,6 +1533,21 @@ sebserver.configtemplate.attr.action.setdefault=Set Default Values
sebserver.configtemplate.attr.action.template=View Configuration Template
sebserver.certificate.action.list=Certificates
sebserver.certificate.action.import=Import Certificate
sebserver.certificate.action.remove=Remove Selected Certificates
sebserver.certificate.list.title=Certificates
sebserver.certificate.list.column.alias=Alias
sebserver.certificate.list.column.validFrom=Valid From
sebserver.certificate.list.column.validTo=Valid To
sebserver.certificate.list.column.type=Types
sebserver.certificate.list.column.type.UNKNOWN=Unknown
sebserver.certificate.list.column.type.DIGITAL_SIGNATURE=TLS/SSL
sebserver.certificate.list.column.type.DATA_ENCIPHERMENT=Identity
sebserver.certificate.list.column.type.KEY_CERT_SIGN=CA
################################
# Monitoring
################################