001/* 002 * (C) Copyright 2013-2015 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 */ 017package org.nuxeo.ecm.platform.ui.web.auth.service; 018 019import java.io.Serializable; 020import java.util.ArrayList; 021import java.util.List; 022 023import javax.ws.rs.core.UriBuilder; 024 025import org.apache.commons.lang.StringUtils; 026 027import org.nuxeo.common.Environment; 028import org.nuxeo.common.xmap.XMap; 029import org.nuxeo.common.xmap.annotation.XNode; 030import org.nuxeo.common.xmap.annotation.XNodeList; 031import org.nuxeo.common.xmap.annotation.XObject; 032import org.nuxeo.runtime.api.Framework; 033 034/** 035 * {@link XMap} object to manage configuration of the login screen (login.jsp) 036 * 037 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> 038 * @since 5.7 039 */ 040@XObject("loginScreenConfig") 041public class LoginScreenConfig implements Serializable { 042 043 private static final long serialVersionUID = 1L; 044 045 @XNodeList(value = "loginProviders/loginProvider", type = ArrayList.class, componentType = LoginProviderLink.class) 046 protected List<LoginProviderLink> providers; 047 048 /** 049 * @since 7.10 050 */ 051 @XNodeList(value = "videos/video", type = ArrayList.class, componentType = LoginVideo.class) 052 protected List<LoginVideo> videos; 053 054 /** 055 * @since 7.10 056 */ 057 @XNode("videos@muted") 058 protected Boolean muted; 059 060 /** 061 * @since 7.10 062 */ 063 @XNode("videos@loop") 064 protected Boolean loop; 065 066 /** 067 * @since 7.10 068 */ 069 protected String backgroundImage; 070 071 @XNode("removeNews") 072 protected Boolean removeNews = false; 073 074 protected String headerStyle; 075 076 protected String footerStyle; 077 078 protected String newsIframeUrl = "//www.nuxeo.com/standalone-login-page/"; 079 080 protected String newsIframeFullUrl = null; 081 082 protected String bodyBackgroundStyle; 083 084 protected String loginBoxBackgroundStyle; 085 086 @XNode("loginBoxWidth") 087 protected String loginBoxWidth; 088 089 protected String logoUrl; 090 091 @XNode("logoAlt") 092 protected String logoAlt; 093 094 @XNode("logoWidth") 095 protected String logoWidth; 096 097 @XNode("logoHeight") 098 protected String logoHeight; 099 100 /** 101 * @since 7.10 102 */ 103 @XNode("fieldAutocomplete") 104 protected Boolean fieldAutocomplete; 105 106 /** 107 * Boolean to disable background-cover CSS behavior on login page background, as it may not be compliant with all 108 * browsers (see NXP-12972/NXP-12978). 109 * 110 * @since 5.8 111 */ 112 @XNode("disableBackgroundSizeCover") 113 protected Boolean disableBackgroundSizeCover; 114 115 /** 116 * @since 7.10 117 */ 118 @XNode("loginButtonBackgroundColor") 119 protected String loginButtonBackgroundColor; 120 121 public LoginScreenConfig() { 122 } 123 124 public List<LoginProviderLink> getProviders() { 125 return providers; 126 } 127 128 public void setProviders(List<LoginProviderLink> providers) { 129 this.providers = providers; 130 } 131 132 public LoginProviderLink getProvider(String name) { 133 if (getProviders() == null) { 134 return null; 135 } 136 for (LoginProviderLink provider : getProviders()) { 137 if (name.equals(provider.getName())) { 138 return provider; 139 } 140 } 141 return null; 142 } 143 144 public void registerLoginProvider(String name, String iconUrl, String link, String label, String description, 145 LoginProviderLinkComputer computer) { 146 LoginProviderLink newProvider = new LoginProviderLink(); 147 newProvider.name = name; 148 newProvider.iconPath = iconUrl; 149 newProvider.link = link; 150 newProvider.label = label; 151 newProvider.description = description; 152 if (computer != null) { 153 newProvider.urlComputer = computer; 154 } 155 156 LoginProviderLink existingProvider = getProvider(name); 157 if (existingProvider != null) { 158 existingProvider.merge(newProvider); 159 } else { 160 if (providers == null) { 161 providers = new ArrayList<>(); 162 } 163 providers.add(newProvider); 164 } 165 } 166 167 public String getHeaderStyle() { 168 return headerStyle; 169 } 170 171 public String getFooterStyle() { 172 return footerStyle; 173 } 174 175 public String getBodyBackgroundStyle() { 176 return bodyBackgroundStyle; 177 } 178 179 public String getLoginBoxBackgroundStyle() { 180 return loginBoxBackgroundStyle; 181 } 182 183 public String getLoginBoxWidth() { 184 return loginBoxWidth; 185 } 186 187 public String getLogoUrl() { 188 return logoUrl; 189 } 190 191 public String getLogoAlt() { 192 return logoAlt; 193 } 194 195 public String getLogoWidth() { 196 return logoWidth; 197 } 198 199 public String getLogoHeight() { 200 return logoHeight; 201 } 202 203 public List<LoginVideo> getVideos() { 204 return videos; 205 } 206 207 public Boolean getVideoMuted() { 208 return muted == null ? false : muted; 209 } 210 211 public Boolean getVideoLoop() { 212 return loop == null ? true : loop; 213 } 214 215 public boolean hasVideos() { 216 return videos != null && !videos.isEmpty(); 217 } 218 219 public boolean getDisplayNews() { 220 return !(removeNews || StringUtils.isBlank(newsIframeUrl)); 221 } 222 223 public Boolean getFieldAutocomplete() { 224 return fieldAutocomplete == null ? true : fieldAutocomplete; 225 } 226 227 @XNode("headerStyle") 228 public void setHeaderStyle(String headerStyle) { 229 this.headerStyle = Framework.expandVars(headerStyle); 230 } 231 232 @XNode("footerStyle") 233 public void setFooterStyle(String footerStyle) { 234 this.footerStyle = Framework.expandVars(footerStyle); 235 } 236 237 @XNode("bodyBackgroundStyle") 238 public void setBodyBackgroundStyle(String bodyBackgroundStyle) { 239 this.bodyBackgroundStyle = Framework.expandVars(bodyBackgroundStyle); 240 } 241 242 @XNode("backgroundImage") 243 public void setBackgroundImage(String backgroundImage) { 244 this.backgroundImage = Framework.expandVars(backgroundImage); 245 } 246 247 public String getBackgroundImage() { 248 return this.backgroundImage; 249 } 250 251 public String getLoginButtonBackgroundColor() { 252 return loginButtonBackgroundColor; 253 } 254 255 @XNode("loginBoxBackgroundStyle") 256 public void setLoginBoxBackgroundStyle(String loginBoxBackgroundStyle) { 257 this.loginBoxBackgroundStyle = Framework.expandVars(loginBoxBackgroundStyle); 258 } 259 260 @XNode("logoUrl") 261 public void setLogoUrl(String logoUrl) { 262 this.logoUrl = Framework.expandVars(logoUrl); 263 } 264 265 /** 266 * @since 7.10 267 */ 268 @XNode("newsIframeUrl") 269 public void setNewsIframeUrl(String newsIframeUrl) { 270 this.newsIframeUrl = newsIframeUrl; 271 newsIframeFullUrl = null; 272 } 273 274 public String getNewsIframeUrl() { 275 if (newsIframeFullUrl == null) { 276 newsIframeFullUrl = UriBuilder.fromPath(newsIframeUrl) 277 .queryParam(Environment.PRODUCT_VERSION, 278 Framework.getProperty(Environment.PRODUCT_VERSION)) 279 .queryParam(Environment.DISTRIBUTION_VERSION, 280 Framework.getProperty(Environment.DISTRIBUTION_VERSION)) 281 .build() 282 .toString(); 283 } 284 return newsIframeFullUrl; 285 } 286 287 /** 288 * @since 5.8 289 * @see #disableBackgroundSizeCover 290 */ 291 public Boolean getDisableBackgroundSizeCover() { 292 return disableBackgroundSizeCover; 293 } 294 295 protected void merge(LoginScreenConfig newConfig) { 296 if (newConfig.newsIframeUrl != null) { 297 setNewsIframeUrl(newConfig.newsIframeUrl); 298 } 299 if (newConfig.headerStyle != null) { 300 headerStyle = newConfig.headerStyle; 301 } 302 if (newConfig.footerStyle != null) { 303 footerStyle = newConfig.footerStyle; 304 } 305 if (newConfig.bodyBackgroundStyle != null) { 306 bodyBackgroundStyle = newConfig.bodyBackgroundStyle; 307 } 308 if (newConfig.loginBoxBackgroundStyle != null) { 309 loginBoxBackgroundStyle = newConfig.loginBoxBackgroundStyle; 310 } 311 if (newConfig.loginBoxWidth != null) { 312 loginBoxWidth = newConfig.loginBoxWidth; 313 } 314 if (newConfig.disableBackgroundSizeCover != null) { 315 disableBackgroundSizeCover = newConfig.disableBackgroundSizeCover; 316 } 317 if (newConfig.logoAlt != null) { 318 logoAlt = newConfig.logoAlt; 319 } 320 if (newConfig.logoHeight != null) { 321 logoHeight = newConfig.logoHeight; 322 } 323 if (newConfig.logoUrl != null) { 324 logoUrl = newConfig.logoUrl; 325 } 326 if (newConfig.logoWidth != null) { 327 logoWidth = newConfig.logoWidth; 328 } 329 if (newConfig.fieldAutocomplete != null) { 330 fieldAutocomplete = newConfig.fieldAutocomplete; 331 } 332 if (newConfig.videos != null) { 333 videos = newConfig.videos; 334 } 335 if (newConfig.loop != null) { 336 loop = newConfig.loop; 337 } 338 if (newConfig.removeNews) { 339 removeNews = newConfig.removeNews; 340 } 341 if (newConfig.muted != null) { 342 muted = newConfig.muted; 343 } 344 if (newConfig.loginButtonBackgroundColor != null) { 345 loginButtonBackgroundColor = newConfig.loginButtonBackgroundColor; 346 } 347 if (newConfig.backgroundImage != null) { 348 backgroundImage = newConfig.backgroundImage; 349 } 350 351 if (providers == null) { 352 providers = newConfig.providers; 353 } else if (newConfig.providers != null && newConfig.providers.size() > 0) { 354 for (LoginProviderLink link : newConfig.providers) { 355 356 int idx = providers.indexOf(link); 357 if (idx >= 0) { 358 if (link.remove) { 359 providers.remove(idx); 360 } else { 361 providers.get(idx).merge(link); 362 } 363 } else { 364 providers.add(link); 365 } 366 } 367 } 368 } 369 370 /** 371 * @since 7.10 372 */ 373 @Override 374 public LoginScreenConfig clone() { 375 LoginScreenConfig clone = new LoginScreenConfig(); 376 clone.bodyBackgroundStyle = bodyBackgroundStyle; 377 clone.disableBackgroundSizeCover = disableBackgroundSizeCover; 378 clone.fieldAutocomplete = fieldAutocomplete; 379 clone.footerStyle = footerStyle; 380 clone.headerStyle = headerStyle; 381 clone.loginBoxBackgroundStyle = loginBoxBackgroundStyle; 382 clone.loginBoxWidth = loginBoxWidth; 383 clone.loginButtonBackgroundColor = loginButtonBackgroundColor; 384 clone.logoAlt = logoAlt; 385 clone.logoHeight = logoHeight; 386 clone.logoUrl = logoUrl; 387 clone.logoWidth = logoWidth; 388 clone.loop = loop; 389 clone.muted = muted; 390 clone.newsIframeUrl = newsIframeUrl; 391 if (providers != null) { 392 clone.providers = new ArrayList<LoginProviderLink>(); 393 for (LoginProviderLink l : providers) { 394 clone.providers.add(l.clone()); 395 } 396 } 397 clone.removeNews = removeNews; 398 if (videos != null) { 399 clone.videos = new ArrayList<LoginVideo>(); 400 for (LoginVideo v : videos) { 401 clone.videos.add(v.clone()); 402 } 403 } 404 return clone; 405 } 406 407}