/* * (C) Copyright 2013-2015 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Nuxeo - initial API and implementation */ package org.nuxeo.ecm.platform.ui.web.auth.service; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.ws.rs.core.UriBuilder; import org.apache.commons.lang.StringUtils; import org.nuxeo.common.Environment; import org.nuxeo.common.xmap.XMap; import org.nuxeo.common.xmap.annotation.XNode; import org.nuxeo.common.xmap.annotation.XNodeList; import org.nuxeo.common.xmap.annotation.XNodeMap; import org.nuxeo.common.xmap.annotation.XObject; import org.nuxeo.runtime.api.Framework; /** * {@link XMap} object to manage configuration of the login screen (login.jsp) * * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> * @since 5.7 */ @XObject("loginScreenConfig") public class LoginScreenConfig implements Serializable { private static final long serialVersionUID = 1L; /** * @since 8.4 */ @XNodeMap(value = "startupPages/startupPage", key = "@id", type = HashMap.class, componentType = LoginStartupPage.class) protected Map<String, LoginStartupPage> startupPages = new HashMap<>(); @XNodeList(value = "loginProviders/loginProvider", type = ArrayList.class, componentType = LoginProviderLink.class) protected List<LoginProviderLink> providers; /** * @since 7.10 */ @XNodeList(value = "videos/video", type = ArrayList.class, componentType = LoginVideo.class, nullByDefault = true) protected List<LoginVideo> videos; /** * @since 7.10 */ @XNode("videos@muted") protected Boolean muted; /** * @since 7.10 */ @XNode("videos@loop") protected Boolean loop; /** * @since 7.10 */ protected String backgroundImage; @XNode("removeNews") protected Boolean removeNews = false; protected String headerStyle; protected String footerStyle; protected String newsIframeUrl = "//www.nuxeo.com/login-page-embedded/"; protected String newsIframeFullUrl = null; protected String bodyBackgroundStyle; protected String loginBoxBackgroundStyle; @XNode("loginBoxWidth") protected String loginBoxWidth; protected String logoUrl; @XNode("logoAlt") protected String logoAlt; @XNode("logoWidth") protected String logoWidth; @XNode("logoHeight") protected String logoHeight; /** * @since 7.10 */ @XNode("fieldAutocomplete") protected Boolean fieldAutocomplete; /** * Boolean to disable background-cover CSS behavior on login page background, as it may not be compliant with all * browsers (see NXP-12972/NXP-12978). * * @since 5.8 */ @XNode("disableBackgroundSizeCover") protected Boolean disableBackgroundSizeCover; /** * @since 7.10 */ @XNode("loginButtonBackgroundColor") protected String loginButtonBackgroundColor; /** * @since 8.4 */ @XNode("defaultLocale") protected String defaultLocale; /** * @since 8.4 */ @XNode("supportedLocales@append") boolean appendSupportedLocales; /** * @since 8.4 */ @XNodeList(value = "supportedLocales/locale", type = ArrayList.class, componentType = String.class) List<String> supportedLocales; public LoginScreenConfig() { } public List<LoginProviderLink> getProviders() { return providers; } public void setProviders(List<LoginProviderLink> providers) { this.providers = providers; } public LoginProviderLink getProvider(String name) { if (getProviders() == null) { return null; } for (LoginProviderLink provider : getProviders()) { if (name.equals(provider.getName())) { return provider; } } return null; } public void registerLoginProvider(String name, String iconUrl, String link, String label, String description, LoginProviderLinkComputer computer) { LoginProviderLink newProvider = new LoginProviderLink(); newProvider.name = name; newProvider.iconPath = iconUrl; newProvider.link = link; newProvider.label = label; newProvider.description = description; if (computer != null) { newProvider.urlComputer = computer; } LoginProviderLink existingProvider = getProvider(name); if (existingProvider != null) { existingProvider.merge(newProvider); } else { if (providers == null) { providers = new ArrayList<>(); } providers.add(newProvider); } } /** * @since 8.4 */ public Map<String, LoginStartupPage> getStartupPages() { return startupPages; } public String getHeaderStyle() { return headerStyle; } public String getFooterStyle() { return footerStyle; } public String getBodyBackgroundStyle() { return bodyBackgroundStyle; } public String getLoginBoxBackgroundStyle() { return loginBoxBackgroundStyle; } public String getLoginBoxWidth() { return loginBoxWidth; } public String getLogoUrl() { return logoUrl; } public String getLogoAlt() { return logoAlt; } public String getLogoWidth() { return logoWidth; } public String getLogoHeight() { return logoHeight; } public List<LoginVideo> getVideos() { return videos; } public Boolean getVideoMuted() { return muted == null ? false : muted; } public Boolean getVideoLoop() { return loop == null ? true : loop; } public boolean hasVideos() { return videos != null && !videos.isEmpty(); } public boolean getDisplayNews() { return !(removeNews || StringUtils.isBlank(newsIframeUrl)); } public Boolean getFieldAutocomplete() { return fieldAutocomplete == null ? true : fieldAutocomplete; } @XNode("headerStyle") public void setHeaderStyle(String headerStyle) { this.headerStyle = Framework.expandVars(headerStyle); } @XNode("footerStyle") public void setFooterStyle(String footerStyle) { this.footerStyle = Framework.expandVars(footerStyle); } @XNode("bodyBackgroundStyle") public void setBodyBackgroundStyle(String bodyBackgroundStyle) { this.bodyBackgroundStyle = Framework.expandVars(bodyBackgroundStyle); } @XNode("backgroundImage") public void setBackgroundImage(String backgroundImage) { this.backgroundImage = Framework.expandVars(backgroundImage); } public String getBackgroundImage() { return this.backgroundImage; } public String getLoginButtonBackgroundColor() { return loginButtonBackgroundColor; } @XNode("loginBoxBackgroundStyle") public void setLoginBoxBackgroundStyle(String loginBoxBackgroundStyle) { this.loginBoxBackgroundStyle = Framework.expandVars(loginBoxBackgroundStyle); } @XNode("logoUrl") public void setLogoUrl(String logoUrl) { this.logoUrl = Framework.expandVars(logoUrl); } /** * @since 7.10 */ @XNode("newsIframeUrl") public void setNewsIframeUrl(String newsIframeUrl) { this.newsIframeUrl = newsIframeUrl; newsIframeFullUrl = null; } public String getNewsIframeUrl() { if (newsIframeFullUrl == null) { newsIframeFullUrl = UriBuilder.fromPath(newsIframeUrl) .queryParam(Environment.PRODUCT_VERSION, Framework.getProperty(Environment.PRODUCT_VERSION)) .queryParam(Environment.DISTRIBUTION_VERSION, Framework.getProperty(Environment.DISTRIBUTION_VERSION)) .queryParam(Environment.DISTRIBUTION_PACKAGE, Framework.getProperty(Environment.DISTRIBUTION_PACKAGE)) .build() .toString(); } return newsIframeFullUrl; } /** * @since 5.8 * @see #disableBackgroundSizeCover */ public Boolean getDisableBackgroundSizeCover() { return disableBackgroundSizeCover; } /** * @since 8.4 */ public String getDefaultLocale() { return defaultLocale; } /** * @since 8.4 */ public boolean isAppendSupportedLocales() { return appendSupportedLocales; } /** * @since 8.4 */ public List<String> getSupportedLocales() { List<String> res = new ArrayList<>(); if (supportedLocales != null) { res.addAll(supportedLocales); } if (!res.contains(getDefaultLocale())) { res.add(getDefaultLocale()); } return res; } protected void merge(LoginScreenConfig newConfig) { if (newConfig.newsIframeUrl != null) { setNewsIframeUrl(newConfig.newsIframeUrl); } if (newConfig.headerStyle != null) { headerStyle = newConfig.headerStyle; } if (newConfig.footerStyle != null) { footerStyle = newConfig.footerStyle; } if (newConfig.bodyBackgroundStyle != null) { bodyBackgroundStyle = newConfig.bodyBackgroundStyle; } if (newConfig.loginBoxBackgroundStyle != null) { loginBoxBackgroundStyle = newConfig.loginBoxBackgroundStyle; } if (newConfig.loginBoxWidth != null) { loginBoxWidth = newConfig.loginBoxWidth; } if (newConfig.disableBackgroundSizeCover != null) { disableBackgroundSizeCover = newConfig.disableBackgroundSizeCover; } if (newConfig.logoAlt != null) { logoAlt = newConfig.logoAlt; } if (newConfig.logoHeight != null) { logoHeight = newConfig.logoHeight; } if (newConfig.logoUrl != null) { logoUrl = newConfig.logoUrl; } if (newConfig.logoWidth != null) { logoWidth = newConfig.logoWidth; } if (newConfig.fieldAutocomplete != null) { fieldAutocomplete = newConfig.fieldAutocomplete; } if (newConfig.videos != null) { videos = newConfig.videos; } if (newConfig.loop != null) { loop = newConfig.loop; } if (newConfig.removeNews) { removeNews = newConfig.removeNews; } if (newConfig.muted != null) { muted = newConfig.muted; } if (newConfig.loginButtonBackgroundColor != null) { loginButtonBackgroundColor = newConfig.loginButtonBackgroundColor; } if (newConfig.backgroundImage != null) { backgroundImage = newConfig.backgroundImage; } if (providers == null) { providers = newConfig.providers; } else if (newConfig.providers != null && newConfig.providers.size() > 0) { for (LoginProviderLink link : newConfig.providers) { int idx = providers.indexOf(link); if (idx >= 0) { if (link.remove) { providers.remove(idx); } else { providers.get(idx).merge(link); } } else { providers.add(link); } } } if (startupPages == null) { startupPages = newConfig.startupPages; } else if (newConfig.startupPages != null && !newConfig.startupPages.isEmpty()) { for (Map.Entry<String, LoginStartupPage> startupPage : newConfig.startupPages.entrySet()) { if (startupPages.containsKey(startupPage.getKey())) { startupPages.get(startupPage.getKey()).merge(startupPage.getValue()); } else { startupPages.put(startupPage.getKey(), startupPage.getValue()); } } } if (newConfig.defaultLocale != null) { defaultLocale = newConfig.defaultLocale; } boolean append = newConfig.isAppendSupportedLocales(); List<String> newLocales = newConfig.getSupportedLocales(); Set<String> mergedLocales = new HashSet<String>(); if (append && supportedLocales != null) { mergedLocales.addAll(supportedLocales); } if (newLocales != null) { mergedLocales.addAll(newLocales); } supportedLocales = new ArrayList<>(mergedLocales); } /** * @since 7.10 */ @Override public LoginScreenConfig clone() { LoginScreenConfig clone = new LoginScreenConfig(); clone.bodyBackgroundStyle = bodyBackgroundStyle; clone.disableBackgroundSizeCover = disableBackgroundSizeCover; clone.fieldAutocomplete = fieldAutocomplete; clone.footerStyle = footerStyle; clone.headerStyle = headerStyle; clone.loginBoxBackgroundStyle = loginBoxBackgroundStyle; clone.loginBoxWidth = loginBoxWidth; clone.loginButtonBackgroundColor = loginButtonBackgroundColor; clone.logoAlt = logoAlt; clone.logoHeight = logoHeight; clone.logoUrl = logoUrl; clone.logoWidth = logoWidth; clone.loop = loop; clone.muted = muted; clone.newsIframeUrl = newsIframeUrl; if (providers != null) { clone.providers = new ArrayList<LoginProviderLink>(); for (LoginProviderLink l : providers) { clone.providers.add(l.clone()); } } if (startupPages != null) { clone.startupPages = new HashMap<String, LoginStartupPage>(); for (Map.Entry<String, LoginStartupPage> startupPage : startupPages.entrySet()) { clone.startupPages.put(startupPage.getKey(), startupPage.getValue().clone()); } } clone.removeNews = removeNews; if (videos != null) { clone.videos = new ArrayList<LoginVideo>(); for (LoginVideo v : videos) { clone.videos.add(v.clone()); } } clone.defaultLocale = defaultLocale; clone.appendSupportedLocales = appendSupportedLocales; if (supportedLocales != null) { clone.supportedLocales = new ArrayList<>(supportedLocales); } return clone; } }