From 438596df72429c4b6ae59450c7e8f23ffcf65984 Mon Sep 17 00:00:00 2001 From: Makhtar DIAGNE <makhtar.diagne@teamdlab.com> Date: Wed, 3 Jun 2020 01:33:22 +0200 Subject: [PATCH] [TECH] CAS 6.1.6 : update static templates, js & add theming variables --- .../config/cas-server-application-dev.yml | 4 +- .../vitamui/cas/config/WebflowConfig.java | 49 +- .../gouv/vitamui/cas/pm/PmMessageToSend.java | 6 +- .../cas/pm/ResetPasswordController.java | 6 +- .../fr/gouv/vitamui/cas/util/Constants.java | 5 +- .../actions/CustomInitialFlowSetupAction.java | 135 + .../GeneralTerminateSessionAction.java | 54 + ...8NSendPasswordResetInstructionsAction.java | 34 +- .../src/main/resources/application.properties | 1 + .../resources/overriden_messages.properties | 24 +- .../overriden_messages_de.properties | 14 +- .../overriden_messages_fr.properties | 20 +- .../resources/static/js/attrresolution.js | 116 - .../main/resources/static/js/authnEvents.js | 49 - .../src/main/resources/static/js/cas.js | 55 +- .../main/resources/static/js/consentReview.js | 221 -- .../resources/static/js/loggingDashboard.js | 342 --- .../main/resources/static/js/passwordMeter.js | 31 +- .../src/main/resources/static/js/sockjs.js | 2378 ----------------- .../main/resources/static/js/ssosessions.js | 351 --- .../resources/static/js/statisticsview.js | 208 -- .../src/main/resources/static/js/stomp.js | 474 ---- .../resources/static/js/trustedDevices.js | 59 - .../main/resources/static/js/viewConfig.js | 157 -- .../resources/static/js/viewConfigMetadata.js | 136 - .../casAccountBadConfigurationView.html | 2 +- .../templates/casAccountDisabledView.html | 3 + .../templates/casAccountLockedView.html | 3 + .../casAuthenticationBlockedView.html | 3 + .../templates/casExpiredPassView.html | 4 + .../templates/casGenericSuccessView.html | 32 +- .../resources/templates/casLoginView.html | 28 +- .../resources/templates/casLogoutView.html | 28 +- .../templates/casMustChangePassView.html | 4 + .../templates/casPac4jStopWebflow.html | 3 + .../casPasswordUpdateSuccessView.html | 5 +- .../templates/casPropagateLogoutView.html | 7 +- .../main/resources/templates/casPwdView.html | 26 +- .../templates/casResetPasswordErrorView.html | 3 + .../casResetPasswordSendInstructionsView.html | 3 + .../casResetPasswordSentInstructionsView.html | 3 + .../templates/casServiceErrorView.html | 7 +- .../templates/casSimpleMfaLoginView.html | 5 +- .../src/main/resources/templates/error.html | 7 +- .../main/resources/templates/error/401.html | 8 +- .../main/resources/templates/error/403.html | 6 +- .../main/resources/templates/error/404.html | 6 +- .../main/resources/templates/error/405.html | 6 +- .../main/resources/templates/error/423.html | 6 +- .../templates/fragments/pwdupdateform.html | 7 + .../templates/fragments/scripts.html | 58 +- .../src/main/resources/templates/layout.html | 32 +- .../protocol/casGetResponseView.html | 4 +- .../group_vars/all/vitamui_vars.yml | 5 + .../templates/cas-server/application.yml.j2 | 8 +- 55 files changed, 496 insertions(+), 4755 deletions(-) create mode 100644 cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java delete mode 100644 cas/cas-server/src/main/resources/static/js/attrresolution.js delete mode 100644 cas/cas-server/src/main/resources/static/js/authnEvents.js delete mode 100644 cas/cas-server/src/main/resources/static/js/consentReview.js delete mode 100644 cas/cas-server/src/main/resources/static/js/loggingDashboard.js delete mode 100644 cas/cas-server/src/main/resources/static/js/sockjs.js delete mode 100644 cas/cas-server/src/main/resources/static/js/ssosessions.js delete mode 100644 cas/cas-server/src/main/resources/static/js/statisticsview.js delete mode 100644 cas/cas-server/src/main/resources/static/js/stomp.js delete mode 100644 cas/cas-server/src/main/resources/static/js/trustedDevices.js delete mode 100644 cas/cas-server/src/main/resources/static/js/viewConfig.js delete mode 100644 cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js diff --git a/cas/cas-server/src/main/config/cas-server-application-dev.yml b/cas/cas-server/src/main/config/cas-server-application-dev.yml index 033c8a6c..e8539df2 100644 --- a/cas/cas-server/src/main/config/cas-server-application-dev.yml +++ b/cas/cas-server/src/main/config/cas-server-application-dev.yml @@ -147,8 +147,10 @@ server-identity : identityServerId: 1 -# Example to override theme colors and logo +# Example to override theme colors, logo, favicon, platform name ... theme: +# vitamui-platform-name: VITAM-UI +# vitamui-favicon: /absolute/path/to/favicon.ico # vitam-logo: /absolute/path/to/logo.png # vitamui-logo-large: /absolute/path/to/logo.png primary: '#ff4a54' diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java index 9ae67f5c..84bf6725 100644 --- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java @@ -36,18 +36,9 @@ */ package fr.gouv.vitamui.cas.config; -import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder; -import fr.gouv.vitamui.cas.pm.ResetPasswordController; -import fr.gouv.vitamui.cas.util.Utils; -import fr.gouv.vitamui.cas.webflow.actions.GeneralTerminateSessionAction; -import fr.gouv.vitamui.cas.provider.ProvidersService; -import fr.gouv.vitamui.cas.webflow.actions.*; -import fr.gouv.vitamui.cas.webflow.configurer.CustomLoginWebflowConfigurer; -import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper; -import fr.gouv.vitamui.iam.external.client.CasExternalRestClient; -import lombok.val; import org.apereo.cas.CentralAuthenticationService; import org.apereo.cas.audit.AuditableExecution; +import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan; import org.apereo.cas.authentication.AuthenticationSystemSupport; import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy; @@ -83,7 +74,11 @@ import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.ApplicationContext; import org.springframework.context.HierarchicalMessageSource; -import org.springframework.context.annotation.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.webflow.config.FlowDefinitionRegistryBuilder; @@ -92,6 +87,26 @@ import org.springframework.webflow.engine.builder.support.FlowBuilderServices; import org.springframework.webflow.execution.Action; import org.thymeleaf.spring5.SpringTemplateEngine; +import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder; +import fr.gouv.vitamui.cas.pm.ResetPasswordController; +import fr.gouv.vitamui.cas.provider.ProvidersService; +import fr.gouv.vitamui.cas.util.Utils; +import fr.gouv.vitamui.cas.webflow.actions.CheckMfaTokenAction; +import fr.gouv.vitamui.cas.webflow.actions.CustomDelegatedClientAuthenticationAction; +import fr.gouv.vitamui.cas.webflow.actions.CustomInitialFlowSetupAction; +import fr.gouv.vitamui.cas.webflow.actions.CustomSendTokenAction; +import fr.gouv.vitamui.cas.webflow.actions.CustomVerifyPasswordResetRequestAction; +import fr.gouv.vitamui.cas.webflow.actions.DispatcherAction; +import fr.gouv.vitamui.cas.webflow.actions.GeneralTerminateSessionAction; +import fr.gouv.vitamui.cas.webflow.actions.I18NSendPasswordResetInstructionsAction; +import fr.gouv.vitamui.cas.webflow.actions.NoOpAction; +import fr.gouv.vitamui.cas.webflow.actions.SelectRedirectAction; +import fr.gouv.vitamui.cas.webflow.actions.TriggerChangePasswordAction; +import fr.gouv.vitamui.cas.webflow.configurer.CustomLoginWebflowConfigurer; +import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper; +import fr.gouv.vitamui.iam.external.client.CasExternalRestClient; +import lombok.val; + /** * Web(flow) customizations. * @@ -116,6 +131,10 @@ public class WebflowConfig { @Qualifier("authenticationServiceSelectionPlan") private ObjectProvider<AuthenticationServiceSelectionPlan> authenticationRequestServiceSelectionStrategies; + @Autowired + @Qualifier("authenticationEventExecutionPlan") + private ObjectProvider<AuthenticationEventExecutionPlan> AuthenticationEventExecutionStrategies; + @Autowired @Qualifier("communicationsManager") private CommunicationsManager communicationsManager; @@ -228,6 +247,14 @@ public class WebflowConfig { surrogationSeparator, utils, delegatedClientDistributedSessionStore.getObject()); } + @RefreshScope + @Bean + public Action initialFlowSetupAction() { + return new CustomInitialFlowSetupAction(CollectionUtils.wrap(argumentExtractor.getObject()), servicesManager.getObject(), + authenticationRequestServiceSelectionStrategies.getObject(), ticketGrantingTicketCookieGenerator.getObject(), warnCookieGenerator.getObject(), + casProperties, AuthenticationEventExecutionStrategies.getObject(), webflowSingleSignOnParticipationStrategy.getObject(), ticketRegistrySupport); + } + @Bean public DefaultTransientSessionTicketFactory pmTicketFactory() { return new DefaultTransientSessionTicketFactory(new PmTransientSessionTicketExpirationPolicyBuilder(casProperties)); diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java index eb40a874..953a5910 100644 --- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java @@ -74,16 +74,16 @@ public class PmMessageToSend { } public static PmMessageToSend buildMessage(final HierarchicalMessageSource messageSource, final String firstname, - final String lastname, final String ttlInMinutes, final String url, final Locale locale) { + final String lastname, final String ttlInMinutes, final String url, final String platformName, final Locale locale) { final String subject; final String text; if (ONE_DAY.equals(ttlInMinutes)) { subject = messageSource.getMessage(PM_ACCOUNTCREATION_SUBJECT_KEY, null, locale); text = messageSource.getMessage(PM_ACCOUNTCREATION_TEXT_KEY, - new Object[] { firstname, lastname, "24", url }, locale); + new Object[] { firstname, lastname, "24", url, platformName }, locale); } else { subject = messageSource.getMessage(PM_RESET_SUBJECT_KEY, null, locale); - text = messageSource.getMessage(PM_RESET_TEXT_KEY, new Object[] { firstname, lastname, ttlInMinutes, url }, + text = messageSource.getMessage(PM_RESET_TEXT_KEY, new Object[] { firstname, lastname, ttlInMinutes, url, platformName}, locale); } return new PmMessageToSend(subject, text); diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java index 80acc38d..d9d385e5 100644 --- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java @@ -51,6 +51,7 @@ import org.apereo.cas.ticket.registry.TicketRegistry; import org.apereo.cas.util.CollectionUtils; import org.apereo.cas.util.io.CommunicationsManager; import org.apereo.cas.web.flow.CasWebflowConfigurer; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.HierarchicalMessageSource; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -89,6 +90,9 @@ public class ResetPasswordController { private final DefaultTransientSessionTicketFactory pmTicketFactory; + @Value("${theme.vitamui-platform-name:VITAM-UI}") + private String vitamuiPlatformName; + @GetMapping("/resetPassword") public boolean resetPassword(@RequestParam(value = "username", defaultValue = "") final String username, @RequestParam(value = "firstname", defaultValue = "") final String firstname, @@ -122,7 +126,7 @@ public class ResetPasswordController { request.setAttribute(PmTransientSessionTicketExpirationPolicyBuilder.PM_EXPIRATION_IN_MINUTES_ATTRIBUTE, expMinutes); final String url = buildPasswordResetUrl(usernameLower, casProperties); - final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, firstname, lastname, ttl, url, new Locale(language)); + final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, firstname, lastname, ttl, url, vitamuiPlatformName, new Locale(language)); LOGGER.debug("Generated password reset URL [{}] for: {} ({}); Link is only active for the next [{}] minute(s)", utils.sanitizePasswordResetUrl(url), email, messageToSend.getSubject(), expMinutes); diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java index ce080b43..a925d0b7 100644 --- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java @@ -55,4 +55,7 @@ public abstract class Constants { public static final String VITAM_LOGO = "vitamLogo"; - public static final String VITAM_UI_LARGE_LOGO = "vitamuiLargeLogo";} + public static final String VITAM_UI_LARGE_LOGO = "vitamuiLargeLogo"; + + public static final String VITAM_UI_FAVICON = "vitamuiFavicon"; +} diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java new file mode 100644 index 00000000..b3408842 --- /dev/null +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java @@ -0,0 +1,135 @@ +/** +* Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) +* and the signatories of the "VITAM - Accord du Contributeur" agreement. +* +* contact@programmevitam.fr +* +* This software is a computer program whose purpose is to implement +* implement a digital archiving front-office system for the secure and +* efficient high volumetry VITAM solution. +* +* This software is governed by the CeCILL-C license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL-C +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL-C license and that you accept its terms. +*/ +package fr.gouv.vitamui.cas.webflow.actions; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import javax.xml.bind.DatatypeConverter; + +import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; +import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan; +import org.apereo.cas.configuration.CasConfigurationProperties; +import org.apereo.cas.services.ServicesManager; +import org.apereo.cas.ticket.registry.TicketRegistrySupport; +import org.apereo.cas.web.cookie.CasCookieBuilder; +import org.apereo.cas.web.flow.SingleSignOnParticipationStrategy; +import org.apereo.cas.web.flow.login.InitialFlowSetupAction; +import org.apereo.cas.web.support.ArgumentExtractor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.webflow.core.collection.MutableAttributeMap; +import org.springframework.webflow.execution.Event; +import org.springframework.webflow.execution.RequestContext; + +import fr.gouv.vitamui.cas.util.Constants; +import fr.gouv.vitamui.commons.api.logger.VitamUILogger; +import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory; + +/** +* Custom initial flow action to retrieve pre-filled inputs. +* +* +*/ +public class CustomInitialFlowSetupAction extends InitialFlowSetupAction { + + private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(CustomInitialFlowSetupAction.class); + + @Value("${theme.vitam-logo:#{null}}") + private String vitamLogoPath; + + @Value("${theme.vitamui-logo-large:#{null}}") + private String vitamuiLargeLogoPath; + + @Value("${theme.vitamui-favicon:#{null}}") + private String vitamuiFaviconPath; + + public CustomInitialFlowSetupAction(final List<ArgumentExtractor> argumentExtractors, final ServicesManager servicesManager, + final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies, + final CasCookieBuilder ticketGrantingTicketCookieGenerator, final CasCookieBuilder warnCookieGenerator, + final CasConfigurationProperties casProperties, final AuthenticationEventExecutionPlan authenticationEventExecutionPlan, + final SingleSignOnParticipationStrategy renewalStrategy, final TicketRegistrySupport ticketRegistrySupport) { + super(argumentExtractors, servicesManager, authenticationRequestServiceSelectionStrategies, ticketGrantingTicketCookieGenerator, warnCookieGenerator, + casProperties, authenticationEventExecutionPlan, renewalStrategy, ticketRegistrySupport); + } + + @Override + public Event doExecute(final RequestContext context) { + + final MutableAttributeMap<Object> flowScope = context.getFlowScope(); + + if (vitamLogoPath != null) { + try { + final Path logoFile = Paths.get(vitamLogoPath); + final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile)); + flowScope.put(Constants.VITAM_LOGO, logo); + } + catch (final IOException e) { + LOGGER.warn("Can't find vitam logo"); + e.printStackTrace(); + } + } + if (vitamuiLargeLogoPath != null) { + try { + final Path logoFile = Paths.get(vitamuiLargeLogoPath); + final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile)); + flowScope.put(Constants.VITAM_UI_LARGE_LOGO, logo); + } + catch (final IOException e) { + LOGGER.warn("Can't find vitam ui large logo"); + e.printStackTrace(); + } + } + + if (vitamuiFaviconPath != null) { + try { + final Path faviconFile = Paths.get(vitamuiFaviconPath); + final String favicon = DatatypeConverter.printBase64Binary(Files.readAllBytes(faviconFile)); + flowScope.put(Constants.VITAM_UI_FAVICON, favicon); + } + catch (final IOException e) { + LOGGER.warn("Can't find vitam ui favicon"); + e.printStackTrace(); + } + } + + return super.doExecute(context); + } + +} diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java index 9803b129..1bca8365 100644 --- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java @@ -36,6 +36,7 @@ */ package fr.gouv.vitamui.cas.webflow.actions; +import fr.gouv.vitamui.cas.util.Constants; import fr.gouv.vitamui.cas.util.Utils; import fr.gouv.vitamui.commons.api.logger.VitamUILogger; import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory; @@ -68,11 +69,19 @@ import org.apereo.cas.web.flow.logout.FrontChannelLogoutAction; import org.apereo.cas.web.flow.logout.TerminateSessionAction; import org.apereo.cas.web.support.WebUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.webflow.core.collection.MutableAttributeMap; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.DatatypeConverter; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import static fr.gouv.vitamui.commons.api.CommonConstants.*; @@ -106,6 +115,15 @@ public class GeneralTerminateSessionAction extends TerminateSessionAction { @Autowired private FrontChannelLogoutAction frontChannelLogoutAction; + @Value("${theme.vitam-logo:#{null}}") + private String vitamLogoPath; + + @Value("${theme.vitamui-logo-large:#{null}}") + private String vitamuiLargeLogoPath; + + @Value("${theme.vitamui-favicon:#{null}}") + private String vitamuiFaviconPath; + public GeneralTerminateSessionAction(final CentralAuthenticationService centralAuthenticationService, final CasCookieBuilder ticketGrantingTicketCookieGenerator, final CasCookieBuilder warnCookieGenerator, @@ -173,6 +191,42 @@ public class GeneralTerminateSessionAction extends TerminateSessionAction { frontChannelLogoutAction.doExecute(context); } + final MutableAttributeMap<Object> flowScope = context.getFlowScope(); + if (vitamLogoPath != null) { + try { + final Path logoFile = Paths.get(vitamLogoPath); + final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile)); + flowScope.put(Constants.VITAM_LOGO, logo); + } + catch (final IOException e) { + LOGGER.warn("Can't find vitam logo"); + e.printStackTrace(); + } + } + if (vitamuiLargeLogoPath != null) { + try { + final Path logoFile = Paths.get(vitamuiLargeLogoPath); + final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile)); + flowScope.put(Constants.VITAM_UI_LARGE_LOGO, logo); + } + catch (final IOException e) { + LOGGER.warn("Can't find vitam ui large logo"); + e.printStackTrace(); + } + } + + if (vitamuiFaviconPath != null) { + try { + final Path faviconFile = Paths.get(vitamuiFaviconPath); + final String favicon = DatatypeConverter.printBase64Binary(Files.readAllBytes(faviconFile)); + flowScope.put(Constants.VITAM_UI_FAVICON, favicon); + } + catch (final IOException e) { + LOGGER.warn("Can't find vitam ui favicon"); + e.printStackTrace(); + } + } + return event; } diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java index 89b321bb..26392dc6 100644 --- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java +++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java @@ -36,14 +36,6 @@ */ package fr.gouv.vitamui.cas.webflow.actions; -import fr.gouv.vitamui.cas.pm.PmMessageToSend; -import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder; -import fr.gouv.vitamui.cas.provider.ProvidersService; -import fr.gouv.vitamui.cas.util.Utils; -import fr.gouv.vitamui.commons.api.logger.VitamUILogger; -import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory; -import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper; -import lombok.val; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.authentication.credential.UsernamePasswordCredential; import org.apereo.cas.configuration.CasConfigurationProperties; @@ -53,12 +45,22 @@ import org.apereo.cas.ticket.TicketFactory; import org.apereo.cas.ticket.registry.TicketRegistry; import org.apereo.cas.util.io.CommunicationsManager; import org.apereo.cas.web.support.WebUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.HierarchicalMessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.webflow.core.collection.MutableAttributeMap; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; +import fr.gouv.vitamui.cas.pm.PmMessageToSend; +import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder; +import fr.gouv.vitamui.cas.provider.ProvidersService; +import fr.gouv.vitamui.cas.util.Utils; +import fr.gouv.vitamui.commons.api.logger.VitamUILogger; +import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory; +import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper; +import lombok.val; + /** * Send reset password emails with i18n messages. * @@ -66,8 +68,7 @@ import org.springframework.webflow.execution.RequestContext; */ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetInstructionsAction { - private static final VitamUILogger LOGGER = VitamUILoggerFactory - .getInstance(I18NSendPasswordResetInstructionsAction.class); + private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(I18NSendPasswordResetInstructionsAction.class); private final CasConfigurationProperties casProperties; @@ -83,6 +84,9 @@ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetIn private final Utils utils; + @Value("${theme.vitamui-platform-name:VITAM-UI}") + private String vitamuiPlatformName; + public I18NSendPasswordResetInstructionsAction(final CasConfigurationProperties casProperties, final CommunicationsManager communicationsManager, final PasswordManagementService passwordManagementService, @@ -141,8 +145,8 @@ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetIn val url = buildPasswordResetUrl(username, passwordManagementService, casProperties, service); if (StringUtils.isNotBlank(url)) { val pm = casProperties.getAuthn().getPm(); - LOGGER.debug("Generated password reset URL [{}]; Link is only active for the next [{}] minute(s)", - utils.sanitizePasswordResetUrl(url), pm.getReset().getExpirationMinutes()); + LOGGER.debug("Generated password reset URL [{}]; Link is only active for the next [{}] minute(s)", utils.sanitizePasswordResetUrl(url), + pm.getReset().getExpirationMinutes()); if (sendPasswordResetEmailToAccount(email, url)) { return success(); } @@ -155,9 +159,9 @@ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetIn @Override protected boolean sendPasswordResetEmailToAccount(final String to, final String url) { - final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, "", "", "10", url, + final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, "", "", "10", url, vitamuiPlatformName, LocaleContextHolder.getLocale()); - return utils.htmlEmail(messageToSend.getText(), casProperties.getAuthn().getPm().getReset().getMail().getFrom(), - messageToSend.getSubject(), to, null, null); + return utils.htmlEmail(messageToSend.getText(), casProperties.getAuthn().getPm().getReset().getMail().getFrom(), messageToSend.getSubject(), to, null, + null); } } diff --git a/cas/cas-server/src/main/resources/application.properties b/cas/cas-server/src/main/resources/application.properties index 2e68c5b1..ca7fdb1b 100644 --- a/cas/cas-server/src/main/resources/application.properties +++ b/cas/cas-server/src/main/resources/application.properties @@ -182,6 +182,7 @@ cas.view.cas2.v3ForwardCompatible=true # theme.vitam-logo=/path/to/vitam-logo/vitam-logo.png # theme.vitamui-logo-large=/path/to/vitam-logo/vitamui-logo-large.png +theme.vitamui-platform-name=VITAM-UI theme.primary=#702382 theme.secondary=#7FA1D4 diff --git a/cas/cas-server/src/main/resources/overriden_messages.properties b/cas/cas-server/src/main/resources/overriden_messages.properties index 422cbc13..2118f9a9 100644 --- a/cas/cas-server/src/main/resources/overriden_messages.properties +++ b/cas/cas-server/src/main/resources/overriden_messages.properties @@ -4,23 +4,23 @@ screen.accountlocked.message=Please wait before trying again authenticationFailure.AccountLockedException=Your account has been locked for the next 20 minutes, please wait before trying again cas.authn.pm.reset.subject=Password creation -cas.authn.pm.reset.text=<html><body>Hello.<br /><br />Here is the link that will allow you to create a new password on VitamUI: <a href="{3}">click here</a>.<br />This one is valid for the next {2} minutes.<br /><br />Have a good day.</body></html> +cas.authn.pm.reset.text=<html><body>Hello.<br /><br />Here is the link that will allow you to create a new password on {4}: <a href="{3}">click here</a>.<br />This one is valid for the next {2} minutes.<br /><br />Have a good day.</body></html> cas.authn.pm.accountcreation.subject=Password creation -cas.authn.pm.accountcreation.text=<html><body>Hello {0} {1}.<br /><br />Here is the link that will allow you to create a new password on VitamUI: <a href="{3}">click here</a>.<br />This one is valid for the next {2} hours.<br /><br />Have a good day.</body></html> +cas.authn.pm.accountcreation.text=<html><body>Hello {0} {1}.<br /><br />Here is the link that will allow you to create a new password on {0}: <a href="{3}">click here</a>.<br />This one is valid for the next {2} hours.<br /><br />Have a good day.</body></html> screen.welcome.label.surrogate=Surrogate: screen.welcome.label.superuser=Super user: -screen.service.error.header=Application Not Authorized to Use VITAMUI +screen.service.error.header=Application Not Authorized to Use {0} service.not.authorized.missing.attr=You are not authorized to access the application as your account \ -is missing privileges required by the VITAMUI server to authenticate into this service. Please notify your support desk. -screen.service.error.message=The application you attempted to authenticate to is not authorized to use VITAMUI. \ - Contact your VITAMUI administrator to learn how you might register and integrate your application with VITAMUI. -screen.service.empty.error.message=Contact your VITAMUI administrator to learn how you might register and integrate your application with VITAMUI. +is missing privileges required by the {0} server to authenticate into this service. Please notify your support desk. +screen.service.error.message=The application you attempted to authenticate to is not authorized. \ + Contact your administrator to learn how you might register and integrate your application. +screen.service.empty.error.message=Contact your administrator to learn how you might register and integrate your application. screen.logout.header=Logout -screen.logout.success=You have successfully logged out of VITAMUI. You may <a href="login">log in</a> again. -screen.logout.fc.success=You have successfully logged out of VITAMUI. You may <a href="login">log in</a> again. +screen.logout.success=You have successfully logged out of {0}. You may <a href="login">log in</a> again. +screen.logout.fc.success=You have successfully logged out of {0}. You may <a href="login">log in</a> again. screen.logout.security=For security reasons, exit your web browser. screen.pac4j.unauthz.message=You are not authorized to access the application. @@ -35,9 +35,9 @@ screen.pm.success.header=Password Change pm.validationFailure.alreadyUsed=You cannot set again one of your three latest passwords # Unavailable -screen.unavailable.header=VITAMUI Error +screen.unavailable.header={0} Error screen.unavailable.heading=An error occurred while processing your request. -screen.unavailable.message=Contact your VITAMUI administrator. +screen.unavailable.message=Contact your {0} administrator. screen.accountbadconfiguration.heading=Your account is not properly configured. -screen.accountbadconfiguration.message=Contact your VITAMUI administrator. +screen.accountbadconfiguration.message=Contact your {0} administrator. diff --git a/cas/cas-server/src/main/resources/overriden_messages_de.properties b/cas/cas-server/src/main/resources/overriden_messages_de.properties index 734a09d4..e8230943 100644 --- a/cas/cas-server/src/main/resources/overriden_messages_de.properties +++ b/cas/cas-server/src/main/resources/overriden_messages_de.properties @@ -11,12 +11,12 @@ cas.authn.pm.accountcreation.text=Hallo {0} {1}.\n\nHier ist der Link, mit dem S screen.welcome.label.surrogate=�bergegangenen : screen.welcome.label.superuser=Superbenutzer : -screen.service.error.header=Anwendung darf VITAMUI nicht verwenden +screen.service.error.header=Anwendung darf {0} nicht verwenden service.not.authorized.missing.attr=Sie sind nicht berechtigt, auf diese Anwendung zuzugreifen, da Ihr Konto nicht �ber die Berechtigungen verf�gt, \ -die der VITAMUI-Anbieter f�r den Zugriff auf diesen Dienst ben�tigt. Bitte kontaktieren Sie Ihren Support. -screen.service.error.message=Die Anwendung, f�r die Sie eine Authentifizierung versucht haben, darf VITAMUI nicht verwenden. \ - <br>Wenden Sie sich an Ihren VITAMUI-Administrator, um zu erfahren, wie Sie Ihre Anwendung bei VITAMUI registrieren und integrieren. -screen.service.empty.error.message=Wenden Sie sich an Ihren VITAMUI-Administrator, um zu erfahren, wie Sie Ihre Anwendung bei VITAMUI registrieren und integrieren. +die der {0}-Anbieter f�r den Zugriff auf diesen Dienst ben�tigt. Bitte kontaktieren Sie Ihren Support. +screen.service.error.message=Die Anwendung, f�r die Sie eine Authentifizierung versucht haben. \ + <br>Wenden Sie sich an Ihren Administrator, um zu erfahren, wie Sie Ihre Anwendung registrieren und integrieren. +screen.service.empty.error.message=Wenden Sie sich an Ihren Administrator, um zu erfahren, wie Sie Ihre Anwendung registrieren und integrieren. screen.logout.header=austragen screen.logout.success=Sie haben sich ausgeloggt. Sie k�nnen sich <a href="login">erneut</a> anmelden. @@ -36,6 +36,6 @@ screen.pm.init.security.four=Beide Passwörter müssen übereinstimmen screen.pm.success.header=�nderung des Passwortes # Unavailable -screen.unavailable.header=VITAMUI-Fehler +screen.unavailable.header={0}-Fehler screen.unavailable.heading=Bei der Bearbeitung Ihrer Anfrage ist ein Fehler aufgetreten. -screen.unavailable.message=Wenden Sie sich an Ihren VITAMUI-Administrator. +screen.unavailable.message=Wenden Sie sich an Ihren {0}-Administrator. diff --git a/cas/cas-server/src/main/resources/overriden_messages_fr.properties b/cas/cas-server/src/main/resources/overriden_messages_fr.properties index 05ca4a0a..9744b82c 100644 --- a/cas/cas-server/src/main/resources/overriden_messages_fr.properties +++ b/cas/cas-server/src/main/resources/overriden_messages_fr.properties @@ -4,19 +4,19 @@ screen.accountlocked.message=Veuillez patienter avant de réessayer authenticationFailure.AccountLockedException=Votre compte est bloqué pour les 20 prochaines minutes, veuillez patienter avant de réessayer cas.authn.pm.reset.subject=Création de mot de passe -cas.authn.pm.reset.text=<html><body>Bonjour.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur VitamUI : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} minutes.<br/><br/>Bonne journée.</body></html> +cas.authn.pm.reset.text=<html><body>Bonjour.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur {4} : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} minutes.<br/><br/>Bonne journée.</body></html> cas.authn.pm.accountcreation.subject=Création de mot de passe -cas.authn.pm.accountcreation.text=<html><body>Bonjour {0} {1}.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur VitamUI : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} heures.<br/><br/>Bonne journée.</body></html> +cas.authn.pm.accountcreation.text=<html><body>Bonjour {0} {1}.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur {4} : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} heures.<br/><br/>Bonne journée.</body></html> screen.welcome.label.surrogate=Subrogé : screen.welcome.label.superuser=Super utilisateur : -screen.service.error.header=Application non autorisée à utiliser VITAMUI +screen.service.error.header=Application non autorisée à utiliser {0} service.not.authorized.missing.attr=Vous n'êtes pas autorisé à accéder à cette application car votre compte \ -n'a pas les privilèges requis par le seveur VITAMUI pour accéder à ce service. Merci de contacter votre support. -screen.service.error.message=L'application pour laquelle vous avez tenté de vous authentifier n'est pas autorisée à utiliser VITAMUI. \ - <br>Contactez votre administrateur VITAMUI pour savoir comment enregistrer et intégrer votre application à VITAMUI. -screen.service.empty.error.message=Contactez votre administrateur VITAMUI pour savoir comment enregistrer et intégrer votre application à VITAMUI. +n'a pas les privilèges requis par le seeveur {0} pour accéder à ce service. Merci de contacter votre support. +screen.service.error.message=L' application pour laquelle vous avez tenté de vous authentifier n'est pas autorisée. \ + <br>Contactez votre administrateur pour savoir comment enregistrer et intégrer votre application. +screen.service.empty.error.message=Contactez votre administrateur pour savoir comment enregistrer et intégrer votre application. screen.logout.header=Déconnexion screen.logout.success=Vous vous êtes déconnecté(e). Vous pouvez vous <a href="login">connecter</a> à nouveau. @@ -57,11 +57,11 @@ screen.mfa.sms.expired.resend=Envoyer un nouveau code au {0} authenticationFailure.AuthenticationException=Le code OTP est erroné # Unavailable -screen.unavailable.header=Erreur VITAMUI +screen.unavailable.header=Erreur {0} screen.unavailable.heading=Une erreur est survenue lors du traitement de votre requête. -screen.unavailable.message=Contactez votre administrateur VITAMUI. +screen.unavailable.message=Contactez votre administrateur {0}. screen.accountbadconfiguration.heading=Votre compte a un problème de configuration. -screen.accountbadconfiguration.message=Contactez votre administrateur VITAMUI. +screen.accountbadconfiguration.message=Contactez votre administrateur {0}. screen.pm.reset.message=Le lien n'est plus valide. diff --git a/cas/cas-server/src/main/resources/static/js/attrresolution.js b/cas/cas-server/src/main/resources/static/js/attrresolution.js deleted file mode 100644 index e500ff3f..00000000 --- a/cas/cas-server/src/main/resources/static/js/attrresolution.js +++ /dev/null @@ -1,116 +0,0 @@ -var table; - -$(document).ready(function () { - $('#fmrel').on('submit', function (e) { - e.preventDefault(); - var username = $('#username').val(); - var password = $('#password').val(); - var service = $('#service').val(); - - releaseAttributes(username, password, service); - }); - - - $('#fm1').on('submit', function (e) { - e.preventDefault(); - var uid = $('#uid').val(); - table = $('#attributesTable').DataTable(); - table.clear().draw(); - - var status = $('#status'); - - if (uid !== null && uid !== '') { - resolveAttributes(uid); - status.html('Resolved attributes for username <strong>' + uid + '</strong>.'); - status.removeClass('alert-danger'); - status.addClass('alert-info'); - status.show(); - } else { - status.html('No username is provided.'); - status.removeClass('alert-info'); - status.addClass('alert-danger'); - status.show(); - } - }); - - if ($.fn.dataTable.isDataTable('#attributesTable')) { - table = $('#attributesTable').DataTable(); - } else { - table = $('#attributesTable').DataTable({ - paging: false, - searching: false - }); - } - - $('#status').hide(); - -}); - -function resolveAttributes(uid) { - $.ajax({ - type: 'post', - url: urls.resolveAttributes, - data: {'uid': uid}, - success: function (data) { - var table = $('#attributesTable').DataTable(); - table.clear(); - var attrs = data.attributes; - for (var property in attrs) { - if (attrs.hasOwnProperty(property)) { - table.row.add([ - '<code>' + property + '</code>', '<code>' + attrs[property] + '</code>' - ]).draw(false); - } - } - } - }); -} - -function releaseAttributes(uid, psw, service) { - $('validationresponse').empty(); - $('cas1').empty(); - $('cas2').empty(); - $('cas3Xml').empty(); - $('cas3Json').empty(); - - $('#submitRelease').attr('disabled', 'disabled'); - $.ajax({ - type: 'post', - url: urls.releaseAttributes, - data: {'username': uid, 'password': psw, 'service': service}, - success: function (data) { - var html = '<ul><li>Service Id: <code>' + data.registeredService.id + '</code></li>' - + '<li>Service Identifier: <code>' + data.registeredService.serviceId + '</code></li>' - + '<li>Service Name: <code>' + data.registeredService.name + '</code></li>' - + '</ul><p/>'; - $('#validationresponse').html(html); - - var resp = '<pre>' + JSON.stringify(data.registeredService, null, 4) + '</pre>'; - $('#serviceJson').html(resp); - - resp = '<pre>' + data.cas1Response + '</pre>'; - $('#cas1').html(resp); - - resp = '<pre>' + data.cas2Response + '</pre>'; - $('#cas2').html(resp); - - resp = '<pre>' + data.cas3XmlResponse + '</pre>'; - $('#cas3Xml').html(resp); - - resp = '<pre>' + data.cas3JsonResponse + '</pre>'; - $('#cas3Json').html(resp); - }, - error: function (err) { - var html = '<div class=\'alert alert-danger\'>' - + '<h4>Response Error</h4>' - + 'Status: <code>' + err.responseJSON.status + '</code><p/>' - + 'Exception: <code>' + err.responseJSON.exception + '</code><p/>' - + 'Message: <code>' + err.responseJSON.message + '</code><p/>' - + '</div>'; - $('#validationresponse').html(html); - }, - complete: function() { - $('#submitRelease').removeAttr('disabled'); - } - }); -} diff --git a/cas/cas-server/src/main/resources/static/js/authnEvents.js b/cas/cas-server/src/main/resources/static/js/authnEvents.js deleted file mode 100644 index 106520bc..00000000 --- a/cas/cas-server/src/main/resources/static/js/authnEvents.js +++ /dev/null @@ -1,49 +0,0 @@ -$('#myTabs a').click(function (e) { - e.preventDefault(); - $(this).tab('show'); -}); - -(function () { - var getData = function () { - $.getJSON(urls.getEvents, function (data) { - authnEventsTable(data); - }); - }; - - var authnEventsTable = function (jsonData) { - var t = $('#authnEventsTable').DataTable({ - 'order': [[2, 'desc']], - retrieve: true, - columnDefs: [ - { - 'targets': 0, - render: function (data) { - return '<span class="glyphicon glyphicon-flash" aria-hidden="true"> </span>' + data; - } - } - ] - }); - for (var i = 0; i < jsonData.length; i++) { - var rec = jsonData[i]; - - var type = rec.type.split('.'); - t.row.add([ - type[type.length - 1], - rec.principalId, - new Date(rec.creationTime*1000), - new Date(rec.timestamp), - rec.properties.agent, - rec.clientIpAddress, - rec.serverIpAddress, - rec.properties.geoLatitude === 'undefined' ? '' : Number(rec.properties.geoLatitude).toFixed(2), - rec.properties.geoLongitude === 'undefined' ? '' : Number(rec.properties.geoLongitude).toFixed(2), - rec.properties.geoAccuracy === 'undefined' ? '' : Number(rec.properties.geoAccuracy).toFixed(2) - ]).draw(false); - } - }; - - // initialization ******* - (function init () { - getData(); - })(); -})(); diff --git a/cas/cas-server/src/main/resources/static/js/cas.js b/cas/cas-server/src/main/resources/static/js/cas.js index 8f8f902a..4152e4de 100644 --- a/cas/cas-server/src/main/resources/static/js/cas.js +++ b/cas/cas-server/src/main/resources/static/js/cas.js @@ -5,8 +5,8 @@ function requestGeoPosition() { // console.log('Requesting GeoLocation data from the browser...'); if (navigator.geolocation) { - navigator.geolocation.getCurrentPosition(showGeoPosition, logGeoLocationError, - {maximumAge: 600000, timeout: 5000, enableHighAccuracy: true}); + navigator.geolocation.watchPosition(showGeoPosition, logGeoLocationError, + {maximumAge: 600000, timeout: 8000, enableHighAccuracy: true}); } else { // console.log('Browser does not support Geo Location'); } @@ -30,8 +30,10 @@ function logGeoLocationError(error) { } function showGeoPosition(position) { - $('[name="geolocation"]').val(position.coords.latitude + ',' - + position.coords.longitude + ',' + position.coords.accuracy + ',' + position.timestamp); + let loc = position.coords.latitude + ',' + position.coords.longitude + + ',' + position.coords.accuracy + ',' + position.timestamp; + console.log("Tracking geolocation for " + loc); + $('[name="geolocation"]').val(loc); } @@ -39,7 +41,7 @@ function preserveAnchorTagOnForm() { $('#fm1').submit(function () { var location = self.document.location; var hash = decodeURIComponent(location.hash); - + if (hash != undefined && hash != '' && hash.indexOf('#') === -1) { hash = '#' + hash; } @@ -47,30 +49,31 @@ function preserveAnchorTagOnForm() { var action = $('#fm1').attr('action'); if (action == undefined) { action = location.href; - } - var qidx = location.href.indexOf('?'); - if (qidx != -1) { - var queryParams = location.href.substring(qidx); - action += queryParams; + } else { + var qidx = location.href.indexOf('?'); + if (qidx != -1) { + var queryParams = location.href.substring(qidx); + action += queryParams; + } } action += hash; $('#fm1').attr('action', action); - + }); } -function areCookiesEnabled() { - if ($.cookie == undefined) { - return; - } - - $.cookie('cookiesEnabled', 'true'); - var value = $.cookie('cookiesEnabled'); - $.removeCookie('cookiesEnabled'); - return value != undefined; - +function preventFormResubmission() { + $('form').submit(function () { + $(':submit').attr('disabled', true); + var altText = $(':submit').attr('data-processing-text'); + if (altText) { + $(':submit').attr('value', altText); + } + return true; + }); } +// Customization VITAMUI ======================= function disableEmptyInputFormSubmission() { var fields = $('#fm1 input[name="username"],[name="password"]'); @@ -103,6 +106,7 @@ function disableEmptyInputFormSubmission() { }, 100); } } +// End of Customization VITAMUI ======================= function resourceLoadedSuccessfully() { $(document).ready(function () { @@ -115,14 +119,11 @@ function resourceLoadedSuccessfully() { $('input:visible:enabled:first').focus(); } - if (areCookiesEnabled()) { - $('#cookiesDisabled').hide(); - } else { - $('#cookiesDisabled').show(); - } - + // Customization VITAMUI ======================= disableEmptyInputFormSubmission(); + // End of Customization VITAMUI ======================= preserveAnchorTagOnForm(); + preventFormResubmission(); $('#capslock-on').hide(); $('#fm1 input[name="username"],[name="password"]').trigger('input'); diff --git a/cas/cas-server/src/main/resources/static/js/consentReview.js b/cas/cas-server/src/main/resources/static/js/consentReview.js deleted file mode 100644 index ba4de18f..00000000 --- a/cas/cas-server/src/main/resources/static/js/consentReview.js +++ /dev/null @@ -1,221 +0,0 @@ -var infoEl = $('tr.info').clone(); -var strings = strings; - -/* Formatting function for row details - modify as you need */ -function format(d) { - var detail = infoEl.clone(); - // show - $(detail).toggleClass('hidden'); - // add data - var dec = d.decision; - // date - detail.find('.created-date')[0].append(date(dec.createdDate).toLocaleString()); - // options & reminder - if (dec.options === 'ALWAYS') { - detail.find('.consent-reminder').parent().remove(); - } else { - var unit = dec.reminderTimeUnit.toLowerCase(); - detail.find('.consent-reminder span:not(.' + unit + ')').remove(); - if (dec.reminder === 1) { - var _unit = detail.find('.consent-reminder span.' + unit); - _unit.html(_unit.text().slice(0, -1)); - } - detail.find('.consent-reminder').prepend(dec.reminder); - } - detail.find('.consent-options span:not(.' + dec.options.toLowerCase().replace('_','-') + ')').remove(); - // render attribute table - attributeTable(detail.find('.consent-attributes'),d.attributes); - // enable tooltip - detail.find('.consent-options [data-toggle="tooltip"]').tooltip(); - // setup delete button - var del = detail.find('.btn-danger'); - var data = { 'id': dec.id, 'service': dec.service }; - del.on('click', data, function (e) { - e.preventDefault(); - confirm(e.data.id, e.data.service); - }); - - return detail; -} - -function alertUser(message, alertType) { - $('#alertWrapper').append('<div id="alertdiv" class="alert alert-' + alertType + ' alert-dismissible">' + - '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' + - '<span class="alertMessage">' + message + '</span></div>' - ); - - setTimeout(function () { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs - $('#alertdiv').remove(); - }, 5000); -} - -function attributeTable(t, attributes) { - - var table; - if ( $.fn.dataTable.isDataTable( t ) ) { - table = $(t).DataTable(); - } - else { - table = $(t).DataTable( { - paging : false, - searching : false, - info: false - } ); - } - - table.clear(); - for (var property in attributes) { - if (attributes.hasOwnProperty(property)) { - table.row.add([ - '<code>' + property + '</code>', '<code>' + attributes[property] + '</code>' - ]).draw(false); - } - } -} - -function date(d) { - var date = new Date(d[0],d[1]-1,d[2],d[3],d[4],d[5]); - return date; -} - -function confirm(decisionId, service) { - $('#confirmdiv').remove(); - var svcStr = service.length > 70 ? service.substr(0,68) + '...' : service; - var message = strings.confirm.replace('{}', svcStr); - $('#alertWrapper').append('<div id="confirmdiv" class="alert alert-warning">' + - '<span class="alertMessage">' + message + '</span><br/>' + - '<button type="button" id="delete" class="btn btn-xs btn-danger" aria-label="Yes"><strong>' + - strings.yes + ' </strong></button>' + - '<button type="button" class="btn btn-xs btn-default" aria-label="No" value="' + decisionId + '"><strong>' + - strings.no + '</strong></button></div>' - ); - $('#confirmdiv .btn').click(function() { - $('#confirmdiv').alert('close'); - }); - $('#delete').click(function() { - removeDecision(decisionId); - }); -} - -function removeDecision(decisionId) { - var factory = {}; - factory.httpHeaders = {}; - factory.httpHeaders[$('meta[name=\'_csrf_header\']').attr('content')] = $('meta[name=\'_csrf\']').attr('content'); - - $.ajax({ - type: 'post', - url: urls.delete, - data: {decisionId: decisionId}, - headers: factory.httpHeaders, - dataType: 'json', - success: function (data) { - // Reinitialize the table data - $('#consentDecisions').DataTable().ajax.reload(); - - if (!data) { - alertUser(strings.error, 'danger'); - } else { - alertUser(strings.success, 'success'); - // Reload the page - location.reload(); - } - }, - error: function () { - alertUser('There appears to be an error. Please try your request again.', 'danger'); - } - }); -} - -var consentDecisions = (function () { - var createDataTable = function () { - $('#consentDecisions').DataTable({ - 'order': [[0, 'desc']], - 'initComplete': function (settings, json) { - if (!json || json.length == 0) { - $('#consent-decisons').hide(); - $('#loadingMessage').hide(); - $('#no-consent-decisions').show(); - } else { - $('#loadingMessage').hide(); - $('#no-consent-decisions').hide(); - $('#consent-decisons').show(); - } - }, - 'language': strings.data, - 'paging': false, - 'ajax': { - 'url': urls.getConsentDecisions, - 'dataSrc': '' - }, - 'data': consentDecisions, - 'columnDefs': [ - { - 'targets': 0, - 'className': 'created-date', - 'data': function (row) { - return date(row.decision.createdDate); - }, - 'render': function (data) { - var opts = { year: 'numeric', month: 'numeric' }; - return '<div class="label label-primary"><span class="hidden">' + data.toISOString() + - '</span>' + data.toLocaleDateString('en', opts ) + - '</div>'; - } - }, - { - 'targets': 1, - 'data': 'decision.service', - 'className': 'col service-id', - 'render': function (data) { - if ($(window).width() <= 855) { - return data.length > 70 ? - '<span title="' + data + '">' + data.substr(0, 68) + '...</span>' : data; - } else { - return data.length > 180 ? - '<span title="' + data + '">' + data.substr(0, 178) + '...</span>' : data; - } - } - } - ] - }); - }; - - var addEventHandlers = function () { - - /* Performs logout for consent application, no SLO */ - $('#logout').click(function() { - var logout = window.location + '/logout'; - window.location.assign(logout); - }); - - // Add event listener for opening and closing details - $(document).on('click', '#consentDecisions > tbody > tr:not(.info)', function () { - var table = $('#consentDecisions').DataTable(); - var tr = $(this); - var row = table.row(tr); - - if (row.child.isShown()) { - // This row is already open - close it - row.child.hide(); - tr.removeClass('shown'); - } - else { - // Open this row - row.child(format(row.data()), 'info').show(); - tr.addClass('shown'); - } - }); - }; - // initialization ******* - (function init() { - createDataTable(); - addEventHandlers(); - })(); - - // Public Methods - return { - /** - * Not used - */ - }; -})(); diff --git a/cas/cas-server/src/main/resources/static/js/loggingDashboard.js b/cas/cas-server/src/main/resources/static/js/loggingDashboard.js deleted file mode 100644 index 4f4416bf..00000000 --- a/cas/cas-server/src/main/resources/static/js/loggingDashboard.js +++ /dev/null @@ -1,342 +0,0 @@ -/* global logConfigFileLocation, SockJS, Stomp */ -var stompClient = null; - -function setConnected(connected) { - - var el = document.getElementById('websocketStatus'); - el.style.visibility = connected ? 'visible' : 'hidden'; - el.class = connected ? 'alert alert-info' : 'alert alert-danger'; - - if (!connected) { - el.innerHTML = 'Disconnected!'; - } else { - el.innerHTML = 'Connected to CAS. Streaming and tailing logs based on <kbd>[' + logConfigFileLocation + ']</kbd>...'; - } -} - -function connect() { - $('#logoutputarea').empty(); - var socket = new SockJS(urls.reportsWebsocket); - stompClient = Stomp.over(socket); - stompClient.connect({}, function () { - setConnected(true); - stompClient.subscribe('/topic/logs', function (msg) { - if (msg != null && msg.body != '') { - showLogs(msg.body); - } - }); - }); -} - -function disconnect() { - $('#logoutputarea').empty(); - $('#logoutputarea').attr('readonly', 'readonly'); - - if (stompClient != null) { - stompClient.disconnect(); - } - setConnected(false); -} - -function showLogs(message) { - if (message != '') { - $('#logoutputarea').val($('#logoutputarea').val() + '\n' + message); - $('#logoutputarea').scrollTop(document.getElementById('logoutputarea').scrollHeight); - } -} - -disconnect(); -connect(); -setInterval(function () { -}, 100); - -/************* - * - ***************/ -$('#myTabs a').click(function (e) { - e.preventDefault(); - $(this).tab('show'); -}); - -var alertHandler = (function () { - var alertContainer = $('#alert-container'); - var create = function (message, state) { - //console.log('create the alert'); - alertContainer.html('<div class="alert alert-' + state + ' alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><span>' + message + '</span></div>'); - - alertContainer.delay(2000).fadeOut('slow'); - }; - - var destroy = function () { - alertContainer.empty(); - }; - - return { - dismiss: function () { - destroy(); - }, - show: function (msg, state) { - create(msg, state); - } - }; -})(); - -var loggingDashboard = (function () { - var json = null; - - var logLevels = ['trace', 'debug', 'info', 'warn', 'error']; - - var getData = function () { - $.getJSON(urls.getConfiguration, function (data) { - json = data; - loggerTable(); - }); - }; - - var getAuditData = function () { - $.getJSON(urls.getAuditLog, function (data) { - if ($(data).length > 0) { - loggerTableAudit(data); - } else { - $('#auditLogTable').DataTable(); - } - }); - }; - - var loggerTableAudit = function (jsonData) { - var t = $('#auditLogTable').DataTable({ - 'autoWidth': false, - 'order': [[3, 'desc']], - retrieve: true, - columnDefs: [ - - {'width': '5%', 'targets': 0}, - {'width': '100%', 'targets': 1}, - { - 'targets': 2, - render: function (data) { - var dd = data.toLowerCase(); - if (dd.indexOf('created') != -1) { - return '<span class="glyphicon glyphicon-plus" aria-hidden="true"> </span>' + data; - } - if (dd.indexOf('validated') != -1) { - return '<span class="glyphicon glyphicon-ok" aria-hidden="true"> </span>' + data; - } - if (dd.indexOf('destroyed') != -1 || dd.indexOf('deleted') != -1) { - return '<span class="glyphicon glyphicon-minus" aria-hidden="true"> </span>' + data; - } - - if (dd.indexOf('success') != -1) { - return '<span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"> </span>' + data; - } - if (dd.indexOf('failed') != -1) { - return '<span class="glyphicon glyphicon-thumbs-down" aria-hidden="true"> </span>' + data; - } - - return data; - } - } - ] - }); - for (var i = 0; i < jsonData.length; i++) { - var rec = jsonData[i]; - t.row.add([ - rec.principal, - rec.resourceOperatedUpon, - rec.actionPerformed, - new Date(rec.whenActionWasPerformed), - rec.clientIpAddress, - rec.serverIpAddress - ]).draw(false); - } - }; - - var loggerTable = function () { - $('#loggersTable').DataTable({ - 'autoWidth': false, - 'order': [[1, 'desc']], - data: json.loggers, - 'drawCallback': function () { - var api = this.api(); - - if (api.page.info().pages > 1) { - $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'block'; - } else { - $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'none'; - } - }, - 'initComplete': function (settings) { - if (!settings.aoData || settings.aoData.length == 0) { - $('#loadingMessage').addClass('d-none'); - $('#errorLoadingData').removeClass('d-none'); - } else { - $('#loadingMessage').addClass('d-none'); - $('#errorLoadingData').addClass('d-none'); - $('#loggingDashboard .tabsContainer').removeClass('d-none'); - } - }, - 'processing': true, - columnDefs: [ - { - 'targets': 0, - 'className': 'details-control', - 'orderable': false, - 'data': 'appenders', - 'defaultContent': '', - render: function (data) { - if (data.length > 0) { - return '<span></span>'; - } else { - return ''; - } - } - }, - { - targets: 1, - data: 'name', - className: 'col-xs-5' - }, - { - targets: 2, - data: 'additive', - className: 'additive col-xs-2', - render: function (data) { - if (data) { - return '<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>'; - } else { - return '<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>'; - - } - } - }, - { - targets: 3, - data: 'state', - className: 'col-xs-2' - }, - { - targets: 4, - data: 'level', - className: 'col-xs-3', - render: function (data, type, full, meta) { - return toggleSwitch(data, type, full, meta); - } - } - ] - }); - }; - - var toggleSwitch = function (data, type, full) { - // Todo: Add additional colors for the other options - //console.log('toggleSwitch data',data); - //console.log('type',type); - //console.log('full',full); - //console.log('meta',meta); - //console.log(logLevels); - var btnColor; - - switch (data.toLowerCase()) { - case 'error': - btnColor = 'danger'; - break; - case 'info': - btnColor = 'info'; - break; - case 'warn': - btnColor = 'warning'; - break; - default: - btnColor = 'default'; - } - var btnGroup = '<div class="btn-group btn-block" data-logger="' + full + '"><button class="btn btn-sm btn-block bg-' + btnColor + ' dropdown-toggle" name="recordinput" data-toggle="dropdown">' + data + ' <span class="caret"></span></button>' + - '<ul class="dropdown-menu">'; - for (var i = 0; i < logLevels.length; i++) { - btnGroup += '<li><a href="#">' + logLevels[i].toUpperCase() + '</a></li>'; - } - btnGroup += '</ul></div>'; - - return btnGroup; - }; - - /* Formatting function for row details - modify as you need */ - var viewAppenders = function (data) { - return '<table class="table table-bordered row-detail"><tbody><tr class="">' + - '<td class="field-label active">Appenders:</td>' + - '<td><kbd>' + JSON.stringify(data.appenders, null, 2) + '</kbd></td>' + - '</tr>' + - '</tbody></table>'; - }; - - var addEventHandlers = function () { - //console.log('addEventHAndlers()'); - - $(document).on('click', '#loggersTable .dropdown-menu li a', function (e) { - //console.log('status change', this); - e.preventDefault(); - var selText = $(this).text(); - - changeLogLevel(selText, this); - }); - - $(document).on('click', '#loggersTable tbody td.details-control span', function () { - var table = $('#loggersTable').DataTable(); - var tr = $(this).closest('tr'); - var row = table.row(tr); - - if (row.child.isShown()) { - // This row is already open - close it - row.child.hide(); - tr.removeClass('shown'); - } else { - // Open this row - row.child(viewAppenders(row.data()), 'info').show(); - tr.addClass('shown'); - } - }); - }; - - var changeLogLevel = function (newLevel, el) { - /** - * POST - /cas/status/logging/updateLoggerLevel - * Allows you to change the log level for given LOGGER. Parameters are: - * loggerName, loggerLevel, additive (true/false) - */ - var table = $('#loggersTable').DataTable(); - var data = table.row($(el).closest('tr')[0]).data(); - - if (newLevel != data.level) { - var cell = table.cell($(el).closest('td')[0]); - - $.post(urls.updateLevel, { - loggerName: data.name, - loggerLevel: newLevel, - additive: data.additive - }, function () { - cell.data(newLevel).draw(); - alertHandler.show('Successfully changed.', 'success'); - }).fail(function () { - alertHandler.show('Error saving change. Please try again', 'danger'); - }); - } - }; - - // initialization ******* - (function init() { - })(); - - return { - init: function () { - getData(); - addEventHandlers(); - getAuditData(); - }, - getJson: function () { - return json; - }, - showLoggersTable: function () { - loggerTable(); - } - }; -})(); - -loggingDashboard.init(); diff --git a/cas/cas-server/src/main/resources/static/js/passwordMeter.js b/cas/cas-server/src/main/resources/static/js/passwordMeter.js index b468c31b..df90defa 100644 --- a/cas/cas-server/src/main/resources/static/js/passwordMeter.js +++ b/cas/cas-server/src/main/resources/static/js/passwordMeter.js @@ -1,13 +1,7 @@ -/* global jqueryReady, policyPattern, zxcvbn */ +/* global jqueryReady, policyPattern, zxcvbn, passwordStrengthI18n */ /*eslint-disable no-unused-vars*/ function jqueryReady() { - var strength = { - 0: 'Worst', - 1: 'Bad', - 2: 'Weak', - 3: 'Good', - 4: 'Strong' - }; + var strength = passwordStrengthI18n; $.fn.zxcvbnProgressBar = function (options) { @@ -77,10 +71,17 @@ function jqueryReady() { var password = document.getElementById('password'); var confirmed = document.getElementById('confirmedPassword'); - password.addEventListener('input', validate); confirmed.addEventListener('input', validate); + var alertSettings = { + allAlertClasses: 'fa-times-circle fa-exclamation-circle fa-info-circle fa-check-circle', + alertClassDanger: 'fa-times-circle', + alertClassWarning: 'fa-exclamation-circle', + alertClassInfo: 'fa-info-circle', + alertClassSuccess: 'fa-check-circle' + }; + function validate() { var val = password.value; var cnf = confirmed.value; @@ -101,28 +102,28 @@ function jqueryReady() { return; } - // Update the text indicator + // Check strength, update the text indicator if (val !== '') { $('#password-strength-text').show(); var title = 'Strength: <strong>' + strength[result.score] + '</strong>'; var text = '<p><span class=\'feedback\'>' + result.feedback.warning + ' ' + result.feedback.suggestions + '</span></p>'; - var clz = 'danger'; + var clz = alertSettings.alertClassDanger; switch (result.score) { case 0: case 1: - clz = 'danger'; + clz = alertSettings.alertClassDanger; break; case 2: - clz = 'warning'; + clz = alertSettings.alertClassWarning; break; case 3: - clz = 'info'; + clz = alertSettings.alertClassInfo; break; case 4: case 5: default: - clz = 'success'; + clz = alertSettings.alertClassSuccess; break; } responseText = '<div class=\'alert alert-' + clz + '\'>' + title + text + '</div>'; diff --git a/cas/cas-server/src/main/resources/static/js/sockjs.js b/cas/cas-server/src/main/resources/static/js/sockjs.js deleted file mode 100644 index 21145b75..00000000 --- a/cas/cas-server/src/main/resources/static/js/sockjs.js +++ /dev/null @@ -1,2378 +0,0 @@ -/* SockJS client, version 0.3.4, http://sockjs.org, MIT License - -Copyright (c) 2011-2012 VMware, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -// JSON2 by Douglas Crockford (minified). -var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g;return e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver=="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")})}() - - -// [*] Including lib/index.js -// Public object -SockJS = (function(){ - var _document = document; - var _window = window; - var utils = {}; - - -// [*] Including lib/reventtarget.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -/* Simplified implementation of DOM2 EventTarget. - * http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget - */ -var REventTarget = function() {}; -REventTarget.prototype.addEventListener = function (eventType, listener) { - if(!this._listeners) { - this._listeners = {}; - } - if(!(eventType in this._listeners)) { - this._listeners[eventType] = []; - } - var arr = this._listeners[eventType]; - if(utils.arrIndexOf(arr, listener) === -1) { - arr.push(listener); - } - return; -}; - -REventTarget.prototype.removeEventListener = function (eventType, listener) { - if(!(this._listeners && (eventType in this._listeners))) { - return; - } - var arr = this._listeners[eventType]; - var idx = utils.arrIndexOf(arr, listener); - if (idx !== -1) { - if(arr.length > 1) { - this._listeners[eventType] = arr.slice(0, idx).concat( arr.slice(idx+1) ); - } else { - delete this._listeners[eventType]; - } - return; - } - return; -}; - -REventTarget.prototype.dispatchEvent = function (event) { - var t = event.type; - var args = Array.prototype.slice.call(arguments, 0); - if (this['on'+t]) { - this['on'+t].apply(this, args); - } - if (this._listeners && t in this._listeners) { - for(var i=0; i < this._listeners[t].length; i++) { - this._listeners[t][i].apply(this, args); - } - } -}; -// [*] End of lib/reventtarget.js - - -// [*] Including lib/simpleevent.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var SimpleEvent = function(type, obj) { - this.type = type; - if (typeof obj !== 'undefined') { - for(var k in obj) { - if (!obj.hasOwnProperty(k)) continue; - this[k] = obj[k]; - } - } -}; - -SimpleEvent.prototype.toString = function() { - var r = []; - for(var k in this) { - if (!this.hasOwnProperty(k)) continue; - var v = this[k]; - if (typeof v === 'function') v = '[function]'; - r.push(k + '=' + v); - } - return 'SimpleEvent(' + r.join(', ') + ')'; -}; -// [*] End of lib/simpleevent.js - - -// [*] Including lib/eventemitter.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var EventEmitter = function(events) { - var that = this; - that._events = events || []; - that._listeners = {}; -}; -EventEmitter.prototype.emit = function(type) { - var that = this; - that._verifyType(type); - if (that._nuked) return; - - var args = Array.prototype.slice.call(arguments, 1); - if (that['on'+type]) { - that['on'+type].apply(that, args); - } - if (type in that._listeners) { - for(var i = 0; i < that._listeners[type].length; i++) { - that._listeners[type][i].apply(that, args); - } - } -}; - -EventEmitter.prototype.on = function(type, callback) { - var that = this; - that._verifyType(type); - if (that._nuked) return; - - if (!(type in that._listeners)) { - that._listeners[type] = []; - } - that._listeners[type].push(callback); -}; - -EventEmitter.prototype._verifyType = function(type) { - var that = this; - if (utils.arrIndexOf(that._events, type) === -1) { - utils.log('Event ' + JSON.stringify(type) + - ' not listed ' + JSON.stringify(that._events) + - ' in ' + that); - } -}; - -EventEmitter.prototype.nuke = function() { - var that = this; - that._nuked = true; - for(var i=0; i<that._events.length; i++) { - delete that[that._events[i]]; - } - that._listeners = {}; -}; -// [*] End of lib/eventemitter.js - - -// [*] Including lib/utils.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var random_string_chars = 'abcdefghijklmnopqrstuvwxyz0123456789_'; -utils.random_string = function(length, max) { - max = max || random_string_chars.length; - var i, ret = []; - for(i=0; i < length; i++) { - ret.push( random_string_chars.substr(Math.floor(Math.random() * max),1) ); - } - return ret.join(''); -}; -utils.random_number = function(max) { - return Math.floor(Math.random() * max); -}; -utils.random_number_string = function(max) { - var t = (''+(max - 1)).length; - var p = Array(t+1).join('0'); - return (p + utils.random_number(max)).slice(-t); -}; - -// Assuming that url looks like: http://asdasd:111/asd -utils.getOrigin = function(url) { - url += '/'; - var parts = url.split('/').slice(0, 3); - return parts.join('/'); -}; - -utils.isSameOriginUrl = function(url_a, url_b) { - // location.origin would do, but it's not always available. - if (!url_b) url_b = _window.location.href; - - return (url_a.split('/').slice(0,3).join('/') - === - url_b.split('/').slice(0,3).join('/')); -}; - -utils.getParentDomain = function(url) { - // ipv4 ip address - if (/^[0-9.]*$/.test(url)) return url; - // ipv6 ip address - if (/^\[/.test(url)) return url; - // no dots - if (!(/[.]/.test(url))) return url; - - var parts = url.split('.').slice(1); - return parts.join('.'); -}; - -utils.objectExtend = function(dst, src) { - for(var k in src) { - if (src.hasOwnProperty(k)) { - dst[k] = src[k]; - } - } - return dst; -}; - -var WPrefix = '_jp'; - -utils.polluteGlobalNamespace = function() { - if (!(WPrefix in _window)) { - _window[WPrefix] = {}; - } -}; - -utils.closeFrame = function (code, reason) { - return 'c'+JSON.stringify([code, reason]); -}; - -utils.userSetCode = function (code) { - return code === 1000 || (code >= 3000 && code <= 4999); -}; - -// See: http://www.erg.abdn.ac.uk/~gerrit/dccp/notes/ccid2/rto_estimator/ -// and RFC 2988. -utils.countRTO = function (rtt) { - var rto; - if (rtt > 100) { - rto = 3 * rtt; // rto > 300msec - } else { - rto = rtt + 200; // 200msec < rto <= 300msec - } - return rto; -} - -utils.log = function() { - if (_window.console && console.log && console.log.apply) { - console.log.apply(console, arguments); - } -}; - -utils.bind = function(fun, that) { - if (fun.bind) { - return fun.bind(that); - } else { - return function() { - return fun.apply(that, arguments); - }; - } -}; - -utils.flatUrl = function(url) { - return url.indexOf('?') === -1 && url.indexOf('#') === -1; -}; - -utils.amendUrl = function(url) { - var dl = _document.location; - if (!url) { - throw new Error('Wrong url for SockJS'); - } - if (!utils.flatUrl(url)) { - throw new Error('Only basic urls are supported in SockJS'); - } - - // '//abc' --> 'http://abc' - if (url.indexOf('//') === 0) { - url = dl.protocol + url; - } - // '/abc' --> 'http://localhost:80/abc' - if (url.indexOf('/') === 0) { - url = dl.protocol + '//' + dl.host + url; - } - // strip trailing slashes - url = url.replace(/[/]+$/,''); - return url; -}; - -// IE doesn't support [].indexOf. -utils.arrIndexOf = function(arr, obj){ - for(var i=0; i < arr.length; i++){ - if(arr[i] === obj){ - return i; - } - } - return -1; -}; - -utils.arrSkip = function(arr, obj) { - var idx = utils.arrIndexOf(arr, obj); - if (idx === -1) { - return arr.slice(); - } else { - var dst = arr.slice(0, idx); - return dst.concat(arr.slice(idx+1)); - } -}; - -// Via: https://gist.github.com/1133122/2121c601c5549155483f50be3da5305e83b8c5df -utils.isArray = Array.isArray || function(value) { - return {}.toString.call(value).indexOf('Array') >= 0 -}; - -utils.delay = function(t, fun) { - if(typeof t === 'function') { - fun = t; - t = 0; - } - return setTimeout(fun, t); -}; - - -// Chars worth escaping, as defined by Douglas Crockford: -// https://github.com/douglascrockford/JSON-js/blob/47a9882cddeb1e8529e07af9736218075372b8ac/json2.js#L196 -var json_escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - json_lookup = { -"\u0000":"\\u0000","\u0001":"\\u0001","\u0002":"\\u0002","\u0003":"\\u0003", -"\u0004":"\\u0004","\u0005":"\\u0005","\u0006":"\\u0006","\u0007":"\\u0007", -"\b":"\\b","\t":"\\t","\n":"\\n","\u000b":"\\u000b","\f":"\\f","\r":"\\r", -"\u000e":"\\u000e","\u000f":"\\u000f","\u0010":"\\u0010","\u0011":"\\u0011", -"\u0012":"\\u0012","\u0013":"\\u0013","\u0014":"\\u0014","\u0015":"\\u0015", -"\u0016":"\\u0016","\u0017":"\\u0017","\u0018":"\\u0018","\u0019":"\\u0019", -"\u001a":"\\u001a","\u001b":"\\u001b","\u001c":"\\u001c","\u001d":"\\u001d", -"\u001e":"\\u001e","\u001f":"\\u001f","\"":"\\\"","\\":"\\\\", -"\u007f":"\\u007f","\u0080":"\\u0080","\u0081":"\\u0081","\u0082":"\\u0082", -"\u0083":"\\u0083","\u0084":"\\u0084","\u0085":"\\u0085","\u0086":"\\u0086", -"\u0087":"\\u0087","\u0088":"\\u0088","\u0089":"\\u0089","\u008a":"\\u008a", -"\u008b":"\\u008b","\u008c":"\\u008c","\u008d":"\\u008d","\u008e":"\\u008e", -"\u008f":"\\u008f","\u0090":"\\u0090","\u0091":"\\u0091","\u0092":"\\u0092", -"\u0093":"\\u0093","\u0094":"\\u0094","\u0095":"\\u0095","\u0096":"\\u0096", -"\u0097":"\\u0097","\u0098":"\\u0098","\u0099":"\\u0099","\u009a":"\\u009a", -"\u009b":"\\u009b","\u009c":"\\u009c","\u009d":"\\u009d","\u009e":"\\u009e", -"\u009f":"\\u009f","\u00ad":"\\u00ad","\u0600":"\\u0600","\u0601":"\\u0601", -"\u0602":"\\u0602","\u0603":"\\u0603","\u0604":"\\u0604","\u070f":"\\u070f", -"\u17b4":"\\u17b4","\u17b5":"\\u17b5","\u200c":"\\u200c","\u200d":"\\u200d", -"\u200e":"\\u200e","\u200f":"\\u200f","\u2028":"\\u2028","\u2029":"\\u2029", -"\u202a":"\\u202a","\u202b":"\\u202b","\u202c":"\\u202c","\u202d":"\\u202d", -"\u202e":"\\u202e","\u202f":"\\u202f","\u2060":"\\u2060","\u2061":"\\u2061", -"\u2062":"\\u2062","\u2063":"\\u2063","\u2064":"\\u2064","\u2065":"\\u2065", -"\u2066":"\\u2066","\u2067":"\\u2067","\u2068":"\\u2068","\u2069":"\\u2069", -"\u206a":"\\u206a","\u206b":"\\u206b","\u206c":"\\u206c","\u206d":"\\u206d", -"\u206e":"\\u206e","\u206f":"\\u206f","\ufeff":"\\ufeff","\ufff0":"\\ufff0", -"\ufff1":"\\ufff1","\ufff2":"\\ufff2","\ufff3":"\\ufff3","\ufff4":"\\ufff4", -"\ufff5":"\\ufff5","\ufff6":"\\ufff6","\ufff7":"\\ufff7","\ufff8":"\\ufff8", -"\ufff9":"\\ufff9","\ufffa":"\\ufffa","\ufffb":"\\ufffb","\ufffc":"\\ufffc", -"\ufffd":"\\ufffd","\ufffe":"\\ufffe","\uffff":"\\uffff"}; - -// Some extra characters that Chrome gets wrong, and substitutes with -// something else on the wire. -var extra_escapable = /[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g, - extra_lookup; - -// JSON Quote string. Use native implementation when possible. -var JSONQuote = (JSON && JSON.stringify) || function(string) { - json_escapable.lastIndex = 0; - if (json_escapable.test(string)) { - string = string.replace(json_escapable, function(a) { - return json_lookup[a]; - }); - } - return '"' + string + '"'; -}; - -// This may be quite slow, so let's delay until user actually uses bad -// characters. -var unroll_lookup = function(escapable) { - var i; - var unrolled = {} - var c = [] - for(i=0; i<65536; i++) { - c.push( String.fromCharCode(i) ); - } - escapable.lastIndex = 0; - c.join('').replace(escapable, function (a) { - unrolled[ a ] = '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - return ''; - }); - escapable.lastIndex = 0; - return unrolled; -}; - -// Quote string, also taking care of unicode characters that browsers -// often break. Especially, take care of unicode surrogates: -// http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates -utils.quote = function(string) { - var quoted = JSONQuote(string); - - // In most cases this should be very fast and good enough. - extra_escapable.lastIndex = 0; - if(!extra_escapable.test(quoted)) { - return quoted; - } - - if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable); - - return quoted.replace(extra_escapable, function(a) { - return extra_lookup[a]; - }); -} - -var _all_protocols = ['websocket', - 'xdr-streaming', - 'xhr-streaming', - 'iframe-eventsource', - 'iframe-htmlfile', - 'xdr-polling', - 'xhr-polling', - 'iframe-xhr-polling', - 'jsonp-polling']; - -utils.probeProtocols = function() { - var probed = {}; - for(var i=0; i<_all_protocols.length; i++) { - var protocol = _all_protocols[i]; - // User can have a typo in protocol name. - probed[protocol] = SockJS[protocol] && - SockJS[protocol].enabled(); - } - return probed; -}; - -utils.detectProtocols = function(probed, protocols_whitelist, info) { - var pe = {}, - protocols = []; - if (!protocols_whitelist) protocols_whitelist = _all_protocols; - for(var i=0; i<protocols_whitelist.length; i++) { - var protocol = protocols_whitelist[i]; - pe[protocol] = probed[protocol]; - } - var maybe_push = function(protos) { - var proto = protos.shift(); - if (pe[proto]) { - protocols.push(proto); - } else { - if (protos.length > 0) { - maybe_push(protos); - } - } - } - - // 1. Websocket - if (info.websocket !== false) { - maybe_push(['websocket']); - } - - // 2. Streaming - if (pe['xhr-streaming'] && !info.null_origin) { - protocols.push('xhr-streaming'); - } else { - if (pe['xdr-streaming'] && !info.cookie_needed && !info.null_origin) { - protocols.push('xdr-streaming'); - } else { - maybe_push(['iframe-eventsource', - 'iframe-htmlfile']); - } - } - - // 3. Polling - if (pe['xhr-polling'] && !info.null_origin) { - protocols.push('xhr-polling'); - } else { - if (pe['xdr-polling'] && !info.cookie_needed && !info.null_origin) { - protocols.push('xdr-polling'); - } else { - maybe_push(['iframe-xhr-polling', - 'jsonp-polling']); - } - } - return protocols; -} -// [*] End of lib/utils.js - - -// [*] Including lib/dom.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -// May be used by htmlfile jsonp and transports. -var MPrefix = '_sockjs_global'; -utils.createHook = function() { - var window_id = 'a' + utils.random_string(8); - if (!(MPrefix in _window)) { - var map = {}; - _window[MPrefix] = function(window_id) { - if (!(window_id in map)) { - map[window_id] = { - id: window_id, - del: function() {delete map[window_id];} - }; - } - return map[window_id]; - } - } - return _window[MPrefix](window_id); -}; - - - -utils.attachMessage = function(listener) { - utils.attachEvent('message', listener); -}; -utils.attachEvent = function(event, listener) { - if (typeof _window.addEventListener !== 'undefined') { - _window.addEventListener(event, listener, false); - } else { - // IE quirks. - // According to: http://stevesouders.com/misc/test-postmessage.php - // the message gets delivered only to 'document', not 'window'. - _document.attachEvent("on" + event, listener); - // I get 'window' for ie8. - _window.attachEvent("on" + event, listener); - } -}; - -utils.detachMessage = function(listener) { - utils.detachEvent('message', listener); -}; -utils.detachEvent = function(event, listener) { - if (typeof _window.addEventListener !== 'undefined') { - _window.removeEventListener(event, listener, false); - } else { - _document.detachEvent("on" + event, listener); - _window.detachEvent("on" + event, listener); - } -}; - - -var on_unload = {}; -// Things registered after beforeunload are to be called immediately. -var after_unload = false; - -var trigger_unload_callbacks = function() { - for(var ref in on_unload) { - on_unload[ref](); - delete on_unload[ref]; - }; -}; - -var unload_triggered = function() { - if(after_unload) return; - after_unload = true; - trigger_unload_callbacks(); -}; - -// 'unload' alone is not reliable in opera within an iframe, but we -// can't use `beforeunload` as IE fires it on javascript: links. -utils.attachEvent('unload', unload_triggered); - -utils.unload_add = function(listener) { - var ref = utils.random_string(8); - on_unload[ref] = listener; - if (after_unload) { - utils.delay(trigger_unload_callbacks); - } - return ref; -}; -utils.unload_del = function(ref) { - if (ref in on_unload) - delete on_unload[ref]; -}; - - -utils.createIframe = function (iframe_url, error_callback) { - var iframe = _document.createElement('iframe'); - var tref, unload_ref; - var unattach = function() { - clearTimeout(tref); - // Explorer had problems with that. - try {iframe.onload = null;} catch (x) {} - iframe.onerror = null; - }; - var cleanup = function() { - if (iframe) { - unattach(); - // This timeout makes chrome fire onbeforeunload event - // within iframe. Without the timeout it goes straight to - // onunload. - setTimeout(function() { - if(iframe) { - iframe.parentNode.removeChild(iframe); - } - iframe = null; - }, 0); - utils.unload_del(unload_ref); - } - }; - var onerror = function(r) { - if (iframe) { - cleanup(); - error_callback(r); - } - }; - var post = function(msg, origin) { - try { - // When the iframe is not loaded, IE raises an exception - // on 'contentWindow'. - if (iframe && iframe.contentWindow) { - iframe.contentWindow.postMessage(msg, origin); - } - } catch (x) {}; - }; - - iframe.src = iframe_url; - iframe.style.display = 'none'; - iframe.style.position = 'absolute'; - iframe.onerror = function(){onerror('onerror');}; - iframe.onload = function() { - // `onload` is triggered before scripts on the iframe are - // executed. Give it few seconds to actually load stuff. - clearTimeout(tref); - tref = setTimeout(function(){onerror('onload timeout');}, 2000); - }; - _document.body.appendChild(iframe); - tref = setTimeout(function(){onerror('timeout');}, 15000); - unload_ref = utils.unload_add(cleanup); - return { - post: post, - cleanup: cleanup, - loaded: unattach - }; -}; - -utils.createHtmlfile = function (iframe_url, error_callback) { - var doc = new ActiveXObject('htmlfile'); - var tref, unload_ref; - var iframe; - var unattach = function() { - clearTimeout(tref); - }; - var cleanup = function() { - if (doc) { - unattach(); - utils.unload_del(unload_ref); - iframe.parentNode.removeChild(iframe); - iframe = doc = null; - CollectGarbage(); - } - }; - var onerror = function(r) { - if (doc) { - cleanup(); - error_callback(r); - } - }; - var post = function(msg, origin) { - try { - // When the iframe is not loaded, IE raises an exception - // on 'contentWindow'. - if (iframe && iframe.contentWindow) { - iframe.contentWindow.postMessage(msg, origin); - } - } catch (x) {}; - }; - - doc.open(); - doc.write('<html><s' + 'cript>' + - 'document.domain="' + document.domain + '";' + - '</s' + 'cript></html>'); - doc.close(); - doc.parentWindow[WPrefix] = _window[WPrefix]; - var c = doc.createElement('div'); - doc.body.appendChild(c); - iframe = doc.createElement('iframe'); - c.appendChild(iframe); - iframe.src = iframe_url; - tref = setTimeout(function(){onerror('timeout');}, 15000); - unload_ref = utils.unload_add(cleanup); - return { - post: post, - cleanup: cleanup, - loaded: unattach - }; -}; -// [*] End of lib/dom.js - - -// [*] Including lib/dom2.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var AbstractXHRObject = function(){}; -AbstractXHRObject.prototype = new EventEmitter(['chunk', 'finish']); - -AbstractXHRObject.prototype._start = function(method, url, payload, opts) { - var that = this; - - try { - that.xhr = new XMLHttpRequest(); - } catch(x) {}; - - if (!that.xhr) { - try { - that.xhr = new _window.ActiveXObject('Microsoft.XMLHTTP'); - } catch(x) {}; - } - if (_window.ActiveXObject || _window.XDomainRequest) { - // IE8 caches even POSTs - url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date); - } - - // Explorer tends to keep connection open, even after the - // tab gets closed: http://bugs.jquery.com/ticket/5280 - that.unload_ref = utils.unload_add(function(){that._cleanup(true);}); - try { - that.xhr.open(method, url, true); - } catch(e) { - // IE raises an exception on wrong port. - that.emit('finish', 0, ''); - that._cleanup(); - return; - }; - - if (!opts || !opts.no_credentials) { - // Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest : - // "This never affects same-site requests." - that.xhr.withCredentials = 'true'; - } - if (opts && opts.headers) { - for(var key in opts.headers) { - that.xhr.setRequestHeader(key, opts.headers[key]); - } - } - - that.xhr.onreadystatechange = function() { - if (that.xhr) { - var x = that.xhr; - switch (x.readyState) { - case 3: - // IE doesn't like peeking into responseText or status - // on Microsoft.XMLHTTP and readystate=3 - try { - var status = x.status; - var text = x.responseText; - } catch (x) {}; - // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450 - if (status === 1223) status = 204; - - // IE does return readystate == 3 for 404 answers. - if (text && text.length > 0) { - that.emit('chunk', status, text); - } - break; - case 4: - var status = x.status; - // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450 - if (status === 1223) status = 204; - - that.emit('finish', status, x.responseText); - that._cleanup(false); - break; - } - } - }; - that.xhr.send(payload); -}; - -AbstractXHRObject.prototype._cleanup = function(abort) { - var that = this; - if (!that.xhr) return; - utils.unload_del(that.unload_ref); - - // IE needs this field to be a function - that.xhr.onreadystatechange = function(){}; - - if (abort) { - try { - that.xhr.abort(); - } catch(x) {}; - } - that.unload_ref = that.xhr = null; -}; - -AbstractXHRObject.prototype.close = function() { - var that = this; - that.nuke(); - that._cleanup(true); -}; - -var XHRCorsObject = utils.XHRCorsObject = function() { - var that = this, args = arguments; - utils.delay(function(){that._start.apply(that, args);}); -}; -XHRCorsObject.prototype = new AbstractXHRObject(); - -var XHRLocalObject = utils.XHRLocalObject = function(method, url, payload) { - var that = this; - utils.delay(function(){ - that._start(method, url, payload, { - no_credentials: true - }); - }); -}; -XHRLocalObject.prototype = new AbstractXHRObject(); - - - -// References: -// http://ajaxian.com/archives/100-line-ajax-wrapper -// http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx -var XDRObject = utils.XDRObject = function(method, url, payload) { - var that = this; - utils.delay(function(){that._start(method, url, payload);}); -}; -XDRObject.prototype = new EventEmitter(['chunk', 'finish']); -XDRObject.prototype._start = function(method, url, payload) { - var that = this; - var xdr = new XDomainRequest(); - // IE caches even POSTs - url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date); - - var onerror = xdr.ontimeout = xdr.onerror = function() { - that.emit('finish', 0, ''); - that._cleanup(false); - }; - xdr.onprogress = function() { - that.emit('chunk', 200, xdr.responseText); - }; - xdr.onload = function() { - that.emit('finish', 200, xdr.responseText); - that._cleanup(false); - }; - that.xdr = xdr; - that.unload_ref = utils.unload_add(function(){that._cleanup(true);}); - try { - // Fails with AccessDenied if port number is bogus - that.xdr.open(method, url); - that.xdr.send(payload); - } catch(x) { - onerror(); - } -}; - -XDRObject.prototype._cleanup = function(abort) { - var that = this; - if (!that.xdr) return; - utils.unload_del(that.unload_ref); - - that.xdr.ontimeout = that.xdr.onerror = that.xdr.onprogress = - that.xdr.onload = null; - if (abort) { - try { - that.xdr.abort(); - } catch(x) {}; - } - that.unload_ref = that.xdr = null; -}; - -XDRObject.prototype.close = function() { - var that = this; - that.nuke(); - that._cleanup(true); -}; - -// 1. Is natively via XHR -// 2. Is natively via XDR -// 3. Nope, but postMessage is there so it should work via the Iframe. -// 4. Nope, sorry. -utils.isXHRCorsCapable = function() { - if (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) { - return 1; - } - // XDomainRequest doesn't work if page is served from file:// - if (_window.XDomainRequest && _document.domain) { - return 2; - } - if (IframeTransport.enabled()) { - return 3; - } - return 4; -}; -// [*] End of lib/dom2.js - - -// [*] Including lib/sockjs.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var SockJS = function(url, dep_protocols_whitelist, options) { - if (this === _window) { - // makes `new` optional - return new SockJS(url, dep_protocols_whitelist, options); - } - - var that = this, protocols_whitelist; - that._options = {devel: false, debug: false, protocols_whitelist: [], - info: undefined, rtt: undefined}; - if (options) { - utils.objectExtend(that._options, options); - } - that._base_url = utils.amendUrl(url); - that._server = that._options.server || utils.random_number_string(1000); - if (that._options.protocols_whitelist && - that._options.protocols_whitelist.length) { - protocols_whitelist = that._options.protocols_whitelist; - } else { - // Deprecated API - if (typeof dep_protocols_whitelist === 'string' && - dep_protocols_whitelist.length > 0) { - protocols_whitelist = [dep_protocols_whitelist]; - } else if (utils.isArray(dep_protocols_whitelist)) { - protocols_whitelist = dep_protocols_whitelist - } else { - protocols_whitelist = null; - } - if (protocols_whitelist) { - that._debug('Deprecated API: Use "protocols_whitelist" option ' + - 'instead of supplying protocol list as a second ' + - 'parameter to SockJS constructor.'); - } - } - that._protocols = []; - that.protocol = null; - that.readyState = SockJS.CONNECTING; - that._ir = createInfoReceiver(that._base_url); - that._ir.onfinish = function(info, rtt) { - that._ir = null; - if (info) { - if (that._options.info) { - // Override if user supplies the option - info = utils.objectExtend(info, that._options.info); - } - if (that._options.rtt) { - rtt = that._options.rtt; - } - that._applyInfo(info, rtt, protocols_whitelist); - that._didClose(); - } else { - that._didClose(1002, 'Can\'t connect to server', true); - } - }; -}; -// Inheritance -SockJS.prototype = new REventTarget(); - -SockJS.version = "0.3.4"; - -SockJS.CONNECTING = 0; -SockJS.OPEN = 1; -SockJS.CLOSING = 2; -SockJS.CLOSED = 3; - -SockJS.prototype._debug = function() { - if (this._options.debug) - utils.log.apply(utils, arguments); -}; - -SockJS.prototype._dispatchOpen = function() { - var that = this; - if (that.readyState === SockJS.CONNECTING) { - if (that._transport_tref) { - clearTimeout(that._transport_tref); - that._transport_tref = null; - } - that.readyState = SockJS.OPEN; - that.dispatchEvent(new SimpleEvent("open")); - } else { - // The server might have been restarted, and lost track of our - // connection. - that._didClose(1006, "Server lost session"); - } -}; - -SockJS.prototype._dispatchMessage = function(data) { - var that = this; - if (that.readyState !== SockJS.OPEN) - return; - that.dispatchEvent(new SimpleEvent("message", {data: data})); -}; - -SockJS.prototype._dispatchHeartbeat = function(data) { - var that = this; - if (that.readyState !== SockJS.OPEN) - return; - that.dispatchEvent(new SimpleEvent('heartbeat', {})); -}; - -SockJS.prototype._didClose = function(code, reason, force) { - var that = this; - if (that.readyState !== SockJS.CONNECTING && - that.readyState !== SockJS.OPEN && - that.readyState !== SockJS.CLOSING) - throw new Error('INVALID_STATE_ERR'); - if (that._ir) { - that._ir.nuke(); - that._ir = null; - } - - if (that._transport) { - that._transport.doCleanup(); - that._transport = null; - } - - var close_event = new SimpleEvent("close", { - code: code, - reason: reason, - wasClean: utils.userSetCode(code)}); - - if (!utils.userSetCode(code) && - that.readyState === SockJS.CONNECTING && !force) { - if (that._try_next_protocol(close_event)) { - return; - } - close_event = new SimpleEvent("close", {code: 2000, - reason: "All transports failed", - wasClean: false, - last_event: close_event}); - } - that.readyState = SockJS.CLOSED; - - utils.delay(function() { - that.dispatchEvent(close_event); - }); -}; - -SockJS.prototype._didMessage = function(data) { - var that = this; - var type = data.slice(0, 1); - switch(type) { - case 'o': - that._dispatchOpen(); - break; - case 'a': - var payload = JSON.parse(data.slice(1) || '[]'); - for(var i=0; i < payload.length; i++){ - that._dispatchMessage(payload[i]); - } - break; - case 'm': - var payload = JSON.parse(data.slice(1) || 'null'); - that._dispatchMessage(payload); - break; - case 'c': - var payload = JSON.parse(data.slice(1) || '[]'); - that._didClose(payload[0], payload[1]); - break; - case 'h': - that._dispatchHeartbeat(); - break; - } -}; - -SockJS.prototype._try_next_protocol = function(close_event) { - var that = this; - if (that.protocol) { - that._debug('Closed transport:', that.protocol, ''+close_event); - that.protocol = null; - } - if (that._transport_tref) { - clearTimeout(that._transport_tref); - that._transport_tref = null; - } - - while(1) { - var protocol = that.protocol = that._protocols.shift(); - if (!protocol) { - return false; - } - // Some protocols require access to `body`, what if were in - // the `head`? - if (SockJS[protocol] && - SockJS[protocol].need_body === true && - (!_document.body || - (typeof _document.readyState !== 'undefined' - && _document.readyState !== 'complete'))) { - that._protocols.unshift(protocol); - that.protocol = 'waiting-for-load'; - utils.attachEvent('load', function(){ - that._try_next_protocol(); - }); - return true; - } - - if (!SockJS[protocol] || - !SockJS[protocol].enabled(that._options)) { - that._debug('Skipping transport:', protocol); - } else { - var roundTrips = SockJS[protocol].roundTrips || 1; - var to = ((that._options.rto || 0) * roundTrips) || 5000; - that._transport_tref = utils.delay(to, function() { - if (that.readyState === SockJS.CONNECTING) { - // I can't understand how it is possible to run - // this timer, when the state is CLOSED, but - // apparently in IE everythin is possible. - that._didClose(2007, "Transport timeouted"); - } - }); - - var connid = utils.random_string(8); - var trans_url = that._base_url + '/' + that._server + '/' + connid; - that._debug('Opening transport:', protocol, ' url:'+trans_url, - ' RTO:'+that._options.rto); - that._transport = new SockJS[protocol](that, trans_url, - that._base_url); - return true; - } - } -}; - -SockJS.prototype.close = function(code, reason) { - var that = this; - if (code && !utils.userSetCode(code)) - throw new Error("INVALID_ACCESS_ERR"); - if(that.readyState !== SockJS.CONNECTING && - that.readyState !== SockJS.OPEN) { - return false; - } - that.readyState = SockJS.CLOSING; - that._didClose(code || 1000, reason || "Normal closure"); - return true; -}; - -SockJS.prototype.send = function(data) { - var that = this; - if (that.readyState === SockJS.CONNECTING) - throw new Error('INVALID_STATE_ERR'); - if (that.readyState === SockJS.OPEN) { - that._transport.doSend(utils.quote('' + data)); - } - return true; -}; - -SockJS.prototype._applyInfo = function(info, rtt, protocols_whitelist) { - var that = this; - that._options.info = info; - that._options.rtt = rtt; - that._options.rto = utils.countRTO(rtt); - that._options.info.null_origin = !_document.domain; - var probed = utils.probeProtocols(); - that._protocols = utils.detectProtocols(probed, protocols_whitelist, info); -}; -// [*] End of lib/sockjs.js - - -// [*] Including lib/trans-websocket.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var WebSocketTransport = SockJS.websocket = function(ri, trans_url) { - var that = this; - var url = trans_url + '/websocket'; - if (url.slice(0, 5) === 'https') { - url = 'wss' + url.slice(5); - } else { - url = 'ws' + url.slice(4); - } - that.ri = ri; - that.url = url; - var Constructor = _window.WebSocket || _window.MozWebSocket; - - that.ws = new Constructor(that.url); - that.ws.onmessage = function(e) { - that.ri._didMessage(e.data); - }; - // Firefox has an interesting bug. If a websocket connection is - // created after onunload, it stays alive even when user - // navigates away from the page. In such situation let's lie - - // let's not open the ws connection at all. See: - // https://github.com/sockjs/sockjs-client/issues/28 - // https://bugzilla.mozilla.org/show_bug.cgi?id=696085 - that.unload_ref = utils.unload_add(function(){that.ws.close()}); - that.ws.onclose = function() { - that.ri._didMessage(utils.closeFrame(1006, "WebSocket connection broken")); - }; -}; - -WebSocketTransport.prototype.doSend = function(data) { - this.ws.send('[' + data + ']'); -}; - -WebSocketTransport.prototype.doCleanup = function() { - var that = this; - var ws = that.ws; - if (ws) { - ws.onmessage = ws.onclose = null; - ws.close(); - utils.unload_del(that.unload_ref); - that.unload_ref = that.ri = that.ws = null; - } -}; - -WebSocketTransport.enabled = function() { - return !!(_window.WebSocket || _window.MozWebSocket); -}; - -// In theory, ws should require 1 round trip. But in chrome, this is -// not very stable over SSL. Most likely a ws connection requires a -// separate SSL connection, in which case 2 round trips are an -// absolute minumum. -WebSocketTransport.roundTrips = 2; -// [*] End of lib/trans-websocket.js - - -// [*] Including lib/trans-sender.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var BufferedSender = function() {}; -BufferedSender.prototype.send_constructor = function(sender) { - var that = this; - that.send_buffer = []; - that.sender = sender; -}; -BufferedSender.prototype.doSend = function(message) { - var that = this; - that.send_buffer.push(message); - if (!that.send_stop) { - that.send_schedule(); - } -}; - -// For polling transports in a situation when in the message callback, -// new message is being send. If the sending connection was started -// before receiving one, it is possible to saturate the network and -// timeout due to the lack of receiving socket. To avoid that we delay -// sending messages by some small time, in order to let receiving -// connection be started beforehand. This is only a halfmeasure and -// does not fix the big problem, but it does make the tests go more -// stable on slow networks. -BufferedSender.prototype.send_schedule_wait = function() { - var that = this; - var tref; - that.send_stop = function() { - that.send_stop = null; - clearTimeout(tref); - }; - tref = utils.delay(25, function() { - that.send_stop = null; - that.send_schedule(); - }); -}; - -BufferedSender.prototype.send_schedule = function() { - var that = this; - if (that.send_buffer.length > 0) { - var payload = '[' + that.send_buffer.join(',') + ']'; - that.send_stop = that.sender(that.trans_url, payload, function(success, abort_reason) { - that.send_stop = null; - if (success === false) { - that.ri._didClose(1006, 'Sending error ' + abort_reason); - } else { - that.send_schedule_wait(); - } - }); - that.send_buffer = []; - } -}; - -BufferedSender.prototype.send_destructor = function() { - var that = this; - if (that._send_stop) { - that._send_stop(); - } - that._send_stop = null; -}; - -var jsonPGenericSender = function(url, payload, callback) { - var that = this; - - if (!('_send_form' in that)) { - var form = that._send_form = _document.createElement('form'); - var area = that._send_area = _document.createElement('textarea'); - area.name = 'd'; - form.style.display = 'none'; - form.style.position = 'absolute'; - form.method = 'POST'; - form.enctype = 'application/x-www-form-urlencoded'; - form.acceptCharset = "UTF-8"; - form.appendChild(area); - _document.body.appendChild(form); - } - var form = that._send_form; - var area = that._send_area; - var id = 'a' + utils.random_string(8); - form.target = id; - form.action = url + '/jsonp_send?i=' + id; - - var iframe; - try { - // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) - iframe = _document.createElement('<iframe name="'+ id +'">'); - } catch(x) { - iframe = _document.createElement('iframe'); - iframe.name = id; - } - iframe.id = id; - form.appendChild(iframe); - iframe.style.display = 'none'; - - try { - area.value = payload; - } catch(e) { - utils.log('Your browser is seriously broken. Go home! ' + e.message); - } - form.submit(); - - var completed = function(e) { - if (!iframe.onerror) return; - iframe.onreadystatechange = iframe.onerror = iframe.onload = null; - // Opera mini doesn't like if we GC iframe - // immediately, thus this timeout. - utils.delay(500, function() { - iframe.parentNode.removeChild(iframe); - iframe = null; - }); - area.value = ''; - // It is not possible to detect if the iframe succeeded or - // failed to submit our form. - callback(true); - }; - iframe.onerror = iframe.onload = completed; - iframe.onreadystatechange = function(e) { - if (iframe.readyState == 'complete') completed(); - }; - return completed; -}; - -var createAjaxSender = function(AjaxObject) { - return function(url, payload, callback) { - var xo = new AjaxObject('POST', url + '/xhr_send', payload); - xo.onfinish = function(status, text) { - callback(status === 200 || status === 204, - 'http status ' + status); - }; - return function(abort_reason) { - callback(false, abort_reason); - }; - }; -}; -// [*] End of lib/trans-sender.js - - -// [*] Including lib/trans-jsonp-receiver.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -// Parts derived from Socket.io: -// https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js -// and jQuery-JSONP: -// https://code.google.com/p/jquery-jsonp/source/browse/trunk/core/jquery.jsonp.js -var jsonPGenericReceiver = function(url, callback) { - var tref; - var script = _document.createElement('script'); - var script2; // Opera synchronous load trick. - var close_script = function(frame) { - if (script2) { - script2.parentNode.removeChild(script2); - script2 = null; - } - if (script) { - clearTimeout(tref); - // Unfortunately, you can't really abort script loading of - // the script. - script.parentNode.removeChild(script); - script.onreadystatechange = script.onerror = - script.onload = script.onclick = null; - script = null; - callback(frame); - callback = null; - } - }; - - // IE9 fires 'error' event after orsc or before, in random order. - var loaded_okay = false; - var error_timer = null; - - script.id = 'a' + utils.random_string(8); - script.src = url; - script.type = 'text/javascript'; - script.charset = 'UTF-8'; - script.onerror = function(e) { - if (!error_timer) { - // Delay firing close_script. - error_timer = setTimeout(function() { - if (!loaded_okay) { - close_script(utils.closeFrame( - 1006, - "JSONP script loaded abnormally (onerror)")); - } - }, 1000); - } - }; - script.onload = function(e) { - close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onload)")); - }; - - script.onreadystatechange = function(e) { - if (/loaded|closed/.test(script.readyState)) { - if (script && script.htmlFor && script.onclick) { - loaded_okay = true; - try { - // In IE, actually execute the script. - script.onclick(); - } catch (x) {} - } - if (script) { - close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onreadystatechange)")); - } - } - }; - // IE: event/htmlFor/onclick trick. - // One can't rely on proper order for onreadystatechange. In order to - // make sure, set a 'htmlFor' and 'event' properties, so that - // script code will be installed as 'onclick' handler for the - // script object. Later, onreadystatechange, manually execute this - // code. FF and Chrome doesn't work with 'event' and 'htmlFor' - // set. For reference see: - // http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html - // Also, read on that about script ordering: - // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order - if (typeof script.async === 'undefined' && _document.attachEvent) { - // According to mozilla docs, in recent browsers script.async defaults - // to 'true', so we may use it to detect a good browser: - // https://developer.mozilla.org/en/HTML/Element/script - if (!/opera/i.test(navigator.userAgent)) { - // Naively assume we're in IE - try { - script.htmlFor = script.id; - script.event = "onclick"; - } catch (x) {} - script.async = true; - } else { - // Opera, second sync script hack - script2 = _document.createElement('script'); - script2.text = "try{var a = document.getElementById('"+script.id+"'); if(a)a.onerror();}catch(x){};"; - script.async = script2.async = false; - } - } - if (typeof script.async !== 'undefined') { - script.async = true; - } - - // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty. - tref = setTimeout(function() { - close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)")); - }, 35000); - - var head = _document.getElementsByTagName('head')[0]; - head.insertBefore(script, head.firstChild); - if (script2) { - head.insertBefore(script2, head.firstChild); - } - return close_script; -}; -// [*] End of lib/trans-jsonp-receiver.js - - -// [*] Including lib/trans-jsonp-polling.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -// The simplest and most robust transport, using the well-know cross -// domain hack - JSONP. This transport is quite inefficient - one -// mssage could use up to one http request. But at least it works almost -// everywhere. -// Known limitations: -// o you will get a spinning cursor -// o for Konqueror a dumb timer is needed to detect errors - - -var JsonPTransport = SockJS['jsonp-polling'] = function(ri, trans_url) { - utils.polluteGlobalNamespace(); - var that = this; - that.ri = ri; - that.trans_url = trans_url; - that.send_constructor(jsonPGenericSender); - that._schedule_recv(); -}; - -// Inheritnace -JsonPTransport.prototype = new BufferedSender(); - -JsonPTransport.prototype._schedule_recv = function() { - var that = this; - var callback = function(data) { - that._recv_stop = null; - if (data) { - // no data - heartbeat; - if (!that._is_closing) { - that.ri._didMessage(data); - } - } - // The message can be a close message, and change is_closing state. - if (!that._is_closing) { - that._schedule_recv(); - } - }; - that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp', - jsonPGenericReceiver, callback); -}; - -JsonPTransport.enabled = function() { - return true; -}; - -JsonPTransport.need_body = true; - - -JsonPTransport.prototype.doCleanup = function() { - var that = this; - that._is_closing = true; - if (that._recv_stop) { - that._recv_stop(); - } - that.ri = that._recv_stop = null; - that.send_destructor(); -}; - - -// Abstract away code that handles global namespace pollution. -var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) { - var id = 'a' + utils.random_string(6); - var url_id = url + '?c=' + escape(WPrefix + '.' + id); - - // Unfortunately it is not possible to abort loading of the - // script. We need to keep track of frake close frames. - var aborting = 0; - - // Callback will be called exactly once. - var callback = function(frame) { - switch(aborting) { - case 0: - // Normal behaviour - delete hook _and_ emit message. - delete _window[WPrefix][id]; - user_callback(frame); - break; - case 1: - // Fake close frame - emit but don't delete hook. - user_callback(frame); - aborting = 2; - break; - case 2: - // Got frame after connection was closed, delete hook, don't emit. - delete _window[WPrefix][id]; - break; - } - }; - - var close_script = constructReceiver(url_id, callback); - _window[WPrefix][id] = close_script; - var stop = function() { - if (_window[WPrefix][id]) { - aborting = 1; - _window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read")); - } - }; - return stop; -}; -// [*] End of lib/trans-jsonp-polling.js - - -// [*] Including lib/trans-xhr.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var AjaxBasedTransport = function() {}; -AjaxBasedTransport.prototype = new BufferedSender(); - -AjaxBasedTransport.prototype.run = function(ri, trans_url, - url_suffix, Receiver, AjaxObject) { - var that = this; - that.ri = ri; - that.trans_url = trans_url; - that.send_constructor(createAjaxSender(AjaxObject)); - that.poll = new Polling(ri, Receiver, - trans_url + url_suffix, AjaxObject); -}; - -AjaxBasedTransport.prototype.doCleanup = function() { - var that = this; - if (that.poll) { - that.poll.abort(); - that.poll = null; - } -}; - -// xhr-streaming -var XhrStreamingTransport = SockJS['xhr-streaming'] = function(ri, trans_url) { - this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XHRCorsObject); -}; - -XhrStreamingTransport.prototype = new AjaxBasedTransport(); - -XhrStreamingTransport.enabled = function() { - // Support for CORS Ajax aka Ajax2? Opera 12 claims CORS but - // doesn't do streaming. - return (_window.XMLHttpRequest && - 'withCredentials' in new XMLHttpRequest() && - (!/opera/i.test(navigator.userAgent))); -}; -XhrStreamingTransport.roundTrips = 2; // preflight, ajax - -// Safari gets confused when a streaming ajax request is started -// before onload. This causes the load indicator to spin indefinetely. -XhrStreamingTransport.need_body = true; - - -// According to: -// http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests -// http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ - - -// xdr-streaming -var XdrStreamingTransport = SockJS['xdr-streaming'] = function(ri, trans_url) { - this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XDRObject); -}; - -XdrStreamingTransport.prototype = new AjaxBasedTransport(); - -XdrStreamingTransport.enabled = function() { - return !!_window.XDomainRequest; -}; -XdrStreamingTransport.roundTrips = 2; // preflight, ajax - - - -// xhr-polling -var XhrPollingTransport = SockJS['xhr-polling'] = function(ri, trans_url) { - this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRCorsObject); -}; - -XhrPollingTransport.prototype = new AjaxBasedTransport(); - -XhrPollingTransport.enabled = XhrStreamingTransport.enabled; -XhrPollingTransport.roundTrips = 2; // preflight, ajax - - -// xdr-polling -var XdrPollingTransport = SockJS['xdr-polling'] = function(ri, trans_url) { - this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XDRObject); -}; - -XdrPollingTransport.prototype = new AjaxBasedTransport(); - -XdrPollingTransport.enabled = XdrStreamingTransport.enabled; -XdrPollingTransport.roundTrips = 2; // preflight, ajax -// [*] End of lib/trans-xhr.js - - -// [*] Including lib/trans-iframe.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -// Few cool transports do work only for same-origin. In order to make -// them working cross-domain we shall use iframe, served form the -// remote domain. New browsers, have capabilities to communicate with -// cross domain iframe, using postMessage(). In IE it was implemented -// from IE 8+, but of course, IE got some details wrong: -// http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx -// http://stevesouders.com/misc/test-postmessage.php - -var IframeTransport = function() {}; - -IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) { - var that = this; - that.ri = ri; - that.origin = utils.getOrigin(base_url); - that.base_url = base_url; - that.trans_url = trans_url; - - var iframe_url = base_url + '/iframe.html'; - if (that.ri._options.devel) { - iframe_url += '?t=' + (+new Date); - } - that.window_id = utils.random_string(8); - iframe_url += '#' + that.window_id; - - that.iframeObj = utils.createIframe(iframe_url, function(r) { - that.ri._didClose(1006, "Unable to load an iframe (" + r + ")"); - }); - - that.onmessage_cb = utils.bind(that.onmessage, that); - utils.attachMessage(that.onmessage_cb); -}; - -IframeTransport.prototype.doCleanup = function() { - var that = this; - if (that.iframeObj) { - utils.detachMessage(that.onmessage_cb); - try { - // When the iframe is not loaded, IE raises an exception - // on 'contentWindow'. - if (that.iframeObj.iframe.contentWindow) { - that.postMessage('c'); - } - } catch (x) {} - that.iframeObj.cleanup(); - that.iframeObj = null; - that.onmessage_cb = that.iframeObj = null; - } -}; - -IframeTransport.prototype.onmessage = function(e) { - var that = this; - if (e.origin !== that.origin) return; - var window_id = e.data.slice(0, 8); - var type = e.data.slice(8, 9); - var data = e.data.slice(9); - - if (window_id !== that.window_id) return; - - switch(type) { - case 's': - that.iframeObj.loaded(); - that.postMessage('s', JSON.stringify([SockJS.version, that.protocol, that.trans_url, that.base_url])); - break; - case 't': - that.ri._didMessage(data); - break; - } -}; - -IframeTransport.prototype.postMessage = function(type, data) { - var that = this; - that.iframeObj.post(that.window_id + type + (data || ''), that.origin); -}; - -IframeTransport.prototype.doSend = function (message) { - this.postMessage('m', message); -}; - -IframeTransport.enabled = function() { - // postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with - // huge delay, or not at all. - var konqueror = navigator && navigator.userAgent && navigator.userAgent.indexOf('Konqueror') !== -1; - return ((typeof _window.postMessage === 'function' || - typeof _window.postMessage === 'object') && (!konqueror)); -}; -// [*] End of lib/trans-iframe.js - - -// [*] Including lib/trans-iframe-within.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var curr_window_id; - -var postMessage = function (type, data) { - if(parent !== _window) { - parent.postMessage(curr_window_id + type + (data || ''), '*'); - } else { - utils.log("Can't postMessage, no parent window.", type, data); - } -}; - -var FacadeJS = function() {}; -FacadeJS.prototype._didClose = function (code, reason) { - postMessage('t', utils.closeFrame(code, reason)); -}; -FacadeJS.prototype._didMessage = function (frame) { - postMessage('t', frame); -}; -FacadeJS.prototype._doSend = function (data) { - this._transport.doSend(data); -}; -FacadeJS.prototype._doCleanup = function () { - this._transport.doCleanup(); -}; - -utils.parent_origin = undefined; - -SockJS.bootstrap_iframe = function() { - var facade; - curr_window_id = _document.location.hash.slice(1); - var onMessage = function(e) { - if(e.source !== parent) return; - if(typeof utils.parent_origin === 'undefined') - utils.parent_origin = e.origin; - if (e.origin !== utils.parent_origin) return; - - var window_id = e.data.slice(0, 8); - var type = e.data.slice(8, 9); - var data = e.data.slice(9); - if (window_id !== curr_window_id) return; - switch(type) { - case 's': - var p = JSON.parse(data); - var version = p[0]; - var protocol = p[1]; - var trans_url = p[2]; - var base_url = p[3]; - if (version !== SockJS.version) { - utils.log("Incompatibile SockJS! Main site uses:" + - " \"" + version + "\", the iframe:" + - " \"" + SockJS.version + "\"."); - } - if (!utils.flatUrl(trans_url) || !utils.flatUrl(base_url)) { - utils.log("Only basic urls are supported in SockJS"); - return; - } - - if (!utils.isSameOriginUrl(trans_url) || - !utils.isSameOriginUrl(base_url)) { - utils.log("Can't connect to different domain from within an " + - "iframe. (" + JSON.stringify([_window.location.href, trans_url, base_url]) + - ")"); - return; - } - facade = new FacadeJS(); - facade._transport = new FacadeJS[protocol](facade, trans_url, base_url); - break; - case 'm': - facade._doSend(data); - break; - case 'c': - if (facade) - facade._doCleanup(); - facade = null; - break; - } - }; - - // alert('test ticker'); - // facade = new FacadeJS(); - // facade._transport = new FacadeJS['w-iframe-xhr-polling'](facade, 'http://host.com:9999/ticker/12/basd'); - - utils.attachMessage(onMessage); - - // Start - postMessage('s'); -}; -// [*] End of lib/trans-iframe-within.js - - -// [*] Including lib/info.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var InfoReceiver = function(base_url, AjaxObject) { - var that = this; - utils.delay(function(){that.doXhr(base_url, AjaxObject);}); -}; - -InfoReceiver.prototype = new EventEmitter(['finish']); - -InfoReceiver.prototype.doXhr = function(base_url, AjaxObject) { - var that = this; - var t0 = (new Date()).getTime(); - var xo = new AjaxObject('GET', base_url + '/info'); - - var tref = utils.delay(8000, - function(){xo.ontimeout();}); - - xo.onfinish = function(status, text) { - clearTimeout(tref); - tref = null; - if (status === 200) { - var rtt = (new Date()).getTime() - t0; - var info = JSON.parse(text); - if (typeof info !== 'object') info = {}; - that.emit('finish', info, rtt); - } else { - that.emit('finish'); - } - }; - xo.ontimeout = function() { - xo.close(); - that.emit('finish'); - }; -}; - -var InfoReceiverIframe = function(base_url) { - var that = this; - var go = function() { - var ifr = new IframeTransport(); - ifr.protocol = 'w-iframe-info-receiver'; - var fun = function(r) { - if (typeof r === 'string' && r.substr(0,1) === 'm') { - var d = JSON.parse(r.substr(1)); - var info = d[0], rtt = d[1]; - that.emit('finish', info, rtt); - } else { - that.emit('finish'); - } - ifr.doCleanup(); - ifr = null; - }; - var mock_ri = { - _options: {}, - _didClose: fun, - _didMessage: fun - }; - ifr.i_constructor(mock_ri, base_url, base_url); - } - if(!_document.body) { - utils.attachEvent('load', go); - } else { - go(); - } -}; -InfoReceiverIframe.prototype = new EventEmitter(['finish']); - - -var InfoReceiverFake = function() { - // It may not be possible to do cross domain AJAX to get the info - // data, for example for IE7. But we want to run JSONP, so let's - // fake the response, with rtt=2s (rto=6s). - var that = this; - utils.delay(function() { - that.emit('finish', {}, 2000); - }); -}; -InfoReceiverFake.prototype = new EventEmitter(['finish']); - -var createInfoReceiver = function(base_url) { - if (utils.isSameOriginUrl(base_url)) { - // If, for some reason, we have SockJS locally - there's no - // need to start up the complex machinery. Just use ajax. - return new InfoReceiver(base_url, utils.XHRLocalObject); - } - switch (utils.isXHRCorsCapable()) { - case 1: - // XHRLocalObject -> no_credentials=true - return new InfoReceiver(base_url, utils.XHRLocalObject); - case 2: - return new InfoReceiver(base_url, utils.XDRObject); - case 3: - // Opera - return new InfoReceiverIframe(base_url); - default: - // IE 7 - return new InfoReceiverFake(); - }; -}; - - -var WInfoReceiverIframe = FacadeJS['w-iframe-info-receiver'] = function(ri, _trans_url, base_url) { - var ir = new InfoReceiver(base_url, utils.XHRLocalObject); - ir.onfinish = function(info, rtt) { - ri._didMessage('m'+JSON.stringify([info, rtt])); - ri._didClose(); - } -}; -WInfoReceiverIframe.prototype.doCleanup = function() {}; -// [*] End of lib/info.js - - -// [*] Including lib/trans-iframe-eventsource.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () { - var that = this; - that.protocol = 'w-iframe-eventsource'; - that.i_constructor.apply(that, arguments); -}; - -EventSourceIframeTransport.prototype = new IframeTransport(); - -EventSourceIframeTransport.enabled = function () { - return ('EventSource' in _window) && IframeTransport.enabled(); -}; - -EventSourceIframeTransport.need_body = true; -EventSourceIframeTransport.roundTrips = 3; // html, javascript, eventsource - - -// w-iframe-eventsource -var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function(ri, trans_url) { - this.run(ri, trans_url, '/eventsource', EventSourceReceiver, utils.XHRLocalObject); -} -EventSourceTransport.prototype = new AjaxBasedTransport(); -// [*] End of lib/trans-iframe-eventsource.js - - -// [*] Including lib/trans-iframe-xhr-polling.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var XhrPollingIframeTransport = SockJS['iframe-xhr-polling'] = function () { - var that = this; - that.protocol = 'w-iframe-xhr-polling'; - that.i_constructor.apply(that, arguments); -}; - -XhrPollingIframeTransport.prototype = new IframeTransport(); - -XhrPollingIframeTransport.enabled = function () { - return _window.XMLHttpRequest && IframeTransport.enabled(); -}; - -XhrPollingIframeTransport.need_body = true; -XhrPollingIframeTransport.roundTrips = 3; // html, javascript, xhr - - -// w-iframe-xhr-polling -var XhrPollingITransport = FacadeJS['w-iframe-xhr-polling'] = function(ri, trans_url) { - this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRLocalObject); -}; - -XhrPollingITransport.prototype = new AjaxBasedTransport(); -// [*] End of lib/trans-iframe-xhr-polling.js - - -// [*] Including lib/trans-iframe-htmlfile.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -// This transport generally works in any browser, but will cause a -// spinning cursor to appear in any browser other than IE. -// We may test this transport in all browsers - why not, but in -// production it should be only run in IE. - -var HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () { - var that = this; - that.protocol = 'w-iframe-htmlfile'; - that.i_constructor.apply(that, arguments); -}; - -// Inheritance. -HtmlFileIframeTransport.prototype = new IframeTransport(); - -HtmlFileIframeTransport.enabled = function() { - return IframeTransport.enabled(); -}; - -HtmlFileIframeTransport.need_body = true; -HtmlFileIframeTransport.roundTrips = 3; // html, javascript, htmlfile - - -// w-iframe-htmlfile -var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function(ri, trans_url) { - this.run(ri, trans_url, '/htmlfile', HtmlfileReceiver, utils.XHRLocalObject); -}; -HtmlFileTransport.prototype = new AjaxBasedTransport(); -// [*] End of lib/trans-iframe-htmlfile.js - - -// [*] Including lib/trans-polling.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var Polling = function(ri, Receiver, recv_url, AjaxObject) { - var that = this; - that.ri = ri; - that.Receiver = Receiver; - that.recv_url = recv_url; - that.AjaxObject = AjaxObject; - that._scheduleRecv(); -}; - -Polling.prototype._scheduleRecv = function() { - var that = this; - var poll = that.poll = new that.Receiver(that.recv_url, that.AjaxObject); - var msg_counter = 0; - poll.onmessage = function(e) { - msg_counter += 1; - that.ri._didMessage(e.data); - }; - poll.onclose = function(e) { - that.poll = poll = poll.onmessage = poll.onclose = null; - if (!that.poll_is_closing) { - if (e.reason === 'permanent') { - that.ri._didClose(1006, 'Polling error (' + e.reason + ')'); - } else { - that._scheduleRecv(); - } - } - }; -}; - -Polling.prototype.abort = function() { - var that = this; - that.poll_is_closing = true; - if (that.poll) { - that.poll.abort(); - } -}; -// [*] End of lib/trans-polling.js - - -// [*] Including lib/trans-receiver-eventsource.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var EventSourceReceiver = function(url) { - var that = this; - var es = new EventSource(url); - es.onmessage = function(e) { - that.dispatchEvent(new SimpleEvent('message', - {'data': unescape(e.data)})); - }; - that.es_close = es.onerror = function(e, abort_reason) { - // ES on reconnection has readyState = 0 or 1. - // on network error it's CLOSED = 2 - var reason = abort_reason ? 'user' : - (es.readyState !== 2 ? 'network' : 'permanent'); - that.es_close = es.onmessage = es.onerror = null; - // EventSource reconnects automatically. - es.close(); - es = null; - // Safari and chrome < 15 crash if we close window before - // waiting for ES cleanup. See: - // https://code.google.com/p/chromium/issues/detail?id=89155 - utils.delay(200, function() { - that.dispatchEvent(new SimpleEvent('close', {reason: reason})); - }); - }; -}; - -EventSourceReceiver.prototype = new REventTarget(); - -EventSourceReceiver.prototype.abort = function() { - var that = this; - if (that.es_close) { - that.es_close({}, true); - } -}; -// [*] End of lib/trans-receiver-eventsource.js - - -// [*] Including lib/trans-receiver-htmlfile.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var _is_ie_htmlfile_capable; -var isIeHtmlfileCapable = function() { - if (_is_ie_htmlfile_capable === undefined) { - if ('ActiveXObject' in _window) { - try { - _is_ie_htmlfile_capable = !!new ActiveXObject('htmlfile'); - } catch (x) {} - } else { - _is_ie_htmlfile_capable = false; - } - } - return _is_ie_htmlfile_capable; -}; - - -var HtmlfileReceiver = function(url) { - var that = this; - utils.polluteGlobalNamespace(); - - that.id = 'a' + utils.random_string(6, 26); - url += ((url.indexOf('?') === -1) ? '?' : '&') + - 'c=' + escape(WPrefix + '.' + that.id); - - var constructor = isIeHtmlfileCapable() ? - utils.createHtmlfile : utils.createIframe; - - var iframeObj; - _window[WPrefix][that.id] = { - start: function () { - iframeObj.loaded(); - }, - message: function (data) { - that.dispatchEvent(new SimpleEvent('message', {'data': data})); - }, - stop: function () { - that.iframe_close({}, 'network'); - } - }; - that.iframe_close = function(e, abort_reason) { - iframeObj.cleanup(); - that.iframe_close = iframeObj = null; - delete _window[WPrefix][that.id]; - that.dispatchEvent(new SimpleEvent('close', {reason: abort_reason})); - }; - iframeObj = constructor(url, function(e) { - that.iframe_close({}, 'permanent'); - }); -}; - -HtmlfileReceiver.prototype = new REventTarget(); - -HtmlfileReceiver.prototype.abort = function() { - var that = this; - if (that.iframe_close) { - that.iframe_close({}, 'user'); - } -}; -// [*] End of lib/trans-receiver-htmlfile.js - - -// [*] Including lib/trans-receiver-xhr.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -var XhrReceiver = function(url, AjaxObject) { - var that = this; - var buf_pos = 0; - - that.xo = new AjaxObject('POST', url, null); - that.xo.onchunk = function(status, text) { - if (status !== 200) return; - while (1) { - var buf = text.slice(buf_pos); - var p = buf.indexOf('\n'); - if (p === -1) break; - buf_pos += p+1; - var msg = buf.slice(0, p); - that.dispatchEvent(new SimpleEvent('message', {data: msg})); - } - }; - that.xo.onfinish = function(status, text) { - that.xo.onchunk(status, text); - that.xo = null; - var reason = status === 200 ? 'network' : 'permanent'; - that.dispatchEvent(new SimpleEvent('close', {reason: reason})); - } -}; - -XhrReceiver.prototype = new REventTarget(); - -XhrReceiver.prototype.abort = function() { - var that = this; - if (that.xo) { - that.xo.close(); - that.dispatchEvent(new SimpleEvent('close', {reason: 'user'})); - that.xo = null; - } -}; -// [*] End of lib/trans-receiver-xhr.js - - -// [*] Including lib/test-hooks.js -/* - * ***** BEGIN LICENSE BLOCK ***** - * Copyright (c) 2011-2012 VMware, Inc. - * - * For the license see COPYING. - * ***** END LICENSE BLOCK ***** - */ - -// For testing -SockJS.getUtils = function(){ - return utils; -}; - -SockJS.getIframeTransport = function(){ - return IframeTransport; -}; -// [*] End of lib/test-hooks.js - - return SockJS; - })(); -if ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1); - -// AMD compliance -if (typeof define === 'function' && define.amd) { - define('sockjs', [], function(){return SockJS;}); -} -// [*] End of lib/index.js - -// [*] End of lib/all.js diff --git a/cas/cas-server/src/main/resources/static/js/ssosessions.js b/cas/cas-server/src/main/resources/static/js/ssosessions.js deleted file mode 100644 index 84224b28..00000000 --- a/cas/cas-server/src/main/resources/static/js/ssosessions.js +++ /dev/null @@ -1,351 +0,0 @@ -/*eslint-disable no-unused-vars*/ -String.prototype.padLeft = function (length, character) { - return new Array(length - this.length + 1).join(character || ' ') + this; -}; - -Date.prototype.toFormattedString = function () { - return [String(this.getMonth() + 1).padLeft(2, '0'), - String(this.getDate()).padLeft(2, '0'), - String(this.getFullYear()).substr(2, 2)].join('/') + ' ' + - [String(this.getHours()).padLeft(2, '0'), - String(this.getMinutes()).padLeft(2, '0')].join(':'); -}; - -function principalAttributes(obj) { - var output = '<table class="table table-condensed principal_attributes"><tbody>'; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - if (Array.isArray(obj[key])) { - output = output.concat('<tr><td class="field-label active">' + key + '</td><td>' + obj[key].toString() + '</td></tr>'); - } else { - output = output.concat('<tr><td class="field-label active">' + key + '</td><td>' + obj[key] + '</td></tr>'); - } - } - } - output = output.concat('</tbody></table>'); - - return output; -} - -function authenticatedServices(obj) { - var output = ''; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - output = output.concat('<h5>' + key + '</h5><table class="table table-condensed principal_attributes"><tbody>'); - for (var foo in obj[key]) { - if (obj[key].hasOwnProperty(foo)) { - if (Array.isArray(obj[key][foo])) { - output = output.concat('<tr><td class="field-label active">' + foo + ':</td><td>' + obj[key][foo].toString() + '</td></tr>'); - } else { - output = output.concat('<tr><td class="field-label active">' + foo + ':</td><td>' + obj[key][foo] + '</td></tr>'); - } - } - } - output = output.concat('</tbody></table>'); - } - } - return output; -} - -/* Formatting function for row details - modify as you need */ -function format(d) { - return '<table class="table table-bordered row-detail">' + - '<tbody>' + - '<tr class="hidden-md hidden-lg">' + - '<td class="field-label active">Access Date:</td>' + - '<td>' + d.authentication_date_formatted + '</td>' + - '</tr>' + - '<tr class="hidden-md hidden-lg">' + - '<td class="field-label active">Usage Count:</td>' + - '<td>' + d.number_of_uses + '</td>' + - '</tr>' + - '<tr>' + - '<td class="field-label active">Ticket Granting Ticket:</td>' + - '<td>' + d.ticket_granting_ticket + '</td>' + - '</tr>' + - '<tr>' + - '<td class="field-label active">Principal Attributes:</td>' + - '<td>' + - principalAttributes(d.principal_attributes) + - '</td>' + - '</tr>' + - '<tr>' + - '<td class="field-label active">Authenticated Services:</td>' + - '<td>' + - authenticatedServices(d.authenticated_services) + - '</td>' + - '</tr>' + - '<tr>' + - '<td class="field-label active">Ticket Granting Service:</td>' + - '<td></td>' + - '</tr>' + - '</tbody></table>'; - -} - -function updateAdminPanels(data) { - //$('#totalUsers').text(data.totalPrincipals); - $('#totalUsers').text(data.activeSsoSessions.length); - $('#totalUsageSessions').text(sum(data.activeSsoSessions, 'number_of_uses')); - //$('#totalProxied').text(data.totalTicketGrantingTickets); - $('#totalTGTs').text(data.totalTicketGrantingTickets); - //$('#totalTGTs').text( sum(data.activeSsoSessions, 'is_proxied' ) ); -} - -function sum(obj, prop) { - var sum = 0; - for (var el in obj) { - if (obj.hasOwnProperty(el)) { - sum += ( typeof obj[el][prop] == 'boolean' ) ? +obj[el][prop] : obj[el][prop]; - } - } - return sum; -} - -/* - function showError(msg) { - $('#msg').removeClass(); - $('#msg').addClass('errors'); - $('#msg').text(msg); - $('#msg').show(); - } - */ - -/* - function showInfo(msg) { - $('#msg').removeClass(); - $('#msg').addClass('info'); - $('#msg').text(msg); - $('#msg').show(); - } - */ - -function alertUser(message, alertType) { - $('#alertWrapper').append('<div id="alertdiv" class="alert alert-' + alertType + ' alert-dismissible">' + - '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' + - '<span class="alertMessage">' + message + '</span></div>' - ); - - setTimeout(function () { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs - $('#alertdiv').remove(); - }, 5000); -} - -function removeSession(ticketId) { - var factory = {}; - factory.httpHeaders = {}; - factory.messages = {}; - factory.httpHeaders[$('meta[name=\'_csrf_header\']').attr('content')] = $('meta[name=\'_csrf\']').attr('content'); - - factory.ticketId = ticketId; - - - if (ticketId && (ticketId == 'ALL' || ticketId == 'PROXIED' || ticketId == 'DIRECT' )) { - factory.url = urls.destroy.all; - factory.data = {type: ticketId}; - factory.messages.success = 'Removed <strong>' + ticketId + '</strong> tickets successfully.'; - factory.messages.error = 'Could not remove <strong>' + ticketId + '</strong> tickets.'; - } else { - factory.url = urls.destroy.single; - factory.data = {ticketGrantingTicket: factory.ticketId}; - factory.messages.success = 'Ticket is removed successfully.'; - factory.messages.error = 'Ticket is not removed successfully.'; - } - - $.ajax({ - type: 'post', - url: factory.url, - //data: { ticketGrantingTicket: factory.ticketId, type: 'ALL' }, - data: factory.data, - headers: factory.httpHeaders, - dataType: 'json', - success: function (data) { - // Reinitialize the table data - $('#ssoSessions').DataTable().ajax.reload(); - - if (data.status != 200) { - alertUser(factory.messages.error, 'danger'); - } else { - alertUser(factory.messages.success, 'success'); - // Reload the page - location.reload(); - } - }, - error: function () { - alertUser('There appears to be an error. Please try your request again.', 'danger'); - } - }); -} - -var ssoSessions = (function () { - var createDataTable = function () { - $('#ssoSessions').DataTable({ - 'order': [[3, 'desc']], - 'initComplete': function (settings, json) { - if (!json || json.activeSsoSessions.length == 0) { - $('#loadingMessage').hide(); - $('#no-cas-sessions').show(); - } else { - updateAdminPanels(json); - - $('#loadingMessage').hide(); - $('#no-cas-sessions').hide(); - $('#cas-sessions').show(); - } - }, - 'language': { - //"infoEmpty": "No active sessions were found", - 'emptyTable': 'No sessions found', - 'zeroRecords': 'No matching sessions found' - }, - 'processing': true, - 'ajax': { - 'url': urls.getSessions, - 'dataSrc': 'activeSsoSessions' - }, - - columnDefs: [ - { - 'targets': 0, - 'className': 'details-control', - 'orderable': false, - 'data': null, - 'defaultContent': '' - }, - { - 'targets': 1, - 'data': 'is_proxied', - 'className': 'col-xs-2 col-md-1', - 'render': function (data) { - if (data === true) { - return '<span class="label label-primary">Proxy</span>'; - } else { - return ' '; - } - } - }, - { - 'targets': 2, - 'data': 'authenticated_principal', - 'className': 'col-xs-4 col-md-2', - 'render': function (data, type) { - return type === 'display' && data.length > 20 ? - '<span title="' + data + '">' + data.substr(0, 18) + '...</span>' : - data; - } - }, - { - 'targets': 3, - 'data': 'ticket_granting_ticket', - 'className': 'hidden-xs hidden-sm col-md-4', - 'render': function (data, type) { - return type === 'display' && data.length > 20 ? - '<span title="' + data + '">' + data.substr(0, 40) + '...</span>' : - data; - } - }, - { - 'targets': 4, - 'data': 'authentication_date_formatted', - 'className': 'col-xs-4 col-sm-4 col-md-2' - }, - { - 'targets': 5, - 'data': 'number_of_uses', - 'className': 'hidden-xs hidden-sm visible-md-* col-md-2' - }, - { - 'targets': 6, - 'data': 'ticket_granting_ticket', - 'className': 'col-xs-2 col-sm-2 col-md-1', - 'render': function (data) { - return '<button class="btn btn-xs btn-block btn-danger" type="button" value="' + data + '">Destroy</button>'; - }, - 'orderable': false - }, - ] - }); - }; - - var addEventHandlers = function () { - - /** - * The Bulk remove button - */ - $('#removeAllSessionsButton').on('click', function (e) { - e.preventDefault(); - removeSession(this.value); - }); - - /** - * Individual removal button - */ - $(document).on('click', '#ssoSessions tbody tr td:last-child button.btn-danger', function (e) { - e.preventDefault(); - removeSession(this.value); - }); - - /** - * The filter buttons - */ - $('#filterButtons .btn').click(function () { - - var filter = $(this).data('filter'); - var table = $('#ssoSessions').DataTable(); - var filterRegex; - var deleteValue; - var btnText; - - // Create Filter RegEx: - if (filter == 'proxied') { - filterRegex = '^Proxy$'; - deleteValue = 'PROXIED'; - btnText = 'Remove <span class="badge">xx</span> Proxied Sessions'; - } else if (filter == 'non-proxied') { - filterRegex = '^ $'; - deleteValue = 'DIRECT'; - btnText = 'Remove <span class="badge">xx</span> Non-Proxied Sessions'; - } else { - filterRegex = ''; - deleteValue = 'ALL'; - btnText = 'Remove All Sessions'; - } - - var searchTerm = table.column(1).search(filterRegex, true, false).draw(); - - $('#removeAllSessionsButton').val(deleteValue).html(btnText.replace('xx', searchTerm.page.info().recordsDisplay)); - }); - - - // Add event listener for opening and closing details - $(document).on('click', '#ssoSessions tbody td.details-control', function () { - var table = $('#ssoSessions').DataTable(); - var tr = $(this).closest('tr'); - var row = table.row(tr); - - if (row.child.isShown()) { - // This row is already open - close it - row.child.hide(); - tr.removeClass('shown'); - } - else { - // Open this row - row.child(format(row.data()), 'info').show(); - tr.addClass('shown'); - } - }); - }; - - // initialization ******* - (function init() { - addEventHandlers(); - createDataTable(); - })(); - - // Public Methods - return { - /** - * Not used - */ - }; -})(); diff --git a/cas/cas-server/src/main/resources/static/js/statisticsview.js b/cas/cas-server/src/main/resources/static/js/statisticsview.js deleted file mode 100644 index e493211f..00000000 --- a/cas/cas-server/src/main/resources/static/js/statisticsview.js +++ /dev/null @@ -1,208 +0,0 @@ -/* global d3 */ -/*eslint-disable no-unused-vars*/ -var Gauge = function (wrapper, percent, options) { - if (!wrapper || !percent) { - //console.error('wrapper and percentage are required. Please check your code.'); - return; - } - - var label = (!options.label) ? '' : options.label; - - var textClass = options.textClass || 'progress-meter'; - - var width = options.width || 200, - height = options.height || 200, - twoPi = 2 * Math.PI, - progress = 0, - total = 100, - formatPercent = d3.format('.0%'); - - var colorScale = d3.scaleLinear() - .domain([0, 0.40, 0.50, 1]) - .range(['green', 'green', 'goldenrod', 'red']); - - var arc = d3.arc() - .startAngle(0) - .innerRadius(width * 0.4) - .outerRadius(width * 0.5) - ; - - var svg = d3.select(wrapper).append('svg') - .attr('width', width) - .attr('height', height) - - .attr('fill', '#2E7AF9') - .append('g') - .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); - - var meter = svg.append('g') - .attr('class', textClass); - - meter.append('path') - .attr('class', 'background') - .attr('d', arc.endAngle(twoPi)); - - var foreground = meter.append('path') - .attr('class', 'foreground'); - - var text = meter.append('text') - .attr('text-anchor', 'middle'); - - var text2 = meter.append('text') - .attr('y', height * 0.15) - .attr('text-anchor', 'middle') - .attr('class', 'text2'); - - text2.text(label); - - var animate = function (percentage) { - var i = d3.interpolate(progress, percentage); - - foreground.transition().duration(2000) - .tween('progress', function () { - - return function (t) { - progress = i(t); - - foreground.style('fill', colorScale(progress)); - foreground.attr('d', arc.endAngle(twoPi * progress)); - text.text(formatPercent(progress)); - }; - }); - }; - - // init - (function () { - setTimeout(function () { - animate(percent); - }, 500); - })(); - - return { - update: function (newPercent) { - animate(newPercent); - } - }; -}; - - -function upTime(countTo, el) { - var wrapper = document.getElementById('card-uptime'); - var element = document.getElementById(el); - var difference = new Date(countTo*1000); - - var days = Math.floor(difference / (60 * 60 * 1000 * 24) * 1); - var hours = Math.floor((difference % (60 * 60 * 1000 * 24)) / (60 * 60 * 1000) * 1); - var mins = Math.floor(((difference % (60 * 60 * 1000 * 24)) % (60 * 60 * 1000)) / (60 * 1000) * 1); - var secs = Math.floor((((difference % (60 * 60 * 1000 * 24)) % (60 * 60 * 1000)) % (60 * 1000)) / 1000 * 1); - - clearTimeout(upTime.to); - - if (isNaN(days) || isNaN(hours) || isNaN(mins) || isNaN(secs) ) { - wrapper.style.display = 'none'; - } else { - days = (days == 1) ? days + ' day ' : days + ' days '; - hours = (hours == 1) ? hours + ' hour ' : hours + ' hours '; - mins = (mins == 1) ? mins + ' minute ' : mins + ' minutes '; - secs = (secs == 1) ? secs + ' second ' : secs + ' seconds'; - - var timeString = '<span class="upTime">' + days + hours + mins + secs + '</span>'; - element.innerHTML = timeString; - wrapper.style.display = 'block'; - - upTime.to = setTimeout(function() { - countTo = countTo + 1; - upTime(countTo, el); - },1000); - - } -} - -var analytics = document.getElementById('expiredSts'); - -var casStatistics = function (urls, messages) { - var timers = { - memory: 5000, - availability: 15000, - tickets: 5000 - }; - - var memoryGauage; - - var getRemoteJSON = function(url) { - return $.getJSON( url); - }; - - var tickets = function() { - var data = getRemoteJSON(urls.tickets); - data.done(function( data ) { - updateElementValue( 'unexpiredTgts', data.unexpiredTgts ); - updateElementValue( 'unexpiredSts', data.unexpiredSts ); - updateElementValue( 'expiredTgts', data.expiredTgts ); - updateElementValue( 'expiredSts', data.expiredSts ); - setTimeout( tickets, timers.tickets ); - }); - }; - - var updateElementValue = function(el, val) { - $( '#' + el ).text( val ); - }; - - var memory = function() { - var data = getRemoteJSON(urls.memory); - data.done(function( data ) { - updateElementValue('freeMemory', data.freeMemory.toFixed(2)); - // updateElementValue('totalMemory', data.totalMemory); - // updateElementValue('maxMemory', data.maxMemory); - // updateElementValue('availableProcessors', data.availableProcessors); - - var memCalc = (data.totalMemory / data.maxMemory).toFixed(2); - - if ( !memoryGauage ) { - memoryGauage = new Gauge('#maxMemoryGauge', memCalc, {width: 200, height: 200, - label: messages.memoryGaugeTitle, - textClass: 'runtimeStatistics'}); - } else { - memoryGauage.update( memCalc ); - } - - setTimeout( memory, timers.memory ); - }); - - }; - var availability = function() { - var data = getRemoteJSON(urls.availability); - data.done(function( data ) { - updateElementValue('upTime', data.upTime); - setTimeout( availability, timers.availability ); - }); - }; - - // initialization ******* - ( function init () { - $('#loading, .statisticsView').toggle(); - tickets(); - memory(); - // availability(); - })(); - - // Public Methods - return { - getTickets: function() { - return tickets(); - }, - getMemory: function() { - return memory(); - }, - getAvailability: function() { - return availability(); - }, - updateGauge: function(val){ - if (memoryGauage) { - memoryGauage.update( val ); - } else { - return 'unable to update'; - } - } - }; -}; diff --git a/cas/cas-server/src/main/resources/static/js/stomp.js b/cas/cas-server/src/main/resources/static/js/stomp.js deleted file mode 100644 index 26a81636..00000000 --- a/cas/cas-server/src/main/resources/static/js/stomp.js +++ /dev/null @@ -1,474 +0,0 @@ -// Generated by CoffeeScript 1.7.1 - -/* - Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0 - - Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/) - Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com) - */ - -(function() { - var Byte, Client, Frame, Stomp, - __hasProp = {}.hasOwnProperty, - __slice = [].slice; - - Byte = { - LF: '\x0A', - NULL: '\x00' - }; - - Frame = (function() { - var unmarshallSingle; - - function Frame(command, headers, body) { - this.command = command; - this.headers = headers != null ? headers : {}; - this.body = body != null ? body : ''; - } - - Frame.prototype.toString = function() { - var lines, name, value, _ref; - lines = [this.command]; - _ref = this.headers; - for (name in _ref) { - if (!__hasProp.call(_ref, name)) continue; - value = _ref[name]; - lines.push("" + name + ":" + value); - } - if (this.body) { - lines.push("content-length:" + (Frame.sizeOfUTF8(this.body))); - } - lines.push(Byte.LF + this.body); - return lines.join(Byte.LF); - }; - - Frame.sizeOfUTF8 = function(s) { - if (s) { - return encodeURI(s).split(/%..|./).length - 1; - } else { - return 0; - } - }; - - unmarshallSingle = function(data) { - var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref, _ref1; - divider = data.search(RegExp("" + Byte.LF + Byte.LF)); - headerLines = data.substring(0, divider).split(Byte.LF); - command = headerLines.shift(); - headers = {}; - trim = function(str) { - return str.replace(/^\s+|\s+$/g, ''); - }; - _ref = headerLines.reverse(); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - line = _ref[_i]; - idx = line.indexOf(':'); - headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1)); - } - body = ''; - start = divider + 2; - if (headers['content-length']) { - len = parseInt(headers['content-length']); - body = ('' + data).substring(start, start + len); - } else { - chr = null; - for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) { - chr = data.charAt(i); - if (chr === Byte.NULL) { - break; - } - body += chr; - } - } - return new Frame(command, headers, body); - }; - - Frame.unmarshall = function(datas) { - var data; - return (function() { - var _i, _len, _ref, _results; - _ref = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*")); - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - data = _ref[_i]; - if ((data != null ? data.length : void 0) > 0) { - _results.push(unmarshallSingle(data)); - } - } - return _results; - })(); - }; - - Frame.marshall = function(command, headers, body) { - var frame; - frame = new Frame(command, headers, body); - return frame.toString() + Byte.NULL; - }; - - return Frame; - - })(); - - Client = (function() { - var now; - - function Client(ws) { - this.ws = ws; - this.ws.binaryType = "arraybuffer"; - this.counter = 0; - this.connected = false; - this.heartbeat = { - outgoing: 10000, - incoming: 10000 - }; - this.maxWebSocketFrameSize = 16 * 1024; - this.subscriptions = {}; - } - - Client.prototype.debug = function(message) { - void 0; - }; - - now = function() { - return Date.now || new Date().valueOf; - }; - - Client.prototype._transmit = function(command, headers, body) { - var out; - out = Frame.marshall(command, headers, body); - if (typeof this.debug === "function") { - this.debug(">>> " + out); - } - while (true) { - if (out.length > this.maxWebSocketFrameSize) { - this.ws.send(out.substring(0, this.maxWebSocketFrameSize)); - out = out.substring(this.maxWebSocketFrameSize); - if (typeof this.debug === "function") { - this.debug("remaining = " + out.length); - } - } else { - return this.ws.send(out); - } - } - }; - - Client.prototype._setupHeartbeat = function(headers) { - var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1; - if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) { - return; - } - _ref1 = (function() { - var _i, _len, _ref1, _results; - _ref1 = headers['heart-beat'].split(","); - _results = []; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - v = _ref1[_i]; - _results.push(parseInt(v)); - } - return _results; - })(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1]; - if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) { - ttl = Math.max(this.heartbeat.outgoing, serverIncoming); - if (typeof this.debug === "function") { - this.debug("send PING every " + ttl + "ms"); - } - this.pinger = Stomp.setInterval(ttl, (function(_this) { - return function() { - _this.ws.send(Byte.LF); - return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0; - }; - })(this)); - } - if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) { - ttl = Math.max(this.heartbeat.incoming, serverOutgoing); - if (typeof this.debug === "function") { - this.debug("check PONG every " + ttl + "ms"); - } - return this.ponger = Stomp.setInterval(ttl, (function(_this) { - return function() { - var delta; - delta = now() - _this.serverActivity; - if (delta > ttl * 2) { - if (typeof _this.debug === "function") { - _this.debug("did not receive server activity for the last " + delta + "ms"); - } - return _this.ws.close(); - } - }; - })(this)); - } - }; - - Client.prototype._parseConnect = function() { - var args, connectCallback, errorCallback, headers; - args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; - headers = {}; - switch (args.length) { - case 2: - headers = args[0], connectCallback = args[1]; - break; - case 3: - if (args[1] instanceof Function) { - headers = args[0], connectCallback = args[1], errorCallback = args[2]; - } else { - headers.login = args[0], headers.passcode = args[1], connectCallback = args[2]; - } - break; - case 4: - headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3]; - break; - default: - headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4]; - } - return [headers, connectCallback, errorCallback]; - }; - - Client.prototype.connect = function() { - var args, errorCallback, headers, out; - args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; - out = this._parseConnect.apply(this, args); - headers = out[0], this.connectCallback = out[1], errorCallback = out[2]; - if (typeof this.debug === "function") { - this.debug("Opening Web Socket..."); - } - this.ws.onmessage = (function(_this) { - return function(evt) { - var arr, c, client, data, frame, messageID, onreceive, subscription, _i, _len, _ref, _results; - data = typeof ArrayBuffer !== 'undefined' && evt.data instanceof ArrayBuffer ? (arr = new Uint8Array(evt.data), typeof _this.debug === "function" ? _this.debug("--- got data length: " + arr.length) : void 0, ((function() { - var _i, _len, _results; - _results = []; - for (_i = 0, _len = arr.length; _i < _len; _i++) { - c = arr[_i]; - _results.push(String.fromCharCode(c)); - } - return _results; - })()).join('')) : evt.data; - _this.serverActivity = now(); - if (data === Byte.LF) { - if (typeof _this.debug === "function") { - _this.debug("<<< PONG"); - } - return; - } - if (typeof _this.debug === "function") { - _this.debug("<<< " + data); - } - _ref = Frame.unmarshall(data); - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - frame = _ref[_i]; - switch (frame.command) { - case "CONNECTED": - if (typeof _this.debug === "function") { - _this.debug("connected to server " + frame.headers.server); - } - _this.connected = true; - _this._setupHeartbeat(frame.headers); - _results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0); - break; - case "MESSAGE": - subscription = frame.headers.subscription; - onreceive = _this.subscriptions[subscription] || _this.onreceive; - if (onreceive) { - client = _this; - messageID = frame.headers["message-id"]; - frame.ack = function(headers) { - if (headers == null) { - headers = {}; - } - return client.ack(messageID, subscription, headers); - }; - frame.nack = function(headers) { - if (headers == null) { - headers = {}; - } - return client.nack(messageID, subscription, headers); - }; - _results.push(onreceive(frame)); - } else { - _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0); - } - break; - case "RECEIPT": - _results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0); - break; - case "ERROR": - _results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0); - break; - default: - _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0); - } - } - return _results; - }; - })(this); - this.ws.onclose = (function(_this) { - return function() { - var msg; - msg = "Whoops! Lost connection to " + _this.ws.url; - if (typeof _this.debug === "function") { - _this.debug(msg); - } - _this._cleanUp(); - return typeof errorCallback === "function" ? errorCallback(msg) : void 0; - }; - })(this); - return this.ws.onopen = (function(_this) { - return function() { - if (typeof _this.debug === "function") { - _this.debug('Web Socket Opened...'); - } - headers["accept-version"] = Stomp.VERSIONS.supportedVersions(); - headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(','); - return _this._transmit("CONNECT", headers); - }; - })(this); - }; - - Client.prototype.disconnect = function(disconnectCallback) { - this._transmit("DISCONNECT"); - this.ws.onclose = null; - this.ws.close(); - this._cleanUp(); - return typeof disconnectCallback === "function" ? disconnectCallback() : void 0; - }; - - Client.prototype._cleanUp = function() { - this.connected = false; - if (this.pinger) { - Stomp.clearInterval(this.pinger); - } - if (this.ponger) { - return Stomp.clearInterval(this.ponger); - } - }; - - Client.prototype.send = function(destination, headers, body) { - if (headers == null) { - headers = {}; - } - if (body == null) { - body = ''; - } - headers.destination = destination; - return this._transmit("SEND", headers, body); - }; - - Client.prototype.subscribe = function(destination, callback, headers) { - var client; - if (headers == null) { - headers = {}; - } - if (!headers.id) { - headers.id = "sub-" + this.counter++; - } - headers.destination = destination; - this.subscriptions[headers.id] = callback; - this._transmit("SUBSCRIBE", headers); - client = this; - return { - id: headers.id, - unsubscribe: function() { - return client.unsubscribe(headers.id); - } - }; - }; - - Client.prototype.unsubscribe = function(id) { - delete this.subscriptions[id]; - return this._transmit("UNSUBSCRIBE", { - id: id - }); - }; - - Client.prototype.begin = function(transaction) { - var client, txid; - txid = transaction || "tx-" + this.counter++; - this._transmit("BEGIN", { - transaction: txid - }); - client = this; - return { - id: txid, - commit: function() { - return client.commit(txid); - }, - abort: function() { - return client.abort(txid); - } - }; - }; - - Client.prototype.commit = function(transaction) { - return this._transmit("COMMIT", { - transaction: transaction - }); - }; - - Client.prototype.abort = function(transaction) { - return this._transmit("ABORT", { - transaction: transaction - }); - }; - - Client.prototype.ack = function(messageID, subscription, headers) { - if (headers == null) { - headers = {}; - } - headers["message-id"] = messageID; - headers.subscription = subscription; - return this._transmit("ACK", headers); - }; - - Client.prototype.nack = function(messageID, subscription, headers) { - if (headers == null) { - headers = {}; - } - headers["message-id"] = messageID; - headers.subscription = subscription; - return this._transmit("NACK", headers); - }; - - return Client; - - })(); - - Stomp = { - VERSIONS: { - V1_0: '1.0', - V1_1: '1.1', - V1_2: '1.2', - supportedVersions: function() { - return '1.1,1.0'; - } - }, - client: function(url, protocols) { - var klass, ws; - if (protocols == null) { - protocols = ['v10.stomp', 'v11.stomp']; - } - klass = Stomp.WebSocketClass || WebSocket; - ws = new klass(url, protocols); - return new Client(ws); - }, - over: function(ws) { - return new Client(ws); - }, - Frame: Frame - }; - - if (typeof window !== "undefined" && window !== null) { - Stomp.setInterval = function(interval, f) { - return window.setInterval(f, interval); - }; - Stomp.clearInterval = function(id) { - return window.clearInterval(id); - }; - window.Stomp = Stomp; - } else if (typeof exports !== "undefined" && exports !== null) { - exports.Stomp = Stomp; - } else { - self.Stomp = Stomp; - } - -}).call(this); diff --git a/cas/cas-server/src/main/resources/static/js/trustedDevices.js b/cas/cas-server/src/main/resources/static/js/trustedDevices.js deleted file mode 100644 index 7fdbdc94..00000000 --- a/cas/cas-server/src/main/resources/static/js/trustedDevices.js +++ /dev/null @@ -1,59 +0,0 @@ -/*eslint-disable no-unused-vars*/ -$('#myTabs a').click(function (e) { - e.preventDefault(); - $(this).tab('show'); -}); - -var revokeDevice = function (key) { - $.ajax({ - type: 'post', - url: urls.revokeRecord, - data: {'key': key}, - success: function () { - var table = $('#trustedDevicesTable').DataTable(); - table - .rows($('#' + key).parents('tr')) - .remove() - .draw(); - }, - error: function () { - //console.log('Could not remove record'); - } - }); -}; - -var trustedDevices = (function () { - var getData = function () { - $.getJSON(urls.getRecords, function (data) { - trustedDevicesTable(data); - }); - }; - - var trustedDevicesTable = function (jsonData) { - var t = $('#trustedDevicesTable').DataTable({ - 'order': [[2, 'desc']], - columnDefs: [ - {'width': '20%', 'targets': 0}, - {'width': '10%', 'targets': 1}, - {'width': '60%', 'targets': 2}, - {'width': '10%', 'targets': 3}, - {'width': '30%', 'targets': 4} - ] - }); - for (var i = 0; i < jsonData.length; i++) { - var rec = jsonData[i]; - t.row.add([ - rec.name, - rec.principal, - new Date(rec.date), - rec.geography, - '<button id=\'' + rec.key + '\' class=\'btn btn-sm btn-danger\' type=\'button\' value=\'ALL\' onclick=\'revokeDevice("' + rec.key + '")\'>Revoke</button>' - ]).draw(false); - } - }; - - // initialization ******* - (function init() { - getData(); - })(); -})(); diff --git a/cas/cas-server/src/main/resources/static/js/viewConfig.js b/cas/cas-server/src/main/resources/static/js/viewConfig.js deleted file mode 100644 index ad69c9bc..00000000 --- a/cas/cas-server/src/main/resources/static/js/viewConfig.js +++ /dev/null @@ -1,157 +0,0 @@ -/* globals $, urls, updateEnabled */ -(function () { - var origData; - - var setupButtonClickOnRefreshedProperties = function () { - $('#formRefreshCAS button').on('click', function (e) { - e.preventDefault(); - - // Show the refreshModal - var myModal = $('#refreshModal').modal({ - keyboard: false, - backdrop: 'static' - }); - - var primaryButton = myModal.find('.modal-footer button.btn-primary'); - - // Disable the primary button - primaryButton.prop('disabled', true).text('Refreshing...'); - - $.post(e.target.parentNode.action, function (data) { - if (data.length !== 0) { - $('#refreshModal-label').text('Refreshed Properties'); - myModal.find('.modal-content .modal-body').html( - '<pre>' + data + '</pre>' + - '<p>Click "OK" to reload page.</p>' - ); - } else { - myModal.find('.modal-header .modal-title').text('Properties Refreshed'); - myModal.find('.modal-content .modal-body').html( - '<p>Click "OK" to reload page.</p>' - ); - } - }) - .done(function () { - primaryButton.prop('disabled', false).text('Reload page').on('click', function (e) { - e.preventDefault(); - window.location.reload(); - }); - }) - .fail(function (jqXHR) { - $('#refreshModal-label').text('Problem With Refreshing Properties'); - myModal.find('.modal-content .modal-body').html( - '<div class="alert alert-warning"><strong>Status: ' + jqXHR.status + '</strong><p/>Unable to refresh the properties. Please try again.</div>' - ); - primaryButton.prop('disabled', false).text('OK').on('click', function (e) { - e.preventDefault(); - myModal.modal('hide'); - }); - }); - }); - }; - - var createDataTable = function () { - $('#viewConfigsTable').DataTable({ - 'autoWidth': false, - 'initComplete': function (settings, json) { - if (!json) { - $('#loadingMessage').hide(); - $('#viewConfigError').show(); - $('#view-configuration').hide(); - } else { - $('#loadingMessage').hide(); - $('#viewConfigError').hide(); - $('#view-configuration').show(); - } - }, - 'drawCallback': function () { - var api = this.api(); - if (api.page.info().pages > 1) { - $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'block'; - } else { - $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'none'; - } - - if (updateEnabled) { - editTable(); - } - }, - 'processing': true, - 'ajax': { - 'url': urls.getConfiguration, - 'dataSrc': function (json) { - var returnData = []; - for (var item in json) { - returnData.push({ - 'key': '<code>' + item + '</code>', - 'value': '' + json[item] + '' - }); - } - return returnData; - } - }, - 'columns': [ - {'data': 'key', 'className': 'col-xs-6 key'}, - {'data': 'value', 'className': 'col-xs-6 value'} - ], - 'pageLength': 50 - }); - }; - - var getRowData = function (row) { - var tds = row.find('td'); - var tmp = {}; - $.each(tds, function (i) { - if (i % 2 === 0) { - tmp.key = $(this).text(); - } else { - tmp.value = $(this).text(); - } - }); - return tmp; - }; - - var editTable = function () { - $('#viewConfigsTable').editableTableWidget({editor: $('<textarea>')}); - - $('#viewConfigsTable td').on('focus', function () { - origData = getRowData($(this).closest('tr')); - }); - - $('#viewConfigsTable tr').on('change', function () { - var newChanges = getRowData($(this)); - - var data = {old: origData, new: newChanges}; - $.ajax({url: urls.updateConfiguration, data: JSON.stringify(data), type: 'POST', contentType: 'application/json'}) - .fail(function () { - var result = 'Failed to save settings.'; - $('#alertWrapper').addClass('alert-warning'); - $('#alertWrapper').removeClass('alert-success'); - - $('#alertWrapper').text(result); - $('#alertWrapper').show(); - }) - .success(function () { - var result = 'Saved settings successfully.'; - $('#alertWrapper').removeClass('alert-warning'); - $('#alertWrapper').addClass('alert-success'); - - $('#resultText').text(result); - $('#alertWrapper').show(); - }); - }); - }; - - // initialization ******* - (function init () { - createDataTable(); - setupButtonClickOnRefreshedProperties(); - })(); - - // Public Methods - return { - /** - * Not used - */ - }; -})(); diff --git a/cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js b/cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js deleted file mode 100644 index 75734824..00000000 --- a/cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js +++ /dev/null @@ -1,136 +0,0 @@ -$('.ui.search').search({ - type: 'message', - searchDelay: 500, - silent: true, - apiSettings: { - silent: true, - cache: false, - url: urls.search, - onResponse: function (casResp) { - var response = { - results: {} - }; - - for (var key in casResp) { - if (casResp.hasOwnProperty(key)) { - var prop = casResp[key]; - var group = prop.group; - - if (response.results[group] === undefined) { - response.results[group] = { - name: group, - results: [] - }; - } - response.results[group].results.push({ - title: prop.id, - description: prop.description, - defaultValue: prop.defaultValue, - type: prop.type, - deprecated: prop.deprecated, - requiredProperty: prop.requiredProperty, - requiredModule: prop.requiredModule, - requiredModuleAutomated: prop.requiredModuleAutomated - }); - } - } - - return response; - }, - }, - minCharacters: 3, - templates: { - message: function (response, type) { - var html = ''; - $('#accordion').empty(); - - if (type === 'empty') { - html += '<h3><i class=\'fa fa-search\' /> <strong>No Results</strong></h3>'; - html += '<div class=\'alert alert-warning\'>'; - html += '<i class=\'fa fa-exclamation-circle\'/> '; - html += 'No search results could be found based on the provided query.'; - html += '</div>'; - } - - for (var group in response.results) { - var modules = new Set(); - - html += '<h2><i class=\'fa fa-users\' /> <strong>Group: </strong>' + group + '</h2>'; - var props = response.results[group].results; - - html += '<div>'; - - for (var i = 0; i < props.length; i++) { - html += '<p>'; - var prop = props[i]; - html += '<i class=\'fa fa-cogs\'/> '; - html += 'Property: <code>' + prop.title + '=' + prop.defaultValue + '</code><br/>'; - if (prop.deprecated) { - html += '<p/><div class=\'alert alert-warning\'>'; - html += '<i class=\'fa fa-exclamation-circle\'/> '; - html += 'This property is deprecated and will be removed in future CAS versions.'; - html += '</div>'; - } - if (prop.requiredProperty) { - html += '<p/><div class=\'alert alert-success\'>'; - html += '<i class=\'fa fa-check-square\'/> '; - html += 'This property is required.'; - html += '</div>'; - } - - html += '<i class=\'fab fa-codepen\' /> Type: <code>' + prop.type + '</code><br/>'; - if (prop.description != null) { - html += '<p>' + prop.description + '</p>'; - } - - if (prop.requiredModule != null) { - modules.add(prop.requiredModule); - } - html += '<hr>'; - } - - if (modules.size > 0) { - html += '<div>'; - html += '<p><i class=\'fa fa-gear\' /> Required Modules</p>'; - html += '<ul class=\'nav nav-pills\'>'; - html += '<li class=\'active\'><a href=\'#1\' data-toggle=\'tab\'>Maven</a></li>'; - html += '<li><a href=\'#2\' data-toggle=\'tab\'>Gradle</a></li>'; - html += '</ul>'; - - for (let moduleString of modules) { - html += '<div class=\'tab-content\'>'; - - var moduleArr = moduleString.split('|'); - var module = moduleArr[0]; - - var maven = '<dependency>\n'; - maven += '\t<groupId>org.apereo.cas</groupId>\n'; - maven += '\t<artifactId>' + module + '</artifactId>\n'; - maven += '\t<cas.version>${cas.version}</cas.version>\n'; - maven += '</dependency>\n'; - html += '<div class=\'tab-pane active\' id=\'1\'><pre>' + maven + '</pre></div>'; - - var gradle = 'compile \'org.apereo.cas:' + module + ':${project.\'cas.version\'}\'\n'; - html += '<div class=\'tab-pane\' id=\'2\'><pre>' + gradle + '</pre></div>'; - - html += '</div>'; - } - - html += '</div>'; - } - - html += '</div>'; - } - - html += '</div>'; - - - $('#accordion').html(html); - $('#accordion').accordion({ - heightStyle: 'content' - }); - $('#accordion').accordion('refresh'); - return ''; - } - } -}); diff --git a/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html b/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html index 124cdb1d..7d4fa057 100644 --- a/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html +++ b/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html @@ -9,7 +9,7 @@ <div layout:fragment="content"> <div> <h2 th:utext="#{screen.accountbadconfiguration.heading}">This account has not properly configured.</h2> - <p th:utext="#{screen.accountbadconfiguration.message}">Please contact the system administrator to regain access.</p> + <p th:utext="#{screen.accountbadconfiguration.message(${@environment.getProperty('theme.vitamui-platform-name')})}">Please contact the system administrator to regain access.</p> </div> </div> </body> diff --git a/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html b/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html index 72a8edaf..2f9486ab 100644 --- a/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html +++ b/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.accountdisabled.heading}">CAS Account Disabled View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casAccountLockedView.html b/cas/cas-server/src/main/resources/templates/casAccountLockedView.html index 9486ed2d..0d0ca2de 100644 --- a/cas/cas-server/src/main/resources/templates/casAccountLockedView.html +++ b/cas/cas-server/src/main/resources/templates/casAccountLockedView.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.accountlocked.heading}">Account Locked View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html b/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html index d404f146..0af1e852 100644 --- a/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html +++ b/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.authnblocked.heading}">Authentication Blocked View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casExpiredPassView.html b/cas/cas-server/src/main/resources/templates/casExpiredPassView.html index 54841117..c01887ff 100644 --- a/cas/cas-server/src/main/resources/templates/casExpiredPassView.html +++ b/cas/cas-server/src/main/resources/templates/casExpiredPassView.html @@ -2,7 +2,11 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.expiredpass.heading}">CAS Expired Password View</title> + <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{/js/passwordMeter.js}"></script> </head> diff --git a/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html b/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html index dbdb3ed9..1b852bc3 100644 --- a/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html +++ b/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html @@ -4,42 +4,20 @@ <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> - <meta charset="UTF-8"/> - <title>Vitam-UI</title> - <meta http-equiv="refresh" th:attr="content=${'1; url=' + portalUrl}" /> - <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta charset="UTF-8"/> + <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title> - <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/> + <meta http-equiv="refresh" th:attr="content=${'1; url=' + portalUrl}" /> + + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/> <link th:href="@{/css/cas.css}" rel="stylesheet"/> - <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script> <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script> - <script th:src="@{#{webjars.bootstrapmin.js}}"></script> - - <script th:inline="javascript"> - /*<![CDATA[*/ - - var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true"; - - var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/; - - if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', googleAnalyticsTrackingId, 'auto'); - ga('send', 'pageview'); - } - /*]]>*/ - </script> </head> <body class="login bg-portal" th:styleappend="${@environment.getProperty('theme.body.style')}"> <div class="background bg-success"></div> diff --git a/cas/cas-server/src/main/resources/templates/casLoginView.html b/cas/cas-server/src/main/resources/templates/casLoginView.html index e23e3dab..55f43b88 100644 --- a/cas/cas-server/src/main/resources/templates/casLoginView.html +++ b/cas/cas-server/src/main/resources/templates/casLoginView.html @@ -5,38 +5,14 @@ <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> <meta charset="UTF-8"/> - <title>Vitam-UI</title> + <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}"> + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"> <link th:href="@{/css/cas.css}" rel="stylesheet"/> - <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script> <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script> - <script th:src="@{#{webjars.bootstrapmin.js}}"></script> - - <script th:inline="javascript"> - /*<![CDATA[*/ - - var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true"; - - var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/; - - if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', googleAnalyticsTrackingId, 'auto'); - ga('send', 'pageview'); - } - - /*]]>*/ - </script> </head> <body th:styleappend="${@environment.getProperty('theme.body.style')}"> diff --git a/cas/cas-server/src/main/resources/templates/casLogoutView.html b/cas/cas-server/src/main/resources/templates/casLogoutView.html index 7a7f82ee..d1468f00 100644 --- a/cas/cas-server/src/main/resources/templates/casLogoutView.html +++ b/cas/cas-server/src/main/resources/templates/casLogoutView.html @@ -5,38 +5,14 @@ <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> <meta charset="UTF-8"/> - <title>Vitam-UI</title> + <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}"> + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"> <link th:href="@{/css/cas.css}" rel="stylesheet"/> - <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script> <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script> - <script th:src="@{#{webjars.bootstrapmin.js}}"></script> - - <script th:inline="javascript"> - /*<![CDATA[*/ - - var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true"; - - var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/; - - if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', googleAnalyticsTrackingId, 'auto'); - ga('send', 'pageview'); - } - - /*]]>*/ - </script> </head> <body th:styleappend="${@environment.getProperty('theme.body.style')}"> diff --git a/cas/cas-server/src/main/resources/templates/casMustChangePassView.html b/cas/cas-server/src/main/resources/templates/casMustChangePassView.html index 6391cb31..b5341a32 100644 --- a/cas/cas-server/src/main/resources/templates/casMustChangePassView.html +++ b/cas/cas-server/src/main/resources/templates/casMustChangePassView.html @@ -2,7 +2,11 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.mustchangepass.heading}"></title> + <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{/js/passwordMeter.js}"></script> </head> diff --git a/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html b/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html index 8a22d98f..3a3434b1 100644 --- a/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html +++ b/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.pac4j.unauthz.pagetitle}">Pac4j Stop Webflow View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html b/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html index c5b51c8e..eb56137c 100644 --- a/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html +++ b/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html @@ -2,7 +2,10 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.success.header}">Password Update Success View</title> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.success.header}">Password Update Success View</title> </head> <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}"> diff --git a/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html b/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html index 142ced36..57614e19 100644 --- a/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html +++ b/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html @@ -9,19 +9,14 @@ <title th:text="#{screen.logout.header}">Propagate Logout View</title> <link rel="stylesheet" th:href="@{#{webjars.fontawesomemin.css}}"/> - <link type="text/css" rel="stylesheet" th:href="@{#{webjars.bootstrapmin.css}}"/> - <link type="text/css" rel="stylesheet" th:href="@{#{webjars.latomin.css}}"/> <link rel="stylesheet" th:href="@{/css/cas.css}"/> - <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/> + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/> - <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script> <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script> - <script th:src="@{#{webjars.bootstrapmin.js}}"></script> <script th:inline="javascript"> /*<![CDATA[*/ diff --git a/cas/cas-server/src/main/resources/templates/casPwdView.html b/cas/cas-server/src/main/resources/templates/casPwdView.html index e65cf6f8..43b516ab 100644 --- a/cas/cas-server/src/main/resources/templates/casPwdView.html +++ b/cas/cas-server/src/main/resources/templates/casPwdView.html @@ -5,38 +5,16 @@ <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> <meta charset="UTF-8"/> - <title>Vitam-UI</title> + <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title> <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}"> + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/> <link th:href="@{/css/cas.css}" rel="stylesheet"/> <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script> <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script> - <script th:src="@{#{webjars.bootstrapmin.js}}"></script> - - <script th:inline="javascript"> - /*<![CDATA[*/ - - var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true"; - - var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/; - - if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', googleAnalyticsTrackingId, 'auto'); - ga('send', 'pageview'); - } - - /*]]>*/ - </script> </head> <body th:styleappend="${@environment.getProperty('theme.body.style')}"> diff --git a/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html b/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html index 832b7b74..10dffe50 100644 --- a/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html +++ b/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.pm.reset.title}">Password Reset Error View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html b/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html index 0f425d52..21847209 100644 --- a/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html +++ b/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.pm.reset.title}">Reset Password Send Instructions View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html b/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html index 5603d1a7..d07c589c 100644 --- a/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html +++ b/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html @@ -2,6 +2,9 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + <title th:text="#{screen.pm.reset.title}">Reset Password Sent Instructions View</title> </head> diff --git a/cas/cas-server/src/main/resources/templates/casServiceErrorView.html b/cas/cas-server/src/main/resources/templates/casServiceErrorView.html index 8ce0ad2b..a11504ff 100644 --- a/cas/cas-server/src/main/resources/templates/casServiceErrorView.html +++ b/cas/cas-server/src/main/resources/templates/casServiceErrorView.html @@ -2,13 +2,16 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.service.error.header}"></title> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:utext="#{screen.service.error.header(${@environment.getProperty('theme.vitamui-platform-name')})}"></title> </head> <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}"> <div layout:fragment="content"> <div> - <h1 th:utext="#{screen.service.error.header}"/> + <h1 th:utext="#{screen.service.error.header(${@environment.getProperty('theme.vitamui-platform-name')})}"/> <p th:if="${rootCauseException != null and rootCauseException.code != null}" th:utext="#{${rootCauseException.code}}"/> </div> diff --git a/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html b/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html index d15015dd..3debe818 100644 --- a/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html +++ b/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html @@ -2,7 +2,10 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.mfa.sms.login.pagetitle}"></title> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{cas.mfa.simple.pagetitle}"></title> </head> <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}"> diff --git a/cas/cas-server/src/main/resources/templates/error.html b/cas/cas-server/src/main/resources/templates/error.html index ab4e1ad4..41f1ae91 100644 --- a/cas/cas-server/src/main/resources/templates/error.html +++ b/cas/cas-server/src/main/resources/templates/error.html @@ -2,14 +2,17 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.unavailable.header}">VITAMUI Error</title> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.unavailable.header(${@environment.getProperty('theme.vitamui-platform-name')})}">VITAMUI Error</title> </head> <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}"> <div layout:fragment="content"> <div> <h2 th:utext="#{screen.unavailable.heading(${status},${error})}">VITAMUI is unable to process this request: "{0}:{1}"</h2> - <div th:utext="#{screen.unavailable.message}">screen.unavailable.message would go here</div> + <div th:utext="#{screen.unavailable.message(${@environment.getProperty('theme.vitamui-platform-name')})}">screen.unavailable.message would go here</div> </div> </div> diff --git a/cas/cas-server/src/main/resources/templates/error/401.html b/cas/cas-server/src/main/resources/templates/error/401.html index f68939a0..ec6e93f2 100644 --- a/cas/cas-server/src/main/resources/templates/error/401.html +++ b/cas/cas-server/src/main/resources/templates/error/401.html @@ -2,8 +2,12 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.error.page.accessdenied}">Error - 401</title> - <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" /> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.error.page.title.accessdenied}">Error - 401</title> + <style> .prompt { font-family: Verdana, sans-serif; diff --git a/cas/cas-server/src/main/resources/templates/error/403.html b/cas/cas-server/src/main/resources/templates/error/403.html index aca83ba1..264a5a14 100644 --- a/cas/cas-server/src/main/resources/templates/error/403.html +++ b/cas/cas-server/src/main/resources/templates/error/403.html @@ -2,7 +2,11 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.error.page.accessdenied}">Error - Permission Denied</title> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.error.page.title.permissiondenied}">Error - Permission Denied</title> <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" /> <style> .prompt { diff --git a/cas/cas-server/src/main/resources/templates/error/404.html b/cas/cas-server/src/main/resources/templates/error/404.html index 22e8bd20..1bc27fa9 100644 --- a/cas/cas-server/src/main/resources/templates/error/404.html +++ b/cas/cas-server/src/main/resources/templates/error/404.html @@ -2,7 +2,11 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.error.page.notfound}">Error Page Not Found</title> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.error.page.title.pagenotfound}">Error - Page Not Found</title> <style> <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" /> diff --git a/cas/cas-server/src/main/resources/templates/error/405.html b/cas/cas-server/src/main/resources/templates/error/405.html index 89118b47..1b2e5c27 100644 --- a/cas/cas-server/src/main/resources/templates/error/405.html +++ b/cas/cas-server/src/main/resources/templates/error/405.html @@ -2,7 +2,11 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.error.page.requestunsupported}">Error - Unsupported Request</title> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.error.page.title.requestunsupported}">Error - Unsupported Request</title> <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" /> <style> .prompt { diff --git a/cas/cas-server/src/main/resources/templates/error/423.html b/cas/cas-server/src/main/resources/templates/error/423.html index 556ca9b7..e5ee085a 100644 --- a/cas/cas-server/src/main/resources/templates/error/423.html +++ b/cas/cas-server/src/main/resources/templates/error/423.html @@ -2,7 +2,11 @@ <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title th:text="#{screen.error.page.accessdenied}">Error - Permission Denied</title> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> + + <title th:text="#{screen.error.page.title.blocked}">Error - Permission Denied</title> <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" /> <style> .prompt { diff --git a/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html b/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html index 6de31f4d..9de6f6ca 100644 --- a/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html +++ b/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html @@ -2,6 +2,13 @@ /*<![CDATA[*/ var policyPattern = /*[[${policyPattern}]]*/; + var passwordStrengthI18n = { + 0: /*[[#{screen.pm.password.strength.0}]]*/, + 1: /*[[#{screen.pm.password.strength.1}]]*/, + 2: /*[[#{screen.pm.password.strength.2}]]*/, + 3: /*[[#{screen.pm.password.strength.3}]]*/, + 4: /*[[#{screen.pm.password.strength.4}]]*/ + }; /*]]>*/ </script> diff --git a/cas/cas-server/src/main/resources/templates/fragments/scripts.html b/cas/cas-server/src/main/resources/templates/fragments/scripts.html index 670b7dec..5a764724 100644 --- a/cas/cas-server/src/main/resources/templates/fragments/scripts.html +++ b/cas/cas-server/src/main/resources/templates/fragments/scripts.html @@ -1,4 +1,8 @@ -<script th:src="@{#{webjars.headmin.js}}"></script> +<script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> +<script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey != null and recaptchaVersion=='v2'}"></script> +<script th:src="${'//www.google.com/recaptcha/api.js?render=' + recaptchaSiteKey}" th:if="${recaptchaSiteKey != null and recaptchaVersion == 'v3'}"></script> + +<script type="text/javascript" th:src="@{#{webjars.headmin.js}}"></script> <script type="text/javascript" th:src="@{${#themes.code('cas.javascript.file')}}"></script> <script th:inline="javascript"> @@ -13,11 +17,6 @@ head.ready(document, function () { function loadjQueryUI() { var jqueryUrl = /*[[@{#{webjars.jqueryui.js}}]]*/; - head.load(jqueryUrl, loadjQueryCookies); -} - -function loadjQueryCookies() { - var jqueryUrl = /*[[@{#{webjars.jquerycookie.js}}]]*/; head.load(jqueryUrl, notifyResourcesAreLoaded(resourceLoadedSuccessfully)); } @@ -28,4 +27,51 @@ function notifyResourcesAreLoaded(callback) { } </script> +<script th:inline="javascript"> + /*<![CDATA[*/ + + var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true"; + + var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/; + + if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') { + (function (i, s, o, g, r, a, m) { + i['GoogleAnalyticsObject'] = r; + i[r] = i[r] || function () { + (i[r].q = i[r].q || []).push(arguments) + }, i[r].l = 1 * new Date(); + a = s.createElement(o), + m = s.getElementsByTagName(o)[0]; + a.async = 1; + a.src = g; + m.parentNode.insertBefore(a, m) + })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); + + ga('create', googleAnalyticsTrackingId, 'auto'); + ga('send', 'pageview'); + } + + /*]]>*/ +</script> + +<span th:if="${recaptchaVersion=='v2'}" th:remove="tag"> + <script type="text/javascript" th:if="${recaptchaSiteKey != null AND recaptchaInvisible != null AND recaptchaInvisible}" th:inline="javascript"> + function onRecaptchaV2Submit(token) { + $('#fm1').submit(); + } + </script> +</span> + +<span th:if="${recaptchaVersion=='v3'}" th:remove="tag"> + <script type="text/javascript" th:if="${recaptchaSiteKey != null}" th:inline="javascript"> + grecaptcha.ready(function() { + grecaptcha.execute(/*[[${recaptchaSiteKey}]]*/, {action: 'login'}) + .then(function(token) { + $("#g-recaptcha-token").val(token) + }); + }); + </script> +</span> + + diff --git a/cas/cas-server/src/main/resources/templates/layout.html b/cas/cas-server/src/main/resources/templates/layout.html index 5f759a0e..897f1c3a 100644 --- a/cas/cas-server/src/main/resources/templates/layout.html +++ b/cas/cas-server/src/main/resources/templates/layout.html @@ -7,38 +7,14 @@ <title layout:title-pattern="$CONTENT_TITLE">VITAMUI</title> - <link rel="stylesheet" th:href="@{#{webjars.fontawesomemin.css}}"/> + <link rel="stylesheet" type="text/css" th:href="@{#{webjars.fontawesomemin.css}}"/> - <link rel="stylesheet" th:href="@{/css/cas.css}"/> + <!--/* Core CAS CSS */--> + <link rel="stylesheet" type="text/css" th:href="@{/css/cas.css}"/> - <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/> + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/> - <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script> - <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script> - <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script> - <script th:src="@{#{webjars.bootstrapmin.js}}"></script> - - <script th:inline="javascript"> - /*<![CDATA[*/ - - var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true"; - - var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/; - - if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', googleAnalyticsTrackingId, 'auto'); - ga('send', 'pageview'); - } - - /*]]>*/ - </script> </head> diff --git a/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html b/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html index 922824f3..dcf0b122 100644 --- a/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html +++ b/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html @@ -5,12 +5,12 @@ <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/> <meta charset="UTF-8"/> - <title>Vitam-UI</title> + <title>${@environment.getProperty('theme.vitamui-platform-name')}</title> <meta http-equiv="refresh" th:attr="content=${'1; url=' + url}" /> <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/> + <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/> <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script> <link th:href="@{/css/cas.css}" rel="stylesheet"/> </head> diff --git a/deployment/environments/group_vars/all/vitamui_vars.yml b/deployment/environments/group_vars/all/vitamui_vars.yml index 82fc596a..70e63424 100755 --- a/deployment/environments/group_vars/all/vitamui_vars.yml +++ b/deployment/environments/group_vars/all/vitamui_vars.yml @@ -156,6 +156,11 @@ vitamui: secure: true jvm_log: false logging_level: "INFO" + theme: + vitamui_platform_name: VITAM-UI + vitamui_favicon: "{{ vitamui_defaults.folder.root_path }}/conf/assets/favicon.ico" + vitam_logo: "{{ vitamui_defaults.folder.root_path }}/conf/assets/logo.png" + vitamui_logo_large: "{{ vitamui_defaults.folder.root_path }}/conf/assets/logo-large.png" log: logback_max_file_size: "10MB" logback_max_history: 30 diff --git a/deployment/roles/vitamui/templates/cas-server/application.yml.j2 b/deployment/roles/vitamui/templates/cas-server/application.yml.j2 index cdcad26e..b81772d8 100644 --- a/deployment/roles/vitamui/templates/cas-server/application.yml.j2 +++ b/deployment/roles/vitamui/templates/cas-server/application.yml.j2 @@ -171,10 +171,12 @@ server-identity: identityServerId: 1 -# Example to override theme colors and logo +# Example to override theme colors, logo, favicon, platform name ... theme: -# vitam-logo: {{ vitamui_defaults.folder.root_path }}/conf/assets/logo.png -# vitamui-logo-large: {{ vitamui_defaults.folder.root_path }}/conf/assets/logo-large.png + vitamui-platform-name: {{ vitamui.cas_server.theme.vitamui_platform_name }} + vitamui-favicon: {{ vitamui.cas_server.theme.vitamui_favicon }} + vitam-logo: {{ vitamui.cas_server.theme.vitam_logo }} + vitamui-logo-large: {{ vitamui.cas_server.theme.vitamui_logo_large }} primary: '{{ vitamui_platform_informations.theme_colors.vitamui_primary }}' secondary: '{{ vitamui_platform_informations.theme_colors.vitamui_secondary }}' -- GitLab