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