feat: Identity brokering (#730)

* feat: add/ remove external idps

* feat: external idp add /remove

* fix: auth proto

* fix: handle login

* feat: loginpolicy on authrequest

* feat: idp providers on login

* feat: link external idp

* fix: check login policy on check username

* feat: add mapping fields for idp config

* feat: use user org id if existing

* feat: use user org id if existing

* feat: register external user

* feat: register external user

* feat: user linking

* feat: user linking

* feat: design external login

* feat: design external login

* fix: tests

* fix: regenerate login design

* feat: next step test linking process

* feat: next step test linking process

* feat: cascade remove external idps on user

* fix: tests

* fix: tests

* feat: external idp requsts on users

* fix: generate protos

* feat: login styles

* feat: login styles

* fix: link user

* fix: register user on specifig org

* fix: user linking

* fix: register external, linking auto

* fix: remove unnecessary request from proto

* fix: tests

* fix: new oidc package

* fix: migration version

* fix: policy permissions

* Update internal/ui/login/static/i18n/en.yaml

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/ui/login/static/i18n/en.yaml

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/ui/login/handler/renderer.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/ui/login/handler/renderer.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: pr requests

* Update internal/ui/login/handler/link_users_handler.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: pr requests

* fix: pr requests

* fix: pr requests

* fix: login name size

* fix: profile image light

* fix: colors

* fix: pr requests

* fix: remove redirect uri validator

* fix: remove redirect uri validator

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Fabi
2020-09-18 13:26:28 +02:00
committed by GitHub
parent 1d542a0c57
commit 320ddfa46d
141 changed files with 30057 additions and 12535 deletions

View File

@@ -28,3 +28,7 @@ func (l *Login) getAuthRequestAndParseData(r *http.Request, data interface{}) (*
err = l.parser.Parse(r, data)
return authReq, err
}
func (l *Login) getParseData(r *http.Request, data interface{}) error {
return l.parser.Parse(r, data)
}

View File

@@ -0,0 +1,269 @@
package handler
import (
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/pkg/rp"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/crypto"
caos_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
org_model "github.com/caos/zitadel/internal/org/model"
usr_model "github.com/caos/zitadel/internal/user/model"
"net/http"
"strings"
"time"
)
const (
queryIDPConfigID = "idpConfigID"
tmplExternalNotFoundOption = "externalnotfoundoption"
)
type externalIDPData struct {
IDPConfigID string `schema:"idpConfigID"`
}
type externalIDPCallbackData struct {
State string `schema:"state"`
Code string `schema:"code"`
}
type externalNotFoundOptionFormData struct {
Link bool `schema:"link"`
AutoRegister bool `schema:"autoregister"`
}
type externalNotFoundOptionData struct {
baseData
}
func (l *Login) handleExternalLogin(w http.ResponseWriter, r *http.Request) {
data := new(externalIDPData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
if authReq == nil {
http.Redirect(w, r, l.zitadelURL, http.StatusFound)
return
}
idpConfig, err := l.getIDPConfigByID(r, data.IDPConfigID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.authRepo.SelectExternalIDP(r.Context(), authReq.ID, idpConfig.IDPConfigID, userAgentID)
if err != nil {
l.renderLogin(w, r, authReq, err)
return
}
if !idpConfig.IsOIDC {
l.renderError(w, r, authReq, caos_errors.ThrowInternal(nil, "LOGIN-Rio9s", "Errors.User.ExternalIDP.IDPTypeNotImplemented"))
return
}
l.handleOIDCAuthorize(w, r, authReq, idpConfig, EndpointExternalLoginCallback)
}
func (l *Login) handleOIDCAuthorize(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, idpConfig *iam_model.IDPConfigView, callbackEndpoint string) {
provider := l.getRPConfig(w, r, authReq, idpConfig, callbackEndpoint)
http.Redirect(w, r, rp.AuthURL(authReq.ID, provider), http.StatusFound)
}
func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Request) {
data := new(externalIDPCallbackData)
err := l.getParseData(r, data)
if err != nil {
l.renderError(w, r, nil, err)
return
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
authReq, err := l.authRepo.AuthRequestByID(r.Context(), data.State, userAgentID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
idpConfig, err := l.authRepo.GetIDPConfigByID(r.Context(), authReq.SelectedIDPConfigID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
provider := l.getRPConfig(w, r, authReq, idpConfig, EndpointExternalLoginCallback)
tokens, err := rp.CodeExchange(r.Context(), data.Code, provider)
if err != nil {
l.renderLogin(w, r, authReq, err)
return
}
l.handleExternalUserAuthenticated(w, r, authReq, idpConfig, userAgentID, tokens)
}
func (l *Login) getRPConfig(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, idpConfig *iam_model.IDPConfigView, callbackEndpoint string) rp.RelayingParty {
oidcClientSecret, err := crypto.DecryptString(idpConfig.OIDCClientSecret, l.IDPConfigAesCrypto)
if err != nil {
l.renderError(w, r, authReq, err)
return nil
}
provider, err := rp.NewRelayingPartyOIDC(idpConfig.OIDCIssuer, idpConfig.OIDCClientID, oidcClientSecret, l.baseURL+callbackEndpoint, idpConfig.OIDCScopes, rp.WithVerifierOpts(rp.WithIssuedAtOffset(3*time.Second)))
if err != nil {
l.renderError(w, r, authReq, err)
return nil
}
return provider
}
func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, idpConfig *iam_model.IDPConfigView, userAgentID string, tokens *oidc.Tokens) {
externalUser := l.mapTokenToLoginUser(tokens, idpConfig)
err := l.authRepo.CheckExternalUserLogin(r.Context(), authReq.ID, userAgentID, externalUser)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, nil)
return
}
l.renderNextStep(w, r, authReq)
}
func (l *Login) renderExternalNotFoundOption(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, err error) {
var errType, errMessage string
if err != nil {
errMessage = l.getErrorMessage(r, err)
}
data := externalNotFoundOptionData{
baseData: l.getBaseData(r, authReq, "ExternalNotFoundOption", errType, errMessage),
}
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplExternalNotFoundOption], data, nil)
}
func (l *Login) handleExternalNotFoundOptionCheck(w http.ResponseWriter, r *http.Request) {
data := new(externalNotFoundOptionFormData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
if data.Link {
l.renderLogin(w, r, authReq, nil)
return
}
l.handleAutoRegister(w, r, authReq)
}
func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest) {
orgIamPolicy, err := l.getOrgIamPolicy(r, authReq.GetScopeOrgID())
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
return
}
iam, err := l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
return
}
resourceOwner := iam.GlobalOrgID
member := &org_model.OrgMember{
ObjectRoot: models.ObjectRoot{AggregateID: iam.GlobalOrgID},
Roles: []string{orgProjectCreatorRole},
}
if authReq.GetScopeOrgID() != iam.GlobalOrgID && authReq.GetScopeOrgID() != "" {
member = nil
resourceOwner = authReq.GetScopeOrgID()
}
idpConfig, err := l.authRepo.GetIDPConfigByID(r.Context(), authReq.SelectedIDPConfigID)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
return
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
user, externalIDP := l.mapExternalUserToLoginUser(orgIamPolicy, authReq.LinkingUsers[len(authReq.LinkingUsers)-1], idpConfig)
err = l.authRepo.AutoRegisterExternalUser(setContext(r.Context(), resourceOwner), user, externalIDP, member, authReq.ID, userAgentID, resourceOwner)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
return
}
l.renderNextStep(w, r, authReq)
}
func (l *Login) mapTokenToLoginUser(tokens *oidc.Tokens, idpConfig *iam_model.IDPConfigView) *model.ExternalUser {
displayName := tokens.IDTokenClaims.PreferredUsername
switch idpConfig.OIDCIDPDisplayNameMapping {
case iam_model.OIDCMappingFieldEmail:
if tokens.IDTokenClaims.EmailVerified && tokens.IDTokenClaims.Email != "" {
displayName = tokens.IDTokenClaims.Email
}
}
externalUser := &model.ExternalUser{
IDPConfigID: idpConfig.IDPConfigID,
ExternalUserID: tokens.IDTokenClaims.Subject,
PreferredUsername: tokens.IDTokenClaims.PreferredUsername,
DisplayName: displayName,
FirstName: tokens.IDTokenClaims.GivenName,
LastName: tokens.IDTokenClaims.FamilyName,
NickName: tokens.IDTokenClaims.Nickname,
Email: tokens.IDTokenClaims.Email,
IsEmailVerified: tokens.IDTokenClaims.EmailVerified,
}
if tokens.IDTokenClaims.PhoneNumber != "" {
externalUser.Phone = tokens.IDTokenClaims.PhoneNumber
externalUser.IsPhoneVerified = tokens.IDTokenClaims.PhoneNumberVerified
}
return externalUser
}
func (l *Login) mapExternalUserToLoginUser(orgIamPolicy *org_model.OrgIAMPolicy, linkingUser *model.ExternalUser, idpConfig *iam_model.IDPConfigView) (*usr_model.User, *usr_model.ExternalIDP) {
username := linkingUser.PreferredUsername
switch idpConfig.OIDCUsernameMapping {
case iam_model.OIDCMappingFieldEmail:
if linkingUser.IsEmailVerified && linkingUser.Email != "" {
username = linkingUser.Email
}
}
if orgIamPolicy.UserLoginMustBeDomain {
splittedUsername := strings.Split(username, "@")
if len(splittedUsername) > 1 {
username = splittedUsername[0]
}
}
user := &usr_model.User{
UserName: username,
Human: &usr_model.Human{
Profile: &usr_model.Profile{
FirstName: linkingUser.FirstName,
LastName: linkingUser.LastName,
PreferredLanguage: linkingUser.PreferredLanguage,
NickName: linkingUser.NickName,
},
Email: &usr_model.Email{
EmailAddress: linkingUser.Email,
IsEmailVerified: linkingUser.IsEmailVerified,
},
},
}
if linkingUser.Phone != "" {
user.Phone = &usr_model.Phone{
PhoneNumber: linkingUser.Phone,
IsPhoneVerified: linkingUser.IsPhoneVerified,
}
}
displayName := linkingUser.PreferredUsername
switch idpConfig.OIDCIDPDisplayNameMapping {
case iam_model.OIDCMappingFieldEmail:
if linkingUser.IsEmailVerified && linkingUser.Email != "" {
displayName = linkingUser.Email
}
}
externalIDP := &usr_model.ExternalIDP{
IDPConfigID: idpConfig.IDPConfigID,
UserID: linkingUser.ExternalUserID,
DisplayName: displayName,
}
return user, externalIDP
}

View File

@@ -0,0 +1,155 @@
package handler
import (
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/pkg/rp"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/auth_request/model"
caos_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
org_model "github.com/caos/zitadel/internal/org/model"
usr_model "github.com/caos/zitadel/internal/user/model"
"net/http"
"strings"
)
func (l *Login) handleExternalRegister(w http.ResponseWriter, r *http.Request) {
data := new(externalIDPData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
if authReq == nil {
http.Redirect(w, r, l.zitadelURL, http.StatusFound)
return
}
idpConfig, err := l.getIDPConfigByID(r, data.IDPConfigID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.authRepo.SelectExternalIDP(r.Context(), authReq.ID, idpConfig.IDPConfigID, userAgentID)
if err != nil {
l.renderLogin(w, r, authReq, err)
return
}
if !idpConfig.IsOIDC {
l.renderError(w, r, authReq, caos_errors.ThrowInternal(nil, "LOGIN-Rio9s", "Errors.User.ExternalIDP.IDPTypeNotImplemented"))
return
}
l.handleOIDCAuthorize(w, r, authReq, idpConfig, EndpointExternalRegisterCallback)
}
func (l *Login) handleExternalRegisterCallback(w http.ResponseWriter, r *http.Request) {
data := new(externalIDPCallbackData)
err := l.getParseData(r, data)
if err != nil {
l.renderError(w, r, nil, err)
return
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
authReq, err := l.authRepo.AuthRequestByID(r.Context(), data.State, userAgentID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
idpConfig, err := l.authRepo.GetIDPConfigByID(r.Context(), authReq.SelectedIDPConfigID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
provider := l.getRPConfig(w, r, authReq, idpConfig, EndpointExternalRegisterCallback)
tokens, err := rp.CodeExchange(r.Context(), data.Code, provider)
if err != nil {
l.renderRegisterOption(w, r, authReq, err)
return
}
l.handleExternalUserRegister(w, r, authReq, idpConfig, userAgentID, tokens)
}
func (l *Login) handleExternalUserRegister(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, idpConfig *iam_model.IDPConfigView, userAgentID string, tokens *oidc.Tokens) {
orgIamPolicy, err := l.getOrgIamPolicy(r, authReq.GetScopeOrgID())
if err != nil {
l.renderRegisterOption(w, r, authReq, err)
return
}
iam, err := l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderRegisterOption(w, r, authReq, err)
return
}
resourceOwner := iam.GlobalOrgID
member := &org_model.OrgMember{
ObjectRoot: models.ObjectRoot{AggregateID: iam.GlobalOrgID},
Roles: []string{orgProjectCreatorRole},
}
if authReq.GetScopeOrgID() != iam.GlobalOrgID && authReq.GetScopeOrgID() != "" {
member = nil
resourceOwner = authReq.GetScopeOrgID()
}
user, externalIDP := l.mapTokenToLoginUserAndExternalIDP(orgIamPolicy, tokens, idpConfig)
_, err = l.authRepo.RegisterExternalUser(setContext(r.Context(), resourceOwner), user, externalIDP, member, resourceOwner)
if err != nil {
l.renderRegisterOption(w, r, authReq, err)
return
}
l.renderNextStep(w, r, authReq)
}
func (l *Login) mapTokenToLoginUserAndExternalIDP(orgIamPolicy *org_model.OrgIAMPolicy, tokens *oidc.Tokens, idpConfig *iam_model.IDPConfigView) (*usr_model.User, *usr_model.ExternalIDP) {
username := tokens.IDTokenClaims.PreferredUsername
switch idpConfig.OIDCUsernameMapping {
case iam_model.OIDCMappingFieldEmail:
if tokens.IDTokenClaims.EmailVerified && tokens.IDTokenClaims.Email != "" {
username = tokens.IDTokenClaims.Email
}
}
if orgIamPolicy.UserLoginMustBeDomain {
splittedUsername := strings.Split(username, "@")
if len(splittedUsername) > 1 {
username = splittedUsername[0]
}
}
user := &usr_model.User{
UserName: username,
Human: &usr_model.Human{
Profile: &usr_model.Profile{
FirstName: tokens.IDTokenClaims.GivenName,
LastName: tokens.IDTokenClaims.FamilyName,
PreferredLanguage: tokens.IDTokenClaims.Locale,
NickName: tokens.IDTokenClaims.Nickname,
},
Email: &usr_model.Email{
EmailAddress: tokens.IDTokenClaims.Email,
IsEmailVerified: tokens.IDTokenClaims.EmailVerified,
},
},
}
if tokens.IDTokenClaims.PhoneNumber != "" {
user.Phone = &usr_model.Phone{
PhoneNumber: tokens.IDTokenClaims.PhoneNumber,
IsPhoneVerified: tokens.IDTokenClaims.PhoneNumberVerified,
}
}
displayName := tokens.IDTokenClaims.PreferredUsername
switch idpConfig.OIDCIDPDisplayNameMapping {
case iam_model.OIDCMappingFieldEmail:
if tokens.IDTokenClaims.EmailVerified && tokens.IDTokenClaims.Email != "" {
displayName = tokens.IDTokenClaims.Email
}
}
externalIDP := &usr_model.ExternalIDP{
IDPConfigID: idpConfig.IDPConfigID,
UserID: tokens.IDTokenClaims.Subject,
DisplayName: displayName,
}
return user, externalIDP
}

View File

@@ -0,0 +1,24 @@
package handler
import (
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"net/http"
"github.com/caos/zitadel/internal/auth_request/model"
)
const (
tmplLinkUsersDone = "linkusersdone"
)
func (l *Login) linkUsers(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, err error) {
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.authRepo.LinkExternalUsers(setContext(r.Context(), authReq.UserOrgID), authReq.ID, userAgentID)
l.renderLinkUsersDone(w, r, authReq, err)
}
func (l *Login) renderLinkUsersDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, err error) {
var errType, errMessage string
data := l.getUserData(r, authReq, "Linking Users Done", errType, errMessage)
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplLinkUsersDone], data, nil)
}

View File

@@ -2,6 +2,7 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/config/systemdefaults"
"net"
"net/http"
@@ -28,11 +29,14 @@ type Login struct {
renderer *Renderer
parser *form.Parser
authRepo auth_repository.Repository
baseURL string
zitadelURL string
oidcAuthCallbackURL string
IDPConfigAesCrypto crypto.EncryptionAlgorithm
}
type Config struct {
BaseURL string
OidcAuthCallbackURL string
ZitadelURL string
LanguageCookieName string
@@ -53,11 +57,17 @@ const (
handlerPrefix = "/login"
)
func CreateLogin(config Config, authRepo *eventsourcing.EsRepository, localDevMode bool) (*Login, string) {
func CreateLogin(config Config, authRepo *eventsourcing.EsRepository, systemDefaults systemdefaults.SystemDefaults, localDevMode bool) (*Login, string) {
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.IDPConfigVerificationKey)
if err != nil {
logging.Log("HANDL-s90ew").WithError(err).Debug("error create new aes crypto")
}
login := &Login{
oidcAuthCallbackURL: config.OidcAuthCallbackURL,
baseURL: config.BaseURL,
zitadelURL: config.ZitadelURL,
authRepo: authRepo,
IDPConfigAesCrypto: aesCrypto,
}
prefix := ""
if localDevMode {

View File

@@ -30,12 +30,12 @@ func (l *Login) handleLogin(w http.ResponseWriter, r *http.Request) {
}
func (l *Login) handleLoginName(w http.ResponseWriter, r *http.Request) {
authSession, err := l.getAuthRequest(r)
authReq, err := l.getAuthRequest(r)
if err != nil {
l.renderError(w, r, authSession, err)
l.renderError(w, r, authReq, err)
return
}
l.renderLogin(w, r, authSession, nil)
l.renderLogin(w, r, authReq, nil)
}
func (l *Login) handleLoginNameCheck(w http.ResponseWriter, r *http.Request) {
@@ -46,6 +46,10 @@ func (l *Login) handleLoginNameCheck(w http.ResponseWriter, r *http.Request) {
return
}
if data.Register {
if authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0 {
l.handleRegisterOption(w, r)
return
}
l.handleRegister(w, r)
return
}

View File

@@ -1,10 +0,0 @@
package handler
import (
org_model "github.com/caos/zitadel/internal/org/model"
"net/http"
)
func (l *Login) getOrgIamPolicy(r *http.Request, orgID string) (*org_model.OrgIAMPolicy, error) {
return l.authRepo.GetOrgIamPolicy(r.Context(), orgID)
}

View File

@@ -0,0 +1,18 @@
package handler
import (
iam_model "github.com/caos/zitadel/internal/iam/model"
org_model "github.com/caos/zitadel/internal/org/model"
"net/http"
)
func (l *Login) getOrgIamPolicy(r *http.Request, orgID string) (*org_model.OrgIAMPolicy, error) {
if orgID == "" {
return l.authRepo.GetDefaultOrgIamPolicy(r.Context()), nil
}
return l.authRepo.GetOrgIamPolicy(r.Context(), orgID)
}
func (l *Login) getIDPConfigByID(r *http.Request, idpConfigID string) (*iam_model.IDPConfigView, error) {
return l.authRepo.GetIDPConfigByID(r.Context(), idpConfigID)
}

View File

@@ -66,11 +66,16 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
return
}
resourceOwner := iam.GlobalOrgID
member := &org_model.OrgMember{
ObjectRoot: models.ObjectRoot{AggregateID: iam.GlobalOrgID},
Roles: []string{orgProjectCreatorRole},
}
user, err := l.authRepo.Register(setContext(r.Context(), iam.GlobalOrgID), data.toUserModel(), member, iam.GlobalOrgID)
if authRequest.GetScopeOrgID() != "" && authRequest.GetScopeOrgID() != iam.GlobalOrgID {
member = nil
resourceOwner = authRequest.GetScopeOrgID()
}
user, err := l.authRepo.Register(setContext(r.Context(), resourceOwner), data.toUserModel(), member, resourceOwner)
if err != nil {
l.renderRegister(w, r, authRequest, data, err)
return

View File

@@ -0,0 +1,53 @@
package handler
import (
"github.com/caos/zitadel/internal/auth_request/model"
"net/http"
)
const (
tmplRegisterOption = "registeroption"
)
type registerOptionFormData struct {
UsernamePassword bool `schema:"usernamepassword"`
}
type registerOptionData struct {
baseData
}
func (l *Login) handleRegisterOption(w http.ResponseWriter, r *http.Request) {
data := new(registerOptionFormData)
authRequest, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authRequest, err)
return
}
l.renderRegisterOption(w, r, authRequest, nil)
}
func (l *Login) renderRegisterOption(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, err error) {
var errType, errMessage string
if err != nil {
errMessage = l.getErrorMessage(r, err)
}
data := registerOptionData{
baseData: l.getBaseData(r, authReq, "RegisterOption", errType, errMessage),
}
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplRegisterOption], data, nil)
}
func (l *Login) handleRegisterOptionCheck(w http.ResponseWriter, r *http.Request) {
data := new(registerOptionFormData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
if data.UsernamePassword {
l.handleRegister(w, r)
return
}
l.handleRegisterOption(w, r)
}

View File

@@ -3,14 +3,14 @@ package handler
import (
"errors"
"fmt"
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/gorilla/csrf"
"golang.org/x/text/language"
"html/template"
"net/http"
"path"
"github.com/caos/logging"
"github.com/gorilla/csrf"
"golang.org/x/text/language"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/auth_request/model"
caos_errs "github.com/caos/zitadel/internal/errors"
@@ -32,28 +32,31 @@ func CreateRenderer(pathPrefix string, staticDir http.FileSystem, cookieName str
pathPrefix: pathPrefix,
}
tmplMapping := map[string]string{
tmplError: "error.html",
tmplLogin: "login.html",
tmplUserSelection: "select_user.html",
tmplPassword: "password.html",
tmplMfaVerify: "mfa_verify.html",
tmplMfaPrompt: "mfa_prompt.html",
tmplMfaInitVerify: "mfa_init_verify.html",
tmplMfaInitDone: "mfa_init_done.html",
tmplMailVerification: "mail_verification.html",
tmplMailVerified: "mail_verified.html",
tmplInitPassword: "init_password.html",
tmplInitPasswordDone: "init_password_done.html",
tmplInitUser: "init_user.html",
tmplInitUserDone: "init_user_done.html",
tmplPasswordResetDone: "password_reset_done.html",
tmplChangePassword: "change_password.html",
tmplChangePasswordDone: "change_password_done.html",
tmplRegister: "register.html",
tmplLogoutDone: "logout_done.html",
tmplRegisterOrg: "register_org.html",
tmplChangeUsername: "change_username.html",
tmplChangeUsernameDone: "change_username_done.html",
tmplError: "error.html",
tmplLogin: "login.html",
tmplUserSelection: "select_user.html",
tmplPassword: "password.html",
tmplMfaVerify: "mfa_verify.html",
tmplMfaPrompt: "mfa_prompt.html",
tmplMfaInitVerify: "mfa_init_verify.html",
tmplMfaInitDone: "mfa_init_done.html",
tmplMailVerification: "mail_verification.html",
tmplMailVerified: "mail_verified.html",
tmplInitPassword: "init_password.html",
tmplInitPasswordDone: "init_password_done.html",
tmplInitUser: "init_user.html",
tmplInitUserDone: "init_user_done.html",
tmplPasswordResetDone: "password_reset_done.html",
tmplChangePassword: "change_password.html",
tmplChangePasswordDone: "change_password_done.html",
tmplRegisterOption: "register_option.html",
tmplRegister: "register.html",
tmplLogoutDone: "logout_done.html",
tmplRegisterOrg: "register_org.html",
tmplChangeUsername: "change_username.html",
tmplChangeUsernameDone: "change_username_done.html",
tmplLinkUsersDone: "link_users_done.html",
tmplExternalNotFoundOption: "external_not_found_option.html",
}
funcs := map[string]interface{}{
"resourceUrl": func(file string) string {
@@ -65,6 +68,12 @@ func CreateRenderer(pathPrefix string, staticDir http.FileSystem, cookieName str
"loginUrl": func() string {
return path.Join(r.pathPrefix, EndpointLogin)
},
"externalIDPAuthURL": func(authReqID, idpConfigID string) string {
return path.Join(r.pathPrefix, fmt.Sprintf("%s?%s=%s&%s=%s", EndpointExternalLogin, queryAuthRequestID, authReqID, queryIDPConfigID, idpConfigID))
},
"externalIDPRegisterURL": func(authReqID, idpConfigID string) string {
return path.Join(r.pathPrefix, fmt.Sprintf("%s?%s=%s&%s=%s", EndpointExternalRegister, queryAuthRequestID, authReqID, queryIDPConfigID, idpConfigID))
},
"registerUrl": func(id string) string {
return path.Join(r.pathPrefix, fmt.Sprintf("%s?%s=%s", EndpointRegister, queryAuthRequestID, id))
},
@@ -107,6 +116,9 @@ func CreateRenderer(pathPrefix string, staticDir http.FileSystem, cookieName str
"changePasswordUrl": func() string {
return path.Join(r.pathPrefix, EndpointChangePassword)
},
"registerOptionUrl": func() string {
return path.Join(r.pathPrefix, EndpointRegisterOption)
},
"registrationUrl": func() string {
return path.Join(r.pathPrefix, EndpointRegister)
},
@@ -116,6 +128,9 @@ func CreateRenderer(pathPrefix string, staticDir http.FileSystem, cookieName str
"changeUsernameUrl": func() string {
return path.Join(r.pathPrefix, EndpointChangeUsername)
},
"externalNotFoundOptionUrl": func() string {
return path.Join(r.pathPrefix, EndpointExternalNotFoundOption)
},
"selectedLanguage": func(l string) bool {
return false
},
@@ -186,6 +201,10 @@ func (l *Login) chooseNextStep(w http.ResponseWriter, r *http.Request, authReq *
l.renderInitUser(w, r, authReq, "", "", step.PasswordSet, nil)
case *model.ChangeUsernameStep:
l.renderChangeUsername(w, r, authReq, nil)
case *model.LinkUsersStep:
l.linkUsers(w, r, authReq, err)
case *model.ExternalNotFoundOptionStep:
l.renderExternalNotFoundOption(w, r, authReq, err)
default:
l.renderInternalError(w, r, authReq, caos_errs.ThrowInternal(nil, "APP-ds3QF", "step no possible"))
}
@@ -204,11 +223,12 @@ func (l *Login) getUserData(r *http.Request, authReq *model.AuthRequest, title s
return userData{
baseData: l.getBaseData(r, authReq, title, errType, errMessage),
profileData: l.getProfileData(authReq),
Linking: len(authReq.LinkingUsers) > 0,
}
}
func (l *Login) getBaseData(r *http.Request, authReq *model.AuthRequest, title string, errType, errMessage string) baseData {
return baseData{
baseData := baseData{
errorData: errorData{
ErrType: errType,
ErrMessage: errMessage,
@@ -217,10 +237,16 @@ func (l *Login) getBaseData(r *http.Request, authReq *model.AuthRequest, title s
Title: title,
Theme: l.getTheme(r),
ThemeMode: l.getThemeMode(r),
OrgID: l.getOrgID(authReq),
AuthReqID: getRequestID(authReq, r),
CSRF: csrf.TemplateField(r),
Nonce: http_mw.GetNonce(r),
}
if authReq != nil {
baseData.LoginPolicy = authReq.LoginPolicy
baseData.IDPProviders = authReq.AllowedExternalIDPs
}
return baseData
}
func (l *Login) getProfileData(authReq *model.AuthRequest) profileData {
@@ -253,6 +279,19 @@ func (l *Login) getThemeMode(r *http.Request) string {
return "" //TODO: impl
}
func (l *Login) getOrgID(authReq *model.AuthRequest) string {
if authReq == nil {
return ""
}
if authReq.UserOrgID != "" {
return authReq.UserOrgID
}
if authReq.Request == nil {
return ""
}
return authReq.GetScopeOrgID()
}
func getRequestID(authReq *model.AuthRequest, r *http.Request) string {
if authReq != nil {
return authReq.ID
@@ -275,13 +314,16 @@ func (l *Login) cspErrorHandler(err error) http.Handler {
type baseData struct {
errorData
Lang string
Title string
Theme string
ThemeMode string
AuthReqID string
CSRF template.HTML
Nonce string
Lang string
Title string
Theme string
ThemeMode string
OrgID string
AuthReqID string
CSRF template.HTML
Nonce string
LoginPolicy *iam_model.LoginPolicyView
IDPProviders []*iam_model.IDPProviderView
}
type errorData struct {
@@ -295,6 +337,7 @@ type userData struct {
PasswordChecked string
MfaProviders []model.MfaType
SelectedMfaProvider model.MfaType
Linking bool
}
type profileData struct {
@@ -315,7 +358,8 @@ type passwordData struct {
type userSelectionData struct {
baseData
Users []model.UserSelection
Users []model.UserSelection
Linking bool
}
type mfaData struct {

View File

@@ -7,26 +7,32 @@ import (
)
const (
EndpointRoot = "/"
EndpointHealthz = "/healthz"
EndpointReadiness = "/ready"
EndpointLogin = "/login"
EndpointLoginName = "/loginname"
EndpointUserSelection = "/userselection"
EndpointChangeUsername = "/username/change"
EndpointPassword = "/password"
EndpointInitPassword = "/password/init"
EndpointChangePassword = "/password/change"
EndpointPasswordReset = "/password/reset"
EndpointInitUser = "/user/init"
EndpointMfaVerify = "/mfa/verify"
EndpointMfaPrompt = "/mfa/prompt"
EndpointMfaInitVerify = "/mfa/init/verify"
EndpointMailVerification = "/mail/verification"
EndpointMailVerified = "/mail/verified"
EndpointRegister = "/register"
EndpointRegisterOrg = "/register/org"
EndpointLogoutDone = "/logout/done"
EndpointRoot = "/"
EndpointHealthz = "/healthz"
EndpointReadiness = "/ready"
EndpointLogin = "/login"
EndpointExternalLogin = "/login/externalidp"
EndpointExternalLoginCallback = "/login/externalidp/callback"
EndpointLoginName = "/loginname"
EndpointUserSelection = "/userselection"
EndpointChangeUsername = "/username/change"
EndpointPassword = "/password"
EndpointInitPassword = "/password/init"
EndpointChangePassword = "/password/change"
EndpointPasswordReset = "/password/reset"
EndpointInitUser = "/user/init"
EndpointMfaVerify = "/mfa/verify"
EndpointMfaPrompt = "/mfa/prompt"
EndpointMfaInitVerify = "/mfa/init/verify"
EndpointMailVerification = "/mail/verification"
EndpointMailVerified = "/mail/verified"
EndpointRegisterOption = "/register/option"
EndpointRegister = "/register"
EndpointExternalRegister = "/register/externalidp"
EndpointExternalRegisterCallback = "/register/externalidp/callback"
EndpointRegisterOrg = "/register/org"
EndpointLogoutDone = "/logout/done"
EndpointExternalNotFoundOption = "/externaluser/option"
EndpointResources = "/resources"
)
@@ -38,6 +44,8 @@ func CreateRouter(login *Login, staticDir http.FileSystem, interceptors ...mux.M
router.HandleFunc(EndpointHealthz, login.handleHealthz).Methods(http.MethodGet)
router.HandleFunc(EndpointReadiness, login.handleReadiness).Methods(http.MethodGet)
router.HandleFunc(EndpointLogin, login.handleLogin).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc(EndpointExternalLogin, login.handleExternalLogin).Methods(http.MethodGet)
router.HandleFunc(EndpointExternalLoginCallback, login.handleExternalLoginCallback).Methods(http.MethodGet)
router.HandleFunc(EndpointLoginName, login.handleLoginName).Methods(http.MethodGet)
router.HandleFunc(EndpointLoginName, login.handleLoginNameCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointUserSelection, login.handleSelectUser).Methods(http.MethodPost)
@@ -55,8 +63,13 @@ func CreateRouter(login *Login, staticDir http.FileSystem, interceptors ...mux.M
router.HandleFunc(EndpointMailVerification, login.handleMailVerification).Methods(http.MethodGet)
router.HandleFunc(EndpointMailVerification, login.handleMailVerificationCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointChangePassword, login.handleChangePassword).Methods(http.MethodPost)
router.HandleFunc(EndpointRegisterOption, login.handleRegisterOption).Methods(http.MethodGet)
router.HandleFunc(EndpointRegisterOption, login.handleRegisterOptionCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointExternalNotFoundOption, login.handleExternalNotFoundOptionCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointRegister, login.handleRegister).Methods(http.MethodGet)
router.HandleFunc(EndpointRegister, login.handleRegisterCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointExternalRegister, login.handleExternalRegister).Methods(http.MethodGet)
router.HandleFunc(EndpointExternalRegisterCallback, login.handleExternalRegisterCallback).Methods(http.MethodGet)
router.HandleFunc(EndpointLogoutDone, login.handleLogoutDone).Methods(http.MethodGet)
router.PathPrefix(EndpointResources).Handler(login.handleResources(staticDir)).Methods(http.MethodGet)
router.HandleFunc(EndpointRegisterOrg, login.handleRegisterOrg).Methods(http.MethodGet)

View File

@@ -19,6 +19,7 @@ func (l *Login) renderUserSelection(w http.ResponseWriter, r *http.Request, auth
data := userSelectionData{
baseData: l.getBaseData(r, authReq, "Select User", "", ""),
Users: selectionData.Users,
Linking: len(authReq.LinkingUsers) > 0,
}
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplUserSelection], data, nil)
}

View File

@@ -2,6 +2,7 @@ package login
import (
"github.com/caos/zitadel/internal/auth/repository/eventsourcing"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/ui/login/handler"
)
@@ -9,6 +10,6 @@ type Config struct {
Handler handler.Config
}
func Start(config Config, authRepo *eventsourcing.EsRepository, localDevMode bool) (*handler.Login, string) {
return handler.CreateLogin(config.Handler, authRepo, localDevMode)
func Start(config Config, authRepo *eventsourcing.EsRepository, systemdefaults systemdefaults.SystemDefaults, localDevMode bool) (*handler.Login, string) {
return handler.CreateLogin(config.Handler, authRepo, systemdefaults, localDevMode)
}

View File

@@ -11,12 +11,17 @@ Password:
Login:
Title: Anmeldung
Description: Gib deine Benutzerdaten ein.
TitleLinking: Anmeldung für Benutzer Linking
DescriptionLinking: Gib deine Benutzerdaten ein um den externen Benutzer mit einem ZITADEL Benutzer zu linken.
Loginname: Loginname
LoginnamePlaceHolder: username@domain
ExternalLogin: Melde dich mit einem externen Benutzer an
UserSelection:
Title: Account auswählen
Description: Wähle deinen Account aus.
TitleLinking: Account auswählen um zu verlinken
DescriptionLinking: Wähle deinen Account, um diesen mit deinem externen Benutzer zu verlinken.
OtherUser: Anderer Benutzer
SessionState0: aktiv
SessionState1: inaktiv
@@ -103,6 +108,11 @@ EmailVerificationDone:
Title: E-Mail Verifizierung
Description: Deine E-Mail Adresse wurde erfolgreich verifiziert.
RegisterOption:
Title: Registrations Möglichkeiten
Description: Wähle aus wie du dich registrieren möchtest.
RegisterUsernamePassword: Mit Benutzername Passwort
Registration:
Title: Registration
Description: Gib deine Benutzerangaben an. Die E-Mail Adresse wird als Benutzernamen verwendet.
@@ -147,6 +157,16 @@ RegistrationOrg:
TosLinkText: AGBs
TosLink: https://zitadel.ch/pdf/agb.pdf
LinkingUsersDone:
Title: Benutzerlinking
Description: Benuzterlinking erledigt.
ExternalNotFoundOption:
Title: Externer Benutzer
Description: Externer Benutzer konnte nicht gefunden werden. Willst du deinen Benutzer mit einem bestehenden verlinken oder diesen als neuen Benutzer registrieren.
Link: Verlinken
AutoRegister: Automatisches registrieren
LogoutDone:
Title: Ausgeloggt
Description: Du wurdest erfolgreich ausgeloggt.
@@ -173,6 +193,7 @@ Errors:
UserIDMissing: UserID ist leer
Invalid: Userdaten sind ungültig
DomainNotAllowedAsUsername: Domäne ist bereits reserviert und kann nicht verwendet werden
NotAllowedToLink: Der Benutzer darf nicht mit einem externen Login Provider verlinkt werden
Password:
ConfirmationWrong: Passwort Bestätigung stimmt nicht überein
Empty: Passwort ist leer
@@ -202,5 +223,7 @@ Errors:
NotReady: Multifaktor OTP (OneTimePassword) ist nicht bereit
Locked: Benutzer ist gesperrt
NotActive: Benutzer ist nicht aktiv
ExternalIDP:
IDPTypeNotImplemented: IDP Typ ist nicht implementiert
optional: (optional)

View File

@@ -1,12 +1,17 @@
Login:
Title: Login
Description: Enter your logindata.
TitleLinking: Login for userlinking
DescriptionLinking: Enter your login data to link your external user with a ZITADEL user.
Loginname: Loginname
LoginnamePlaceHolder: username@domain
ExternalLogin: Login with an external user.
UserSelection:
Title: Select account
Description: Select your account.
TitleLinking: Select account for userlinking
DescriptionLinking: Select your account to link with your external user.
OtherUser: Other User
SessionState0: active
SessionState1: inactive
@@ -103,6 +108,11 @@ EmailVerificationDone:
Title: E-Mail Verification
Description: Your email address has been successfully verified.
RegistrationOption:
Title: Registration Options
Description: Choose how you'd like to register
RegisterUsernamePassword: With username password
Registration:
Title: Registration
Description: Enter your Userdata. Your email address will be used as loginname.
@@ -147,11 +157,20 @@ RegistrationOrg:
TosLinkText: TOS
TosLink: https://zitadel.ch/pdf/tos.pdf
LogoutDone:
Title: Logged out
Description: You have logged out successfully.
LinkingUsersDone:
Title: Userlinking
Description: Userlinking done.
ExternalNotFoundOption:
Title: External User
Description: External user not found. Do you want to link your user or auto register a new one.
Link: Link
AutoRegister: Auto register
Actions:
Login: login
Next: next
@@ -163,7 +182,6 @@ Actions:
Cancel: cancel
Save: save
Errors:
Internal: An internal error occured
AuthRequest:
@@ -175,6 +193,7 @@ Errors:
UserIDMissing: UserID is empty
Invalid: Invalid userdata
DomainNotAllowedAsUsername: Domain is already reserved and cannot be used
NotAllowedToLink: User is not allowed to link with external login provider
Password:
ConfirmationWrong: Passwordconfirmation is wrong
Empty: Password is empty
@@ -204,6 +223,8 @@ Errors:
NotReady: Multifactor OTP (OneTimePassword) isn't ready
Locked: User is locked
NotActive: User is not active
ExternalIDP:
IDPTypeNotImplemented: IDP Type is not implemented
optional: (optional)

View File

@@ -73,7 +73,7 @@
*, *::before, *::after {
box-sizing: border-box;
font-family: Lato;
font-size: 18px;
font-size: 16px;
font-weight: 400;
}
@@ -97,6 +97,7 @@ h1 {
font-family: Aileron;
font-weight: 300;
font-size: 40px;
text-align: center;
}
h2 {
@@ -122,7 +123,13 @@ header .logo {
margin: 30px;
}
.content {
.head {
width: 100%;
max-width: 1000px;
margin: auto;
}
.content form {
margin: auto;
padding: 20px;
width: 100%;
@@ -137,11 +144,14 @@ a {
a:hover {
color: #f60075;
}
a.tos-link {
font-size: 14px;
}
button {
button, .button {
background-color: #282828;
color: #760038;
border: 2px solid #760038;
border: 1px solid #760038;
border-radius: 5px;
width: 100%;
max-width: 600px;
@@ -149,36 +159,39 @@ button {
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
display: inline-block;
text-align: center;
line-height: 40px;
}
button:hover {
button:hover, .button:hover {
background-color: #f60075;
color: #282828;
border: 2px solid #f60075;
border: 1px solid #f60075;
}
button.primary {
button.primary, .button.primary {
background-color: #760038;
color: white;
border: none;
}
button.primary:hover {
button.primary:hover, .button.primary:hover {
background-color: #f60075;
}
button:disabled {
background-color: #505050;
border: 2px solid #505050;
button:disabled, .button:disabled {
background-color: #999999;
border: 1px solid #999999;
}
button:disabled:hover {
background-color: #505050;
border: 2px solid #505050;
button:disabled:hover, .button:disabled:hover {
background-color: #999999;
border: 1px solid #999999;
}
input:not([type=radio]), select {
background-color: #252525;
color: white;
height: 50px;
border: 2px solid #505050;
border: 1px solid #999999;
border-radius: 5px;
padding-left: 15px;
padding-left: 8px;
}
form button.user-selection .profile-image, .login-profile .profile-image {
@@ -213,7 +226,7 @@ form button.user-selection:hover .profile-image, .login-profile:hover .profile-i
text-align: center;
}
.login-profile .names div:first-of-type {
font-size: 40px;
font-size: 26px;
font-weight: 300;
}
.login-profile .names div:nth-of-type(2) {
@@ -244,20 +257,21 @@ form .field.check-box {
display: flex;
}
form .field.check-box input[type=checkbox] {
height: 20px;
height: 16px;
vertical-align: middle;
}
form .field.check-box label {
height: 20px;
height: 16px;
text-transform: inherit;
display: inline-block;
padding: 2px 0 0 15px;
width: 100%;
color: white;
}
form label {
color: #898989;
text-transform: uppercase;
font-size: 0.9rem;
font-size: 0.8rem;
margin-bottom: 3px;
}
form label span.optional {
@@ -301,7 +315,7 @@ form button.user-selection .sessionstate {
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #505050;
border-color: #999999;
border-style: solid;
border-width: 1px;
position: absolute;
@@ -362,6 +376,7 @@ form ul#passwordcomplexity {
flex-wrap: wrap;
padding: 0;
list-style: none;
margin-bottom: 0;
}
form ul#passwordcomplexity li {
flex: 1 0 50%;
@@ -444,4 +459,8 @@ footer {
padding: 10px;
}
.error {
color: #F20D6B;
}
/*# sourceMappingURL=dark.css.map */

View File

@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/caos/variables.scss","../../scss/variables.scss"],"names":[],"mappings":"AACA;EACI;EACA;;AAIJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;EACA;EACA;EACA;AAA6D;EAC7D;;AC5EJ;EACI;EACA,aCMW;EDLX;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA,kBCDc;EDEd,OCDQ;EDER;EACA;EACA;;;AAMJ;EACI,OCXQ;EDYR,aClBS;EDmBT;EACA,WEzBS;;;AF4Bb;EACI,OClBQ;EDmBR,aCzBS;ED0BT;EACA,WE/BU;;;AFkCd;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OChDW;EDiDX;EACA;;AAEA;EACI,OCpDY;;;ADwDpB;EACI,kBC5Dc;ED6Dd,OC3DW;ED4DX;EACA;EACA;EACA;EACA,QE7EU;EF8EV;EACA;EACA;;AACA;EACI,kBCpEY;EDqEZ,OCxEU;EDyEV;;AAGJ;EACI,kBC3EO;ED4EP,OC7EI;ED8EJ;;AACA;EACI,kBC9EQ;;ADkFhB;EACI,kBEzEW;EF0EX;;AAEA;EACI,kBE7EO;EF8EP;;;AAKZ;EACI,kBEnFmB;EFoFnB,OCjGQ;EDkGR,QE9GU;EF+GV;EACA;EACA;;;AAIA;EACI;EACA;EACA;EACA;EE9GN;;AACA;EFyGE;IExGA;IACA;;;AF+GA;EElHF;;AACA;EFiHE;IEhHA;IACA;;;;AFsHA;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,WE7IC;EF8ID;;AAGJ;EACI;EACA;EACA;EACA,OE/HC;;;AFqIT;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAIR;EACI,OE5KK;EF6KL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OCjNI;EDkNJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBE5MW;;AF+Mf;EACI;;AAIR;EACI;;AAKA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA,cErOO;EFsOP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OEjQP;;AFwQL;EACI;;AAEJ;EACI;EACA;EACA;EACA;EE3RV;;AACA;EFsRM;IErRJ;IACA;;;AF6RQ;EACI;EACA;EElSd;;AACA;EF+RU;IE9RR;IACA;;;AFoSI;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,OE3SN;;AFgTE;EACI,OElTL;;AFuTP;EACI;;AACA;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MC1VI;;AD6VR;EACI,MC/VU;;;ADoWd;EACI;EACA;;;AAIR;EAEQ;EAEJ;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AAGJ;EACI;EACA;EACA","file":"dark.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/caos/variables.scss","../../scss/variables.scss"],"names":[],"mappings":"AACA;EACI;EACA;;AAIJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;EACA;EACA;EACA;AAA6D;EAC7D;;AC5EJ;EACI;EACA,aCMW;EDLX;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA,kBCDc;EDEd,OCDQ;EDER;EACA;EACA;;;AAMJ;EACI,OCXQ;EDYR,aClBS;EDmBT;EACA,WEzBS;EF0BT;;;AAGJ;EACI,OCnBQ;EDoBR,aC1BS;ED2BT;EACA,WEhCU;;;AFmCd;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCvDW;EDwDX;EACA;;AAEA;EACI,OC3DY;;AD8DhB;EACI;;;AAIR;EACI,kBCvEc;EDwEd,OCtEW;EDuEX;EACA;EACA;EACA;EACA,QExFU;EFyFV;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI,kBCnFY;EDoFZ,OCvFU;EDwFV;;AAGJ;EACI,kBC1FO;ED2FP,OC5FI;ED6FJ;;AACA;EACI,kBC7FQ;;ADiGhB;EACI,kBEvFW;EFwFX;;AAEA;EACI,kBE3FO;EF4FP;;;AAOZ;EACI,kBEnGmB;EFoGnB,OClHQ;EDmHR,QE/HU;EFgIV;EACA;EACA;;;AAIA;EACI;EACA;EACA;EACA;EE9HN;;AACA;EFyHE;IExHA;IACA;;;AF+HA;EElIF;;AACA;EFiIE;IEhIA;IACA;;;;AFsIA;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,WE5JE;EF6JF;;AAGJ;EACI;EACA;EACA;EACA,OE/IC;;;AFqJT;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA,OCpMA;;ADwMR;EACI,OE7LK;EF8LL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OCnOI;EDoOJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBE7NW;;AFgOf;EACI;;AAIR;EACI;;AAKA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA,cEtPO;EFuPP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OElRP;;AFyRL;EACI;;AAEJ;EACI;EACA;EACA;EACA;EE5SV;;AACA;EFuSM;IEtSJ;IACA;;;AF8SQ;EACI;EACA;EEnTd;;AACA;EFgTU;IE/SR;IACA;;;AFqTI;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,OE7TN;;AFkUE;EACI,OEpUL;;AFyUP;EACI;;AACA;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MC7WI;;ADgXR;EACI,MClXU;;;ADuXd;EACI;EACA;;;AAIR;EAEQ;EAEJ;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI,OEpZO","file":"dark.css"}

View File

@@ -73,7 +73,7 @@
*, *::before, *::after {
box-sizing: border-box;
font-family: Lato;
font-size: 18px;
font-size: 16px;
font-weight: 400;
}
@@ -97,6 +97,7 @@ h1 {
font-family: Aileron;
font-weight: 300;
font-size: 40px;
text-align: center;
}
h2 {
@@ -122,7 +123,13 @@ header .logo {
margin: 30px;
}
.content {
.head {
width: 100%;
max-width: 1000px;
margin: auto;
}
.content form {
margin: auto;
padding: 20px;
width: 100%;
@@ -137,11 +144,14 @@ a {
a:hover {
color: #f60075;
}
a.tos-link {
font-size: 14px;
}
button {
button, .button {
background-color: #282828;
color: #760038;
border: 2px solid #760038;
border: 1px solid #760038;
border-radius: 5px;
width: 100%;
max-width: 600px;
@@ -149,36 +159,39 @@ button {
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
display: inline-block;
text-align: center;
line-height: 40px;
}
button:hover {
button:hover, .button:hover {
background-color: #f60075;
color: #282828;
border: 2px solid #f60075;
border: 1px solid #f60075;
}
button.primary {
button.primary, .button.primary {
background-color: #760038;
color: white;
border: none;
}
button.primary:hover {
button.primary:hover, .button.primary:hover {
background-color: #f60075;
}
button:disabled {
background-color: #505050;
border: 2px solid #505050;
button:disabled, .button:disabled {
background-color: #999999;
border: 1px solid #999999;
}
button:disabled:hover {
background-color: #505050;
border: 2px solid #505050;
button:disabled:hover, .button:disabled:hover {
background-color: #999999;
border: 1px solid #999999;
}
input:not([type=radio]), select {
background-color: #252525;
color: white;
height: 50px;
border: 2px solid #505050;
border: 1px solid #999999;
border-radius: 5px;
padding-left: 15px;
padding-left: 8px;
}
form button.user-selection .profile-image, .login-profile .profile-image {
@@ -213,7 +226,7 @@ form button.user-selection:hover .profile-image, .login-profile:hover .profile-i
text-align: center;
}
.login-profile .names div:first-of-type {
font-size: 40px;
font-size: 26px;
font-weight: 300;
}
.login-profile .names div:nth-of-type(2) {
@@ -244,20 +257,21 @@ form .field.check-box {
display: flex;
}
form .field.check-box input[type=checkbox] {
height: 20px;
height: 16px;
vertical-align: middle;
}
form .field.check-box label {
height: 20px;
height: 16px;
text-transform: inherit;
display: inline-block;
padding: 2px 0 0 15px;
width: 100%;
color: white;
}
form label {
color: #898989;
text-transform: uppercase;
font-size: 0.9rem;
font-size: 0.8rem;
margin-bottom: 3px;
}
form label span.optional {
@@ -301,7 +315,7 @@ form button.user-selection .sessionstate {
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #505050;
border-color: #999999;
border-style: solid;
border-width: 1px;
position: absolute;
@@ -362,6 +376,7 @@ form ul#passwordcomplexity {
flex-wrap: wrap;
padding: 0;
list-style: none;
margin-bottom: 0;
}
form ul#passwordcomplexity li {
flex: 1 0 50%;
@@ -444,6 +459,10 @@ footer {
padding: 10px;
}
.error {
color: #F20D6B;
}
html {
background-color: white;
color: #282828;
@@ -454,66 +473,75 @@ html header .logo {
html h1, html h2 {
color: #282828;
}
html button {
html button, html .button {
background-color: white;
color: #760038;
border: 2px solid #760038;
border: 1px solid #760038;
}
html button:hover {
html button:hover, html .button:hover {
background-color: #f60075;
border: 2px solid #f60075;
border: 1px solid #f60075;
color: #FFFFFF;
}
html button.primary {
html button.primary, html .button.primary {
background-color: #760038;
color: white;
color: #FFFFFF;
border: none;
box-shadow: 0px 10px 30px #760038;
}
html button.primary:hover {
html button.primary:hover, html .button.primary:hover {
background-color: #f60075;
}
html button.clean {
html button:disabled, html .button:disabled {
background-color: #999999;
border: 1px solid #999999;
}
html button:disabled:hover, html .button:disabled:hover {
background-color: #999999;
border: 1px solid #999999;
}
html button.clean, html .button.clean {
color: #282828;
}
html button.clean:hover {
html button.clean:hover, html .button.clean:hover {
border: none;
background-color: #FFFFFF;
}
html button.user-selection .profile-image {
html button.user-selection .profile-image, html .button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.user-selection .profile-image {
html button.user-selection .profile-image, html .button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light@2x.png");
background-size: 80px 80px;
}
}
html button.user-selection:hover {
html button.user-selection:hover, html .button.user-selection:hover {
background-color: #FFFFFF;
}
html button.user-selection:hover .profile-image {
html button.user-selection:hover .profile-image, html .button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.user-selection:hover .profile-image {
html button.user-selection:hover .profile-image, html .button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover@2x.png");
background-size: 80px 80px;
}
}
html button.other-user .other-user-image {
html button.other-user .other-user-image, html .button.other-user .other-user-image {
background-image: url("../../../images/icon-newuser-light.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.other-user .other-user-image {
html button.other-user .other-user-image, html .button.other-user .other-user-image {
background-image: url("../../../images/icon-newuser-light@2x.png");
background-size: 80px 60px;
}
}
html button.other-user:hover .other-user-image {
html button.other-user:hover .other-user-image, html .button.other-user:hover .other-user-image {
background-image: url("../../../images/icon-newuser-light-hover.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.other-user:hover .other-user-image {
html button.other-user:hover .other-user-image, html .button.other-user:hover .other-user-image {
background-image: url("../../../images/icon-newuser-light-hover@2x.png");
background-size: 80px 60px;
}
@@ -532,4 +560,41 @@ html footer {
background-image: url("../gradientdeco-full.svg");
}
form .field.check-box label {
color: #282828;
}
form ul#passwordcomplexity li i {
color: #50CA3D;
}
form ul#passwordcomplexity li.invalid i {
color: #F20D6B;
}
.login-profile .profile-image, form button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
.login-profile .profile-image, form button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light@2x.png");
background-size: 80px 80px;
}
}
.login-profile:hover .profile-image, form button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
.login-profile:hover .profile-image, form button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover@2x.png");
background-size: 80px 80px;
}
}
.free-tier {
border: 2px solid #F20D6B;
}
.error {
color: #F20D6B;
}
/*# sourceMappingURL=light.css.map */

View File

@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/caos/variables.scss","../../scss/variables.scss","../../scss/light.scss"],"names":[],"mappings":"AACA;EACI;EACA;;AAIJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;EACA;EACA;EACA;AAA6D;EAC7D;;AC5EJ;EACI;EACA,aCMW;EDLX;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA,kBCDc;EDEd,OCDQ;EDER;EACA;EACA;;;AAMJ;EACI,OCXQ;EDYR,aClBS;EDmBT;EACA,WEzBS;;;AF4Bb;EACI,OClBQ;EDmBR,aCzBS;ED0BT;EACA,WE/BU;;;AFkCd;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OChDW;EDiDX;EACA;;AAEA;EACI,OCpDY;;;ADwDpB;EACI,kBC5Dc;ED6Dd,OC3DW;ED4DX;EACA;EACA;EACA;EACA,QE7EU;EF8EV;EACA;EACA;;AACA;EACI,kBCpEY;EDqEZ,OCxEU;EDyEV;;AAGJ;EACI,kBC3EO;ED4EP,OC7EI;ED8EJ;;AACA;EACI,kBC9EQ;;ADkFhB;EACI,kBEzEW;EF0EX;;AAEA;EACI,kBE7EO;EF8EP;;;AAKZ;EACI,kBEnFmB;EFoFnB,OCjGQ;EDkGR,QE9GU;EF+GV;EACA;EACA;;;AAIA;EACI;EACA;EACA;EACA;EE9GN;;AACA;EFyGE;IExGA;IACA;;;AF+GA;EElHF;;AACA;EFiHE;IEhHA;IACA;;;;AFsHA;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,WE7IC;EF8ID;;AAGJ;EACI;EACA;EACA;EACA,OE/HC;;;AFqIT;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAIR;EACI,OE5KK;EF6KL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OCjNI;EDkNJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBE5MW;;AF+Mf;EACI;;AAIR;EACI;;AAKA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA,cErOO;EFsOP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OEjQP;;AFwQL;EACI;;AAEJ;EACI;EACA;EACA;EACA;EE3RV;;AACA;EFsRM;IErRJ;IACA;;;AF6RQ;EACI;EACA;EElSd;;AACA;EF+RU;IE9RR;IACA;;;AFoSI;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,OE3SN;;AFgTE;EACI,OElTL;;AFuTP;EACI;;AACA;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MC1VI;;AD6VR;EACI,MC/VU;;;ADoWd;EACI;EACA;;;AAIR;EAEQ;EAEJ;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AAGJ;EACI;EACA;EACA;;;AG/ZJ;EACI,kBFeQ;EEdR,OFac;;AERd;EACI;;AAGJ;EACI,OFGU;;AEAd;EACI;EACA;EACA;;AAEA;EACI,kBFIa;EEHb;;AAGJ;EACI,kBFTG;EEUH,OFXA;EEYA;EACA;;AACA;EACI,kBFbI;;AEiBZ;EACI,OFrBM;;AEuBN;EACI;EACA,kBDEY;;ACGhB;ED9BV;;AACA;EC6BU;ID5BR;IACA;;;AC+BQ;EACI,kBDRY;;ACUZ;EDrCd;;AACA;ECoCc;IDnCZ;IACA;;;ACyCQ;ED5CV;;AACA;EC2CU;ID1CR;IACA;;;AC8CY;EDjDd;;AACA;ECgDc;ID/CZ;IACA;;;ACqDA;EACI,kBD9BoB;EC+BpB,OF1DU;;AE8DV;EACI,MF/DM;;AEkEV;EACI,MFlEA;;AEsER;EAEQ","file":"light.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/caos/variables.scss","../../scss/variables.scss","../../scss/light.scss"],"names":[],"mappings":"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","file":"light.css"}

View File

@@ -14,19 +14,20 @@ html {
color: $fontColorLight;
}
button {
button, .button {
background-color: $backgroundColorLight;
color: $primaryColorLight;
border: 2px solid $primaryColorLight;
border: 1px solid $primaryColorLight;
&:hover {
background-color: $primaryColorHoverLight;
border: 2px solid $primaryColorHoverLight;
border: 1px solid $primaryColorHoverLight;
color: $buttonBackgroundColorHoverLight
}
&.primary {
background-color: $primaryColor;
color: $fontColor;
color: $buttonBackgroundColorHoverLight;
border: none;
box-shadow: 0px 10px 30px $primaryColor;
&:hover {
@@ -34,6 +35,16 @@ html {
}
}
&:disabled {
background-color: $inputBorderColor;
border: 1px solid $inputBorderColor;
&:hover {
background-color: $inputBorderColor;
border: 1px solid $inputBorderColor;
}
}
&.clean {
color: $fontColorLight;
@@ -90,4 +101,41 @@ html {
background-image: url($footerimgLight);
}
}
}
form {
.field.check-box label {
color: $fontColorLight;
}
ul#passwordcomplexity li {
i {
color: $okColorLight;
}
&.invalid {
i {
color: $nokColorLight;
}
}
}
}
%profile-image {
.profile-image {
@include retina-background-image($profileImgLight, "png", false, 80px, 80px);
}
&:hover .profile-image {
@include retina-background-image($profileImgLight, "png", true, 80px, 80px);
}
}
.free-tier {
border: 2px solid $nokColorLight;
}
.error {
color: $nokColorLight;
}

View File

@@ -3,7 +3,7 @@
*, *::before, *::after {
box-sizing: border-box;
font-family: $standardFont;
font-size: 18px;
font-size: 16px;
font-weight: 400;
}
@@ -30,6 +30,7 @@ h1 {
font-family: $headerFont;
font-weight: 300;
font-size: $headerSize;
text-align: center;
}
h2 {
@@ -56,7 +57,13 @@ header {
}
}
.content {
.head {
width: 100%;
max-width: 1000px;
margin: auto;
}
.content form {
margin: auto;
padding: 20px;
width: 100%;
@@ -71,12 +78,16 @@ a {
&:hover {
color: $primaryColorHover;
}
&.tos-link {
font-size: 14px;
}
}
button {
button, .button {
background-color: $backgroundColor;
color: $primaryColor;
border: 2px solid $primaryColor;
border: 1px solid $primaryColor;
border-radius: 5px;
width: 100%;
max-width: 600px;
@@ -84,10 +95,14 @@ button {
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
display: inline-block;
text-align: center;
line-height: 40px;
&:hover {
background-color: $primaryColorHover;
color: $backgroundColor;
border: 2px solid $primaryColorHover;
border: 1px solid $primaryColorHover;
}
&.primary {
@@ -101,22 +116,24 @@ button {
&:disabled {
background-color: $inputBorderColor;
border: 2px solid $inputBorderColor;
border: 1px solid $inputBorderColor;
&:hover {
background-color: $inputBorderColor;
border: 2px solid $inputBorderColor;
border: 1px solid $inputBorderColor;
}
}
}
input:not([type='radio']), select {
background-color: $inputBackgroundColor;
color: $fontColor;
height: $inputHeight;
border: 2px solid $inputBorderColor;
border: 1px solid $inputBorderColor;
border-radius: 5px;
padding-left: 15px;
padding-left: 8px;
}
%profile-image {
@@ -145,7 +162,7 @@ input:not([type='radio']), select {
text-align: center;
div:first-of-type {
font-size: $headerSize;
font-size: $header3Size;
font-weight: 300;
}
@@ -184,23 +201,24 @@ form {
display: flex;
input[type='checkbox'] {
height: 20px;
height: 16px;
vertical-align: middle;
}
& label {
height: 20px;
height: 16px;
text-transform: inherit;
display: inline-block;
padding: 2px 0 0 15px;
width: 100%;
color: $fontColor;
}
}
label {
color: $labelColor;
text-transform: uppercase;
font-size: 0.9rem;
font-size: 0.8rem;
margin-bottom: 3px;
span.optional {
@@ -320,6 +338,7 @@ form {
flex-wrap: wrap;
padding: 0;
list-style: none;
margin-bottom: 0;
li {
flex: 1 0 50%;
@@ -412,7 +431,11 @@ footer {
}
.free-tier {
border: 2px solid #F20D6B;
border: 2px solid $nokColor;
border-radius: 5px;
padding: 10px;
}
.error {
color: $nokColor;
}

View File

@@ -6,6 +6,7 @@ $headerFont: Lato;
$inputHeight: 50px;
$headerSize: 40px;
$header2Size: 30px;
$header3Size: 26px;
$retina: "only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)";
@mixin retina-background-image($file, $type, $hover, $width, $height) {
@@ -27,13 +28,14 @@ $fontColor: #BBBBC8;
$primaryColor: #3574C6;
$primaryColorHover: lighten($primaryColor, 10%);
$labelColor: #898989;
$inputBorderColor: #505050;
$inputBorderColor: #999999;
$inputBackgroundColor: #252525;
$buttonBackgroundColorHover: $inputBackgroundColor;
$profileImgDark: "../../../images/icon-user-dark";
$otherUserImgDark: "../../../images/icon-newuser-dark";
$nokColor: #F20D6B;
$okColor: #0DF279;
$errorColor: red;
// ----- LIGHT-THEME --------
@@ -44,4 +46,6 @@ $primaryColorHoverLight: lighten($primaryColorLight, 10%);
$inputBackgroundColorLight: #FFFFFF;
$buttonBackgroundColorHoverLight: $inputBackgroundColorLight;
$profileImgLight: "../../../images/icon-user-light";
$otherUserImgLight: "../../../images/icon-newuser-light";
$otherUserImgLight: "../../../images/icon-newuser-light";
$nokColorLight: #F20D6B;
$okColorLight: #50CA3D;

View File

@@ -73,7 +73,7 @@
*, *::before, *::after {
box-sizing: border-box;
font-family: Lato;
font-size: 18px;
font-size: 16px;
font-weight: 400;
}
@@ -98,6 +98,7 @@ h1 {
font-family: Lato;
font-weight: 300;
font-size: 40px;
text-align: center;
}
h2 {
@@ -123,7 +124,13 @@ header .logo {
margin: 30px;
}
.content {
.head {
width: 100%;
max-width: 1000px;
margin: auto;
}
.content form {
margin: auto;
padding: 20px;
width: 100%;
@@ -138,11 +145,14 @@ a {
a:hover {
color: #5b8fd3;
}
a.tos-link {
font-size: 14px;
}
button {
button, .button {
background-color: #282828;
color: #3574C6;
border: 2px solid #3574C6;
border: 1px solid #3574C6;
border-radius: 5px;
width: 100%;
max-width: 600px;
@@ -150,36 +160,39 @@ button {
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
display: inline-block;
text-align: center;
line-height: 40px;
}
button:hover {
button:hover, .button:hover {
background-color: #5b8fd3;
color: #282828;
border: 2px solid #5b8fd3;
border: 1px solid #5b8fd3;
}
button.primary {
button.primary, .button.primary {
background-color: #3574C6;
color: #BBBBC8;
border: none;
}
button.primary:hover {
button.primary:hover, .button.primary:hover {
background-color: #5b8fd3;
}
button:disabled {
background-color: #505050;
border: 2px solid #505050;
button:disabled, .button:disabled {
background-color: #999999;
border: 1px solid #999999;
}
button:disabled:hover {
background-color: #505050;
border: 2px solid #505050;
button:disabled:hover, .button:disabled:hover {
background-color: #999999;
border: 1px solid #999999;
}
input:not([type=radio]), select {
background-color: #252525;
color: #BBBBC8;
height: 50px;
border: 2px solid #505050;
border: 1px solid #999999;
border-radius: 5px;
padding-left: 15px;
padding-left: 8px;
}
form button.user-selection .profile-image, .login-profile .profile-image {
@@ -214,7 +227,7 @@ form button.user-selection:hover .profile-image, .login-profile:hover .profile-i
text-align: center;
}
.login-profile .names div:first-of-type {
font-size: 40px;
font-size: 26px;
font-weight: 300;
}
.login-profile .names div:nth-of-type(2) {
@@ -245,20 +258,21 @@ form .field.check-box {
display: flex;
}
form .field.check-box input[type=checkbox] {
height: 20px;
height: 16px;
vertical-align: middle;
}
form .field.check-box label {
height: 20px;
height: 16px;
text-transform: inherit;
display: inline-block;
padding: 2px 0 0 15px;
width: 100%;
color: #BBBBC8;
}
form label {
color: #898989;
text-transform: uppercase;
font-size: 0.9rem;
font-size: 0.8rem;
margin-bottom: 3px;
}
form label span.optional {
@@ -302,7 +316,7 @@ form button.user-selection .sessionstate {
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #505050;
border-color: #999999;
border-style: solid;
border-width: 1px;
position: absolute;
@@ -363,6 +377,7 @@ form ul#passwordcomplexity {
flex-wrap: wrap;
padding: 0;
list-style: none;
margin-bottom: 0;
}
form ul#passwordcomplexity li {
flex: 1 0 50%;
@@ -444,4 +459,8 @@ footer {
padding: 10px;
}
.error {
color: #F20D6B;
}
/*# sourceMappingURL=dark.css.map */

View File

@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/variables.scss"],"names":[],"mappings":"AACA;EACI;EACA;;AAIJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;EACA;EACA;EACA;AAA6D;EAC7D;;AC5EJ;EACI;EACA,aCHW;EDIX;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA,kBCOc;EDNd,OCOQ;EDNR;EACA;EACA;EAEI;;;AAIR;EACI,OCHQ;EDIR,aC3BS;ED4BT;EACA,WCzBS;;;AD4Bb;EACI,OCVQ;EDWR,aClCS;EDmCT;EACA,WC/BU;;;ADkCd;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCxCW;EDyCX;EACA;;AAEA;EACI,OC5CY;;;ADgDpB;EACI,kBCpDc;EDqDd,OCnDW;EDoDX;EACA;EACA;EACA;EACA,QC7EU;ED8EV;EACA;EACA;;AACA;EACI,kBC5DY;ED6DZ,OChEU;EDiEV;;AAGJ;EACI,kBCnEO;EDoEP,OCrEI;EDsEJ;;AACA;EACI,kBCtEQ;;AD0EhB;EACI,kBCzEW;ED0EX;;AAEA;EACI,kBC7EO;ED8EP;;;AAKZ;EACI,kBCnFmB;EDoFnB,OCzFQ;ED0FR,QC9GU;ED+GV;EACA;EACA;;;AAIA;EACI;EACA;EACA;EACA;EC9GN;;AACA;EDyGE;ICxGA;IACA;;;AD+GA;EClHF;;AACA;EDiHE;IChHA;IACA;;;;ADsHA;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,WC7IC;ED8ID;;AAGJ;EACI;EACA;EACA;EACA,OC/HC;;;ADqIT;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAIR;EACI,OC5KK;ED6KL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OCzMI;ED0MJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBC5MW;;AD+Mf;EACI;;AAIR;EACI;;AAKA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA,cCrOO;EDsOP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OCjQP;;ADwQL;EACI;;AAEJ;EACI;EACA;EACA;EACA;EC3RV;;AACA;EDsRM;ICrRJ;IACA;;;AD6RQ;EACI;EACA;EClSd;;AACA;ED+RU;IC9RR;IACA;;;ADoSI;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,OC3SN;;ADgTE;EACI,OClTL;;ADuTP;EACI;;AACA;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MClVI;;ADqVR;EACI,MCvVU;;;AD4Vd;EACI;EACA;;;AAIR;EAII;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AAGJ;EACI;EACA;EACA","file":"dark.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/variables.scss"],"names":[],"mappings":"AACA;EACI;EACA;;AAIJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;EACA;EACA;EACA;AAA6D;EAC7D;;AC5EJ;EACI;EACA,aCHW;EDIX;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA,kBCQc;EDPd,OCQQ;EDPR;EACA;EACA;EAEI;;;AAIR;EACI,OCFQ;EDGR,aC3BS;ED4BT;EACA,WCzBS;ED0BT;;;AAGJ;EACI,OCVQ;EDWR,aCnCS;EDoCT;EACA,WChCU;;;ADmCd;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OC9CW;ED+CX;EACA;;AAEA;EACI,OClDY;;ADqDhB;EACI;;;AAIR;EACI,kBC9Dc;ED+Dd,OC7DW;ED8DX;EACA;EACA;EACA;EACA,QCxFU;EDyFV;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI,kBC1EY;ED2EZ,OC9EU;ED+EV;;AAGJ;EACI,kBCjFO;EDkFP,OCnFI;EDoFJ;;AACA;EACI,kBCpFQ;;ADwFhB;EACI,kBCvFW;EDwFX;;AAEA;EACI,kBC3FO;ED4FP;;;AAOZ;EACI,kBCnGmB;EDoGnB,OCzGQ;ED0GR,QC/HU;EDgIV;EACA;EACA;;;AAIA;EACI;EACA;EACA;EACA;EC9HN;;AACA;EDyHE;ICxHA;IACA;;;AD+HA;EClIF;;AACA;EDiIE;IChIA;IACA;;;;ADsIA;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,WC5JE;ED6JF;;AAGJ;EACI;EACA;EACA;EACA,OC/IC;;;ADqJT;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA,OC3LA;;AD+LR;EACI,OC7LK;ED8LL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OC1NI;ED2NJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBC7NW;;ADgOf;EACI;;AAIR;EACI;;AAKA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA,cCtPO;EDuPP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OClRP;;ADyRL;EACI;;AAEJ;EACI;EACA;EACA;EACA;EC5SV;;AACA;EDuSM;ICtSJ;IACA;;;AD8SQ;EACI;EACA;ECnTd;;AACA;EDgTU;IC/SR;IACA;;;ADqTI;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,OC7TN;;ADkUE;EACI,OCpUL;;ADyUP;EACI;;AACA;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MCpWI;;ADuWR;EACI,MCzWU;;;AD8Wd;EACI;EACA;;;AAIR;EAII;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI,OCpZO","file":"dark.css"}

View File

@@ -73,7 +73,7 @@
*, *::before, *::after {
box-sizing: border-box;
font-family: Lato;
font-size: 18px;
font-size: 16px;
font-weight: 400;
}
@@ -98,6 +98,7 @@ h1 {
font-family: Lato;
font-weight: 300;
font-size: 40px;
text-align: center;
}
h2 {
@@ -123,7 +124,13 @@ header .logo {
margin: 30px;
}
.content {
.head {
width: 100%;
max-width: 1000px;
margin: auto;
}
.content form {
margin: auto;
padding: 20px;
width: 100%;
@@ -138,11 +145,14 @@ a {
a:hover {
color: #5b8fd3;
}
a.tos-link {
font-size: 14px;
}
button {
button, .button {
background-color: #282828;
color: #3574C6;
border: 2px solid #3574C6;
border: 1px solid #3574C6;
border-radius: 5px;
width: 100%;
max-width: 600px;
@@ -150,36 +160,39 @@ button {
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
display: inline-block;
text-align: center;
line-height: 40px;
}
button:hover {
button:hover, .button:hover {
background-color: #5b8fd3;
color: #282828;
border: 2px solid #5b8fd3;
border: 1px solid #5b8fd3;
}
button.primary {
button.primary, .button.primary {
background-color: #3574C6;
color: #BBBBC8;
border: none;
}
button.primary:hover {
button.primary:hover, .button.primary:hover {
background-color: #5b8fd3;
}
button:disabled {
background-color: #505050;
border: 2px solid #505050;
button:disabled, .button:disabled {
background-color: #999999;
border: 1px solid #999999;
}
button:disabled:hover {
background-color: #505050;
border: 2px solid #505050;
button:disabled:hover, .button:disabled:hover {
background-color: #999999;
border: 1px solid #999999;
}
input:not([type=radio]), select {
background-color: #252525;
color: #BBBBC8;
height: 50px;
border: 2px solid #505050;
border: 1px solid #999999;
border-radius: 5px;
padding-left: 15px;
padding-left: 8px;
}
form button.user-selection .profile-image, .login-profile .profile-image {
@@ -214,7 +227,7 @@ form button.user-selection:hover .profile-image, .login-profile:hover .profile-i
text-align: center;
}
.login-profile .names div:first-of-type {
font-size: 40px;
font-size: 26px;
font-weight: 300;
}
.login-profile .names div:nth-of-type(2) {
@@ -245,20 +258,21 @@ form .field.check-box {
display: flex;
}
form .field.check-box input[type=checkbox] {
height: 20px;
height: 16px;
vertical-align: middle;
}
form .field.check-box label {
height: 20px;
height: 16px;
text-transform: inherit;
display: inline-block;
padding: 2px 0 0 15px;
width: 100%;
color: #BBBBC8;
}
form label {
color: #898989;
text-transform: uppercase;
font-size: 0.9rem;
font-size: 0.8rem;
margin-bottom: 3px;
}
form label span.optional {
@@ -302,7 +316,7 @@ form button.user-selection .sessionstate {
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #505050;
border-color: #999999;
border-style: solid;
border-width: 1px;
position: absolute;
@@ -363,6 +377,7 @@ form ul#passwordcomplexity {
flex-wrap: wrap;
padding: 0;
list-style: none;
margin-bottom: 0;
}
form ul#passwordcomplexity li {
flex: 1 0 50%;
@@ -444,6 +459,10 @@ footer {
padding: 10px;
}
.error {
color: #F20D6B;
}
html {
background-color: #f5f5f5;
color: #282828;
@@ -455,66 +474,75 @@ html header .logo {
html h1, html h2 {
color: #282828;
}
html button {
html button, html .button {
background-color: #f5f5f5;
color: #3574C6;
border: 2px solid #3574C6;
border: 1px solid #3574C6;
}
html button:hover {
html button:hover, html .button:hover {
background-color: #5b8fd3;
border: 2px solid #5b8fd3;
border: 1px solid #5b8fd3;
color: #FFFFFF;
}
html button.primary {
html button.primary, html .button.primary {
background-color: #3574C6;
color: #BBBBC8;
color: #FFFFFF;
border: none;
box-shadow: 0px 10px 30px #3574C6;
}
html button.primary:hover {
html button.primary:hover, html .button.primary:hover {
background-color: #5b8fd3;
}
html button.clean {
html button:disabled, html .button:disabled {
background-color: #999999;
border: 1px solid #999999;
}
html button:disabled:hover, html .button:disabled:hover {
background-color: #999999;
border: 1px solid #999999;
}
html button.clean, html .button.clean {
color: #282828;
}
html button.clean:hover {
html button.clean:hover, html .button.clean:hover {
border: none;
background-color: #FFFFFF;
}
html button.user-selection .profile-image {
html button.user-selection .profile-image, html .button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.user-selection .profile-image {
html button.user-selection .profile-image, html .button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light@2x.png");
background-size: 80px 80px;
}
}
html button.user-selection:hover {
html button.user-selection:hover, html .button.user-selection:hover {
background-color: #FFFFFF;
}
html button.user-selection:hover .profile-image {
html button.user-selection:hover .profile-image, html .button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.user-selection:hover .profile-image {
html button.user-selection:hover .profile-image, html .button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover@2x.png");
background-size: 80px 80px;
}
}
html button.other-user .other-user-image {
html button.other-user .other-user-image, html .button.other-user .other-user-image {
background-image: url("../../../images/icon-newuser-light.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.other-user .other-user-image {
html button.other-user .other-user-image, html .button.other-user .other-user-image {
background-image: url("../../../images/icon-newuser-light@2x.png");
background-size: 80px 60px;
}
}
html button.other-user:hover .other-user-image {
html button.other-user:hover .other-user-image, html .button.other-user:hover .other-user-image {
background-image: url("../../../images/icon-newuser-light-hover.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
html button.other-user:hover .other-user-image {
html button.other-user:hover .other-user-image, html .button.other-user:hover .other-user-image {
background-image: url("../../../images/icon-newuser-light-hover@2x.png");
background-size: 80px 60px;
}
@@ -529,5 +557,41 @@ html #qrcode svg rect.color {
html #qrcode svg rect.bg-color {
fill: #f5f5f5;
}
form .field.check-box label {
color: #282828;
}
form ul#passwordcomplexity li i {
color: #50CA3D;
}
form ul#passwordcomplexity li.invalid i {
color: #F20D6B;
}
.login-profile .profile-image, form button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
.login-profile .profile-image, form button.user-selection .profile-image {
background-image: url("../../../images/icon-user-light@2x.png");
background-size: 80px 80px;
}
}
.login-profile:hover .profile-image, form button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
.login-profile:hover .profile-image, form button.user-selection:hover .profile-image {
background-image: url("../../../images/icon-user-light-hover@2x.png");
background-size: 80px 80px;
}
}
.free-tier {
border: 2px solid #F20D6B;
}
.error {
color: #F20D6B;
}
/*# sourceMappingURL=light.css.map */

View File

@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/variables.scss","../../scss/light.scss"],"names":[],"mappings":"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","file":"light.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.scss","../../scss/variables.scss","../../scss/light.scss"],"names":[],"mappings":"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","file":"light.css"}

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "PasswordChange.Description"}}</p>
<p>{{t "PasswordChange.Description"}}</p>
</div>
<form action="{{ changePasswordUrl }}" method="POST">
@@ -42,8 +44,8 @@
<div class="actions">
<button type="submit" id="change-password-button" name="resend" value="false" class="primary right">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "PasswordChangeDone.Description"}}</p>
<p>{{t "PasswordChangeDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
@@ -13,8 +15,8 @@
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "UsernameChange.Description"}}</p>
<p>{{t "UsernameChange.Description"}}</p>
</div>
<form action="{{ changeUsernameUrl }}" method="POST">
@@ -21,8 +23,8 @@
<div class="actions">
<button type="submit" id="submit-button" value="false" class="primary right">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "UsernameChangeDone.Description"}}</p>
<p>{{t "UsernameChangeDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">

View File

@@ -0,0 +1,31 @@
{{template "main-top" .}}
<div class="head">
<h1>{{t "ExternalNotFoundOption.Title"}}</h1>
<p>{{t "ExternalNotFoundOption.Description"}}</p>
</div>
<form action="{{ externalNotFoundOptionUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="secondary right" name="link" value="true" formnovalidate>{{t "ExternalNotFoundOption.Link"}}</button>
<button class="secondary right" name="autoregister" value="true" formnovalidate>{{t "ExternalNotFoundOption.AutoRegister"}}</button>
<a class="button secondary" href="{{ loginUrl .AuthReqID }}">
{{t "Actions.Back"}}
</a>
</div>
{{template "error-message" .}}
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "InitPassword.Description" }}</p>
<p>{{t "InitPassword.Description" }}</p>
</div>
<form action="{{ initPasswordUrl }}" method="POST">
@@ -47,8 +49,8 @@
<div class="actions">
<button type="submit" id="init-button" name="resend" value="false" class="primary right" >{{t "Actions.Next"}}</button>
<button type="submit" name="resend" value="true" class="secondary right" formnovalidate>{{t "Actions.Resend" }}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "PasswordSetDone.Description"}}</p>
<p>{{t "PasswordSetDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
@@ -12,8 +14,8 @@
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "InitUser.Description" }}</p>
<p>{{t "InitUser.Description" }}</p>
</div>
<form action="{{ initUserUrl }}" method="POST">
@@ -49,8 +51,8 @@
value="false"
class="primary right">{{t "Actions.Next"}}</button>
<button type="submit" name="resend" value="true" class="secondary right" formnovalidate>{{t "Actions.Resend" }}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "InitUserDone.Description"}}</p>
<p>{{t "InitUserDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
@@ -12,8 +14,8 @@
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -0,0 +1,25 @@
{{template "main-top" .}}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "LinkingUsersDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -1,8 +1,16 @@
{{template "main-top" .}}
<h1>{{t "Login.Title"}}</h1>
<p>{{t "Login.Description"}}</p>
<div class="head">
{{if .Linking}}
<h1>{{t "Login.TitleLinking"}}</h1>
<p>{{t "Login.DescriptionLinking"}}</p>
{{else}}
<h1>{{t "Login.Title"}}</h1>
<p>{{t "Login.Description"}}</p>
{{end}}
</div>
<form action="{{ loginNameUrl }}" method="POST">
@@ -10,19 +18,36 @@
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
{{if .LoginPolicy.AllowUsernamePassword }}
<div class="fields">
<div class="field">
<label class="label" for="loginName">{{t "Login.Loginname"}}</label>
<input class="input" type="text" id="loginName" name="loginName" placeholder="{{t "Login.LoginnamePlaceHolder"}}" value="{{ .LoginName }}" autocomplete="username" autofocus required>
</div>
</div>
{{end}}
{{template "error-message" .}}
<div class="actions">
<button class="primary right" id="submit-button" type="submit">{{t "Actions.Next"}}</button>
<button class="secondary right" name="register" value="true" formnovalidate>{{t "Actions.Register"}}</button>
<button class="primary" id="submit-button" type="submit">{{t "Actions.Next"}}</button>
{{if .LoginPolicy.AllowRegister}}
<button class="secondary" name="register" value="true" formnovalidate>{{t "Actions.Register"}}</button>
{{end}}
</div>
{{if .LoginPolicy.AllowExternalIDP}}
<div class="actions idp-providers">
<p>{{t "Login.ExternalLogin"}}</p>
{{ $reqid := .AuthReqID}}
{{range $provider := .IDPProviders}}
<a href="{{ externalIDPAuthURL $reqid $provider.IDPConfigID}}" class="button secondary idp-providers">
{{$provider.Name}}
</a>
{{end}}
</div>
{{end}}
</form>

View File

@@ -1,8 +1,9 @@
{{template "main-top" .}}
<h1>{{t "LogoutDone.Title"}}</h1>
<p>{{t "LogoutDone.Description"}}</p>
<div class="head">
<h1>{{t "LogoutDone.Title"}}</h1>
<p> {{t "LogoutDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "EmailVerification.Description"}}</p>
<p>{{t "EmailVerification.Description"}}</p>
</div>
<form action="{{ mailVerificationUrl }}" method="POST">
@@ -25,8 +27,8 @@
{{ if .UserID }}
<button type="submit" name="resend" value="true" class="secondary right" formnovalidate>{{t "Actions.Resend"}}</button>
{{ end }}
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "EmailVerificationDone.Description"}}</p>
<p>{{t "EmailVerificationDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
@@ -13,8 +15,8 @@
<div class="actions">
<button class="primary right" type="submit">{{if .AuthReqID }}{{t "Actions.Next"}}{{else}}{{t "Actions.Login"}}{{end}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "MfaInitDone.Description"}}</p>
<p>{{t "MfaInitDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
@@ -13,8 +15,8 @@
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "MfaInitVerify.Description"}}</p>
<p>{{t "MfaInitVerify.Description"}}</p>
</div>
<form action="{{ mfaInitVerifyUrl }}" method="POST">
@@ -35,11 +37,11 @@
<div class="actions">
<button class="primary right" id="submit-button" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ mfaPromptChangeUrl .AuthReqID .MfaType }}">
<button class="secondary" type="button">{{t "Actions.Back"}}</button>
<a class="button secondary" href="{{ mfaPromptChangeUrl .AuthReqID .MfaType }}">
{{t "Actions.Back"}}
</a>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "MfaPrompt.Description"}}</p>
<p>{{t "MfaPrompt.Description"}}</p>
</div>
<form action="{{ mfaPromptUrl }}" method="POST">
@@ -25,8 +27,8 @@
{{if not .MfaRequired}}
<button class="default right" name="skip" value="true" type="submit" formnovalidate>{{t "Actions.Skip"}}</button>
{{end}}
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "MfaVerify.Description"}}</p>
<p>{{t "MfaVerify.Description"}}</p>
</div>
<form action="{{ mfaVerifyUrl }}" method="POST">
@@ -22,8 +24,8 @@
<div class="actions">
<button class="primary right" id="submit-button" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ loginUrl }}">
<button class="secondary" type="button">{{t "Actions.Cancel"}}</button>
<a class="button secondary" href="{{ loginUrl }}">
{{t "Actions.Cancel"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "Password.Description"}}</p>
<p>{{t "Password.Description"}}</p>
</div>
<form action="{{ passwordUrl }}" method="POST">
@@ -25,8 +27,8 @@
<a href="{{ loginNameChangeUrl .AuthReqID }}">
<button class="secondary" type="button">{{t "Actions.Back"}}</button>
</a>
<a href="{{ passwordResetUrl .AuthReqID }}">
<button class="secondary" type="button">{{t "Actions.ForgotPassword"}}</button>
<a class="button secondary" href="{{ passwordResetUrl .AuthReqID }}">
{{t "Actions.ForgotPassword"}}
</a>
</div>
</form>

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
{{ template "user-profile" . }}
<div class="head">
{{ template "user-profile" . }}
<p>{{t "PasswordResetDone.Description"}}</p>
<p>{{t "PasswordResetDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">

View File

@@ -1,7 +1,10 @@
{{template "main-top" .}}
<h1>{{t "Registration.Title"}}</h1>
<p>{{t "Registration.Description"}}</p>
<div class="head">
<h1>{{t "Registration.Title"}}</h1>
<p>{{t "Registration.Description"}}</p>
</div>
<form action="{{ registrationUrl }}" method="POST">
@@ -62,7 +65,7 @@
<input class="input" type="checkbox" id="register-term-confirmation" name="register-term-confirmation" required>
<label for="register-term-confirmation">
{{t "Registration.TosConfirm"}}
<a class="" target="_blank" href="{{t "Registration.TosLink"}}">{{t "Registration.TosLinkText"}}</a>
<a class="tos-link" target="_blank" href="{{t "Registration.TosLink"}}">{{t "Registration.TosLinkText"}}</a>
</label>
</div>
</div>
@@ -72,8 +75,8 @@
<div class="actions">
<button class="primary right" id="register-button" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ loginNameChangeUrl .AuthReqID }}">
<button class="secondary" type="button">{{t "Actions.Back"}}</button>
<a class="button secondary" href="{{ loginNameChangeUrl .AuthReqID }}">
{{t "Actions.Back"}}
</a>
</div>
</form>

View File

@@ -0,0 +1,40 @@
{{template "main-top" .}}
<div class="head">
<h1>{{t "RegisterOption.Title"}}</h1>
<p>{{t "RegisterOption.Description"}}</p>
</div>
<form action="{{ registerOptionUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
{{if .LoginPolicy.AllowUsernamePassword }}
<button class="secondary right" name="usernamepassword" value="true" formnovalidate>{{t "RegisterOption.RegisterUsernamePassword"}}</button>
{{end}}
{{if .LoginPolicy.AllowExternalIDP}}
{{ $reqid := .AuthReqID}}
{{range $provider := .IDPProviders}}
<a href="{{ externalIDPRegisterURL $reqid $provider.IDPConfigID}}" class="button secondary idp-providers">
{{$provider.Name}}
</a>
{{end}}
{{end}}
<a class="button secondary" href="{{ loginNameChangeUrl .AuthReqID }}">
{{t "Actions.Back"}}
</a>
</div>
{{template "error-message" .}}
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -1,8 +1,10 @@
{{template "main-top" .}}
<h1>{{t "RegistrationOrg.Title"}}</h1>
<p class="free-tier">{{t "RegistrationOrg.FreeTillEndOfYear"}}</p>
<p>{{t "RegistrationOrg.Description"}}</p>
<div class="head">
<h1>{{t "RegistrationOrg.Title"}}</h1>
<p class="free-tier">{{t "RegistrationOrg.FreeTillEndOfYear"}}</p>
<p>{{t "RegistrationOrg.Description"}}</p>
</div>
<form action="{{ orgRegistrationUrl }}" method="POST">
@@ -61,7 +63,7 @@
<input class="input" type="checkbox" id="register-term-confirmation" name="register-term-confirmation" required>
<label for="register-term-confirmation">
{{t "RegistrationOrg.TosConfirm"}}
<a class="" target="_blank" href="{{t "RegistrationOrg.TosLink"}}">{{t "RegistrationOrg.TosLinkText"}}</a>
<a class="tos-link" target="_blank" href="{{t "RegistrationOrg.TosLink"}}">{{t "RegistrationOrg.TosLinkText"}}</a>
</label>
</div>
</div>

View File

@@ -1,8 +1,15 @@
{{template "main-top" .}}
<div class="head">
{{if .Linking}}
<h1>{{t "UserSelection.TitleLinking"}}</h1>
<p>{{t "UserSelection.DescriptionLinking"}}</p>
{{else}}
<h1>{{t "UserSelection.Title"}}</h1>
<p>{{t "UserSelection.Description"}}</p>
{{end}}
</div>
<h1>{{t "UserSelection.Title"}}</h1>
<p>{{t "UserSelection.Description"}}</p>
<form action="{{ userSelectionUrl }}" method="POST">

View File

@@ -1,13 +1,13 @@
{{define "user-profile"}}
{{if .LoginName}}
<div class="login-profile">
<div class="profile-image"></div>
<div class="names">
{{if .DisplayName}}
<div class="displayname">{{.DisplayName}}</div>
{{end}}
<div class="loginname">{{.LoginName}}</div>
{{if .LoginName}}
<div class="login-profile">
<div class="profile-image"></div>
<div class="names">
{{if .DisplayName}}
<div class="displayname">{{.DisplayName}}</div>
{{end}}
<div class="loginname">{{.LoginName}}</div>
</div>
</div>
</div>
{{end}}
{{end}}
{{end}}