fix: improvements for login and oidc (#227)

* add csrf

* caching

* caching

* caching

* caching

* security headers

* csp and security headers

* error handler csp

* select user with display name

* csp

* user selection styling

* username to loginname

* regenerate grpc

* regenerate

* change to login name
This commit is contained in:
Livio Amstutz 2020-06-17 08:06:40 +02:00 committed by GitHub
parent dfe6d0deb4
commit 1c59d18fee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
108 changed files with 19226 additions and 19220 deletions

View File

@ -24,6 +24,7 @@ export ZITADEL_USER_VERIFICATION_KEY=UserVerificationKey_1
export ZITADEL_OTP_VERIFICATION_KEY=OTPVerificationKey_1 export ZITADEL_OTP_VERIFICATION_KEY=OTPVerificationKey_1
export ZITADEL_OIDC_KEYS_ID=OIDCKey_1 export ZITADEL_OIDC_KEYS_ID=OIDCKey_1
export ZITADEL_COOKIE_KEY=CookieKey_1 export ZITADEL_COOKIE_KEY=CookieKey_1
export ZITADEL_CSRF_KEY=CookieKey_1
# Notifications # Notifications
export DEBUG_MODE=TRUE export DEBUG_MODE=TRUE
@ -47,6 +48,13 @@ export ZITADEL_CONSOLE=http://localhost:4200
export CAOS_OIDC_DEV=true export CAOS_OIDC_DEV=true
export ZITADEL_COOKIE_DOMAIN=localhost export ZITADEL_COOKIE_DOMAIN=localhost
#CSRF
export ZITADEL_CSRF_DEV=true
#CACHE
export ZITADEL_CACHE_MAXAGE=12h
export ZITADEL_CACHE_SHARED_MAXAGE=168h
#Console #Console
export ZITADEL_CONSOLE_ENV_DIR=../../console/src/assets/ export ZITADEL_CONSOLE_ENV_DIR=../../console/src/assets/

View File

@ -66,6 +66,9 @@ Auth:
Domain: $ZITADEL_COOKIE_DOMAIN Domain: $ZITADEL_COOKIE_DOMAIN
Key: Key:
EncryptionKeyID: $ZITADEL_COOKIE_KEY EncryptionKeyID: $ZITADEL_COOKIE_KEY
Cache:
MaxAge: $ZITADEL_CACHE_MAXAGE
SharedMaxAge: $ZITADEL_CACHE_SHARED_MAXAGE
Endpoints: Endpoints:
Auth: Auth:
Path: 'authorize' Path: 'authorize'
@ -129,6 +132,14 @@ Login:
ZitadelURL: '$ZITADEL_CONSOLE' ZitadelURL: '$ZITADEL_CONSOLE'
LanguageCookieName: 'caos.zitadel.login.lang' LanguageCookieName: 'caos.zitadel.login.lang'
DefaultLanguage: 'de' DefaultLanguage: 'de'
CSRF:
CookieName: 'caos.zitadel.login.csrf'
Key:
EncryptionKeyID: $ZITADEL_CSRF_KEY
Development: $ZITADEL_CSRF_DEV
Cache:
MaxAge: $ZITADEL_CACHE_MAXAGE
SharedMaxAge: $ZITADEL_CACHE_SHARED_MAXAGE
AuthZ: AuthZ:

1
go.mod
View File

@ -23,6 +23,7 @@ require (
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/mock v1.4.3 github.com/golang/mock v1.4.3
github.com/gorilla/csrf v1.7.0
github.com/golang/protobuf v1.4.2 github.com/golang/protobuf v1.4.2
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/schema v1.1.0 github.com/gorilla/schema v1.1.0

3
go.sum
View File

@ -166,6 +166,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/csrf v1.7.0 h1:mMPjV5/3Zd460xCavIkppUdvnl5fPXMpv2uz2Zyg7/Y=
github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA=
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
@ -259,6 +261,7 @@ github.com/nicksnyder/go-i18n/v2 v2.0.3 h1:ks/JkQiOEhhuF6jpNvx+Wih1NIiXzUnZeZVnJ
github.com/nicksnyder/go-i18n/v2 v2.0.3/go.mod h1:oDab7q8XCYMRlcrBnaY/7B1eOectbvj6B1UPBT+p5jo= github.com/nicksnyder/go-i18n/v2 v2.0.3/go.mod h1:oDab7q8XCYMRlcrBnaY/7B1eOectbvj6B1UPBT+p5jo=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

View File

@ -76,6 +76,7 @@ func createMux(ctx context.Context, g Gateway) *runtime.ServeMux {
func addInterceptors(handler http.Handler, g Gateway) http.Handler { func addInterceptors(handler http.Handler, g Gateway) http.Handler {
handler = http_mw.DefaultTraceHandler(handler) handler = http_mw.DefaultTraceHandler(handler)
handler = http_mw.NoCacheInterceptor(handler)
if interceptor, ok := g.(grpcGatewayCustomInterceptor); ok { if interceptor, ok := g.(grpcGatewayCustomInterceptor); ok {
handler = interceptor.GatewayHTTPInterceptor(handler) handler = interceptor.GatewayHTTPInterceptor(handler)
} }

View File

@ -4,12 +4,23 @@ const (
Authorization = "authorization" Authorization = "authorization"
Accept = "accept" Accept = "accept"
AcceptLanguage = "accept-language" AcceptLanguage = "accept-language"
CacheControl = "cache-control"
ContentType = "content-type" ContentType = "content-type"
Expires = "expires"
Location = "location" Location = "location"
Origin = "origin" Origin = "origin"
Pragma = "pragma"
UserAgent = "user-agent" UserAgent = "user-agent"
ForwardedFor = "x-forwarded-for" ForwardedFor = "x-forwarded-for"
ContentSecurityPolicy = "content-security-policy"
XXSSProtection = "x-xss-protection"
StrictTransportSecurity = "strict-transport-security"
XFrameOptions = "x-frame-options"
XContentTypeOptions = "x-content-type-options"
ReferrerPolicy = "referrer-policy"
FeaturePolicy = "feature-policy"
ZitadelOrgID = "x-zitadel-orgid" ZitadelOrgID = "x-zitadel-orgid"
//TODO: Remove as soon an authentification is implemented //TODO: Remove as soon an authentification is implemented
ZitadelUserID = "x-zitadel-userid" ZitadelUserID = "x-zitadel-userid"

View File

@ -0,0 +1,128 @@
package middleware
import (
"fmt"
"net/http"
"regexp"
"strings"
"time"
"github.com/caos/zitadel/internal/api"
"github.com/caos/zitadel/internal/config/types"
)
type Cache struct {
Cacheability Cacheability
NoCache bool
NoStore bool
MaxAge time.Duration
SharedMaxAge time.Duration
NoTransform bool
Revalidation Revalidation
}
type Cacheability string
const (
CacheabilityNotSet Cacheability = ""
CacheabilityPublic = "public"
CacheabilityPrivate = "private"
)
type Revalidation string
const (
RevalidationNotSet Revalidation = ""
RevalidationMust = "must-revalidate"
RevalidationProxy = "proxy-revalidate"
)
type CacheConfig struct {
MaxAge types.Duration
SharedMaxAge types.Duration
}
var (
NeverCacheOptions = &Cache{
NoStore: true,
}
AssetOptions = func(maxAge, SharedMaxAge time.Duration) *Cache {
return &Cache{
Cacheability: CacheabilityPublic,
MaxAge: maxAge,
SharedMaxAge: SharedMaxAge,
}
}
)
func DefaultCacheInterceptor(pattern string, maxAge, sharedMaxAge time.Duration) (func(http.Handler) http.Handler, error) {
regex, err := regexp.Compile(pattern)
if err != nil {
return nil, err
}
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if regex.MatchString(r.URL.Path) {
AssetsCacheInterceptor(maxAge, sharedMaxAge, handler).ServeHTTP(w, r)
return
}
NoCacheInterceptor(handler).ServeHTTP(w, r)
})
}, nil
}
func NoCacheInterceptor(h http.Handler) http.Handler {
return CacheInterceptorOpts(h, NeverCacheOptions)
}
func AssetsCacheInterceptor(maxAge, sharedMaxAge time.Duration, h http.Handler) http.Handler {
return CacheInterceptorOpts(h, AssetOptions(maxAge, sharedMaxAge))
}
func CacheInterceptorOpts(h http.Handler, cache *Cache) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
cache.serializeHeaders(w)
h.ServeHTTP(w, req)
})
}
func (c *Cache) serializeHeaders(w http.ResponseWriter) {
control := make([]string, 0, 6)
pragma := false
if c.Cacheability != CacheabilityNotSet {
control = append(control, string(c.Cacheability))
control = append(control, fmt.Sprintf("max-age=%v", c.MaxAge.Seconds()))
if c.SharedMaxAge != c.MaxAge {
control = append(control, fmt.Sprintf("s-maxage=%v", c.SharedMaxAge.Seconds()))
}
}
maxAge := c.MaxAge
if maxAge == 0 {
maxAge = -time.Hour
}
expires := time.Now().UTC().Add(maxAge).Format(http.TimeFormat)
if c.NoCache {
control = append(control, fmt.Sprintf("no-cache"))
pragma = true
}
if c.NoStore {
control = append(control, fmt.Sprintf("no-store"))
pragma = true
}
if c.NoTransform {
control = append(control, fmt.Sprintf("no-transform"))
}
if c.Revalidation != RevalidationNotSet {
control = append(control, string(c.Revalidation))
}
w.Header().Set(api.CacheControl, strings.Join(control, ", "))
w.Header().Set(api.Expires, expires)
if pragma {
w.Header().Set(api.Pragma, "no-cache")
}
}

View File

@ -0,0 +1,82 @@
package middleware
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestCache_serializeHeaders(t *testing.T) {
type fields struct {
Cacheability Cacheability
NoCache bool
NoStore bool
MaxAge time.Duration
SharedMaxAge time.Duration
NoTransform bool
Revalidation Revalidation
}
tests := []struct {
name string
fields fields
wantControl string
wantExpires string
wantPragma string
}{
{
"no-store",
fields{
NoStore: true,
},
"no-store",
time.Now().UTC().Add(-1 * time.Hour).Format(http.TimeFormat),
"no-cache",
},
{
"private and max-age",
fields{
Cacheability: CacheabilityPrivate,
MaxAge: 1 * time.Hour,
SharedMaxAge: 1 * time.Hour,
},
"private, max-age=3600",
time.Now().UTC().Add(1 * time.Hour).Format(http.TimeFormat),
"",
},
{
"public, no-cache, proxy-revalidate",
fields{
Cacheability: CacheabilityPublic,
NoCache: true,
Revalidation: RevalidationProxy,
},
"public, max-age=0, no-cache, proxy-revalidate",
time.Now().UTC().Add(-1 * time.Hour).Format(http.TimeFormat),
"no-cache",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
recorder := httptest.NewRecorder()
c := &Cache{
Cacheability: tt.fields.Cacheability,
NoCache: tt.fields.NoCache,
NoStore: tt.fields.NoStore,
MaxAge: tt.fields.MaxAge,
SharedMaxAge: tt.fields.SharedMaxAge,
NoTransform: tt.fields.NoTransform,
Revalidation: tt.fields.Revalidation,
}
c.serializeHeaders(recorder)
cc := recorder.Result().Header.Get("cache-control")
assert.Equal(t, tt.wantControl, cc)
exp := recorder.Result().Header.Get("expires")
assert.Equal(t, tt.wantExpires, exp)
pragma := recorder.Result().Header.Get("pragma")
assert.Equal(t, tt.wantPragma, pragma)
})
}
}

View File

@ -0,0 +1,125 @@
package middleware
import (
"fmt"
"strings"
)
type CSP struct {
DefaultSrc CSPSourceOptions
ScriptSrc CSPSourceOptions
ObjectSrc CSPSourceOptions
StyleSrc CSPSourceOptions
ImgSrc CSPSourceOptions
MediaSrc CSPSourceOptions
FrameSrc CSPSourceOptions
FontSrc CSPSourceOptions
ConnectSrc CSPSourceOptions
FormAction CSPSourceOptions
}
var (
DefaultSCP = CSP{
DefaultSrc: CSPSourceOptsNone(),
ScriptSrc: CSPSourceOptsSelf(),
ObjectSrc: CSPSourceOptsNone(),
StyleSrc: CSPSourceOptsSelf(),
ImgSrc: CSPSourceOptsSelf(),
MediaSrc: CSPSourceOptsNone(),
FrameSrc: CSPSourceOptsNone(),
FontSrc: CSPSourceOptsSelf(),
ConnectSrc: CSPSourceOptsSelf(),
}
)
func (csp *CSP) Value(nonce string) string {
valuesMap := csp.asMap()
values := make([]string, 0, len(valuesMap))
for k, v := range valuesMap {
if v == nil {
continue
}
values = append(values, fmt.Sprintf("%v %v", k, v.String(nonce)))
}
return strings.Join(values, ";")
}
func (csp *CSP) asMap() map[string]CSPSourceOptions {
return map[string]CSPSourceOptions{
"default-src": csp.DefaultSrc,
"script-src": csp.ScriptSrc,
"object-src": csp.ObjectSrc,
"style-src": csp.StyleSrc,
"img-src": csp.ImgSrc,
"media-src": csp.MediaSrc,
"frame-src": csp.FrameSrc,
"font-src": csp.FontSrc,
"connect-src": csp.ConnectSrc,
"form-action": csp.FormAction,
}
}
type CSPSourceOptions []string
func CSPSourceOpts() CSPSourceOptions {
return CSPSourceOptions{}
}
func CSPSourceOptsNone() CSPSourceOptions {
return []string{"'none'"}
}
func CSPSourceOptsSelf() CSPSourceOptions {
return []string{"'self'"}
}
func (srcOpts CSPSourceOptions) AddSelf() CSPSourceOptions {
return append(srcOpts, "'self'")
}
func (srcOpts CSPSourceOptions) AddInline() CSPSourceOptions {
return append(srcOpts, "'unsafe-inline'")
}
func (srcOpts CSPSourceOptions) AddEval() CSPSourceOptions {
return append(srcOpts, "'unsafe-eval'")
}
func (srcOpts CSPSourceOptions) AddStrictDynamic() CSPSourceOptions {
return append(srcOpts, "'strict-dynamic'")
}
func (srcOpts CSPSourceOptions) AddHost(h ...string) CSPSourceOptions {
return append(srcOpts, h...)
}
func (srcOpts CSPSourceOptions) AddScheme(s ...string) CSPSourceOptions {
return srcOpts.add(s, "%v:")
}
func (srcOpts CSPSourceOptions) AddNonce() CSPSourceOptions {
return append(srcOpts, "'nonce-%v'")
}
func (srcOpts CSPSourceOptions) AddHash(alg, b64v string) CSPSourceOptions {
return append(srcOpts, fmt.Sprintf("'%v-%v'", alg, b64v))
}
func (srcOpts CSPSourceOptions) String(nonce string) string {
value := strings.Join(srcOpts, " ")
if !strings.Contains(value, "%v") {
return value
}
return fmt.Sprintf(value, nonce)
}
func (srcOpts CSPSourceOptions) add(values []string, format string) CSPSourceOptions {
for i, v := range values {
values[i] = fmt.Sprintf(format, v)
}
return append(srcOpts, values...)
}

View File

@ -0,0 +1,90 @@
package middleware
import (
"context"
"crypto/rand"
"encoding/base64"
"net/http"
"github.com/caos/zitadel/internal/api"
)
type key int
const (
nonceKey key = 0
DefaultNonceLength = uint(32)
)
func SecurityHeaders(csp *CSP, errorHandler func(error) http.Handler, nonceLength ...uint) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
if csp == nil {
csp = &DefaultSCP
}
length := DefaultNonceLength
if len(nonceLength) > 0 {
length = nonceLength[0]
}
return &headers{
csp: csp,
handler: handler,
errorHandler: errorHandler,
nonceLength: length,
}
}
}
type headers struct {
csp *CSP
handler http.Handler
errorHandler func(err error) http.Handler
nonceLength uint
}
func (h *headers) ServeHTTP(w http.ResponseWriter, r *http.Request) {
nonce := GetNonce(r)
if nonce == "" {
var err error
nonce, err = generateNonce(h.nonceLength)
if err != nil {
h.errorHandler(err).ServeHTTP(w, r)
return
}
r = saveContext(r, nonceKey, nonce)
}
headers := w.Header()
headers.Set(api.ContentSecurityPolicy, h.csp.Value(nonce))
headers.Set(api.XXSSProtection, "1; mode=block")
headers.Set(api.StrictTransportSecurity, "max-age=31536000; includeSubDomains")
headers.Set(api.XFrameOptions, "DENY")
headers.Set(api.XContentTypeOptions, "nosniff")
headers.Set(api.ReferrerPolicy, "same-origin")
headers.Set(api.FeaturePolicy, "payment 'none'")
//PLANNED: add expect-ct
h.handler.ServeHTTP(w, r)
}
func GetNonce(r *http.Request) string {
nonce, _ := getContext(r, nonceKey).(string)
return nonce
}
func generateNonce(length uint) (string, error) {
b := make([]byte, length)
_, err := rand.Read(b)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(b), nil
}
func saveContext(r *http.Request, key, value interface{}) *http.Request {
ctx := context.WithValue(r.Context(), key, value)
return r.WithContext(ctx)
}
func getContext(r *http.Request, key interface{}) interface{} {
return r.Context().Value(key)
}

View File

@ -25,11 +25,11 @@ type UserAgentCookieConfig struct {
} }
func NewUserAgentHandler(config *UserAgentCookieConfig, idGenerator id.Generator) (*UserAgentHandler, error) { func NewUserAgentHandler(config *UserAgentCookieConfig, idGenerator id.Generator) (*UserAgentHandler, error) {
keys, _, err := crypto.LoadKeys(config.Key) key, err := crypto.LoadKey(config.Key, config.Key.EncryptionKeyID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
cookieKey := []byte(keys[config.Key.EncryptionKeyID]) cookieKey := []byte(key)
handler := NewCookieHandler( handler := NewCookieHandler(
WithEncryption(cookieKey, cookieKey), WithEncryption(cookieKey, cookieKey),
WithDomain(config.Domain), WithDomain(config.Domain),

View File

@ -13,7 +13,7 @@ type AuthRequestRepository interface {
AuthRequestByCode(ctx context.Context, code string) (*model.AuthRequest, error) AuthRequestByCode(ctx context.Context, code string) (*model.AuthRequest, error)
SaveAuthCode(ctx context.Context, id, code string) error SaveAuthCode(ctx context.Context, id, code string) error
DeleteAuthRequest(ctx context.Context, id string) error DeleteAuthRequest(ctx context.Context, id string) error
CheckUsername(ctx context.Context, id, username string) error CheckLoginName(ctx context.Context, id, loginName string) error
SelectUser(ctx context.Context, id, userID string) error SelectUser(ctx context.Context, id, userID string) error
VerifyPassword(ctx context.Context, id, userID, password string, info *model.BrowserInfo) error VerifyPassword(ctx context.Context, id, userID, password string, info *model.BrowserInfo) error
VerifyMfaOTP(ctx context.Context, agentID, authRequestID string, code string, info *model.BrowserInfo) error VerifyMfaOTP(ctx context.Context, agentID, authRequestID string, code string, info *model.BrowserInfo) error

View File

@ -106,16 +106,16 @@ func (repo *AuthRequestRepo) DeleteAuthRequest(ctx context.Context, id string) e
return repo.AuthRequests.DeleteAuthRequest(ctx, id) return repo.AuthRequests.DeleteAuthRequest(ctx, id)
} }
func (repo *AuthRequestRepo) CheckUsername(ctx context.Context, id, username string) error { func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName string) error {
request, err := repo.AuthRequests.GetAuthRequestByID(ctx, id) request, err := repo.AuthRequests.GetAuthRequestByID(ctx, id)
if err != nil { if err != nil {
return err return err
} }
user, err := repo.View.UserByLoginName(username) user, err := repo.View.UserByLoginName(loginName)
if err != nil { if err != nil {
return err return err
} }
request.SetUserInfo(user.ID, user.UserName, user.ResourceOwner) request.SetUserInfo(user.ID, loginName, user.ResourceOwner)
return repo.AuthRequests.UpdateAuthRequest(ctx, request) return repo.AuthRequests.UpdateAuthRequest(ctx, request)
} }
@ -128,7 +128,7 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID string)
if err != nil { if err != nil {
return err return err
} }
request.SetUserInfo(user.ID, user.UserName, user.ResourceOwner) request.SetUserInfo(user.ID, user.PreferredLoginName, user.ResourceOwner)
return repo.AuthRequests.UpdateAuthRequest(ctx, request) return repo.AuthRequests.UpdateAuthRequest(ctx, request)
} }
@ -236,7 +236,8 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *model.AuthRequest) (
for i, session := range userSessions { for i, session := range userSessions {
users[i] = model.UserSelection{ users[i] = model.UserSelection{
UserID: session.UserID, UserID: session.UserID,
UserName: session.UserName, DisplayName: session.DisplayName,
LoginName: session.LoginName,
UserSessionState: session.State, UserSessionState: session.State,
} }
} }

View File

@ -47,7 +47,7 @@ type mockViewUserSession struct {
type mockUser struct { type mockUser struct {
UserID string UserID string
UserName string LoginName string
} }
func (m *mockViewUserSession) UserSessionByIDs(string, string) (*view_model.UserSessionView, error) { func (m *mockViewUserSession) UserSessionByIDs(string, string) (*view_model.UserSessionView, error) {
@ -62,7 +62,7 @@ func (m *mockViewUserSession) UserSessionsByAgentID(string) ([]*view_model.UserS
for i, user := range m.Users { for i, user := range m.Users {
sessions[i] = &view_model.UserSessionView{ sessions[i] = &view_model.UserSessionView{
UserID: user.UserID, UserID: user.UserID,
UserName: user.UserName, LoginName: user.LoginName,
} }
} }
return sessions, nil return sessions, nil
@ -175,11 +175,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Users: []mockUser{ Users: []mockUser{
{ {
"id1", "id1",
"username1", "loginname1",
}, },
{ {
"id2", "id2",
"username2", "loginname2",
}, },
}, },
}, },
@ -192,11 +192,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Users: []model.UserSelection{ Users: []model.UserSelection{
{ {
UserID: "id1", UserID: "id1",
UserName: "username1", LoginName: "loginname1",
}, },
{ {
UserID: "id2", UserID: "id2",
UserName: "username2", LoginName: "loginname2",
}, },
}, },
}}, }},

View File

@ -203,8 +203,8 @@ func (repo *UserRepo) SkipMfaInit(ctx context.Context, userID string) error {
return repo.UserEvents.SkipMfaInit(ctx, userID) return repo.UserEvents.SkipMfaInit(ctx, userID)
} }
func (repo *UserRepo) RequestPasswordReset(ctx context.Context, username string) error { func (repo *UserRepo) RequestPasswordReset(ctx context.Context, loginname string) error {
user, err := repo.View.UserByUsername(username) user, err := repo.View.UserByLoginName(loginname)
if err != nil { if err != nil {
return err return err
} }

View File

@ -67,7 +67,8 @@ func (u *UserSession) Process(event *models.Event) (err error) {
} }
return u.updateSession(session, event) return u.updateSession(session, event)
case es_model.UserPasswordChanged, case es_model.UserPasswordChanged,
es_model.MfaOtpRemoved: es_model.MfaOtpRemoved,
es_model.UserProfileChanged:
sessions, err := u.view.UserSessionsByUserID(event.AggregateID) sessions, err := u.view.UserSessionsByUserID(event.AggregateID)
if err != nil { if err != nil {
return err return err
@ -91,11 +92,9 @@ func (u *UserSession) OnError(event *models.Event, err error) error {
func (u *UserSession) updateSession(session *view_model.UserSessionView, event *models.Event) error { func (u *UserSession) updateSession(session *view_model.UserSessionView, event *models.Event) error {
session.Sequence = event.Sequence session.Sequence = event.Sequence
session.AppendEvent(event) session.AppendEvent(event)
if session.UserName == "" {
if err := u.fillUserInfo(session, event.AggregateID); err != nil { if err := u.fillUserInfo(session, event.AggregateID); err != nil {
return err return err
} }
}
return u.view.PutUserSession(session) return u.view.PutUserSession(session)
} }
@ -105,5 +104,7 @@ func (u *UserSession) fillUserInfo(session *view_model.UserSessionView, id strin
return err return err
} }
session.UserName = user.UserName session.UserName = user.UserName
session.LoginName = user.PreferredLoginName
session.DisplayName = user.DisplayName
return nil return nil
} }

View File

@ -24,7 +24,7 @@ type AuthRequest struct {
levelOfAssurance LevelOfAssurance levelOfAssurance LevelOfAssurance
UserID string UserID string
UserName string LoginName string
UserOrgID string UserOrgID string
PossibleSteps []NextStep PossibleSteps []NextStep
PasswordVerified bool PasswordVerified bool
@ -96,8 +96,8 @@ func (a *AuthRequest) WithCurrentInfo(info *BrowserInfo) *AuthRequest {
return a return a
} }
func (a *AuthRequest) SetUserInfo(userID string, userName string, userOrgID string) { func (a *AuthRequest) SetUserInfo(userID string, loginName string, userOrgID string) {
a.UserID = userID a.UserID = userID
a.UserName = userName a.LoginName = loginName
a.UserOrgID = userOrgID a.UserOrgID = userOrgID
} }

View File

@ -43,7 +43,8 @@ func (s *SelectUserStep) Type() NextStepType {
type UserSelection struct { type UserSelection struct {
UserID string UserID string
UserName string DisplayName string
LoginName string
UserSessionState UserSessionState UserSessionState UserSessionState
} }

View File

@ -33,6 +33,14 @@ func ReadKeys(path string) (Keys, error) {
return *keys, err return *keys, err
} }
func LoadKey(config *KeyConfig, id string) (string, error) {
keys, _, err := LoadKeys(config)
if err != nil {
return "", err
}
return keys[id], nil
}
func LoadKeys(config *KeyConfig) (map[string]string, []string, error) { func LoadKeys(config *KeyConfig) (map[string]string, []string, error) {
if config == nil { if config == nil {
return nil, nil, errors.ThrowInvalidArgument(nil, "CRYPT-dJK8s", "config must not be nil") return nil, nil, errors.ThrowInvalidArgument(nil, "CRYPT-dJK8s", "config must not be nil")

View File

@ -37,7 +37,7 @@ func (l *Login) renderChangePassword(w http.ResponseWriter, r *http.Request, aut
} }
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Change Password", errType, errMessage), baseData: l.getBaseData(r, authReq, "Change Password", errType, errMessage),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplChangePassword], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplChangePassword], data, nil)
} }
@ -46,7 +46,7 @@ func (l *Login) renderChangePasswordDone(w http.ResponseWriter, r *http.Request,
var errType, errMessage string var errType, errMessage string
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Password Change Done", errType, errMessage), baseData: l.getBaseData(r, authReq, "Password Change Done", errType, errMessage),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplChangePasswordDone], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplChangePasswordDone], data, nil)
} }

View File

@ -72,7 +72,7 @@ func (l *Login) resendPasswordSet(w http.ResponseWriter, r *http.Request, authRe
if authReq != nil { if authReq != nil {
userOrg = authReq.UserOrgID userOrg = authReq.UserOrgID
} }
err := l.authRepo.RequestPasswordReset(setContext(r.Context(), userOrg), authReq.UserName) err := l.authRepo.RequestPasswordReset(setContext(r.Context(), userOrg), authReq.LoginName)
l.renderInitPassword(w, r, authReq, authReq.UserID, "", err) l.renderInitPassword(w, r, authReq, authReq.UserID, "", err)
} }
@ -95,7 +95,7 @@ func (l *Login) renderInitPassword(w http.ResponseWriter, r *http.Request, authR
func (l *Login) renderInitPasswordDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest) { func (l *Login) renderInitPasswordDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest) {
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Password Init Done", "", ""), baseData: l.getBaseData(r, authReq, "Password Init Done", "", ""),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplInitPasswordDone], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplInitPasswordDone], data, nil)
} }

View File

@ -93,13 +93,13 @@ func (l *Login) renderInitUser(w http.ResponseWriter, r *http.Request, authReq *
} }
func (l *Login) renderInitUserDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest) { func (l *Login) renderInitUserDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest) {
var userName string var loginName string
if authReq != nil { if authReq != nil {
userName = authReq.UserName loginName = authReq.LoginName
} }
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "User Init Done", "", ""), baseData: l.getBaseData(r, authReq, "User Init Done", "", ""),
UserName: userName, LoginName: loginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplInitUserDone], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplInitUserDone], data, nil)
} }

View File

@ -6,12 +6,14 @@ import (
"net/http" "net/http"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/gorilla/mux" "github.com/gorilla/csrf"
"github.com/rakyll/statik/fs" "github.com/rakyll/statik/fs"
"golang.org/x/text/language" "golang.org/x/text/language"
"github.com/caos/zitadel/internal/api/auth" "github.com/caos/zitadel/internal/api/auth"
"github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing" "github.com/caos/zitadel/internal/auth/repository/eventsourcing"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/form" "github.com/caos/zitadel/internal/form"
_ "github.com/caos/zitadel/internal/login/statik" _ "github.com/caos/zitadel/internal/login/statik"
@ -19,7 +21,7 @@ import (
type Login struct { type Login struct {
endpoint string endpoint string
router *mux.Router router http.Handler
renderer *Renderer renderer *Renderer
parser *form.Parser parser *form.Parser
authRepo *eventsourcing.EsRepository authRepo *eventsourcing.EsRepository
@ -33,6 +35,14 @@ type Config struct {
ZitadelURL string ZitadelURL string
LanguageCookieName string LanguageCookieName string
DefaultLanguage language.Tag DefaultLanguage language.Tag
CSRF CSRF
Cache middleware.CacheConfig
}
type CSRF struct {
CookieName string
Key *crypto.KeyConfig
Development bool
} }
const ( const (
@ -47,14 +57,39 @@ func StartLogin(ctx context.Context, config Config, authRepo *eventsourcing.EsRe
authRepo: authRepo, authRepo: authRepo,
} }
statikFS, err := fs.NewWithNamespace("login") statikFS, err := fs.NewWithNamespace("login")
logging.Log("CONFI-7usEW").OnError(err).Panic("unable to start listener") logging.Log("CONFI-Ga21f").OnError(err).Panic("unable to create filesystem")
login.router = CreateRouter(login, statikFS) csrf, err := csrfInterceptor(config.CSRF, login.csrfErrorHandler())
logging.Log("CONFI-dHR2a").OnError(err).Panic("unable to create csrfInterceptor")
cache, err := middleware.DefaultCacheInterceptor(EndpointResources, config.Cache.MaxAge.Duration, config.Cache.SharedMaxAge.Duration)
logging.Log("CONFI-BHq2a").OnError(err).Panic("unable to create cacheInterceptor")
security := middleware.SecurityHeaders(csp(), login.cspErrorHandler)
login.router = CreateRouter(login, statikFS, csrf, cache, security)
login.renderer = CreateRenderer(statikFS, config.LanguageCookieName, config.DefaultLanguage) login.renderer = CreateRenderer(statikFS, config.LanguageCookieName, config.DefaultLanguage)
login.parser = form.NewParser() login.parser = form.NewParser()
login.Listen(ctx) login.Listen(ctx)
} }
func csp() *middleware.CSP {
csp := middleware.DefaultSCP
csp.ObjectSrc = middleware.CSPSourceOptsSelf()
csp.StyleSrc = csp.StyleSrc.AddNonce()
csp.ScriptSrc = csp.ScriptSrc.AddNonce()
return &csp
}
func csrfInterceptor(config CSRF, errorHandler http.Handler) (func(http.Handler) http.Handler, error) {
csrfKey, err := crypto.LoadKey(config.Key, config.Key.EncryptionKeyID)
if err != nil {
return nil, err
}
return csrf.Protect([]byte(csrfKey),
csrf.Secure(!config.Development),
csrf.CookieName(config.CookieName),
csrf.ErrorHandler(errorHandler),
), nil
}
func (l *Login) Listen(ctx context.Context) { func (l *Login) Listen(ctx context.Context) {
if l.endpoint == "" { if l.endpoint == "" {
l.endpoint = ":80" l.endpoint = ":80"

View File

@ -10,7 +10,7 @@ const (
) )
type loginData struct { type loginData struct {
UserName string `schema:"username"` LoginName string `schema:"loginName"`
} }
func (l *Login) handleLogin(w http.ResponseWriter, r *http.Request) { func (l *Login) handleLogin(w http.ResponseWriter, r *http.Request) {
@ -26,7 +26,7 @@ func (l *Login) handleLogin(w http.ResponseWriter, r *http.Request) {
l.renderNextStep(w, r, authReq) l.renderNextStep(w, r, authReq)
} }
func (l *Login) handleUsername(w http.ResponseWriter, r *http.Request) { func (l *Login) handleLoginName(w http.ResponseWriter, r *http.Request) {
authSession, err := l.getAuthRequest(r) authSession, err := l.getAuthRequest(r)
if err != nil { if err != nil {
l.renderError(w, r, authSession, err) l.renderError(w, r, authSession, err)
@ -35,14 +35,14 @@ func (l *Login) handleUsername(w http.ResponseWriter, r *http.Request) {
l.renderLogin(w, r, authSession, nil) l.renderLogin(w, r, authSession, nil)
} }
func (l *Login) handleUsernameCheck(w http.ResponseWriter, r *http.Request) { func (l *Login) handleLoginNameCheck(w http.ResponseWriter, r *http.Request) {
data := new(loginData) data := new(loginData)
authReq, err := l.getAuthRequestAndParseData(r, data) authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil { if err != nil {
l.renderError(w, r, authReq, err) l.renderError(w, r, authReq, err)
return return
} }
err = l.authRepo.CheckUsername(r.Context(), authReq.ID, data.UserName) err = l.authRepo.CheckLoginName(r.Context(), authReq.ID, data.LoginName)
if err != nil { if err != nil {
l.renderLogin(w, r, authReq, err) l.renderLogin(w, r, authReq, err)
return return
@ -57,7 +57,7 @@ func (l *Login) renderLogin(w http.ResponseWriter, r *http.Request, authReq *mod
} }
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Login", errType, errMessage), baseData: l.getBaseData(r, authReq, "Login", errType, errMessage),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplLogin], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplLogin], data, nil)
} }

View File

@ -15,6 +15,6 @@ type mfaInitDoneData struct {
func (l *Login) renderMfaInitDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, data *mfaDoneData) { func (l *Login) renderMfaInitDone(w http.ResponseWriter, r *http.Request, authReq *model.AuthRequest, data *mfaDoneData) {
var errType, errMessage string var errType, errMessage string
data.baseData = l.getBaseData(r, authReq, "Mfa Init Done", errType, errMessage) data.baseData = l.getBaseData(r, authReq, "Mfa Init Done", errType, errMessage)
data.UserName = authReq.UserName data.LoginName = authReq.LoginName
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplMfaInitDone], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplMfaInitDone], data, nil)
} }

View File

@ -4,10 +4,11 @@ import (
"bytes" "bytes"
"net/http" "net/http"
"github.com/aaronarduino/goqrsvg"
svg "github.com/ajstarks/svgo" svg "github.com/ajstarks/svgo"
"github.com/boombuler/barcode/qr" "github.com/boombuler/barcode/qr"
"github.com/caos/zitadel/internal/auth_request/model" "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/qrcode"
) )
const ( const (
@ -67,7 +68,7 @@ func (l *Login) renderMfaInitVerify(w http.ResponseWriter, r *http.Request, auth
errMessage = l.getErrorMessage(r, err) errMessage = l.getErrorMessage(r, err)
} }
data.baseData = l.getBaseData(r, authReq, "Mfa Init Verify", errType, errMessage) data.baseData = l.getBaseData(r, authReq, "Mfa Init Verify", errType, errMessage)
data.UserName = authReq.UserName data.LoginName = authReq.LoginName
if data.MfaType == model.MfaTypeOTP { if data.MfaType == model.MfaTypeOTP {
code, err := generateQrCode(data.otpData.Url) code, err := generateQrCode(data.otpData.Url)
if err == nil { if err == nil {
@ -86,7 +87,7 @@ func generateQrCode(url string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
qs := goqrsvg.NewQrSVG(qrCode, 5) qs := qrcode.NewQrSVG(qrCode, 5)
qs.StartQrSVG(s) qs.StartQrSVG(s)
qs.WriteQrSVG(s) qs.WriteQrSVG(s)

View File

@ -43,7 +43,7 @@ func (l *Login) renderMfaPrompt(w http.ResponseWriter, r *http.Request, authSess
} }
data := mfaData{ data := mfaData{
baseData: l.getBaseData(r, authSession, "Mfa Prompt", errType, errMessage), baseData: l.getBaseData(r, authSession, "Mfa Prompt", errType, errMessage),
UserName: authSession.UserName, LoginName: authSession.LoginName,
} }
if mfaPromptData == nil { if mfaPromptData == nil {

View File

@ -39,7 +39,7 @@ func (l *Login) renderMfaVerify(w http.ResponseWriter, r *http.Request, authReq
} }
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Mfa Verify", errType, errMessage), baseData: l.getBaseData(r, authReq, "Mfa Verify", errType, errMessage),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
if verificationStep != nil { if verificationStep != nil {
data.MfaProviders = verificationStep.MfaProviders data.MfaProviders = verificationStep.MfaProviders

View File

@ -21,7 +21,7 @@ func (l *Login) renderPassword(w http.ResponseWriter, r *http.Request, authReq *
} }
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Password", errType, errMessage), baseData: l.getBaseData(r, authReq, "Password", errType, errMessage),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplPassword], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplPassword], data, nil)
} }

View File

@ -15,7 +15,7 @@ func (l *Login) handlePasswordReset(w http.ResponseWriter, r *http.Request) {
l.renderError(w, r, authReq, err) l.renderError(w, r, authReq, err)
return return
} }
err = l.authRepo.RequestPasswordReset(setContext(r.Context(), authReq.UserOrgID), authReq.UserName) err = l.authRepo.RequestPasswordReset(setContext(r.Context(), authReq.UserOrgID), authReq.LoginName)
l.renderPasswordResetDone(w, r, authReq, err) l.renderPasswordResetDone(w, r, authReq, err)
} }
@ -26,7 +26,7 @@ func (l *Login) renderPasswordResetDone(w http.ResponseWriter, r *http.Request,
} }
data := userData{ data := userData{
baseData: l.getBaseData(r, authReq, "Password Reset Done", errType, errMessage), baseData: l.getBaseData(r, authReq, "Password Reset Done", errType, errMessage),
UserName: authReq.UserName, LoginName: authReq.LoginName,
} }
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplPasswordResetDone], data, nil) l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplPasswordResetDone], data, nil)
} }

View File

@ -71,7 +71,7 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, l.zitadelURL, http.StatusFound) http.Redirect(w, r, l.zitadelURL, http.StatusFound)
return return
} }
authRequest.UserName = user.UserName authRequest.LoginName = user.PreferredLoginName
l.renderNextStep(w, r, authRequest) l.renderNextStep(w, r, authRequest)
} }

View File

@ -3,6 +3,11 @@ package handler
import ( import (
"errors" "errors"
"fmt" "fmt"
"html/template"
"github.com/gorilla/csrf"
"github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/auth_request/model" "github.com/caos/zitadel/internal/auth_request/model"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/i18n" "github.com/caos/zitadel/internal/i18n"
@ -58,11 +63,11 @@ func CreateRenderer(staticDir http.FileSystem, cookieName string, defaultLanguag
"registerUrl": func(id string) string { "registerUrl": func(id string) string {
return fmt.Sprintf("%s?%s=%s", EndpointRegister, queryAuthRequestID, id) return fmt.Sprintf("%s?%s=%s", EndpointRegister, queryAuthRequestID, id)
}, },
"usernameUrl": func() string { "loginNameUrl": func() string {
return EndpointUsername return EndpointLoginName
}, },
"usernameChangeUrl": func(id string) string { "loginNameChangeUrl": func(id string) string {
return fmt.Sprintf("%s?%s=%s", EndpointUsername, queryAuthRequestID, id) return fmt.Sprintf("%s?%s=%s", EndpointLoginName, queryAuthRequestID, id)
}, },
"userSelectionUrl": func() string { "userSelectionUrl": func() string {
return EndpointUserSelection return EndpointUserSelection
@ -189,6 +194,8 @@ func (l *Login) getBaseData(r *http.Request, authReq *model.AuthRequest, title s
Theme: l.getTheme(r), Theme: l.getTheme(r),
ThemeMode: l.getThemeMode(r), ThemeMode: l.getThemeMode(r),
AuthReqID: getRequestID(authReq, r), AuthReqID: getRequestID(authReq, r),
CSRF: csrf.TemplateField(r),
Nonce: middleware.GetNonce(r),
} }
} }
@ -217,6 +224,19 @@ func getRequestID(authReq *model.AuthRequest, r *http.Request) string {
return r.FormValue(queryAuthRequestID) return r.FormValue(queryAuthRequestID)
} }
func (l *Login) csrfErrorHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := csrf.FailureReason(r)
l.renderInternalError(w, r, nil, err)
})
}
func (l *Login) cspErrorHandler(err error) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
l.renderInternalError(w, r, nil, err)
})
}
type baseData struct { type baseData struct {
errorData errorData
Lang string Lang string
@ -224,6 +244,8 @@ type baseData struct {
Theme string Theme string
ThemeMode string ThemeMode string
AuthReqID string AuthReqID string
CSRF template.HTML
Nonce string
} }
type errorData struct { type errorData struct {
@ -233,7 +255,7 @@ type errorData struct {
type userData struct { type userData struct {
baseData baseData
UserName string LoginName string
PasswordChecked string PasswordChecked string
MfaProviders []model.MfaType MfaProviders []model.MfaType
SelectedMfaProvider model.MfaType SelectedMfaProvider model.MfaType
@ -246,21 +268,21 @@ type userSelectionData struct {
type mfaData struct { type mfaData struct {
baseData baseData
UserName string LoginName string
MfaProviders []model.MfaType MfaProviders []model.MfaType
MfaRequired bool MfaRequired bool
} }
type mfaVerifyData struct { type mfaVerifyData struct {
baseData baseData
UserName string LoginName string
MfaType model.MfaType MfaType model.MfaType
otpData otpData
} }
type mfaDoneData struct { type mfaDoneData struct {
baseData baseData
UserName string LoginName string
MfaType model.MfaType MfaType model.MfaType
} }

View File

@ -11,7 +11,7 @@ const (
EndpointHealthz = "/healthz" EndpointHealthz = "/healthz"
EndpointReadiness = "/ready" EndpointReadiness = "/ready"
EndpointLogin = "/login" EndpointLogin = "/login"
EndpointUsername = "/username" EndpointLoginName = "/loginname"
EndpointUserSelection = "/userselection" EndpointUserSelection = "/userselection"
EndpointPassword = "/password" EndpointPassword = "/password"
EndpointInitPassword = "/password/init" EndpointInitPassword = "/password/init"
@ -29,14 +29,15 @@ const (
EndpointResources = "/resources" EndpointResources = "/resources"
) )
func CreateRouter(login *Login, staticDir http.FileSystem) *mux.Router { func CreateRouter(login *Login, staticDir http.FileSystem, interceptors ...mux.MiddlewareFunc) *mux.Router {
router := mux.NewRouter() router := mux.NewRouter()
router.Use(interceptors...)
router.HandleFunc(EndpointRoot, login.handleLogin).Methods(http.MethodGet) router.HandleFunc(EndpointRoot, login.handleLogin).Methods(http.MethodGet)
router.HandleFunc(EndpointHealthz, login.handleHealthz).Methods(http.MethodGet) router.HandleFunc(EndpointHealthz, login.handleHealthz).Methods(http.MethodGet)
router.HandleFunc(EndpointReadiness, login.handleReadiness).Methods(http.MethodGet) router.HandleFunc(EndpointReadiness, login.handleReadiness).Methods(http.MethodGet)
router.HandleFunc(EndpointLogin, login.handleLogin).Methods(http.MethodGet, http.MethodPost) router.HandleFunc(EndpointLogin, login.handleLogin).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc(EndpointUsername, login.handleUsername).Methods(http.MethodGet) router.HandleFunc(EndpointLoginName, login.handleLoginName).Methods(http.MethodGet)
router.HandleFunc(EndpointUsername, login.handleUsernameCheck).Methods(http.MethodPost) router.HandleFunc(EndpointLoginName, login.handleLoginNameCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointUserSelection, login.handleSelectUser).Methods(http.MethodPost) router.HandleFunc(EndpointUserSelection, login.handleSelectUser).Methods(http.MethodPost)
router.HandleFunc(EndpointPassword, login.handlePasswordCheck).Methods(http.MethodPost) router.HandleFunc(EndpointPassword, login.handlePasswordCheck).Methods(http.MethodPost)
router.HandleFunc(EndpointInitPassword, login.handleInitPassword).Methods(http.MethodGet) router.HandleFunc(EndpointInitPassword, login.handleInitPassword).Methods(http.MethodGet)

View File

@ -6,7 +6,6 @@ Password:
Login: Login:
Title: Anmeldung Title: Anmeldung
Description: Gib deine Benutzerdaten ein. Description: Gib deine Benutzerdaten ein.
Username: Benutzername
Loginname: Loginname Loginname: Loginname
LoginnamePlaceHolder: username@domain LoginnamePlaceHolder: username@domain

View File

@ -1,7 +1,6 @@
Login: Login:
Title: Login Title: Login
Description: Enter your logindata. Description: Enter your logindata.
Username: Username
Loginname: Loginname Loginname: Loginname
LoginnamePlaceHolder: username@domain LoginnamePlaceHolder: username@domain
@ -91,7 +90,7 @@ EmailVerificationDone:
Registration: Registration:
Title: Registration Title: Registration
Description: Enter your Userdata. Your email address will be used as username. Description: Enter your Userdata. Your email address will be used as loginname.
Email: E-Mail Email: E-Mail
Firstname: Firstname Firstname: Firstname
Lastname: Lastname Lastname: Lastname

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,6 @@
const copyToClipboard = str => {
navigator.clipboard.writeText(str);
}
let copyButton = document.getElementsByClassName("copy")[0];
copyButton.addEventListener("click", copyToClipboard(copyButton.getAttribute("data-copy").value));

View File

@ -95,7 +95,7 @@ h1 {
} }
p { p {
font-width: 300; font-weight: 300;
} }
header { header {
@ -151,9 +151,6 @@ button.primary {
button.primary:hover { button.primary:hover {
background-color: #f60075; background-color: #f60075;
} }
button > .sessionstate {
text-transform: lowercase;
}
input:not([type=radio]), select { input:not([type=radio]), select {
background-color: #252525; background-color: #252525;
@ -200,6 +197,102 @@ form .actions .right {
form .actions button, form .actions a { form .actions button, form .actions a {
margin: 10px 0; margin: 10px 0;
} }
form button.clean {
border: none;
height: auto;
color: white;
text-align: left;
text-transform: unset;
display: flex;
padding: 15px;
}
form button.clean:hover {
border: none;
background-color: #252525;
}
form button.clean * {
font-weight: 300;
}
form .user-selection-list {
margin-bottom: 80px;
}
form button.user-selection .profile-image {
width: 100px;
height: 100px;
background-image: url("/resources/images/icon-user-dark.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) {
form button.user-selection .profile-image {
background-image: url("/resources/images/icon-user-dark@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-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) {
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-hover@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection .sessionstate {
display: inline-block;
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #595959;
border-style: solid;
border-width: 1px;
position: absolute;
bottom: 0px;
right: 10px;
}
form button.user-selection .sessionstate.sessionstate-0 {
background-color: #138D00;
}
form button.user-selection .sessionstate.sessionstate-1 {
background-color: #BC372E;
}
form button.user-selection > div {
position: relative;
}
form button.user-selection > div.names {
margin: 15px;
}
form button.user-selection > div.names .displayname {
font-size: 1.4rem;
}
form button.user-selection > div.names .loginname {
color: #898989;
}
.user-selection + form button.other-user {
margin-top: 80px;
}
form button.other-user .other-user-image {
width: 100px;
height: 75px;
background-image: url("/resources/images/icon-newuser-dark.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) {
form button.other-user .other-user-image {
background-image: url("/resources/images/icon-newuser-dark@2x.png");
background-size: 100px 75px;
}
}
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-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) {
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-hover@2x.png");
background-size: 100px 75px;
}
}
form button.other-user > div:nth-of-type(2) {
margin: 15px;
font-size: 1.4rem;
}
#copy-secret { #copy-secret {
visibility: hidden; visibility: hidden;
@ -209,11 +302,11 @@ form .actions button, form .actions a {
#qrcode { #qrcode {
text-align: center; text-align: center;
} }
#qrcode svg rect[style*="fill:white"] { #qrcode svg rect.color {
fill: #282828 !important; fill: white;
} }
#qrcode svg rect[style*="fill:black"] { #qrcode svg rect.bg-color {
fill: white !important; fill: #282828;
} }
#secret .copy { #secret .copy {

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,aCGW;EDFX;EACA;;;AAGJ;EACI;;;AAGJ;EACI,kBCDc;EDEd,OCDQ;;;ADIZ;EACI,OCLQ;EDMR,aCZS;EDaT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCnCW;EDoCX;EACA;EACA;;AAEA;EACI,OCxCY;;;AD4CpB;EACI;EACA,kBCjDc;EDkDd,OChDW;EDiDX;EACA;EACA;EACA;EACA,QE/DU;EFgEV;EACA;EACA;;AACA;EACI,kBCzDY;ED0DZ;;AAGJ;EACI,kBC/DO;EDgEP,OCjEI;EDkEJ;;AACA;EACI,kBClEQ;;ADsEhB;EACI;;;AAIR;EACI,kBE7EmB;EF8EnB,OC/EQ;EDgFR,QEzFU;EF0FV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OE9GK;EF+GL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKJ;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;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,aCGW;EDFX;EACA;;;AAGJ;EACI;;;AAGJ;EACI,kBCDc;EDEd,OCDQ;;;ADIZ;EACI,OCLQ;EDMR,aCZS;EDaT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCnCW;EDoCX;EACA;EACA;;AAEA;EACI,OCxCY;;;AD4CpB;EACI;EACA,kBCjDc;EDkDd,OChDW;EDiDX;EACA;EACA;EACA;EACA,QE/DU;EFgEV;EACA;EACA;;AACA;EACI,kBCzDY;ED0DZ;;AAGJ;EACI,kBC/DO;EDgEP,OCjEI;EDkEJ;;AACA;EACI,kBClEQ;;;ADuEpB;EACI,kBE5DmB;EF6DnB,OC3EQ;ED4ER,QErFU;EFsFV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OE7FK;EF8FL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OCnII;EDoIJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBE7HW;;AFgIf;EACI;;AAIR;EACI;;AAIA;EACI;EACA;EE1JV;;AACA;EFuJM;IEtJJ;IACA;;;AF4JQ;EE/JV;;AACA;EF8JU;IE7JR;IACA;;;AFiKI;EACI;EACA;EACA;EACA;EACA,cE5JO;EF6JP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OExLP;;AF+LL;EACI;;AAEJ;EACI;EACA;EEhNV;;AACA;EF6MM;IE5MJ;IACA;;;AFkNQ;EErNV;;AACA;EFoNU;IEnNR;IACA;;;AFuNI;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MC1OI;;AD6OR;EACI,MC/OU;;;ADoPd;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA","file":"dark.css"}

View File

@ -95,7 +95,7 @@ h1 {
} }
p { p {
font-width: 300; font-weight: 300;
} }
header { header {
@ -151,9 +151,6 @@ button.primary {
button.primary:hover { button.primary:hover {
background-color: #f60075; background-color: #f60075;
} }
button > .sessionstate {
text-transform: lowercase;
}
input:not([type=radio]), select { input:not([type=radio]), select {
background-color: #252525; background-color: #252525;
@ -200,6 +197,102 @@ form .actions .right {
form .actions button, form .actions a { form .actions button, form .actions a {
margin: 10px 0; margin: 10px 0;
} }
form button.clean {
border: none;
height: auto;
color: white;
text-align: left;
text-transform: unset;
display: flex;
padding: 15px;
}
form button.clean:hover {
border: none;
background-color: #252525;
}
form button.clean * {
font-weight: 300;
}
form .user-selection-list {
margin-bottom: 80px;
}
form button.user-selection .profile-image {
width: 100px;
height: 100px;
background-image: url("/resources/images/icon-user-dark.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) {
form button.user-selection .profile-image {
background-image: url("/resources/images/icon-user-dark@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-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) {
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-hover@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection .sessionstate {
display: inline-block;
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #595959;
border-style: solid;
border-width: 1px;
position: absolute;
bottom: 0px;
right: 10px;
}
form button.user-selection .sessionstate.sessionstate-0 {
background-color: #138D00;
}
form button.user-selection .sessionstate.sessionstate-1 {
background-color: #BC372E;
}
form button.user-selection > div {
position: relative;
}
form button.user-selection > div.names {
margin: 15px;
}
form button.user-selection > div.names .displayname {
font-size: 1.4rem;
}
form button.user-selection > div.names .loginname {
color: #898989;
}
.user-selection + form button.other-user {
margin-top: 80px;
}
form button.other-user .other-user-image {
width: 100px;
height: 75px;
background-image: url("/resources/images/icon-newuser-dark.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) {
form button.other-user .other-user-image {
background-image: url("/resources/images/icon-newuser-dark@2x.png");
background-size: 100px 75px;
}
}
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-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) {
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-hover@2x.png");
background-size: 100px 75px;
}
}
form button.other-user > div:nth-of-type(2) {
margin: 15px;
font-size: 1.4rem;
}
#copy-secret { #copy-secret {
visibility: hidden; visibility: hidden;
@ -209,11 +302,11 @@ form .actions button, form .actions a {
#qrcode { #qrcode {
text-align: center; text-align: center;
} }
#qrcode svg rect[style*="fill:white"] { #qrcode svg rect.color {
fill: #282828 !important; fill: white;
} }
#qrcode svg rect[style*="fill:black"] { #qrcode svg rect.bg-color {
fill: white !important; fill: #282828;
} }
#secret .copy { #secret .copy {
@ -282,6 +375,48 @@ html button.primary {
html button.primary:hover { html button.primary:hover {
background-color: #f60075; background-color: #f60075;
} }
html button.clean {
color: #282828;
}
html button.user-selection .profile-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-user-light@2x.png");
background-size: 100px 100px;
}
}
html button.user-selection:hover {
background-color: #252525;
}
html button.user-selection:hover .profile-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-user-light-hover@2x.png");
background-size: 100px 100px;
}
}
html button.other-user .other-user-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-newuser-light@2x.png");
background-size: 100px 75px;
}
}
html button.other-user:hover .other-user-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-newuser-light-hover@2x.png");
background-size: 100px 75px;
}
}
html input { html input {
background-color: white; background-color: white;
color: #282828; color: #282828;

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,aCGW;EDFX;EACA;;;AAGJ;EACI;;;AAGJ;EACI,kBCDc;EDEd,OCDQ;;;ADIZ;EACI,OCLQ;EDMR,aCZS;EDaT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCnCW;EDoCX;EACA;EACA;;AAEA;EACI,OCxCY;;;AD4CpB;EACI;EACA,kBCjDc;EDkDd,OChDW;EDiDX;EACA;EACA;EACA;EACA,QE/DU;EFgEV;EACA;EACA;;AACA;EACI,kBCzDY;ED0DZ;;AAGJ;EACI,kBC/DO;EDgEP,OCjEI;EDkEJ;;AACA;EACI,kBClEQ;;ADsEhB;EACI;;;AAIR;EACI,kBE7EmB;EF8EnB,OC/EQ;EDgFR,QEzFU;EF0FV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OE9GK;EF+GL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKJ;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AG1MJ;EACI,kBFYQ;EEXR,OFUc;;AERd;EACI;;AAGJ;EACI,OFGU;;AEAd;EACI;EACA;EACA;;AAEA;EACI,kBFIa;EEHb;;AAGJ;EACI,kBFTG;EEUH,OFXA;EEYA;EACA;;AACA;EACI,kBFbI;;AEkBhB;EACI,kBFrBI;EEsBJ,OFvBU;;AE2BV;EACI;;AAGJ;EACI;;AAIR;EACI","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":"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,aCGW;EDFX;EACA;;;AAGJ;EACI;;;AAGJ;EACI,kBCDc;EDEd,OCDQ;;;ADIZ;EACI,OCLQ;EDMR,aCZS;EDaT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCnCW;EDoCX;EACA;EACA;;AAEA;EACI,OCxCY;;;AD4CpB;EACI;EACA,kBCjDc;EDkDd,OChDW;EDiDX;EACA;EACA;EACA;EACA,QE/DU;EFgEV;EACA;EACA;;AACA;EACI,kBCzDY;ED0DZ;;AAGJ;EACI,kBC/DO;EDgEP,OCjEI;EDkEJ;;AACA;EACI,kBClEQ;;;ADuEpB;EACI,kBE5DmB;EF6DnB,OC3EQ;ED4ER,QErFU;EFsFV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OE7FK;EF8FL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OCnII;EDoIJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBE7HW;;AFgIf;EACI;;AAIR;EACI;;AAIA;EACI;EACA;EE1JV;;AACA;EFuJM;IEtJJ;IACA;;;AF4JQ;EE/JV;;AACA;EF8JU;IE7JR;IACA;;;AFiKI;EACI;EACA;EACA;EACA;EACA,cE5JO;EF6JP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OExLP;;AF+LL;EACI;;AAEJ;EACI;EACA;EEhNV;;AACA;EF6MM;IE5MJ;IACA;;;AFkNQ;EErNV;;AACA;EFoNU;IEnNR;IACA;;;AFuNI;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MC1OI;;AD6OR;EACI,MC/OU;;;ADoPd;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AGtSJ;EACI,kBFYQ;EEXR,OFUc;;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;;AEyBN;EDxBV;;AACA;ECuBU;IDtBR;IACA;;;ACyBQ;EACI,kBDfO;;ACiBP;ED/Bd;;AACA;EC8Bc;ID7BZ;IACA;;;ACmCQ;EDtCV;;AACA;ECqCU;IDpCR;IACA;;;ACwCY;ED3Cd;;AACA;EC0Cc;IDzCZ;IACA;;;AC+CA;EACI,kBFnDI;EEoDJ,OFrDU;;AEyDV;EACI;;AAGJ;EACI;;AAIR;EACI","file":"light.css"}

View File

@ -30,6 +30,36 @@ html {
background-color: $primaryColorHover; background-color: $primaryColorHover;
} }
} }
&.clean {
color: $fontColorLight;
}
&.user-selection {
.profile-image {
@include retina-background-image($profileImgLight, "png", false, 100px, 100px);
}
&:hover {
background-color: $buttonBackgroundColorHover;
.profile-image {
@include retina-background-image($profileImgLight, "png", true, 100px, 100px);
}
}
}
&.other-user {
.other-user-image {
@include retina-background-image($otherUserImgLight, "png", false, 100px, 75px);
}
&:hover {
.other-user-image {
@include retina-background-image($otherUserImgLight, "png", true, 100px, 75px);
}
}
}
} }
input { input {

View File

@ -25,7 +25,7 @@ h1 {
} }
p { p {
font-width: 300; font-weight: 300;
} }
header { header {
@ -83,10 +83,6 @@ button {
background-color: $primaryColorHover; background-color: $primaryColorHover;
} }
} }
& > .sessionstate {
text-transform: lowercase;
}
} }
input:not([type='radio']), select { input:not([type='radio']), select {
@ -143,6 +139,102 @@ form {
margin: 10px 0; margin: 10px 0;
} }
} }
button.clean {
border: none;
height: auto;
color: $fontColor;
text-align: left;
text-transform: unset;
display: flex;
padding: 15px;
&:hover {
border: none;
background-color: $buttonBackgroundColorHover;
}
* {
font-weight: 300;
}
}
.user-selection-list {
margin-bottom: 80px;
}
button.user-selection {
.profile-image {
width: 100px;
height: 100px;
@include retina-background-image($profileImgDark, "png", false, 100px, 100px);
}
&:hover {
.profile-image {
@include retina-background-image($profileImgDark, "png", true, 100px, 100px);
}
}
.sessionstate {
display: inline-block;
height: 20px;
width: 20px;
border-radius: 20px;
border-color: $inputBorderColor;
border-style: solid;
border-width: 1px;
position: absolute;
bottom: 0px;
right: 10px;
&.sessionstate-0 {
background-color: #138D00;
}
&.sessionstate-1 {
background-color: #BC372E;
}
}
& > div {
position: relative;
&.names {
margin: 15px;
.displayname {
font-size: 1.4rem;
}
.loginname {
color: $labelColor;
}
}
}
}
button.other-user {
.user-selection+&{
margin-top: 80px;
}
.other-user-image {
width: 100px;
height: 75px;
@include retina-background-image($otherUserImgDark, "png", false, 100px, 75px);
}
&:hover {
.other-user-image {
@include retina-background-image($otherUserImgDark, "png", true, 100px, 75px);
}
}
& > div:nth-of-type(2) {
margin: 15px;
font-size: 1.4rem;
}
}
} }
#copy-secret { #copy-secret {
@ -153,12 +245,12 @@ form {
#qrcode { #qrcode {
text-align: center; text-align: center;
svg rect[style*="fill:white"] { svg rect.color {
fill: $backgroundColor !important; fill: $fontColor;
} }
svg rect[style*="fill:black"] { svg rect.bg-color {
fill: $fontColor !important; fill: $backgroundColor;
} }
} }

View File

@ -4,7 +4,20 @@ $headerFont: Aileron;
// ----- LAYOUT ------------ // ----- LAYOUT ------------
$inputHeight: 50px; $inputHeight: 50px;
$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) {
$hovername: '';
@if $hover {
$hovername: '-hover';
}
$filename :$file + $hovername;
background-image: url($filename + '.' + $type);
@media #{$retina} {
background-image: url($filename + '@2x.' + $type);
background-size: $width $height;
}
}
// ----- DARK-THEME -------- // ----- DARK-THEME --------
$backgroundColor: #282828; $backgroundColor: #282828;
@ -14,6 +27,9 @@ $primaryColorHover: lighten($primaryColor, 10%);
$labelColor: #898989; $labelColor: #898989;
$inputBorderColor: #595959; $inputBorderColor: #595959;
$inputBackgroundColor: #252525; $inputBackgroundColor: #252525;
$buttonBackgroundColorHover: $inputBackgroundColor;
$profileImgDark: "/resources/images/icon-user-dark";
$otherUserImgDark: "/resources/images/icon-newuser-dark";
// ----- LIGHT-THEME -------- // ----- LIGHT-THEME --------
@ -21,3 +37,6 @@ $backgroundColorLight: $fontColor;
$fontColorLight: $backgroundColor; $fontColorLight: $backgroundColor;
$primaryColorLight: $primaryColor; $primaryColorLight: $primaryColor;
$primaryColorHoverLight: lighten($primaryColorLight, 10%); $primaryColorHoverLight: lighten($primaryColorLight, 10%);
$buttonBackgroundColorHoverLight: #EFEFEF;
$profileImgLight: "/resources/images/icon-user-light";
$otherUserImgLight: "/resources/images/icon-newuser-light";

View File

@ -95,7 +95,7 @@ h1 {
} }
p { p {
font-width: 300; font-weight: 300;
} }
header { header {
@ -151,9 +151,6 @@ button.primary {
button.primary:hover { button.primary:hover {
background-color: #6778f8; background-color: #6778f8;
} }
button > .sessionstate {
text-transform: lowercase;
}
input:not([type=radio]), select { input:not([type=radio]), select {
background-color: #252525; background-color: #252525;
@ -200,6 +197,102 @@ form .actions .right {
form .actions button, form .actions a { form .actions button, form .actions a {
margin: 10px 0; margin: 10px 0;
} }
form button.clean {
border: none;
height: auto;
color: #FFFFFF;
text-align: left;
text-transform: unset;
display: flex;
padding: 15px;
}
form button.clean:hover {
border: none;
background-color: #252525;
}
form button.clean * {
font-weight: 300;
}
form .user-selection-list {
margin-bottom: 80px;
}
form button.user-selection .profile-image {
width: 100px;
height: 100px;
background-image: url("/resources/images/icon-user-dark.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) {
form button.user-selection .profile-image {
background-image: url("/resources/images/icon-user-dark@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-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) {
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-hover@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection .sessionstate {
display: inline-block;
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #595959;
border-style: solid;
border-width: 1px;
position: absolute;
bottom: 0px;
right: 10px;
}
form button.user-selection .sessionstate.sessionstate-0 {
background-color: #138D00;
}
form button.user-selection .sessionstate.sessionstate-1 {
background-color: #BC372E;
}
form button.user-selection > div {
position: relative;
}
form button.user-selection > div.names {
margin: 15px;
}
form button.user-selection > div.names .displayname {
font-size: 1.4rem;
}
form button.user-selection > div.names .loginname {
color: #898989;
}
.user-selection + form button.other-user {
margin-top: 80px;
}
form button.other-user .other-user-image {
width: 100px;
height: 75px;
background-image: url("/resources/images/icon-newuser-dark.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) {
form button.other-user .other-user-image {
background-image: url("/resources/images/icon-newuser-dark@2x.png");
background-size: 100px 75px;
}
}
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-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) {
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-hover@2x.png");
background-size: 100px 75px;
}
}
form button.other-user > div:nth-of-type(2) {
margin: 15px;
font-size: 1.4rem;
}
#copy-secret { #copy-secret {
visibility: hidden; visibility: hidden;
@ -209,11 +302,11 @@ form .actions button, form .actions a {
#qrcode { #qrcode {
text-align: center; text-align: center;
} }
#qrcode svg rect[style*="fill:white"] { #qrcode svg rect.color {
fill: #282828 !important; fill: #FFFFFF;
} }
#qrcode svg rect[style*="fill:black"] { #qrcode svg rect.bg-color {
fill: #FFFFFF !important; fill: #282828;
} }
#secret .copy { #secret .copy {

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,kBCLc;EDMd,OCLQ;;;ADQZ;EACI,OCTQ;EDUR,aClBS;EDmBT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCvCW;EDwCX;EACA;EACA;;AAEA;EACI,OC5CY;;;ADgDpB;EACI;EACA,kBCrDc;EDsDd,OCpDW;EDqDX;EACA;EACA;EACA;EACA,QC/DU;EDgEV;EACA;EACA;;AACA;EACI,kBC7DY;ED8DZ;;AAGJ;EACI,kBCnEO;EDoEP,OCrEI;EDsEJ;;AACA;EACI,kBCtEQ;;AD0EhB;EACI;;;AAIR;EACI,kBC7EmB;ED8EnB,OCnFQ;EDoFR,QCzFU;ED0FV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OC9GK;ED+GL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKJ;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;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,kBCQc;EDPd,OCQQ;;;ADLZ;EACI,OCIQ;EDHR,aClBS;EDmBT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OC1BW;ED2BX;EACA;EACA;;AAEA;EACI,OC/BY;;;ADmCpB;EACI;EACA,kBCxCc;EDyCd,OCvCW;EDwCX;EACA;EACA;EACA;EACA,QC/DU;EDgEV;EACA;EACA;;AACA;EACI,kBChDY;EDiDZ;;AAGJ;EACI,kBCtDO;EDuDP,OCxDI;EDyDJ;;AACA;EACI,kBCzDQ;;;AD8DpB;EACI,kBC5DmB;ED6DnB,OClEQ;EDmER,QCrFU;EDsFV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OC7FK;ED8FL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OC1HI;ED2HJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBC7HW;;ADgIf;EACI;;AAIR;EACI;;AAIA;EACI;EACA;EC1JV;;AACA;EDuJM;ICtJJ;IACA;;;AD4JQ;EC/JV;;AACA;ED8JU;IC7JR;IACA;;;ADiKI;EACI;EACA;EACA;EACA;EACA,cC5JO;ED6JP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OCxLP;;AD+LL;EACI;;AAEJ;EACI;EACA;EChNV;;AACA;ED6MM;IC5MJ;IACA;;;ADkNQ;ECrNV;;AACA;EDoNU;ICnNR;IACA;;;ADuNI;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MCjOI;;ADoOR;EACI,MCtOU;;;AD2Od;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA","file":"dark.css"}

View File

@ -95,7 +95,7 @@ h1 {
} }
p { p {
font-width: 300; font-weight: 300;
} }
header { header {
@ -151,9 +151,6 @@ button.primary {
button.primary:hover { button.primary:hover {
background-color: #6778f8; background-color: #6778f8;
} }
button > .sessionstate {
text-transform: lowercase;
}
input:not([type=radio]), select { input:not([type=radio]), select {
background-color: #252525; background-color: #252525;
@ -200,6 +197,102 @@ form .actions .right {
form .actions button, form .actions a { form .actions button, form .actions a {
margin: 10px 0; margin: 10px 0;
} }
form button.clean {
border: none;
height: auto;
color: #FFFFFF;
text-align: left;
text-transform: unset;
display: flex;
padding: 15px;
}
form button.clean:hover {
border: none;
background-color: #252525;
}
form button.clean * {
font-weight: 300;
}
form .user-selection-list {
margin-bottom: 80px;
}
form button.user-selection .profile-image {
width: 100px;
height: 100px;
background-image: url("/resources/images/icon-user-dark.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) {
form button.user-selection .profile-image {
background-image: url("/resources/images/icon-user-dark@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-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) {
form button.user-selection:hover .profile-image {
background-image: url("/resources/images/icon-user-dark-hover@2x.png");
background-size: 100px 100px;
}
}
form button.user-selection .sessionstate {
display: inline-block;
height: 20px;
width: 20px;
border-radius: 20px;
border-color: #595959;
border-style: solid;
border-width: 1px;
position: absolute;
bottom: 0px;
right: 10px;
}
form button.user-selection .sessionstate.sessionstate-0 {
background-color: #138D00;
}
form button.user-selection .sessionstate.sessionstate-1 {
background-color: #BC372E;
}
form button.user-selection > div {
position: relative;
}
form button.user-selection > div.names {
margin: 15px;
}
form button.user-selection > div.names .displayname {
font-size: 1.4rem;
}
form button.user-selection > div.names .loginname {
color: #898989;
}
.user-selection + form button.other-user {
margin-top: 80px;
}
form button.other-user .other-user-image {
width: 100px;
height: 75px;
background-image: url("/resources/images/icon-newuser-dark.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) {
form button.other-user .other-user-image {
background-image: url("/resources/images/icon-newuser-dark@2x.png");
background-size: 100px 75px;
}
}
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-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) {
form button.other-user:hover .other-user-image {
background-image: url("/resources/images/icon-newuser-dark-hover@2x.png");
background-size: 100px 75px;
}
}
form button.other-user > div:nth-of-type(2) {
margin: 15px;
font-size: 1.4rem;
}
#copy-secret { #copy-secret {
visibility: hidden; visibility: hidden;
@ -209,11 +302,11 @@ form .actions button, form .actions a {
#qrcode { #qrcode {
text-align: center; text-align: center;
} }
#qrcode svg rect[style*="fill:white"] { #qrcode svg rect.color {
fill: #282828 !important; fill: #FFFFFF;
} }
#qrcode svg rect[style*="fill:black"] { #qrcode svg rect.bg-color {
fill: #FFFFFF !important; fill: #282828;
} }
#secret .copy { #secret .copy {
@ -282,6 +375,48 @@ html button.primary {
html button.primary:hover { html button.primary:hover {
background-color: #6778f8; background-color: #6778f8;
} }
html button.clean {
color: #282828;
}
html button.user-selection .profile-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-user-light@2x.png");
background-size: 100px 100px;
}
}
html button.user-selection:hover {
background-color: #252525;
}
html button.user-selection:hover .profile-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-user-light-hover@2x.png");
background-size: 100px 100px;
}
}
html button.other-user .other-user-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-newuser-light@2x.png");
background-size: 100px 75px;
}
}
html button.other-user:hover .other-user-image {
background-image: url("/resources/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 {
background-image: url("/resources/images/icon-newuser-light-hover@2x.png");
background-size: 100px 75px;
}
}
html input { html input {
background-color: #FFFFFF; background-color: #FFFFFF;
color: #282828; color: #282828;

View File

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.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,aCHW;EDIX;EACA;;;AAGJ;EACI;;;AAGJ;EACI,kBCLc;EDMd,OCLQ;;;ADQZ;EACI,OCTQ;EDUR,aClBS;EDmBT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OCvCW;EDwCX;EACA;EACA;;AAEA;EACI,OC5CY;;;ADgDpB;EACI;EACA,kBCrDc;EDsDd,OCpDW;EDqDX;EACA;EACA;EACA;EACA,QC/DU;EDgEV;EACA;EACA;;AACA;EACI,kBC7DY;ED8DZ;;AAGJ;EACI,kBCnEO;EDoEP,OCrEI;EDsEJ;;AACA;EACI,kBCtEQ;;AD0EhB;EACI;;;AAIR;EACI,kBC7EmB;ED8EnB,OCnFQ;EDoFR,QCzFU;ED0FV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OC9GK;ED+GL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI;;AAGJ;EACI;;;AAKJ;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AE1MJ;EACI,kBDQQ;ECPR,ODMc;;ACJd;EACI;;AAGJ;EACI,ODDU;;ACId;EACI,kBDJI;ECKJ,ODJO;ECKP;;AAEA;EACI,kBDGa;ECFb;;AAGJ;EACI,kBDbG;ECcH,ODfA;ECgBA;EACA;;AACA;EACI,kBDjBI;;ACsBhB;EACI,kBDzBI;EC0BJ,OD3BU;;AC+BV;EACI;;AAGJ;EACI;;AAIR;EACI","file":"light.css"} {"version":3,"sourceRoot":"","sources":["../../scss/fonts.scss","../../scss/main.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,aCHW;EDIX;EACA;;;AAGJ;EACI;;;AAGJ;EACI,kBCQc;EDPd,OCQQ;;;ADLZ;EACI,OCIQ;EDHR,aClBS;EDmBT;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;;;AAGJ;EACI,OC1BW;ED2BX;EACA;EACA;;AAEA;EACI,OC/BY;;;ADmCpB;EACI;EACA,kBCxCc;EDyCd,OCvCW;EDwCX;EACA;EACA;EACA;EACA,QC/DU;EDgEV;EACA;EACA;;AACA;EACI,kBChDY;EDiDZ;;AAGJ;EACI,kBCtDO;EDuDP,OCxDI;EDyDJ;;AACA;EACI,kBCzDQ;;;AD8DpB;EACI,kBC5DmB;ED6DnB,OClEQ;EDmER,QCrFU;EDsFV;EACA;EACA;;;AAIA;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI,OC7FK;ED8FL;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,OC1HI;ED2HJ;EACA;EACA;EACA;;AAEA;EACI;EACA,kBC7HW;;ADgIf;EACI;;AAIR;EACI;;AAIA;EACI;EACA;EC1JV;;AACA;EDuJM;ICtJJ;IACA;;;AD4JQ;EC/JV;;AACA;ED8JU;IC7JR;IACA;;;ADiKI;EACI;EACA;EACA;EACA;EACA,cC5JO;ED6JP;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAKR;EACI;;AAEA;EACI;;AAEA;EACI;;AAEJ;EACI,OCxLP;;AD+LL;EACI;;AAEJ;EACI;EACA;EChNV;;AACA;ED6MM;IC5MJ;IACA;;;ADkNQ;ECrNV;;AACA;EDoNU;ICnNR;IACA;;;ADuNI;EACI;EACA;;;AAKZ;EACI;EACA;;;AAGJ;EACI;;AAEA;EACI,MCjOI;;ADoOR;EACI,MCtOU;;;AD2Od;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;AAAkB;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;AAEA;EACA;AACA;EACA;AAEA;EACA;AAEA;EACA;;;AEtSJ;EACI,kBDqBQ;ECpBR,ODmBc;;ACjBd;EACI;;AAGJ;EACI,ODYU;;ACTd;EACI,kBDSI;ECRJ,ODSO;ECRP;;AAEA;EACI,kBDmBa;EClBb;;AAGJ;EACI;EACA,ODFA;ECGA;EACA;;AACA;EACI,kBDJI;;ACQZ;EACI,ODZM;;ACgBN;EDxBV;;AACA;ECuBU;IDtBR;IACA;;;ACyBQ;EACI,kBDfO;;ACiBP;ED/Bd;;AACA;EC8Bc;ID7BZ;IACA;;;ACmCQ;EDtCV;;AACA;ECqCU;IDpCR;IACA;;;ACwCY;ED3Cd;;AACA;EC0Cc;IDzCZ;IACA;;;AC+CA;EACI,kBD1CI;EC2CJ,OD5CU;;ACgDV;EACI;;AAGJ;EACI;;AAIR;EACI","file":"light.css"}

View File

@ -6,6 +6,8 @@
<form action="{{ changePasswordUrl }}" method="POST"> <form action="{{ changePasswordUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields"> <div class="fields">

View File

@ -6,6 +6,8 @@
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />

View File

@ -6,6 +6,8 @@
<form action="{{ initPasswordUrl }}" method="POST"> <form action="{{ initPasswordUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" /> <input type="hidden" name="userID" value="{{ .UserID }}" />

View File

@ -5,6 +5,8 @@
<p>{{t "PasswordSetDone.Description"}}</p> <p>{{t "PasswordSetDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions"> <div class="actions">

View File

@ -6,6 +6,8 @@
<form action="{{ initUserUrl }}" method="POST"> <form action="{{ initUserUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" /> <input type="hidden" name="userID" value="{{ .UserID }}" />

View File

@ -5,6 +5,8 @@
<p>{{t "InitUserDone.Description"}}</p> <p>{{t "InitUserDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions"> <div class="actions">

View File

@ -4,14 +4,16 @@
<h1>{{t "Login.Title"}}</h1> <h1>{{t "Login.Title"}}</h1>
<p>{{t "Login.Description"}}</p> <p>{{t "Login.Description"}}</p>
<form action="{{ usernameUrl }}" method="POST"> <form action="{{ loginNameUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields"> <div class="fields">
<div class="field"> <div class="field">
<label class="label" for="username">{{t "Login.Loginname"}}</label> <label class="label" for="loginName">{{t "Login.Loginname"}}</label>
<input class="input" type="text" id="username" name="username" placeholder="{{t "Login.LoginnamePlaceHolder"}}" value="{{ .UserName }}" autocomplete="username" autofocus required> <input class="input" type="text" id="loginName" name="loginName" placeholder="{{t "Login.LoginnamePlaceHolder"}}" value="{{ .LoginName }}" autocomplete="username" autofocus required>
</div> </div>
</div> </div>

View File

@ -5,6 +5,8 @@
<p>{{t "LogoutDone.Description"}}</p> <p>{{t "LogoutDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<div class="actions"> <div class="actions">
<button class="primary right" type="submit">{{t "Actions.Login"}}</button> <button class="primary right" type="submit">{{t "Actions.Login"}}</button>
</div> </div>

View File

@ -6,6 +6,8 @@
<form action="{{ mailVerificationUrl }}" method="POST"> <form action="{{ mailVerificationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" /> <input type="hidden" name="userID" value="{{ .UserID }}" />

View File

@ -6,6 +6,8 @@
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />

View File

@ -6,6 +6,8 @@
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .MfaType }}" /> <input type="hidden" name="mfaType" value="{{ .MfaType }}" />

View File

@ -6,6 +6,8 @@
<form action="{{ mfaInitVerifyUrl }}" method="POST"> <form action="{{ mfaInitVerifyUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .MfaType }}" /> <input type="hidden" name="mfaType" value="{{ .MfaType }}" />
<input type="hidden" name="url" value="{{ .Url }}" /> <input type="hidden" name="url" value="{{ .Url }}" />
@ -21,7 +23,7 @@
<span class="label" for="secret">{{t "MfaInitVerify.Secret"}}</span> <span class="label" for="secret">{{t "MfaInitVerify.Secret"}}</span>
<span class="input" id="secret"> <span class="input" id="secret">
{{.Secret}} {{.Secret}}
<span class="copy material-icons" onclick="copyToClipboard('{{ .Secret }}')">content_copy</span> <span class="copy material-icons" data-copy="{{ .Secret }}" >content_copy</span>
</span> </span>
</div> </div>
<div class="field"> <div class="field">
@ -36,12 +38,7 @@
</div> </div>
</form> </form>
<script> <script src="{{ resourceUrl "scripts/copy_to_clipboard.js" }}"></script>
const copyToClipboard = str => {
navigator.clipboard.writeText(str);
}
</script>
{{template "main-bottom" .}} {{template "main-bottom" .}}

View File

@ -5,6 +5,8 @@
<form action="{{ mfaPromptUrl }}" method="POST"> <form action="{{ mfaPromptUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields"> <div class="fields">

View File

@ -6,6 +6,8 @@
<form action="{{ mfaVerifyUrl }}" method="POST"> <form action="{{ mfaVerifyUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .SelectedMfaProvider }}" /> <input type="hidden" name="mfaType" value="{{ .SelectedMfaProvider }}" />

View File

@ -5,8 +5,10 @@
<form action="{{ passwordUrl }}" method="POST"> <form action="{{ passwordUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="username" value="{{ .UserName }}" /> <input type="hidden" name="loginName" value="{{ .LoginName }}" />
<div class="fields"> <div class="fields">
<div class="field"> <div class="field">
@ -19,7 +21,7 @@
<div class="actions"> <div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button> <button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ usernameChangeUrl .AuthReqID }}"> <a href="{{ loginNameChangeUrl .AuthReqID }}">
<button class="secondary" type="button">{{t "Actions.Back"}}</button> <button class="secondary" type="button">{{t "Actions.Back"}}</button>
</a> </a>
<a href="{{ passwordResetUrl .AuthReqID }}"> <a href="{{ passwordResetUrl .AuthReqID }}">

View File

@ -5,6 +5,8 @@
<p>{{t "PasswordResetDone.Description"}}</p> <p>{{t "PasswordResetDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST"> <form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions"> <div class="actions">

View File

@ -5,6 +5,8 @@
<form action="{{ registrationUrl }}" method="POST"> <form action="{{ registrationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields"> <div class="fields">

View File

@ -6,17 +6,32 @@
<form action="{{ userSelectionUrl }}" method="POST"> <form action="{{ userSelectionUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" /> <input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions"> <div class="actions">
{{ if .Users }}
<div class="user-selection-list">
{{ range $user := .Users }} {{ range $user := .Users }}
{{ $sessionState := (t (printf "UserSelection.SessionState%v" $user.UserSessionState)) }} {{ $sessionState := (printf "sessionstate-%v" $user.UserSessionState) }}
<button type="submit" name="userID" value="{{$user.UserID}}" class="primary"> <button type="submit" name="userID" value="{{$user.UserID}}" class="clean user-selection">
<span class="username">{{$user.UserName}}</span> <div>
<span class="sessionstate">({{$sessionState}})</span> <div class="profile-image"></div>
<div class="sessionstate {{$sessionState}}"></div>
</div>
<div class="names">
<div class="displayname">{{$user.DisplayName}}</div>
<div class="loginname">{{$user.LoginName}}</div>
</div>
</button> </button>
{{ end }} {{ end }}
<button type="submit" name="userID" value="0" class="primary">{{t "UserSelection.OtherUser"}}</button> </div>
{{ end }}
<button type="submit" name="userID" value="0" class="clean other-user">
<div class="other-user-image"></div>
<div>{{t "UserSelection.OtherUser"}}</div>
</button>
</div> </div>
</form> </form>

73
internal/qrcode/qr_svg.go Normal file
View File

@ -0,0 +1,73 @@
package qrcode
import (
"errors"
"image/color"
"github.com/ajstarks/svgo"
"github.com/boombuler/barcode"
)
// QrSVG holds the data related to the size, location,
// and block size of the QR Code. Holds unexported fields.
type QrSVG struct {
qr barcode.Barcode
qrWidth int
blockSize int
startingX int
startingY int
}
// NewQrSVG contructs a QrSVG struct. It takes a QR Code in the form
// of barcode.Barcode and sets the "pixel" or block size of QR Code in
// the SVG file.
func NewQrSVG(qr barcode.Barcode, blockSize int) QrSVG {
return QrSVG{
qr: qr,
qrWidth: qr.Bounds().Max.X,
blockSize: blockSize,
startingX: 0,
startingY: 0,
}
}
// WriteQrSVG writes the QR Code to SVG.
func (qs *QrSVG) WriteQrSVG(s *svg.SVG) error {
if qs.qr.Metadata().CodeKind == "QR Code" {
currY := qs.startingY
for x := 0; x < qs.qrWidth; x++ {
currX := qs.startingX
for y := 0; y < qs.qrWidth; y++ {
if qs.qr.At(x, y) == color.Black {
s.Rect(currX, currY, qs.blockSize, qs.blockSize, "class=\"color\"")
} else if qs.qr.At(x, y) == color.White {
s.Rect(currX, currY, qs.blockSize, qs.blockSize, "class=\"bg-color\"")
}
currX += qs.blockSize
}
currY += qs.blockSize
}
return nil
}
return errors.New("can not write to SVG: Not a QR code")
}
// SetStartPoint sets the top left start point of QR Code.
// This takes an X and Y value and then adds four white "blocks"
// to create the "quiet zone" around the QR Code.
func (qs *QrSVG) SetStartPoint(x, y int) {
qs.startingX = x + (qs.blockSize * 4)
qs.startingY = y + (qs.blockSize * 4)
}
// StartQrSVG creates a start for writing an SVG file that
// only contains a barcode. This is similar to the svg.Start() method.
// This fucntion should only be used if you only want to write a QR code
// to the SVG. Otherwise use the regular svg.Start() method to start your
// SVG file.
func (qs *QrSVG) StartQrSVG(s *svg.SVG) {
width := (qs.qrWidth * qs.blockSize) + (qs.blockSize * 8)
qs.SetStartPoint(0, 0)
s.Start(width, width)
}

View File

@ -0,0 +1,493 @@
package qrcode
import (
"bytes"
"os"
"testing"
"github.com/ajstarks/svgo"
"github.com/boombuler/barcode/qr"
)
func Test_goqrsvg(t *testing.T) {
buf := bytes.NewBufferString("")
s := svg.New(buf)
// Create the barcode
qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto)
// Write QR code to SVG
qs := NewQrSVG(qrCode, 5)
qs.StartQrSVG(s)
qs.WriteQrSVG(s)
s.End()
// Check if output the same as correctOutput
if buf.String() != correctOutput {
t.Error("Something is not right... The SVG created is not the same as correctOutput.")
}
}
func ExampleNewQrSVG() {
s := svg.New(os.Stdout)
// Create the barcode
qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto)
// Write QR code to SVG
qs := NewQrSVG(qrCode, 5)
qs.StartQrSVG(s)
qs.WriteQrSVG(s)
s.End()
}
const correctOutput = `<?xml version="1.0"?>
<!-- Generated by SVGo -->
<svg width="145" height="145"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="20" y="20" width="5" height="5" class="color" />
<rect x="25" y="20" width="5" height="5" class="color" />
<rect x="30" y="20" width="5" height="5" class="color" />
<rect x="35" y="20" width="5" height="5" class="color" />
<rect x="40" y="20" width="5" height="5" class="color" />
<rect x="45" y="20" width="5" height="5" class="color" />
<rect x="50" y="20" width="5" height="5" class="color" />
<rect x="55" y="20" width="5" height="5" class="bg-color" />
<rect x="60" y="20" width="5" height="5" class="color" />
<rect x="65" y="20" width="5" height="5" class="color" />
<rect x="70" y="20" width="5" height="5" class="bg-color" />
<rect x="75" y="20" width="5" height="5" class="color" />
<rect x="80" y="20" width="5" height="5" class="bg-color" />
<rect x="85" y="20" width="5" height="5" class="bg-color" />
<rect x="90" y="20" width="5" height="5" class="color" />
<rect x="95" y="20" width="5" height="5" class="color" />
<rect x="100" y="20" width="5" height="5" class="color" />
<rect x="105" y="20" width="5" height="5" class="color" />
<rect x="110" y="20" width="5" height="5" class="color" />
<rect x="115" y="20" width="5" height="5" class="color" />
<rect x="120" y="20" width="5" height="5" class="color" />
<rect x="20" y="25" width="5" height="5" class="color" />
<rect x="25" y="25" width="5" height="5" class="bg-color" />
<rect x="30" y="25" width="5" height="5" class="bg-color" />
<rect x="35" y="25" width="5" height="5" class="bg-color" />
<rect x="40" y="25" width="5" height="5" class="bg-color" />
<rect x="45" y="25" width="5" height="5" class="bg-color" />
<rect x="50" y="25" width="5" height="5" class="color" />
<rect x="55" y="25" width="5" height="5" class="bg-color" />
<rect x="60" y="25" width="5" height="5" class="bg-color" />
<rect x="65" y="25" width="5" height="5" class="bg-color" />
<rect x="70" y="25" width="5" height="5" class="color" />
<rect x="75" y="25" width="5" height="5" class="bg-color" />
<rect x="80" y="25" width="5" height="5" class="color" />
<rect x="85" y="25" width="5" height="5" class="bg-color" />
<rect x="90" y="25" width="5" height="5" class="color" />
<rect x="95" y="25" width="5" height="5" class="bg-color" />
<rect x="100" y="25" width="5" height="5" class="bg-color" />
<rect x="105" y="25" width="5" height="5" class="bg-color" />
<rect x="110" y="25" width="5" height="5" class="bg-color" />
<rect x="115" y="25" width="5" height="5" class="bg-color" />
<rect x="120" y="25" width="5" height="5" class="color" />
<rect x="20" y="30" width="5" height="5" class="color" />
<rect x="25" y="30" width="5" height="5" class="bg-color" />
<rect x="30" y="30" width="5" height="5" class="color" />
<rect x="35" y="30" width="5" height="5" class="color" />
<rect x="40" y="30" width="5" height="5" class="color" />
<rect x="45" y="30" width="5" height="5" class="bg-color" />
<rect x="50" y="30" width="5" height="5" class="color" />
<rect x="55" y="30" width="5" height="5" class="bg-color" />
<rect x="60" y="30" width="5" height="5" class="color" />
<rect x="65" y="30" width="5" height="5" class="bg-color" />
<rect x="70" y="30" width="5" height="5" class="color" />
<rect x="75" y="30" width="5" height="5" class="color" />
<rect x="80" y="30" width="5" height="5" class="color" />
<rect x="85" y="30" width="5" height="5" class="bg-color" />
<rect x="90" y="30" width="5" height="5" class="color" />
<rect x="95" y="30" width="5" height="5" class="bg-color" />
<rect x="100" y="30" width="5" height="5" class="color" />
<rect x="105" y="30" width="5" height="5" class="color" />
<rect x="110" y="30" width="5" height="5" class="color" />
<rect x="115" y="30" width="5" height="5" class="bg-color" />
<rect x="120" y="30" width="5" height="5" class="color" />
<rect x="20" y="35" width="5" height="5" class="color" />
<rect x="25" y="35" width="5" height="5" class="bg-color" />
<rect x="30" y="35" width="5" height="5" class="color" />
<rect x="35" y="35" width="5" height="5" class="color" />
<rect x="40" y="35" width="5" height="5" class="color" />
<rect x="45" y="35" width="5" height="5" class="bg-color" />
<rect x="50" y="35" width="5" height="5" class="color" />
<rect x="55" y="35" width="5" height="5" class="bg-color" />
<rect x="60" y="35" width="5" height="5" class="color" />
<rect x="65" y="35" width="5" height="5" class="color" />
<rect x="70" y="35" width="5" height="5" class="color" />
<rect x="75" y="35" width="5" height="5" class="bg-color" />
<rect x="80" y="35" width="5" height="5" class="bg-color" />
<rect x="85" y="35" width="5" height="5" class="bg-color" />
<rect x="90" y="35" width="5" height="5" class="color" />
<rect x="95" y="35" width="5" height="5" class="bg-color" />
<rect x="100" y="35" width="5" height="5" class="color" />
<rect x="105" y="35" width="5" height="5" class="color" />
<rect x="110" y="35" width="5" height="5" class="color" />
<rect x="115" y="35" width="5" height="5" class="bg-color" />
<rect x="120" y="35" width="5" height="5" class="color" />
<rect x="20" y="40" width="5" height="5" class="color" />
<rect x="25" y="40" width="5" height="5" class="bg-color" />
<rect x="30" y="40" width="5" height="5" class="color" />
<rect x="35" y="40" width="5" height="5" class="color" />
<rect x="40" y="40" width="5" height="5" class="color" />
<rect x="45" y="40" width="5" height="5" class="bg-color" />
<rect x="50" y="40" width="5" height="5" class="color" />
<rect x="55" y="40" width="5" height="5" class="bg-color" />
<rect x="60" y="40" width="5" height="5" class="color" />
<rect x="65" y="40" width="5" height="5" class="color" />
<rect x="70" y="40" width="5" height="5" class="color" />
<rect x="75" y="40" width="5" height="5" class="color" />
<rect x="80" y="40" width="5" height="5" class="bg-color" />
<rect x="85" y="40" width="5" height="5" class="bg-color" />
<rect x="90" y="40" width="5" height="5" class="color" />
<rect x="95" y="40" width="5" height="5" class="bg-color" />
<rect x="100" y="40" width="5" height="5" class="color" />
<rect x="105" y="40" width="5" height="5" class="color" />
<rect x="110" y="40" width="5" height="5" class="color" />
<rect x="115" y="40" width="5" height="5" class="bg-color" />
<rect x="120" y="40" width="5" height="5" class="color" />
<rect x="20" y="45" width="5" height="5" class="color" />
<rect x="25" y="45" width="5" height="5" class="bg-color" />
<rect x="30" y="45" width="5" height="5" class="bg-color" />
<rect x="35" y="45" width="5" height="5" class="bg-color" />
<rect x="40" y="45" width="5" height="5" class="bg-color" />
<rect x="45" y="45" width="5" height="5" class="bg-color" />
<rect x="50" y="45" width="5" height="5" class="color" />
<rect x="55" y="45" width="5" height="5" class="bg-color" />
<rect x="60" y="45" width="5" height="5" class="color" />
<rect x="65" y="45" width="5" height="5" class="color" />
<rect x="70" y="45" width="5" height="5" class="bg-color" />
<rect x="75" y="45" width="5" height="5" class="bg-color" />
<rect x="80" y="45" width="5" height="5" class="bg-color" />
<rect x="85" y="45" width="5" height="5" class="bg-color" />
<rect x="90" y="45" width="5" height="5" class="color" />
<rect x="95" y="45" width="5" height="5" class="bg-color" />
<rect x="100" y="45" width="5" height="5" class="bg-color" />
<rect x="105" y="45" width="5" height="5" class="bg-color" />
<rect x="110" y="45" width="5" height="5" class="bg-color" />
<rect x="115" y="45" width="5" height="5" class="bg-color" />
<rect x="120" y="45" width="5" height="5" class="color" />
<rect x="20" y="50" width="5" height="5" class="color" />
<rect x="25" y="50" width="5" height="5" class="color" />
<rect x="30" y="50" width="5" height="5" class="color" />
<rect x="35" y="50" width="5" height="5" class="color" />
<rect x="40" y="50" width="5" height="5" class="color" />
<rect x="45" y="50" width="5" height="5" class="color" />
<rect x="50" y="50" width="5" height="5" class="color" />
<rect x="55" y="50" width="5" height="5" class="bg-color" />
<rect x="60" y="50" width="5" height="5" class="color" />
<rect x="65" y="50" width="5" height="5" class="bg-color" />
<rect x="70" y="50" width="5" height="5" class="color" />
<rect x="75" y="50" width="5" height="5" class="bg-color" />
<rect x="80" y="50" width="5" height="5" class="color" />
<rect x="85" y="50" width="5" height="5" class="bg-color" />
<rect x="90" y="50" width="5" height="5" class="color" />
<rect x="95" y="50" width="5" height="5" class="color" />
<rect x="100" y="50" width="5" height="5" class="color" />
<rect x="105" y="50" width="5" height="5" class="color" />
<rect x="110" y="50" width="5" height="5" class="color" />
<rect x="115" y="50" width="5" height="5" class="color" />
<rect x="120" y="50" width="5" height="5" class="color" />
<rect x="20" y="55" width="5" height="5" class="bg-color" />
<rect x="25" y="55" width="5" height="5" class="bg-color" />
<rect x="30" y="55" width="5" height="5" class="bg-color" />
<rect x="35" y="55" width="5" height="5" class="bg-color" />
<rect x="40" y="55" width="5" height="5" class="bg-color" />
<rect x="45" y="55" width="5" height="5" class="bg-color" />
<rect x="50" y="55" width="5" height="5" class="bg-color" />
<rect x="55" y="55" width="5" height="5" class="bg-color" />
<rect x="60" y="55" width="5" height="5" class="bg-color" />
<rect x="65" y="55" width="5" height="5" class="bg-color" />
<rect x="70" y="55" width="5" height="5" class="color" />
<rect x="75" y="55" width="5" height="5" class="bg-color" />
<rect x="80" y="55" width="5" height="5" class="bg-color" />
<rect x="85" y="55" width="5" height="5" class="bg-color" />
<rect x="90" y="55" width="5" height="5" class="bg-color" />
<rect x="95" y="55" width="5" height="5" class="bg-color" />
<rect x="100" y="55" width="5" height="5" class="bg-color" />
<rect x="105" y="55" width="5" height="5" class="bg-color" />
<rect x="110" y="55" width="5" height="5" class="bg-color" />
<rect x="115" y="55" width="5" height="5" class="bg-color" />
<rect x="120" y="55" width="5" height="5" class="bg-color" />
<rect x="20" y="60" width="5" height="5" class="bg-color" />
<rect x="25" y="60" width="5" height="5" class="bg-color" />
<rect x="30" y="60" width="5" height="5" class="color" />
<rect x="35" y="60" width="5" height="5" class="color" />
<rect x="40" y="60" width="5" height="5" class="color" />
<rect x="45" y="60" width="5" height="5" class="color" />
<rect x="50" y="60" width="5" height="5" class="color" />
<rect x="55" y="60" width="5" height="5" class="color" />
<rect x="60" y="60" width="5" height="5" class="bg-color" />
<rect x="65" y="60" width="5" height="5" class="color" />
<rect x="70" y="60" width="5" height="5" class="bg-color" />
<rect x="75" y="60" width="5" height="5" class="color" />
<rect x="80" y="60" width="5" height="5" class="bg-color" />
<rect x="85" y="60" width="5" height="5" class="color" />
<rect x="90" y="60" width="5" height="5" class="bg-color" />
<rect x="95" y="60" width="5" height="5" class="color" />
<rect x="100" y="60" width="5" height="5" class="color" />
<rect x="105" y="60" width="5" height="5" class="color" />
<rect x="110" y="60" width="5" height="5" class="color" />
<rect x="115" y="60" width="5" height="5" class="bg-color" />
<rect x="120" y="60" width="5" height="5" class="color" />
<rect x="20" y="65" width="5" height="5" class="bg-color" />
<rect x="25" y="65" width="5" height="5" class="bg-color" />
<rect x="30" y="65" width="5" height="5" class="bg-color" />
<rect x="35" y="65" width="5" height="5" class="color" />
<rect x="40" y="65" width="5" height="5" class="bg-color" />
<rect x="45" y="65" width="5" height="5" class="bg-color" />
<rect x="50" y="65" width="5" height="5" class="bg-color" />
<rect x="55" y="65" width="5" height="5" class="color" />
<rect x="60" y="65" width="5" height="5" class="bg-color" />
<rect x="65" y="65" width="5" height="5" class="bg-color" />
<rect x="70" y="65" width="5" height="5" class="color" />
<rect x="75" y="65" width="5" height="5" class="color" />
<rect x="80" y="65" width="5" height="5" class="bg-color" />
<rect x="85" y="65" width="5" height="5" class="bg-color" />
<rect x="90" y="65" width="5" height="5" class="bg-color" />
<rect x="95" y="65" width="5" height="5" class="bg-color" />
<rect x="100" y="65" width="5" height="5" class="bg-color" />
<rect x="105" y="65" width="5" height="5" class="color" />
<rect x="110" y="65" width="5" height="5" class="color" />
<rect x="115" y="65" width="5" height="5" class="bg-color" />
<rect x="120" y="65" width="5" height="5" class="bg-color" />
<rect x="20" y="70" width="5" height="5" class="color" />
<rect x="25" y="70" width="5" height="5" class="color" />
<rect x="30" y="70" width="5" height="5" class="color" />
<rect x="35" y="70" width="5" height="5" class="bg-color" />
<rect x="40" y="70" width="5" height="5" class="bg-color" />
<rect x="45" y="70" width="5" height="5" class="color" />
<rect x="50" y="70" width="5" height="5" class="color" />
<rect x="55" y="70" width="5" height="5" class="bg-color" />
<rect x="60" y="70" width="5" height="5" class="bg-color" />
<rect x="65" y="70" width="5" height="5" class="bg-color" />
<rect x="70" y="70" width="5" height="5" class="bg-color" />
<rect x="75" y="70" width="5" height="5" class="bg-color" />
<rect x="80" y="70" width="5" height="5" class="bg-color" />
<rect x="85" y="70" width="5" height="5" class="color" />
<rect x="90" y="70" width="5" height="5" class="bg-color" />
<rect x="95" y="70" width="5" height="5" class="bg-color" />
<rect x="100" y="70" width="5" height="5" class="bg-color" />
<rect x="105" y="70" width="5" height="5" class="color" />
<rect x="110" y="70" width="5" height="5" class="bg-color" />
<rect x="115" y="70" width="5" height="5" class="color" />
<rect x="120" y="70" width="5" height="5" class="color" />
<rect x="20" y="75" width="5" height="5" class="bg-color" />
<rect x="25" y="75" width="5" height="5" class="bg-color" />
<rect x="30" y="75" width="5" height="5" class="bg-color" />
<rect x="35" y="75" width="5" height="5" class="color" />
<rect x="40" y="75" width="5" height="5" class="bg-color" />
<rect x="45" y="75" width="5" height="5" class="color" />
<rect x="50" y="75" width="5" height="5" class="bg-color" />
<rect x="55" y="75" width="5" height="5" class="bg-color" />
<rect x="60" y="75" width="5" height="5" class="color" />
<rect x="65" y="75" width="5" height="5" class="color" />
<rect x="70" y="75" width="5" height="5" class="bg-color" />
<rect x="75" y="75" width="5" height="5" class="color" />
<rect x="80" y="75" width="5" height="5" class="bg-color" />
<rect x="85" y="75" width="5" height="5" class="bg-color" />
<rect x="90" y="75" width="5" height="5" class="color" />
<rect x="95" y="75" width="5" height="5" class="bg-color" />
<rect x="100" y="75" width="5" height="5" class="color" />
<rect x="105" y="75" width="5" height="5" class="bg-color" />
<rect x="110" y="75" width="5" height="5" class="bg-color" />
<rect x="115" y="75" width="5" height="5" class="bg-color" />
<rect x="120" y="75" width="5" height="5" class="color" />
<rect x="20" y="80" width="5" height="5" class="color" />
<rect x="25" y="80" width="5" height="5" class="color" />
<rect x="30" y="80" width="5" height="5" class="color" />
<rect x="35" y="80" width="5" height="5" class="color" />
<rect x="40" y="80" width="5" height="5" class="color" />
<rect x="45" y="80" width="5" height="5" class="bg-color" />
<rect x="50" y="80" width="5" height="5" class="color" />
<rect x="55" y="80" width="5" height="5" class="bg-color" />
<rect x="60" y="80" width="5" height="5" class="bg-color" />
<rect x="65" y="80" width="5" height="5" class="color" />
<rect x="70" y="80" width="5" height="5" class="color" />
<rect x="75" y="80" width="5" height="5" class="color" />
<rect x="80" y="80" width="5" height="5" class="color" />
<rect x="85" y="80" width="5" height="5" class="color" />
<rect x="90" y="80" width="5" height="5" class="bg-color" />
<rect x="95" y="80" width="5" height="5" class="bg-color" />
<rect x="100" y="80" width="5" height="5" class="bg-color" />
<rect x="105" y="80" width="5" height="5" class="color" />
<rect x="110" y="80" width="5" height="5" class="color" />
<rect x="115" y="80" width="5" height="5" class="color" />
<rect x="120" y="80" width="5" height="5" class="color" />
<rect x="20" y="85" width="5" height="5" class="bg-color" />
<rect x="25" y="85" width="5" height="5" class="bg-color" />
<rect x="30" y="85" width="5" height="5" class="bg-color" />
<rect x="35" y="85" width="5" height="5" class="bg-color" />
<rect x="40" y="85" width="5" height="5" class="bg-color" />
<rect x="45" y="85" width="5" height="5" class="bg-color" />
<rect x="50" y="85" width="5" height="5" class="bg-color" />
<rect x="55" y="85" width="5" height="5" class="bg-color" />
<rect x="60" y="85" width="5" height="5" class="bg-color" />
<rect x="65" y="85" width="5" height="5" class="color" />
<rect x="70" y="85" width="5" height="5" class="color" />
<rect x="75" y="85" width="5" height="5" class="color" />
<rect x="80" y="85" width="5" height="5" class="color" />
<rect x="85" y="85" width="5" height="5" class="bg-color" />
<rect x="90" y="85" width="5" height="5" class="bg-color" />
<rect x="95" y="85" width="5" height="5" class="color" />
<rect x="100" y="85" width="5" height="5" class="bg-color" />
<rect x="105" y="85" width="5" height="5" class="color" />
<rect x="110" y="85" width="5" height="5" class="bg-color" />
<rect x="115" y="85" width="5" height="5" class="color" />
<rect x="120" y="85" width="5" height="5" class="bg-color" />
<rect x="20" y="90" width="5" height="5" class="color" />
<rect x="25" y="90" width="5" height="5" class="color" />
<rect x="30" y="90" width="5" height="5" class="color" />
<rect x="35" y="90" width="5" height="5" class="color" />
<rect x="40" y="90" width="5" height="5" class="color" />
<rect x="45" y="90" width="5" height="5" class="color" />
<rect x="50" y="90" width="5" height="5" class="color" />
<rect x="55" y="90" width="5" height="5" class="bg-color" />
<rect x="60" y="90" width="5" height="5" class="color" />
<rect x="65" y="90" width="5" height="5" class="color" />
<rect x="70" y="90" width="5" height="5" class="color" />
<rect x="75" y="90" width="5" height="5" class="bg-color" />
<rect x="80" y="90" width="5" height="5" class="color" />
<rect x="85" y="90" width="5" height="5" class="bg-color" />
<rect x="90" y="90" width="5" height="5" class="color" />
<rect x="95" y="90" width="5" height="5" class="bg-color" />
<rect x="100" y="90" width="5" height="5" class="color" />
<rect x="105" y="90" width="5" height="5" class="color" />
<rect x="110" y="90" width="5" height="5" class="bg-color" />
<rect x="115" y="90" width="5" height="5" class="bg-color" />
<rect x="120" y="90" width="5" height="5" class="color" />
<rect x="20" y="95" width="5" height="5" class="color" />
<rect x="25" y="95" width="5" height="5" class="bg-color" />
<rect x="30" y="95" width="5" height="5" class="bg-color" />
<rect x="35" y="95" width="5" height="5" class="bg-color" />
<rect x="40" y="95" width="5" height="5" class="bg-color" />
<rect x="45" y="95" width="5" height="5" class="bg-color" />
<rect x="50" y="95" width="5" height="5" class="color" />
<rect x="55" y="95" width="5" height="5" class="bg-color" />
<rect x="60" y="95" width="5" height="5" class="color" />
<rect x="65" y="95" width="5" height="5" class="color" />
<rect x="70" y="95" width="5" height="5" class="bg-color" />
<rect x="75" y="95" width="5" height="5" class="bg-color" />
<rect x="80" y="95" width="5" height="5" class="bg-color" />
<rect x="85" y="95" width="5" height="5" class="bg-color" />
<rect x="90" y="95" width="5" height="5" class="bg-color" />
<rect x="95" y="95" width="5" height="5" class="color" />
<rect x="100" y="95" width="5" height="5" class="color" />
<rect x="105" y="95" width="5" height="5" class="color" />
<rect x="110" y="95" width="5" height="5" class="color" />
<rect x="115" y="95" width="5" height="5" class="bg-color" />
<rect x="120" y="95" width="5" height="5" class="bg-color" />
<rect x="20" y="100" width="5" height="5" class="color" />
<rect x="25" y="100" width="5" height="5" class="bg-color" />
<rect x="30" y="100" width="5" height="5" class="color" />
<rect x="35" y="100" width="5" height="5" class="color" />
<rect x="40" y="100" width="5" height="5" class="color" />
<rect x="45" y="100" width="5" height="5" class="bg-color" />
<rect x="50" y="100" width="5" height="5" class="color" />
<rect x="55" y="100" width="5" height="5" class="bg-color" />
<rect x="60" y="100" width="5" height="5" class="color" />
<rect x="65" y="100" width="5" height="5" class="color" />
<rect x="70" y="100" width="5" height="5" class="bg-color" />
<rect x="75" y="100" width="5" height="5" class="color" />
<rect x="80" y="100" width="5" height="5" class="bg-color" />
<rect x="85" y="100" width="5" height="5" class="bg-color" />
<rect x="90" y="100" width="5" height="5" class="bg-color" />
<rect x="95" y="100" width="5" height="5" class="bg-color" />
<rect x="100" y="100" width="5" height="5" class="bg-color" />
<rect x="105" y="100" width="5" height="5" class="color" />
<rect x="110" y="100" width="5" height="5" class="bg-color" />
<rect x="115" y="100" width="5" height="5" class="color" />
<rect x="120" y="100" width="5" height="5" class="color" />
<rect x="20" y="105" width="5" height="5" class="color" />
<rect x="25" y="105" width="5" height="5" class="bg-color" />
<rect x="30" y="105" width="5" height="5" class="color" />
<rect x="35" y="105" width="5" height="5" class="color" />
<rect x="40" y="105" width="5" height="5" class="color" />
<rect x="45" y="105" width="5" height="5" class="bg-color" />
<rect x="50" y="105" width="5" height="5" class="color" />
<rect x="55" y="105" width="5" height="5" class="bg-color" />
<rect x="60" y="105" width="5" height="5" class="color" />
<rect x="65" y="105" width="5" height="5" class="color" />
<rect x="70" y="105" width="5" height="5" class="color" />
<rect x="75" y="105" width="5" height="5" class="color" />
<rect x="80" y="105" width="5" height="5" class="bg-color" />
<rect x="85" y="105" width="5" height="5" class="color" />
<rect x="90" y="105" width="5" height="5" class="bg-color" />
<rect x="95" y="105" width="5" height="5" class="color" />
<rect x="100" y="105" width="5" height="5" class="bg-color" />
<rect x="105" y="105" width="5" height="5" class="color" />
<rect x="110" y="105" width="5" height="5" class="bg-color" />
<rect x="115" y="105" width="5" height="5" class="color" />
<rect x="120" y="105" width="5" height="5" class="bg-color" />
<rect x="20" y="110" width="5" height="5" class="color" />
<rect x="25" y="110" width="5" height="5" class="bg-color" />
<rect x="30" y="110" width="5" height="5" class="color" />
<rect x="35" y="110" width="5" height="5" class="color" />
<rect x="40" y="110" width="5" height="5" class="color" />
<rect x="45" y="110" width="5" height="5" class="bg-color" />
<rect x="50" y="110" width="5" height="5" class="color" />
<rect x="55" y="110" width="5" height="5" class="bg-color" />
<rect x="60" y="110" width="5" height="5" class="color" />
<rect x="65" y="110" width="5" height="5" class="color" />
<rect x="70" y="110" width="5" height="5" class="color" />
<rect x="75" y="110" width="5" height="5" class="color" />
<rect x="80" y="110" width="5" height="5" class="bg-color" />
<rect x="85" y="110" width="5" height="5" class="bg-color" />
<rect x="90" y="110" width="5" height="5" class="color" />
<rect x="95" y="110" width="5" height="5" class="color" />
<rect x="100" y="110" width="5" height="5" class="bg-color" />
<rect x="105" y="110" width="5" height="5" class="bg-color" />
<rect x="110" y="110" width="5" height="5" class="color" />
<rect x="115" y="110" width="5" height="5" class="color" />
<rect x="120" y="110" width="5" height="5" class="bg-color" />
<rect x="20" y="115" width="5" height="5" class="color" />
<rect x="25" y="115" width="5" height="5" class="bg-color" />
<rect x="30" y="115" width="5" height="5" class="bg-color" />
<rect x="35" y="115" width="5" height="5" class="bg-color" />
<rect x="40" y="115" width="5" height="5" class="bg-color" />
<rect x="45" y="115" width="5" height="5" class="bg-color" />
<rect x="50" y="115" width="5" height="5" class="color" />
<rect x="55" y="115" width="5" height="5" class="bg-color" />
<rect x="60" y="115" width="5" height="5" class="bg-color" />
<rect x="65" y="115" width="5" height="5" class="bg-color" />
<rect x="70" y="115" width="5" height="5" class="color" />
<rect x="75" y="115" width="5" height="5" class="bg-color" />
<rect x="80" y="115" width="5" height="5" class="bg-color" />
<rect x="85" y="115" width="5" height="5" class="bg-color" />
<rect x="90" y="115" width="5" height="5" class="color" />
<rect x="95" y="115" width="5" height="5" class="color" />
<rect x="100" y="115" width="5" height="5" class="bg-color" />
<rect x="105" y="115" width="5" height="5" class="bg-color" />
<rect x="110" y="115" width="5" height="5" class="bg-color" />
<rect x="115" y="115" width="5" height="5" class="bg-color" />
<rect x="120" y="115" width="5" height="5" class="color" />
<rect x="20" y="120" width="5" height="5" class="color" />
<rect x="25" y="120" width="5" height="5" class="color" />
<rect x="30" y="120" width="5" height="5" class="color" />
<rect x="35" y="120" width="5" height="5" class="color" />
<rect x="40" y="120" width="5" height="5" class="color" />
<rect x="45" y="120" width="5" height="5" class="color" />
<rect x="50" y="120" width="5" height="5" class="color" />
<rect x="55" y="120" width="5" height="5" class="bg-color" />
<rect x="60" y="120" width="5" height="5" class="bg-color" />
<rect x="65" y="120" width="5" height="5" class="color" />
<rect x="70" y="120" width="5" height="5" class="bg-color" />
<rect x="75" y="120" width="5" height="5" class="bg-color" />
<rect x="80" y="120" width="5" height="5" class="color" />
<rect x="85" y="120" width="5" height="5" class="bg-color" />
<rect x="90" y="120" width="5" height="5" class="bg-color" />
<rect x="95" y="120" width="5" height="5" class="color" />
<rect x="100" y="120" width="5" height="5" class="color" />
<rect x="105" y="120" width="5" height="5" class="bg-color" />
<rect x="110" y="120" width="5" height="5" class="bg-color" />
<rect x="115" y="120" width="5" height="5" class="bg-color" />
<rect x="120" y="120" width="5" height="5" class="bg-color" />
</svg>
`

14
internal/qrcode/readme.md Normal file
View File

@ -0,0 +1,14 @@
# QR Code to SVG
This package is a copy of https://github.com/aaronarduino/goqrsvg with the difference of creating the svg with `class` attribute instead of inline `style`:
```go
s.Rect(currX, currY, qs.blockSize, qs.blockSize, "class=\"color\"")
```
and not
```go
s.Rect(currX, currY, qs.blockSize, qs.blockSize, "fill:black;stroke:none")
```
This allows the svg to be styled by css more easily and does not compromise Content Security Policy (CSP).

View File

@ -81,6 +81,12 @@ func (u *User) CheckOrgIamPolicy(policy *org_model.OrgIamPolicy) error {
return nil return nil
} }
func (u *User) SetNamesAsDisplayname() {
if u.Profile != nil && u.DisplayName == "" && u.FirstName != "" && u.LastName != "" {
u.DisplayName = u.FirstName + " " + u.LastName
}
}
func (u *User) IsValid() bool { func (u *User) IsValid() bool {
return u.Profile != nil && u.FirstName != "" && u.LastName != "" && u.UserName != "" && u.Email != nil && u.Email.IsValid() && u.Phone == nil || (u.Phone != nil && u.Phone.IsValid()) return u.Profile != nil && u.FirstName != "" && u.LastName != "" && u.UserName != "" && u.Email != nil && u.Email.IsValid() && u.Phone == nil || (u.Phone != nil && u.Phone.IsValid())
} }

View File

@ -15,6 +15,8 @@ type UserSessionView struct {
UserAgentID string UserAgentID string
UserID string UserID string
UserName string UserName string
LoginName string
DisplayName string
PasswordVerification time.Time PasswordVerification time.Time
MfaSoftwareVerification time.Time MfaSoftwareVerification time.Time
MfaSoftwareVerificationType req_model.MfaType MfaSoftwareVerificationType req_model.MfaType

View File

@ -109,6 +109,7 @@ func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
user.SetNamesAsDisplayname()
if !user.IsValid() { if !user.IsValid() {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "User is invalid") return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "User is invalid")
} }
@ -161,6 +162,7 @@ func (es *UserEventstore) PrepareRegisterUser(ctx context.Context, user *usr_mod
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
user.SetNamesAsDisplayname()
if !user.IsValid() || user.Password == nil || user.SecretString == "" { if !user.IsValid() || user.Password == nil || user.SecretString == "" {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Errors.User.InvalidData") return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Errors.User.InvalidData")
} }

View File

@ -27,7 +27,9 @@ type UserSessionView struct {
State int32 `json:"-" gorm:"column:state"` State int32 `json:"-" gorm:"column:state"`
UserAgentID string `json:"userAgentID" gorm:"column:user_agent_id;primary_key"` UserAgentID string `json:"userAgentID" gorm:"column:user_agent_id;primary_key"`
UserID string `json:"userID" gorm:"column:user_id;primary_key"` UserID string `json:"userID" gorm:"column:user_id;primary_key"`
UserName string `json:"userName" gorm:"column:user_name"` UserName string `json:"-" gorm:"column:user_name"`
LoginName string `json:"-" gorm:"column:login_name"`
DisplayName string `json:"-" gorm:"column:user_display_name"`
PasswordVerification time.Time `json:"-" gorm:"column:password_verification"` PasswordVerification time.Time `json:"-" gorm:"column:password_verification"`
MfaSoftwareVerification time.Time `json:"-" gorm:"column:mfa_software_verification"` MfaSoftwareVerification time.Time `json:"-" gorm:"column:mfa_software_verification"`
MfaSoftwareVerificationType int32 `json:"-" gorm:"column:mfa_software_verification_type"` MfaSoftwareVerificationType int32 `json:"-" gorm:"column:mfa_software_verification_type"`
@ -54,6 +56,8 @@ func UserSessionToModel(userSession *UserSessionView) *model.UserSessionView {
UserAgentID: userSession.UserAgentID, UserAgentID: userSession.UserAgentID,
UserID: userSession.UserID, UserID: userSession.UserID,
UserName: userSession.UserName, UserName: userSession.UserName,
LoginName: userSession.LoginName,
DisplayName: userSession.DisplayName,
PasswordVerification: userSession.PasswordVerification, PasswordVerification: userSession.PasswordVerification,
MfaSoftwareVerification: userSession.MfaSoftwareVerification, MfaSoftwareVerification: userSession.MfaSoftwareVerification,
MfaSoftwareVerificationType: req_model.MfaType(userSession.MfaSoftwareVerificationType), MfaSoftwareVerificationType: req_model.MfaType(userSession.MfaSoftwareVerificationType),

View File

@ -0,0 +1,6 @@
BEGIN;
ALTER TABLE auth.user_sessions ADD COLUMN user_display_name TEXT;
ALTER TABLE auth.user_sessions ADD COLUMN login_name TEXT;
COMMIT;

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,15 @@ func request_AdminService_Healthz_0(ctx context.Context, marshaler runtime.Marsh
} }
func local_request_AdminService_Healthz_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty
var metadata runtime.ServerMetadata
msg, err := server.Healthz(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty var protoReq empty.Empty
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -47,6 +56,15 @@ func request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshal
} }
func local_request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty
var metadata runtime.ServerMetadata
msg, err := server.Ready(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty var protoReq empty.Empty
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -56,6 +74,15 @@ func request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Mars
} }
func local_request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty
var metadata runtime.ServerMetadata
msg, err := server.Validate(ctx, &protoReq)
return msg, metadata, err
}
var ( var (
filter_AdminService_IsOrgUnique_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} filter_AdminService_IsOrgUnique_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
) )
@ -64,7 +91,10 @@ func request_AdminService_IsOrgUnique_0(ctx context.Context, marshaler runtime.M
var protoReq UniqueOrgRequest var protoReq UniqueOrgRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_AdminService_IsOrgUnique_0); err != nil { if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AdminService_IsOrgUnique_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
@ -73,6 +103,19 @@ func request_AdminService_IsOrgUnique_0(ctx context.Context, marshaler runtime.M
} }
func local_request_AdminService_IsOrgUnique_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq UniqueOrgRequest
var metadata runtime.ServerMetadata
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_AdminService_IsOrgUnique_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.IsOrgUnique(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgID var protoReq OrgID
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -100,6 +143,33 @@ func request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Ma
} }
func local_request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgID
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.GetOrgByID(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgSearchRequest var protoReq OrgSearchRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -117,6 +187,23 @@ func request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Ma
} }
func local_request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgSearchRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.SearchOrgs(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgSetUpRequest var protoReq OrgSetUpRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -134,6 +221,23 @@ func request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Mars
} }
func local_request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgSetUpRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.SetUpOrg(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_GetOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_GetOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyID var protoReq OrgIamPolicyID
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -161,6 +265,33 @@ func request_AdminService_GetOrgIamPolicy_0(ctx context.Context, marshaler runti
} }
func local_request_AdminService_GetOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyID
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.GetOrgIamPolicy(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_CreateOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_CreateOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyRequest var protoReq OrgIamPolicyRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -196,6 +327,41 @@ func request_AdminService_CreateOrgIamPolicy_0(ctx context.Context, marshaler ru
} }
func local_request_AdminService_CreateOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.CreateOrgIamPolicy(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_UpdateOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_UpdateOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyRequest var protoReq OrgIamPolicyRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -231,6 +397,41 @@ func request_AdminService_UpdateOrgIamPolicy_0(ctx context.Context, marshaler ru
} }
func local_request_AdminService_UpdateOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.UpdateOrgIamPolicy(ctx, &protoReq)
return msg, metadata, err
}
func request_AdminService_DeleteOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_AdminService_DeleteOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyID var protoReq OrgIamPolicyID
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -258,6 +459,261 @@ func request_AdminService_DeleteOrgIamPolicy_0(ctx context.Context, marshaler ru
} }
func local_request_AdminService_DeleteOrgIamPolicy_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq OrgIamPolicyID
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.DeleteOrgIamPolicy(ctx, &protoReq)
return msg, metadata, err
}
// RegisterAdminServiceHandlerServer registers the http handlers for service AdminService to "mux".
// UnaryRPC :call AdminServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AdminServiceServer, opts []grpc.DialOption) error {
mux.Handle("GET", pattern_AdminService_Healthz_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_Healthz_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_Healthz_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AdminService_Ready_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_Ready_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_Ready_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AdminService_Validate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_Validate_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_Validate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AdminService_IsOrgUnique_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_IsOrgUnique_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_IsOrgUnique_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AdminService_GetOrgByID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_GetOrgByID_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_GetOrgByID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AdminService_SearchOrgs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_SearchOrgs_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_SearchOrgs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AdminService_SetUpOrg_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_SetUpOrg_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_SetUpOrg_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AdminService_GetOrgIamPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_GetOrgIamPolicy_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_GetOrgIamPolicy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AdminService_CreateOrgIamPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_CreateOrgIamPolicy_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_CreateOrgIamPolicy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("PUT", pattern_AdminService_UpdateOrgIamPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_UpdateOrgIamPolicy_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_UpdateOrgIamPolicy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_AdminService_DeleteOrgIamPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AdminService_DeleteOrgIamPolicy_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AdminService_DeleteOrgIamPolicy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterAdminServiceHandlerFromEndpoint is same as RegisterAdminServiceHandler but // RegisterAdminServiceHandlerFromEndpoint is same as RegisterAdminServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done. // automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterAdminServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { func RegisterAdminServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
@ -520,27 +976,27 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu
} }
var ( var (
pattern_AdminService_Healthz_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"healthz"}, "")) pattern_AdminService_Healthz_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"healthz"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_Ready_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ready"}, "")) pattern_AdminService_Ready_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ready"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_Validate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"validate"}, "")) pattern_AdminService_Validate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"validate"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_IsOrgUnique_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_isunique"}, "")) pattern_AdminService_IsOrgUnique_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_isunique"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_GetOrgByID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"orgs", "id"}, "")) pattern_AdminService_GetOrgByID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"orgs", "id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_SearchOrgs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_search"}, "")) pattern_AdminService_SearchOrgs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_search"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_SetUpOrg_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_setup"}, "")) pattern_AdminService_SetUpOrg_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_setup"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_GetOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "")) pattern_AdminService_GetOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_CreateOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "")) pattern_AdminService_CreateOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_UpdateOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "")) pattern_AdminService_UpdateOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_AdminService_DeleteOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "")) pattern_AdminService_DeleteOrgIamPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"orgs", "org_id", "iampolicy"}, "", runtime.AssumeColonVerbOpt(true)))
) )
var ( var (

View File

@ -274,7 +274,7 @@
"200": { "200": {
"description": "A successful response.", "description": "A successful response.",
"schema": { "schema": {
"$ref": "#/definitions/protobufStruct" "type": "object"
} }
} }
}, },
@ -285,19 +285,6 @@
} }
}, },
"definitions": { "definitions": {
"protobufListValue": {
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"$ref": "#/definitions/protobufValue"
},
"description": "Repeated field of dynamically typed values."
}
},
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
},
"protobufNullValue": { "protobufNullValue": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -306,51 +293,6 @@
"default": "NULL_VALUE", "default": "NULL_VALUE",
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value." "description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
}, },
"protobufStruct": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/protobufValue"
},
"description": "Unordered map of dynamically typed values."
}
},
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
},
"protobufValue": {
"type": "object",
"properties": {
"null_value": {
"$ref": "#/definitions/protobufNullValue",
"description": "Represents a null value."
},
"number_value": {
"type": "number",
"format": "double",
"description": "Represents a double value."
},
"string_value": {
"type": "string",
"description": "Represents a string value."
},
"bool_value": {
"type": "boolean",
"format": "boolean",
"description": "Represents a boolean value."
},
"struct_value": {
"$ref": "#/definitions/protobufStruct",
"description": "Represents a structured value."
},
"list_value": {
"$ref": "#/definitions/protobufListValue",
"description": "Represents a repeated `Value`."
}
},
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
},
"v1CreateOrgRequest": { "v1CreateOrgRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -377,9 +319,6 @@
"nick_name": { "nick_name": {
"type": "string" "type": "string"
}, },
"display_name": {
"type": "string"
},
"preferred_language": { "preferred_language": {
"type": "string" "type": "string"
}, },

View File

@ -32,7 +32,6 @@ func userCreateRequestToModel(user *CreateUserRequest) *usr_model.User {
return &usr_model.User{ return &usr_model.User{
Profile: &usr_model.Profile{ Profile: &usr_model.Profile{
UserName: user.UserName, UserName: user.UserName,
DisplayName: user.DisplayName,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
NickName: user.NickName, NickName: user.NickName,

View File

@ -220,19 +220,18 @@ message CreateUserRequest {
string first_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}]; string first_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
string last_name = 3 [(validate.rules).string = {min_len: 1, max_len: 200}]; string last_name = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
string nick_name = 4 [(validate.rules).string = {max_len: 200}]; string nick_name = 4 [(validate.rules).string = {max_len: 200}];
string display_name = 5 [(validate.rules).string = {max_len: 200}]; string preferred_language = 5 [(validate.rules).string = {max_len: 200}];
string preferred_language = 6 [(validate.rules).string = {max_len: 200}]; Gender gender = 6;
Gender gender = 7; string email = 7 [(validate.rules).string = {min_len: 1, max_len: 200, email: true}];
string email = 8 [(validate.rules).string = {min_len: 1, max_len: 200, email: true}]; bool is_email_verified = 8;
bool is_email_verified = 9; string phone = 9 [(validate.rules).string = {max_len: 20}];
string phone = 11 [(validate.rules).string = {max_len: 20}]; bool is_phone_verified = 10;
bool is_phone_verified = 12; string country = 11 [(validate.rules).string = {max_len: 200}];
string country = 13 [(validate.rules).string = {max_len: 200}]; string locality = 12 [(validate.rules).string = {max_len: 200}];
string locality = 14 [(validate.rules).string = {max_len: 200}]; string postal_code = 13 [(validate.rules).string = {max_len: 200}];
string postal_code = 15 [(validate.rules).string = {max_len: 200}]; string region = 14 [(validate.rules).string = {max_len: 200}];
string region = 16 [(validate.rules).string = {max_len: 200}]; string street_address = 15 [(validate.rules).string = {max_len: 200}];
string street_address = 17 [(validate.rules).string = {max_len: 200}]; string password = 16 [(validate.rules).string = {max_len: 72}];
string password = 18 [(validate.rules).string = {max_len: 72}];
} }
message User { message User {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -520,7 +520,7 @@
"200": { "200": {
"description": "A successful response.", "description": "A successful response.",
"schema": { "schema": {
"$ref": "#/definitions/protobufStruct" "type": "object"
} }
} }
}, },
@ -531,19 +531,6 @@
} }
}, },
"definitions": { "definitions": {
"protobufListValue": {
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"$ref": "#/definitions/protobufValue"
},
"description": "Repeated field of dynamically typed values."
}
},
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
},
"protobufNullValue": { "protobufNullValue": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -552,51 +539,6 @@
"default": "NULL_VALUE", "default": "NULL_VALUE",
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value." "description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
}, },
"protobufStruct": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/protobufValue"
},
"description": "Unordered map of dynamically typed values."
}
},
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
},
"protobufValue": {
"type": "object",
"properties": {
"null_value": {
"$ref": "#/definitions/protobufNullValue",
"description": "Represents a null value."
},
"number_value": {
"type": "number",
"format": "double",
"description": "Represents a double value."
},
"string_value": {
"type": "string",
"description": "Represents a string value."
},
"bool_value": {
"type": "boolean",
"format": "boolean",
"description": "Represents a boolean value."
},
"struct_value": {
"$ref": "#/definitions/protobufStruct",
"description": "Represents a structured value."
},
"list_value": {
"$ref": "#/definitions/protobufListValue",
"description": "Represents a repeated `Value`."
}
},
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
},
"v1Gender": { "v1Gender": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -826,9 +768,6 @@
"nick_name": { "nick_name": {
"type": "string" "type": "string"
}, },
"display_name": {
"type": "string"
},
"preferred_language": { "preferred_language": {
"type": "string" "type": "string"
}, },

View File

@ -138,14 +138,14 @@ func (mr *MockAuthServiceClientMockRecorder) GetMyMfas(arg0, arg1 interface{}, a
} }
// GetMyUserAddress mocks base method // GetMyUserAddress mocks base method
func (m *MockAuthServiceClient) GetMyUserAddress(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserAddress, error) { func (m *MockAuthServiceClient) GetMyUserAddress(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserAddressView, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1} varargs := []interface{}{arg0, arg1}
for _, a := range arg2 { for _, a := range arg2 {
varargs = append(varargs, a) varargs = append(varargs, a)
} }
ret := m.ctrl.Call(m, "GetMyUserAddress", varargs...) ret := m.ctrl.Call(m, "GetMyUserAddress", varargs...)
ret0, _ := ret[0].(*grpc.UserAddress) ret0, _ := ret[0].(*grpc.UserAddressView)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -158,14 +158,14 @@ func (mr *MockAuthServiceClientMockRecorder) GetMyUserAddress(arg0, arg1 interfa
} }
// GetMyUserEmail mocks base method // GetMyUserEmail mocks base method
func (m *MockAuthServiceClient) GetMyUserEmail(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserEmail, error) { func (m *MockAuthServiceClient) GetMyUserEmail(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserEmailView, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1} varargs := []interface{}{arg0, arg1}
for _, a := range arg2 { for _, a := range arg2 {
varargs = append(varargs, a) varargs = append(varargs, a)
} }
ret := m.ctrl.Call(m, "GetMyUserEmail", varargs...) ret := m.ctrl.Call(m, "GetMyUserEmail", varargs...)
ret0, _ := ret[0].(*grpc.UserEmail) ret0, _ := ret[0].(*grpc.UserEmailView)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -178,14 +178,14 @@ func (mr *MockAuthServiceClientMockRecorder) GetMyUserEmail(arg0, arg1 interface
} }
// GetMyUserPhone mocks base method // GetMyUserPhone mocks base method
func (m *MockAuthServiceClient) GetMyUserPhone(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserPhone, error) { func (m *MockAuthServiceClient) GetMyUserPhone(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserPhoneView, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1} varargs := []interface{}{arg0, arg1}
for _, a := range arg2 { for _, a := range arg2 {
varargs = append(varargs, a) varargs = append(varargs, a)
} }
ret := m.ctrl.Call(m, "GetMyUserPhone", varargs...) ret := m.ctrl.Call(m, "GetMyUserPhone", varargs...)
ret0, _ := ret[0].(*grpc.UserPhone) ret0, _ := ret[0].(*grpc.UserPhoneView)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -198,14 +198,14 @@ func (mr *MockAuthServiceClientMockRecorder) GetMyUserPhone(arg0, arg1 interface
} }
// GetMyUserProfile mocks base method // GetMyUserProfile mocks base method
func (m *MockAuthServiceClient) GetMyUserProfile(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserProfile, error) { func (m *MockAuthServiceClient) GetMyUserProfile(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*grpc.UserProfileView, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1} varargs := []interface{}{arg0, arg1}
for _, a := range arg2 { for _, a := range arg2 {
varargs = append(varargs, a) varargs = append(varargs, a)
} }
ret := m.ctrl.Call(m, "GetMyUserProfile", varargs...) ret := m.ctrl.Call(m, "GetMyUserProfile", varargs...)
ret0, _ := ret[0].(*grpc.UserProfile) ret0, _ := ret[0].(*grpc.UserProfileView)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }

View File

@ -66,7 +66,6 @@ func updateProfileToModel(ctx context.Context, u *UpdateUserProfileRequest) *usr
FirstName: u.FirstName, FirstName: u.FirstName,
LastName: u.LastName, LastName: u.LastName,
NickName: u.NickName, NickName: u.NickName,
DisplayName: u.DisplayName,
PreferredLanguage: preferredLanguage, PreferredLanguage: preferredLanguage,
Gender: genderToModel(u.Gender), Gender: genderToModel(u.Gender),
} }

View File

@ -55,7 +55,7 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc
userInfo.FamilyName = user.LastName userInfo.FamilyName = user.LastName
userInfo.GivenName = user.FirstName userInfo.GivenName = user.FirstName
userInfo.Nickname = user.NickName userInfo.Nickname = user.NickName
userInfo.PreferredUsername = user.UserName userInfo.PreferredUsername = user.PreferredLoginName
userInfo.UpdatedAt = user.ChangeDate userInfo.UpdatedAt = user.ChangeDate
userInfo.Gender = oidc.Gender(getGender(user.Gender)) userInfo.Gender = oidc.Gender(getGender(user.Gender))
case scopePhone: case scopePhone:

Some files were not shown because too many files have changed in this diff Show More