institutional logo implementation
This commit is contained in:
parent
6b8ef6c694
commit
64f10c6455
18 changed files with 412 additions and 195 deletions
|
@ -57,6 +57,8 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
|||
@Order(6)
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ErrorController {
|
||||
|
||||
@Value("${sebserver.webservice.api.admin.endpoint}")
|
||||
private String adminEndpoint;
|
||||
@Value("${sebserver.webservice.api.redirect.unauthorized}")
|
||||
private String unauthorizedRedirect;
|
||||
|
||||
|
@ -82,7 +84,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E
|
|||
web
|
||||
.ignoring()
|
||||
.antMatchers("/error")
|
||||
.antMatchers(API.LOGO_ENDPOINT + "/*");
|
||||
.antMatchers(this.adminEndpoint + API.INFO_ENDPOINT + "/**");
|
||||
}
|
||||
|
||||
@RequestMapping("/error")
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gbl.api;
|
|||
|
||||
public final class API {
|
||||
|
||||
public static final String PARAM_LOGO_IMAGE = "logoImageBase64";
|
||||
public static final String PARAM_INSTITUTION_ID = "institutionId";
|
||||
public static final String PARAM_MODEL_ID = "modelId";
|
||||
public static final String PARAM_ENTITY_TYPE = "entityType";
|
||||
|
@ -17,8 +18,13 @@ public final class API {
|
|||
public static final String INSTITUTION_VAR_PATH_SEGMENT = "/{" + PARAM_INSTITUTION_ID + "}";
|
||||
public static final String MODEL_ID_VAR_PATH_SEGMENT = "/{" + PARAM_MODEL_ID + "}";
|
||||
|
||||
public static final String LOGO_ENDPOINT = "/logo";
|
||||
public static final String INSTITUTIONAL_LOGO_PATH = LOGO_ENDPOINT + INSTITUTION_VAR_PATH_SEGMENT;
|
||||
public static final String INFO_ENDPOINT = "/info";
|
||||
|
||||
public static final String LOGO_PATH_SEGMENT = "/logo";
|
||||
public static final String INSTITUTIONAL_LOGO_PATH = LOGO_PATH_SEGMENT + "/{urlSuffix}";
|
||||
|
||||
public static final String PRIVILEGES_PATH_SEGMENT = "/privileges";
|
||||
public static final String PRIVILEGES_ENDPOINT = INFO_ENDPOINT + PRIVILEGES_PATH_SEGMENT;
|
||||
|
||||
public static final String INSTITUTION_ENDPOINT = "/institution";
|
||||
|
||||
|
|
|
@ -19,28 +19,28 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
|||
public final class Privilege {
|
||||
|
||||
/** The RoleTypeKey defining the UserRole and EntityType for this Privilege */
|
||||
@JsonProperty
|
||||
@JsonProperty("roleTypeKey")
|
||||
public final RoleTypeKey roleTypeKey;
|
||||
|
||||
/** Defines a base-privilege type that defines the overall access for an entity-type */
|
||||
@JsonProperty
|
||||
@JsonProperty("basePrivilege")
|
||||
public final PrivilegeType basePrivilege;
|
||||
|
||||
/** Defines an institutional privilege type that defines the institutional restricted access for a
|
||||
* entity-type */
|
||||
@JsonProperty
|
||||
@JsonProperty("institutionalPrivilege")
|
||||
public final PrivilegeType institutionalPrivilege;
|
||||
|
||||
/** Defines an ownership privilege type that defines the ownership restricted access for a entity-type */
|
||||
@JsonProperty
|
||||
@JsonProperty("ownershipPrivilege")
|
||||
public final PrivilegeType ownershipPrivilege;
|
||||
|
||||
@JsonCreator
|
||||
public Privilege(
|
||||
final RoleTypeKey roleTypeKey,
|
||||
final PrivilegeType basePrivilege,
|
||||
final PrivilegeType institutionalPrivilege,
|
||||
final PrivilegeType ownershipPrivilege) {
|
||||
@JsonProperty("roleTypeKey") final RoleTypeKey roleTypeKey,
|
||||
@JsonProperty("basePrivilege") final PrivilegeType basePrivilege,
|
||||
@JsonProperty("institutionalPrivilege") final PrivilegeType institutionalPrivilege,
|
||||
@JsonProperty("ownershipPrivilege") final PrivilegeType ownershipPrivilege) {
|
||||
|
||||
this.roleTypeKey = roleTypeKey;
|
||||
this.basePrivilege = basePrivilege;
|
||||
|
@ -85,13 +85,16 @@ public final class Privilege {
|
|||
/** A key that combines UserRole EntityType identity */
|
||||
public static final class RoleTypeKey {
|
||||
|
||||
@JsonProperty
|
||||
@JsonProperty("entityType")
|
||||
public final EntityType entityType;
|
||||
@JsonProperty
|
||||
@JsonProperty("userRole")
|
||||
public final UserRole userRole;
|
||||
|
||||
@JsonCreator
|
||||
public RoleTypeKey(final EntityType type, final UserRole role) {
|
||||
public RoleTypeKey(
|
||||
@JsonProperty("entityType") final EntityType type,
|
||||
@JsonProperty("userRole") final UserRole role) {
|
||||
|
||||
this.entityType = type;
|
||||
this.userRole = role;
|
||||
}
|
||||
|
|
|
@ -8,22 +8,13 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
@ -35,10 +26,8 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
|||
@Order(4)
|
||||
public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Value("${sebserver.gui.entrypoint}")
|
||||
private String guiEndpointPath;
|
||||
@Value("${sebserver.webservice.api.redirect.unauthorized}")
|
||||
private String unauthorizedRedirect;
|
||||
@Autowired
|
||||
private InstitutionalAuthenticationEntryPoint institutionalAuthenticationEntryPoint;
|
||||
|
||||
/** Gui-service related public URLS from spring web security perspective */
|
||||
public static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
|
||||
|
@ -67,19 +56,7 @@ public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
.authenticated()
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(
|
||||
new AuthenticationEntryPoint() {
|
||||
|
||||
@Override
|
||||
public void commence(
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final AuthenticationException authException) throws IOException, ServletException {
|
||||
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.sendRedirect(GuiWebsecurityConfig.this.unauthorizedRedirect);
|
||||
}
|
||||
})
|
||||
.authenticationEntryPoint(this.institutionalAuthenticationEntryPoint)
|
||||
.and()
|
||||
.formLogin().disable()
|
||||
.httpBasic().disable()
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURIService;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
final class InstitutionalAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InstitutionalAuthenticationEntryPoint.class);
|
||||
|
||||
private final String guiEntryPoint;
|
||||
private final String guiRedirect;
|
||||
private final WebserviceURIService webserviceURIService;
|
||||
private final ClientHttpRequestFactory clientHttpRequestFactory;
|
||||
|
||||
protected InstitutionalAuthenticationEntryPoint(
|
||||
@Value("${sebserver.gui.entrypoint}") final String guiEntryPoint,
|
||||
@Value("${sebserver.webservice.api.redirect.unauthorized}") final String guiRedirect,
|
||||
final WebserviceURIService webserviceURIService,
|
||||
final ClientHttpRequestFactory clientHttpRequestFactory) {
|
||||
|
||||
this.guiEntryPoint = guiEntryPoint;
|
||||
this.guiRedirect = guiRedirect;
|
||||
this.webserviceURIService = webserviceURIService;
|
||||
this.clientHttpRequestFactory = clientHttpRequestFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commence(
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final AuthenticationException authException) throws IOException, ServletException {
|
||||
|
||||
final String requestURI = request.getRequestURI();
|
||||
|
||||
log.info("No default gui entrypoint requested: {}", requestURI);
|
||||
|
||||
final String logoImageBase64 = requestLogoImage(requestURI);
|
||||
if (StringUtils.isNoneBlank(logoImageBase64)) {
|
||||
// forward
|
||||
request.getSession().setAttribute(API.PARAM_LOGO_IMAGE, logoImageBase64);
|
||||
final RequestDispatcher dispatcher = request.getServletContext()
|
||||
.getRequestDispatcher(this.guiEntryPoint);
|
||||
dispatcher.forward(request, response);
|
||||
// redirect
|
||||
} else {
|
||||
request.getSession().removeAttribute(API.PARAM_LOGO_IMAGE);
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.sendRedirect(this.guiRedirect);
|
||||
}
|
||||
}
|
||||
|
||||
private String requestLogoImage(final String requestURI) {
|
||||
log.debug("Trying to verify insitution from requested entrypoint url: {}", requestURI);
|
||||
try {
|
||||
|
||||
final RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setRequestFactory(this.clientHttpRequestFactory);
|
||||
|
||||
final ResponseEntity<String> exchange = restTemplate
|
||||
.exchange(
|
||||
this.webserviceURIService.getURIBuilder()
|
||||
.path(API.INFO_ENDPOINT + API.INSTITUTIONAL_LOGO_PATH)
|
||||
.toUriString(),
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
String.class,
|
||||
requestURI.replaceAll("/", ""));
|
||||
|
||||
if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) {
|
||||
return exchange.getBody();
|
||||
} else {
|
||||
log.error("Failed to verify insitution from requested entrypoint url: {}, response: {}", requestURI,
|
||||
exchange);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to verify insitution from requested entrypoint url: {}", requestURI, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ import java.util.Map;
|
|||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.rap.rwt.application.AbstractEntryPoint;
|
||||
import org.eclipse.rap.rwt.application.Application;
|
||||
|
@ -22,14 +21,12 @@ import org.eclipse.rap.rwt.application.ApplicationConfiguration;
|
|||
import org.eclipse.rap.rwt.application.EntryPoint;
|
||||
import org.eclipse.rap.rwt.application.EntryPointFactory;
|
||||
import org.eclipse.rap.rwt.client.WebClient;
|
||||
import org.eclipse.rap.rwt.client.service.StartupParameters;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
|
||||
|
||||
|
@ -100,19 +97,6 @@ public class RAPConfiguration implements ApplicationConfiguration {
|
|||
final HttpSession httpSession,
|
||||
final WebApplicationContext webApplicationContext) {
|
||||
|
||||
// NOTE: if the user comes from a specified institutional login url (redirect from server) the institutionId is get from
|
||||
// request and put to the session attributes. The institutionId can later be used for institution specific login page
|
||||
// look and feel as well as for sending the institutionId within the login credentials to give the authorization service
|
||||
// some restriction to search the user. This is especially useful if the user is external registered and verified
|
||||
// with LDAP or AAI SAML
|
||||
final StartupParameters reqParams = RWT.getClient().getService(StartupParameters.class);
|
||||
final String institutionId = reqParams.getParameter(API.PARAM_INSTITUTION_ID);
|
||||
if (StringUtils.isNotBlank(institutionId)) {
|
||||
httpSession.setAttribute(API.PARAM_INSTITUTION_ID, institutionId);
|
||||
} else {
|
||||
httpSession.removeAttribute(API.PARAM_INSTITUTION_ID);
|
||||
}
|
||||
|
||||
final AuthorizationContextHolder authorizationContextHolder = webApplicationContext
|
||||
.getBean(AuthorizationContextHolder.class);
|
||||
final SEBServerAuthorizationContext authorizationContext = authorizationContextHolder
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
|
@ -37,6 +38,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.NewInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.SaveInstitution;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
|
@ -46,10 +48,16 @@ public class InstitutionForm implements TemplateComposer {
|
|||
|
||||
private final PageFormService pageFormService;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
|
||||
protected InstitutionForm(
|
||||
final PageFormService pageFormService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
protected InstitutionForm(final PageFormService pageFormService, final RestService restService) {
|
||||
this.pageFormService = pageFormService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,7 +101,7 @@ public class InstitutionForm implements TemplateComposer {
|
|||
content.setLayout(contentLayout);
|
||||
content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
// title
|
||||
// title (interactive9
|
||||
final Label pageTitle = widgetFactory.labelLocalizedTitle(
|
||||
content, new LocTextKey(
|
||||
"sebserver.institution.form.title",
|
||||
|
@ -141,20 +149,24 @@ public class InstitutionForm implements TemplateComposer {
|
|||
|
||||
// propagate content actions to action-pane
|
||||
if (readonly) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.withExec(InstitutionActions::editInstitution)
|
||||
.publish();
|
||||
if (!institution.isActive()) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_ACTIVATE)
|
||||
.withExec(InstitutionActions::activateInstitution)
|
||||
if (this.currentUser.hasPrivilege(PrivilegeType.WRITE, institution)) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publish();
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
|
||||
.withExec(InstitutionActions::deactivateInstitution)
|
||||
}
|
||||
if (this.currentUser.hasPrivilege(PrivilegeType.MODIFY, institution)) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.withExec(InstitutionActions::editInstitution)
|
||||
.publish();
|
||||
if (!institution.isActive()) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_ACTIVATE)
|
||||
.withExec(InstitutionActions::activateInstitution)
|
||||
.publish();
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
|
||||
.withExec(InstitutionActions::deactivateInstitution)
|
||||
.publish();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_SAVE)
|
||||
|
@ -164,7 +176,6 @@ public class InstitutionForm implements TemplateComposer {
|
|||
.withExec(InstitutionActions::cancelEditInstitution)
|
||||
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
|
||||
.publish();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.io.ByteArrayInputStream;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64InputStream;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
|
@ -27,7 +28,6 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
|
@ -36,7 +36,6 @@ import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURIService;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.Message;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory.CustomVariant;
|
||||
|
@ -47,20 +46,17 @@ public class DefaultPageLayout implements TemplateComposer {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultPageLayout.class);
|
||||
|
||||
private final WebserviceURIService webserviceURIService;
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final PolyglotPageService polyglotPageService;
|
||||
private final AuthorizationContextHolder authorizationContextHolder;
|
||||
private final String sebServerVersion;
|
||||
|
||||
public DefaultPageLayout(
|
||||
final WebserviceURIService webserviceURIService,
|
||||
final WidgetFactory widgetFactory,
|
||||
final PolyglotPageService polyglotPageService,
|
||||
final AuthorizationContextHolder authorizationContextHolder,
|
||||
@Value("${sebserver.version}") final String sebServerVersion) {
|
||||
|
||||
this.webserviceURIService = webserviceURIService;
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.polyglotPageService = polyglotPageService;
|
||||
this.authorizationContextHolder = authorizationContextHolder;
|
||||
|
@ -173,28 +169,7 @@ public class DefaultPageLayout implements TemplateComposer {
|
|||
logo.setLayoutData(logoCell);
|
||||
|
||||
// try to get institutional logo first. If no success, use default logo
|
||||
try {
|
||||
final String institutionId = (String) RWT.getUISession()
|
||||
.getHttpSession()
|
||||
.getAttribute(API.PARAM_INSTITUTION_ID);
|
||||
|
||||
final String logoBase64 = new RestTemplate()
|
||||
.getForObject(
|
||||
this.webserviceURIService.getWebserviceServerAddress() + API.INSTITUTIONAL_LOGO_PATH,
|
||||
String.class,
|
||||
institutionId);
|
||||
|
||||
final Base64InputStream input = new Base64InputStream(
|
||||
new ByteArrayInputStream(logoBase64.getBytes(StandardCharsets.UTF_8)),
|
||||
false);
|
||||
|
||||
logo.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage");
|
||||
logo.setBackgroundImage(new Image(pageContext.getShell().getDisplay(), input));
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.warn("Get institutional logo failed: {}", e.getMessage());
|
||||
logo.setData(RWT.CUSTOM_VARIANT, "bgLogo");
|
||||
}
|
||||
loadInstitutionalLogo(pageContext, logo);
|
||||
|
||||
final Composite langSupport = new Composite(logoBar, SWT.NONE);
|
||||
final GridData langSupportCell = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
|
||||
|
@ -208,14 +183,6 @@ public class DefaultPageLayout implements TemplateComposer {
|
|||
langSupport.setLayout(rowLayout);
|
||||
|
||||
this.widgetFactory.createLanguageSelector(pageContext.copyOf(langSupport));
|
||||
// for (final Locale locale : this.i18nSupport.supportedLanguages()) {
|
||||
// final LanguageSelection languageSelection = new LanguageSelection(langSupport, locale);
|
||||
// languageSelection.updateLocale(this.i18nSupport);
|
||||
// languageSelection.addListener(SWT.MouseDown, event -> {
|
||||
// this.polyglotPageService.setPageLocale(pageContext.root, languageSelection.locale);
|
||||
//
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
private void composeContent(final PageContext pageContext) {
|
||||
|
@ -305,25 +272,28 @@ public class DefaultPageLayout implements TemplateComposer {
|
|||
new LocTextKey("sebserver.overall.version", this.sebServerVersion));
|
||||
}
|
||||
|
||||
// private final class LanguageSelection extends Label implements Polyglot {
|
||||
//
|
||||
// private static final long serialVersionUID = 8110167162843383940L;
|
||||
// private final Locale locale;
|
||||
//
|
||||
// public LanguageSelection(final Composite parent, final Locale locale) {
|
||||
// super(parent, SWT.NONE);
|
||||
// this.locale = locale;
|
||||
// super.setData(RWT.CUSTOM_VARIANT, "header");
|
||||
// super.setText("| " + locale.getLanguage().toUpperCase());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void updateLocale(final I18nSupport i18nSupport) {
|
||||
// super.setVisible(
|
||||
// !i18nSupport.getCurrentLocale()
|
||||
// .getLanguage()
|
||||
// .equals(this.locale.getLanguage()));
|
||||
// }
|
||||
// }
|
||||
private void loadInstitutionalLogo(final PageContext pageContext, final Composite logo) {
|
||||
logo.setData(RWT.CUSTOM_VARIANT, "bgLogo");
|
||||
try {
|
||||
|
||||
final String imageBase64 = (String) RWT.getUISession()
|
||||
.getHttpSession()
|
||||
.getAttribute(API.PARAM_LOGO_IMAGE);
|
||||
|
||||
if (StringUtils.isBlank(imageBase64)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Base64InputStream input = new Base64InputStream(
|
||||
new ByteArrayInputStream(imageBase64.getBytes(StandardCharsets.UTF_8)),
|
||||
false);
|
||||
|
||||
logo.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage");
|
||||
logo.setBackgroundImage(new Image(pageContext.getShell().getDisplay(), input));
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.warn("Get institutional logo failed: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ public class RestService {
|
|||
|
||||
public RestService(
|
||||
final AuthorizationContextHolder authorizationContextHolder,
|
||||
final WebserviceURIService webserviceURIBuilderSupplier,
|
||||
final JSONMapper jsonMapper,
|
||||
final Collection<RestCall<?>> calls) {
|
||||
|
||||
this.authorizationContextHolder = authorizationContextHolder;
|
||||
this.webserviceURIBuilderSupplier = webserviceURIBuilderSupplier;
|
||||
this.webserviceURIBuilderSupplier = authorizationContextHolder
|
||||
.getWebserviceURIService();
|
||||
|
||||
this.calls = calls
|
||||
.stream()
|
||||
|
@ -54,7 +54,7 @@ public class RestService {
|
|||
}
|
||||
|
||||
public UriComponentsBuilder getWebserviceURIBuilder() {
|
||||
return this.webserviceURIBuilderSupplier.getBuilder();
|
||||
return this.webserviceURIBuilderSupplier.getURIBuilder();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -16,8 +16,11 @@ public interface AuthorizationContextHolder {
|
|||
|
||||
SEBServerAuthorizationContext getAuthorizationContext(HttpSession session);
|
||||
|
||||
WebserviceURIService getWebserviceURIService();
|
||||
|
||||
// TODO error handling!?
|
||||
default SEBServerAuthorizationContext getAuthorizationContext() {
|
||||
return getAuthorizationContext(RWT.getUISession().getHttpSession());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,17 +8,33 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege.RoleTypeKey;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
|
||||
@Component
|
||||
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
|
@ -29,6 +45,7 @@ public class CurrentUser {
|
|||
|
||||
private final AuthorizationContextHolder authorizationContextHolder;
|
||||
private SEBServerAuthorizationContext authContext = null;
|
||||
private Map<RoleTypeKey, Privilege> privileges = null;
|
||||
|
||||
public CurrentUser(final AuthorizationContextHolder authorizationContextHolder) {
|
||||
this.authorizationContextHolder = authorizationContextHolder;
|
||||
|
@ -58,6 +75,64 @@ public class CurrentUser {
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean hasPrivilege(final PrivilegeType privilegeType, final EntityType entityType) {
|
||||
if (loadPrivileges()) {
|
||||
try {
|
||||
return get().getRoles()
|
||||
.stream()
|
||||
.map(roleName -> UserRole.valueOf(roleName))
|
||||
.map(role -> new RoleTypeKey(entityType, role))
|
||||
.map(key -> this.privileges.get(key))
|
||||
.filter(checkPrivilege(get(), privilegeType, null))
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to verify privilege: PrivilegeType {} EntityType {}",
|
||||
privilegeType, entityType, e);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasPrivilege(
|
||||
final PrivilegeType privilegeType,
|
||||
final GrantEntity grantEntity) {
|
||||
|
||||
if (loadPrivileges()) {
|
||||
final EntityType entityType = grantEntity.entityType();
|
||||
try {
|
||||
return get().getRoles()
|
||||
.stream()
|
||||
.map(roleName -> UserRole.valueOf(roleName))
|
||||
.map(role -> new RoleTypeKey(entityType, role))
|
||||
.map(key -> this.privileges.get(key))
|
||||
.filter(checkPrivilege(get(), privilegeType, grantEntity))
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to verify privilege: PrivilegeType {} EntityType {}",
|
||||
privilegeType, entityType, e);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Predicate<Privilege> checkPrivilege(
|
||||
final UserInfo userInfo,
|
||||
final PrivilegeType privilegeType,
|
||||
final GrantEntity grantEntity) {
|
||||
|
||||
return priv -> priv.hasBasePrivilege(privilegeType)
|
||||
|| ((grantEntity != null) &&
|
||||
(priv.hasInstitutionalPrivilege(privilegeType)
|
||||
&& get().institutionId.longValue() == grantEntity.getInstitutionId()
|
||||
.longValue())
|
||||
|| (priv.hasOwnershipPrivilege(privilegeType)
|
||||
&& get().uuid.equals(grantEntity.getOwnerId())));
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
updateContext();
|
||||
return this.authContext != null && this.authContext.isLoggedIn();
|
||||
|
@ -69,4 +144,52 @@ public class CurrentUser {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean loadPrivileges() {
|
||||
if (this.privileges != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
updateContext();
|
||||
if (this.authContext != null) {
|
||||
try {
|
||||
final WebserviceURIService webserviceURIService =
|
||||
this.authorizationContextHolder.getWebserviceURIService();
|
||||
final ResponseEntity<Collection<Privilege>> exchange = this.authContext.getRestTemplate()
|
||||
.exchange(
|
||||
webserviceURIService.getURIBuilder()
|
||||
.path(API.PRIVILEGES_ENDPOINT)
|
||||
.toUriString(),
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<Collection<Privilege>>() {
|
||||
});
|
||||
|
||||
if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) {
|
||||
this.privileges = exchange.getBody().stream()
|
||||
.reduce(new HashMap<RoleTypeKey, Privilege>(),
|
||||
(map, priv) -> {
|
||||
map.put(priv.roleTypeKey, priv);
|
||||
return map;
|
||||
},
|
||||
(map1, map2) -> {
|
||||
map1.putAll(map2);
|
||||
return map1;
|
||||
});
|
||||
|
||||
return true;
|
||||
} else {
|
||||
log.error("Failed to get Privileges from webservice API: {}", exchange);
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to get Privileges from webservice API: ", e);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log.error("Failed to get Privileges from webservice API. No AuthorizationContext available");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,6 +75,11 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
|
|||
this.clientHttpRequestFactory = clientHttpRequestFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebserviceURIService getWebserviceURIService() {
|
||||
return this.webserviceURIService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SEBServerAuthorizationContext getAuthorizationContext(final HttpSession session) {
|
||||
log.debug("Trying to get OAuth2AuthorizationContext from HttpSession: {}", session.getId());
|
||||
|
|
|
@ -43,7 +43,7 @@ public class WebserviceURIService {
|
|||
return this.webserviceServerAddress;
|
||||
}
|
||||
|
||||
public UriComponentsBuilder getBuilder() {
|
||||
public UriComponentsBuilder getURIBuilder() {
|
||||
return this.webserviceURIBuilder.cloneBuilder();
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ public class WebserviceURIService {
|
|||
}
|
||||
|
||||
public String getCurrentUserRequestURI() {
|
||||
return getBuilder()
|
||||
return getURIBuilder()
|
||||
.path(CURRENT_USER_URI_PATH)
|
||||
.toUriString();
|
||||
}
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
@ -27,6 +29,11 @@ public interface AuthorizationGrantService {
|
|||
* @return the UserService that is bundled within the AuthorizationGrantService */
|
||||
UserService getUserService();
|
||||
|
||||
/** All Privileges in a collection.
|
||||
*
|
||||
* @return all registered Privileges */
|
||||
Collection<Privilege> getAllPrivileges();
|
||||
|
||||
/** Checks if the current user has any privilege (base or institutional or owner) for the given EntityType and
|
||||
* PrivilegeType.
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
|||
|
||||
import java.security.Principal;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -21,8 +22,8 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege.RoleTypeKey;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
|
@ -34,7 +35,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
|
|||
public class AuthorizationGrantServiceImpl implements AuthorizationGrantService {
|
||||
|
||||
/** Map of role based grants for specified entity types. */
|
||||
private final Map<Privilege.RoleTypeKey, Privilege> grants = new HashMap<>();
|
||||
private final Map<Privilege.RoleTypeKey, Privilege> privileges = new HashMap<>();
|
||||
/** Map of collected AuthorizationGrantRule exceptions */
|
||||
private final Map<EntityType, AuthorizationGrantRule> exceptionalRules =
|
||||
new EnumMap<>(EntityType.class);
|
||||
|
@ -58,6 +59,11 @@ public class AuthorizationGrantServiceImpl implements AuthorizationGrantService
|
|||
return this.userService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Privilege> getAllPrivileges() {
|
||||
return Collections.unmodifiableCollection(this.privileges.values());
|
||||
}
|
||||
|
||||
/** Initialize the (hard-coded) grants */
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
|
@ -200,7 +206,7 @@ public class AuthorizationGrantServiceImpl implements AuthorizationGrantService
|
|||
final SEBServerUser user) {
|
||||
|
||||
for (final UserRole role : user.getUserRoles()) {
|
||||
final Privilege roleTypeGrant = this.grants.get(new RoleTypeKey(entityType, role));
|
||||
final Privilege roleTypeGrant = this.privileges.get(new RoleTypeKey(entityType, role));
|
||||
if (roleTypeGrant != null && roleTypeGrant.hasBasePrivilege(privilegeType)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -238,7 +244,7 @@ public class AuthorizationGrantServiceImpl implements AuthorizationGrantService
|
|||
final SEBServerUser user) {
|
||||
|
||||
for (final UserRole role : user.getUserRoles()) {
|
||||
final Privilege roleTypeGrant = this.grants.get(new RoleTypeKey(entityType, role));
|
||||
final Privilege roleTypeGrant = this.privileges.get(new RoleTypeKey(entityType, role));
|
||||
if (roleTypeGrant != null && roleTypeGrant.hasInstitutionalPrivilege(privilegeType)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -328,7 +334,7 @@ public class AuthorizationGrantServiceImpl implements AuthorizationGrantService
|
|||
this.grants = new EnumMap<>(UserRole.class);
|
||||
for (final UserRole role : UserRole.values()) {
|
||||
this.grants.put(role,
|
||||
service.grants.get(new RoleTypeKey(type, role)));
|
||||
service.privileges.get(new RoleTypeKey(type, role)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,7 +443,7 @@ public class AuthorizationGrantServiceImpl implements AuthorizationGrantService
|
|||
this.institutionalPrivilege,
|
||||
this.ownerPrivilege);
|
||||
|
||||
AuthorizationGrantServiceImpl.this.grants.put(roleTypeKey, roleTypeGrant);
|
||||
AuthorizationGrantServiceImpl.this.privileges.put(roleTypeKey, roleTypeGrant);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.webservice.weblayer.api;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
|
||||
|
||||
@WebServiceProfile
|
||||
@RestController
|
||||
@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + API.INFO_ENDPOINT)
|
||||
public class InfoController {
|
||||
|
||||
private final InstitutionDAO institutionDAO;
|
||||
private final AuthorizationGrantService authorizationGrantService;
|
||||
|
||||
protected InfoController(
|
||||
final InstitutionDAO institutionDAO,
|
||||
final AuthorizationGrantService authorizationGrantService) {
|
||||
|
||||
this.institutionDAO = institutionDAO;
|
||||
this.authorizationGrantService = authorizationGrantService;
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.INSTITUTIONAL_LOGO_PATH,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.IMAGE_PNG_VALUE + ";base64")
|
||||
public String logo(@PathVariable final String urlSuffix) {
|
||||
return this.institutionDAO
|
||||
.all(null, true)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.filter(inst -> urlSuffix.endsWith(inst.urlSuffix))
|
||||
.findFirst()
|
||||
.map(inst -> inst.logoImage)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.PRIVILEGES_PATH_SEGMENT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public Collection<Privilege> privileges() {
|
||||
return this.authorizationGrantService.getAllPrivileges();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.webservice.weblayer.api;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
|
||||
|
||||
@WebServiceProfile
|
||||
@RestController
|
||||
public class LogoController {
|
||||
|
||||
private final InstitutionDAO institutionDAO;
|
||||
|
||||
protected LogoController(final InstitutionDAO institutionDAO) {
|
||||
this.institutionDAO = institutionDAO;
|
||||
}
|
||||
|
||||
@RequestMapping(API.INSTITUTIONAL_LOGO_PATH)
|
||||
public String logo(@PathVariable final String institutionId) throws IOException {
|
||||
return this.institutionDAO
|
||||
.byModelId(institutionId)
|
||||
.getOrThrow().logoImage;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.webservice.weblayer.api;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
|
||||
@WebServiceProfile
|
||||
@RestController
|
||||
public class PrivilegesController {
|
||||
|
||||
}
|
Loading…
Reference in a new issue