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}