update tigon version
37
cas/.gitignore
vendored
@ -1,37 +0,0 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/web/dist
|
||||
/web/tmp
|
||||
/build
|
||||
/overlays
|
||||
/target
|
||||
|
||||
# dependencies
|
||||
/web/node_modules
|
||||
/web/bower_components
|
||||
|
||||
# misc
|
||||
/web/.sass-cache
|
||||
/web/connect.lock
|
||||
/web/coverage/*
|
||||
/web/libpeerconnection.log
|
||||
/web/npm-debug.log
|
||||
/web/testem.log
|
||||
/web/package-lock.json
|
||||
|
||||
.*
|
||||
!.editorconfig
|
||||
!.ember-cli
|
||||
!.jshintrc
|
||||
!.eslintrc.js
|
||||
!.travis.yml
|
||||
!.watchmanconfig
|
||||
!.gitignore
|
||||
!.gitkeep
|
||||
*.iml
|
||||
|
||||
# ember-try
|
||||
.node_modules.ember-try/
|
||||
bower.json.ember-try
|
||||
package.json.ember-try
|
86
cas/deploy
@ -1,86 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# get real path of softlink
|
||||
get_real_path() {
|
||||
local f="$1"
|
||||
while [ -h "$f" ]; do
|
||||
ls=`ls -ld "$f"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
f="$link"
|
||||
else
|
||||
f=`dirname "$f"`/"$link"
|
||||
fi
|
||||
done
|
||||
echo "$f"
|
||||
}
|
||||
|
||||
prg_path=$(get_real_path "$0")
|
||||
echo "Script Path [$prg_path]"
|
||||
pushd $(dirname "$prg_path") > /dev/null
|
||||
PROJECT_HOME=$(pwd)
|
||||
echo "Project Home [$PROJECT_HOME]"
|
||||
|
||||
if [ "$1" = 'test' ]; then
|
||||
SERVER=xiandou@tj-daily
|
||||
elif [ "$1" == 'prod' ]; then
|
||||
echo 'deploy dw'
|
||||
SERVER=crm@dw-crm
|
||||
else
|
||||
echo 'Profile required.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" != 'nb' ]; then
|
||||
mvn -T 4C clean package -am -DskipTests
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'Maven build failed.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET_DIR=target
|
||||
echo "Target dir [$TARGET_DIR]"
|
||||
JAR=$(find "$TARGET_DIR" -maxdepth 1 -type f -name "*.war" | grep -v "sources.jar$")
|
||||
|
||||
if [ -z "$JAR" ]; then
|
||||
echo "Build target JAR is blank, exit."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Target JAR [$JAR] found"
|
||||
JAR_FILE_NAME="${JAR##*/}"
|
||||
echo "JAR file name [$JAR_FILE_NAME]"
|
||||
|
||||
SERVICE_HOME=/data/program/cas
|
||||
echo "Service Home [$SERVICE_HOME], Server [$SERVER]"
|
||||
|
||||
echo "$SERVER [ -f $SERVICE_HOME/lib/main.jar ] && mv $SERVICE_HOME/lib/main.jar $SERVICE_HOME/lib/main_prev.jar"
|
||||
ssh "$SERVER" "[ -f $SERVICE_HOME/lib/main.jar ] && mv $SERVICE_HOME/lib/main.jar $SERVICE_HOME/lib/main_prev.jar"
|
||||
|
||||
echo "Copy [$JAR] to [$SERVER:$SERVICE_HOME/lib/]"
|
||||
|
||||
# Rename jar
|
||||
mv $JAR $TARGET_DIR/main.jar
|
||||
|
||||
TAR_FILE=main.tgz
|
||||
tar -C $TARGET_DIR -czvf $TARGET_DIR/$TAR_FILE main.jar
|
||||
DIST_TAR_FILE=$SERVICE_HOME/lib/$TAR_FILE
|
||||
|
||||
# Copy file to remote
|
||||
scp "$TARGET_DIR/$TAR_FILE" "$SERVER:$DIST_TAR_FILE"
|
||||
ssh "$SERVER" "tar -C $SERVICE_HOME/lib -xzvf $DIST_TAR_FILE && rm -rf $DIST_TAR_FILE"
|
||||
|
||||
# Restore jar
|
||||
mv $TARGET_DIR/main.jar $JAR
|
||||
# Remove tar
|
||||
rm -rf $TARGET_DIR/$TAR_FILE
|
||||
|
||||
echo "$SERVER $SERVICE_HOME/bin/stop.sh"
|
||||
ssh "$SERVER" "$SERVICE_HOME/bin/stop.sh"
|
||||
|
||||
echo "$SERVER $SERVICE_HOME/bin/start.sh"
|
||||
ssh "$SERVER" "$SERVICE_HOME/bin/start.sh"
|
||||
|
||||
popd > /dev/null
|
200
cas/pom.xml
@ -1,200 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.pudonghot.cas</groupId>
|
||||
<artifactId>cas</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>cas</name>
|
||||
<packaging>war</packaging>
|
||||
<description>CAS Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
|
||||
|
||||
<!--这三个依赖版本必须一致,不然会有jar重复-->
|
||||
<spring.version>5.3.22</spring.version>
|
||||
<spring-boot.version>2.7.3</spring-boot.version>
|
||||
<cas.version>6.6.7</cas.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-core-web-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-core-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-webapp-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-support-json-service-registry</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-core-authentication-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-core-webflow-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-core-webflow</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-support-jdbc</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-support-jdbc-drivers</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.30</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>jquery-backstretch</artifactId>
|
||||
<version>2.1.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>jquery-validation</artifactId>
|
||||
<version>1.19.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.cage</groupId>
|
||||
<artifactId>cage</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-webapp-tomcat</artifactId>
|
||||
<version>${cas.version}</version>
|
||||
<type>war</type>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.26</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!--不要再引入其他依赖管理,可能会和war包lib中jar冲突导致重复引入,war包中的lib已经不在版本管理之中-->
|
||||
<dependency>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-support-bom</artifactId>
|
||||
<version>${cas.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<finalName>cas</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>application*.yml</exclude>
|
||||
<exclude>application*.properties</exclude>
|
||||
<exclude>log4j2*.xml</exclude>
|
||||
<exclude>logback*.xml</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<configuration>
|
||||
<mainClass>org.apereo.cas.web.CasWebApplication</mainClass>
|
||||
<addResources>true</addResources>
|
||||
<layout>WAR</layout>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-webapp-tomcat</artifactId>
|
||||
</exclude>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<configuration>
|
||||
<archiveClasses>false</archiveClasses>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<overlays>
|
||||
<overlay>
|
||||
<groupId>org.apereo.cas</groupId>
|
||||
<artifactId>cas-server-webapp-tomcat</artifactId>
|
||||
<excludes>
|
||||
<exclude>WEB-INF/lib/material-components-web*.jar</exclude>
|
||||
<exclude>WEB-INF/lib/material__*.jar</exclude>
|
||||
<exclude>WEB-INF/lib/mdi__font*.jar</exclude>
|
||||
</excludes>
|
||||
</overlay>
|
||||
</overlays>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -1,40 +0,0 @@
|
||||
package com.pudonghot.cas.auth;
|
||||
|
||||
import lombok.val;
|
||||
import org.apereo.cas.web.flow.CasWebflowConstants;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration;
|
||||
import org.apereo.cas.web.flow.configurer.AbstractCasWebflowConfigurer;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:16:09
|
||||
*/
|
||||
public class CustomWebflowConfigurer extends AbstractCasWebflowConfigurer {
|
||||
|
||||
public CustomWebflowConfigurer(FlowBuilderServices flowBuilderServices,
|
||||
FlowDefinitionRegistry mainFlowDefinitionRegistry,
|
||||
ConfigurableApplicationContext applicationContext,
|
||||
CasConfigurationProperties casProperties) {
|
||||
super(flowBuilderServices, mainFlowDefinitionRegistry, applicationContext, casProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void doInitialize() {
|
||||
val flow = getLoginFlow();
|
||||
// 重写绑定自定义credential
|
||||
createFlowVariable(flow, CasWebflowConstants.VAR_ID_CREDENTIAL, UsernamePasswordSysCredential.class);
|
||||
// 登录页绑定新参数
|
||||
val state = (ViewState) flow.getState(CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM);
|
||||
val cfg = getViewStateBinderConfiguration(state);
|
||||
// 由于用户名以及密码已经绑定,所以只需对新加系统参数绑定即可
|
||||
cfg.addBinding(new BinderConfiguration.Binding("system", null, false));
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.pudonghot.cas.auth;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apereo.cas.authentication.credential.RememberMeUsernamePasswordCredential;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date May 27, 2023 10:27:33
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UsernamePasswordSysCredential extends RememberMeUsernamePasswordCredential {
|
||||
private String system;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder()
|
||||
.appendSuper(super.hashCode())
|
||||
.append(system)
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.pudonghot.cas.auth.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||
import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
|
||||
import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import com.pudonghot.cas.auth.handler.UsernamePasswordSystemAuthenticationHandler;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date May 27, 2023 10:37:01
|
||||
*/
|
||||
@Configuration("customAuthenticationEventExecutionPlanConfiguration")
|
||||
@EnableConfigurationProperties(CasConfigurationProperties.class)
|
||||
public class CustomAuthenticationEventExecutionPlanConfiguration implements AuthenticationEventExecutionPlanConfigurer {
|
||||
@Autowired
|
||||
private UsernamePasswordSystemAuthenticationHandler customAuthenticationHandler;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
|
||||
// 注册自定义认证器
|
||||
plan.registerAuthenticationHandler(customAuthenticationHandler);
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package com.pudonghot.cas.auth.config;
|
||||
|
||||
import lombok.val;
|
||||
import org.apereo.cas.services.ServicesManager;
|
||||
import org.apereo.cas.web.flow.CasWebflowConstants;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.apereo.cas.web.flow.CasWebflowConfigurer;
|
||||
import com.pudonghot.cas.auth.CustomWebflowConfigurer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||
import org.apereo.cas.authentication.principal.PrincipalFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.apereo.cas.web.flow.config.CasWebflowContextConfiguration;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import com.pudonghot.cas.auth.handler.UsernamePasswordSystemAuthenticationHandler;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date May 27, 2023 10:29:19
|
||||
*/
|
||||
@Configuration("customerAuthWebflowConfiguration")
|
||||
@EnableConfigurationProperties(CasConfigurationProperties.class)
|
||||
@AutoConfigureBefore(CasWebflowContextConfiguration.class)
|
||||
public class CustomerAuthWebflowConfiguration {
|
||||
|
||||
@Bean
|
||||
public CasWebflowConfigurer customWebflowConfigurer(
|
||||
final FlowBuilderServices builder,
|
||||
@Qualifier(CasWebflowConstants.BEAN_NAME_LOGIN_FLOW_DEFINITION_REGISTRY)
|
||||
final FlowDefinitionRegistry loginFlowRegistry,
|
||||
@Qualifier(CasWebflowConstants.BEAN_NAME_LOGOUT_FLOW_DEFINITION_REGISTRY)
|
||||
final FlowDefinitionRegistry logoutFlowRegistry,
|
||||
final ConfigurableApplicationContext applicationContext,
|
||||
final CasConfigurationProperties properties) {
|
||||
|
||||
val webflowConfigurer = new CustomWebflowConfigurer(builder, loginFlowRegistry, applicationContext, properties);
|
||||
webflowConfigurer.setLogoutFlowDefinitionRegistry(logoutFlowRegistry);
|
||||
return webflowConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册验证器
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public UsernamePasswordSystemAuthenticationHandler customAuthenticationHandler(
|
||||
@Qualifier("servicesManager")
|
||||
final ServicesManager servicesManager,
|
||||
@Qualifier("jdbcPrincipalFactory")
|
||||
final PrincipalFactory jdbcPrincipalFactory) {
|
||||
|
||||
// 优先验证
|
||||
return new UsernamePasswordSystemAuthenticationHandler("customAuthenticationHandler",
|
||||
servicesManager, jdbcPrincipalFactory, 1);
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package com.pudonghot.cas.auth.handler;
|
||||
|
||||
import lombok.val;
|
||||
import java.util.Collections;
|
||||
import java.security.GeneralSecurityException;
|
||||
import org.apereo.cas.services.ServicesManager;
|
||||
import org.apereo.cas.authentication.Credential;
|
||||
import org.apereo.cas.authentication.principal.Service;
|
||||
import org.apereo.cas.authentication.PreventedException;
|
||||
import javax.security.auth.login.AccountNotFoundException;
|
||||
import com.pudonghot.cas.auth.UsernamePasswordSysCredential;
|
||||
import org.apereo.cas.authentication.principal.PrincipalFactory;
|
||||
import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
|
||||
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
|
||||
|
||||
/**
|
||||
* 用户名系统认证,只要是admin用户加上sso系统就允许通过
|
||||
*
|
||||
* @author Donghuang
|
||||
* @date May 27, 2023 10:37:32
|
||||
*/
|
||||
public class UsernamePasswordSystemAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {
|
||||
|
||||
public UsernamePasswordSystemAuthenticationHandler(final String name,
|
||||
final ServicesManager servicesManager,
|
||||
final PrincipalFactory principalFactory,
|
||||
final Integer order) {
|
||||
|
||||
super(name, servicesManager, principalFactory, order);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationHandlerExecutionResult doAuthentication(Credential credential, Service service) throws GeneralSecurityException, PreventedException {
|
||||
//当用户名为admin,并且system为sso即允许通过
|
||||
val sysCredential = (UsernamePasswordSysCredential) credential;
|
||||
|
||||
if ("admin".equals(sysCredential.getUsername()) && "sso".equals(sysCredential.getSystem())) {
|
||||
//这里可以自定义属性数据
|
||||
return createHandlerResult(credential, this.principalFactory.createPrincipal(((UsernamePasswordSysCredential) credential).getUsername(), Collections.emptyMap()), null);
|
||||
}
|
||||
|
||||
throw new AccountNotFoundException("必须是admin用户才允许通过");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(final Credential credential) {
|
||||
return credential instanceof UsernamePasswordSysCredential;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.pudonghot.cas.captcha;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 16:36:51
|
||||
*/
|
||||
public interface CaptchaConstants {
|
||||
/**
|
||||
* 验证码存储常量,可以存储session等等
|
||||
*/
|
||||
String STORE_CODE = "captcha_code";
|
||||
|
||||
/**
|
||||
* 请求路径
|
||||
*/
|
||||
String REQUEST_MAPPING = "/captcha";
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.pudonghot.cas.captcha;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date May 27, 2023 20:27:40
|
||||
*/
|
||||
public interface CaptchaService<S, T> {
|
||||
|
||||
/**
|
||||
* 获取数据结果
|
||||
*
|
||||
* @param s 存储器
|
||||
* @return
|
||||
*/
|
||||
T getAndStore(S s);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.pudonghot.cas.captcha;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:20:12
|
||||
*/
|
||||
public interface CaptchaStore<T, S> {
|
||||
|
||||
/**
|
||||
* 把S存储到T
|
||||
*
|
||||
* @param t
|
||||
* @param s
|
||||
*/
|
||||
void store(T t, S s);
|
||||
|
||||
/**
|
||||
* 校验
|
||||
* @param store 持久化对象
|
||||
* @param code 校验编码
|
||||
* @return
|
||||
*/
|
||||
boolean validate(T store, S code);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.pudonghot.cas.captcha;
|
||||
|
||||
import lombok.val;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import com.github.cage.token.RandomTokenGenerator;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:29:42
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class SessionCaptchaService implements CaptchaService<HttpSession, String> {
|
||||
private final RandomTokenGenerator generator = new RandomTokenGenerator(null, 4);
|
||||
|
||||
private final CaptchaStore<HttpSession, String> store;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getAndStore(final HttpSession httpSession) {
|
||||
val token = generator.next();
|
||||
store.store(httpSession, token);
|
||||
return token;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package com.pudonghot.cas.captcha;
|
||||
|
||||
import lombok.val;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:32:01
|
||||
*/
|
||||
public class SessionCaptchaStore implements CaptchaStore<HttpSession, String> {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void store(final HttpSession httpSession, final String s) {
|
||||
httpSession.setAttribute(CaptchaConstants.STORE_CODE, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean validate(final HttpSession store, String code) {
|
||||
val relCode = get(store);
|
||||
|
||||
if (StringUtils.hasText(relCode) && relCode.equals(code)) {
|
||||
// 校验完清空
|
||||
store.removeAttribute(CaptchaConstants.STORE_CODE);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String get(final HttpSession httpSession) {
|
||||
return (String) httpSession.getAttribute(CaptchaConstants.STORE_CODE);
|
||||
}
|
||||
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package com.pudonghot.cas.captcha.action;
|
||||
|
||||
import lombok.val;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import org.apereo.cas.web.support.WebUtils;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import com.pudonghot.cas.captcha.CaptchaStore;
|
||||
import org.springframework.webflow.action.AbstractAction;
|
||||
import org.springframework.binding.message.MessageBuilder;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.apereo.cas.authentication.credential.UsernamePasswordCredential;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 16:43:31
|
||||
*/
|
||||
@Slf4j
|
||||
public class ValidateLoginCaptchaAction extends AbstractAction {
|
||||
// 验证码存储器
|
||||
private CaptchaStore<HttpSession, String> captchaStore;
|
||||
|
||||
private static final String CODE = "captchaError";
|
||||
|
||||
public ValidateLoginCaptchaAction(CaptchaStore<HttpSession, String> captchaStore) {
|
||||
this.captchaStore = captchaStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端验证码
|
||||
*/
|
||||
public static final String CODE_PARAM = "validateCode";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Event doExecute(final RequestContext context) {
|
||||
val credential = WebUtils.getCredential(context);
|
||||
|
||||
// validate UsernamePasswordCredential only
|
||||
if (credential instanceof UsernamePasswordCredential) {
|
||||
log.debug("开始校验登录校验码");
|
||||
val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(context);
|
||||
//校验码
|
||||
val inCode = request.getParameter(CODE_PARAM);
|
||||
log.debug("input code [{}].", inCode);
|
||||
val httpSession = request.getSession();
|
||||
// 校验码失败跳转到登录页
|
||||
if (!captchaStore.validate(httpSession, inCode)) {
|
||||
return getError(context);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到错误页
|
||||
*
|
||||
* @param requestContext
|
||||
* @return
|
||||
*/
|
||||
private Event getError(final RequestContext requestContext) {
|
||||
val messageContext = requestContext.getMessageContext();
|
||||
messageContext.addMessage(new MessageBuilder().error().code(CODE).build());
|
||||
return getEventFactorySupport().event(this, CODE);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package com.pudonghot.cas.captcha.config;
|
||||
|
||||
import org.apereo.cas.web.flow.CasWebflowConstants;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.apereo.cas.web.flow.CasWebflowConfigurer;
|
||||
import com.pudonghot.cas.captcha.SessionCaptchaStore;
|
||||
import com.pudonghot.cas.captcha.SessionCaptchaService;
|
||||
import com.pudonghot.cas.captcha.controller.CaptchaController;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import com.pudonghot.cas.captcha.action.ValidateLoginCaptchaAction;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:35:55
|
||||
*/
|
||||
@Configuration("captchaConfiguration")
|
||||
@EnableConfigurationProperties(CasConfigurationProperties.class)
|
||||
public class CaptchaConfiguration {
|
||||
|
||||
@Bean
|
||||
public SessionCaptchaStore sessionCaptchaStore() {
|
||||
return new SessionCaptchaStore();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionCaptchaService sessionCaptchaService(final SessionCaptchaStore store) {
|
||||
return new SessionCaptchaService(store);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CaptchaController captchaController(final SessionCaptchaService service) {
|
||||
return new CaptchaController(service);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CasWebflowConfigurer validateWebflowConfigurer(
|
||||
final FlowBuilderServices flowBuilderServices,
|
||||
@Qualifier(CasWebflowConstants.BEAN_NAME_LOGIN_FLOW_DEFINITION_REGISTRY)
|
||||
final FlowDefinitionRegistry loginFlowRegistry,
|
||||
final ConfigurableApplicationContext applicationContext,
|
||||
final CasConfigurationProperties casProperties) {
|
||||
|
||||
return new ValidateWebflowConfigurer(flowBuilderServices, loginFlowRegistry, applicationContext, casProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ValidateLoginCaptchaAction validateLoginCaptchaAction(
|
||||
final SessionCaptchaStore store) {
|
||||
|
||||
return new ValidateLoginCaptchaAction(store);
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.pudonghot.cas.captcha.config;
|
||||
|
||||
import org.apereo.cas.web.flow.CasWebflowExecutionPlan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.apereo.cas.web.flow.CasWebflowExecutionPlanConfigurer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:56:18
|
||||
*/
|
||||
@Configuration("validateWebflowConfiguation")
|
||||
@AutoConfigureAfter(CaptchaConfiguration.class)
|
||||
@EnableConfigurationProperties(CasConfigurationProperties.class)
|
||||
public class ValidateWebflowConfiguation implements CasWebflowExecutionPlanConfigurer {
|
||||
@Autowired
|
||||
private ValidateWebflowConfigurer validateWebflowConfigurer;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void configureWebflowExecutionPlan(final CasWebflowExecutionPlan plan) {
|
||||
plan.registerWebflowConfigurer(validateWebflowConfigurer);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package com.pudonghot.cas.captcha.config;
|
||||
|
||||
import lombok.val;
|
||||
import java.util.ArrayList;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apereo.cas.web.flow.CasWebflowConstants;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.engine.ActionState;
|
||||
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.apereo.cas.web.flow.configurer.AbstractCasWebflowConfigurer;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:37:11
|
||||
*/
|
||||
@Slf4j
|
||||
public class ValidateWebflowConfigurer extends AbstractCasWebflowConfigurer {
|
||||
|
||||
public ValidateWebflowConfigurer(FlowBuilderServices flowBuilderServices,
|
||||
FlowDefinitionRegistry loginFlowDefinitionRegistry,
|
||||
ConfigurableApplicationContext applicationContext,
|
||||
CasConfigurationProperties casProperties) {
|
||||
|
||||
super(flowBuilderServices, loginFlowDefinitionRegistry, applicationContext, casProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void doInitialize() {
|
||||
createLoginValidateValidateFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录校验流程
|
||||
*/
|
||||
void createLoginValidateValidateFlow() {
|
||||
log.info("Create login validate flow.");
|
||||
|
||||
val flow = getLoginFlow();
|
||||
val state = (ActionState) flow.getState(CasWebflowConstants.STATE_ID_REAL_SUBMIT);
|
||||
val actionList = state.getActionList();
|
||||
|
||||
val currentActions = new ArrayList<Action>();
|
||||
actionList.forEach(currentActions::add);
|
||||
currentActions.forEach(a -> actionList.remove(a));
|
||||
|
||||
actionList.add(createEvaluateAction("validateLoginCaptchaAction"));
|
||||
currentActions.forEach(a -> actionList.add(a));
|
||||
|
||||
state.getTransitionSet().add(createTransition("captchaError", CasWebflowConstants.STATE_ID_INIT_LOGIN_FORM));
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package com.pudonghot.cas.captcha.controller;
|
||||
|
||||
import lombok.val;
|
||||
import com.github.cage.Cage;
|
||||
import com.github.cage.GCage;
|
||||
import javax.imageio.ImageIO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import com.pudonghot.cas.captcha.CaptchaConstants;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.apereo.cas.web.AbstractDelegateController;
|
||||
import com.pudonghot.cas.captcha.SessionCaptchaService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jun 05, 2023 15:26:56
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CaptchaController extends AbstractDelegateController {
|
||||
private final Cage cage = new GCage();
|
||||
private final SessionCaptchaService service;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean canHandle(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@GetMapping(value = CaptchaConstants.REQUEST_MAPPING, produces = "image/png")
|
||||
protected ModelAndView handleRequestInternal(
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
|
||||
// 禁止缓存
|
||||
// 设置response头信息
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
response.setContentType("image/png");
|
||||
|
||||
try (val outputStream = response.getOutputStream()) {
|
||||
// 存储验证码到session
|
||||
val text = service.getAndStore(request.getSession());
|
||||
ImageIO.write(cage.drawImage(text), "png", outputStream);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
package com.pudonghot.cas;
|
@ -1,4 +0,0 @@
|
||||
com.pudonghot.cas.auth.config.CustomerAuthWebflowConfiguration
|
||||
com.pudonghot.cas.auth.config.CustomAuthenticationEventExecutionPlanConfiguration
|
||||
com.pudonghot.cas.captcha.config.CaptchaConfiguration
|
||||
com.pudonghot.cas.captcha.config.ValidateWebflowConfiguation
|
@ -1,2 +0,0 @@
|
||||
cas.javascript.file=/themes/apereo/js/cas.js
|
||||
cas.standard.css.file=themes/apereo/css/cas.css
|
@ -1,169 +0,0 @@
|
||||
server:
|
||||
port: 8443
|
||||
compression:
|
||||
enabled: false
|
||||
error:
|
||||
include-stacktrace: ALWAYS
|
||||
forward-headers-strategy: native
|
||||
max-http-header-size: 2097152
|
||||
servlet:
|
||||
context-parameters:
|
||||
isLog4jAutoInitializationDisabled: true
|
||||
context-path: /
|
||||
encoding:
|
||||
charset: UTF-8
|
||||
enabled: true
|
||||
force: true
|
||||
session:
|
||||
cookie:
|
||||
http-only: true
|
||||
name: JSID
|
||||
timeout: PT30S
|
||||
tracking-modes: COOKIE
|
||||
ssl:
|
||||
enabled: false
|
||||
tomcat:
|
||||
accesslog:
|
||||
enabled: true
|
||||
pattern: '%t %a "%r" %s (%D ms)'
|
||||
suffix: .log
|
||||
additional-tld-skip-patterns: '*.jar'
|
||||
basedir: build/tomcat
|
||||
max-http-form-post-size: 2097152
|
||||
max-threads: 200
|
||||
min-spare-threads: 10
|
||||
port-header: X-Forwarded-Port
|
||||
protocol-header: X-Forwarded-Proto
|
||||
protocol-header-https-value: https
|
||||
remote-ip-header: X-Forwarded-For
|
||||
uri-encoding: UTF-8
|
||||
|
||||
spring:
|
||||
aop:
|
||||
auto: true
|
||||
proxy-target-class: true
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
thymeleaf:
|
||||
cache: false
|
||||
encoding: UTF-8
|
||||
mode: HTML
|
||||
template-resolver-order: 100
|
||||
prefix: file://${work.dir}/src/main/resources/views/
|
||||
web:
|
||||
resources:
|
||||
static-locations: file://${work.dir}/src/main/resources/static/
|
||||
cache:
|
||||
period: 0
|
||||
|
||||
cas:
|
||||
server:
|
||||
name: https://cas.zhujiachefu.com
|
||||
prefix: ${cas.server.name}
|
||||
authn:
|
||||
jdbc:
|
||||
query:
|
||||
- autocommit: true
|
||||
dialect: org.hibernate.dialect.MySQLDialect
|
||||
driver-class: com.mysql.cj.jdbc.Driver
|
||||
field-password: password
|
||||
health-query: 'select 1'
|
||||
password-encoder:
|
||||
character-encoding: UTF-8
|
||||
encoding-algorithm: MD5
|
||||
type: DEFAULT
|
||||
pool:
|
||||
name: DataSourcePool
|
||||
url: 'jdbc:mysql://172.16.4.8/yobr-daily?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai'
|
||||
user: 'yobr_query'
|
||||
password: 'yobr_query!'
|
||||
sql: 'select password from br_auth_user where account = ? and active = 1'
|
||||
|
||||
attribute-repository:
|
||||
jdbc:
|
||||
- order: 0
|
||||
url: ${cas.authn.jdbc.query[0].url}
|
||||
user: ${cas.authn.jdbc.query[0].user}
|
||||
password: ${cas.authn.jdbc.query[0].password}
|
||||
driver-class: ${cas.authn.jdbc.query[0].driver-class}
|
||||
dialect: ${cas.authn.jdbc.query[0].dialect}
|
||||
single-row: true
|
||||
query-type: OR
|
||||
# 以下属性为查询sql时,当为多个时逗号分隔,
|
||||
# 如填写username,email,sql会变成
|
||||
# select * from sys_user where username=${?} {and/or} email=${?}
|
||||
username: username
|
||||
sql: 'select * from br_auth_user where account = ? and active = 1'
|
||||
attributes:
|
||||
name: name
|
||||
admin: admin
|
||||
account: account
|
||||
active: active
|
||||
accept:
|
||||
# 禁用静态账户
|
||||
users:
|
||||
jdbc:
|
||||
show-sql: true
|
||||
locale:
|
||||
cookie:
|
||||
name: LOCALE
|
||||
default-value: zh-CN
|
||||
service-registry:
|
||||
core:
|
||||
init-from-json: true
|
||||
json:
|
||||
location: classpath:/services
|
||||
view:
|
||||
cas2:
|
||||
v3-forward-compatible: true
|
||||
template-prefixes: file://${work.dir}/src/main/resources/views/
|
||||
webflow:
|
||||
auto-configuration:
|
||||
enabled: true
|
||||
crypto:
|
||||
# 禁用加密,报错
|
||||
enabled: false
|
||||
|
||||
management:
|
||||
endpoint:
|
||||
restart:
|
||||
enabled: false
|
||||
shutdown:
|
||||
enabled: false
|
||||
metrics:
|
||||
enable:
|
||||
logback: false
|
||||
process:
|
||||
files: true
|
||||
export:
|
||||
atlas:
|
||||
enabled: false
|
||||
datadog:
|
||||
enabled: false
|
||||
ganglia:
|
||||
enabled: false
|
||||
graphite:
|
||||
enabled: false
|
||||
influx:
|
||||
enabled: false
|
||||
jmx:
|
||||
enabled: false
|
||||
newrelic:
|
||||
enabled: false
|
||||
prometheus:
|
||||
enabled: false
|
||||
signalfx:
|
||||
enabled: false
|
||||
simple:
|
||||
enabled: true
|
||||
statsd:
|
||||
enabled: false
|
||||
wavefront:
|
||||
enabled: false
|
||||
web:
|
||||
server:
|
||||
request:
|
||||
autotime:
|
||||
enabled: true
|
||||
server:
|
||||
add-application-context-header: false
|
@ -1,46 +0,0 @@
|
||||
# Path to theme CSS file; `/themes/[theme_name]/css/cas.css`.
|
||||
# Multiple files may be comma-separated.
|
||||
cas.standard.css.file=/assets/css/cas.css
|
||||
|
||||
# Path to theme Javascript file; `/themes/[theme_name]/js/js/css`
|
||||
# Multiple files may be comma-separated.
|
||||
cas.standard.js.file=/assets/js/cas.js,/assets/js/material.js
|
||||
|
||||
# Path to theme logo to display via the common layout.
|
||||
# Example: /images/logo.png
|
||||
cas.logo.file=/assets/images/cas-logo.png
|
||||
|
||||
# Decide whether drawer menu should be displayed.
|
||||
cas.drawer-menu.enabled=false
|
||||
|
||||
# The name of this theme used in various titles/captions.
|
||||
# cas.theme.name=Default Theme
|
||||
|
||||
# Whether password management/reset links should be displayed.
|
||||
cas.pm-links.enabled=true
|
||||
|
||||
# When the CAS login form should be displayed.
|
||||
cas.login-form.enabled=true
|
||||
|
||||
# Enable and display the notifications menu.
|
||||
cas.notifications-menu.enabled=false
|
||||
|
||||
# Path to the theme favicon
|
||||
# Example: `/themes/example/images/favicon.ico`
|
||||
# cas.favicon.file=
|
||||
|
||||
# The description for this theme to describe its purpose
|
||||
cas.theme.description=Central Authentication Service
|
||||
|
||||
# Path to a "hero" styled image/logo
|
||||
# that would be displayed on the login form.
|
||||
# cas.hero-banner.file=
|
||||
|
||||
# Whether core/default Javascript libraries
|
||||
# should be included in the theme.
|
||||
# cas.js.core.enabled=true
|
||||
|
||||
# Whether principal/authentication attributes
|
||||
# and other application data should be displayed on the screen
|
||||
# after a successful "generic" authentication event.
|
||||
cas.successful-login.display-attributes=true
|
@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Properties>
|
||||
<Property name="pattern">%-d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%t][%c{1.}] %m%n</Property>
|
||||
<Property name="log.dir">target/.logs</Property>
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%highlight{%-d{yyyy-MM-dd HH:mm:ss,SSS}}{FATAL=magenta, ERROR=magenta, WARN=magenta, INFO=magenta, DEBUG=magenta, TRACE=magenta} %highlight{%-5p}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=black, DEBUG=green bold, TRACE=blue} [%t][%highlight{%c{1.}] %m%n"/>
|
||||
</Console>
|
||||
<RollingFile name="File"
|
||||
fileName="${log.dir}/app.log"
|
||||
filePattern="${log.dir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}-%i.log">
|
||||
<PatternLayout pattern="${pattern}" />
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy />
|
||||
<SizeBasedTriggeringPolicy size="16 MB" />
|
||||
</Policies>
|
||||
<DefaultRolloverStrategy max="32" />
|
||||
</RollingFile>
|
||||
<!-- appender to send mails asynchronously -->
|
||||
<Async name="AsyncFile">
|
||||
<AppenderRef ref="File" />
|
||||
</Async>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="debug" additivity="false">
|
||||
<AppenderRef ref="Console" />
|
||||
<AppenderRef ref="File" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
@ -1,667 +0,0 @@
|
||||
screen.welcome.security=For security reasons, please <a href="logout">log out</a> and exit your web browser when you are done accessing \
|
||||
services that require authentication!
|
||||
screen.welcome.instructions=Enter Username & Password
|
||||
screen.welcome.forcedsso=Welcome back, <code><strong>{0}</strong></code>. We have detected an existing single sign-on session for you. However, \
|
||||
you are being asked to re-authenticate again as CAS cannot successfully accept your previous single sign-on participation status which may be \
|
||||
related to the policy assigned to <code><strong>{1}</strong></code>. Please enter your Username and Password and proceed.
|
||||
screen.welcome.label.source=Source:
|
||||
screen.welcome.label.token=Token:
|
||||
screen.welcome.label.netid=<span class="accesskey">U</span>sername:
|
||||
screen.welcome.label.netid.accesskey=u
|
||||
screen.welcome.label.password=<span class="accesskey">P</span>assword:
|
||||
screen.welcome.label.password.accesskey=p
|
||||
screen.welcome.label.publicstation=I am at a public workstation.
|
||||
screen.welcome.label.warn=<span class="accesskey">W</span>arn me!
|
||||
screen.welcome.label.warn.accesskey=w
|
||||
screen.welcome.label.warnremove=Do not warn me again
|
||||
screen.welcome.button.login=Login
|
||||
screen.welcome.button.logout=Logout
|
||||
screen.welcome.button.loginwip=One moment please...
|
||||
screen.welcome.button.register=Register
|
||||
screen.welcome.button.deregister=Deregister
|
||||
screen.welcome.button.print=Print
|
||||
screen.welcome.button.clear=Clear
|
||||
screen.welcome.button.confirm=Confirm
|
||||
|
||||
screen.welcome.label.loginwith=External Identity Providers
|
||||
screen.welcome.label.navto=Navigating to external identity provider <strong>{0}</strong>. Please wait...
|
||||
screen.welcome.button.loginx509=Login w/ Certificate
|
||||
|
||||
screen.cookies.disabled.title=Cookies Disabled
|
||||
screen.cookies.disabled.message=Your browser does not support cookies. The browser's ability to store or read cookies \
|
||||
is essential for single sign-on to work. Please consult your browser settings and ensure cookie support is turned on.
|
||||
|
||||
screen.acct.button.signUp=Sign Up
|
||||
|
||||
screen.pm.button.submit=Submit
|
||||
screen.pm.button.cancel=Cancel
|
||||
screen.pm.button.forgotpwd=<a href="{0}">Forgot your password? </a>
|
||||
screen.pm.button.resetPassword=Reset your password
|
||||
screen.pm.button.forgotUsername=Forgot your username?
|
||||
screen.pm.reset.username=Username:
|
||||
screen.pm.reset.email=Email:
|
||||
screen.pm.reset.heading=Password Reset Failed
|
||||
screen.pm.reset.message=We were unable to process your password reset request at this time.
|
||||
screen.pm.reset.qstitle=Answer Security Questions
|
||||
screen.pm.reset.qsmsg=Welcome <strong>{0}</strong>. Before you can reset your password, you must answer the following security questions.
|
||||
screen.pm.reset.sentInstructions=You should shortly receive a message with follow-instructions to reset your password. Please do not take \
|
||||
long as the password reset instructions may expire.
|
||||
screen.pm.reset.sent=Password Reset Instructions Sent Successfully.
|
||||
screen.pm.reset.title=Reset your password
|
||||
screen.pm.reset.instructions=Please provide your username. You will receive a notification with follow-up instructions on how to reset your password.
|
||||
screen.pm.reset.answer=Answer {0}
|
||||
screen.pm.reset.question=Question {0}
|
||||
screen.pm.password.policyViolation=Password does not match the password policy requirement.
|
||||
screen.pm.password.confirmMismatch=Passwords do not match.
|
||||
screen.pm.password.strength=Strength:
|
||||
screen.pm.password.strength.0=Worst
|
||||
screen.pm.password.strength.1=Bad
|
||||
screen.pm.password.strength.2=Weak
|
||||
screen.pm.password.strength.3=Good
|
||||
screen.pm.password.strength.4=Strong
|
||||
|
||||
screen.pm.reset.contact.failed=Unable to send email/SMS as no email/SMS server is defined in the CAS configuration.
|
||||
screen.pm.reset.username.required=No email is provided.
|
||||
screen.pm.reset.contact.invalid=Provided contact information is missing or invalid.
|
||||
screen.pm.reset.email.invalid=Provided email address is invalid.
|
||||
screen.pm.reset.username.failed=Failed to send the username to the given email address.
|
||||
|
||||
screen.pm.forgotusername.title=Forgot your username?
|
||||
screen.pm.forgotusername.instructions=Please provide your email address. You will receive an email with your username.
|
||||
screen.pm.forgotusername.email.failed=Unable to send email as no email server is defined in the CAS configuration.
|
||||
screen.pm.forgotusername.email.invalid=No email is provided, or the given address is invalid.
|
||||
screen.pm.forgotusername.contact.invalid=Provided email address or phone number is invalid.
|
||||
screen.pm.forgotusername.username.missing=No username could be located for the given email address.
|
||||
screen.pm.forgotusername.username.failed=Failed to send the username to the given email address.
|
||||
screen.pm.forgotusername.sent=Instructions Sent Successfully.
|
||||
screen.pm.forgotusername.sentInstructions=You should shortly receive a message with follow-instructions to how to retrieve your username.
|
||||
|
||||
screen.aup.heading=Acceptable Usage Policy
|
||||
screen.aup.policyterms=<p>The purpose of this policy is to establish acceptable and unacceptable use of electronic devices \
|
||||
and network resources in conjunction with the established culture of ethical and lawful behavior, openness, trust, and integrity.</p> \
|
||||
<p>By using these resources, you agree to abide by the Acceptable Usage Policy.</p>
|
||||
|
||||
screen.aup.button.accept=ACCEPT
|
||||
screen.aup.button.cancel=CANCEL
|
||||
|
||||
screen.saml.idp.discovery=SAML2 Identity Provider Discovery
|
||||
|
||||
screen.consent.confirm=Confirm
|
||||
screen.consent.cancel=Cancel
|
||||
screen.consent.title=Attribute Consent
|
||||
screen.consent.attributes=Attributes
|
||||
screen.consent.options=Options
|
||||
screen.consent.attributes.header=The following attributes will be released to <strong>[{0}]</strong>:
|
||||
screen.consent.attributes.attribute=Attribute
|
||||
screen.consent.attributes.values=Value(s)
|
||||
|
||||
screen.consent.options.header=How should I be prompted for consent again?
|
||||
screen.consent.options.always=<strong>Every Time</strong>
|
||||
screen.consent.options.desc.always=Show the consent screen every time I attempt to log into {0}.
|
||||
screen.consent.options.attributename=<strong>Attribute Name</strong>
|
||||
screen.consent.options.desc.attributename=Show the consent screen, if an attribute is added or removed from the collection of attributes released to {0}.
|
||||
screen.consent.options.attributevalue=<strong>Attribute Value</strong>
|
||||
screen.consent.options.desc.attributevalue.intro=Show the consent screen, if:
|
||||
screen.consent.options.desc.attributevalue.first=A new attribute is authorized for release to {0}.
|
||||
screen.consent.options.desc.attributevalue.second=An attribute is removed from the attribute bundle previously released to {0}.
|
||||
screen.consent.options.desc.attributevalue.third=The value of an attribute authorized for release to {0} has changed.
|
||||
screen.consent.options.reminder.header=How often should I be reminded to consent again?
|
||||
screen.consent.options.reminder.expl=Show the consent screen, as a reminder, in the event that there is no change to the collection of attributes released to {0}.
|
||||
screen.consent.options.timeunit.seconds=Seconds
|
||||
screen.consent.options.timeunit.minutes=Minutes
|
||||
screen.consent.options.timeunit.hours=Hours
|
||||
screen.consent.options.timeunit.days=Days
|
||||
screen.consent.options.timeunit.weeks=Weeks
|
||||
screen.consent.options.timeunit.months=Months
|
||||
screen.consent.options.timeunit.years=Years
|
||||
|
||||
screen.consent.review.header=Review Attribute Consent
|
||||
screen.consent.review.loading=Loading consent decisions...
|
||||
screen.consent.review.noconsentdecisions=There are no consent decisions registered for you.
|
||||
screen.consent.review.success=Consent decision was deleted successfully.
|
||||
screen.consent.review.error=There was an error!
|
||||
screen.consent.review.confirm=Delete consent decision for [{}]?
|
||||
screen.consent.review.yes=Yes
|
||||
screen.consent.review.no=No
|
||||
screen.consent.review.date=Date
|
||||
screen.consent.review.service=Service
|
||||
screen.consent.review.delete=DELETE
|
||||
screen.consent.review.createddate=Created Date:
|
||||
screen.consent.review.reminder=Reminder:
|
||||
screen.consent.review.option=Option:
|
||||
screen.consent.review.options.attributename=Attribute Name
|
||||
screen.consent.review.options.attributevalue=Attribute Value
|
||||
screen.consent.review.options.always=Always
|
||||
screen.consent.review.options.desc.always=Show the consent screen every time I attempt to log in.
|
||||
screen.consent.review.options.desc.attributename=Show the consent screen, if an attribute is added or removed from the collection of attributes released.
|
||||
screen.consent.review.options.desc.attributevalue=Show the consent screen, if 1) a new attribute is authorized for release, 2) an attribute is removed from the attribute bundle previously released, 3) the value of an attribute authorized for release has changed.
|
||||
screen.consent.review.attributes=Attributes:
|
||||
screen.consent.review.data.search=Search
|
||||
screen.consent.review.data.zerorecords=No matching decisions found
|
||||
screen.consent.review.data.info=Showing _START_ to _END_ of _TOTAL_ entries
|
||||
screen.consent.review.data.infofiltered=(filtered from _MAX_ total entries)
|
||||
screen.consent.review.data.infoempty=No decisions to show
|
||||
screen.consent.review.logout.success=You have successfully logged out of the Consent Review page. You may completely <a href="../logout">log out</a> of the Central Authentication Service and end your single sign-on session.
|
||||
|
||||
screen.nonsecure.title=Non-secure Connection
|
||||
screen.nonsecure.message=You are currently accessing CAS over a non-secure connection. Single Sign On WILL NOT WORK. In order to have single sign on work, you MUST log in over HTTPS.
|
||||
|
||||
screen.accountunlocked.heading=Your account is now unlocked.
|
||||
screen.account.unlock.description=Your account has been locked and is unable to login. Please follow the instructions \
|
||||
on the screen to unlock your account and then try to login again.
|
||||
screen.account.unlock.label=Image Text
|
||||
screen.account.unlock.hint=To continue, please enter the characters as you see in the image.
|
||||
screen.account.unlock.fail=CAS is unable to reset and unlock your account. Contact your CAS administrator for more info.
|
||||
screen.account.unlock.success=Your account status is now unlocked. Note that this change might take some time to fully take effect. \
|
||||
You should now be able to login and proceed.
|
||||
|
||||
screen.defaultauthn.title=Static Authentication
|
||||
screen.defaultauthn.heading=CAS is configured to accept a static list of users for primary authentication. This is <strong>ONLY</strong> useful for \
|
||||
demo purposes. It is recommended that you connect CAS to LDAP, JDBC, etc instead.
|
||||
logo.title=go to Apereo home page
|
||||
copyright=Copyright © 2005–2022 Apereo, Inc.
|
||||
screen.capslock.on = CAPSLOCK key is turned on!
|
||||
screen.button.continue=Continue
|
||||
screen.post.response.message=You are being redirected to {0}.
|
||||
|
||||
screen.interrupt.title=Authentication Interrupt
|
||||
screen.interrupt.message=The authentication flow has been interrupted for <strong>{0}</strong>.
|
||||
|
||||
screen.mdui.infolink.text=<a href="{0}" target="_blank">More information about this application</a>.
|
||||
screen.mdui.privacylink.text=<a href="{0}" target="_blank">Privacy statement for application</a>.
|
||||
|
||||
screen.interrupt.btn.proceed=Proceed
|
||||
screen.interrupt.btn.cancel=Cancel
|
||||
|
||||
# Generic Error Pages 401, 404, 500, etc
|
||||
########################################
|
||||
screen.error.page.heading=Error
|
||||
screen.error.page.invalidrequest.title=Unknown Request
|
||||
screen.error.page.invalidrequest.desc=The authentication request submitted to CAS is invalid, incorrectly constructed, \
|
||||
or contains parameters that are seen as invalid or expired. Please review the original request, consult CAS logs and try again.
|
||||
screen.error.page.invalidrequest=Invalid/Unknown Request
|
||||
screen.error.page.title.accessdenied=Error - 401
|
||||
screen.error.page.title.permissiondenied=Error - Permission Denied
|
||||
screen.error.page.title.pagenotfound=Error - Page Not Found
|
||||
screen.error.page.title.requestunsupported=Error - Unsupported Request
|
||||
screen.error.page.accessdenied=Access Denied
|
||||
screen.error.page.permissiondenied=You do not have permission to view this page.
|
||||
screen.error.page.requestunsupported=The request type or syntax is not supported.
|
||||
screen.error.page.loginagain=Login Again
|
||||
screen.error.page.notfound=Page Not Found
|
||||
screen.error.page.doesnotexist=The page you are attempting to access does not exist at the moment.
|
||||
screen.error.page.authdenied=Authorization Denied
|
||||
|
||||
# Remember-Me Authentication
|
||||
screen.rememberme.checkbox.title=Remember Me
|
||||
|
||||
# Gua
|
||||
screen.gua.confirm.message=If you do not recognize this image as yours, do NOT continue.
|
||||
|
||||
# Blocked Errors Page
|
||||
screen.error.page.title.blocked=Error - Permission Denied
|
||||
screen.blocked.header=Access Denied
|
||||
screen.blocked.message=You've entered the wrong password for the user too many times. You've been throttled.
|
||||
AbstractAccessDecisionManager.accessDenied=You are not authorized to access this resource. Contact your CAS administrator for more info.
|
||||
|
||||
# Confirmation Screen Messages
|
||||
screen.confirmation.message=You asked to be warned before logging into applications. Please proceed.
|
||||
screen.authentication.warning=Authentication Succeeded with Warnings
|
||||
|
||||
# Account Profile Messages
|
||||
screen.account.success=You, <strong>{0}</strong>, have successfully logged into the Central Authentication Service. This page allows you to \
|
||||
review and manage your account profile and verify the collection of person attributes retrieved by CAS.
|
||||
screen.account.security=When you are finished, for security reasons, please <a href="logout">log out</a> and exit your web browser.
|
||||
screen.account.tooltip.logout=This operation forces a logout prior to changing the password.
|
||||
screen.account.failure=Operation Failure
|
||||
screen.account.securityquestions.subtitle=You can review and update your security questions here. \
|
||||
Remember that all security questions and answers <strong>MUST</strong> be unique. \
|
||||
Duplicate questions or answers are rejected by CAS.
|
||||
screen.account.mfadevices.title=Multifactor Authentication Devices
|
||||
screen.account.mfadevices.subtitle=The following devices are registered under your account and may be used for multifactor authentication.
|
||||
screen.account.auditlog.title=Audit Log
|
||||
screen.account.auditlog.subtitle=Examine your audited authentication activity as recorded and captured by CAS.
|
||||
screen.account.securityquestions.title=Manage Security Questions
|
||||
screen.account.securityquestions.failure=Unable to accept and update your security questions.
|
||||
screen.account.securityquestions.success=Security questions are now accepted and updated successfully.
|
||||
screen.account.sessions=Review your active single sign-on sessions registered with CAS across all your devices and browsers.
|
||||
screen.account.applications=There are applications registered with CAS for which CAS is authorized to allow you access.
|
||||
screen.account.attributes=These are the attributes that CAS has found and attached to your authenticated profile. \
|
||||
These attributes are included in the pool of available attributes that may be shared and released to applications.
|
||||
screen.account.consent.title=Attribute Consent Decisions
|
||||
screen.account.consent.subtitle=These are the attribute consent decisions that CAS has found and attached to your authenticated profile.
|
||||
screen.account.consent.always=Always
|
||||
screen.account.consent.attribute_name=Attribute Name Changes
|
||||
screen.account.consent.attribute_value=Attribute Value Changes
|
||||
|
||||
# Generic Success Screen Messages
|
||||
screen.success.header=Log In Successful
|
||||
screen.success.success=You, <strong>{0}</strong>, have successfully logged into the Central Authentication Service. However, you are seeing \
|
||||
this page because CAS does not know about your target destination and how to get you there. Examine the authentication request again and \
|
||||
make sure a target service/application that is authorized and registered with CAS is specified.
|
||||
screen.success.security=When you are finished, for security reasons, please <a href="logout">log out</a> and exit your web browser.
|
||||
|
||||
# Logout Screen Messages
|
||||
screen.logout.confirm.header=Do you, <strong>{0}</strong>, want to log out completely?
|
||||
screen.logout.confirm.text=<p>An application may have redirected you to the Central Authentication Service \
|
||||
to completely log you out and destroy your single sign-on session. If you choose to log out, you will be asked again \
|
||||
to provide your credentials and login again once you attempt to access an application.</p>
|
||||
screen.logout.confirm.proceed=Do you want to proceed?
|
||||
|
||||
screen.logout.header=Logout successful
|
||||
screen.logout.success=You have successfully logged out of the Central Authentication Service. You may <a href="login">log in</a> again.
|
||||
screen.logout.fc.success=You have successfully logged out of the Central Authentication Service. Given single logout is enabled with CAS, \
|
||||
the following list of applications are <strong> only notified</strong> to log you out and destroy your user session. Remember that this \
|
||||
is just a notification, not a guarantee. It is up the application itself to honor these notifications and properly take action to log you \
|
||||
out.
|
||||
screen.logout.security=For security reasons, exit your web browser.
|
||||
|
||||
screen.service.sso.error.header=Re-Authentication Required to Access this Service
|
||||
screen.service.sso.error.message=You attempted to access a service that requires authentication without re-authenticating. Please try authenticating again</a>.
|
||||
screen.service.required.message=You attempted authentication without specifying the target application. Please re-examine the request and try again.
|
||||
screen.service.initial.message=Attempting to access CAS or the indicated target application is disallowed at this time. \
|
||||
The authentication policy requires that you change your starting application \
|
||||
and then move onto other applications and services.
|
||||
|
||||
captchaError=reCAPTCHA validation failed.
|
||||
username.required=Username is a required field.
|
||||
password.required=Password is a required field.
|
||||
source.required=Authentication source is a required field.
|
||||
|
||||
# Password Management
|
||||
confirmedPassword.required=Password must be confirmed.
|
||||
pm.passwordsMustMatch=Provided passwords do not match.
|
||||
pm.passwordFailedCriteria=Provided password does not satisfy the password security policy. Please try again.
|
||||
pm.updateFailure=Account password could not be modified. Please try again.
|
||||
|
||||
# Authentication failure messages
|
||||
authenticationFailure.AccountDisabledException=This account has been disabled.
|
||||
authenticationFailure.AccountLockedException=This account has been locked.
|
||||
authenticationFailure.AccountExpiredException=This account has expired and is forbidden to login at this time.
|
||||
authenticationFailure.CredentialExpiredException=Your password has expired.
|
||||
authenticationFailure.InvalidLoginLocationException=You cannot login from this workstation.
|
||||
authenticationFailure.UniquePrincipalRequiredException=You cannot login at this time, since you have another active single sign-on session in progress \
|
||||
and CAS is configured with an authentication policy the prevents multiple concurrent single sign-on sessions.
|
||||
authenticationFailure.InvalidLoginTimeException=Your account is forbidden to login at this time.
|
||||
authenticationFailure.AccountNotFoundException=Your account is not recognized and cannot login at this time.
|
||||
authenticationFailure.FailedLoginException=Authentication attempt has failed, likely due to invalid credentials. Please verify and try again.
|
||||
authenticationFailure.MultifactorAuthenticationProviderAbsentException=Unable to satisfy multifactor authentication requirements. \
|
||||
Your account is configured for a multifactor authentication strategy, yet CAS is unable to locate and execute that strategy \
|
||||
most likely due to misconfiguration of the server. Contact the service administrators for assistance.
|
||||
authenticationFailure.SurrogateAuthenticationException=You are not authorized to impersonate the indicated user at this time.
|
||||
authenticationFailure.AccountPasswordMustChangeException=Your account password has expired and must be changed.
|
||||
authenticationFailure.UnauthorizedServiceForPrincipalException=Service access denied due to missing privileges.
|
||||
authenticationFailure.MultifactorAuthenticationRequiredException=Authentication attempt for your account is denied, \
|
||||
because your account is not yet configured to go through multifactor authentication. Contact the service administrators \
|
||||
for assistance, make sure your account is enrolled and eligible for multifactor authentication and try again.
|
||||
authenticationFailure.UNKNOWN=Authentication attempt has failed.
|
||||
authenticationFailure.AuthenticationException=Credentials are rejected/invalid and authentication attempt has failed.
|
||||
|
||||
INVALID_REQUEST_PROXY=The request is incorrectly formatted. Ensure all required parameters are properly encoded and included.
|
||||
INVALID_TICKET_SPEC=Ticket failed validation specification. Possible errors could include attempting to validate a Proxy Ticket via a Service Ticket validator, or not complying with the renew true request.
|
||||
INVALID_REQUEST=Unable to identify, authorize or complete this request, likely due to malformed or missing required parameters.
|
||||
INVALID_AUTHENTICATION_CONTEXT=The validation request for [''{0}''] cannot be satisfied. The request is either unrecognized or unfulfilled.
|
||||
INVALID_TICKET=Ticket ''{0}'' not recognized
|
||||
INVALID_PROXY_GRANTING_TICKET=PGT already generated for this ST. Cannot grant more than one PGT for ST
|
||||
INVALID_SERVICE=Ticket ''{0}'' does not match supplied service. The original service was ''{1}'' and the supplied service was ''{2}''.
|
||||
INVALID_PROXY_CALLBACK=The supplied proxy callback url ''{0}'' could not be authenticated. Either ''{0}'' cannot be reached, it is not \
|
||||
allowed to exercise proxy authentication.
|
||||
UNAUTHORIZED_SERVICE_PROXY=The supplied service ''{0}'' is not authorized to use CAS proxy authentication.
|
||||
UNSATISFIED_AUTHN_POLICY=Service access denied due to an unsatisfied authentication policy.
|
||||
INVALID_AUTHN_REQUEST=Authentication attempt has failed, likely due to invalid credentials.
|
||||
BLOCKED_AUTHN_REQUEST=Authentication attempt is blocked and cannot proceed, likely due to malformed or missing required parameters. \
|
||||
Examine the CAS server logs to locate the root cause of the error.
|
||||
UNSATISFIED_SAML_REQUEST=The SAML authentication request cannot be understood, accepted or validated by CAS, \
|
||||
likely due to malformed or missing required parameters. Please examine the CAS server logs to locate the root cause of the error
|
||||
|
||||
screen.service.error.header=Application Not Authorized to Use CAS
|
||||
service.principal.resolution.error=CAS is unable to determine the correct authentication principal. \
|
||||
Either the principal could not be resolved correctly as a single unique entity or CAS has found \
|
||||
mixed/multiple candidate principals and is unable to decide which should be used. \
|
||||
This error may also be caused if the authenticated principal is not allowed to access the target application \
|
||||
due to missing privileges set by the CAS server authorization policies.
|
||||
service.not.authorized.missing.attr=You are not authorized to access the application as your account \
|
||||
is missing privileges required by the CAS 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 CAS. \
|
||||
This usually indicates that the application is not registered with CAS, or its authorization policy defined in its registration record \
|
||||
prevents it from leveraging CAS functionality, or it's malformed and unrecognized by CAS. \
|
||||
Contact your CAS administrator to learn how you might register and integrate your application with CAS.
|
||||
screen.service.empty.error.message=The services registry of CAS is empty and has no service definitions. \
|
||||
Applications that wish to authenticate with CAS must explicitly be defined in the services registry.
|
||||
screen.service.expired.message=The application you attempted to authenticate to has been expired in the CAS Service Registry. \
|
||||
If this service should still be considered in use, please contact the service administrators to have the application renewed.
|
||||
# Surrogate Account Selection
|
||||
screen.surrogates.account.selection.header=Impersonation Account Selection
|
||||
screen.surrogates.choose.account=Choose Account
|
||||
screen.surrogates.message=<p>You are provided with a list of accounts on behalf of which you are allowed to authenticate.</p> \
|
||||
<p>Select one and continue.</p>
|
||||
screen.surrogates.button.cancel=Cancel
|
||||
screen.surrogates.account.selection.error=You are not authorized to impersonate the indicated user at this time.
|
||||
screen.surrogates.wildcard.title=Impersonation Account Selection
|
||||
screen.surrogates.wildcard.description=Your account is internally recognized by CAS as one with special permissions, \
|
||||
authorized to impersonate all users and accounts. Therefor, impersonation account selection is not allowed for your \
|
||||
account. Instead, you may directly proceed to login and impersonate any other account using its username.
|
||||
|
||||
# Password policy
|
||||
password.expiration.warning=Your password expires in {0} day(s). Please <a href="https://pm.example.edu">change your password</a> now.
|
||||
password.expiration.loginsRemaining=You have {0} login(s) remaining before you <strong>MUST</strong> change your password.
|
||||
screen.accountdisabled.heading=This account has been disabled.
|
||||
screen.accountdisabled.message=Please contact the system administrator to regain access.
|
||||
screen.accountlocked.heading=This account has been locked.
|
||||
screen.accountlocked.message=Please contact the system administrator to regain access.
|
||||
screen.expiredpass.heading=Hello, {0}. Your password has expired.
|
||||
screen.expiredpass.message=Please <a href="{0}">change your password</a>.
|
||||
screen.mustchangepass.heading=Hello, {0}. You must change your password.
|
||||
screen.mustchangepass.message=Please <a href="{0}">change your password</a>.
|
||||
screen.badhours.heading=Your account is forbidden to login at this time.
|
||||
screen.badhours.message=Please try again later.
|
||||
screen.authnblocked.heading=Authentication attempt is blocked.
|
||||
screen.authnblocked.message=Your authentication attempt is untrusted and unauthorized from your current workstation.
|
||||
screen.risk.authnblocked.heading=Authentication attempt is blocked.
|
||||
screen.risk.authnblocked.message=Your authentication attempt is untrusted and unauthorized from your current workstation.
|
||||
screen.badworkstation.heading=You cannot login from this workstation.
|
||||
screen.badworkstation.message=Please contact the system administrator to regain access.
|
||||
screen.button.changePassword=Change Password
|
||||
|
||||
screen.pm.success.header=Password Change Successful
|
||||
screen.pm.success.message=Your account password is successfully updated.
|
||||
|
||||
screen.pm.confirmpsw=Confirm Password:
|
||||
screen.pm.enterpsw=Enter Password:
|
||||
|
||||
screen.pac4j.authn.TechnicalException=Unable to locate or parse identity provider configuration, most likely due to misconfiguration. \
|
||||
Review logs to find the root cause of the issue.
|
||||
screen.pac4j.authn.unknown=Authentication response provided to CAS by the external identity provider cannot be accepted.
|
||||
screen.pac4j.unauthz.pagetitle=Unauthorized Access
|
||||
screen.pac4j.unauthz.gotoapp=Go to Application
|
||||
screen.pac4j.unauthz.login=Back to CAS
|
||||
screen.pac4j.unauthz.heading=Unauthorized Access
|
||||
screen.pac4j.unauthz.message=Either the authentication request was rejected/cancelled, or the authentication provider denied access due \
|
||||
to permissions, etc. Review logs to find the root cause of the issue.
|
||||
screen.pac4j.button.retry=Try Again
|
||||
screen.pac4j.discovery.intro=Please provide your username or email address so CAS can locate the correct identity provider for your account.
|
||||
screen.pac4j.discovery.unknownclient=Delegated identity provider cannot be found based for this request.
|
||||
screen.pac4j.button.selectprovider=Select Identity Provider
|
||||
screen.pac4j.discovery.title=Delegated Authentication Dynamic Discovery
|
||||
screen.pac4j.authn.SAMLException=Authentication response provided to CAS by the external identity provider cannot be accepted. \
|
||||
Please examine the CAS server logs and configuration to locate the root cause of the issue, and then try again.
|
||||
screen.pac4j.authn.SAMLIssueInstantException=Authentication response provided to CAS by the external identity provider cannot be accepted \
|
||||
because the authentication issue instant, given the present CAS configuration, is either too old or set in the future.
|
||||
|
||||
screen.pac4j.credential-selection.title=Delegated Authentication Profile Selection
|
||||
screen.pac4j.credential-selection.intro=CAS has found multiple profiles associated with your user account. Please choose the account \
|
||||
with which you wish to login and proceed.
|
||||
|
||||
screen.delauthn.error.header=Delegated Authentication Failure
|
||||
screen.delauthn.error.message=CAS is unable to complete the delegated authentication scenario, \
|
||||
or redirect to the selected identity provider. Please examine the original authentication request and try again. \
|
||||
You may need to close your browser and start again.
|
||||
|
||||
# GAuth
|
||||
screen.authentication.gauth.register=Your account is not registered. Use the below settings to register your device with CAS.
|
||||
screen.authentication.gauth.key=Secret key to register is: <pre>{0}</pre>
|
||||
screen.authentication.gauth.scratchcodes=Scratch codes:
|
||||
screen.authentication.gauth.selecteddevice=Your selected device for multifactor authentication is: <code>{0}</code>.
|
||||
screen.authentication.gauth.selanotherdevice=You can select another device for multifactor authentication, if <code>{0}</code> is not your current device.
|
||||
screen.authentication.gauth.name=Device Name:
|
||||
screen.authentication.gauth.cancel=Cancel
|
||||
screen.authentication.gauth.reganotherdevice=You can also register another device to use for multifactor authentication.
|
||||
screen.authentication.gauth.selectdevice=Select Device
|
||||
screen.authentication.gauth.deletedevice=Delete Device
|
||||
screen.authentication.gauth.invalid=Unable to accept this authentication request. The selected device or given credentials is invalid.
|
||||
screen.authentication.gauth.invalidtoken=Unable to accept this token. The given token is invalid, does not belong to the device or has expired.
|
||||
screen.authentication.gauth.confirm.title=Confirm Account Registration
|
||||
screen.authentication.gauth.confirm.desc=Confirm your account registration by providing a token \
|
||||
from the authenticator app on your device. Once the token is validated, your account registration will be finalized.
|
||||
|
||||
screen.welcome.button.register-residentkey=Register Device with Discoverable Credentials
|
||||
screen.authentication.webauthn.confirm.title=Confirm Account Registration
|
||||
screen.authentication.webauthn.confirm.desc=Start the device registration process by assigning a friendly name to your FIDO2-enabled device.
|
||||
screen.authentication.webauthn.name=Device Name
|
||||
screen.authentication.webauthn.login.title=Login with FIDO2-enabled Device
|
||||
screen.authentication.webauthn.login.desc=Use your registered FIDO2-enabled device to login. \
|
||||
To successfully perform this action, your username and device must already be registered with CAS.
|
||||
screen.authentication.webauthn.authn.fail.title=Authentication Failed
|
||||
screen.authentication.webauthn.authn.fail.desc=The authentication attempt has failed. Please make sure \
|
||||
your username and chosen device are registered with CAS.
|
||||
|
||||
# OAuth
|
||||
screen.oauth.confirm.header=Authorization
|
||||
screen.oauth.confirm.message=Do you want to grant access to "{0}" ?
|
||||
screen.oauth.confirm.allow=Allow
|
||||
screen.oauth.confirm.deny=Deny
|
||||
cas.oauth.confirm.pagetitle=Approve Access
|
||||
|
||||
cas.oauth.device.confirm.header=Connect Device
|
||||
cas.oauth.device.confirm.message=Enter the code displayed on your device to proceed.
|
||||
|
||||
cas.oauth.device.confirmed.header=Code Approved
|
||||
cas.oauth.device.confirmed.message=Return to your device to continue.
|
||||
|
||||
cas.oauth.error.pagetitle=OAuth Error
|
||||
cas.oauth.error.header=OAuth Authorization Error
|
||||
OAUTH_BAD_SESSION_REQUEST=The OAuth request cannot be completed, as CAS is unable to locate or determine OAuth redirect URL. \
|
||||
This is usually an indication of a stale or mismatched request where the processed request session id is different from the \
|
||||
active session and may be caused by an complete logout operation. Clear cookies and history, restart your browser and try again please.
|
||||
|
||||
# OIDC
|
||||
screen.oidc.confirm.infourl=Learn more about {0}.
|
||||
screen.oidc.confirm.privacyurl=Learn about {0} privacy rules.
|
||||
screen.oidc.confirm.scopes=Scopes
|
||||
screen.oidc.confirm.claims=Claims
|
||||
screen.oidc.confirm.scope.profile=This requests access to the profile claims excluding the address and email claims.
|
||||
screen.oidc.confirm.scope.email=This requests access to the email claims.
|
||||
screen.oidc.confirm.scope.address=This requests access to the address claims.
|
||||
screen.oidc.confirm.scope.openid=This indicates an OpenID Connect authorization request.
|
||||
screen.oidc.confirm.scope.phone=This requests access to the phone claims.
|
||||
screen.oidc.confirm.scope.offline_access=This requests access for a refresh token used for offline access.
|
||||
|
||||
|
||||
screen.oidc.confirm.claim.name=End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.
|
||||
screen.oidc.confirm.claim.given_name=Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.
|
||||
screen.oidc.confirm.claim.middle_name=Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used.
|
||||
screen.oidc.confirm.claim.family_name=Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.
|
||||
screen.oidc.confirm.claim.email=End-User's preferred e-mail address.
|
||||
screen.oidc.confirm.claim.preferred_username=MAY be any valid JSON string including special characters such as @, /, or whitespace. The RP MUST NOT rely upon this value being unique.
|
||||
screen.oidc.confirm.claim.profile=URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User.
|
||||
screen.oidc.confirm.claim.picture=URL of the End-User's profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.
|
||||
screen.oidc.confirm.claim.phone_number=End-User's preferred telephone number. It is RECOMMENDED as the format of this claim. \
|
||||
For example, <code>+1 (425) 555-1212</code> or <code>+56 (2) 687 2400</code>.
|
||||
|
||||
screen.oidc.confirm.asksinfo=The client is asking for the following information:
|
||||
screen.oidc.confirm.dynamic=This client was dynamically registered at <code>{0}</code>.
|
||||
|
||||
# Unavailable
|
||||
screen.unavailable.header=CAS error
|
||||
screen.unavailable.heading=CAS is unable to process this request: "{0}:{1}"
|
||||
screen.unavailable.message=There was an error trying to complete your request. \
|
||||
<strong>Please notify your support desk or try again.</strong> \
|
||||
<div>Apereo is a non-profit open source software governance foundation. The CAS software is an Apereo sponsored project \
|
||||
and is freely downloadable and usable by anyone. However, Apereo does not operate the systems of anyone using the \
|
||||
software and in most cases doesn't even know who is using it or how to contact them unless they are an active part \
|
||||
of the Apereo community.<br/></br>If you are having problems logging in using CAS, \
|
||||
<strong>you will need to contact the IT staff or Help Desk of your organization for assistance</strong>. \
|
||||
<br/><br/>We wish we could be more directly helpful to you.</div>
|
||||
|
||||
screen.mfaDenied.header=MFA Denied
|
||||
screen.mfaDenied.heading=MFA attempt has been denied by provider
|
||||
screen.mfaDenied.message=Your MFA provider has denied your attempt at second factor \
|
||||
authentication. Contact your system administrator for help in restoring your account.
|
||||
|
||||
screen.mfaUnavailable.header=MFA Provider Unavailable
|
||||
screen.mfaUnavailable.heading=MFA Provider Unavailable
|
||||
screen.mfaUnavailable.message=CAS was unable to reach your configured MFA provider at this time. \
|
||||
Due to failure policies configured for the service you are attempting to access, authentication can not \
|
||||
be granted at this time.
|
||||
|
||||
#####################################################################
|
||||
# Login View
|
||||
#####################################################################
|
||||
#Resources Labels
|
||||
cas.login.pagetitle=Login
|
||||
cas.login.resources.header=Resources
|
||||
cas.login.resources.wiki=Documentation
|
||||
cas.login.resources.endpoints=Actuator Endpoints
|
||||
cas.login.resources.pulls=Pull Requests
|
||||
cas.login.resources.mailinglist=Mailing Lists
|
||||
cas.login.resources.chat=Chatroom
|
||||
cas.login.resources.blog=Blog
|
||||
cas.login.resources.support=Support
|
||||
cas.login.resources.contribguide=Contributor Guidelines
|
||||
|
||||
####
|
||||
# Acceptable Usage Policy View
|
||||
#
|
||||
cas.acceptableusagepolicyview.pagetitle=Acceptable Usage Policy View
|
||||
|
||||
##
|
||||
# MFA
|
||||
##
|
||||
cas.mfa.providerselection.pagetitle=Multifactor Provider Selection
|
||||
|
||||
cas.mfa.providerselection.mfa-duo=Duo Security
|
||||
cas.mfa.providerselection.mfa-duo.notes=Duo's wide variety of authentication methods enable every user to \
|
||||
securely and quickly log in. Duo Push, sent by the Duo Mobile authentication app, allows users to approve \
|
||||
push notifications to verify their identity.
|
||||
|
||||
cas.mfa.providerselection.mfa-webauthn=FIDO2 WebAuthn
|
||||
cas.mfa.providerselection.mfa-webauthn.notes=WebAuthn is an API that makes it very easy for a relying party, \
|
||||
such as a web service, to integrate strong authentication into applications using support built in to all \
|
||||
leading browsers and platforms.
|
||||
|
||||
cas.mfa.providerselection.mfa-gauth=Google Authenticator
|
||||
cas.mfa.providerselection.mfa-gauth.notes=Google Authenticator is a software-based authenticator that \
|
||||
implements two-step verification services for authenticating users of mobile applications by Google.
|
||||
cas.mfa.providerselection.mfa-simple=CAS Multifactor Authentication
|
||||
cas.mfa.providerselection.mfa-simple.notes=Allow CAS to act as a multifactor authentication provider on its own, \
|
||||
issuing tokens and sending them to end-users via pre-defined communication channels such as email or text messages.
|
||||
cas.mfa.providerselection.mfa-yubikey=YubiKey Multifactor Authentication
|
||||
cas.mfa.providerselection.mfa-yubikey.notes=Yubico is a cloud-based service that enables strong, easy-to-use \
|
||||
and affordable two-factor authentication with one-time passwords through their flagship product, YubiKey.
|
||||
cas.mfa.providerselection.mfa-u2f=YubiKey Multifactor Authentication
|
||||
cas.mfa.providerselection.mfa-u2f.notes=U2F is an open authentication standard that enables internet users \
|
||||
to securely access any number of online services, with one single device, instantly and with no drivers, or client software needed.
|
||||
|
||||
cas.mfa.duologin.pagetitle=Duo Security Login
|
||||
|
||||
cas.mfa.simple.pagetitle=CAS Multifactor Authentication Login
|
||||
cas.mfa.simple.label.token=Token:
|
||||
cas.mfa.simple.label.resend=Resend
|
||||
cas.mfa.simple.label.tokensent=A multifactor authentication token is sent to you via an email or text message. \
|
||||
Please locate the token and submit it here to continue. Note that the token will expire after a short period of time \
|
||||
and will no longer be recognized by CAS, in which case, you may ask CAS to send you a new token.
|
||||
|
||||
cas.mfa.googleauth.pagetitle=Google Authenticator
|
||||
cas.mfa.googleauth.label.token=Token:
|
||||
|
||||
cas.mfa.radius.pagetitle=Radius Authentication
|
||||
|
||||
screen.authentication.yubikey.reganotherdevice=You can also register another device to use for multifactor authentication.
|
||||
screen.authentication.yubikey.name=Device Name:
|
||||
cas.mfa.yubikey.pagetitle=YubiKey Authentication
|
||||
cas.mfa.yubikey.authenticate=Use your registered YubiKey device(s) to authenticate.
|
||||
cas.mfa.yubikey.register=Your device is not yet registered. Use the below form to register your device with CAS.
|
||||
cas.mfa.yubikey.register.fail=Unable to register your YubiKey device for authentication. Provided token may be invalid, expired or otherwise compromised.
|
||||
cas.mfa.yubikey.label.token=Token:
|
||||
|
||||
cas.mfa.u2f.pagetitle=U2F Authentication
|
||||
cas.mfa.u2f.authentication.device=Authenticate Device
|
||||
cas.mfa.u2f.authentication.message=<p><strong>Please touch the flashing U2F device now.</strong></p><p> You may be prompted to allow \
|
||||
the site permission to access your security keys. After granting permission, the device will start to blink.</p>
|
||||
cas.mfa.u2f.register.device=Register Device
|
||||
cas.mfa.u2f.register.message=<p><strong>Please touch the flashing U2F device now.</strong></p><p> You may be prompted to allow \
|
||||
the site permission to access your security keys. After granting permission, the device will start to blink.</p>
|
||||
|
||||
cas.mfa.webauthn.auth.fail=Unable to verify your device for authentication. Provided payloads may be invalid, expired or otherwise compromised.
|
||||
|
||||
cas.mfa.authy.pagetitle=Authy Login
|
||||
cas.mfa.authy.error.authn=We are unable to contact Authy. CAS authentication attempt has failed. Your account may have been locked \
|
||||
and disabled for too many incorrect attempts. Please contact your CAS administrator for more info.
|
||||
|
||||
cas.mfa.swivel.pagetitle=Swivel Authentication
|
||||
cas.mfa.swivel.label.token=Token:
|
||||
cas.mfa.swivel.label.header=Swivel Authentication
|
||||
|
||||
cas.mfa.registerdevice.label.title=Register Device
|
||||
cas.mfa.registerdevice.label.intro=Please name the current device.
|
||||
cas.mfa.registerdevice.pagetitle=Register Device
|
||||
cas.mfa.registerdevice.label.name=Name
|
||||
cas.mfa.registerdevice.label.duration=How long should we remember this device?
|
||||
cas.mfa.registerdevice.label.expiration=Expiration
|
||||
cas.mfa.registerdevice.button.register=Register
|
||||
cas.mfa.registerdevice.button.skip=Skip
|
||||
cas.mfa.registerdevice.options.timeunit.forever=Forever
|
||||
|
||||
passwordless.token.header=Provide Token
|
||||
passwordless.token.description=Please provide the security token sent to you via email, phone, etc. \
|
||||
Note that the token is valid for only a brief window and upon submission, all other tokens will be invalidated and removed.
|
||||
|
||||
passwordless.error.failure.title=Authentication Failure
|
||||
passwordless.error.failure.description=The provided token could not be verified. It may have been invalidated, removed or expired.
|
||||
|
||||
passwordless.error.unknown.user=Provided username cannot be recognized and located by CAS.
|
||||
passwordless.error.invalid.user=Provided username does not carry enough contact information.
|
||||
|
||||
cas.authn.qr.fail=Unable to accept authentication request based on QR code. Make sure the QR code is correctly scanned, \
|
||||
and provided credentials are valid, issued by this CAS server and have not expired.
|
||||
|
||||
# Inwebo
|
||||
cas.inwebo.checkresult.title=Checking Inwebo authentication
|
||||
cas.inwebo.checkresult.heading=Waiting for the Inwebo notification to be approved:
|
||||
cas.inwebo.checkresult.message=Please validate it on your phone/desktop...
|
||||
cas.inwebo.error.title=Inwebo authentication error
|
||||
cas.inwebo.error.heading=An error has occurred.
|
||||
cas.inwebo.error.userrefusedortoolate=You refused the authentication or did not validate it quickly enough.
|
||||
cas.inwebo.error.usernotregistered=Before any login, you must be registered at Inwebo. Check your mailbox to \
|
||||
follow the enrollment process or fill in your activation and PIN codes below to enroll in your browser...
|
||||
cas.inwebo.selectauthent.title=Select authentication
|
||||
cas.inwebo.selectauthent.heading=Select your authentication method:
|
||||
cas.inwebo.selectauthent.browser=Browser authentication
|
||||
cas.inwebo.selectauthent.push=Mobile/desktop application authentication
|
||||
cas.inwebo.browserauthent.title=Browser authentication
|
||||
cas.inwebo.enroll.code=Activation code
|
||||
cas.inwebo.enroll.button=Enroll for browser authentication
|
||||
cas.inwebo.enroll.failure=The enrollment failed
|
||||
cas.inwebo.pin=PIN code
|
||||
cas.inwebo.pin2=PIN code confirmation
|
||||
cas.inwebo.enroll.badpinconfirmation=PIN codes don't match
|
||||
cas.inwebo.browser.heading=Fill in your PIN code:
|
||||
cas.inwebo.browser.button=Log in in the browser
|
||||
cas.inwebo.browser.failure=OTP generation error
|
||||
cas.inwebo.retry.button=Retry the Inwebo multi-factor authentication
|
||||
|
||||
cas.screen.acct.title=Account Registration
|
||||
cas.screen.acct.intro=Please complete the form below to register your new account with CAS. \
|
||||
Once the form is submitted, you will receive an email with an account activation link to \
|
||||
enable your account, set up your password and begin using CAS.
|
||||
cas.screen.acct.infosent=Account activation instructions are successfully sent. \
|
||||
Please check your email, etc and follow the instructions.
|
||||
|
||||
cas.screen.acct.intro.complete=Welcome back! Thank you for verifying your account. \
|
||||
Please complete the form below to register your new account with CAS.
|
||||
cas.screen.acct.intro.completed=Thank you! Your account is now activated and registered with CAS.
|
||||
|
||||
cas.screen.acct.button.submit=Submit
|
||||
cas.screen.acct.button.cancel=Cancel
|
||||
cas.screen.acct.button.update=Update
|
||||
|
||||
cas.screen.acct.error.provision=Unable to provision the requested account.
|
||||
cas.screen.acct.error.fail=Unable to register the requested account, or send the account activation link.
|
||||
cas.screen.acct.error.invalid-value=The provided value is missing, invalid or does not match the required pattern for the input type.
|
||||
|
||||
cas.screen.acct.label.email=Email Address
|
||||
cas.screen.acct.title.email=This is the your primary email address to which the activation link would be sent.
|
||||
cas.screen.acct.label.firstName=First Name
|
||||
cas.screen.acct.title.firstName=Your first name.
|
||||
cas.screen.acct.label.lastName=Last Name
|
||||
cas.screen.acct.title.lastName=Your last/surname.
|
||||
cas.screen.acct.label.username=Username
|
||||
cas.screen.acct.title.username=The username you wish to use for login attempts.
|
||||
cas.screen.acct.label.phone=Phone Number
|
||||
cas.screen.acct.title.phone=This is the your phone number to which the activation link would be sent.
|
||||
cas.screen.acct.label.country=Country
|
||||
cas.screen.acct.title.country=This is the country linked associated to your phone number.
|
||||
|
||||
screen.acct.label.security.question.1=Security Question 1
|
||||
screen.acct.label.security.question.2=Security Question 2
|
||||
screen.acct.label.security.answer=Type your answer here...
|
@ -1,93 +0,0 @@
|
||||
# Welcome Screen Messages
|
||||
|
||||
screen.welcome.welcome=欢迎来到中央认证系统。默认的认证处理器支持那些用户名等于密码的账号,开发者可以试试看。
|
||||
screen.welcome.security=出于安全考虑,一旦您访问过那些需要您提供凭证信息的应用时,请操作完成之后<a href="logout">登出</a>并关闭浏览器。
|
||||
screen.welcome.instructions=请输入您的用户名和密码.
|
||||
screen.welcome.label.netid=用户名:
|
||||
screen.welcome.label.netid.accesskey=n
|
||||
screen.welcome.label.password=密 码:
|
||||
screen.welcome.label.password.accesskey=p
|
||||
screen.welcome.label.warn=转向其他站点前提示我。
|
||||
screen.welcome.label.warn.accesskey=w
|
||||
screen.welcome.button.login=登录
|
||||
screen.welcome.button.clear=重置
|
||||
|
||||
logo.title=转到Apereo网站首页
|
||||
copyright=版权所有 © 2005–2012 Apereo, Inc. 保留全部权利。
|
||||
|
||||
# Blocked Errors Page
|
||||
screen.blocked.header=访问被拒绝
|
||||
screen.blocked.message=输错密码次数太多,账号被锁定。
|
||||
|
||||
# Confirmation Screen Messages
|
||||
screen.confirmation.message=单击 <a href="{0}">这里</a> ,便能够访问到目标应用。
|
||||
|
||||
# Generic Success Screen Messages
|
||||
screen.success.header=登录成功
|
||||
screen.success.success=您已经成功登录。
|
||||
screen.success.security=出于安全考虑,请操作完成之后<a href="logout">注销登录</a>,并关闭浏览器。
|
||||
|
||||
# Logout Screen Messages
|
||||
screen.logout.header=注销成功
|
||||
screen.logout.success=您已经成功退出CAS系统,谢谢使用!
|
||||
screen.logout.security=出于安全考虑,请关闭您的浏览器。
|
||||
|
||||
screen.service.sso.error.header=在访问到到目标服务前,你必须经过重新认证的考验
|
||||
screen.service.sso.error.message=你正试图访问要求重新认证的服务。请尝试进行<a href="{0}">再次认证</a>。
|
||||
|
||||
username.required=请输入用户名
|
||||
password.required=请输入登录密码
|
||||
captchaError=验证码不正确
|
||||
|
||||
# Authentication failure messages
|
||||
authenticationFailure.AccountDisabledException=这个账户被禁用了。
|
||||
authenticationFailure.AccountLockedException=这个账户被上锁了。
|
||||
authenticationFailure.CredentialExpiredException=你的密码过期了。
|
||||
authenticationFailure.InvalidLoginLocationException=你不能从这个工作站登录。
|
||||
authenticationFailure.InvalidLoginTimeException=你的账户现在被禁止登录了。
|
||||
authenticationFailure.AccountNotFoundException=认证信息无效。
|
||||
authenticationFailure.FailedLoginException=认证信息无效。
|
||||
authenticationFailure.UNKNOWN=认证信息无效。
|
||||
|
||||
INVALID_REQUEST_PROXY=必须同时提供'pgt'和'targetService'参数
|
||||
INVALID_TICKET_SPEC=校验票根失败。您可能采用服务票根来校验代理票根,或没有将renew设为true。
|
||||
INVALID_REQUEST=必须同时提供'service'和'ticket'参数
|
||||
INVALID_TICKET=未能够识别出目标 ''{0}''票根
|
||||
INVALID_SERVICE=票根''{0}''不符合目标服务
|
||||
INVALID_PROXY_CALLBACK=所提供的代理回调网址''{0}''不能提供认证。
|
||||
UNAUTHORIZED_SERVICE_PROXY=所提供的服务''{0}''没有权限使用CAS代理的认证方式。
|
||||
|
||||
screen.service.error.header=未认证授权的服务
|
||||
screen.service.error.message=不允许使用CAS来认证您访问的目标应用。
|
||||
screen.service.empty.error.message=CAS的服务记录是空的,没有定义服务。 \
|
||||
希望通过CAS进行认证的应用程序必须在服务记录中明确定义。
|
||||
|
||||
# Password policy
|
||||
password.expiration.warning=你的密码会在{0}天内过期。请立刻<a href="{1}">修改你的密码</a>。
|
||||
password.expiration.loginsRemaining=在<strong>必须</strong>修改密码之前,你还剩{0}次登录。
|
||||
screen.accountdisabled.heading=这个账户已经被禁用了。
|
||||
screen.accountdisabled.message=请联系系统管理员来重新获得访问权限。
|
||||
screen.accountlocked.heading=这个账户已经被锁住了。
|
||||
screen.accountlocked.message=请联系系统管理员来重新获得访问权限。
|
||||
screen.expiredpass.heading=你的密码已经过期了。
|
||||
screen.expiredpass.message=请<a href="{0}">修改你的密码</a>。
|
||||
screen.mustchangepass.heading=你必须修改你的密码。
|
||||
screen.mustchangepass.message=请<a href="{0}">修改你的密码</a>。
|
||||
screen.badhours.heading=现在你的账户被禁止登录了。
|
||||
screen.badhours.message=请稍后再试。
|
||||
screen.badworkstation.heading=你不能从这个工作站登录。
|
||||
screen.badworkstation.message=请联系系统管理员来重新获得访问权限。
|
||||
|
||||
# OAuth
|
||||
screen.oauth.confirm.header=授权
|
||||
screen.oauth.confirm.message=要授权"{0}"访问你全部个人信息吗?
|
||||
screen.oauth.confirm.allow=允许
|
||||
|
||||
# Unavailable
|
||||
screen.unavailable.heading=CAS无法使用
|
||||
screen.unavailable.message=在试图完成你的请求时出错。请通知你的技术支持或重试。
|
||||
|
||||
# Custom
|
||||
login-form.system=系统
|
||||
customLoginFormField.phone=手机号
|
||||
customFields[phone].required=请填写手机号
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"@class": "org.apereo.cas.services.CasRegisteredService",
|
||||
"serviceId": "^(https?|imaps)://([^.]+\\.zhujiachefu\\.com|localhost:\\d+)/.*",
|
||||
"name": "HTTPS and IMAPS",
|
||||
"id": 10000001,
|
||||
"description": "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
|
||||
"evaluationOrder": 10000
|
||||
}
|
@ -1,641 +0,0 @@
|
||||
/* Root / Reset */
|
||||
|
||||
|
||||
:root {
|
||||
--mdc-text-button-label-text-color: #f7f7f7;
|
||||
--mdc-theme-error: #d9534f;
|
||||
--cas-theme-primary: #153e50;
|
||||
--cas-theme-primary-bg: rgba(21, 62, 80, 0.2);
|
||||
--cas-theme-button-bg: #26418f;
|
||||
--cas-theme-primary-light: #006d85;
|
||||
--cas-theme-secondary: #74C163;
|
||||
--cas-theme-success: var(--cas-theme-secondary);
|
||||
--cas-theme-danger: var(--mdc-theme-error);
|
||||
--cas-theme-warning: #e6a210;
|
||||
--cas-theme-border-light: 1px solid rgba(0, 0, 0, .2);
|
||||
--mdc-theme-primary: var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
background: #EFEFEF;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #153e50;
|
||||
color: var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
a:hover, a:visited, a:active {
|
||||
color: #006d85;
|
||||
color: var(--cas-theme-primary-light);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
aside, section, main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Material */
|
||||
|
||||
.mdc-drawer {
|
||||
top: 56px;
|
||||
}
|
||||
|
||||
.mdc-drawer-app-content {
|
||||
flex: auto;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mdc-top-app-bar {
|
||||
z-index: 7;
|
||||
}
|
||||
|
||||
div#content {
|
||||
box-shadow:1px 1px 3px #888;
|
||||
}
|
||||
/* widgets */
|
||||
|
||||
.notifications-count {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 12px;
|
||||
background-color: #b00020;
|
||||
background-color: var(--cas-theme-danger);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
padding: 1px 3px;
|
||||
font: 8px Verdana;
|
||||
}
|
||||
|
||||
.cas-brand {
|
||||
height: 48px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
header>nav .cas-brand path.cls-1 {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
header>nav .cas-brand .cas-logo {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.caps-warn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.caps-on {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-section {
|
||||
border-right: 1px solid rgba(0, 0, 0, .2);
|
||||
border-right: var(--cas-theme-border-light, 1px solid rgba(0, 0, 0, .2));
|
||||
padding: 2rem 2.5rem;
|
||||
flex: 1 1 auto;
|
||||
/* IE flex fix */
|
||||
}
|
||||
|
||||
.login-section:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767.99px) {
|
||||
.login-section {
|
||||
border-right: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, .2);
|
||||
border-bottom: var(--cas-theme-border-light, 1px solid rgba(0, 0, 0, .2));
|
||||
max-width: none;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.noborder {
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
color: #000;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
text-transform: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button.close {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.banner {
|
||||
border: 1px solid rgba(0, 0, 0, .2);
|
||||
border: var(--cas-theme-border-light, 1px solid rgba(0, 0, 0, .2));
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
box-shadow:1px 1px 3px #888;
|
||||
border-radius:.5em;
|
||||
padding-top: .5em;
|
||||
padding-bottom: .5em;
|
||||
}
|
||||
|
||||
.banner>span {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.banner .banner-message {
|
||||
margin: 0.375rem 0;
|
||||
}
|
||||
|
||||
.banner .banner-heading:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.banner .banner-message:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.banner .banner-message:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.banner-primary {
|
||||
border-color: #153e50;
|
||||
border-color: var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
.banner-primary .mdi {
|
||||
color: #153e50;
|
||||
color: var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
.banner-danger h1:before,
|
||||
.banner-danger h2:before,
|
||||
.banner-danger h3:before,
|
||||
.banner-danger h4:before,
|
||||
.banner-danger h5:before {
|
||||
content: "\F0027";
|
||||
font-size: 24px;
|
||||
font: normal normal normal 24px/1 "Material Design Icons";
|
||||
}
|
||||
|
||||
.banner-danger {
|
||||
border-color: #b00020;
|
||||
border-color: var(--cas-theme-danger, #b00020);
|
||||
color: #D8000C;
|
||||
background-color: #FFD2D2;
|
||||
}
|
||||
|
||||
.banner-danger .mdi {
|
||||
color: #b00020;
|
||||
color: var(--cas-theme-danger, #b00020);
|
||||
}
|
||||
|
||||
.banner-warning {
|
||||
border-color: #e6a210;
|
||||
border-color: var(--cas-theme-warning, #e6a210);
|
||||
color: #e6a210;
|
||||
color: var(--cas-theme-warning, #e6a210);
|
||||
}
|
||||
|
||||
.banner-warning .mdi {
|
||||
color: #e6a210;
|
||||
color: var(--cas-theme-warning, #e6a210);
|
||||
}
|
||||
|
||||
.banner-success h1:before,
|
||||
.banner-success h2:before,
|
||||
.banner-success h3:before,
|
||||
.banner-success h4:before,
|
||||
.banner-success h5:before {
|
||||
content: "\F012D";
|
||||
font-size: 24px;
|
||||
font: normal normal normal 24px/1 "Material Design Icons";
|
||||
}
|
||||
|
||||
.banner-success {
|
||||
border-color: var(--cas-theme-success);
|
||||
color: var(--cas-theme-primary, #153e50);
|
||||
background-color: #b3e7f8;
|
||||
}
|
||||
|
||||
.banner-dismissible {
|
||||
padding-right: 4rem;
|
||||
}
|
||||
|
||||
.banner-dismissible .close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: .75rem 1.25rem;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.login-provider-item {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.login-provider-item .mdc-button .mdi {
|
||||
margin-right: 0.375rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767.99px) {
|
||||
.logout-banner {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.cas-footer {
|
||||
background-color: var(--mdc-theme-primary, #6200ee);
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.cas-footer a {
|
||||
color: deepskyblue;
|
||||
}
|
||||
|
||||
.cas-footer>* {
|
||||
margin-right: 0.25rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cas-footer>*:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cas-notification-dialog .mdc-dialog__content>.cas-notification-message:not(:last-child) {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, .2);
|
||||
border-bottom: var(--cas-theme-border-light, 1px solid rgba(0, 0, 0, .2));
|
||||
}
|
||||
|
||||
.mdc-dialog__title::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mdi {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.mdi:before {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
/* custom components */
|
||||
|
||||
.custom-select {
|
||||
display: inline-block;
|
||||
min-width: 80%;
|
||||
height: 56px;
|
||||
padding: .375rem 1.75rem .375rem .75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
vertical-align: middle;
|
||||
background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: .25rem;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/* utilities */
|
||||
|
||||
.bg-primary {
|
||||
background-color: rgba(21, 62, 80, 0.2);
|
||||
background-color: var(--cas-theme-primary-bg, rgba(21, 62, 80, 0.2));
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-color: #153e50;
|
||||
border-bottom: 1px solid var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #e6a210;
|
||||
color: var(--cas-theme-warning, #e6a210);
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #b00020;
|
||||
color: var(--cas-theme-danger, #b00020);
|
||||
}
|
||||
|
||||
.text-secondary, .text-success {
|
||||
color: var(--cas-theme-secondary);
|
||||
}
|
||||
|
||||
.progress-bar-danger .mdc-linear-progress__bar-inner {
|
||||
border-color: #b00020;
|
||||
border-color: var(--cas-theme-danger, #b00020);
|
||||
}
|
||||
|
||||
.progress-bar-warning .mdc-linear-progress__bar-inner {
|
||||
border-color: #e6a210;
|
||||
border-color: var(--cas-theme-warning, #e6a210);
|
||||
}
|
||||
|
||||
.progress-bar-success .mdc-linear-progress__bar-inner {
|
||||
border-color: var(--cas-theme-success);
|
||||
}
|
||||
|
||||
.word-break-all {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.mdc-text-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mdc-text-field>.mdc-text-field__input, .mdc-text-field:not(.mdc-text-field--disabled):not(.mdc-text-field--outlined):not(.mdc-text-field--textarea)>.mdc-text-field__input {
|
||||
border-color: #153e50;
|
||||
border: 1px solid var(--cas-theme-primary, #153e50);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mdc-input-group .mdc-input-group-field .mdc-text-field {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.mdc-input-group .mdc-input-group-append {
|
||||
order: 2;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.mdc-input-group .mdc-input-group-prepend, .mdc-input-group .mdc-input-group-append {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.mdc-input-group .mdc-input-group-prepend {
|
||||
order: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.mdc-input-group .mdc-input-group-field.mdc-input-group-field-prepend .mdc-text-field>.mdc-text-field__input {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.mdc-input-group .mdc-input-group-field.mdc-input-group-field-append .mdc-text-field>.mdc-text-field__input {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.text-danger, .mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon.text-danger, .mdc-text-field:not(.mdc-text-field--disabled)+.mdc-text-field-helper-line .mdc-text-field-helper-text.text-danger {
|
||||
color: #b00020;
|
||||
color: var(--cas-theme-danger);
|
||||
}
|
||||
|
||||
.mdc-text-field--focused:not(.mdc-text-field--disabled) .mdc-floating-label {
|
||||
color: #153e50;
|
||||
color: var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
.mdc-button--outline:not(:disabled) {
|
||||
background-color: #428bca;
|
||||
border-radius: 12px 4px;
|
||||
}
|
||||
|
||||
.mdc-button--raised:not(:disabled) {
|
||||
margin-right: 4px;
|
||||
border-radius: 12px 4px;
|
||||
background-color: var(--cas-theme-primary, #153E50);
|
||||
}
|
||||
|
||||
.list-unstyled {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pad-0 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.w-66 {
|
||||
width: 66%;
|
||||
}
|
||||
|
||||
.w-33 {
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
.w-25 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.w-50 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.w-75 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.h-25 {
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.h-50 {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.h-75 {
|
||||
height: 75%;
|
||||
}
|
||||
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.h-auto {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.mw-100 {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.mh-100 {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.min-vw-100 {
|
||||
min-width: 100vw;
|
||||
}
|
||||
|
||||
.min-vh-100 {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.vw-100 {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.vh-100 {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.mw-50 {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.border-rounded {
|
||||
border-color: #153e50;
|
||||
border: 1px solid var(--cas-theme-primary, #153e50);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-color: #153e50;
|
||||
border-bottom: 1px solid var(--cas-theme-primary, #153e50);
|
||||
}
|
||||
|
||||
@media all and (min-width: 768px) {
|
||||
.w-md-50 {
|
||||
width: 50%;
|
||||
}
|
||||
.w-md-66 {
|
||||
width: 66%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 992px) {
|
||||
.w-lg-50 {
|
||||
width: 50%;
|
||||
}
|
||||
.w-lg-66 {
|
||||
width: 66%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 767.99px) {
|
||||
.w-md-50 {
|
||||
width: 100%;
|
||||
}
|
||||
.w-md-66 {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 991.99px) {
|
||||
.w-lg-50 {
|
||||
width: 100%;
|
||||
}
|
||||
.w-lg-66 {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
*, ::after, ::before {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.text-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
#duo_iframe {
|
||||
width: 100%;
|
||||
min-width: 304px;
|
||||
height: 330px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dataTables_wrapper {
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#serviceui {
|
||||
background-color: #17a3b844;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#heroimg {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* IE flex fix */
|
||||
|
||||
#main-content {
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/* oddly, the auto right and left margins caused the login form to not be centered in IE */
|
||||
|
||||
@media all and (min-width: 768px) {
|
||||
.login-section {
|
||||
flex: 1 1 500px;
|
||||
/* according to flexbugs, flex-basis should be explicitly set for IE */
|
||||
/* https://github.com/philipwalton/flexbugs#flexbug-4 */
|
||||
}
|
||||
}
|
||||
|
||||
/* flex-basis: auto works in IE with the column view,
|
||||
but a specific value needs to be set for row view
|
||||
*/
|
||||
|
||||
/* fix for not showing password reveal icon on MSEdge and MSIE */
|
||||
.pwd::-ms-reveal,
|
||||
.pwd::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 1400px) {
|
||||
.container-xxl {
|
||||
max-width: 90%;
|
||||
}
|
||||
}
|
@ -1,210 +0,0 @@
|
||||
/* Top level is idpSelectIdPSelector */
|
||||
#idpSelectIdPSelector
|
||||
{
|
||||
width: 80%;
|
||||
text-align: justify-all;
|
||||
background-color: #FFFFFF;
|
||||
/*border: 2px #0f253c dotted;*/
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The preferred IdP tile (if present) has a specified height, so
|
||||
* we can fit the preselected * IdPs in there
|
||||
*/
|
||||
#idpSelectPreferredIdPTile
|
||||
{
|
||||
height:138px;
|
||||
}
|
||||
#idpSelectPreferredIdPTileNoImg
|
||||
{
|
||||
height:80px;
|
||||
}
|
||||
|
||||
/***
|
||||
* The preselect buttons
|
||||
*/
|
||||
div.IdPSelectPreferredIdPButton
|
||||
{
|
||||
margin: 3px;
|
||||
width: 120px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the entire box look like a hyperlink
|
||||
*/
|
||||
div.IdPSelectPreferredIdPButton a
|
||||
{
|
||||
float: left;
|
||||
width: 99%;
|
||||
|
||||
}
|
||||
div.IdPSelectTextDiv{
|
||||
height: 3.5ex;
|
||||
font-size: 15px;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
div.IdPSelectPreferredIdPImg
|
||||
{
|
||||
/* max-width: 95%; */
|
||||
height: 69px; /* We need the absolute height to force all buttons to the same size */
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
img.IdPSelectIdPImg {
|
||||
/*width:84px;*/
|
||||
/*height:64px;*/
|
||||
width:auto;
|
||||
}
|
||||
|
||||
div.IdPSelectautoDispatchTile {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.IdPSelectautoDispatchArea {
|
||||
margin-top: 30px ;
|
||||
}
|
||||
|
||||
div.IdPSelectPreferredIdPButton img
|
||||
{
|
||||
display: block; /* Block display to allow auto centring */
|
||||
max-width: 114px; /* Specify max to allow scaling, percent does work */
|
||||
max-height: 64px; /* Specify max to allow scaling, percent doesn't work */
|
||||
margin-top: 3px ;
|
||||
margin-bottom: 3px ;
|
||||
border: solid 0px #000000; /* Strip any embellishments the brower may give us */
|
||||
margin-left: auto; /* Auto centring */
|
||||
margin-right: auto; /* Auto centring */
|
||||
|
||||
}
|
||||
|
||||
div.IdPSelectPreferredIdPButton div.IdPSelectTextDiv
|
||||
{
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
max-width: 95%;
|
||||
height: 30px; /* Specify max height to allow two lines. The
|
||||
* Javascript controlls the max length of the
|
||||
* strings
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Force the size of the selectors and the buttons
|
||||
*/
|
||||
#idpSelectInput, #idpSelectSelector
|
||||
{
|
||||
width: 80%;
|
||||
}
|
||||
/*
|
||||
* For some reason a <select> width includes the border and an
|
||||
* <input> doesn't hence we have to force a margin onto the <select>
|
||||
*/
|
||||
#idpSelectSelector
|
||||
{
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
|
||||
}
|
||||
#idpSelectSelectButton, #idpSelectListButton
|
||||
{
|
||||
padding-left: 4px;
|
||||
padding-right: 2px;
|
||||
margin-left: 5px;
|
||||
width: 16%;
|
||||
color: #fff;
|
||||
background-color: #007bff;
|
||||
border-color: #007bff;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* change underlining of HREFS
|
||||
*/
|
||||
#idpSelectIdPSelector a:link
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#idpSelectIdPSelector a:visited
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#idpSelectIdPSelector a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Arrange to have the dropdown/list aref on the left and the
|
||||
* help button on the right
|
||||
*/
|
||||
|
||||
a.IdPSelectDropDownToggle
|
||||
{
|
||||
display: inline-block;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
a.IdPSelectHelpButton
|
||||
{
|
||||
display: none;
|
||||
text-align: right;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop down (incremental search) stuff - see the associated javascript for reference
|
||||
*/
|
||||
ul.IdPSelectDropDown {
|
||||
-moz-box-sizing: border-box;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: small;
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
padding-left: 0px;
|
||||
border: 1px solid black;
|
||||
z-index: 6;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
ul.IdPSelectDropDown li {
|
||||
background-color: white;
|
||||
cursor: default;
|
||||
padding: 0px 3px;
|
||||
}
|
||||
|
||||
ul.IdPSelectDropDown li.IdPSelectCurrent {
|
||||
background-color: #3366cc;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Legacy */
|
||||
div.IdPSelectDropDown {
|
||||
-moz-box-sizing: border-box;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: small;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid black;
|
||||
z-index: 6;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
div.IdPSelectDropDown div {
|
||||
background-color: white;
|
||||
cursor: default;
|
||||
padding: 0px 3px;
|
||||
}
|
||||
|
||||
div.IdPSelectDropDown div.IdPSelectCurrent {
|
||||
background-color: #3366cc;
|
||||
color: white;
|
||||
}
|
||||
/* END */
|
@ -1,142 +0,0 @@
|
||||
/***
|
||||
Login page
|
||||
***/
|
||||
|
||||
/* logo page */
|
||||
.login {
|
||||
background-color: #666 !important;
|
||||
}
|
||||
|
||||
.login .logo {
|
||||
margin: 0 auto;
|
||||
margin-top: 60px;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login .content {
|
||||
background: url(../img/bg-white-lock.png) repeat;
|
||||
width: 360px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.login .content h3 {
|
||||
color: #eee;
|
||||
}
|
||||
.login .content h4 {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.login .content p,
|
||||
.login .content label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.login .content .login-form,
|
||||
.login .content .forget-form {
|
||||
padding: 0 30px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.login .content .login-form .form-group {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.login .content .form-control {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.login .content .forget-form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.login .content .register-form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.login .content .form-title {
|
||||
padding-top: 35px;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login .content .form-actions {
|
||||
background-color: transparent;
|
||||
clear: both;
|
||||
border: 0px;
|
||||
padding: 0px 30px 25px 30px;
|
||||
margin-left: -30px;
|
||||
margin-right: -30px;
|
||||
}
|
||||
|
||||
.login .content .form-actions .checkbox {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.login .content .forget-form .form-actions {
|
||||
border: 0;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.login .content .register-form .form-actions {
|
||||
border: 0;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.login .content .form-actions .checkbox {
|
||||
margin-top: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.login .content .form-actions .btn {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.login .content .forget-password {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.login .content .create-account {
|
||||
border-top: 1px dotted #eee;
|
||||
padding-top: 10px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.login .content .create-account a {
|
||||
display: inline-block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* footer copyright */
|
||||
.login .copyright {
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
padding: 10px;
|
||||
color: #eee;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
/***
|
||||
Login page
|
||||
***/
|
||||
.login .logo {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.login .content {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.login .content h3 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.login .checkbox {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
@ -1,980 +0,0 @@
|
||||
/***
|
||||
Responsive Theme.
|
||||
Based on http://getbootstrap.com/css/#responsive-utilities-classes
|
||||
***/
|
||||
|
||||
/***
|
||||
Fixed Footer
|
||||
***/
|
||||
|
||||
.page-footer-fixed.page-footer-fixed-mobile .footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10000;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.page-footer-fixed.page-footer-fixed-mobile .page-container {
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.page-footer-fixed.page-footer-fixed-mobile.page-sidebar-fixed .footer {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Form Medium Devices Up To Large Devices
|
||||
***/
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1200px) {
|
||||
|
||||
.page-boxed .header.navbar .dropdown .username {
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.hidden-1024 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
From Medium Devices Up To Larger Devices
|
||||
***/
|
||||
|
||||
@media (min-width: 992px) {
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
width: 225px;
|
||||
float: left;
|
||||
position: relative;
|
||||
margin-right: -100%;
|
||||
}
|
||||
|
||||
.page-sidebar.navbar-collapse {
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Page content
|
||||
***/
|
||||
.page-content-wrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
margin-left: 225px;
|
||||
margin-top: 0px;
|
||||
min-height: 600px;
|
||||
padding: 25px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.page-content.no-min-height {
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/***
|
||||
Fixed Sidebar
|
||||
***/
|
||||
.page-sidebar-fixed .page-content {
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed .page-sidebar {
|
||||
position: fixed !important;
|
||||
margin-left: 0;
|
||||
top: 41px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed ul.page-sidebar-menu > li.last {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-hover-on .page-sidebar {
|
||||
z-index: 10000;
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-hover-on .page-sidebar .selected {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-hover-on .page-content {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-hover-on .footer {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed .page-sidebar-closed .page-sidebar .sidebar-search .submit,
|
||||
.page-sidebar-fixed .page-sidebar .sidebar-toggler {
|
||||
-webkit-transition: all 0.3s ease;
|
||||
-moz-transition: all 0.3s ease;
|
||||
-o-transition: all 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-reversed .page-sidebar-closed .page-sidebar .sidebar-search .submit,
|
||||
.page-sidebar-fixed.page-sidebar-reversed .page-sidebar .sidebar-toggler {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.page-sidebar-hovering {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.page-sidebar-hovering .sub-menu,
|
||||
.page-sidebar-hovering span.badge,
|
||||
.page-sidebar-hovering span.title,
|
||||
.page-sidebar-hovering span.arrow {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.page-sidebar-hovering .submit {
|
||||
opacity: 0;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Fixed Sidebar
|
||||
***/
|
||||
|
||||
.page-sidebar-fixed .footer {
|
||||
margin-left: 225px;
|
||||
background-color: #fff;
|
||||
padding: 8px 20px 5px 20px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed .footer .footer-inner {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-closed .footer {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed .footer .footer-tools .go-top {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed .footer .footer-tools .go-top i {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
/***
|
||||
Boxed Layout
|
||||
***/
|
||||
|
||||
.page-boxed .header.navbar .navbar-brand {
|
||||
margin-left: 0px !important;
|
||||
width: 226px;
|
||||
}
|
||||
|
||||
.page-boxed .header.navbar .navbar-brand img {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page-boxed .header.navbar .navbar-nav {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.page-boxed .footer {
|
||||
padding: 8px 0 5px 0;
|
||||
}
|
||||
|
||||
.page-boxed.page-sidebar-fixed .footer {
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
/***
|
||||
Sidebar Reversed
|
||||
***/
|
||||
|
||||
.page-sidebar-reversed .page-sidebar {
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
margin-left: -100%;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
margin-left: -225px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed .page-content {
|
||||
margin-left: 0;
|
||||
margin-right: 225px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed .page-sidebar-wrapper {
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed .footer {
|
||||
margin-left: 0;
|
||||
margin-right: 225px;
|
||||
padding: 8px 20px 5px 20px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed.page-sidebar-hover-on .page-content {
|
||||
margin-left: 0;
|
||||
margin-right: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed.page-sidebar-hover-on .footer {
|
||||
margin-right: 35px;
|
||||
}
|
||||
|
||||
/***
|
||||
Sidebar Closed
|
||||
***/
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-toggler {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search .form-container {
|
||||
width: 29px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search .form-container .input-box {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search .form-container input[type="text"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search .form-container .submit {
|
||||
margin-top: 5px !important;
|
||||
margin-left: 7px !important;
|
||||
margin-right: 7px !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
width: 255px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container input[type="text"] {
|
||||
margin-top: 7px;
|
||||
margin-left: 8px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 2px;
|
||||
width: 185px;
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .submit {
|
||||
display: inline-block;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
margin: 11px 8px 9px 6px !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-repeat: no-repeat;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
margin: 12px 8px 9px 8px !important;
|
||||
display: inline-block !important;
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li > a .selected {
|
||||
right: -3px !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li > a > .badge,
|
||||
.page-sidebar-closed .page-sidebar-menu > li > a > .title,
|
||||
.page-sidebar-closed .page-sidebar-menu > li > a > .arrow {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-toggler {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search {
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu {
|
||||
width: 35px !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li > a {
|
||||
padding-left: 7px;
|
||||
}
|
||||
|
||||
.page-sidebar-fixed.page-sidebar-closed .page-sidebar-menu > li > a {
|
||||
-webkit-transition: all 0.2s ease;
|
||||
-moz-transition: all 0.2s ease;
|
||||
-o-transition: all 0.2s ease;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed.page-sidebar-closed .page-sidebar-menu > li > a {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover {
|
||||
width: 236px !important;
|
||||
position: relative !important;
|
||||
z-index: 2000;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li.sidebar-toggler-wrapper:hover,
|
||||
.page-sidebar-closed .page-sidebar-menu > li.sidebar-search-wrapper:hover {
|
||||
width: 35px !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover .selected {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover > a > i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover .title {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover .badge {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li > .sub-menu {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu {
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
z-index: 2000;
|
||||
left: 36px;
|
||||
margin-top: 0;
|
||||
top: 100%;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu > li > .sub-menu,
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu > li > .sub-menu > li > .sub-menu {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
/* 2rd level sub menu*/
|
||||
.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu > li > a {
|
||||
padding-left: 15px !important;
|
||||
}
|
||||
|
||||
/* 3rd level sub menu*/
|
||||
.page-sidebar-closed .page-sidebar-menu > li > ul.sub-menu > li > .sub-menu > li > a {
|
||||
padding-left: 30px !important;
|
||||
}
|
||||
|
||||
/* 4rd level sub menu*/
|
||||
.page-sidebar-closed .page-sidebar-menu > li > ul.sub-menu > li > .sub-menu > li > .sub-menu > li > a {
|
||||
padding-left: 45px !important;
|
||||
}
|
||||
|
||||
/* sidebar container */
|
||||
|
||||
.page-sidebar-closed .page-sidebar {
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-closed .page-content {
|
||||
margin-left: 35px !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Sidebar Reversed & Sidebar Closed
|
||||
***/
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar {
|
||||
margin-left: -35px;
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-content {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 35px !important;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar-menu > li:hover {
|
||||
margin-left: -201px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar-menu > li.sidebar-toggler-wrapper:hover,
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar-menu > li.sidebar-search-wrapper:hover {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
margin-left: -225px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .submit {
|
||||
margin: 11px 8px 9px 12px !important;
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
margin: 12px 6px 9px 8px !important;
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu {
|
||||
left:auto;
|
||||
right: 36px;
|
||||
}
|
||||
|
||||
.page-sidebar-reversed.page-sidebar-fixed.page-sidebar-closed .footer {
|
||||
margin-right: 35px;
|
||||
}
|
||||
|
||||
/***
|
||||
Fixed Footer
|
||||
***/
|
||||
|
||||
.page-footer-fixed .footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10000;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.page-footer-fixed .page-container {
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.page-footer-fixed.page-sidebar-fixed .footer {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***
|
||||
Up To Medium Devices
|
||||
***/
|
||||
|
||||
@media (max-width:991px) {
|
||||
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header.navbar {
|
||||
padding: 0 20px 0 20px;
|
||||
position: relative;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.page-header-fixed.page-header-fixed-mobile .navbar-fixed-top {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.page-sidebar.navbar-collapse {
|
||||
max-height: none; /* set some max height to have a scrollable menu on mobile devices */
|
||||
}
|
||||
|
||||
.page-sidebar.navbar-collapse.collapse {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.page-sidebar.navbar-collapse.in {
|
||||
overflow: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.page-full-width .page-sidebar-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.page-sidebar.navbar-collapse.navbar-no-scroll {
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.header.navbar .nav li.dropdown i {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top:1px;
|
||||
right:0px;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav {
|
||||
display: block;
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav .open .dropdown-menu {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav {
|
||||
display: inline-block;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav > li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-brand {
|
||||
margin-left: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-brand img {
|
||||
margin-left: 4px !important;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
Header Search Box
|
||||
***/
|
||||
|
||||
.header.navbar .search-form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-sidebar .header.navbar-responsive-search {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/***
|
||||
Page container
|
||||
***/
|
||||
.page-container {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.page-header-fixed.page-header-fixed-mobile .page-container {
|
||||
margin-top: 42px !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Page content
|
||||
***/
|
||||
.page-content {
|
||||
margin: 0px !important;
|
||||
padding: 20px 20px 20px 20px !important;
|
||||
min-height: 280px;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
border-top: 0 !important;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.page-sidebar.in {
|
||||
border-top: 0 !important;
|
||||
margin: 20px;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.header.navbar .sidebar-toggler,
|
||||
.page-sidebar .sidebar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-sidebar ul {
|
||||
margin-top:0px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.page-sidebar .selected {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
/***
|
||||
Styler panel
|
||||
***/
|
||||
.styler-panel {
|
||||
top:55px;
|
||||
right:20px;
|
||||
}
|
||||
|
||||
/***
|
||||
Boxed Layout
|
||||
***/
|
||||
.page-boxed .header.navbar > .container,
|
||||
.page-boxed .footer > .container,
|
||||
.page-boxed > .container {
|
||||
max-width: none !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***
|
||||
From Small Devices Up To Medium Devices
|
||||
***/
|
||||
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
|
||||
/***
|
||||
Body
|
||||
***/
|
||||
body {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar .btn-navbar.collapsed .arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-sidebar .btn-navbar .arrow {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top:50px;
|
||||
border-bottom: 15px solid #5f646b;
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
}
|
||||
|
||||
/***
|
||||
Boxed Layout
|
||||
***/
|
||||
.page-boxed .header.navbar > .container,
|
||||
.page-boxed > .container {
|
||||
margin: auto !important;
|
||||
}
|
||||
|
||||
.page-boxed .header.navbar {
|
||||
margin: auto !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page-boxed .footer {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***
|
||||
Extra Small Devices Only
|
||||
***/
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
|
||||
.header.navbar {
|
||||
padding: 0 10px 0 10px;
|
||||
}
|
||||
|
||||
.header.navbar .top-nav .nav{
|
||||
margin-top: 0px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.header.navbar .nav > li > .dropdown-menu.notification:after,
|
||||
.header.navbar .nav > li > .dropdown-menu.notification:before {
|
||||
margin-right: 160px;
|
||||
}
|
||||
|
||||
.header.navbar .nav > li > .dropdown-menu.notification {
|
||||
margin-right: -160px;
|
||||
}
|
||||
|
||||
.header.navbar .nav > li > .dropdown-menu.inbox:after,
|
||||
.header.navbar .nav > li > .dropdown-menu.inbox:before {
|
||||
margin-right: 110px;
|
||||
}
|
||||
|
||||
.header.navbar .nav > li > .dropdown-menu.inbox {
|
||||
margin-right: -110px;
|
||||
}
|
||||
|
||||
.header.navbar .nav > li > .dropdown-menu.tasks:after,
|
||||
.header.navbar .nav > li > .dropdown-menu.tasks:before {
|
||||
margin-right: 60px;
|
||||
}
|
||||
|
||||
.header.navbar .nav > li > .dropdown-menu.tasks {
|
||||
margin-right: -60px;
|
||||
}
|
||||
|
||||
/* Header logo */
|
||||
.header.navbar .navbar-brand {
|
||||
margin-left: 0px !important;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
/***
|
||||
Page content
|
||||
***/
|
||||
.page-content {
|
||||
padding: 20px 10px 10px 10px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/***
|
||||
Page title
|
||||
***/
|
||||
.page-title {
|
||||
margin-bottom: 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.page-title small {
|
||||
font-size: 13px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
/***
|
||||
Styler pagel
|
||||
***/
|
||||
.styler-panel {
|
||||
top:58px;
|
||||
right:12px;
|
||||
}
|
||||
|
||||
/***
|
||||
Page breadcrumb
|
||||
***/
|
||||
.breadcrumb {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
/***
|
||||
Portlet form action
|
||||
***/
|
||||
.portlet-body.form .form-actions{
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
Form input validation states
|
||||
***/
|
||||
.input-icon .input-error,
|
||||
.input-icon .input-warning,
|
||||
.input-icon .input-success {
|
||||
top:-27px;
|
||||
float: right;
|
||||
right:10px !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Advance tables
|
||||
***/
|
||||
.table-advance tr td.highlight:first-child a {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.footer .go-top {
|
||||
float: right;
|
||||
display: block;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
/***
|
||||
Vertical inline menu
|
||||
***/
|
||||
.ver-inline-menu li.active:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/***
|
||||
Form controls
|
||||
***/
|
||||
.form-horizontal .form-actions {
|
||||
padding-left: 180px;
|
||||
}
|
||||
|
||||
.portlet .form-horizontal .form-actions {
|
||||
padding-left: 190px;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
The Most Extra Small Devices Landscape Mode Only
|
||||
***/
|
||||
|
||||
@media (max-width: 580px) {
|
||||
|
||||
.header.navbar .username {
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
|
||||
/***
|
||||
Header navbar
|
||||
***/
|
||||
.page-header-fixed.page-header-fixed-mobile .header.navbar {
|
||||
height: 84px;
|
||||
}
|
||||
|
||||
.page-header-fixed.page-header-fixed-mobile .page-container {
|
||||
margin-top: 84px !important;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav {
|
||||
display: block;
|
||||
clear: both;
|
||||
margin-top: 2px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav > li.dropdown .dropdown-toggle {
|
||||
margin-top:-1px;
|
||||
padding-left: 9px;
|
||||
padding-right: 9px;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav > li.dropdown.language .dropdown-toggle,
|
||||
.header.navbar .navbar-nav > li.dropdown.user .dropdown-toggle {
|
||||
padding-left: 4px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-nav li.dropdown .dropdown-toggle .badge {
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar,
|
||||
.page-sidebar.in {
|
||||
margin: 0 10px 10px 10px;
|
||||
}
|
||||
|
||||
.page-header-fixed.page-header-fixed-mobile .page-sidebar,
|
||||
.page-header-fixed.page-header-fixed-mobile .page-sidebar.in {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/***
|
||||
Page title
|
||||
***/
|
||||
.page-title small {
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/***
|
||||
Forms
|
||||
***/
|
||||
.portlet .form-horizontal .form-actions {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/***
|
||||
Dashboard date range panel
|
||||
***/
|
||||
.page-content .breadcrumb .dashboard-date-range {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.page-content .breadcrumb .dashboard-date-range span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-content .breadcrumb > .btn-group span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-content .breadcrumb > .btn-group > .btn {
|
||||
padding-left: 7px;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
/***
|
||||
Hidden phone
|
||||
***/
|
||||
.hidden-480 {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
The Most Extra Small Devices Portrait Mode Only
|
||||
***/
|
||||
|
||||
@media (max-width: 320px) {
|
||||
|
||||
/***
|
||||
Hidden phone
|
||||
***/
|
||||
.hidden-320 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header.navbar .navbar-brand {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
@ -1,356 +0,0 @@
|
||||
/***
|
||||
Blue theme
|
||||
***/
|
||||
/***
|
||||
Reset and overrides
|
||||
***/
|
||||
body {
|
||||
background-color: #1570a6 !important;
|
||||
}
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header {
|
||||
filter: none !important;
|
||||
background-image: none !important;
|
||||
background-color: #0f4e74 !important;
|
||||
}
|
||||
.header .btn-navbar {
|
||||
background-color: #0f4e74 !important;
|
||||
}
|
||||
.header .navbar-nav .dropdown-toggle:hover,
|
||||
.header .navbar-nav .dropdown.open .dropdown-toggle {
|
||||
color: #fff;
|
||||
background-color: #146a9d !important;
|
||||
}
|
||||
.header .navbar-nav li.dropdown .dropdown-toggle i {
|
||||
color: #68bbec !important;
|
||||
}
|
||||
/***
|
||||
Header Search
|
||||
***/
|
||||
.header .search-form {
|
||||
background-color: #0B4263;
|
||||
}
|
||||
|
||||
.header .search-form .form-control{
|
||||
color: #68bbec;
|
||||
border: 0;
|
||||
background-color: #0B4263;
|
||||
}
|
||||
|
||||
.header .search-form .submit {
|
||||
background: url(../../img/search-icon-blue.png);
|
||||
}
|
||||
|
||||
/***
|
||||
Hor menu
|
||||
***/
|
||||
.header .hor-menu ul.nav li a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.open > a,
|
||||
.header .hor-menu ul.nav li > a:hover,
|
||||
.header .hor-menu ul.nav li > a:focus {
|
||||
color: #fff;
|
||||
background: #146a9d;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu li:hover > a,
|
||||
.header .hor-menu ul.nav li.active > a,
|
||||
.header .hor-menu ul.nav li.active > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.current > a,
|
||||
.header .hor-menu ul.nav li.current > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu {
|
||||
background: #146a9d;
|
||||
}
|
||||
.header .hor-menu .dropdown-menu li > a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .hor-menu-search-form-toggler.off {
|
||||
background: #146a9d url(../../img/hor-menu-search-close-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form {
|
||||
background:#146a9d;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form .btn {
|
||||
color: #ccc;
|
||||
background: url(../../img/search-icon-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/***
|
||||
Mega Menu
|
||||
***/
|
||||
.mega-menu .mega-menu-submenu {
|
||||
border-right: 1px solid #1876AD;
|
||||
}
|
||||
|
||||
.mega-menu .mega-menu-submenu li h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #1570a6;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #1c95dc !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li a i {
|
||||
color: #7fc5ef;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #12618f;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a {
|
||||
background: #cc1d1d !important;
|
||||
border-top-color: transparent !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a i {
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
|
||||
border-top: 0px !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
color: #ffffff !important;
|
||||
background: #1b8fd3 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
background: #1b8fd3 !important;
|
||||
}
|
||||
/* 3rd level sub menu */
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li.open > a {
|
||||
color: #ffffff !important;
|
||||
background: #1b8fd3 !important;
|
||||
}
|
||||
/* font color for all sub menu links*/
|
||||
ul.page-sidebar-menu li > ul.sub-menu > li > a {
|
||||
color: #c3e4f7;
|
||||
}
|
||||
/* menu arrows */
|
||||
ul.page-sidebar-menu > li > a .arrow:before,
|
||||
ul.page-sidebar-menu > li > a .arrow.open:before {
|
||||
color: #51b1e9 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
|
||||
color: #3ba6e6 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a > .arrow.open:before {
|
||||
color: #68bbec !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .arrow:before,
|
||||
ul.page-sidebar-menu > li.active > a .arrow.open:before {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/* sidebar search */
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #0f5179 !important;
|
||||
color: #51b1e9;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #51b1e9 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #51b1e9 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #51b1e9 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #1570a6 !important;
|
||||
color: #bfbfbf !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom: 1px solid #51b1e9 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .submit {
|
||||
background-image: url(../../img/search-icon-blue.png);
|
||||
}
|
||||
/***
|
||||
Sidebar toggler
|
||||
***/
|
||||
.sidebar-toggler {
|
||||
background-image: url(../../img/sidebar-toggler-blue.jpg);
|
||||
background-color: #0f5179;
|
||||
}
|
||||
/* search box bg color on expanded */
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
background-color: #1570a6 !important;
|
||||
}
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-image: url("../../img/sidebar-search-close-blue.png");
|
||||
}
|
||||
/* sub menu bg color on hover menu item */
|
||||
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
|
||||
background-color: #1570a6;
|
||||
}
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer .footer-inner {
|
||||
color: #68bbec;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #1985c6;
|
||||
}
|
||||
.footer .footer-tools .go-top:hover {
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70);
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #68bbec;
|
||||
}
|
||||
/***
|
||||
Footer Layouts (new in v1.3)
|
||||
***/
|
||||
/* begin:fixed footer */
|
||||
.page-footer-fixed .footer {
|
||||
background-color: #0f5179;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-inner {
|
||||
color: #68bbec;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top {
|
||||
background-color: #1985c6;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top i {
|
||||
color: #68bbec;
|
||||
}
|
||||
/* end:fixed footer */
|
||||
/***
|
||||
Gritter Notifications
|
||||
***/
|
||||
.gritter-top {
|
||||
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left -30px !important;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left bottom !important;
|
||||
}
|
||||
.gritter-item {
|
||||
display: block;
|
||||
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left -40px !important;
|
||||
}
|
||||
.gritter-close {
|
||||
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left top !important;
|
||||
}
|
||||
.gritter-title {
|
||||
text-shadow: none !important;
|
||||
/* Not supported by IE :( */
|
||||
|
||||
}
|
||||
/* for the light (white) version of the gritter notice */
|
||||
.gritter-light .gritter-item,
|
||||
.gritter-light .gritter-bottom,
|
||||
.gritter-light .gritter-top,
|
||||
.gritter-light .gritter-close {
|
||||
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
|
||||
}
|
||||
.gritter-item-wrapper a {
|
||||
color: #18a5ed;
|
||||
}
|
||||
.gritter-item-wrapper a:hover {
|
||||
color: #0b6694;
|
||||
}
|
||||
/* begin: boxed page */
|
||||
@media (min-width: 992px) {
|
||||
.page-boxed {
|
||||
background-color: #125e8b !important;
|
||||
}
|
||||
.page-boxed .page-container {
|
||||
background-color: #1570a6;
|
||||
border-left: 1px solid #1c98e1;
|
||||
border-bottom: 1px solid #1c98e1;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #1c98e1;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-sidebar {
|
||||
border-left: 1px solid #1c98e1;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #1c98e1;
|
||||
border-left: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
background-color: #125e8b !important;
|
||||
}
|
||||
}
|
||||
/* end: boxed page */
|
||||
/***
|
||||
Landscape phone to portrait tablet
|
||||
***/
|
||||
@media (max-width: 991px) {
|
||||
/***
|
||||
page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #105882 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #187fbd !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #105882 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #0e4b70;
|
||||
}
|
||||
}
|
@ -1,355 +0,0 @@
|
||||
/***
|
||||
Brown theme
|
||||
***/
|
||||
/***
|
||||
Reset and overrides
|
||||
***/
|
||||
body {
|
||||
background-color: #623f18 !important;
|
||||
}
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header {
|
||||
filter: none !important;
|
||||
background-image: none !important;
|
||||
background-color: #35220d !important;
|
||||
}
|
||||
.header .btn-navbar {
|
||||
background-color: #35220d !important;
|
||||
}
|
||||
.header .navbar-nav .dropdown-toggle:hover,
|
||||
.header .navbar-nav .dropdown.open .dropdown-toggle {
|
||||
background-color: #5a3a16 !important;
|
||||
}
|
||||
.header .navbar-nav li.dropdown .dropdown-toggle i {
|
||||
color: #d18d42 !important;
|
||||
}
|
||||
/***
|
||||
Header Search
|
||||
***/
|
||||
.header .search-form {
|
||||
background-color: #241709;
|
||||
}
|
||||
|
||||
.header .search-form .form-control{
|
||||
color: #ccc;
|
||||
border: 0;
|
||||
background-color: #241709;
|
||||
}
|
||||
|
||||
.header .search-form .submit {
|
||||
background: url(../../img/search-icon-brown.png);
|
||||
}
|
||||
/***
|
||||
Hor menu
|
||||
***/
|
||||
.header .hor-menu ul.nav li a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.open > a,
|
||||
.header .hor-menu ul.nav li > a:hover,
|
||||
.header .hor-menu ul.nav li > a:focus {
|
||||
color: #fff;
|
||||
background: #5a3a16;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu li:hover > a,
|
||||
.header .hor-menu ul.nav li.active > a,
|
||||
.header .hor-menu ul.nav li.active > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.current > a,
|
||||
.header .hor-menu ul.nav li.current > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
|
||||
.header .hor-menu .dropdown-menu {
|
||||
background: #5a3a16;
|
||||
}
|
||||
.header .hor-menu .dropdown-menu li > a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .hor-menu-search-form-toggler.off {
|
||||
background: #5a3a16 url(../../img/hor-menu-search-close-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form {
|
||||
background:#5a3a16;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form .btn {
|
||||
color: #ccc;
|
||||
background: url(../../img/search-icon-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/***
|
||||
Mega Menu
|
||||
***/
|
||||
.mega-menu .mega-menu-submenu {
|
||||
border-right: 1px solid #6B451B;
|
||||
}
|
||||
|
||||
.mega-menu .mega-menu-submenu li h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #623f18;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #935f24 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li a i {
|
||||
color: #9a6d3a;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #4e3112;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a {
|
||||
background: #4e3112 !important;
|
||||
border-top-color: transparent !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a i {
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
|
||||
border-top: 0px !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
color: #ffffff !important;
|
||||
background: #8b5922 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
background: #8b5922 !important;
|
||||
}
|
||||
/* 3rd level sub menu */
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li.open > a {
|
||||
color: #ffffff !important;
|
||||
background: #8b5922 !important;
|
||||
}
|
||||
/* font color for all sub menu links*/
|
||||
ul.page-sidebar-menu li > ul.sub-menu > li > a {
|
||||
color: #e5bf94;
|
||||
}
|
||||
/* menu arrows */
|
||||
ul.page-sidebar-menu > li > a .arrow:before,
|
||||
ul.page-sidebar-menu > li > a .arrow.open:before {
|
||||
color: #c88131 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
|
||||
color: #b4742c !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a > .arrow.open:before {
|
||||
color: #d18d42 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .arrow:before,
|
||||
ul.page-sidebar-menu > li.active > a .arrow.open:before {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/* sidebar search */
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #39250e !important;
|
||||
color: #b18d65;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #b18d65 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #b18d65 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #b18d65 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #623f18 !important;
|
||||
color: #b18d65 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom: 1px solid #845f36 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .submit {
|
||||
background-image: url(../../img/search-icon-brown.png);
|
||||
}
|
||||
/***
|
||||
Sidebar toggler
|
||||
***/
|
||||
.sidebar-toggler {
|
||||
background-image: url(../../img/sidebar-toggler-brown.jpg);
|
||||
background-color: #39250e;
|
||||
}
|
||||
/* search box bg color on expanded */
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
background-color: #623f18 !important;
|
||||
}
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-image: url("../../img/sidebar-search-close-brown.png");
|
||||
}
|
||||
/* sub menu bg color on hover menu item */
|
||||
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
|
||||
background-color: #623f18;
|
||||
}
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer .footer-inner {
|
||||
color: #999999;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #7f511f;
|
||||
}
|
||||
.footer .footer-tools .go-top:hover {
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70);
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #d18d42;
|
||||
}
|
||||
/***
|
||||
Footer Layouts (new in v1.3)
|
||||
***/
|
||||
/* begin:fixed footer */
|
||||
.page-footer-fixed .footer {
|
||||
background-color: #39250e;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-inner {
|
||||
color: #999999;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top {
|
||||
background-color: #7f511f;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top i {
|
||||
color: #d18d42;
|
||||
}
|
||||
/* end:fixed footer */
|
||||
/***
|
||||
Gritter Notifications
|
||||
***/
|
||||
.gritter-top {
|
||||
background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left -30px !important;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left bottom !important;
|
||||
}
|
||||
.gritter-item {
|
||||
display: block;
|
||||
background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left -40px !important;
|
||||
}
|
||||
.gritter-close {
|
||||
background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left top !important;
|
||||
}
|
||||
.gritter-title {
|
||||
text-shadow: none !important;
|
||||
/* Not supported by IE :( */
|
||||
|
||||
}
|
||||
/* for the light (white) version of the gritter notice */
|
||||
.gritter-light .gritter-item,
|
||||
.gritter-light .gritter-bottom,
|
||||
.gritter-light .gritter-top,
|
||||
.gritter-light .gritter-close {
|
||||
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
|
||||
}
|
||||
.gritter-item-wrapper a {
|
||||
color: #b18d65;
|
||||
}
|
||||
.gritter-item-wrapper a:hover {
|
||||
color: #755a3b;
|
||||
}
|
||||
/* begin: boxed page */
|
||||
@media (min-width: 992px) {
|
||||
.page-boxed {
|
||||
background-color: #492f12 !important;
|
||||
}
|
||||
.page-boxed .page-container {
|
||||
background-color: #623f18;
|
||||
border-left: 1px solid #976125;
|
||||
border-bottom: 1px solid #976125;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #976125;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-sidebar {
|
||||
border-left: 1px solid #976125;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #976125;
|
||||
border-left: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
background-color: #492f12 !important;
|
||||
}
|
||||
}
|
||||
/* end: boxed page */
|
||||
/***
|
||||
Landscape phone to portrait tablet
|
||||
***/
|
||||
@media (max-width: 991px) {
|
||||
/***
|
||||
page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #412a10 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #764c1d !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #412a10 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #311f0c;
|
||||
}
|
||||
}
|
@ -1,370 +0,0 @@
|
||||
/***
|
||||
Default theme
|
||||
***/
|
||||
|
||||
/***
|
||||
Reset and overrides
|
||||
***/
|
||||
body {
|
||||
background-color: #3d3d3d !important;
|
||||
}
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header {
|
||||
filter: none !important;
|
||||
background-image: none !important;
|
||||
background-color: #212121 !important;
|
||||
}
|
||||
.header .btn-navbar {
|
||||
background-color: #212121 !important;
|
||||
}
|
||||
.header .navbar-nav .dropdown-toggle:hover,
|
||||
.header .navbar-nav .dropdown.open .dropdown-toggle {
|
||||
background-color: #383838 !important;
|
||||
}
|
||||
.header .navbar-nav li.dropdown .dropdown-toggle i {
|
||||
color: #8a8a8a !important;
|
||||
}
|
||||
|
||||
/***
|
||||
Header Search
|
||||
***/
|
||||
.header .search-form {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.header .search-form .form-control {
|
||||
color: #999;
|
||||
border: 0;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.header .search-form .form-control::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #777;
|
||||
}
|
||||
.header .search-form .form-control:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #777;
|
||||
}
|
||||
.header .search-form .form-control::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #777;
|
||||
}
|
||||
.header .search-form .form-control:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.header .search-form .submit {
|
||||
background: url(../../img/search-icon-light.png);
|
||||
}
|
||||
|
||||
/***
|
||||
Hor menu
|
||||
***/
|
||||
.header .hor-menu ul.nav li a {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.open > a,
|
||||
.header .hor-menu ul.nav li > a:hover,
|
||||
.header .hor-menu ul.nav li > a:focus {
|
||||
color: #fff;
|
||||
background: #383838;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu li:hover > a,
|
||||
.header .hor-menu ul.nav li.active > a,
|
||||
.header .hor-menu ul.nav li.active > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.current > a,
|
||||
.header .hor-menu ul.nav li.current > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu {
|
||||
background: #383838;
|
||||
}
|
||||
.header .hor-menu .dropdown-menu li > a {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.header .hor-menu .hor-menu-search-form-toggler.off {
|
||||
background: #383838 url(../../img/hor-menu-search-close.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form {
|
||||
background:#383838;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form .btn {
|
||||
color: #999;
|
||||
background: url(../../img/search-icon.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #999;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #999;
|
||||
}
|
||||
.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #999;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/***
|
||||
Mega Menu
|
||||
***/
|
||||
.mega-menu .mega-menu-submenu {
|
||||
border-right: 1px solid #444;
|
||||
}
|
||||
|
||||
.mega-menu .mega-menu-submenu li h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #5c5c5c !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li a i {
|
||||
color: #969696;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #303030;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a {
|
||||
background: #e02222 !important;
|
||||
border-top-color: transparent !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a i {
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
|
||||
border-top: 0px !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
color: #ffffff !important;
|
||||
background: #575757 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
background: #575757 !important;
|
||||
}
|
||||
/* 3rd level sub menu */
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li.open > a {
|
||||
color: #ffffff !important;
|
||||
background: #575757 !important;
|
||||
}
|
||||
/* font color for all sub menu links*/
|
||||
ul.page-sidebar-menu li > ul.sub-menu > li > a {
|
||||
color: #bdbdbd;
|
||||
}
|
||||
/* menu arrows */
|
||||
ul.page-sidebar-menu > li > a .arrow:before,
|
||||
ul.page-sidebar-menu > li > a .arrow.open:before {
|
||||
color: #7d7d7d !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
|
||||
color: #707070 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a > .arrow.open:before {
|
||||
color: #8a8a8a !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .arrow:before,
|
||||
ul.page-sidebar-menu > li.active > a .arrow.open:before {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/* sidebar search */
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #242424 !important;
|
||||
color: #7d7d7d;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #7d7d7d !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #7d7d7d !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #7d7d7d !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #3d3d3d !important;
|
||||
color: #bfbfbf !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom: 1px solid #7d7d7d !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .submit {
|
||||
background-image: url(../../img/search-icon.png);
|
||||
}
|
||||
/***
|
||||
Sidebar toggler
|
||||
***/
|
||||
.sidebar-toggler {
|
||||
background-image: url(../../img/sidebar-toggler.jpg);
|
||||
background-color: #242424;
|
||||
}
|
||||
/* search box bg color on expanded */
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
background-color: #3d3d3d !important;
|
||||
}
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-image: url("../../img/sidebar-search-close.png");
|
||||
}
|
||||
/* sub menu bg color on hover menu item */
|
||||
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer .footer-inner {
|
||||
color: #999999;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #4f4f4f;
|
||||
}
|
||||
.footer .footer-tools .go-top:hover {
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70);
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #8a8a8a;
|
||||
}
|
||||
/***
|
||||
Footer Layouts (new in v1.3)
|
||||
***/
|
||||
/* begin:fixed footer */
|
||||
.page-footer-fixed .footer {
|
||||
background-color: #242424;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-inner {
|
||||
color: #999999;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top {
|
||||
background-color: #4f4f4f;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top i {
|
||||
color: #8a8a8a;
|
||||
}
|
||||
/* end:fixed footer */
|
||||
/***
|
||||
Gritter Notifications
|
||||
***/
|
||||
.gritter-top {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left -30px !important;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left bottom !important;
|
||||
}
|
||||
.gritter-item {
|
||||
display: block;
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left -40px !important;
|
||||
}
|
||||
.gritter-close {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left top !important;
|
||||
}
|
||||
.gritter-title {
|
||||
text-shadow: none !important;
|
||||
/* Not supported by IE :( */
|
||||
|
||||
}
|
||||
/* for the light (white) version of the gritter notice */
|
||||
.gritter-light .gritter-item,
|
||||
.gritter-light .gritter-bottom,
|
||||
.gritter-light .gritter-top,
|
||||
.gritter-light .gritter-close {
|
||||
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
|
||||
}
|
||||
.gritter-item-wrapper a {
|
||||
color: #18a5ed;
|
||||
}
|
||||
.gritter-item-wrapper a:hover {
|
||||
color: #0b6694;
|
||||
}
|
||||
/* begin: boxed page */
|
||||
@media (min-width: 992px) {
|
||||
.page-boxed {
|
||||
background-color: #2e2e2e !important;
|
||||
}
|
||||
.page-boxed .page-container {
|
||||
background-color: #3d3d3d;
|
||||
border-left: 1px solid #5e5e5e;
|
||||
border-bottom: 1px solid #5e5e5e;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #5e5e5e;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-sidebar {
|
||||
border-left: 1px solid #5e5e5e;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #5e5e5e;
|
||||
border-left: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
background-color: #2e2e2e !important;
|
||||
}
|
||||
}
|
||||
/* end: boxed page */
|
||||
/***
|
||||
Landscape phone to portrait tablet
|
||||
***/
|
||||
@media (max-width: 991px) {
|
||||
/***
|
||||
page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #292929 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #4a4a4a !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #292929 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #1e1e1e;
|
||||
}
|
||||
}
|
@ -1,354 +0,0 @@
|
||||
/***
|
||||
Grey theme
|
||||
***/
|
||||
/***
|
||||
Reset and overrides
|
||||
***/
|
||||
body {
|
||||
background-color: #666666 !important;
|
||||
}
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header {
|
||||
filter: none !important;
|
||||
background-image: none !important;
|
||||
background-color: #4a4a4a !important;
|
||||
}
|
||||
.header .btn-navbar {
|
||||
background-color: #4a4a4a !important;
|
||||
}
|
||||
.header .navbar-nav .dropdown-toggle:hover,
|
||||
.header .navbar-nav .dropdown.open .dropdown-toggle {
|
||||
background-color: #616161 !important;
|
||||
}
|
||||
.header .navbar-nav li.dropdown .dropdown-toggle i {
|
||||
color: #b3b3b3 !important;
|
||||
}
|
||||
/***
|
||||
Header Search
|
||||
***/
|
||||
.header .search-form {
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.header .search-form .form-control{
|
||||
color: #ccc;
|
||||
border: 0;
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.header .search-form .submit {
|
||||
background: url(../../img/search-icon-light.png);
|
||||
}
|
||||
/***
|
||||
Hor menu
|
||||
***/
|
||||
.header .hor-menu ul.nav li a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.open > a,
|
||||
.header .hor-menu ul.nav li > a:hover,
|
||||
.header .hor-menu ul.nav li > a:focus {
|
||||
color: #fff;
|
||||
background: #616161;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu li:hover > a,
|
||||
.header .hor-menu ul.nav li.active > a,
|
||||
.header .hor-menu ul.nav li.active > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.current > a,
|
||||
.header .hor-menu ul.nav li.current > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu {
|
||||
background: #616161;
|
||||
}
|
||||
.header .hor-menu .dropdown-menu li > a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .hor-menu-search-form-toggler.off {
|
||||
background: #616161 url(../../img/hor-menu-search-close-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form {
|
||||
background:#616161;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form .btn {
|
||||
color: #ccc;
|
||||
background: url(../../img/search-icon-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/***
|
||||
Mega Menu
|
||||
***/
|
||||
.mega-menu .mega-menu-submenu {
|
||||
border-right: 1px solid #757575;
|
||||
}
|
||||
|
||||
.mega-menu .mega-menu-submenu li h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #666666;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #858585 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li a i {
|
||||
color: #bfbfbf;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #595959;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a {
|
||||
background: #e02222 !important;
|
||||
border-top-color: transparent !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a i {
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
|
||||
border-top: 0px !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
color: #ffffff !important;
|
||||
background: #808080 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
background: #808080 !important;
|
||||
}
|
||||
/* 3rd level sub menu */
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li.open > a {
|
||||
color: #ffffff !important;
|
||||
background: #808080 !important;
|
||||
}
|
||||
/* font color for all sub menu links*/
|
||||
ul.page-sidebar-menu li > ul.sub-menu > li > a {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
/* menu arrows */
|
||||
ul.page-sidebar-menu > li > a .arrow:before,
|
||||
ul.page-sidebar-menu > li > a .arrow.open:before {
|
||||
color: #a6a6a6 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
|
||||
color: #999999 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a > .arrow.open:before {
|
||||
color: #b3b3b3 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .arrow:before,
|
||||
ul.page-sidebar-menu > li.active > a .arrow.open:before {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/* sidebar search */
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #4d4d4d !important;
|
||||
color: #a6a6a6;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #a6a6a6 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #a6a6a6 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #a6a6a6 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #666666 !important;
|
||||
color: #bfbfbf !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom: 1px solid #a6a6a6 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .submit {
|
||||
background-image: url(../../img/search-icon.png);
|
||||
}
|
||||
/***
|
||||
Sidebar toggler
|
||||
***/
|
||||
.sidebar-toggler {
|
||||
background-image: url(../../img/sidebar-toggler.jpg);
|
||||
background-color: #4d4d4d;
|
||||
}
|
||||
/* search box bg color on expanded */
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
background-color: #666666 !important;
|
||||
}
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-image: url("../../img/sidebar-search-close.png");
|
||||
}
|
||||
/* sub menu bg color on hover menu item */
|
||||
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
|
||||
background-color: #666666;
|
||||
}
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer .footer-inner {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #787878;
|
||||
}
|
||||
.footer .footer-tools .go-top:hover {
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70);
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
/***
|
||||
Footer Layouts (new in v1.3)
|
||||
***/
|
||||
/* begin:fixed footer */
|
||||
.page-footer-fixed .footer {
|
||||
background-color: #4d4d4d;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-inner {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top {
|
||||
background-color: #787878;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top i {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
/* end:fixed footer */
|
||||
/***
|
||||
Gritter Notifications
|
||||
***/
|
||||
.gritter-top {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left -30px !important;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left bottom !important;
|
||||
}
|
||||
.gritter-item {
|
||||
display: block;
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left -40px !important;
|
||||
}
|
||||
.gritter-close {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left top !important;
|
||||
}
|
||||
.gritter-title {
|
||||
text-shadow: none !important;
|
||||
/* Not supported by IE :( */
|
||||
|
||||
}
|
||||
/* for the light (white) version of the gritter notice */
|
||||
.gritter-light .gritter-item,
|
||||
.gritter-light .gritter-bottom,
|
||||
.gritter-light .gritter-top,
|
||||
.gritter-light .gritter-close {
|
||||
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
|
||||
}
|
||||
.gritter-item-wrapper a {
|
||||
color: #18a5ed;
|
||||
}
|
||||
.gritter-item-wrapper a:hover {
|
||||
color: #0b6694;
|
||||
}
|
||||
/* begin: boxed page */
|
||||
@media (min-width: 992px) {
|
||||
.page-boxed {
|
||||
background-color: #575757 !important;
|
||||
}
|
||||
.page-boxed .page-container {
|
||||
background-color: #666666;
|
||||
border-left: 1px solid #878787;
|
||||
border-bottom: 1px solid #878787;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #878787;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-sidebar {
|
||||
border-left: 1px solid #878787;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #878787;
|
||||
border-left: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
background-color: #575757 !important;
|
||||
}
|
||||
}
|
||||
/* end: boxed page */
|
||||
/***
|
||||
Landscape phone to portrait tablet
|
||||
***/
|
||||
@media (max-width: 991px) {
|
||||
/***
|
||||
page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #525252 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #737373 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #525252 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #474747;
|
||||
}
|
||||
}
|
@ -1,454 +0,0 @@
|
||||
/***
|
||||
light theme
|
||||
***/
|
||||
|
||||
/***
|
||||
Reset and overrides
|
||||
***/
|
||||
body {
|
||||
background-color: #fafafa !important;
|
||||
}
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header {
|
||||
filter: none !important;
|
||||
background-image: none !important;
|
||||
background-color: #434343 !important;
|
||||
}
|
||||
.header .btn-navbar {
|
||||
background-color: #434343 !important;
|
||||
}
|
||||
.header .navbar-nav .dropdown-toggle:hover,
|
||||
.header .navbar-nav .dropdown.open .dropdown-toggle {
|
||||
background-color: #4f4f4f !important;
|
||||
}
|
||||
.header .navbar-nav li.dropdown .dropdown-toggle i {
|
||||
color: #808080 !important;
|
||||
}
|
||||
/***
|
||||
Header Search
|
||||
***/
|
||||
.header .search-form {
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.header .search-form .form-control{
|
||||
color: #ccc;
|
||||
border: 0;
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.header .search-form .submit {
|
||||
background: url(../../img/search-icon.png);
|
||||
}
|
||||
/***
|
||||
Hor menu
|
||||
***/
|
||||
.header .hor-menu ul.nav li a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.open > a,
|
||||
.header .hor-menu ul.nav li > a:hover,
|
||||
.header .hor-menu ul.nav li > a:focus {
|
||||
color: #fff;
|
||||
background: #4f4f4f;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu li:hover > a,
|
||||
.header .hor-menu ul.nav li.active > a,
|
||||
.header .hor-menu ul.nav li.active > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.current > a,
|
||||
.header .hor-menu ul.nav li.current > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu {
|
||||
background: #4f4f4f;
|
||||
}
|
||||
.header .hor-menu .dropdown-menu li > a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .hor-menu-search-form-toggler.off {
|
||||
background: #4f4f4f url(../../img/hor-menu-search-close-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form {
|
||||
background:#4f4f4f;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form .btn {
|
||||
color: #ccc;
|
||||
background: url(../../img/search-icon-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/***
|
||||
Mega Menu
|
||||
***/
|
||||
.mega-menu .mega-menu-submenu {
|
||||
border-right: 1px solid #656565;
|
||||
}
|
||||
|
||||
.mega-menu .mega-menu-submenu li h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-content {
|
||||
border-left: 1px solid #e2e2e2 !important;
|
||||
border-bottom: 1px solid #e2e2e2 !important;
|
||||
}
|
||||
.page-sidebar-reversed .page-content {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #e2e2e2 !important;
|
||||
}
|
||||
.page-sidebar {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.page-sidebar-fixed .page-content {
|
||||
border: 0 !important;
|
||||
}
|
||||
.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #e2e2e2 !important;
|
||||
}
|
||||
|
||||
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #e2e2e2 !important;
|
||||
color: #000 !important;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu > li:first-child > a {
|
||||
border-top: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu > li a i {
|
||||
color: #bbb !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #eee;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .selected {
|
||||
right:-7px;
|
||||
top:0px;
|
||||
width: 7px;
|
||||
height: 39px;
|
||||
background-image: url("../../img/sidebar-menu-arrow-green.png");
|
||||
}
|
||||
.page-sidebar-reversed ul.page-sidebar-menu > li.active > a .selected {
|
||||
right: auto;
|
||||
left:-7px;
|
||||
background-image: url("../../img/sidebar-menu-arrow-green-reverse.png");
|
||||
}
|
||||
ul.page-sidebar-menu > li.active i {
|
||||
color: #fff !important;
|
||||
}
|
||||
.page-sidebar-fixed ul.page-sidebar-menu > li.active > a .selected {
|
||||
display: none;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a{
|
||||
background: #28b779 !important;
|
||||
border-top-color: transparent !important;
|
||||
color:#fff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a i {
|
||||
color: #fff;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a > .arrow:before,
|
||||
ul.page-sidebar-menu > li > a > .arrow.open:before {
|
||||
color: #ccc !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .arrow:before,
|
||||
ul.page-sidebar-menu > li.active > a .arrow.open:before {
|
||||
color: #fff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
|
||||
border-top: 0px !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu ul.sub-menu > li > a {
|
||||
font-weight: 400 !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
ul.page-sidebar-menu ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu ul.sub-menu > li > a:hover {
|
||||
color: #818181 !important;
|
||||
background: #efefef !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
/* sub menu links effects */
|
||||
ul.page-sidebar-menu ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu ul.sub-menu > li > a:hover,
|
||||
ul.page-sidebar-menu ul.sub-menu > li.open > a {
|
||||
color: #818181 !important;
|
||||
background: #efefef !important;
|
||||
}
|
||||
ul.page-sidebar-menu ul.sub-menu > li > a i {
|
||||
color: #bbb !important;
|
||||
}
|
||||
|
||||
/* sidebar search */
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #fbfbfb !important;
|
||||
color: #727272 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #aaa !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #aaa !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #aaa !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom: 1px solid #e2e2e2 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .submit {
|
||||
background-image: url(../../img/search-icon-white.png);
|
||||
}
|
||||
|
||||
/***
|
||||
Sidebar toggler
|
||||
***/
|
||||
.sidebar-toggler {
|
||||
background-image: url(../../img/sidebar-toggler-light.jpg);
|
||||
background-color: #333;
|
||||
}
|
||||
/* search box bg color on expanded */
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
background-color: #fbfbfb !important;
|
||||
}
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-image: url("../../img/sidebar-search-close-light.png");
|
||||
}
|
||||
/* sub menu bg color on hover menu item */
|
||||
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer .footer-inner {
|
||||
color: #333333;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #666666;
|
||||
}
|
||||
.footer .footer-tools .go-top:hover {
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70);
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #999999;
|
||||
}
|
||||
/***
|
||||
Footer Layouts (new in v1.3)
|
||||
***/
|
||||
/* begin:fixed footer */
|
||||
.page-footer-fixed .footer {
|
||||
background-color: #434343;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-inner {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top {
|
||||
background-color: #666666;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top i {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
/* end:fixed footer */
|
||||
/***
|
||||
Gritter Notifications
|
||||
***/
|
||||
.gritter-top {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left -30px !important;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left bottom !important;
|
||||
}
|
||||
.gritter-item {
|
||||
display: block;
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left -40px !important;
|
||||
}
|
||||
.gritter-close {
|
||||
background: url(../../plugins/gritter/images/gritter.png) no-repeat left top !important;
|
||||
}
|
||||
.gritter-title {
|
||||
text-shadow: none !important;
|
||||
/* Not supported by IE :( */
|
||||
|
||||
}
|
||||
/* for the light (white) version of the gritter notice */
|
||||
.gritter-light .gritter-item,
|
||||
.gritter-light .gritter-bottom,
|
||||
.gritter-light .gritter-top,
|
||||
.gritter-light .gritter-close {
|
||||
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
|
||||
}
|
||||
.gritter-item-wrapper a {
|
||||
color: #18a5ed;
|
||||
}
|
||||
.gritter-item-wrapper a:hover {
|
||||
color: #0b6694;
|
||||
}
|
||||
/* begin: boxed page */
|
||||
@media (min-width: 992px) {
|
||||
.page-boxed {
|
||||
background-color: #E8E8E8 !important;
|
||||
}
|
||||
.page-boxed .page-container {
|
||||
background-color: #fafafa;
|
||||
border-left: 1px solid #e2e2e2;
|
||||
border-bottom: 1px solid #e2e2e2;
|
||||
}
|
||||
.page-sidebar-reversed.page-boxed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #e2e2e2;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-sidebar {
|
||||
border-left: 1px solid #e2e2e2;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #e2e2e2;
|
||||
border-left: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
background-color: #E8E8E8 !important;
|
||||
}
|
||||
}
|
||||
/* end: boxed page */
|
||||
/***
|
||||
Landscape phone to portrait tablet
|
||||
***/
|
||||
@media (max-width: 991px) {
|
||||
/***
|
||||
page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #f1f1f1 !important;
|
||||
border-right: none !important;
|
||||
}
|
||||
.page-sidebar-fixed .page-sidebar {
|
||||
border-right: none !important;
|
||||
}
|
||||
.page-content {
|
||||
border-left: none !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #ccc !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover {
|
||||
color: #666666 !important;
|
||||
background-color: #dddddd !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a {
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a {
|
||||
color: #ffffff !important;
|
||||
background-color: #28b779 !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu ul.sub-menu > li > a {
|
||||
color: #111 !important;
|
||||
}
|
||||
|
||||
ul.page-sidebar-menu ul.sub-menu > li.open > a,
|
||||
ul.page-sidebar-menu ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu ul.sub-menu > li > a:hover {
|
||||
color: #666666 !important;
|
||||
background: #dddddd !important;
|
||||
}
|
||||
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #f1f1f1 !important;
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom-color: #ccc !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #ccc !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #ccc !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
/***
|
||||
page footer
|
||||
***/
|
||||
|
||||
.footer {
|
||||
background-color: #434343;
|
||||
}
|
||||
|
||||
.footer .footer-inner {
|
||||
color: #cccccc;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #666666;
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
body {
|
||||
background-color: #333 !important;
|
||||
}
|
||||
}
|
@ -1,354 +0,0 @@
|
||||
/***
|
||||
Purple theme
|
||||
***/
|
||||
/***
|
||||
Reset and overrides
|
||||
***/
|
||||
body {
|
||||
background-color: #701584 !important;
|
||||
}
|
||||
/***
|
||||
Page header
|
||||
***/
|
||||
.header {
|
||||
filter: none !important;
|
||||
background-image: none !important;
|
||||
background-color: #470d54 !important;
|
||||
}
|
||||
.header .btn-navbar {
|
||||
background-color: #470d54 !important;
|
||||
}
|
||||
.header .navbar-nav .dropdown-toggle:hover,
|
||||
.header .navbar-nav .dropdown.open .dropdown-toggle {
|
||||
background-color: #69147b !important;
|
||||
}
|
||||
.header .navbar-nav li.dropdown .dropdown-toggle i {
|
||||
color: #c84fe3 !important;
|
||||
}
|
||||
/***
|
||||
Header Search
|
||||
***/
|
||||
.header .search-form {
|
||||
background-color: #360A40;
|
||||
}
|
||||
|
||||
.header .search-form .form-control{
|
||||
color: #ccc;
|
||||
border: 0;
|
||||
background-color: #360A40;
|
||||
}
|
||||
|
||||
.header .search-form .submit {
|
||||
background: url(../../img/search-icon-purple.png);
|
||||
}
|
||||
/***
|
||||
Hor menu
|
||||
***/
|
||||
.header .hor-menu ul.nav li a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.open > a,
|
||||
.header .hor-menu ul.nav li > a:hover,
|
||||
.header .hor-menu ul.nav li > a:focus {
|
||||
color: #fff;
|
||||
background: #69147b;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu li:hover > a,
|
||||
.header .hor-menu ul.nav li.active > a,
|
||||
.header .hor-menu ul.nav li.active > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu ul.nav li.current > a,
|
||||
.header .hor-menu ul.nav li.current > a:hover {
|
||||
color: #fff;
|
||||
background: #e02222 !important;
|
||||
}
|
||||
|
||||
.header .hor-menu .dropdown-menu {
|
||||
background: #69147b;
|
||||
}
|
||||
.header .hor-menu .dropdown-menu li > a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .hor-menu-search-form-toggler.off {
|
||||
background: #69147b url(../../img/hor-menu-search-close-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form {
|
||||
background:#69147b;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form .btn {
|
||||
color: #ccc;
|
||||
background: url(../../img/search-icon-white.png) no-repeat center;
|
||||
}
|
||||
|
||||
.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */
|
||||
color: #ccc;
|
||||
}
|
||||
.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/***
|
||||
Mega Menu
|
||||
***/
|
||||
.mega-menu .mega-menu-submenu {
|
||||
border-right: 1px solid #78188C;
|
||||
}
|
||||
|
||||
.mega-menu .mega-menu-submenu li h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/***
|
||||
Page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #701584;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #9d1db9 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li a i {
|
||||
color: #cf65e7;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #5d116e;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a {
|
||||
background: #571067 !important;
|
||||
border-top-color: transparent !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a i {
|
||||
color: #ffffff;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
|
||||
border-top: 0px !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
color: #ffffff !important;
|
||||
background: #951cb0 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
|
||||
background: #951cb0 !important;
|
||||
}
|
||||
/* 3rd level sub menu */
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu li.open > a {
|
||||
color: #ffffff !important;
|
||||
background: #951cb0 !important;
|
||||
}
|
||||
/* font color for all sub menu links*/
|
||||
ul.page-sidebar-menu li > ul.sub-menu > li > a {
|
||||
color: #e4a7f1;
|
||||
}
|
||||
/* menu arrows */
|
||||
ul.page-sidebar-menu > li > a .arrow:before,
|
||||
ul.page-sidebar-menu > li > a .arrow.open:before {
|
||||
color: #c239df !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
|
||||
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
|
||||
color: #bb23dc !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a > .arrow.open:before {
|
||||
color: #c84fe3 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.active > a .arrow:before,
|
||||
ul.page-sidebar-menu > li.active > a .arrow.open:before {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/* sidebar search */
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #4b0e58 !important;
|
||||
color: #bf55d7;
|
||||
}
|
||||
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
|
||||
color: #b84dd0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-moz-placeholder {
|
||||
color: #b84dd0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input:-ms-input-placeholder {
|
||||
color: #b84dd0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #701584 !important;
|
||||
color: #bfbfbf !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .input-box {
|
||||
border-bottom: 1px solid #a93bc1 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search .submit {
|
||||
background-image: url(../../img/search-icon-purple.png);
|
||||
}
|
||||
/***
|
||||
Sidebar toggler
|
||||
***/
|
||||
.sidebar-toggler {
|
||||
background-image: url(../../img/sidebar-toggler-purple.jpg);
|
||||
background-color: #4b0e58;
|
||||
}
|
||||
/* search box bg color on expanded */
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {
|
||||
background-color: #701584 !important;
|
||||
}
|
||||
.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {
|
||||
background-image: url("../../img/sidebar-search-close-purple.png");
|
||||
}
|
||||
/* sub menu bg color on hover menu item */
|
||||
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
|
||||
background-color: #701584;
|
||||
}
|
||||
/***
|
||||
Footer
|
||||
***/
|
||||
.footer .footer-inner {
|
||||
color: #c84fe3;
|
||||
}
|
||||
.footer .footer-tools .go-top {
|
||||
background-color: #8a1aa3;
|
||||
}
|
||||
.footer .footer-tools .go-top:hover {
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70);
|
||||
}
|
||||
.footer .footer-tools .go-top i {
|
||||
color: #c84fe3;
|
||||
}
|
||||
/***
|
||||
Footer Layouts (new in v1.3)
|
||||
***/
|
||||
/* begin:fixed footer */
|
||||
.page-footer-fixed .footer {
|
||||
background-color: #4b0e58;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-inner {
|
||||
color: #c84fe3;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top {
|
||||
background-color: #8a1aa3;
|
||||
}
|
||||
.page-footer-fixed .footer .footer-tools .go-top i {
|
||||
color: #c84fe3;
|
||||
}
|
||||
/* end:fixed footer */
|
||||
/***
|
||||
Gritter Notifications
|
||||
***/
|
||||
.gritter-top {
|
||||
background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left -30px !important;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left bottom !important;
|
||||
}
|
||||
.gritter-item {
|
||||
display: block;
|
||||
background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left -40px !important;
|
||||
}
|
||||
.gritter-close {
|
||||
background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left top !important;
|
||||
}
|
||||
.gritter-title {
|
||||
text-shadow: none !important;
|
||||
/* Not supported by IE :( */
|
||||
|
||||
}
|
||||
/* for the light (white) version of the gritter notice */
|
||||
.gritter-light .gritter-item,
|
||||
.gritter-light .gritter-bottom,
|
||||
.gritter-light .gritter-top,
|
||||
.gritter-light .gritter-close {
|
||||
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
|
||||
}
|
||||
.gritter-item-wrapper a {
|
||||
color: #18a5ed;
|
||||
}
|
||||
.gritter-item-wrapper a:hover {
|
||||
color: #0b6694;
|
||||
}
|
||||
/* begin: boxed page */
|
||||
@media (min-width: 992px) {
|
||||
.page-boxed {
|
||||
background-color: #5a116a !important;
|
||||
}
|
||||
.page-boxed .page-container {
|
||||
background-color: #701584;
|
||||
border-left: 1px solid #a11ebd;
|
||||
border-bottom: 1px solid #a11ebd;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 1px solid #a11ebd;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-container {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed .page-sidebar {
|
||||
border-left: 1px solid #a11ebd;
|
||||
}
|
||||
.page-boxed.page-sidebar-reversed.page-sidebar-fixed .page-sidebar {
|
||||
border-right: 1px solid #a11ebd;
|
||||
border-left: 0;
|
||||
}
|
||||
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
|
||||
background-color: #5a116a !important;
|
||||
}
|
||||
}
|
||||
/* end: boxed page */
|
||||
/***
|
||||
Landscape phone to portrait tablet
|
||||
***/
|
||||
@media (max-width: 991px) {
|
||||
/***
|
||||
page sidebar
|
||||
***/
|
||||
.page-sidebar {
|
||||
background-color: #520f61 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li > a {
|
||||
border-top: 1px solid #83189a !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li:last-child > a {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
.page-sidebar .sidebar-search input {
|
||||
background-color: #520f61 !important;
|
||||
}
|
||||
ul.page-sidebar-menu > li.open > a,
|
||||
ul.page-sidebar-menu > li > a:hover,
|
||||
ul.page-sidebar-menu > li:hover > a {
|
||||
background: #430d4f;
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1011 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 514 B |
Before Width: | Height: | Size: 240 B |
Before Width: | Height: | Size: 269 B |
Before Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 330 B |
Before Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 256 B |
Before Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 345 B |
Before Width: | Height: | Size: 260 B |
Before Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 193 B |
Before Width: | Height: | Size: 247 B |
Before Width: | Height: | Size: 243 B |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 8.0 KiB |
@ -1,96 +0,0 @@
|
||||
var Login = function () {
|
||||
|
||||
var handleLogin = function() {
|
||||
$('.login-form').validate({
|
||||
errorElement: 'span', //default input error message container
|
||||
errorClass: 'help-block', // default input error message class
|
||||
focusInvalid: false, // do not focus the last invalid input
|
||||
rules: {
|
||||
username: {
|
||||
required: true
|
||||
},
|
||||
password: {
|
||||
required: true
|
||||
},
|
||||
validateCode: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
messages: {
|
||||
username: {
|
||||
required: '请输入登录账户'
|
||||
},
|
||||
password: {
|
||||
required: '请输入登录密码 '
|
||||
},
|
||||
validateCode: {
|
||||
required: '请输入验证码'
|
||||
}
|
||||
},
|
||||
|
||||
invalidHandler: function (event, validator) { //display error alert on form submit
|
||||
//$('.alert-danger', $('.login-form')).show();
|
||||
$('#msg_v').show();
|
||||
$('#msg').hide();
|
||||
},
|
||||
|
||||
highlight: function (element) { // hightlight error inputs
|
||||
$(element).closest('.form-group').addClass('has-error'); // set error class to the control group
|
||||
},
|
||||
|
||||
success: function (label) {
|
||||
label.closest('.form-group').removeClass('has-error');
|
||||
label.remove();
|
||||
},
|
||||
|
||||
errorPlacement: function (error, element) {
|
||||
error.insertAfter(element.closest('.input-icon'));
|
||||
},
|
||||
|
||||
submitHandler: function (form) {
|
||||
//$('.alert-danger', $('.login-form'))[1].show();
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
|
||||
$('.login-form input').keypress(function (e) {
|
||||
if (e.which == 13) {
|
||||
if ($('.login-form').validate().form()) {
|
||||
$('.login-form').submit();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
//main function to initiate the module
|
||||
init: function () {
|
||||
|
||||
handleLogin();
|
||||
|
||||
$.backstretch([
|
||||
"assets/custom/img/bg/1.jpg",
|
||||
"assets/custom/img/bg/2.jpg",
|
||||
"assets/custom/img/bg/3.jpg",
|
||||
"assets/custom/img/bg/4.jpg"
|
||||
], {
|
||||
fade: 1000,
|
||||
duration: 8000
|
||||
});
|
||||
|
||||
// image click
|
||||
$('#captchaImg').click(function() {
|
||||
var img = $(this);
|
||||
img.attr('src', 'captcha?_d=' + Date.now());
|
||||
});
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
$(function() {
|
||||
Login.init();
|
||||
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
|
||||
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
|
||||
});
|
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 261 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 958 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 43 B |
Before Width: | Height: | Size: 980 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 43 B |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 602 B |
Before Width: | Height: | Size: 9.9 KiB |
@ -1,153 +0,0 @@
|
||||
function randomWord() {
|
||||
let things = ["admiring", "adoring", "affectionate", "agitated", "amazing",
|
||||
"angry", "awesome", "beautiful", "blissful", "bold", "boring",
|
||||
"brave", "busy", "charming", "clever", "cool", "compassionate", "competent",
|
||||
"confident", "dazzling", "determined", "sweet", "sad", "silly",
|
||||
"relaxed", "romantic", "sad", "serene", "sharp", "quirky", "scared",
|
||||
"sleepy", "stoic", "strange", "suspicious", "sweet", "tender", "thirsty",
|
||||
"trusting", "unruffled", "upbeat", "vibrant", "vigilant", "vigorous",
|
||||
"wizardly", "wonderful", "youthful", "zealous", "zen"];
|
||||
|
||||
let names = ["austin", "borg", "bohr", "wozniak", "bose", "wu", "wing", "wilson",
|
||||
"boyd", "guss", "jobs", "hawking", "hertz", "ford", "solomon", "spence",
|
||||
"turing", "torvalds", "morse", "ford", "penicillin", "lovelace", "davinci",
|
||||
"darwin", "buck", "brown", "benz", "boss", "allen", "gates", "bose",
|
||||
"edison", "einstein", "feynman", "ferman", "franklin", "lincoln", "jefferson",
|
||||
"mandela", "gandhi", "curie", "newton", "tesla", "faraday", "bell",
|
||||
"aristotle", "hubble", "nobel", "pascal", "washington", "galileo"];
|
||||
|
||||
let n1 = things[Math.floor(Math.random() * things.length)];
|
||||
let n2 = names[Math.floor(Math.random() * names.length)];
|
||||
return `${n1}_${n2}`;
|
||||
}
|
||||
|
||||
function copyClipboard(element) {
|
||||
element.select();
|
||||
element.setSelectionRange(0, 99999);
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
function isValidURL(str) {
|
||||
let pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
|
||||
return !!pattern.test(str);
|
||||
}
|
||||
|
||||
function requestGeoPosition() {
|
||||
// console.log('Requesting GeoLocation data from the browser...');
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.watchPosition(showGeoPosition, logGeoLocationError,
|
||||
{maximumAge: 600000, timeout: 8000, enableHighAccuracy: true});
|
||||
} else {
|
||||
console.log('Browser does not support Geo Location');
|
||||
}
|
||||
}
|
||||
|
||||
function logGeoLocationError(error) {
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
console.log('User denied the request for GeoLocation.');
|
||||
break;
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
console.log('Location information is unavailable.');
|
||||
break;
|
||||
case error.TIMEOUT:
|
||||
console.log('The request to get user location timed out.');
|
||||
break;
|
||||
default:
|
||||
console.log('An unknown error occurred.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function showGeoPosition(position) {
|
||||
let loc = `${position.coords.latitude},${position.coords.longitude},${position.coords.accuracy},${position.timestamp}`;
|
||||
console.log(`Tracking geolocation for ${loc}`);
|
||||
$('[name="geolocation"]').val(loc);
|
||||
}
|
||||
|
||||
|
||||
function preserveAnchorTagOnForm() {
|
||||
$('#fm1').submit(() => {
|
||||
let location = self.document.location;
|
||||
|
||||
let action = $('#fm1').attr('action');
|
||||
if (action === undefined) {
|
||||
action = location.href;
|
||||
} else {
|
||||
action += location.search + location.hash;
|
||||
}
|
||||
$('#fm1').attr('action', action);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function preventFormResubmission() {
|
||||
$('form').submit(() => {
|
||||
$(':submit').attr('disabled', true);
|
||||
let altText = $(':submit').attr('data-processing-text');
|
||||
if (altText) {
|
||||
$(':submit').attr('value', altText);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function writeToSessionStorage(value) {
|
||||
if (typeof (Storage) !== "undefined") {
|
||||
window.sessionStorage.removeItem("sessionStorage");
|
||||
window.sessionStorage.setItem('sessionStorage', value);
|
||||
console.log(`Stored ${value} in session storage`);
|
||||
} else {
|
||||
console.log("Browser does not support session storage for write-ops");
|
||||
}
|
||||
}
|
||||
|
||||
function readFromSessionStorage() {
|
||||
if (typeof (Storage) !== "undefined") {
|
||||
let sessionStorage = window.sessionStorage.getItem("sessionStorage");
|
||||
console.log(`Read ${sessionStorage} in session storage`);
|
||||
window.localStorage.removeItem("sessionStorage");
|
||||
return sessionStorage;
|
||||
} else {
|
||||
console.log("Browser does not support session storage for read-ops");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function resourceLoadedSuccessfully() {
|
||||
$(document).ready(() => {
|
||||
if (trackGeoLocation) {
|
||||
requestGeoPosition();
|
||||
}
|
||||
|
||||
if ($(':focus').length === 0) {
|
||||
$('input:visible:enabled:first').focus();
|
||||
}
|
||||
|
||||
preserveAnchorTagOnForm();
|
||||
preventFormResubmission();
|
||||
$('#fm1 input[name="username"],[name="password"]').trigger('input');
|
||||
$('#fm1 input[name="username"]').focus();
|
||||
|
||||
$('.reveal-password').click(ev => {
|
||||
if ($('.pwd').attr('type') !== 'text') {
|
||||
$('.pwd').attr('type', 'text');
|
||||
$(".reveal-password-icon").removeClass("mdi mdi-eye").addClass("mdi mdi-eye-off");
|
||||
} else {
|
||||
$('.pwd').attr('type', 'password');
|
||||
$(".reveal-password-icon").removeClass("mdi mdi-eye-off").addClass("mdi mdi-eye");
|
||||
}
|
||||
ev.preventDefault();
|
||||
});
|
||||
// console.log(`JQuery Ready: ${typeof (jqueryReady)}`);
|
||||
if (typeof (jqueryReady) == 'function') {
|
||||
jqueryReady();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
$(document).ready(function () {
|
||||
optionSelected();
|
||||
tabify(mdc);
|
||||
});
|
||||
|
||||
|
||||
function tabify(material) {
|
||||
let elm = document.getElementById('consent-tabs');
|
||||
let tabs = material.tabBar.MDCTabBar.attachTo(elm);
|
||||
|
||||
tabs.listen('MDCTabBar:activated', function (ev) {
|
||||
let index = ev.detail.index;
|
||||
$('.consent-tab').addClass('d-none');
|
||||
$('#consent-tab-' + index).removeClass('d-none');
|
||||
});
|
||||
|
||||
tabs.foundation.adapter.activateTabAtIndex(0);
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
function optionSelected() {
|
||||
var v = $('input[name=option]:checked', '#fm1').val();
|
||||
if (v == 0) {
|
||||
$('#reminderPanel').hide();
|
||||
$('#reminderTab').hide();
|
||||
} else {
|
||||
$('#reminderPanel').show();
|
||||
$('#reminderTab').show();
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
(function(e,t){if(typeof define==="function"&&define.amd){define([],t)}else if(typeof module==="object"&&module.exports){module.exports=t()}else{var o=t();o._onReady(o.init);e.Duo=o}})(this,function(){var e=/^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/;var t=/^ERR\|[\w\s\.\(\)]+$/;var o=/^DUO_OPEN_WINDOW\|/;var n=["duo.com","duosecurity.com","duomobile.s3-us-west-1.amazonaws.com"];var i="duo_iframe",a="",r="sig_response",s,u,f,d,m,c;function l(e,t){throw new Error("Duo Web SDK error: "+e+(t?"\n"+"See "+t+" for more information":""))}function h(e){return e.replace(/([a-z])([A-Z])/,"$1-$2").toLowerCase()}function p(e,t){if("dataset"in e){return e.dataset[t]}else{return e.getAttribute("data-"+h(t))}}function g(e,t,o,n){if("addEventListener"in window){e.addEventListener(t,n,false)}else{e.attachEvent(o,n)}}function w(e,t,o,n){if("removeEventListener"in window){e.removeEventListener(t,n,false)}else{e.detachEvent(o,n)}}function v(e){g(document,"DOMContentLoaded","onreadystatechange",e)}function _(e){w(document,"DOMContentLoaded","onreadystatechange",e)}function b(e){g(window,"message","onmessage",e)}function E(e){w(window,"message","onmessage",e)}function y(e){if(!e){return}if(e.indexOf("ERR|")===0){l(e.split("|")[1])}if(e.indexOf(":")===-1||e.split(":").length!==2){l("Duo was given a bad token. This might indicate a configuration "+"problem with one of Duo's client libraries.","https://www.duosecurity.com/docs/duoweb#first-steps")}var t=e.split(":");u=e;f=t[0];d=t[1];return{sigRequest:e,duoSig:t[0],appSig:t[1]}}function D(){m=document.getElementById(i);if(!m){throw new Error("This page does not contain an iframe for Duo to use."+'Add an element like <iframe id="duo_iframe"></iframe> '+"to this page. "+"See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe "+"for more information.")}q();_(D)}function O(n){return Boolean(n.origin==="https://"+s&&typeof n.data==="string"&&(n.data.match(e)||n.data.match(t)||n.data.match(o)))}function R(e){if(e){if(e.host){s=e.host}if(e.sig_request){y(e.sig_request)}if(e.post_action){a=e.post_action}if(e.post_argument){r=e.post_argument}if(e.iframe){if(e.iframe.tagName){m=e.iframe}else if(typeof e.iframe==="string"){i=e.iframe}}if(typeof e.submit_callback==="function"){c=e.submit_callback}}if(m){q()}else{m=document.getElementById(i);if(m){q()}else{v(D)}}_(R)}function A(e){if(O(e)){if(e.data.match(o)){var t=e.data.substring("DUO_OPEN_WINDOW|".length);if(L(t)){window.open(t,"_self")}}else{B(e.data);E(A)}}}function L(e){if(!e){return false}var t=document.createElement("a");t.href=e;if(t.protocol==="duotrustedendpoints:"){return true}else if(t.protocol!=="https:"){return false}for(var o=0;o<n.length;o++){if(t.hostname.endsWith("."+n[o])||t.hostname===n[o]){return true}}return false}function q(){if(!s){s=p(m,"host");if(!s){l("No API hostname is given for Duo to use. Be sure to pass "+"a `host` parameter to Duo.init, or through the `data-host` "+"attribute on the iframe element.","https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe")}}if(!f||!d){y(p(m,"sigRequest"));if(!f||!d){l("No valid signed request is given. Be sure to give the "+"`sig_request` parameter to Duo.init, or use the "+"`data-sig-request` attribute on the iframe element.","https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe")}}if(a===""){a=p(m,"postAction")||a}if(r==="sig_response"){r=p(m,"postArgument")||r}m.src=["https://",s,"/frame/web/v1/auth?tx=",f,"&parent=",encodeURIComponent(document.location.href),"&v=2.6"].join("");b(A)}function B(e){var t=document.createElement("input");t.type="hidden";t.name=r;t.value=e+":"+d;var o=document.getElementById("duo_form");if(!o){o=document.createElement("form");m.parentElement.insertBefore(o,m.nextSibling)}o.method="POST";o.action=a;o.appendChild(t);if(typeof c==="function"){c.call(null,o)}else{o.submit()}}return{init:R,_onReady:v,_parseSigRequest:y,_isDuoMessage:O,_doPostBack:B}});
|
@ -1,64 +0,0 @@
|
||||
((material, $) => {
|
||||
let cas = {
|
||||
init: () => {
|
||||
cas.attachFields();
|
||||
material.autoInit();
|
||||
},
|
||||
attachFields: () => {
|
||||
new material.textField.MDCTextFieldHelperText(document.querySelectorAll('.mdc-text-field-helper-text'));
|
||||
|
||||
let divs = document.querySelectorAll('.mdc-text-field'),
|
||||
field;
|
||||
let div;
|
||||
for (i = 0; i < divs.length; ++i) {
|
||||
div = divs[i];
|
||||
field = material.textField.MDCTextField.attachTo(div);
|
||||
if (div.classList.contains('caps-check')) {
|
||||
field.foundation.adapter.registerInputInteractionHandler('keypress', cas.checkCaps);
|
||||
}
|
||||
}
|
||||
let selector = document.querySelector('.mdc-select');
|
||||
if (selector != null) {
|
||||
const select = new material.select.MDCSelect(selector);
|
||||
select.listen('MDCSelect:change', () => {
|
||||
$('#source').val(select.value);
|
||||
});
|
||||
$('#source').val(select.value);
|
||||
}
|
||||
|
||||
let tooltips = document.querySelectorAll('.mdc-tooltip');
|
||||
if (tooltips != null) {
|
||||
tooltips.forEach(t => {
|
||||
new material.tooltip.MDCTooltip(t);
|
||||
})
|
||||
}
|
||||
let banners = document.querySelectorAll('.mdc-banner');
|
||||
if (banners != null) {
|
||||
banners.forEach(b => {
|
||||
new material.banner.MDCBanner(b);
|
||||
})
|
||||
}
|
||||
},
|
||||
checkCaps: ev => {
|
||||
let s = String.fromCharCode(ev.which);
|
||||
let el = ev.target.parentElement.nextElementSibling.nextElementSibling;
|
||||
if (el != null) {
|
||||
if (s.toUpperCase() === s && s.toLowerCase() !== s && !ev.shiftKey) {
|
||||
// console.log('CAPSLOCK is on');
|
||||
el.classList.remove("caps-warn");
|
||||
el.classList.add('caps-on');
|
||||
} else {
|
||||
// console.log('CAPSLOCK is off')
|
||||
el.classList.remove("caps-on");
|
||||
el.classList.add('caps-warn');
|
||||
}
|
||||
} else {
|
||||
console.log("Unable to locate element for CAPSLOCK")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
cas.init();
|
||||
});
|
||||
})(mdc, jQuery);
|
@ -1,168 +0,0 @@
|
||||
/* global jqueryReady, policyPattern, zxcvbn, passwordStrengthI18n */
|
||||
/*eslint-disable no-unused-vars*/
|
||||
function jqueryReady() {
|
||||
var strength = passwordStrengthI18n;
|
||||
|
||||
$.fn.zxcvbnProgressBar = function (options) {
|
||||
|
||||
//init settings
|
||||
var settings = $.extend({
|
||||
allProgressBarClasses: 'progress-bar-danger progress-bar-warning progress-bar-success progress-bar-striped active',
|
||||
progressBarClass0: 'progress-bar-danger',
|
||||
progressBarClass1: 'progress-bar-danger',
|
||||
progressBarClass2: 'progress-bar-warning',
|
||||
progressBarClass3: 'progress-bar-success',
|
||||
progressBarClass4: 'progress-bar-success'
|
||||
}, options);
|
||||
|
||||
return this.each(function () {
|
||||
settings.progressBar = this;
|
||||
//init progress bar display
|
||||
UpdateProgressBar();
|
||||
//Update progress bar on each keypress of password input
|
||||
$(settings.passwordInput).keyup(function (event) {
|
||||
UpdateProgressBar();
|
||||
});
|
||||
});
|
||||
|
||||
function setProgress(value, bar) {
|
||||
var materialBar = bar.foundation;
|
||||
if (materialBar) {
|
||||
materialBar.setProgress(value > 0 ? value / 100 : 0);
|
||||
} else {
|
||||
$(bar).find('#progress-strength-indicator').css('width', value + '%');
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateProgressBar() {
|
||||
var progressBar = settings.progressBar;
|
||||
|
||||
var indicator = document.getElementById('progress-strength-indicator');
|
||||
var password = document.getElementById('password').value;
|
||||
|
||||
if (password) {
|
||||
var result = zxcvbn(password, settings.userInputs);
|
||||
//result.score: 0, 1, 2, 3 or 4 - if crack time is less than 10**2, 10**4, 10**6, 10**8, Infinity.
|
||||
var scorePercentage = (result.score + 1) * 20;
|
||||
setProgress(scorePercentage, settings.bar);
|
||||
|
||||
if (result.score == 0) {
|
||||
//weak
|
||||
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass0);
|
||||
$(indicator).html(strength[0]);
|
||||
}
|
||||
else if (result.score == 1) {
|
||||
//normal
|
||||
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass1);
|
||||
$(indicator).html(strength[1]);
|
||||
}
|
||||
else if (result.score == 2) {
|
||||
//medium
|
||||
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass2);
|
||||
$(indicator).html(strength[2]);
|
||||
}
|
||||
else if (result.score == 3) {
|
||||
//strong
|
||||
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass3);
|
||||
$(indicator).html(strength[3]);
|
||||
}
|
||||
else if (result.score == 4) {
|
||||
//very strong
|
||||
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass4);
|
||||
$(indicator).html(strength[4]);
|
||||
}
|
||||
} else {
|
||||
setProgress(0);
|
||||
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass0);
|
||||
$(indicator).html('');
|
||||
}
|
||||
}
|
||||
};
|
||||
var policyPatternRegex = new RegExp(policyPattern);
|
||||
var password = document.getElementById('password');
|
||||
var confirmed = document.getElementById('confirmedPassword');
|
||||
var barElement = document.getElementById('strengthProgressBar');
|
||||
var bar;
|
||||
|
||||
if (typeof mdc !== 'undefined') {
|
||||
bar = new mdc.linearProgress.MDCLinearProgress(barElement);
|
||||
} else {
|
||||
bar = $(barElement);
|
||||
}
|
||||
|
||||
|
||||
password.addEventListener('input', validate);
|
||||
confirmed.addEventListener('input', validate);
|
||||
|
||||
var alertSettings = {
|
||||
allAlertClasses: 'mdi-close-circle mdi-alert-circle mdi-information mdi-check-circle text-danger text-warning text-secondary text-success',
|
||||
alertClassDanger: 'mdi-close-circle text-danger',
|
||||
alertClassWarning: 'mdi-alert-circle text-warning',
|
||||
alertClassInfo: 'mdi-information text-secondary',
|
||||
alertClassSuccess: 'mdi-check-circle text-success'
|
||||
};
|
||||
|
||||
function validate() {
|
||||
var val = password.value;
|
||||
var cnf = confirmed.value;
|
||||
|
||||
$('#password-strength-msg').hide();
|
||||
$('#password-policy-violation-msg').hide();
|
||||
$('#password-confirm-mismatch-msg').hide();
|
||||
|
||||
var passwordPolicyViolated = val === '' || !policyPatternRegex.test(val);
|
||||
var passwordMismatch = val !== '' && val !== cnf;
|
||||
var disableSubmit = passwordPolicyViolated || passwordMismatch;
|
||||
$('#submit').prop('disabled', disableSubmit);
|
||||
|
||||
var result = zxcvbn(val);
|
||||
$('#strengthProgressBar').zxcvbnProgressBar({ passwordInput: 'password', bar: bar });
|
||||
|
||||
// Check strength, update the text indicator
|
||||
if (val !== '') {
|
||||
$('#strengthProgressBar').removeClass('d-none');
|
||||
$('#password-strength-warning').text(result.feedback.warning);
|
||||
$('#password-strength-suggestions').text(result.feedback.suggestions.join(' ').trim());
|
||||
|
||||
var clz = alertSettings.alertClassDanger;
|
||||
switch (result.score) {
|
||||
case 0:
|
||||
case 1:
|
||||
clz = alertSettings.alertClassDanger;
|
||||
break;
|
||||
case 2:
|
||||
clz = alertSettings.alertClassWarning;
|
||||
break;
|
||||
case 3:
|
||||
clz = alertSettings.alertClassInfo;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
default:
|
||||
clz = alertSettings.alertClassSuccess;
|
||||
break;
|
||||
}
|
||||
|
||||
$('#password-strength-icon').removeClass(alertSettings.allAlertClasses).addClass(clz);
|
||||
// Check for suggestions
|
||||
if (result.feedback.warning > 0 || result.feedback.suggestions.length > 0) {
|
||||
$('#password-strength-msg').show();
|
||||
}
|
||||
} else {
|
||||
$('#password-strength-icon').removeClass(alertSettings.allAlertClasses);
|
||||
$('#password-strength-warning').text('');
|
||||
$('#password-strength-suggestions').text('');
|
||||
}
|
||||
|
||||
// Check for mismatch
|
||||
if (passwordMismatch && cnf !== '') {
|
||||
$('#password-confirm-mismatch-msg').show();
|
||||
}
|
||||
|
||||
// Check password policy
|
||||
if (passwordPolicyViolated) {
|
||||
$('#password-policy-violation-msg').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
function IdPSelectUIParms(){
|
||||
this.alwaysShow = true; // If true, this will show results as soon as you start typing
|
||||
this.defaultLanguage = 'en'; // Language to use if the browser local doesnt have a bundle
|
||||
|
||||
this.defaultLogoWidth = 64;
|
||||
this.defaultLogoHeight = 64 ;
|
||||
//this.defaultReturn = null; // If non null, then the default place to send users who are not
|
||||
// Approaching via the Discovery Protocol for example
|
||||
//this.defaultReturn = "https://example.org/Shibboleth.sso/DS?SAMLDS=1&target=https://example.org/secure";
|
||||
//this.defaultReturnIDParam = "";
|
||||
this.returnWhiteList = [];
|
||||
//this.helpURL = 'https://wiki.shibboleth.net/confluence/display/SHIB2/DSRoadmap';
|
||||
this.ie6Hack = null; // An array of structures to disable when drawing the pull down (needed to
|
||||
// handle the ie6 z axis problem
|
||||
this.insertAtDiv = 'idpSelect'; // The div where we will insert the data
|
||||
this.maxResults = 10; // How many results to show at once or the number at which to
|
||||
// start showing if alwaysShow is false
|
||||
this.preferredIdP = null; // Array of entityIds to always show
|
||||
this.hiddenIdPs = null; // Array of entityIds to delete
|
||||
this.ignoreKeywords = false; // Do we ignore the <mdui:Keywords/> when looking for candidates
|
||||
this.showListFirst = false; // Do we start with a list of IdPs or just the dropdown
|
||||
this.samlIdPCookieTTL = 730; // in days
|
||||
this.setFocusTextBox = true; // Set to false to suppress focus
|
||||
this.testGUI = false;
|
||||
|
||||
this.autoFollowCookie = '_shibboleth_eds'; // If you want auto-dispatch, set this to the cookie name to use
|
||||
this.autoFollowCookieTTLs = [ 1, 60, 270 ]; // Cookie life (in days). Changing this requires changes to idp_select_languages
|
||||
|
||||
//
|
||||
// Language support.
|
||||
//
|
||||
// The minified source provides "en", "de", "pt-br" and "jp".
|
||||
//
|
||||
// Override any of these below, or provide your own language
|
||||
//
|
||||
//this.langBundles = {
|
||||
//'en': {
|
||||
// 'fatal.divMissing': '<div> specified as "insertAtDiv" could not be located in the HTML',
|
||||
// 'fatal.noXMLHttpRequest': 'Browser does not support XMLHttpRequest, unable to load IdP selection data',
|
||||
// 'fatal.wrongProtocol' : 'Policy supplied to DS was not "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single"',
|
||||
// 'fatal.wrongEntityId' : 'entityId supplied by SP did not match configuration',
|
||||
// 'fatal.noData' : 'Metadata download returned no data',
|
||||
// 'fatal.loadFailed': 'Failed to download metadata from ',
|
||||
// 'fatal.noparms' : 'No parameters to discovery session and no defaultReturn parameter configured',
|
||||
// 'fatal.noReturnURL' : "No URL return parameter provided",
|
||||
// 'fatal.badProtocol' : "Return request must start with https:// or http://",
|
||||
// 'idpPreferred.label': 'Use a suggested selection:',
|
||||
// 'idpEntry.label': 'Or enter your organization\'s name',
|
||||
// 'idpEntry.NoPreferred.label': 'Enter your organization\'s name',
|
||||
// 'idpList.label': 'Or select your organization from the list below',
|
||||
// 'idpList.NoPreferred.label': 'Select your organization from the list below',
|
||||
// 'idpList.defaultOptionLabel': 'Please select your organization...',
|
||||
// 'idpList.showList' : 'Allow me to pick from a list',
|
||||
// 'idpList.showSearch' : 'Allow me to specify the site',
|
||||
// 'submitButton.label': 'Continue',
|
||||
// 'helpText': 'Help',
|
||||
// 'defaultLogoAlt' : 'DefaultLogo'
|
||||
//}
|
||||
//};
|
||||
|
||||
//
|
||||
// The following should not be changed without changes to the css. Consider them as mandatory defaults
|
||||
//
|
||||
this.maxPreferredIdPs = 5;
|
||||
this.maxIdPCharsButton = 33;
|
||||
this.maxIdPCharsDropDown = 58;
|
||||
this.maxIdPCharsAltTxt = 60;
|
||||
|
||||
this.minWidth = 30;
|
||||
this.minHeight = 20;
|
||||
this.maxWidth = 115;
|
||||
this.maxHeight = 69;
|
||||
this.bestRatio = Math.log(80 / 60);
|
||||
|
||||
IdPSelectUIParametersForCAS(this);
|
||||
}
|
||||
|
||||
|
@ -1,748 +0,0 @@
|
||||
//Copyright 2014-2015 Google Inc. All rights reserved.
|
||||
|
||||
//Use of this source code is governed by a BSD-style
|
||||
//license that can be found in the LICENSE file or at
|
||||
//https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
/**
|
||||
* @fileoverview The U2F api.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
||||
/**
|
||||
* Namespace for the U2F api.
|
||||
* @type {Object}
|
||||
*/
|
||||
var u2f = u2f || {};
|
||||
|
||||
/**
|
||||
* FIDO U2F Javascript API Version
|
||||
* @number
|
||||
*/
|
||||
var js_api_version;
|
||||
|
||||
/**
|
||||
* The U2F extension id
|
||||
* @const {string}
|
||||
*/
|
||||
// The Chrome packaged app extension ID.
|
||||
// Uncomment this if you want to deploy a server instance that uses
|
||||
// the package Chrome app and does not require installing the U2F Chrome extension.
|
||||
u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
|
||||
// The U2F Chrome extension ID.
|
||||
// Uncomment this if you want to deploy a server instance that uses
|
||||
// the U2F Chrome extension to authenticate.
|
||||
// u2f.EXTENSION_ID = 'pfboblefjcgdjicmnffhdgionmgcdmne';
|
||||
|
||||
|
||||
/**
|
||||
* Message types for messsages to/from the extension
|
||||
* @const
|
||||
* @enum {string}
|
||||
*/
|
||||
u2f.MessageTypes = {
|
||||
'U2F_REGISTER_REQUEST': 'u2f_register_request',
|
||||
'U2F_REGISTER_RESPONSE': 'u2f_register_response',
|
||||
'U2F_SIGN_REQUEST': 'u2f_sign_request',
|
||||
'U2F_SIGN_RESPONSE': 'u2f_sign_response',
|
||||
'U2F_GET_API_VERSION_REQUEST': 'u2f_get_api_version_request',
|
||||
'U2F_GET_API_VERSION_RESPONSE': 'u2f_get_api_version_response'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Response status codes
|
||||
* @const
|
||||
* @enum {number}
|
||||
*/
|
||||
u2f.ErrorCodes = {
|
||||
'OK': 0,
|
||||
'OTHER_ERROR': 1,
|
||||
'BAD_REQUEST': 2,
|
||||
'CONFIGURATION_UNSUPPORTED': 3,
|
||||
'DEVICE_INELIGIBLE': 4,
|
||||
'TIMEOUT': 5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A message for registration requests
|
||||
* @typedef {{
|
||||
* type: u2f.MessageTypes,
|
||||
* appId: ?string,
|
||||
* timeoutSeconds: ?number,
|
||||
* requestId: ?number
|
||||
* }}
|
||||
*/
|
||||
u2f.U2fRequest;
|
||||
|
||||
|
||||
/**
|
||||
* A message for registration responses
|
||||
* @typedef {{
|
||||
* type: u2f.MessageTypes,
|
||||
* responseData: (u2f.Error | u2f.RegisterResponse | u2f.SignResponse),
|
||||
* requestId: ?number
|
||||
* }}
|
||||
*/
|
||||
u2f.U2fResponse;
|
||||
|
||||
|
||||
/**
|
||||
* An error object for responses
|
||||
* @typedef {{
|
||||
* errorCode: u2f.ErrorCodes,
|
||||
* errorMessage: ?string
|
||||
* }}
|
||||
*/
|
||||
u2f.Error;
|
||||
|
||||
/**
|
||||
* Data object for a single sign request.
|
||||
* @typedef {enum {BLUETOOTH_RADIO, BLUETOOTH_LOW_ENERGY, USB, NFC}}
|
||||
*/
|
||||
u2f.Transport;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a single sign request.
|
||||
* @typedef {Array<u2f.Transport>}
|
||||
*/
|
||||
u2f.Transports;
|
||||
|
||||
/**
|
||||
* Data object for a single sign request.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* challenge: string,
|
||||
* keyHandle: string,
|
||||
* appId: string
|
||||
* }}
|
||||
*/
|
||||
u2f.SignRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a sign response.
|
||||
* @typedef {{
|
||||
* keyHandle: string,
|
||||
* signatureData: string,
|
||||
* clientData: string
|
||||
* }}
|
||||
*/
|
||||
u2f.SignResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a registration request.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* challenge: string
|
||||
* }}
|
||||
*/
|
||||
u2f.RegisterRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a registration response.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* keyHandle: string,
|
||||
* transports: Transports,
|
||||
* appId: string
|
||||
* }}
|
||||
*/
|
||||
u2f.RegisterResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a registered key.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* keyHandle: string,
|
||||
* transports: ?Transports,
|
||||
* appId: ?string
|
||||
* }}
|
||||
*/
|
||||
u2f.RegisteredKey;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a get API register response.
|
||||
* @typedef {{
|
||||
* js_api_version: number
|
||||
* }}
|
||||
*/
|
||||
u2f.GetJsApiVersionResponse;
|
||||
|
||||
|
||||
//Low level MessagePort API support
|
||||
|
||||
/**
|
||||
* Sets up a MessagePort to the U2F extension using the
|
||||
* available mechanisms.
|
||||
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
|
||||
*/
|
||||
u2f.getMessagePort = function(callback) {
|
||||
if (typeof chrome != 'undefined' && chrome.runtime) {
|
||||
// The actual message here does not matter, but we need to get a reply
|
||||
// for the callback to run. Thus, send an empty signature request
|
||||
// in order to get a failure response.
|
||||
var msg = {
|
||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
||||
signRequests: []
|
||||
};
|
||||
chrome.runtime.sendMessage(u2f.EXTENSION_ID, msg, function() {
|
||||
if (!chrome.runtime.lastError) {
|
||||
// We are on a allowed origin and can talk directly
|
||||
// with the extension.
|
||||
u2f.getChromeRuntimePort_(callback);
|
||||
} else {
|
||||
// chrome.runtime was available, but we couldn't message
|
||||
// the extension directly, use iframe
|
||||
u2f.getIframePort_(callback);
|
||||
}
|
||||
});
|
||||
} else if (u2f.isAndroidChrome_()) {
|
||||
u2f.getAuthenticatorPort_(callback);
|
||||
} else if (u2f.isIosChrome_()) {
|
||||
u2f.getIosPort_(callback);
|
||||
} else {
|
||||
// chrome.runtime was not available at all, which is normal
|
||||
// when this origin doesn't have access to any extensions.
|
||||
u2f.getIframePort_(callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect chrome running on android based on the browser's useragent.
|
||||
* @private
|
||||
*/
|
||||
u2f.isAndroidChrome_ = function() {
|
||||
var userAgent = navigator.userAgent;
|
||||
return userAgent.indexOf('Chrome') != -1 &&
|
||||
userAgent.indexOf('Android') != -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect chrome running on iOS based on the browser's platform.
|
||||
* @private
|
||||
*/
|
||||
u2f.isIosChrome_ = function() {
|
||||
return ["iPhone", "iPad", "iPod"].indexOf(navigator.platform) > -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Connects directly to the extension via chrome.runtime.connect.
|
||||
* @param {function(u2f.WrappedChromeRuntimePort_)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getChromeRuntimePort_ = function(callback) {
|
||||
var port = chrome.runtime.connect(u2f.EXTENSION_ID,
|
||||
{'includeTlsChannelId': true});
|
||||
setTimeout(function() {
|
||||
callback(new u2f.WrappedChromeRuntimePort_(port));
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a 'port' abstraction to the Authenticator app.
|
||||
* @param {function(u2f.WrappedAuthenticatorPort_)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getAuthenticatorPort_ = function(callback) {
|
||||
setTimeout(function() {
|
||||
callback(new u2f.WrappedAuthenticatorPort_());
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a 'port' abstraction to the iOS client app.
|
||||
* @param {function(u2f.WrappedIosPort_)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getIosPort_ = function(callback) {
|
||||
setTimeout(function() {
|
||||
callback(new u2f.WrappedIosPort_());
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* A wrapper for chrome.runtime.Port that is compatible with MessagePort.
|
||||
* @param {Port} port
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedChromeRuntimePort_ = function(port) {
|
||||
this.port_ = port;
|
||||
};
|
||||
|
||||
/**
|
||||
* Format and return a sign request compliant with the JS API version supported by the extension.
|
||||
* @param {Array<u2f.SignRequest>} signRequests
|
||||
* @param {number} timeoutSeconds
|
||||
* @param {number} reqId
|
||||
* @return {Object}
|
||||
*/
|
||||
u2f.formatSignRequest_ =
|
||||
function(appId, challenge, registeredKeys, timeoutSeconds, reqId) {
|
||||
if (js_api_version === undefined || js_api_version < 1.1) {
|
||||
// Adapt request to the 1.0 JS API
|
||||
var signRequests = [];
|
||||
for (var i = 0; i < registeredKeys.length; i++) {
|
||||
signRequests[i] = {
|
||||
version: registeredKeys[i].version,
|
||||
challenge: challenge,
|
||||
keyHandle: registeredKeys[i].keyHandle,
|
||||
appId: appId
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
||||
signRequests: signRequests,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
}
|
||||
// JS 1.1 API
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
||||
appId: appId,
|
||||
challenge: challenge,
|
||||
registeredKeys: registeredKeys,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Format and return a register request compliant with the JS API version supported by the extension..
|
||||
* @param {Array<u2f.SignRequest>} signRequests
|
||||
* @param {Array<u2f.RegisterRequest>} signRequests
|
||||
* @param {number} timeoutSeconds
|
||||
* @param {number} reqId
|
||||
* @return {Object}
|
||||
*/
|
||||
u2f.formatRegisterRequest_ =
|
||||
function(appId, registeredKeys, registerRequests, timeoutSeconds, reqId) {
|
||||
if (js_api_version === undefined || js_api_version < 1.1) {
|
||||
// Adapt request to the 1.0 JS API
|
||||
for (var i = 0; i < registerRequests.length; i++) {
|
||||
registerRequests[i].appId = appId;
|
||||
}
|
||||
var signRequests = [];
|
||||
for (var i = 0; i < registeredKeys.length; i++) {
|
||||
signRequests[i] = {
|
||||
version: registeredKeys[i].version,
|
||||
challenge: registerRequests[0],
|
||||
keyHandle: registeredKeys[i].keyHandle,
|
||||
appId: appId
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
|
||||
signRequests: signRequests,
|
||||
registerRequests: registerRequests,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
}
|
||||
// JS 1.1 API
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
|
||||
appId: appId,
|
||||
registerRequests: registerRequests,
|
||||
registeredKeys: registeredKeys,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Posts a message on the underlying channel.
|
||||
* @param {Object} message
|
||||
*/
|
||||
u2f.WrappedChromeRuntimePort_.prototype.postMessage = function(message) {
|
||||
this.port_.postMessage(message);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Emulates the HTML 5 addEventListener interface. Works only for the
|
||||
* onmessage event, which is hooked up to the chrome.runtime.Port.onMessage.
|
||||
* @param {string} eventName
|
||||
* @param {function({data: Object})} handler
|
||||
*/
|
||||
u2f.WrappedChromeRuntimePort_.prototype.addEventListener =
|
||||
function(eventName, handler) {
|
||||
var name = eventName.toLowerCase();
|
||||
if (name == 'message' || name == 'onmessage') {
|
||||
this.port_.onMessage.addListener(function(message) {
|
||||
// Emulate a minimal MessageEvent object
|
||||
handler({'data': message});
|
||||
});
|
||||
} else {
|
||||
console.error('WrappedChromeRuntimePort only supports onMessage');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrap the Authenticator app with a MessagePort interface.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_ = function() {
|
||||
this.requestId_ = -1;
|
||||
this.requestObject_ = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch the Authenticator intent.
|
||||
* @param {Object} message
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.postMessage = function(message) {
|
||||
var intentUrl =
|
||||
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
|
||||
';S.request=' + encodeURIComponent(JSON.stringify(message)) +
|
||||
';end';
|
||||
document.location = intentUrl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells what type of port this is.
|
||||
* @return {String} port type
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.getPortType = function() {
|
||||
return "WrappedAuthenticatorPort_";
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Emulates the HTML 5 addEventListener interface.
|
||||
* @param {string} eventName
|
||||
* @param {function({data: Object})} handler
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.addEventListener = function(eventName, handler) {
|
||||
var name = eventName.toLowerCase();
|
||||
if (name == 'message') {
|
||||
var self = this;
|
||||
/* Register a callback to that executes when
|
||||
* chrome injects the response. */
|
||||
window.addEventListener(
|
||||
'message', self.onRequestUpdate_.bind(self, handler), false);
|
||||
} else {
|
||||
console.error('WrappedAuthenticatorPort only supports message');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback invoked when a response is received from the Authenticator.
|
||||
* @param function({data: Object}) callback
|
||||
* @param {Object} message message Object
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.onRequestUpdate_ =
|
||||
function(callback, message) {
|
||||
var messageObject = JSON.parse(message.data);
|
||||
var intentUrl = messageObject['intentURL'];
|
||||
|
||||
var errorCode = messageObject['errorCode'];
|
||||
var responseObject = null;
|
||||
if (messageObject.hasOwnProperty('data')) {
|
||||
responseObject = /** @type {Object} */ (
|
||||
JSON.parse(messageObject['data']));
|
||||
}
|
||||
|
||||
callback({'data': responseObject});
|
||||
};
|
||||
|
||||
/**
|
||||
* Base URL for intents to Authenticator.
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ =
|
||||
'intent:#Intent;action=com.google.android.apps.authenticator.AUTHENTICATE';
|
||||
|
||||
/**
|
||||
* Wrap the iOS client app with a MessagePort interface.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedIosPort_ = function() {};
|
||||
|
||||
/**
|
||||
* Launch the iOS client app request
|
||||
* @param {Object} message
|
||||
*/
|
||||
u2f.WrappedIosPort_.prototype.postMessage = function(message) {
|
||||
var str = JSON.stringify(message, undefined, 2);
|
||||
var url = "u2f://auth?" + encodeURI(str);
|
||||
location.replace(url);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells what type of port this is.
|
||||
* @return {String} port type
|
||||
*/
|
||||
u2f.WrappedIosPort_.prototype.getPortType = function() {
|
||||
return "WrappedIosPort_";
|
||||
};
|
||||
|
||||
/**
|
||||
* Emulates the HTML 5 addEventListener interface.
|
||||
* @param {string} eventName
|
||||
* @param {function({data: Object})} handler
|
||||
*/
|
||||
u2f.WrappedIosPort_.prototype.addEventListener = function(eventName, handler) {
|
||||
var name = eventName.toLowerCase();
|
||||
if (name !== 'message') {
|
||||
console.error('WrappedIosPort only supports message');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets up an embedded trampoline iframe, sourced from the extension.
|
||||
* @param {function(MessagePort)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getIframePort_ = function(callback) {
|
||||
// Create the iframe
|
||||
var iframeOrigin = 'chrome-extension://' + u2f.EXTENSION_ID;
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.src = iframeOrigin + '/u2f-comms.html';
|
||||
iframe.setAttribute('style', 'display:none');
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
var channel = new MessageChannel();
|
||||
var ready = function(message) {
|
||||
if (message.data == 'ready') {
|
||||
channel.port1.removeEventListener('message', ready);
|
||||
callback(channel.port1);
|
||||
} else {
|
||||
console.error('First event on iframe port was not "ready"');
|
||||
}
|
||||
};
|
||||
channel.port1.addEventListener('message', ready);
|
||||
channel.port1.start();
|
||||
|
||||
iframe.addEventListener('load', function() {
|
||||
// Deliver the port to the iframe and initialize
|
||||
iframe.contentWindow.postMessage('init', iframeOrigin, [channel.port2]);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//High-level JS API
|
||||
|
||||
/**
|
||||
* Default extension response timeout in seconds.
|
||||
* @const
|
||||
*/
|
||||
u2f.EXTENSION_TIMEOUT_SEC = 30;
|
||||
|
||||
/**
|
||||
* A singleton instance for a MessagePort to the extension.
|
||||
* @type {MessagePort|u2f.WrappedChromeRuntimePort_}
|
||||
* @private
|
||||
*/
|
||||
u2f.port_ = null;
|
||||
|
||||
/**
|
||||
* Callbacks waiting for a port
|
||||
* @type {Array<function((MessagePort|u2f.WrappedChromeRuntimePort_))>}
|
||||
* @private
|
||||
*/
|
||||
u2f.waitingForPort_ = [];
|
||||
|
||||
/**
|
||||
* A counter for requestIds.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
u2f.reqCounter_ = 0;
|
||||
|
||||
/**
|
||||
* A map from requestIds to client callbacks
|
||||
* @type {Object.<number,(function((u2f.Error|u2f.RegisterResponse))
|
||||
* |function((u2f.Error|u2f.SignResponse)))>}
|
||||
* @private
|
||||
*/
|
||||
u2f.callbackMap_ = {};
|
||||
|
||||
/**
|
||||
* Creates or retrieves the MessagePort singleton to use.
|
||||
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getPortSingleton_ = function(callback) {
|
||||
if (u2f.port_) {
|
||||
callback(u2f.port_);
|
||||
} else {
|
||||
if (u2f.waitingForPort_.length == 0) {
|
||||
u2f.getMessagePort(function(port) {
|
||||
u2f.port_ = port;
|
||||
u2f.port_.addEventListener('message',
|
||||
/** @type {function(Event)} */ (u2f.responseHandler_));
|
||||
|
||||
// Careful, here be async callbacks. Maybe.
|
||||
while (u2f.waitingForPort_.length)
|
||||
u2f.waitingForPort_.shift()(u2f.port_);
|
||||
});
|
||||
}
|
||||
u2f.waitingForPort_.push(callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles response messages from the extension.
|
||||
* @param {MessageEvent.<u2f.Response>} message
|
||||
* @private
|
||||
*/
|
||||
u2f.responseHandler_ = function(message) {
|
||||
var response = message.data;
|
||||
var reqId = response['requestId'];
|
||||
if (!reqId || !u2f.callbackMap_[reqId]) {
|
||||
console.error('Unknown or missing requestId in response.');
|
||||
return;
|
||||
}
|
||||
var cb = u2f.callbackMap_[reqId];
|
||||
delete u2f.callbackMap_[reqId];
|
||||
cb(response['responseData']);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches an array of sign requests to available U2F tokens.
|
||||
* If the JS API version supported by the extension is unknown, it first sends a
|
||||
* message to the extension to find out the supported API version and then it sends
|
||||
* the sign request.
|
||||
* @param {string=} appId
|
||||
* @param {string=} challenge
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.SignResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.sign = function(appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
if (js_api_version === undefined) {
|
||||
// Send a message to get the extension to JS API version, then send the actual sign request.
|
||||
u2f.getApiVersion(
|
||||
function (response) {
|
||||
js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
|
||||
console.log("Extension JS API Version: ", js_api_version);
|
||||
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
|
||||
});
|
||||
} else {
|
||||
// We know the JS API version. Send the actual sign request in the supported API version.
|
||||
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches an array of sign requests to available U2F tokens.
|
||||
* @param {string=} appId
|
||||
* @param {string=} challenge
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.SignResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.sendSignRequest = function(appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
u2f.getPortSingleton_(function(port) {
|
||||
var reqId = ++u2f.reqCounter_;
|
||||
u2f.callbackMap_[reqId] = callback;
|
||||
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
|
||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
|
||||
var req = u2f.formatSignRequest_(appId, challenge, registeredKeys, timeoutSeconds, reqId);
|
||||
port.postMessage(req);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches register requests to available U2F tokens. An array of sign
|
||||
* requests identifies already registered tokens.
|
||||
* If the JS API version supported by the extension is unknown, it first sends a
|
||||
* message to the extension to find out the supported API version and then it sends
|
||||
* the register request.
|
||||
* @param {string=} appId
|
||||
* @param {Array<u2f.RegisterRequest>} registerRequests
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.register = function(appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
if (js_api_version === undefined) {
|
||||
// Send a message to get the extension to JS API version, then send the actual register request.
|
||||
u2f.getApiVersion(
|
||||
function (response) {
|
||||
js_api_version = response['js_api_version'] === undefined ? 0: response['js_api_version'];
|
||||
console.log("Extension JS API Version: ", js_api_version);
|
||||
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
|
||||
callback, opt_timeoutSeconds);
|
||||
});
|
||||
} else {
|
||||
// We know the JS API version. Send the actual register request in the supported API version.
|
||||
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
|
||||
callback, opt_timeoutSeconds);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches register requests to available U2F tokens. An array of sign
|
||||
* requests identifies already registered tokens.
|
||||
* @param {string=} appId
|
||||
* @param {Array<u2f.RegisterRequest>} registerRequests
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.sendRegisterRequest = function(appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
u2f.getPortSingleton_(function(port) {
|
||||
var reqId = ++u2f.reqCounter_;
|
||||
u2f.callbackMap_[reqId] = callback;
|
||||
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
|
||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
|
||||
var req = u2f.formatRegisterRequest_(
|
||||
appId, registeredKeys, registerRequests, timeoutSeconds, reqId);
|
||||
port.postMessage(req);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches a message to the extension to find out the supported
|
||||
* JS API version.
|
||||
* If the user is on a mobile phone and is thus using Google Authenticator instead
|
||||
* of the Chrome extension, don't send the request and return 0.
|
||||
* @param {function((u2f.Error|u2f.GetJsApiVersionResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.getApiVersion = function(callback, opt_timeoutSeconds) {
|
||||
u2f.getPortSingleton_(function(port) {
|
||||
// If we are using Android Google Authenticator or iOS client app,
|
||||
// do not fire an intent to ask which JS API version to use.
|
||||
if (port.getPortType) {
|
||||
var apiVersion;
|
||||
switch (port.getPortType()) {
|
||||
case 'WrappedIosPort_':
|
||||
case 'WrappedAuthenticatorPort_':
|
||||
apiVersion = 1.1;
|
||||
break;
|
||||
|
||||
default:
|
||||
apiVersion = 0;
|
||||
break;
|
||||
}
|
||||
callback({ 'js_api_version': apiVersion });
|
||||
return;
|
||||
}
|
||||
var reqId = ++u2f.reqCounter_;
|
||||
u2f.callbackMap_[reqId] = callback;
|
||||
var req = {
|
||||
type: u2f.MessageTypes.U2F_GET_API_VERSION_REQUEST,
|
||||
timeoutSeconds: (typeof opt_timeoutSeconds !== 'undefined' ?
|
||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC),
|
||||
requestId: reqId
|
||||
};
|
||||
port.postMessage(req);
|
||||
});
|
||||
};
|
@ -1,581 +0,0 @@
|
||||
/**********************************
|
||||
* Base64 Core
|
||||
**********************************/
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['base64js'], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = factory(require('base64js'));
|
||||
} else {
|
||||
root.base64url = factory(root.base64js);
|
||||
}
|
||||
})(this, function (base64js) {
|
||||
|
||||
function ensureUint8Array(arg) {
|
||||
if (arg instanceof ArrayBuffer) {
|
||||
return new Uint8Array(arg);
|
||||
} else {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
function base64UrlToMime(code) {
|
||||
return code.replace(/-/g, '+').replace(/_/g, '/') + '===='.substring(0, (4 - (code.length % 4)) % 4);
|
||||
}
|
||||
|
||||
function mimeBase64ToUrl(code) {
|
||||
return code.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
||||
}
|
||||
|
||||
function fromByteArray(bytes) {
|
||||
return mimeBase64ToUrl(base64js.fromByteArray(ensureUint8Array(bytes)));
|
||||
}
|
||||
|
||||
function toByteArray(code) {
|
||||
return base64js.toByteArray(base64UrlToMime(code));
|
||||
}
|
||||
|
||||
return {
|
||||
fromByteArray: fromByteArray,
|
||||
toByteArray: toByteArray,
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*******************************************************
|
||||
* WebAuthN Core
|
||||
*******************************************************/
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['base64url'], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = factory(require('base64url'));
|
||||
} else {
|
||||
root.webauthn = factory(root.base64url);
|
||||
}
|
||||
})(this, function (base64url) {
|
||||
|
||||
function extend(obj, more) {
|
||||
return Object.assign({}, obj, more);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a WebAuthn credential.
|
||||
*
|
||||
* @param request: object - A PublicKeyCredentialCreationOptions object, except
|
||||
* where binary values are base64url encoded strings instead of byte arrays
|
||||
*
|
||||
* @return a PublicKeyCredentialCreationOptions suitable for passing as the
|
||||
* `publicKey` parameter to `navigator.credentials.create()`
|
||||
*/
|
||||
function decodePublicKeyCredentialCreationOptions(request) {
|
||||
const excludeCredentials = request.excludeCredentials.map(credential => extend(
|
||||
credential, {
|
||||
id: base64url.toByteArray(credential.id),
|
||||
}));
|
||||
|
||||
const publicKeyCredentialCreationOptions = extend(
|
||||
request, {
|
||||
attestation: 'direct',
|
||||
user: extend(
|
||||
request.user, {
|
||||
id: base64url.toByteArray(request.user.id),
|
||||
}),
|
||||
challenge: base64url.toByteArray(request.challenge),
|
||||
excludeCredentials,
|
||||
});
|
||||
|
||||
return publicKeyCredentialCreationOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a WebAuthn credential.
|
||||
*
|
||||
* @param request: object - A PublicKeyCredentialCreationOptions object, except
|
||||
* where binary values are base64url encoded strings instead of byte arrays
|
||||
*
|
||||
* @return the Promise returned by `navigator.credentials.create`
|
||||
*/
|
||||
function createCredential(request) {
|
||||
return navigator.credentials.create({
|
||||
publicKey: decodePublicKeyCredentialCreationOptions(request),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a WebAuthn assertion.
|
||||
*
|
||||
* @param request: object - A PublicKeyCredentialRequestOptions object,
|
||||
* except where binary values are base64url encoded strings instead of byte
|
||||
* arrays
|
||||
*
|
||||
* @return a PublicKeyCredentialRequestOptions suitable for passing as the
|
||||
* `publicKey` parameter to `navigator.credentials.get()`
|
||||
*/
|
||||
function decodePublicKeyCredentialRequestOptions(request) {
|
||||
const allowCredentials = request.allowCredentials && request.allowCredentials.map(credential => extend(
|
||||
credential, {
|
||||
id: base64url.toByteArray(credential.id),
|
||||
}));
|
||||
|
||||
const publicKeyCredentialRequestOptions = extend(
|
||||
request, {
|
||||
allowCredentials,
|
||||
challenge: base64url.toByteArray(request.challenge),
|
||||
});
|
||||
|
||||
return publicKeyCredentialRequestOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a WebAuthn assertion.
|
||||
*
|
||||
* @param request: object - A PublicKeyCredentialRequestOptions object,
|
||||
* except where binary values are base64url encoded strings instead of byte
|
||||
* arrays
|
||||
*
|
||||
* @return the Promise returned by `navigator.credentials.get`
|
||||
*/
|
||||
function getAssertion(request) {
|
||||
console.log('Get assertion', request);
|
||||
return navigator.credentials.get({
|
||||
publicKey: decodePublicKeyCredentialRequestOptions(request),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** Turn a PublicKeyCredential object into a plain object with base64url encoded binary values */
|
||||
function responseToObject(response) {
|
||||
if (response.u2fResponse) {
|
||||
return response;
|
||||
} else {
|
||||
let clientExtensionResults = {};
|
||||
|
||||
try {
|
||||
clientExtensionResults = response.getClientExtensionResults();
|
||||
} catch (e) {
|
||||
console.error('getClientExtensionResults failed', e);
|
||||
}
|
||||
|
||||
if (response.response.attestationObject) {
|
||||
return {
|
||||
type: response.type,
|
||||
id: response.id,
|
||||
response: {
|
||||
attestationObject: base64url.fromByteArray(response.response.attestationObject),
|
||||
clientDataJSON: base64url.fromByteArray(response.response.clientDataJSON),
|
||||
},
|
||||
clientExtensionResults,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: response.type,
|
||||
id: response.id,
|
||||
response: {
|
||||
authenticatorData: base64url.fromByteArray(response.response.authenticatorData),
|
||||
clientDataJSON: base64url.fromByteArray(response.response.clientDataJSON),
|
||||
signature: base64url.fromByteArray(response.response.signature),
|
||||
userHandle: response.response.userHandle && base64url.fromByteArray(response.response.userHandle),
|
||||
},
|
||||
clientExtensionResults,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
decodePublicKeyCredentialCreationOptions,
|
||||
decodePublicKeyCredentialRequestOptions,
|
||||
createCredential,
|
||||
getAssertion,
|
||||
responseToObject,
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* WebAuthn Utilities
|
||||
*****************************************************/
|
||||
|
||||
let ceremonyState = {};
|
||||
let session = {};
|
||||
|
||||
function extend(obj, more) {
|
||||
return Object.assign({}, obj, more);
|
||||
}
|
||||
|
||||
function rejectIfNotSuccess(response) {
|
||||
if (response.success) {
|
||||
return response;
|
||||
}
|
||||
return new Promise((resolve, reject) => reject(response));
|
||||
}
|
||||
|
||||
function updateSession(response) {
|
||||
if (response.sessionToken) {
|
||||
session.sessionToken = response.sessionToken;
|
||||
} else {
|
||||
session.sessionToken = null;
|
||||
}
|
||||
if (response.username) {
|
||||
session.username = response.username;
|
||||
} else {
|
||||
session.username = null;
|
||||
}
|
||||
updateSessionBox();
|
||||
return response;
|
||||
}
|
||||
|
||||
function logout() {
|
||||
session = {};
|
||||
updateSession({});
|
||||
}
|
||||
|
||||
function updateSessionBox() {
|
||||
const disabled = session.username == null || session.username === '';
|
||||
$('#logoutButton').prop('disabled', disabled);
|
||||
}
|
||||
|
||||
function rejected(err) {
|
||||
return new Promise((resolve, reject) => reject(err));
|
||||
}
|
||||
|
||||
function setStatus(statusText) {
|
||||
$('#status').val(statusText);
|
||||
}
|
||||
|
||||
function addDeviceAttributeAsRow(name, value) {
|
||||
let row = `<tr class="mdc-data-table__row">`
|
||||
+ `<td class="mdc-data-table__cell"><code>${name}</code></td>`
|
||||
+ `<td class="mdc-data-table__cell"><code>${value}</code></td>`
|
||||
+ `</tr>`;
|
||||
$('#deviceTable tbody').append(row);
|
||||
}
|
||||
|
||||
function addMessage(message) {
|
||||
$('#messages').html("<p>" + message + "</p>");
|
||||
}
|
||||
|
||||
function addMessages(messages) {
|
||||
messages.forEach(addMessage);
|
||||
}
|
||||
|
||||
function showJson(name, data) {
|
||||
if (data != null) {
|
||||
$('#' + name).text(JSON.stringify(data, false, 4));
|
||||
}
|
||||
}
|
||||
|
||||
function showRequest(data) {
|
||||
return showJson('request', data);
|
||||
}
|
||||
|
||||
function showAuthenticatorResponse(data) {
|
||||
const clientDataJson = data && (data.response && data.response.clientDataJSON);
|
||||
return showJson('authenticator-response', extend(
|
||||
data, {
|
||||
_clientDataJson: data && JSON.parse(new TextDecoder('utf-8').decode(base64url.toByteArray(clientDataJson))),
|
||||
}));
|
||||
}
|
||||
|
||||
function showServerResponse(data) {
|
||||
if (data && data.messages) {
|
||||
addMessages(data.messages);
|
||||
}
|
||||
return showJson('server-response', data);
|
||||
}
|
||||
|
||||
function hideDeviceInfo() {
|
||||
$("#device-info").hide();
|
||||
$("#registerButton").show();
|
||||
$("#registerDiscoverableCredentialButton").show();
|
||||
}
|
||||
|
||||
function showDeviceInfo(params) {
|
||||
$("#device-info").show();
|
||||
$("#device-name").text(params.displayName);
|
||||
$("#device-icon").attr("src", params.imageUrl);
|
||||
$("#registerButton").hide();
|
||||
$("#deviceNamePanel").hide();
|
||||
|
||||
$("#registerDiscoverableCredentialButton").hide();
|
||||
$("#residentKeysPanel").hide();
|
||||
}
|
||||
|
||||
function resetDisplays() {
|
||||
/*
|
||||
showRequest(null);
|
||||
showAuthenticatorResponse(null);
|
||||
showServerResponse(null);
|
||||
*/
|
||||
hideDeviceInfo();
|
||||
}
|
||||
|
||||
function getWebAuthnUrls() {
|
||||
let endpoints = {
|
||||
authenticate: "webauthn/authenticate",
|
||||
register: "webauthn/register",
|
||||
};
|
||||
return new Promise((resolve, reject) => resolve(endpoints)).then(data => {
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
function getRegisterRequest(urls,
|
||||
username,
|
||||
displayName,
|
||||
credentialNickname,
|
||||
requireResidentKey = false) {
|
||||
return fetch(urls.register, {
|
||||
body: new URLSearchParams({
|
||||
username,
|
||||
displayName,
|
||||
credentialNickname,
|
||||
requireResidentKey,
|
||||
sessionToken: session.sessionToken || null,
|
||||
}),
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": csrfToken
|
||||
},
|
||||
method: 'POST',
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(updateSession)
|
||||
.then(rejectIfNotSuccess);
|
||||
}
|
||||
|
||||
function executeRegisterRequest(request) {
|
||||
return webauthn.createCredential(request.publicKeyCredentialCreationOptions);
|
||||
}
|
||||
|
||||
function submitResponse(url, request, response) {
|
||||
const body = {
|
||||
requestId: request.requestId,
|
||||
credential: response,
|
||||
sessionToken: request.sessionToken || session.sessionToken || null,
|
||||
};
|
||||
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": csrfToken
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(updateSession);
|
||||
}
|
||||
|
||||
function performCeremony(params) {
|
||||
const callbacks = params.callbacks || {};
|
||||
const getWebAuthnUrls = params.getWebAuthnUrls;
|
||||
const getRequest = params.getRequest;
|
||||
const statusStrings = params.statusStrings;
|
||||
const executeRequest = params.executeRequest;
|
||||
|
||||
resetDisplays();
|
||||
|
||||
return getWebAuthnUrls()
|
||||
.then(urls => {
|
||||
setStatus(statusStrings.int);
|
||||
if (callbacks.init) {
|
||||
callbacks.init(urls);
|
||||
}
|
||||
return getRequest(urls);
|
||||
})
|
||||
|
||||
.then((params) => {
|
||||
const request = params.request;
|
||||
const urls = params.actions;
|
||||
setStatus(statusStrings.authenticatorRequest);
|
||||
if (callbacks.authenticatorRequest) {
|
||||
callbacks.authenticatorRequest({request, urls});
|
||||
}
|
||||
showRequest(request);
|
||||
ceremonyState = {
|
||||
callbacks,
|
||||
request,
|
||||
statusStrings,
|
||||
urls
|
||||
};
|
||||
return executeRequest(request)
|
||||
.then(webauthn.responseToObject);
|
||||
})
|
||||
.then(finishCeremony);
|
||||
}
|
||||
|
||||
function finishCeremony(response) {
|
||||
const callbacks = ceremonyState.callbacks;
|
||||
const request = ceremonyState.request;
|
||||
const statusStrings = ceremonyState.statusStrings;
|
||||
const urls = ceremonyState.urls;
|
||||
|
||||
setStatus(statusStrings.serverRequest || 'Sending response to server...');
|
||||
if (callbacks.serverRequest) {
|
||||
callbacks.serverRequest({urls, request, response});
|
||||
}
|
||||
showAuthenticatorResponse(response);
|
||||
|
||||
return submitResponse(urls.finish, request, response)
|
||||
.then(data => {
|
||||
if (data && data.success) {
|
||||
setStatus(statusStrings.success);
|
||||
} else {
|
||||
setStatus('Error');
|
||||
}
|
||||
showServerResponse(data);
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
function register(username, displayName, credentialNickname, csrfToken,
|
||||
requireResidentKey = false,
|
||||
getRequest = getRegisterRequest) {
|
||||
let request;
|
||||
return performCeremony({
|
||||
getWebAuthnUrls,
|
||||
getRequest: urls => getRequest(urls, username, displayName, credentialNickname, requireResidentKey),
|
||||
statusStrings: {
|
||||
init: 'Initiating registration ceremony with server...',
|
||||
authenticatorRequest: 'Asking authenticators to create credential...',
|
||||
success: 'Registration successful.',
|
||||
},
|
||||
executeRequest: req => {
|
||||
request = req;
|
||||
return executeRegisterRequest(req);
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
if (data.registration) {
|
||||
const nicknameInfo = {nickname: data.registration.credentialNickname};
|
||||
|
||||
if (data.registration && data.registration.attestationMetadata) {
|
||||
showDeviceInfo(extend(
|
||||
data.registration.attestationMetadata.deviceProperties,
|
||||
nicknameInfo
|
||||
));
|
||||
} else {
|
||||
showDeviceInfo(nicknameInfo);
|
||||
}
|
||||
|
||||
if (!data.attestationTrusted) {
|
||||
addMessage("Attestation cannot be trusted.");
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
$('#sessionToken').val(session.sessionToken);
|
||||
console.log("Submitting registration form");
|
||||
$('#form').submit();
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setStatus('Registration failed.');
|
||||
console.error('Registration failed', err);
|
||||
|
||||
if (err.name === 'NotAllowedError') {
|
||||
if (request.publicKeyCredentialCreationOptions.excludeCredentials
|
||||
&& request.publicKeyCredentialCreationOptions.excludeCredentials.length > 0
|
||||
) {
|
||||
addMessage('Credential creation failed, probably because an already registered credential is available.');
|
||||
} else {
|
||||
addMessage('Credential creation failed for an unknown reason.');
|
||||
}
|
||||
} else if (err.name === 'InvalidStateError') {
|
||||
addMessage(`This authenticator is already registered for the account "${username}".`)
|
||||
} else if (err.message) {
|
||||
addMessage(`${err.message}`);
|
||||
} else if (err.messages) {
|
||||
addMessages(err.messages);
|
||||
}
|
||||
return rejected(err);
|
||||
});
|
||||
}
|
||||
|
||||
function getAuthenticateRequest(urls, username) {
|
||||
return fetch(urls.authenticate, {
|
||||
body: new URLSearchParams(username ? {username} : {}),
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": csrfToken
|
||||
},
|
||||
method: 'POST',
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(updateSession)
|
||||
.then(rejectIfNotSuccess);
|
||||
}
|
||||
|
||||
function executeAuthenticateRequest(request) {
|
||||
console.log('Sending authentication request', request);
|
||||
return webauthn.getAssertion(request.publicKeyCredentialRequestOptions);
|
||||
}
|
||||
|
||||
function authenticate(username = null, getRequest = getAuthenticateRequest) {
|
||||
$('#deviceTable tbody tr').remove();
|
||||
$('#divDeviceInfo').hide();
|
||||
hideDeviceInfo();
|
||||
|
||||
return performCeremony({
|
||||
getWebAuthnUrls,
|
||||
getRequest: urls => getRequest(urls, username),
|
||||
statusStrings: {
|
||||
init: 'Initiating authentication ceremony...',
|
||||
authenticatorRequest: 'Asking authenticators to perform assertion...',
|
||||
success: 'Authentication successful.',
|
||||
},
|
||||
executeRequest: executeAuthenticateRequest,
|
||||
}).then(data => {
|
||||
$('#divDeviceInfo').show();
|
||||
console.log("Received: " + JSON.stringify(data, undefined, 2));
|
||||
if (data.registrations) {
|
||||
|
||||
data.registrations.forEach(reg => {
|
||||
|
||||
addDeviceAttributeAsRow("Username", reg.username);
|
||||
addDeviceAttributeAsRow("Credential Nickname", reg.credentialNickname);
|
||||
addDeviceAttributeAsRow("Registration Date", reg.registrationTime);
|
||||
addDeviceAttributeAsRow("Session Token", data.sessionToken);
|
||||
if (reg.attestationMetadata.deviceProperties) {
|
||||
addDeviceAttributeAsRow("Device Id", reg.attestationMetadata.deviceProperties.deviceId);
|
||||
addDeviceAttributeAsRow("Device Name", reg.attestationMetadata.deviceProperties.displayName);
|
||||
|
||||
showDeviceInfo({
|
||||
"displayName": reg.attestationMetadata.deviceProperties.displayName,
|
||||
"imageUrl": reg.attestationMetadata.deviceProperties.imageUrl
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
$('#authnButton').hide();
|
||||
|
||||
setTimeout(function () {
|
||||
$('#token').val(data.sessionToken);
|
||||
console.log("Submitting authentication form");
|
||||
$('#webauthnLoginForm').submit();
|
||||
}, 1500);
|
||||
}
|
||||
return data;
|
||||
}).catch((err) => {
|
||||
setStatus(authFailTitle);
|
||||
if (err.name === 'InvalidStateError') {
|
||||
addMessage(`This authenticator is not registered for the account "${username}".`)
|
||||
} else if (err.message) {
|
||||
addMessage(`${err.name}: ${err.message}`);
|
||||
} else if (err.messages) {
|
||||
addMessages(err.messages);
|
||||
}
|
||||
console.error('Authentication failed', err);
|
||||
addMessage(authFailDesc);
|
||||
return rejected(err);
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
hideDeviceInfo();
|
||||
return false;
|
||||
}
|
||||
|
||||
window.onload = init;
|
@ -1,76 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<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>Acceptto Registration View</title>
|
||||
<link href="../../static/assets/css/cas.css" rel="stylesheet" th:remove="tag" />
|
||||
|
||||
<script type="text/javascript" src="https://faye.acceptto.com/faye/faye.js"></script>
|
||||
<script type="text/javascript" src="https://dbfp.acceptto.com/bfp.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main role="main" class="container mt-3 mb-3">
|
||||
<div layout:fragment="content" id="login" class="mdc-card card p-4 m-auto w-lg-66">
|
||||
<h3>Register Device</h3>
|
||||
|
||||
<ol>
|
||||
<li>Open the app store and search for "Acceptto It's Me".</li>
|
||||
<li>Install the "Acceptto It's Me" application.</li>
|
||||
<li>Open the application and follow the instructions to access the QR Code scanner.</li>
|
||||
<li>Scan this QR Code.</li>
|
||||
</ol>
|
||||
|
||||
<div class="d-flex justify-content-center">
|
||||
<a href="https://itunes.apple.com/us/app/acceptto-itsme/id893534370?mt=8" target="_blank" class="me-2">
|
||||
<img src="https://s3-us-west-2.amazonaws.com/acceptto-log-and-graphics/Asset+14.png" alt="App Store"
|
||||
title="App Store" width="151.25" height="50">
|
||||
</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.acceptto.mfa&amp;hl=en" target="_blank">
|
||||
<img src="https://s3-us-west-2.amazonaws.com/acceptto-log-and-graphics/Asset+13.png"
|
||||
alt="Google Play" title="Google Play" width="151.25" height="50">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="POST" id="fmAccepttoQRCode">
|
||||
<script type="text/javascript" th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
$(() => {
|
||||
var invitationToken = /*[[${accepttoInvitationToken}]]*/;
|
||||
var hashCode = /*[[${accepttoInvitationTokenQRCodeHash}]]*/;
|
||||
var src = "https://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=" + hashCode + "&chld=H|0";
|
||||
$('#qrLoginCode').attr("src", src);
|
||||
var faye = new Faye.Client("https://faye.acceptto.com/faye");
|
||||
faye.subscribe("/messages/" + invitationToken,
|
||||
function (data) {
|
||||
setTimeout(function () {
|
||||
$('#fmAccepttoQRCode').submit();
|
||||
}, 2500);
|
||||
}
|
||||
);
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
<input type="hidden" name="_eventId" value="success" />
|
||||
<input type="hidden" name="execution" th:value="${flowExecutionKey}" />
|
||||
</form>
|
||||
<div class="d-flex justify-content-center flex-column align-items-center">
|
||||
<img class="autowidth my-4" id="qrLoginCode" width="250" />
|
||||
<div class="progress" style="height: 35px;">
|
||||
<div class="progress-bar bg-info progress-bar-striped progress-bar-animated" role="progressbar"
|
||||
aria-valuenow="99" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
|
||||
<span style="font-size: larger">Waiting for device registration notification...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,104 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<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"/>
|
||||
<link href="../../static/assets/css/cas.css" rel="stylesheet" th:remove="tag"/>
|
||||
</head>
|
||||
|
||||
<body id="cas">
|
||||
<main role="main" class="container mt-3 mb-3">
|
||||
<div layout:fragment="content" class="mdc-card p-4 m-auto w-lg-100">
|
||||
<script>
|
||||
function jqueryReady() {
|
||||
document.forms[0].elements[0].focus();
|
||||
}
|
||||
</script>
|
||||
|
||||
<h2 th:utext="#{cas.screen.acct.title}" />
|
||||
<p class="intro" th:utext="#{cas.screen.acct.intro}" />
|
||||
|
||||
<form method="post" id="fm1">
|
||||
<div class="banner banner-danger my-2" th:if="${flowRequestContext.messageContext.hasErrorMessages()}">
|
||||
<p th:each="message : ${flowRequestContext.messageContext.allMessages}"
|
||||
th:utext="${message.text}">Message Text</p>
|
||||
</div>
|
||||
|
||||
|
||||
<section th:each="entry : ${registrationProperties}" class="cas-field my-3">
|
||||
<div>
|
||||
<label class="mdc-text-field mdc-text-field--outlined"
|
||||
th:if="${entry.type != 'select'}">
|
||||
<input class="mdc-text-field__input"
|
||||
th:id="${entry.name}"
|
||||
th:name="${entry.name}"
|
||||
size="25"
|
||||
th:classappend="${entry.cssClass}"
|
||||
th:type="${entry.type}"
|
||||
th:attr="required=${entry.required ? 'true' : 'false'},pattern=${entry.pattern}"
|
||||
autocapitalize="none"
|
||||
th:title="#{${entry.title}}"
|
||||
spellcheck="false"
|
||||
th:autocomplete="${entry.name}"/>
|
||||
<span class="mdc-notched-outline">
|
||||
<span class="mdc-notched-outline__leading"></span>
|
||||
<span class="mdc-notched-outline__notch">
|
||||
<span class="mdc-floating-label" th:utext="#{${entry.label}}">Label</span>
|
||||
</span>
|
||||
<span class="mdc-notched-outline__trailing"></span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<select th:if="${entry.type == 'select'}"
|
||||
th:id="${entry.name}"
|
||||
th:title="#{${entry.title}}"
|
||||
th:name="${entry.name}"
|
||||
th:classappend="${'custom-select ' + entry.cssClass}">
|
||||
<option th:each="option,status : ${entry.values}" th:value="${status.index}" th:text="${option}" />
|
||||
</select>
|
||||
|
||||
<div class="mdc-text-field-helper-line" th:if="${entry.validationMessage != null}">
|
||||
<div th:id="${'helpertext-' + entry.name}"
|
||||
class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg"
|
||||
aria-hidden="true">
|
||||
<span th:if="${entry.validationMessage != null}"
|
||||
th:utext="#{${entry.validationMessage}}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<span th:if="${accountRegistrationCaptchaEnabled}">
|
||||
<div th:replace="fragments/recaptcha :: recaptchaToken" />
|
||||
</span>
|
||||
|
||||
<input type="hidden" name="execution" th:value="${flowExecutionKey}"/>
|
||||
<input type="hidden" name="_eventId" value="submit"/>
|
||||
<div class="form-actions d-flex justify-content-center">
|
||||
<button class="mdc-button mdc-button--raised me-2"
|
||||
name="submit"
|
||||
th:value="#{cas.screen.acct.button.submit}"
|
||||
id="submit"
|
||||
accesskey="s">
|
||||
<span class="mdc-button__label" th:value="#{cas.screen.acct.button.submit}">Submit</span>
|
||||
</button>
|
||||
|
||||
<button class="mdc-button mdc-button--outlined"
|
||||
name="cancel"
|
||||
th:value="#{cas.screen.acct.button.cancel}"
|
||||
accesskey="c"
|
||||
id="cancel"
|
||||
type="button"
|
||||
onclick="location.href = location.href;">
|
||||
<span class="mdc-button__label" th:text="#{cas.screen.acct.button.cancel}">CANCEL</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
@ -1,215 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<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"/>
|
||||
|
||||
<script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
|
||||
<script type="text/javascript" th:src="@{/js/passwordMeter.js}"></script>
|
||||
|
||||
<link href="../../static/assets/css/cas.css" rel="stylesheet" th:remove="tag"/>
|
||||
</head>
|
||||
|
||||
<body id="cas">
|
||||
<main role="main" class="container mt-3 mb-3">
|
||||
<div layout:fragment="content" class="mdc-card p-4 m-auto w-lg-100">
|
||||
<script th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
|
||||
let policyPattern = /*[[${passwordPolicyPattern}]]*/;
|
||||
let 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>
|
||||
|
||||
<h2 th:utext="#{cas.screen.acct.title}"/>
|
||||
<p class="intro" th:utext="#{cas.screen.acct.intro.complete}"/>
|
||||
|
||||
<form method="post" id="fm1">
|
||||
<div class="banner banner-danger my-2" th:if="${flowRequestContext.messageContext.hasErrorMessages()}">
|
||||
<p th:each="message : ${flowRequestContext.messageContext.allMessages}"
|
||||
th:utext="${message.text}">Message Text</p>
|
||||
</div>
|
||||
|
||||
<div class="cas-field my-3 mdc-input-group">
|
||||
<div class="mdc-input-group-field mdc-input-group-field-append">
|
||||
<div class="d-flex caps-check">
|
||||
<label for="password" class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-trailing-icon">
|
||||
<input class="mdc-text-field__input pwd"
|
||||
autocapitalize="none"
|
||||
spellcheck="false"
|
||||
th:attr="pattern=${passwordPolicyPattern}"
|
||||
type="password"
|
||||
name="password"
|
||||
id="password"
|
||||
autocomplete="off" required/>
|
||||
<span class="mdc-notched-outline">
|
||||
<span class="mdc-notched-outline__leading"></span>
|
||||
<span class="mdc-notched-outline__notch">
|
||||
<span class="mdc-floating-label" th:utext="#{screen.pm.enterpsw}">Enter Password:</span>
|
||||
</span>
|
||||
<span class="mdc-notched-outline__trailing"></span>
|
||||
</span>
|
||||
</label>
|
||||
<button class="reveal-password mdc-button mdc-button--raised mdc-input-group-append mdc-icon-button"
|
||||
tabindex="-1"
|
||||
type="button">
|
||||
<i class="mdi mdi-eye reveal-password-icon"></i>
|
||||
<span class="visually-hidden">Toggle Password</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="mdc-text-field-helper-line">
|
||||
<div class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg"
|
||||
th:utext="#{cas.screen.acct.error.invalid-value}"
|
||||
aria-hidden="true"/>
|
||||
</div>
|
||||
|
||||
<div class="mdc-text-field-helper-line caps-warn">
|
||||
<p class="mdc-text-field-helper-text mdc-text-field-helper-text--persistent mdc-text-field-helper-text--validation-msg text-danger">
|
||||
<span th:utext="#{screen.capslock.on}"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cas-field my-3">
|
||||
<div class="caps-check">
|
||||
<label for="confirmedPassword" class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-trailing-icon">
|
||||
<input class="mdc-text-field__input pwd"
|
||||
type="password"
|
||||
autocapitalize="none"
|
||||
spellcheck="false"
|
||||
th:attr="pattern=${passwordPolicyPattern}"
|
||||
name="confirmedPassword"
|
||||
id="confirmedPassword"
|
||||
autocomplete="off" required/>
|
||||
<span class="mdc-notched-outline">
|
||||
<span class="mdc-notched-outline__leading"></span>
|
||||
<span class="mdc-notched-outline__notch">
|
||||
<span class="mdc-floating-label" th:utext="#{screen.pm.confirmpsw}">Confirm Password:</span>
|
||||
</span>
|
||||
<span class="mdc-notched-outline__trailing"></span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="mdc-text-field-helper-line">
|
||||
<div class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg"
|
||||
th:utext="#{cas.screen.acct.error.invalid-value}"
|
||||
aria-hidden="true"/>
|
||||
</div>
|
||||
<i class="mdi mdi-alert mdc-text-field__icon text-danger caps-warn"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section th:if="${accountRegistrationSecurityQuestionsCount gt 0}">
|
||||
<div class="cas-field my-3" th:each="count : ${#numbers.sequence(1, accountRegistrationSecurityQuestionsCount)}">
|
||||
<div class="d-flex">
|
||||
<label class="mdc-text-field mdc-text-field--outlined">
|
||||
<input class="mdc-text-field__input"
|
||||
th:id="${'securityquestion' + count}"
|
||||
th:name="${'securityquestion' + count}"
|
||||
size="50"
|
||||
type="text"
|
||||
autocapitalize="none"
|
||||
spellcheck="false"/>
|
||||
<span class="mdc-notched-outline">
|
||||
<span class="mdc-notched-outline__leading"></span>
|
||||
<span class="mdc-notched-outline__notch">
|
||||
<span class="mdc-floating-label"
|
||||
th:utext="#{${'screen.acct.label.security.question.' + count}}"></span>
|
||||
</span>
|
||||
<span class="mdc-notched-outline__trailing"></span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="caps-check my-3">
|
||||
<label class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-trailing-icon">
|
||||
<input class="mdc-text-field__input pwd"
|
||||
autocapitalize="none"
|
||||
spellcheck="false"
|
||||
type="password"
|
||||
th:id="${'securityanswer' + count}"
|
||||
th:name="${'securityanswer' + count}"
|
||||
autocomplete="off" required/>
|
||||
|
||||
<span class="mdc-notched-outline">
|
||||
<span class="mdc-notched-outline__leading"></span>
|
||||
<span class="mdc-notched-outline__notch">
|
||||
<span class="mdc-floating-label" th:utext="#{screen.acct.label.security.answer}"></span>
|
||||
</span>
|
||||
<span class="mdc-notched-outline__trailing"></span>
|
||||
</span>
|
||||
</label>
|
||||
<i class="mdi mdi-alert mdc-text-field__icon text-danger caps-warn"></i>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="cas-field my-3 d-flex flex-column">
|
||||
<div class="d-flex align-items-center">
|
||||
<span th:text="#{screen.pm.password.strength}">Strength:</span>
|
||||
<span id="password-strength-icon" class="mdi" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div id="strengthProgressBar" role="progressbar" class="d-none">
|
||||
<div id="progress-strength-indicator" class="progress-bar-indicator text-center"></div>
|
||||
<div class="mdc-linear-progress">
|
||||
<div class="mdc-linear-progress__buffering-dots"></div>
|
||||
<div class="mdc-linear-progress__buffer"></div>
|
||||
<div class="mdc-linear-progress__bar mdc-linear-progress__primary-bar" style="transform: scaleX(0);">
|
||||
<span class="mdc-linear-progress__bar-inner"></span>
|
||||
</div>
|
||||
<div class="mdc-linear-progress__bar mdc-linear-progress__secondary-bar">
|
||||
<span class="mdc-linear-progress__bar-inner"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cas-field my-3 text-warning" id="password-strength-msg" style="display: none;">
|
||||
<div class="suggestions banner banner-warning p-2 mb-2 d-flex align-items-center" role="alert">
|
||||
<span class="mdi mdi-information" aria-hidden="true"></span>
|
||||
<p class="m-0">
|
||||
<span id="password-strength-warning"></span>
|
||||
<span id="password-strength-suggestions"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cas-field my-3 text-danger" id="password-strength-notes">
|
||||
<div id="password-policy-violation-msg" class="banner banner-danger p-2" role="alert" style="display: none;">
|
||||
<span class="mdi mdi-alert" aria-hidden="true"></span>
|
||||
<strong th:text="#{screen.pm.password.policyViolation}">Password does not match the password policy
|
||||
requirement.</strong>
|
||||
</div>
|
||||
<div id="password-confirm-mismatch-msg" class="banner banner-danger p-2" role="alert" style="display: none;">
|
||||
<span class="mdi mdi-alert" aria-hidden="true"></span>
|
||||
<strong th:text="#{screen.pm.password.confirmMismatch}">Passwords do not match.</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="execution" th:value="${flowExecutionKey}"/>
|
||||
<input type="hidden" name="_eventId" value="submit"/>
|
||||
<div class="form-actions d-flex justify-content-center">
|
||||
<button class="mdc-button mdc-button--raised me-2"
|
||||
name="submit"
|
||||
th:value="#{cas.screen.acct.button.submit}"
|
||||
id="submit"
|
||||
accesskey="s">
|
||||
<span class="mdc-button__label" th:value="#{cas.screen.acct.button.submit}">Submit</span>
|
||||
</button>
|
||||
|
||||
<a class="mdc-button mdc-button--outlined" th:href="@{/login}">
|
||||
<span class="mdc-button__label" th:text="#{cas.screen.acct.button.cancel}">CANCEL</span>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<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"/>
|
||||
<link href="../../static/assets/css/cas.css" rel="stylesheet" th:remove="tag"/>
|
||||
</head>
|
||||
|
||||
<body id="cas">
|
||||
<main role="main" class="container mt-3 mb-3">
|
||||
<div layout:fragment="content" class="mdc-card p-4 m-auto w-lg-100">
|
||||
<h2 th:utext="#{cas.screen.acct.title}"/>
|
||||
<p class="intro" th:utext="#{cas.screen.acct.intro.completed}"/>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|