From 00d7a91a43f35d285e4a40a1e7bcd1760e669cdb Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 8 Aug 2019 20:35:57 +0200 Subject: [PATCH] fixed institutional logo handling --- .../ethz/seb/sebserver/WebSecurityConfig.java | 4 +++ .../sebserver/gui/GuiWebsecurityConfig.java | 9 +++++-- ...InstitutionalAuthenticationEntryPoint.java | 18 +++++++------ .../gui/content/InstitutionForm.java | 5 +++- .../gui/form/ImageUploadFieldBuilder.java | 17 ++++++++++++- .../service/page/impl/DefaultPageLayout.java | 25 ++++++++++++++++--- .../seb/sebserver/gui/widget/ImageUpload.java | 20 ++++++++++++--- .../sebserver/gui/widget/WidgetFactory.java | 22 ++++++++++++++-- 8 files changed, 100 insertions(+), 20 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java b/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java index d8250180..ea916d7d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java @@ -45,6 +45,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.filter.CharacterEncodingFilter; +import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.profile.DevGuiProfile; import ch.ethz.seb.sebserver.gbl.profile.DevWebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; @@ -67,6 +68,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E private String guiRedirect; @Value("${sebserver.webservice.api.exam.endpoint.discovery}") private String examAPIDiscoveryEndpoint; + @Value("${sebserver.webservice.api.admin.endpoint}") + private String adminAPIEndpoint; /** Spring bean name of user password encoder */ public static final String USER_PASSWORD_ENCODER_BEAN_NAME = "userPasswordEncoder"; @@ -101,6 +104,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E .ignoring() .antMatchers("/error") .antMatchers(this.examAPIDiscoveryEndpoint) + .antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**") .and(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java b/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java index 06cc1ead..ee96baa2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java @@ -9,6 +9,7 @@ package ch.ethz.seb.sebserver.gui; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -30,12 +31,15 @@ public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private InstitutionalAuthenticationEntryPoint institutionalAuthenticationEntryPoint; + @Value("${sebserver.gui.entrypoint:/gui}") + private String guiEntryPoint; + /** Gui-service related public URLS from spring web security perspective */ public static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher( // OAuth entry-points new AntPathRequestMatcher(API.OAUTH_REVOKE_TOKEN_ENDPOINT), // GUI entry-point - new AntPathRequestMatcher("/gui"), +// new AntPathRequestMatcher(guiEntryPoint), // RAP/RWT resources has to be accessible new AntPathRequestMatcher("/rwt-resources/**"), // project specific static resources @@ -47,7 +51,8 @@ public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter { public void configure(final WebSecurity web) { web .ignoring() - .requestMatchers(PUBLIC_URLS); + .requestMatchers(PUBLIC_URLS) + .antMatchers(this.guiEntryPoint); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java b/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java index 5b49c20b..5926f635 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java @@ -65,21 +65,25 @@ final class InstitutionalAuthenticationEntryPoint implements AuthenticationEntry final String logoImageBase64 = requestLogoImage(requestURI); if (StringUtils.isNotBlank(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.guiEntryPoint); } + + final RequestDispatcher dispatcher = request.getServletContext() + .getRequestDispatcher(this.guiEntryPoint); + dispatcher.forward(request, response); } private String requestLogoImage(final String requestURI) { log.debug("Trying to verify insitution from requested entrypoint url: {}", requestURI); + + final String instPrefix = requestURI.replaceAll("/", ""); + if (StringUtils.isBlank(instPrefix)) { + return null; + } + try { final RestTemplate restTemplate = new RestTemplate(); @@ -93,7 +97,7 @@ final class InstitutionalAuthenticationEntryPoint implements AuthenticationEntry HttpMethod.GET, HttpEntity.EMPTY, String.class, - requestURI.replaceAll("/", "")); + instPrefix); if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) { return exchange.getBody(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java index c8519f82..e5b17526 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java @@ -27,6 +27,7 @@ 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.page.impl.DefaultPageLayout; import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution; @@ -129,7 +130,9 @@ public class InstitutionForm implements TemplateComposer { .addField(FormBuilder.imageUpload( Domain.INSTITUTION.ATTR_LOGO_IMAGE, FORM_LOGO_IMAGE_TEXT_KEY, - institution.logoImage)) + institution.logoImage) + .withMaxWidth(DefaultPageLayout.LOGO_IMAGE_MAX_WIDTH) + .withMaxHeight(DefaultPageLayout.LOGO_IMAGE_MAX_HEIGHT)) .buildFor((isNew) ? this.restService.getRestCall(NewInstitution.class) : this.restService.getRestCall(SaveInstitution.class)); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java index c4eaed0b..2abb666b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/ImageUploadFieldBuilder.java @@ -18,10 +18,23 @@ import ch.ethz.seb.sebserver.gui.widget.ImageUpload; public final class ImageUploadFieldBuilder extends FieldBuilder { + private int maxWidth = 100; + private int maxHeight = 100; + ImageUploadFieldBuilder(final String name, final LocTextKey label, final String value) { super(name, label, value); } + public ImageUploadFieldBuilder withMaxWidth(final int width) { + this.maxWidth = width; + return this; + } + + public ImageUploadFieldBuilder withMaxHeight(final int height) { + this.maxHeight = height; + return this; + } + @Override void build(final FormBuilder builder) { @@ -35,7 +48,9 @@ public final class ImageUploadFieldBuilder extends FieldBuilder { final ImageUpload imageUpload = builder.widgetFactory.imageUploadLocalized( fieldGrid, new LocTextKey("sebserver.overall.upload"), - builder.readonly || this.readonly); + builder.readonly || this.readonly, + this.maxWidth, + this.maxHeight); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); imageUpload.setLayoutData(gridData); imageUpload.setImageBase64(this.value); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultPageLayout.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultPageLayout.java index 19974588..1d232216 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultPageLayout.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/DefaultPageLayout.java @@ -17,11 +17,14 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.MessageBox; import org.slf4j.Logger; @@ -49,6 +52,9 @@ public class DefaultPageLayout implements TemplateComposer { private static final Logger log = LoggerFactory.getLogger(DefaultPageLayout.class); + public static final int LOGO_IMAGE_MAX_WIDTH = 400; + public static final int LOGO_IMAGE_MAX_HEIGHT = 80; + private final WidgetFactory widgetFactory; private final PolyglotPageService polyglotPageService; private final AuthorizationContextHolder authorizationContextHolder; @@ -155,9 +161,9 @@ public class DefaultPageLayout implements TemplateComposer { final Composite logo = new Composite(logoBar, SWT.NONE); final GridData logoCell = new GridData(SWT.LEFT, SWT.CENTER, true, true); - logoCell.minimumHeight = 80; - logoCell.heightHint = 80; - logoCell.minimumWidth = 400; + logoCell.minimumHeight = LOGO_IMAGE_MAX_HEIGHT; + logoCell.heightHint = LOGO_IMAGE_MAX_HEIGHT; + logoCell.minimumWidth = LOGO_IMAGE_MAX_WIDTH; logoCell.horizontalIndent = 50; logo.setLayoutData(logoCell); @@ -283,8 +289,19 @@ public class DefaultPageLayout implements TemplateComposer { new ByteArrayInputStream(imageBase64.getBytes(StandardCharsets.UTF_8)), false); + final Display display = pageContext.getShell().getDisplay(); + final Image image = new Image(display, input); + final Rectangle imageBounds = image.getBounds(); + final int width = (imageBounds.width > LOGO_IMAGE_MAX_WIDTH) + ? LOGO_IMAGE_MAX_WIDTH + : imageBounds.width; + final int height = (imageBounds.height > LOGO_IMAGE_MAX_HEIGHT) + ? LOGO_IMAGE_MAX_HEIGHT + : imageBounds.height; + final ImageData imageData = image.getImageData().scaledTo(width, height); + logo.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage"); - logo.setBackgroundImage(new Image(pageContext.getShell().getDisplay(), input)); + logo.setBackgroundImage(new Image(display, imageData)); } catch (final Exception e) { log.warn("Get institutional logo failed: {}", e.getMessage()); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java index 015e2897..d78ef7ae 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUpload.java @@ -32,6 +32,7 @@ import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; @@ -54,6 +55,9 @@ public final class ImageUpload extends Composite { private final Composite imageCanvas; private final FileUpload fileUpload; + private final int maxWidth; + private final int maxHeight; + private Consumer errorHandler; private String imageBase64 = null; private boolean loadNewImage = false; @@ -63,12 +67,16 @@ public final class ImageUpload extends Composite { final Composite parent, final ServerPushService serverPushService, final I18nSupport i18nSupport, - final boolean readonly) { + final boolean readonly, + final int maxWidth, + final int maxHeight) { super(parent, SWT.NONE); super.setLayout(new GridLayout(1, false)); this.serverPushService = serverPushService; + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; if (!readonly) { this.fileUpload = new FileUpload(this, SWT.NONE); @@ -189,8 +197,14 @@ public final class ImageUpload extends Composite { imageUpload.imageCanvas.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage"); final Image image = new Image(imageUpload.imageCanvas.getDisplay(), input); - final ImageData imageData = image.getImageData().scaledTo(200, 100); - + final Rectangle imageBounds = image.getBounds(); + final int width = (imageBounds.width > imageUpload.maxWidth) + ? imageUpload.maxWidth + : imageBounds.width; + final int height = (imageBounds.height > imageUpload.maxHeight) + ? imageUpload.maxHeight + : imageBounds.height; + final ImageData imageData = image.getImageData().scaledTo(width, height); imageUpload.imageCanvas.setBackgroundImage(new Image(imageUpload.imageCanvas.getDisplay(), imageData)); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java index 543828d8..b1c3d10e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java @@ -48,6 +48,7 @@ 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.i18n.PolyglotPageService; import ch.ethz.seb.sebserver.gui.service.page.PageService; +import ch.ethz.seb.sebserver.gui.service.page.impl.DefaultPageLayout; import ch.ethz.seb.sebserver.gui.service.push.ServerPushService; @Lazy @@ -584,16 +585,33 @@ public class WidgetFactory { return thresholdList; } - public ImageUpload imageUploadLocalized( + public ImageUpload logoImageUploadLocalized( final Composite parent, final LocTextKey locTextKey, final boolean readonly) { + return imageUploadLocalized( + parent, + locTextKey, + readonly, + DefaultPageLayout.LOGO_IMAGE_MAX_WIDTH, + DefaultPageLayout.LOGO_IMAGE_MAX_HEIGHT); + } + + public ImageUpload imageUploadLocalized( + final Composite parent, + final LocTextKey locTextKey, + final boolean readonly, + final int maxWidth, + final int maxHeight) { + final ImageUpload imageUpload = new ImageUpload( parent, this.serverPushService, this.i18nSupport, - readonly); + readonly, + maxWidth, + maxHeight); this.polyglotPageService.injectI18n(imageUpload, locTextKey); return imageUpload;