feat: run on a single port (#3163)

* start v2

* start

* run

* some cleanup

* remove v2 pkg again

* simplify

* webauthn

* remove unused config

* fix login path in Dockerfile

* fix asset_generator.go

* health handler

* fix grpc web

* refactor

* merge

* build new main.go

* run new main.go

* update logging pkg

* fix error msg

* update logging

* cleanup

* cleanup

* go mod tidy

* change localDevMode

* fix customEndpoints

* update logging

* comments

* change local flag to external configs

* fix location generated go code

* fix

Co-authored-by: fforootd <florian@caos.ch>
This commit is contained in:
Livio Amstutz
2022-02-14 17:22:30 +01:00
committed by GitHub
parent 2f3a482ade
commit 389eb4a27a
306 changed files with 1708 additions and 1567 deletions

View File

@@ -0,0 +1,57 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "PasswordChange.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "PasswordChange.Description"}}</p>
</div>
<form action="{{ changePasswordUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields">
<div class="field">
<label class="lgn-label" for="change-old-password">{{t "PasswordChange.OldPasswordLabel"}}</label>
<input class="lgn-input" type="password" id="change-old-password" name="change-old-password"
autocomplete="current-password" autofocus required>
</div>
<div class="field">
<label class="lgn-label" for="change-new-password">{{t "PasswordChange.NewPasswordLabel"}}</label>
<input data-minlength="{{ .MinLength }}" data-has-uppercase="{{ .HasUppercase }}"
data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}"
data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="change-new-password"
name="change-new-password" autocomplete="new-password" required>
{{ .PasswordPolicyDescription }}
</div>
<div class="field">
<label class="lgn-label"
for="change-password-confirmation">{{t "PasswordChange.NewPasswordConfirmLabel"}}</label>
<input class="lgn-input" type="password" id="change-password-confirmation"
name="change-password-confirmation" autocomplete="new-password" required>
</div>
</div>
{{ template "error-message" .}}
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "PasswordChange.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button type="submit" id="change-password-button" name="resend" value="false"
class="lgn-raised-button lgn-primary">{{t "PasswordChange.NextButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/password_policy_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/change_password_check.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,22 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "PasswordChangeDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "PasswordChangeDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "PasswordChangeDone.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,39 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "UsernameChange.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "UsernameChange.Description"}}</p>
</div>
<form action="{{ changeUsernameUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="field">
<label class="lgn-label" for="username">{{t "UsernameChange.UsernameLabel"}}</label>
<input class="lgn-input" type="text" id="username" name="username" autocomplete="username" autofocus required>
</div>
{{ template "error-message" .}}
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "UsernameChange.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button type="submit" id="submit-button" value="false"
class="lgn-raised-button lgn-primary">{{t "UsernameChange.NextButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,25 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "UsernameChangeDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "UsernameChangeDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "UsernameChangeDone.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,10 @@
{{ define "error-message" }}
{{if .ErrMessage }}
<div class="lgn-error" title="{{.ErrID}}">
<i class="lgn-icon-exclamation-circle-solid lgn-warn"></i>
<p class="lgn-error-message">
{{ .ErrMessage }}
</p>
</div>
{{end}}
{{ end }}

View File

@@ -0,0 +1,12 @@
{{template "main-top" .}}
<div class="lgn-head">
<div class="lgn-error">
<i class="lgn-icon-exclamation-circle-solid lgn-warn"></i>
<p class="lgn-error-message">
{{ .ErrMessage }}{{ if .ErrID }} ({{ .ErrID }}){{end}}
</p>
</div>
</div>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,121 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "ExternalNotFoundOption.Title"}}</h1>
<p>{{t "ExternalNotFoundOption.Description"}}</p>
</div>
<form action="{{ externalNotFoundOptionUrl "none" }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" id="external-idp-config-id" name="external-idp-config-id" value="{{ .ExternalIDPID }}" />
<input type="hidden" id="external-idp-ext-user-id" name="external-idp-ext-user-id" value="{{ .ExternalIDPUserID }}" />
<input type="hidden" id="external-idp-display-name" name="external-idp-display-name" value="{{ .ExternalIDPUserDisplayName }}" />
<input type="hidden" id="external-email" name="external-email" value="{{ .ExternalEmail }}" />
<input type="hidden" id="external-email-verified" name="external-email-verified" value="{{ .ExternalEmailVerified }}" />
<input type="hidden" id="external-phone" name="external-phone" value="{{ .ExternalPhone }}" />
<input type="hidden" id="external-phone-verified" name="external-phone-verified" value="{{ .ExternalPhoneVerified }}" />
<div class="lgn-register">
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="firstname">{{t "ExternalRegistrationUserOverview.FirstnameLabel"}}</label>
<input class="lgn-input" type="text" id="firstname" name="firstname" autocomplete="given-name"
value="{{ .Firstname }}" autofocus required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="lastname">{{t "ExternalRegistrationUserOverview.LastnameLabel"}}</label>
<input class="lgn-input" type="text" id="lastname" name="lastname" autocomplete="family-name"
value="{{ .Lastname }}" required>
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="username">{{t "ExternalRegistrationUserOverview.UsernameLabel"}}</label>
<div class="lgn-suffix-wrapper">
<input class="lgn-input lgn-suffix-input" type="text" id="username" name="username"
value="{{ .Username }}" required>
{{if .DisplayLoginNameSuffix}}
<span id="default-login-suffix" lgnsuffix class="loginname-suffix">@{{.PrimaryDomain}}</span>
{{end}}
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="phone">{{t "ExternalRegistrationUserOverview.PhoneLabel"}}</label>
<input class="lgn-input" type="text" id="phone" name="phone" autocomplete="tel" value="{{ .Phone }}">
</div>
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="languages">{{t "ExternalRegistrationUserOverview.LanguageLabel"}}</label>
<select id="languages" name="language">
<option value=""></option>
<option value="de" id="de" {{if (selectedLanguage "de")}} selected {{end}}>{{t "ExternalNotFoundOption.German"}}
</option>
<option value="en" id="en" {{if (selectedLanguage "en")}} selected {{end}}>{{t "ExternalNotFoundOption.English"}}
</option>
<option value="it" id="it" {{if (selectedLanguage "it")}} selected {{end}}>{{t "ExternalNotFoundOption.Italian"}}
</option>
</select>
</div>
</div>
{{ if or .TOSLink .PrivacyLink }}
<div class="lgn-field">
<label class="lgn-label">{{t "ExternalNotFoundOption.TosAndPrivacyLabel"}}</label>
<div class="lgn-checkbox">
<input type="checkbox" id="terms-confirm"
name="terms-confirm" required>
<label for="terms-confirm">
{{t "ExternalNotFoundOption.TosConfirm"}}
{{ if .TOSLink }}
<a class="tos-link" target="_blank" href="{{ .TOSLink }}" rel="noopener noreferrer">
{{t "ExternalNotFoundOption.TosLinkText"}}
</a>
{{end}}
{{ if and .TOSLink .PrivacyLink }}
{{t "ExternalNotFoundOption.TosConfirmAnd"}}
{{ end }}
{{ if .PrivacyLink }}
<a class="tos-link" target="_blank" href="{{ .PrivacyLink}}" rel="noopener noreferrer">
{{t "ExternalNotFoundOption.PrivacyLinkText"}}
</a>
{{end}}
</label>
</div>
</div>
{{ end }}
</div>
{{template "error-message" .}}
<div class="lgn-actions">
<button class="lgn-icon-button lgn-left-action" name="resetlinking" value="true"
formnovalidate>
<i class="lgn-icon-arrow-left-solid"></i>
</button>
<button type="submit" formaction="{{ externalNotFoundOptionUrl "linkbutton"}}" class="lgn-raised-button lgn-primary" name="linkbutton" value="true">
{{t "ExternalNotFoundOption.LinkButtonText"}}
</button>
<span class="fill-space"></span>
<button type="submit" formaction="{{ externalNotFoundOptionUrl "autoregisterbutton"}}" class="lgn-raised-button lgn-primary" name="autoregisterbutton" value="true">
{{t "ExternalNotFoundOption.AutoRegisterButtonText"}}
</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/external_not_found_check.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,115 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "ExternalRegistrationUserOverview.Title"}}</h1>
<p>{{t "ExternalRegistrationUserOverview.Description"}}</p>
</div>
<form action="{{ externalRegistrationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" id="external-idp-config-id" name="external-idp-config-id" value="{{ .ExternalIDPID }}" />
<input type="hidden" id="external-idp-ext-user-id" name="external-idp-ext-user-id" value="{{ .ExternalIDPUserID }}" />
<input type="hidden" id="external-idp-display-name" name="external-idp-display-name" value="{{ .ExternalIDPUserDisplayName }}" />
<input type="hidden" id="external-email" name="external-email" value="{{ .ExternalEmail }}" />
<input type="hidden" id="external-email-verified" name="external-email-verified" value="{{ .ExternalEmailVerified }}" />
<input type="hidden" id="external-phone" name="external-phone" value="{{ .ExternalPhone }}" />
<input type="hidden" id="external-phone-verified" name="external-phone-verified" value="{{ .ExternalPhoneVerified }}" />
<div class="lgn-register">
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="firstname">{{t "ExternalRegistrationUserOverview.FirstnameLabel"}}</label>
<input class="lgn-input" type="text" id="firstname" name="firstname" autocomplete="given-name"
value="{{ .Firstname }}" autofocus required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="lastname">{{t "ExternalRegistrationUserOverview.LastnameLabel"}}</label>
<input class="lgn-input" type="text" id="lastname" name="lastname" autocomplete="family-name"
value="{{ .Lastname }}" required>
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="username">{{t "ExternalRegistrationUserOverview.UsernameLabel"}}</label>
<div class="lgn-suffix-wrapper">
<input class="lgn-input lgn-suffix-input" type="text" id="username" name="username"
value="{{ .Username }}" required>
{{if .DisplayLoginNameSuffix}}
<span id="default-login-suffix" lgnsuffix class="loginname-suffix">@{{.PrimaryDomain}}</span>
{{end}}
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="phone">{{t "ExternalRegistrationUserOverview.PhoneLabel"}}</label>
<input class="lgn-input" type="text" id="phone" name="phone" autocomplete="tel" value="{{ .Phone }}">
</div>
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="languages">{{t "ExternalRegistrationUserOverview.LanguageLabel"}}</label>
<select id="languages" name="language">
<option value=""></option>
<option value="de" id="de" {{if (selectedLanguage "de")}} selected {{end}}>{{t "ExternalRegistrationUserOverview.German"}}
</option>
<option value="en" id="en" {{if (selectedLanguage "en")}} selected {{end}}>{{t "ExternalRegistrationUserOverview.English"}}
</option>
<option value="it" id="it" {{if (selectedLanguage "it")}} selected {{end}}>{{t "ExternalRegistrationUserOverview.Italian"}}
</option>
</select>
</div>
</div>
{{ if or .TOSLink .PrivacyLink }}
<div class="lgn-field">
<label class="lgn-label">{{t "ExternalRegistrationUserOverview.TosAndPrivacyLabel"}}</label>
<div class="lgn-checkbox">
<input type="checkbox" id="register-term-confirmation"
name="register-term-confirmation" required>
<label for="register-term-confirmation">
{{t "ExternalRegistrationUserOverview.TosConfirm"}}
{{ if .TOSLink }}
<a class="tos-link" target="_blank" href="{{ .TOSLink }}" rel="noopener noreferrer">
{{t "ExternalRegistrationUserOverview.TosLinkText"}}
</a>
{{end}}
{{ if and .TOSLink .PrivacyLink }}
{{t "ExternalRegistrationUserOverview.TosConfirmAnd"}}
{{ end }}
{{ if .PrivacyLink }}
<a class="tos-link" target="_blank" href="{{ .PrivacyLink}}" rel="noopener noreferrer">
{{t "ExternalRegistrationUserOverview.PrivacyLinkText"}}
</a>
{{end}}
</label>
</div>
</div>
{{ end }}
</div>
{{template "error-message" .}}
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ registerOptionUrl }}">
{{t "ExternalRegistrationUserOverview.BackButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" id="submit-button" type="submit">{{t "ExternalRegistrationUserOverview.NextButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,18 @@
{{define "footer"}}
<footer>
{{ if hasWatermark .LabelPolicy }}
<span class="watermark" >
<span class="powered">{{t "Footer.PoweredBy"}}</span>
<span class="lgn-logo-watermark" sourcelight="logo-light.svg" sourcedark="logo-dark.svg" alt="logo"></span>
</span>
{{end}}
<span class="fill-space"></span>
{{ if .TOSLink }}
<a href="{{.TOSLink}}" rel="noopener noreferrer" target="_blank" alt="TOS">{{t "Footer.Tos"}}</a>
{{ end }}
{{ if .PrivacyLink }}
<a href="{{.PrivacyLink}}" rel="noopener noreferrer" target="_blank" alt="Privacy Policy">{{t "Footer.PrivacyPolicy"}}</a>
{{end}}
<a href="{{t "Footer.HelpLink"}}" target="_black" alt="Help">{{t "Footer.Help"}}</a>
</footer>
{{end}}

View File

@@ -0,0 +1,17 @@
{{define "header"}}
<header class="lgn-header">
{{ if hasCustomPolicy .LabelPolicy }}
{{ $logo := customLogoResource .PrivateLabelingOrgID .LabelPolicy .DarkMode }}
{{if $logo}}
<img class="lgn-logo" src="{{$logo}}" alt="Logo">
{{end}}
{{ else }}
{{if .DarkMode }}
<img class="lgn-logo" src="{{ resourceThemeUrl "logo-light.svg" .Theme }}" alt="Logo">
{{else}}
<img class="lgn-logo" src="{{ resourceThemeUrl "logo-dark.svg" .Theme }}" alt="Logo">
{{end}}
{{end}}
</header>
{{end}}

View File

@@ -0,0 +1,59 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitPassword.Title" }}</h1>
{{ template "user-profile" . }}
<p>{{t "InitPassword.Description" }}</p>
</div>
<form action="{{ initPasswordUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<div class="fields">
<div class="field">
<label class="lgn-label" for="code">{{t "InitPassword.CodeLabel"}}</label>
<input class="lgn-input" type="text" id="code" name="code" value="{{.Code}}" autocomplete="off" autofocus
required>
</div>
<div class="field">
<label class="lgn-label" for="password">{{t "InitPassword.NewPasswordLabel"}}</label>
<input data-minlength="{{ .MinLength }}" data-has-uppercase="{{ .HasUppercase }}"
data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}"
data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="password" name="password"
autocomplete="new-password" autofocus required>
{{ .PasswordPolicyDescription }}
</div>
<div class="field">
<label class="lgn-label" for="passwordconfirm">{{t "InitPassword.NewPasswordConfirmLabel"}}</label>
<input class="lgn-input" type="password" id="passwordconfirm" name="passwordconfirm"
autocomplete="new-password" autofocus required>
</div>
</div>
{{ template "error-message" .}}
<div class="lgn-actions lgn-reverse-order">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ loginUrl }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
<button type="submit" id="init-button" name="resend" value="false"
class="lgn-raised-button lgn-primary">{{t "InitPassword.NextButtonText"}}</button>
<span class="fill-space"></span>
<button type="submit" name="resend" value="true" class="lgn-stroked-button" formnovalidate>{{t "InitPassword.ResendButtonText" }}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/password_policy_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/init_password_check.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,26 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitPasswordDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "InitPasswordDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgnactions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "InitPasswordDone.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "InitPasswordDone.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,66 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitUser.Title" }}</h1>
{{ template "user-profile" . }}
<p>{{t "InitUser.Description" }}</p>
</div>
<form action="{{ initUserUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<input type="hidden" name="passwordSet" value="{{ .PasswordSet }}" />
<div class="fields">
<div class="field">
<label class="lgn-label" for="code">{{t "InitUser.CodeLabel"}}</label>
<input class="lgn-input" {{if .ErrMessage}}shake {{end}} type="text" id="code" name="code" value="{{.Code}}" autocomplete="off" autofocus
required>
</div>
{{ if not .PasswordSet }}
<div class="field">
<label class="lgn-label" for="password">{{t "InitUser.NewPasswordLabel"}}</label>
<input data-minlength="{{ .MinLength }}" data-has-uppercase="{{ .HasUppercase }}"
data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}"
data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="password" name="password"
autocomplete="new-password" autofocus required>
{{ .PasswordPolicyDescription }}
</div>
<div class="field">
<label class="lgn-label" for="passwordconfirm">{{t "InitUser.NewPasswordConfirmLabel"}}</label>
<input class="lgn-input" type="password" id="passwordconfirm" name="passwordconfirm"
autocomplete="new-password" autofocus required>
</div>
{{ end }}
</div>
{{ template "error-message" .}}
<div class="lgn-actions lgn-reverse-order">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ loginUrl }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
<button type="submit" id="init-button" name="resend" value="false"
class="lgn-primary lgn-raised-button">{{t "InitUser.NextButtonText"}}</button>
<span class="fill-space"></span>
<button type="submit" name="resend" value="true" class="lgn-stroked-button" formnovalidate>{{t "InitUser.ResendButtonText" }}</button>
</div>
</form>
{{ if not .PasswordSet }}
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/password_policy_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/init_password_check.js" }}"></script>
{{ end }}
{{template "main-bottom" .}}

View File

@@ -0,0 +1,27 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitUserDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "InitUserDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions lgn-reverse-order">
<button class="lgn-raised-button lgn-primary" type="submit">{{t "InitUserDone.NextButtonText"}}</button>
<span class="fill-space"></span>
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "InitUserDone.CancelButtonText"}}
</a>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,26 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "LinkingUsersDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "LinkingUsersDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "LinkingUsersDone.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "LinkingUsersDone.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,63 @@
{{template "main-top" .}}
<div class="lgn-head">
{{if .Linking}}
<h1>{{t "Login.TitleLinking"}}</h1>
<p>{{t "Login.DescriptionLinking"}}{{if .OrgName}} {{t "Login.MustBeMemberOfOrg" "OrgName" .OrgName}}{{end}}</p>
{{else}}
<h1>{{t "Login.Title"}}</h1>
<p>{{t "Login.Description"}}{{if .OrgName}} {{t "Login.MustBeMemberOfOrg" "OrgName" .OrgName}}{{end}}</p>
{{end}}
</div>
<form action="{{ loginNameUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
{{if hasUsernamePasswordLogin }}
<div class="fields">
<label class="lgn-label" for="loginName">{{t "Login.LoginNameLabel"}}</label>
<div class="lgn-suffix-wrapper">
<input class="lgn-input lgn-suffix-input" type="text" id="loginName" name="loginName" placeholder="{{if .OrgID }}{{t "Login.UsernamePlaceHolder"}}{{else}}{{t "Login.LoginnamePlaceHolder"}}{{end}}"
value="{{ .UserName }}" {{if .ErrMessage}}shake {{end}} autocomplete="username" autofocus required>
{{if .DisplayLoginNameSuffix}}
<span id="default-login-suffix" lgnsuffix class="loginname-suffix">@{{.PrimaryDomain}}</span>
{{end}}
</div>
</div>
{{end}}
{{template "error-message" .}}
<div class="lgn-actions lgn-reverse-order">
<button class="lgn-raised-button lgn-primary lgn-initial-focus" id="submit-button" type="submit">{{t "Login.NextButtonText"}}</button>
<span class="fill-space"></span>
{{if .LoginPolicy.AllowRegister}}
<button class="lgn-stroked-button lgn-primary" name="register" value="true" formnovalidate>{{t "Login.RegisterButtonText"}}</button>
{{end}}
</div>
{{if hasExternalLogin }}
<div class="lgn-idp-providers">
<p>{{t "Login.ExternalUserDescription"}}</p>
{{ $reqid := .AuthReqID}}
{{range $provider := .IDPProviders}}
<a href="{{ externalIDPAuthURL $reqid $provider.IDPConfigID}}"
class="lgn-idp {{idpProviderClass $provider.StylingType}}">
<span class="logo"></span>
<span class="provider-name">{{$provider.Name}}</span>
</a>
{{end}}
</div>
{{end}}
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,32 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "LoginSuccess.Title"}}</h1>
{{ template "user-profile" . }}
{{if .RedirectURI}}
<p>{{t "LoginSuccess.AutoRedirectDescription"}}</p>
</div>
<form action="{{ .RedirectURI }}" method="GET">
<input type="hidden" name="id" value="{{ .AuthReqID }}" />
{{ template "error-message" .}}
<div class="lgn-actions">
<span class="fill-space"></span>
<button id="redirect-button" class="lgn-raised-button lgn-primary">{{t "LoginSuccess.NextButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/login_success.js" }}"></script>
{{else}}
<p>{{t "LoginSuccess.RedirectedDescription"}}</p>
</div>
{{end}}
{{template "main-bottom" .}}

View File

@@ -0,0 +1,18 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "LogoutDone.Title"}}</h1>
<p> {{t "LogoutDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<div class="lgn-actions">
<span class="fill-space"></span>
<button class="primary right" type="submit">{{t "LogoutDone.LoginButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,44 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "EmailVerification.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "EmailVerification.Description"}}</p>
</div>
<form action="{{ mailVerificationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<div class="fields">
<label class="lgn-label" for="code">{{t "EmailVerification.CodeLabel"}}</label>
<input class="lgn-input" type="text" id="code" name="code" autocomplete="off" autofocus required>
</div>
{{ template "error-message" .}}
<div class="lgn-actions lgn-reverse-order">
<button type="submit" id="submit-button" name="resend" value="false"
class="lgn-primary lgn-raised-button">{{t "EmailVerification.NextButtonText"}}
</button>
<span class="fill-space"></span>
{{ if .UserID }}
<button type="submit" name="resend" value="true" class="lgn-stroked-button lgn-primary" formnovalidate>{{t "EmailVerification.ResendButtonText"}}</button>
{{ end }}
<a class="lgn-icon-button lgn-left-action" name="resetlinking" value="true" href="{{ loginUrl }}"
formnovalidate>
<i class="lgn-icon-arrow-left-solid"></i>
</a>
</div>
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,32 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "EmailVerificationDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "EmailVerificationDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "EmailVerificationDone.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">
{{if .AuthReqID }}
{{t "EmailVerificationDone.NextButtonText"}}
{{else}}
{{t "EmailVerificationDone.LoginButtonText"}}
{{end}}
</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,40 @@
{{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">
<link rel="stylesheet" href="{{ resourceThemeUrl "css/zitadel.css" .Theme }}" type="text/css">
<link rel="icon" type="image/x-icon" href="{{ resourceThemeUrl "favicon.ico" .Theme }}">
{{ if hasCustomPolicy .LabelPolicy }}
<link rel="stylesheet" href="{{ variablesCssFileUrl .PrivateLabelingOrgID .LabelPolicy}}" type="text/css">
{{ end}}
<link rel="stylesheet" href="{{ resourceThemeUrl "../../fonts/lgn-icons/css/lgn-icon-font.css" .Theme }}">
<title>{{ .Title }}</title>
<script src="{{ resourceUrl "scripts/theme.js" }}"></script>
</head>
<!-- lgn-app-background tints the background to the selected theme colors -->
<body class="lgn-app-background">
<div class="lgn-grow">
<div class="lgn-max-width-wrapper">
{{template "header" .}}
<div class="content-container">
{{end}}
<!-- here goes the content -->
{{define "main-bottom"}}
</div>
</div>
</div>
<script src="{{ resourceUrl "scripts/avatar.js" }}"></script>
</body>
<footer>
{{template "footer" .}}
</footer>
{{end}}

View File

@@ -0,0 +1,28 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitMFADone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "InitMFADone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .MFAType }}" />
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "InitMFADone.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "InitMFADone.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,61 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitMFAOTP.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "InitMFAOTP.Description"}}</p>
</div>
<form action="{{ mfaInitVerifyUrl }}" method="POST">
{{ .CSRF }}
<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 "InitMFAOTP.OTPDescription"}}</p>
<div class="lgn-qrcode" id="qrcode">
{{.QrCode}}
</div>
<div class="fields">
<div class="field">
<span class="lgn-label" for="secret">{{t "InitMFAOTP.SecretLabel"}}</span>
<div class="lgn-row">
<span id="secret"> {{.Secret}} </span>
<span class="fill-space"></span>
<button id="copy" data-copy="{{ .Secret }}" class="lgn-icon-button">
<i class="lgn-icon-clipboard"></i>
</button>
</div>
</div>
<div class="field">
<label class="lgn-label" for="code">{{t "InitMFAOTP.CodeLabel"}}</label>
<input class="lgn-input" type="text" id="code" name="code" autocomplete="off" autofocus required>
</div>
</div>
{{end}}
<div class="lgn-actions">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ mfaPromptChangeUrl .AuthReqID .MFAType }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
{{t "InitMFAOTP.CancelButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-primary lgn-raised-button" id="submit-button" type="submit">{{t "InitMFAOTP.NextButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/copy_to_clipboard.js" }}"></script>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,48 @@
{{template "main-top" .}}
<div class="head">
<h1>{{t "InitMFAU2F.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "InitMFAU2F.Description"}}</p>
</div>
<form action="{{ mfaInitU2FVerifyUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="credentialCreationData" value="{{ .CredentialCreationData }}" />
<input type="hidden" name="credentialData" />
<div class="fields">
<p class="wa-no-support lgn-error hidden">{{t "InitMFAU2F.NotSupported"}}</p>
<div class="field wa-support">
<label class="lgn-label" for="name">{{t "InitMFAU2F.TokenNameLabel"}}</label>
<input class="lgn-input" type="text" id="name" name="name" autocomplete="off" autofocus>
</div>
<div id="wa-error" class="lgn-error hidden">
<span class="cause"></span>
<span>{{t "InitMFAU2F.ErrorRetry"}}</span>
</div>
</div>
{{ template "error-message" .}}
<div class="lgn-actions">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ mfaPromptChangeUrl .AuthReqID .MFAType }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
<span class="fill-space"></span>
<a id="btn-register" class="lgn-raised-button lgn-primary wa-support">{{t "InitMFAU2F.RegisterTokenButtonText"}}</a>
</div>
</form>
<script src="{{ resourceUrl "scripts/base64.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn_register.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,41 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "InitMFAPrompt.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "InitMFAPrompt.Description"}}</p>
</div>
<form action="{{ mfaPromptUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="fields">
{{ range $provider := .MFAProviders}}
{{ $providerName := (t (printf "InitMFAPrompt.Provider%v" $provider)) }}
<div class="lgn-radio block">
<input id="{{ $provider }}" type="radio" name="provider" value="{{ $provider }}">
<label for="{{ $provider }}">{{ $providerName }}</label>
</div>
{{ end }}
</div>
<div class="lgn-actions">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ loginUrl }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
{{if not .MFARequired}}
<button class="lgn-stroked-button lgn-primary" name="skip" value="true" type="submit" formnovalidate>{{t "InitMFAPrompt.SkipButtonText"}}</button>
{{end}}
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "InitMFAPrompt.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,48 @@
{{template "main-top" .}}
<div class="head">
<h1>{{t "VerifyMFAU2F.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "VerifyMFAU2F.Description"}}</p>
</div>
<form action="{{ mfaInitU2FLoginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}"/>
<input type="hidden" name="credentialAssertionData" value="{{ .CredentialCreationData }}"/>
<input type="hidden" name="credentialData"/>
<p class="wa-no-support lgn-error hidden">{{t "VerifyMFAU2F.NotSupported"}}</p>
<div id="wa-error" class="error hidden">
<span class="cause"></span>
<span>{{t "VerifyMFAU2F.ErrorRetry"}}</span>
</div>
{{ template "error-message" .}}
<div class="lgn-actions" id="webauthn">
<span class="fill-space"></span>
<a id="btn-login" class="lgn-raised-button lgn-primary wa-support">{{t "VerifyMFAU2F.ValidateTokenButtonText"}}</a>
</div>
{{ if .MFAProviders }}
<div class="lgn-mfa-other">
<p>{{t "MFAProvider.ChooseOther"}}</p>
{{ range $provider := .MFAProviders}}
{{ $providerName := (t (printf "MFAProvider.Provider%v" $provider)) }}
<button class="lgn-stroked-button lgn-primary" type="submit" name="provider" value="{{$provider}}">{{$providerName}}</button>
{{ end }}
</div>
{{ end }}
</form>
<script src="{{ resourceUrl "scripts/base64.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn_login.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,48 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "VerifyMFAOTP.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "VerifyMFAOTP.Description"}}</p>
</div>
<form action="{{ mfaVerifyUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="mfaType" value="{{ .SelectedMFAProvider }}" />
<div class="fields">
<label class="lgn-label" for="code">{{t "VerifyMFAOTP.CodeLabel"}}</label>
<input class="lgn-input" type="text" id="code" name="code" autocomplete="off" autofocus required>
</div>
{{ template "error-message" .}}
<div class="lgn-actions">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ loginUrl }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" id="submit-button" type="submit">{{t "VerifyMFAOTP.NextButtonText"}}</button>
</div>
{{ if .MFAProviders }}
<div class="lgn-mfa-other">
<p>{{t "MFAProvider.ChooseOther"}}</p>
{{ range $provider := .MFAProviders}}
{{ $providerName := (t (printf "MFAProvider.Provider%v" $provider)) }}
<button class="lgn-stroked-button lgn-primary" type="submit" name="provider" value="{{$provider}}"
formnovalidate>{{$providerName}}</button>
{{ end }}
</div>
{{ end }}
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,43 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "Password.Title"}}</h1>
{{ template "user-profile" . }}
</div>
<form action="{{ passwordUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="loginName" value="{{ .LoginName }}" />
<div class="fields">
<label class="lgn-label" for="password">{{t "Password.PasswordLabel"}}</label>
<input class="lgn-input" type="password" id="password" name="password" autocomplete="current-password" autofocus
required {{if .ErrMessage}}shake {{end}}>
</div>
{{template "error-message" .}}
{{ if showPasswordReset }}
<a class="block" href="{{ passwordResetUrl .AuthReqID }}">
{{t "Password.ResetLinkText"}}
</a>
{{ end }}
<div class="lgn-actions">
<a href="{{ loginNameChangeUrl .AuthReqID }}">
<button class="lgn-stroked-button lgn-primary" type="button">{{t "Password.BackButtonText"}}</button>
</a>
<span class="fill-space"></span>
<button id="submit-button" class="lgn-raised-button lgn-primary right" type="submit">{{t "Password.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>

View File

@@ -0,0 +1,24 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "PasswordResetDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "PasswordResetDone.Description"}}</p>
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
{{template "error-message" .}}
<div class="lgn-actions">
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" type="submit">{{t "PasswordResetDone.NextButtonText"}}</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,44 @@
{{template "main-top" .}}
<div class="head">
<h1>{{t "Passwordless.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "Passwordless.Description"}}</p>
</div>
<form action="{{ passwordLessVerificationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}"/>
<input type="hidden" name="credentialAssertionData" value="{{ .CredentialCreationData }}"/>
<input type="hidden" name="credentialData"/>
<p class="wa-no-support lgn-error hidden">{{t "Passwordless.NotSupported"}}</p>
<div id="wa-error" class="error hidden">
<span class="cause"></span>
<span>{{t "Passwordless.ErrorRetry"}}</span>
</div>
{{ template "error-message" .}}
<div class="lgn-actions" id="webauthn">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ loginNameChangeUrl .AuthReqID }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
{{if .PasswordLogin}}
<button class="lgn-stroked-button lgn-primary" name="passwordlogin" value="true" type="submit">{{t "Passwordless.LoginWithPwButtonText"}}</button>
{{end}}
<span class="fill-space"></span>
<a id="btn-login" class="lgn-raised-button lgn-primary wa-support">{{t "Passwordless.ValidateTokenButtonText"}}</a>
</div>
</form>
<script src="{{ resourceUrl "scripts/base64.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn_login.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,25 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "PasswordlessPrompt.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "PasswordlessPrompt.DescriptionInit"}}</p>
</div>
<form action="{{ passwordlessPromptUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
<!-- position element in header -->
<a class="lgn-icon-button lgn-left-action" href="{{ loginUrl }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,52 @@
{{template "main-top" .}}
<div class="head">
<h1>{{t "PasswordlessRegistration.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "PasswordlessRegistration.Description"}}</p>
</div>
<form action="{{ passwordLessRegistrationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
<input type="hidden" name="orgID" value="{{ .OrgID }}" />
<input type="hidden" name="codeID" value="{{ .CodeID }}" />
<input type="hidden" name="code" value="{{ .Code }}" />
<input type="hidden" name="requestPlatformType" value="{{ .RequestPlatformType }}" />
<input type="hidden" name="credentialCreationData" value="{{ .CredentialCreationData }}" />
<input type="hidden" name="credentialData" />
<div class="fields">
<p class="wa-no-support lgn-error hidden">{{t "PasswordlessRegistration.NotSupported"}}</p>
{{if not .Disabled}}
<div class="field wa-support">
<label class="lgn-label" for="name" disabled="false">{{t "PasswordlessRegistration.TokenNameLabel"}}</label>
<input class="lgn-input" type="text" id="name" name="name" autocomplete="off" autofocus>
</div>
{{end}}
<div id="wa-error" class="lgn-error hidden">
<span class="cause"></span>
<span>{{t "PasswordlessRegistration.ErrorRetry"}}</span>
</div>
</div>
{{ template "error-message" .}}
<div class="lgn-actions">
<span class="fill-space"></span>
{{if not .Disabled}}
<a id="btn-register" class="lgn-raised-button lgn-primary wa-support">{{t "PasswordlessRegistration.RegisterTokenButtonText"}}</a>
{{end}}
</div>
</form>
<script src="{{ resourceUrl "scripts/base64.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn.js" }}"></script>
<script src="{{ resourceUrl "scripts/webauthn_register.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,28 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "PasswordlessRegistrationDone.Title"}}</h1>
{{ template "user-profile" . }}
<p>{{t "PasswordlessRegistrationDone.Description"}}</p>
{{if .HideNextButton }}
<p>{{t "PasswordlessRegistrationDone.DescriptionClose"}}</p>
{{end}}
</div>
<form action="{{ loginUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
{{if not .HideNextButton }}
<button class="lgn-raised-button lgn-primary" type="submit">{{t "PasswordlessRegistrationDone.NextButtonText"}}</button>
{{end}}
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,144 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "RegistrationUser.Title"}}</h1>
{{if .OrgRegister}}
<p>{{t "RegistrationUser.DescriptionOrgRegister"}}</p>
{{ else}}
<p>{{t "RegistrationUser.Description"}}</p>
{{end}}
</div>
<form action="{{ registrationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-register">
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="firstname">{{t "RegistrationUser.FirstnameLabel"}}</label>
<input class="lgn-input" type="text" id="firstname" name="firstname" autocomplete="given-name"
value="{{ .Firstname }}" autofocus required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="lastname">{{t "RegistrationUser.LastnameLabel"}}</label>
<input class="lgn-input" type="text" id="lastname" name="lastname" autocomplete="family-name"
value="{{ .Lastname }}" required>
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="email">{{t "RegistrationUser.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div>
{{if .ShowUsername}}
<div class="lgn-field double">
<label class="lgn-label" for="username">{{t "RegistrationUser.UsernameLabel"}}</label>
<div class="lgn-suffix-wrapper">
<input class="lgn-input lgn-suffix-input" type="text" id="username" name="username" autocomplete="email" value="{{ .Email }}" required>
{{if .DisplayLoginNameSuffix}}
<span id="default-login-suffix" lgnsuffix class="loginname-suffix">@{{.PrimaryDomain}}</span>
{{end}}
</div>
</div>
{{end}}
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="languages">{{t "RegistrationUser.LanguageLabel"}}</label>
<select id="languages" name="language">
<option value=""></option>
<option value="de" id="de" {{if (selectedLanguage "de")}} selected {{end}}>{{t "RegistrationUser.German"}}
</option>
<option value="en" id="en" {{if (selectedLanguage "en")}} selected {{end}}>{{t "RegistrationUser.English"}}
</option>
<option value="it" id="it" {{if (selectedLanguage "it")}} selected {{end}}>{{t "RegistrationUser.Italian"}}
</option>
</select>
</div>
<div class="lgn-field" >
<label class="lgn-label" for="genders">
{{t "RegistrationUser.GenderLabel"}}
<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 "RegistrationUser.Female"}}
</option>
<option value="2" id="male" {{if (selectedGender 2)}} selected {{end}}>{{t "RegistrationUser.Male"}}
</option>
<option value="3" id="diverse" {{if (selectedGender 3)}} selected {{end}}>{{t "RegistrationUser.Diverse"}}
</option>
</select>
</div>
</div>
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="register-password">{{t "RegistrationUser.PasswordLabel"}}</label>
<input data-minlength="{{ .MinLength }}" data-has-uppercase="{{ .HasUppercase }}"
data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}"
data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="register-password"
name="register-password" autocomplete="new-password" required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="register-password-confirmation">{{t "RegistrationUser.PasswordConfirmLabel"}}</label>
<input class="lgn-input" type="password" id="register-password-confirmation"
name="register-password-confirmation" autocomplete="new-password" required>
</div>
</div>
<div class="lgn-field">
{{ .PasswordPolicyDescription }}
</div>
{{ if or .TOSLink .PrivacyLink }}
<div class="lgn-field">
<label class="lgn-label">{{t "RegistrationUser.TosAndPrivacyLabel"}}</label>
<div class="lgn-checkbox">
<input type="checkbox" id="register-term-confirmation"
name="register-term-confirmation" required>
<label for="register-term-confirmation">
{{t "RegistrationUser.TosConfirm"}}
{{ if .TOSLink }}
<a class="tos-link" target="_blank" href="{{ .TOSLink }}" rel="noopener noreferrer">
{{t "RegistrationUser.TosLinkText"}}
</a>
{{end}}
{{ if and .TOSLink .PrivacyLink }}
{{t "RegistrationUser.TosConfirmAnd"}}
{{ end }}
{{ if .PrivacyLink }}
<a class="tos-link" target="_blank" href="{{ .PrivacyLink}}" rel="noopener noreferrer">
{{t "RegistrationUser.PrivacyLinkText"}}
</a>
{{end}}
</label>
</div>
</div>
{{ end }}
</div>
{{template "error-message" .}}
<div class="lgn-actions">
<a class="lgn-stroked-button lgn-primary" href="{{ loginNameChangeUrl .AuthReqID }}">
{{t "RegistrationUser.BackButtonText"}}
</a>
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" id="register-button" type="submit">{{t "RegistrationUser.NextButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/password_policy_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/register_check.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,45 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "RegisterOption.Title"}}</h1>
<p>{{t "RegisterOption.Description"}}</p>
</div>
<form action="{{ registerOptionUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-actions">
<a class="lgn-icon-button lgn-left-action" href="{{ loginNameChangeUrl .AuthReqID }}">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
</div>
<div class="lgn-register-options">
{{if .LoginPolicy.AllowUsernamePassword }}
<button class="lgn-raised-button lgn-primary" name="usernamepassword" value="true"
formnovalidate>{{t "RegisterOption.RegisterUsernamePasswordButtonText"}}</button>
{{end}}
{{if hasExternalLogin}}
<p>{{t "RegisterOption.ExternalLoginDescription"}}</p>
{{ $reqid := .AuthReqID}}
{{range $provider := .IDPProviders}}
<a href="{{ externalIDPRegisterURL $reqid $provider.IDPConfigID}}"
class="lgn-idp {{idpProviderClass $provider.StylingType}}">
<span class="logo"></span>
<span class="provider-name">{{$provider.Name}}</span>
</a>
{{end}}
{{end}}
</div>
{{template "error-message" .}}
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,112 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "RegistrationOrg.Title"}}</h1>
<p>{{t "RegistrationOrg.Description"}}</p>
</div>
<form action="{{ orgRegistrationUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-register">
<div class="lgn-field">
<label class="lgn-label" for="orgname">{{t "RegistrationOrg.OrgNameLabel"}}</label>
<input class="lgn-input" type="text" id="orgname" name="orgname" value="{{ .RegisterOrgName }}" autofocus
required>
</div>
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="firstname">{{t "RegistrationOrg.FirstnameLabel"}}</label>
<input class="lgn-input" type="text" id="firstname" name="firstname" autocomplete="given-name"
value="{{ .Firstname }}" required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="lastname">{{t "RegistrationOrg.LastnameLabel"}}</label>
<input class="lgn-input" type="text" id="lastname" name="lastname" autocomplete="family-name"
value="{{ .Lastname }}" required>
</div>
</div>
{{if .UserLoginMustBeDomain}}
<div class="lgn-field">
<label class="lgn-label" for="username">{{t "RegistrationOrg.UsernameLabel"}}</label>
<span id="loginname">
<div class="lgn-suffix-wrapper">
<input data-iam-domain="{{ .IamDomain }}" class="lgn-input lgn-suffix-input" type="text" id="username" name="username"
value="{{ .Username }}" autofocus required>
<!-- suffix requires parent div 'lgn-suffix-wrapper', corresponding input class 'lgn-suffix-input' and its id="default-login-suffix" as well as an offset script -->
<span id="default-login-suffix" lgnSuffix class="loginname-suffix"></span>
</div>
</span>
</div>
{{end}}
<div class="lgn-field">
<label class="lgn-label" for="email">{{t "RegistrationOrg.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}"
autofocus required>
</div>
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="register-password">{{t "RegistrationOrg.PasswordLabel"}}</label>
<input data-minlength="{{ .MinLength }}" data-has-uppercase="{{ .HasUppercase }}"
data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}"
data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="register-password"
name="register-password" autocomplete="new-password" required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="register-password-confirmation">{{t "RegistrationOrg.PasswordConfirmLabel"}}</label>
<input class="lgn-input" type="password" id="register-password-confirmation"
name="register-password-confirmation" autocomplete="new-password" required>
</div>
</div>
<div class="lgn-field">
{{ .PasswordPolicyDescription }}
</div>
{{ if or .TOSLink .PrivacyLink }}
<div class="lgn-field">
<label class="lgn-label" for="register-term-confirmation">{{t "RegistrationOrg.TosAndPrivacyLabel"}}</label>
<div class="lgn-checkbox">
<input class="lgn-input" type="checkbox" id="register-term-confirmation"
name="register-term-confirmation" required>
<label class="lgn-label" for="register-term-confirmation">
{{t "RegistrationOrg.TosConfirm"}}
{{ if .TOSLink }}
<a class="tos-link" target="_blank" href="{{.TOSLink}}" rel="noopener noreferrer">{{t "RegistrationOrg.TosLinkText"}}</a>
{{end}}
{{ if and .TOSLink .PrivacyLink }}
{{t "RegistrationOrg.TosConfirmAnd"}}
{{end}}
{{ if .PrivacyLink }}
<a class="tos-link" target="_blank" href="{{.PrivacyLink}}" rel="noopener noreferrer">
{{t "RegistrationOrg.PrivacyLinkText"}}
</a>
{{end}}
</label>
</div>
</div>
{{ end }}
</div>
{{template "error-message" .}}
<div class="lgn-actions">
<span class="fill-space"></span>
<button class="lgn-raised-button lgn-primary" id="register-button" type="submit">{{t "RegistrationOrg.SaveButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/password_policy_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/register_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/loginname_suffix.js" }}"></script>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,68 @@
{{template "main-top" .}}
<div class="lgn-head">
{{if .Linking}}
<h1>{{t "SelectAccount.TitleLinking"}}</h1>
<p>{{t "SelectAccount.DescriptionLinking"}}{{if .OrgName}}
{{t "SelectAccount.MustBeMemberOfOrg" "OrgName" .OrgName}}{{end}}</p>
{{else}}
<h1>{{t "SelectAccount.Title"}}</h1>
<p>{{t "SelectAccount.Description"}}{{if .OrgName}}
{{t "SelectAccount.MustBeMemberOfOrg" "OrgName" .OrgName}}
{{end}}
</p>
{{end}}
</div>
<form action="{{ userSelectionUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<div class="lgn-account-selection">
{{ if .Users }}
{{ $displayLoginNameSuffix := and .OrgID (not .DisplayLoginNameSuffix)}}
{{ $orgName := .OrgName }}
{{ range $user := .Users }}
{{ $sessionState := (printf "SelectAccount.SessionState%v" $user.UserSessionState) }}
{{if $user.SelectionPossible}}
<button type="submit" name="userID" value="{{$user.UserID}}" class="lgn-account"
{{if not $user.SelectionPossible}}disabled title="{{t "Errors.User.NotAllowedOrg"}}"{{end}}>
<div class="left">
<div class="lgn-avatar" {{if not $user.AvatarKey}}loginname="{{$user.LoginName}}"{{end}}>
{{if $user.AvatarKey}}
<img class="avatar-img" src="{{ avatarResource $user.ResourceOwner $user.AvatarKey }}" alt="user-avatar">
{{else}}
<span class="initials">A</span>
{{end}}
</div>
</div>
<div class="lgn-names">
<p class="lgn-displayname">{{$user.DisplayName}}</p>
<p class="lgn-loginname">{{if and $displayLoginNameSuffix $user.SelectionPossible}}{{$user.UserName}}{{else}}{{$user.LoginName}}{{end}}</p>
<p class="lgn-session-state i{{$user.UserSessionState}}">{{t $sessionState}}</p>
</div>
<span class="fill-space"></span>
<i class="lgn-icon-angle-right-solid"></i>
</button>
{{ end }}
{{ end }}
{{ end }}
<button type="submit" name="userID" value="0" class="lgn-account">
<div class="left">
<div class="lgn-avatar transparent">
<i class="lgn-icon-user-plus-solid"></i>
</div>
</div>
<div class="lgn-names">
<p>{{t "SelectAccount.OtherUser"}}</p>
</div>
<span class="fill-space"></span>
<i class="lgn-icon-angle-right-solid"></i>
</button>
</div>
</form>
{{template "main-bottom" .}}

View File

@@ -0,0 +1,22 @@
{{define "user-profile"}}
{{if or .LoginName .UserName}}
<div class="lgn-login-profile">
<div class="lgn-profile-image"></div>
<div class="lgn-names">
<div class="inline-block">
<div class="lgn-avatar lgn-primary" {{if not .AvatarKey}}loginname="{{.LoginName}}"{{end}}>
{{if .AvatarKey}}
<img class="avatar-img" src="{{ avatarResource .OrgID .AvatarKey }}" alt="user-avatar">
{{else}}
<span class="initials lgn-primary">A</span>
{{end}}
</div>
</div>
<div class="lgn-loginname">
<p>{{if .DisplayLoginNameSuffix}}{{.LoginName}}{{else}}{{.UserName}}{{end}}</p>
</div>
</div>
</div>
{{end}}
{{end}}