feat: Login, OP Support and Auth Queries (#177)

* fix: change oidc config

* fix: change oidc config secret

* begin models

* begin repo

* fix: implement grpc app funcs

* fix: add application requests

* fix: converter

* fix: converter

* fix: converter and generate clientid

* fix: tests

* feat: project grant aggregate

* feat: project grant

* fix: project grant check if role existing

* fix: project grant requests

* fix: project grant fixes

* fix: project grant member model

* fix: project grant member aggregate

* fix: project grant member eventstore

* fix: project grant member requests

* feat: user model

* begin repo

* repo models and more

* feat: user command side

* lots of functions

* user command side

* profile requests

* commit before rebase on user

* save

* local config with gopass and more

* begin new auth command (user centric)

* Update internal/user/model/user.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/address.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/address.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/email.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/email.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/email.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/mfa.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/mfa.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/password.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/password.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/password.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/phone.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/phone.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/phone.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/user.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/user.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/model/user.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/usergrant/repository/eventsourcing/model/user_grant.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/usergrant/repository/eventsourcing/model/user_grant.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/usergrant/repository/eventsourcing/user_grant.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/user_test.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* Update internal/user/repository/eventsourcing/eventstore_mock_test.go

Co-Authored-By: Livio Amstutz <livio.a@gmail.com>

* changes from mr review

* save files into basedir

* changes from mr review

* changes from mr review

* move to auth request

* Update internal/usergrant/repository/eventsourcing/cache.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/usergrant/repository/eventsourcing/cache.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* changes requested on mr

* fix generate codes

* fix return if no events

* password code

* email verification step

* more steps

* lot of mfa

* begin tests

* more next steps

* auth api

* auth api (user)

* auth api (user)

* auth api (user)

* differ requests

* merge

* tests

* fix compilation error

* mock for id generator

* Update internal/user/repository/eventsourcing/model/password.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/user/repository/eventsourcing/model/user.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* requests of mr

* check email

* begin separation of command and query

* otp

* change packages

* some cleanup and fixes

* tests for auth request / next steps

* add VerificationLifetimes to config and make it run

* tests

* fix code challenge validation

* cleanup

* fix merge

* begin view

* repackaging tests and configs

* fix startup config for auth

* add migration

* add PromptSelectAccount

* fix copy / paste

* remove user_agent files

* fixes

* fix sequences in user_session

* token commands

* token queries and signout

* fix

* fix set password test

* add token handler and table

* handle session init

* add session state

* add user view test cases

* change VerifyMyMfaOTP

* some fixes

* fix user repo in auth api

* cleanup

* add user session view test

* fix merge

* begin oidc

* user agent and more

* config

* keys

* key command and query

* add login statics

* key handler

* start login

* login handlers

* lot of fixes

* merge oidc

* add missing exports

* add missing exports

* fix some bugs

* authrequestid in htmls

* getrequest

* update auth request

* fix userid check

* add username to authrequest

* fix user session and auth request handling

* fix UserSessionsByAgentID

* fix auth request tests

* fix user session on UserPasswordChanged and MfaOtpRemoved

* fix MfaTypesSetupPossible

* handle mfa

* fill username

* auth request query checks new events

* fix userSessionByIDs

* fix tokens

* fix userSessionByIDs test

* add user selection

* init code

* user code creation date

* add init user step

* add verification failed types

* add verification failures

* verify init code

* user init code handle

* user init code handle

* fix userSessionByIDs

* update logging

* user agent cookie

* browserinfo from request

* add DeleteAuthRequest

* add static login files to binary

* add login statik to build

* move generate to separate file and remove statik.go files

* remove static dirs from startup.yaml

* generate into separate namespaces

* merge master

* auth request code

* auth request type mapping

* fix keys

* improve tokens

* improve register and basic styling

* fix ailerons font

* improve password reset

* add audience to token

* all oidc apps as audience

* fix test nextStep

* fix email texts

* remove "not set"

* lot of style changes

* improve copy to clipboard

* fix footer

* add cookie handler

* remove placeholders

* fix compilation after merge

* fix auth config

* remove comments

* typo

* use new secrets store

* change default pws to match default policy

* fixes

* add todo

* enable login

* fix db name

* Auth queries (#179)

* my usersession

* org structure/ auth handlers

* working user grant spooler

* auth internal user grants

* search my project orgs

* remove permissions file

* my zitadel permissions

* my zitadel permissions

* remove unused code

* authz

* app searches in view

* token verification

* fix user grant load

* fix tests

* fix tests

* read configs

* remove unused const

* remove todos

* env variables

* app_name

* working authz

* search projects

* global resourceowner

* Update internal/api/auth/permissions.go

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

* Update internal/api/auth/permissions.go

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

* model2 rename

* at least it works

* check token expiry

* search my user grants

* remove token table from authz

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

* fix test

* fix ports and enable console

Co-authored-by: Fabiennne <fabienne.gerschwiler@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
This commit is contained in:
Livio Amstutz
2020-06-05 07:50:04 +02:00
committed by GitHub
parent 46b60a6968
commit 8a5badddf6
293 changed files with 14189 additions and 3176 deletions

View File

@@ -0,0 +1,32 @@
{{template "main-top" .}}
<h1>{{t "PasswordChange.Title"}}</h1>
<p>{{t "PasswordChange.Description"}}</p>
<form action="{{ changePasswordUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields">
<div class="field">
<label class="label" for="old_password">{{t "PasswordChange.OldPassword"}}</label>
<input class="input" type="password" id="old_password" name="old_password" autocomplete="current-password" autofocus required>
</div>
<div class="field">
<label class="label" for="new_password">{{t "PasswordChange.NewPassword"}}</label>
<input class="input" type="password" id="new-password" name="new_password" autocomplete="new-password" required>
</div>
</div>
{{ template "error-message" .}}
<div class="actions">
<button type="submit" name="resend" value="false" class="primary right" >{{t "Actions.Next"}}</buttontype="submit">
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,19 @@
{{template "main-top" .}}
<h1>{{t "PasswordChangeDone.Title"}}</h1>
<p>{{t "PasswordChangeDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,9 @@
{{ define "error-message" }}
{{if .ErrMessage }}
<div class="field">
<div class="error">
{{ if .ErrType }}{{ .ErrType }} - {{end}}{{ .ErrMessage }}
</div>
</div>
{{end}}
{{ end }}

View File

@@ -0,0 +1,9 @@
{{template "main-top" .}}
<div>
{{ .ErrType }}
{{ .ErrMessage }}
</div>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,3 @@
{{define "footer"}}
{{end}}

View File

@@ -0,0 +1,3 @@
{{define "header"}}
<div class="logo"></div>
{{end}}selec

View File

@@ -0,0 +1,37 @@
{{template "main-top" .}}
<h1>{{t "InitPassword.Title" }}</h1>
<p>{{t "InitPassword.Description" }}</p>
<form action="{{ initPasswordUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<div class="fields">
<div class="field">
<label class="label" for="code">{{t "InitPassword.Code"}}</label>
<input class="input" type="text" id="code" name="code" value="{{.Code}}" autocomplete="off" autofocus required>
</div>
<div class="field">
<label class="label" for="password">{{t "InitPassword.NewPassword"}}</label>
<input class="input" type="password" id="password" name="password" autocomplete="new-password" autofocus required>
</div>
<div class="field">
<label class="label" for="passwordconfirm">{{t "InitPassword.NewPasswordConfirm"}}</label>
<input class="input" type="password" id="passwordconfirm" name="passwordconfirm" autocomplete="new-password" autofocus required>
</div>
</div>
{{ template "error-message" .}}
<div class="actions">
<button type="submit" name="resend" value="false" class="primary right" >{{t "Actions.Next"}}</buttontype="submit">
<button type="submit" name="resend" value="true" class="secondary right" formnovalidate>{{t "Actions.Resend" }}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,17 @@
{{template "main-top" .}}
<h1>{{t "PasswordSetDone.Title"}}</h1>
<p>{{t "PasswordSetDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,37 @@
{{template "main-top" .}}
<h1>{{t "InitUser.Title" }}</h1>
<p>{{t "InitUser.Description" }}</p>
<form action="{{ initUserUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<div class="fields">
<div class="field">
<label class="label" for="code">{{t "InitUser.Code"}}</label>
<input class="input" type="text" id="code" name="code" value="{{.Code}}" autocomplete="off" autofocus required>
</div>
<div class="field">
<label class="label" for="password">{{t "InitUser.NewPassword"}}</label>
<input class="input" type="password" id="password" name="password" autocomplete="new-password" autofocus required>
</div>
<div class="field">
<label class="label" for="passwordconfirm">{{t "InitUser.NewPasswordConfirm"}}</label>
<input class="input" type="password" id="passwordconfirm" name="passwordconfirm" autocomplete="new-password" autofocus required>
</div>
</div>
{{ template "error-message" .}}
<div class="actions">
<button type="submit" name="resend" value="false" class="primary right" >{{t "Actions.Next"}}</buttontype="submit">
<button type="submit" name="resend" value="true" class="secondary right" formnovalidate>{{t "Actions.Resend" }}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,17 @@
{{template "main-top" .}}
<h1>{{t "InitUserDone.Title"}}</h1>
<p>{{t "InitUserDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,27 @@
{{template "main-top" .}}
<h1>{{t "Login.Title"}}</h1>
<p>{{t "Login.Description"}}</p>
<form action="{{ usernameUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields">
<div class="field">
<label class="label" for="username">{{t "Login.Username"}}</label>
<input class="input" type="text" id="username" name="username" value="{{ .UserName }}" autocomplete="username" autofocus required>
</div>
</div>
{{template "error-message" .}}
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a class="default right" href="{{ registerUrl .AuthReqID }}" >{{t "Actions.Register"}}</a>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,15 @@
{{template "main-top" .}}
<h1>{{t "LogoutDone.Title"}}</h1>
<p>{{t "LogoutDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Login"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,31 @@
{{template "main-top" .}}
<h1>{{t "EmailVerification.Title"}}</h1>
<p>{{t "EmailVerification.Description"}}</p>
<form action="{{ mailVerificationUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<div class="fields">
<div class="field">
<label class="label" for="code">{{t "EmailVerification.Code"}}</label>
<input class="input" type="text" id="code" name="code" autocomplete="off" autofocus required>
</div>
</div>
{{ template "error-message" .}}
<div class="actions">
<button type="submit" name="resend" value="false" class="primary right" >{{t "Actions.Next"}}</buttontype="submit">
{{ if .UserID }}
<button type="submit" name="resend" value="true" class="secondary right" formnovalidate>{{t "Actions.Resend"}}</button>
{{ end }}
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,19 @@
{{template "main-top" .}}
<h1>{{t "EmailVerificationDone.Title"}}</h1>
<p>{{t "EmailVerificationDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="primary right" type="submit">{{if .AuthReqID }}{{t "Actions.Next"}}{{else}}{{t "Actions.Login"}}{{end}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,34 @@
{{define "main-top"}}
<!DOCTYPE html>
<html lang="{{ .Lang }}" class="{{.ThemeMode}}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{{if .ThemeMode}}
<link rel="stylesheet" href="{{ resourceThemeUrl (printf "css/%s.css" .ThemeMode) .Theme }}" type="text/css" media="all">
{{else}}
<link rel="stylesheet" href="{{ resourceThemeUrl "css/dark.css" .Theme }}" type="text/css" media="(prefers-color-scheme: dark), (prefers-color-scheme: no-preference)">
<link rel="stylesheet" href="{{ resourceThemeUrl "css/light.css" .Theme }}" type="text/css" media="(prefers-color-scheme: light)">
{{end}}
<link rel="icon" type="image/x-icon" href="{{ resourceThemeUrl "favicon.ico" .Theme }}">
<title>{{ .Title }}</title>
</head>
<body>
<header>
{{template "header" .}}
</header>
<div class="content">
{{end}}
<!-- here goes the content -->
{{define "main-bottom"}}
</div>
</body>
<footer>
{{template "footer" .}}
</footer>
{{end}}

View File

@@ -0,0 +1,19 @@
{{template "main-top" .}}
<h1>{{t "MfaInitDone.Title"}}</h1>
<p>{{t "MfaInitDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .MfaType }}" />
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,47 @@
{{template "main-top" .}}
<h1>{{t "MfaInitVerify.Title"}}</h1>
<p>{{t "MfaInitVerify.Description"}}</p>
<form action="{{ mfaInitVerifyUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .MfaType }}" />
<input type="hidden" name="url" value="{{ .Url }}" />
<input type="hidden" name="secret" value="{{ .Secret }}" />
{{if (eq .MfaType 0) }}
<p>{{t "MfaInitVerify.OtpDescription"}}</p>
<div id="qrcode">
{{.QrCode}}
</div>
<div class="fields">
<div class="field">
<span class="label" for="secret">{{t "MfaInitVerify.Secret"}}</span>
<span class="input" id="secret">
{{.Secret}}
<span class="copy material-icons" onclick="copyToClipboard('{{ .Secret }}')">content_copy</span>
</span>
</div>
<div class="field">
<label class="label" for="code">{{t "MfaInitVerify.Code"}}</label>
<input class="input" type="text" id="code" name="code" autocomplete="off" autofocus required>
</div>
</div>
{{end}}
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
<script>
const copyToClipboard = str => {
navigator.clipboard.writeText(str);
}
</script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,30 @@
{{template "main-top" .}}
<h1>{{t "MfaPrompt.Title"}}</h1>
<form action="{{ mfaPromptUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields">
{{ range $provider := .MfaProviders}}
{{ $providerName := (t (printf "MfaPrompt.Provider%v" $provider)) }}
<div class="field radio-button">
<input id="{{ $provider }}" type="radio" name="provider" value="{{ $provider }}">
<label for="{{ $provider }}">{{ $providerName }}</label>
</div>
{{ end }}
</div>
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
{{if not .MfaRequired}}
<button class="default right" name="skip" value="true" type="submit" formnovalidate>{{t "Actions.Skip"}}</button>
{{end}}
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,28 @@
{{template "main-top" .}}
<h1>{{t "MfaVerify.Title"}}</h1>
<p>{{t "MfaVerify.Description"}}</p>
<form action="{{ mfaVerifyUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .SelectedMfaProvider }}" />
<div class="fields">
<div class="field">
<label class="label" for="code">{{t "MfaVerify.Code"}}</label>
<input class="input" type="text" id="code" name="code" autocomplete="off" autofocus required>
</div>
</div>
{{ template "error-message" .}}
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,33 @@
{{template "main-top" .}}
<h1>{{t "Password.Title"}}</h1>
<form action="{{ passwordUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="username" value="{{ .UserName }}" />
<div class="fields">
<div class="field">
<label class="label" for="password">{{t "Password.Password"}}</label>
<input class="input" type="password" id="password" name="password" autocomplete="current-password" autofocus required>
</div>
</div>
{{template "error-message" .}}
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
<a href="{{ usernameChangeUrl .AuthReqID }}">
<button class="secondary" type="button">{{t "Actions.Back"}}</button>
</a>
<a href="{{ passwordResetUrl .AuthReqID }}">
<button class="secondary" type="button">{{t "Actions.ForgotPassword"}}</button>
</a>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,17 @@
{{template "main-top" .}}
<h1>{{t "PasswordResetDone.Title"}}</h1>
<p>{{t "PasswordResetDone.Description"}}</p>
<form action="{{ loginUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,61 @@
{{template "main-top" .}}
<h1>{{t "Registration.Title"}}</h1>
<p>{{t "Registration.Description"}}</p>
<form action="{{ registrationUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields">
<div class="field">
<label class="label" for="email">{{t "Registration.Email"}}</label>
<input class="input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" autofocus required>
</div>
<div class="field">
<label class="label" for="firstname">{{t "Registration.Firstname"}}</label>
<input class="input" type="text" id="firstname" name="firstname" autocomplete="given-name" value="{{ .Firstname }}" required>
</div>
<div class="field">
<label class="label" for="lastname">{{t "Registration.Lastname"}}</label>
<input class="input" type="text" id="lastname" name="lastname" autocomplete="family-name" value="{{ .Lastname }}" required>
</div>
<div class="field">
<label class="label" for="languages">{{t "Registration.Language"}}</label>
<select id="languages" name="language">
<option value=""></option>
<option value="de" id="de" {{if (selectedLanguage "de")}} selected {{end}}>{{t "Registration.German"}}</option>
<option value="en" id="en" {{if (selectedLanguage "en")}} selected {{end}}>{{t "Registration.English"}}</option>
</select>
</div>
<div class="field">
<label class="label" for="genders">
{{t "Registration.Gender"}}
<span class="optional">{{t "optional"}}</span>
</label>
<select id="genders" name="gender">
<option value=""></option>
<option value="1" id="female" {{if (selectedGender 1)}} selected {{end}}>{{t "Registration.Female"}}</option>
<option value="2" id="male" {{if (selectedGender 2)}} selected {{end}}>{{t "Registration.Male"}}</option>
<option value="3" id="diverse" {{if (selectedGender 3)}} selected {{end}}>{{t "Registration.Diverse"}}</option>
</select>
</div>
<div class="field">
<label class="label" for="password">{{t "Registration.Password"}}</label>
<input class="input" type="password" id="password" name="password" autocomplete="new-password" required>
</div>
<div class="field">
<label class="label" for="password2">{{t "Registration.Password2"}}</label>
<input class="input" type="password" id="password2" name="password2" autocomplete="new-password" required>
</div>
</div>
{{template "error-message" .}}
<div class="actions">
<button class="primary right" type="submit">{{t "Actions.Next"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,25 @@
{{template "main-top" .}}
<h1>{{t "UserSelection.Title"}}</h1>
<p>{{t "UserSelection.Description"}}</p>
<form action="{{ userSelectionUrl }}" method="POST">
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="actions">
{{ range $user := .Users }}
{{ $sessionState := (t (printf "UserSelection.SessionState%v" $user.UserSessionState)) }}
<button type="submit" name="userID" value="{{$user.UserID}}" class="primary">
<span class="username">{{$user.UserName}}</span>
<span class="sessionstate">({{$sessionState}})</span>
</button>
{{ end }}
<button type="submit" name="userID" value="0" class="primary">{{t "UserSelection.OtherUser"}}</button>
</div>
</form>
{{template "main-bottom" .}}