Merge branch '2021.3.x-auth-ui-redesign' into 2021.3.x

This commit is contained in:
Denis Arh
2021-03-06 16:45:39 +01:00
30 changed files with 502 additions and 430 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 890 KiB

+11 -9
View File
@@ -1,10 +1,12 @@
// placeholder
$(function () {
$('.toast').toast('show');
function buttonDisabler() {
setTimeout(function() {
let bb = document.getElementsByTagName('button')
for (let i = 0; i < bb.length; i++) {
bb[i].disabled = true
}
}, 100)
}
$('form').not('do-not-disable-buttons-on-submit').on('submit', function() {
let form = this
setTimeout(function() {
$('button, input[type=submit]', form)
.not('do-not-disable-on-submit')
.attr('disabled', true)
}, 50)
})
})
+61 -29
View File
@@ -1,39 +1,24 @@
:root {
--primary: #568ba2;
--primary: #4D7281;
--primary-hover: #497689;
--light: #E4E9EF;
--danger: #E54122;
--body-margin: 50px;
}
html {
overflow: hidden;
}
html,
body {
height: 100%;
}
body {
overflow: scroll;
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
padding-top: 150px;
padding-bottom: 100px;
background: rgb(17, 25, 31);
}
body::before {
content: "";
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.23);
margin: var(--body-margin) 0;
font-family: 'Nunito', sans-serif;
height: calc(100vh - 2 * var(--body-margin));
}
.logo {
height: 30px;
height: 45px;
}
.version {
@@ -41,15 +26,28 @@ body::before {
right: 0;
}
.user {
top: 0;
right: 0;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6, label, .btn, a {
font-weight: 600;
}
/* over-ride default variables colors */
a {
color: var(--primary);
a, label, .text-primary {
color: var(--primary) !important;
}
a:hover {
color: var(--primary-hover);
}
.text-danger {
color: var(--danger) !important;
}
.card,
.card-header {
border-radius: 1rem;
@@ -66,10 +64,32 @@ a:hover {
border-color: var(--primary-hover);
}
.btn-light,
.bg-light,
.badge-light {
background-color: var(--light)!important;
border-color: var(--light);
}
.btn-danger,
.bg-danger {
background-color: var(--danger)!important;
border-color: var(--danger);
}
.btn-lg {
font-size: 1rem;
}
/* Navigation */
.nav-item.active {
border-bottom: 4px solid var(--primary);
}
/* form styling*/
.form-control,
.input-group-text {
border-radius: 0;
.form-control {
border: 2px solid var(--light);
padding: 1.25rem 0.75rem;
}
.form-control:focus {
@@ -79,6 +99,18 @@ a:hover {
.auth {
width: 100%;
max-width: 750px;
max-width: 650px;
margin: auto;
padding: 0 20px;
}
.footer {
bottom: 0;
z-index: -1;
}
/* position bootstrap icons on buttons centrally */
[class^="bi-"]::before, [class*=" bi-"]::before {
vertical-align: middle;
line-height: 1.6;
}
@@ -1,42 +1,35 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
{{ template "inc_header.html.tpl" set . "activeNav" "clients" }}
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Authorized clients</h4>
<form
method="POST"
class="clearfix"
action="{{ links.AuthorizedClients }}"
onsubmit="buttonDisabler()"
class="p-3"
>
<h4 class="card-title">Authorized clients</h4>
{{ .csrfField }}
{{ range .authorizedClients}}
<div class="card-body bg-light">
<div class="row">
<div class="col-9">
{{ .Name }}
<div class="small">
Authorized on
<time
datetime="{{ .ConfirmedAt | date "2006-01-02T15:04:05Z07:00" }}"
>
{{ .ConfirmedAt | date "Mon, 02 Jan 2006 15:04 MST" }}
</time>
</div>
</div>
<div class="col-3 text-right">
<button
type="submit"
name="revoke"
value="{{ .ID }}"
class="btn btn-sm btn-link text-danger"
>
Revoke access
</button>
</div>
</div>
</div>
<div class="p-3">
<div class="text-primary font-weight-bold">{{ .Name }}</div>
<div>
Authorized on
<time
datetime="{{ .ConfirmedAt | date "2006-01-02T15:04:05Z07:00" }}"
>
{{ .ConfirmedAt | date "Mon, 02 Jan 2006 15:04 MST" }}
</time>
</div>
<button
type="submit"
name="revoke"
value="{{ .ID }}"
class="btn btn-sm btn-danger"
>
Revoke access
</button>
</div>
{{ else }}
<div class="text-center m-3">
<i>No authorized clients found</i>
+20 -21
View File
@@ -1,22 +1,21 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Change your password</h4>
{{ template "inc_header.html.tpl" set . "activeNav" "security" }}
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Change your password</h4>
<form
method="POST"
action="{{ links.ChangePassword }}"
onsubmit="buttonDisabler()"
class="p-3"
>
{{ .csrfField }}
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger font-weight-bold mb-3" role="alert">
{{ .form.error }}
</div>
{{ end }}
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-envelope"></i>
</span>
<div class="mb-3">
<label>
E-mail *
</label>
<input
type="email"
class="form-control"
@@ -26,34 +25,34 @@
value="{{ .user.Email }}"
aria-label="Email">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-key-fill"></i>
</span>
<div class="mb-3">
<label>
Old Password *
</label>
<input
type="password"
required
class="form-control"
name="oldPassword"
autocomplete="current-password"
placeholder="Old password"
placeholder="Enter your old password"
aria-label="Old password">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-key-fill"></i>
</span>
<div class="mb-3">
<label>
New Password *
</label>
<input
type="password"
required
class="form-control"
name="newPassword"
autocomplete="new-password"
placeholder="New password"
placeholder="Enter your new password"
aria-label="New password">
</div>
<div class="text-right">
<button class="btn btn-primary btn-block" type="submit">Change your password</button>
<button class="btn btn-primary btn-block btn-lg" type="submit">Change your password</button>
</div>
</form>
</div>
@@ -1,7 +1,7 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
<h4 class="card-title">Internal error</h4>
<div class="alert alert-danger" role="alert">
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Internal error</h4>
<div class="text-danger mb-4 font-weight-bold p-3" role="alert">
{{ .error }}
</div>
</div>
@@ -1,5 +0,0 @@
{{ range . }}
<div class="alert alert-{{ .Type }}" role="alert">
{{ .Text | html }}
</div>
{{ end }}
+16 -9
View File
@@ -1,15 +1,22 @@
<div class="card-footer">
<div class="col text-right small">
<a href="https://cortezaproject.org/" target="_blank">cortezaproject.org</a>
<span> | </span>
<a href="https://github.com/cortezaproject/" target="_blank">Github</a>
</div>
</div>
</main>
<small class="p-1 text-secondary position-absolute version">
{{ template "inc_toasts.html.tpl" .alerts }}
{{ if .user }}
<div class="position-absolute user text-white m-2">
You're logged-in as
<a class="font-weight-bold text-white" href="{{ links.Profile }}">{{ coalesce .user.Name .user.Handle .user.Email }}</a>
|
<a class="font-weight-bold text-white" href="{{ links.Logout }}">Logout</a>
</div>
{{ end }}
<div class="footer col text-center position-absolute mb-4">
<a href="https://cortezaproject.org/" target="_blank" class="text-white mr-2">cortezaproject.org</a>
<a href="https://github.com/cortezaproject/" target="_blank" class="text-white ml-2">GitHub</a>
</div>
<small class="p-1 text-secondary position-absolute version mt-2">
version {{ version }}
</small>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>
<script src="{{ links.Assets }}/script.js?{{ buildtime }}"></script>
</html>
+5 -2
View File
@@ -9,8 +9,11 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css">
<!-- Custom CSS -->
<link href="{{ links.Assets }}/style.css?{{ buildtime }}" rel="stylesheet">
<!-- Nunito font -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600&display=swap" rel="stylesheet">
</head>
<body style="background: url({{ links.Assets }}/background.png);">
<main class="auth">
<body style="background: url({{ links.Assets }}/background.jpeg) no-repeat bottom;background-size: cover;background-attachment: fixed;" class="d-flex">
<main class="auth justify-content-center align-items-center">
<div class="card">
{{ template "inc_nav.html.tpl" . }}
+17 -26
View File
@@ -1,43 +1,34 @@
<div class="card-header p-0">
<div class="row">
<div class="col cols-6">
<a href="{{ links.Profile }}">
<img class="logo m-3" src="{{ links.Assets }}/logo.png">
</a>
</div>
<div class="col cols-6 text-right small m-3">
{{ if .user }}
Logged-in as
<a href="{{ links.Profile }}">{{ coalesce .user.Name .user.Handle .user.Email }}</a>
|
<a href="{{ links.Logout }}">Logout</a>
{{ end }}
</div>
</div>
<div class="card-header border-0 p-0">
<div class="text-center w-100">
<a href="{{ links.Profile }}">
<img class="logo m-3" src="{{ links.Assets }}/logo.png">
</a>
</div>
{{ if not .hideNav }}
{{ if and .user .client }}
<div class="py-1 px-3">
<a href="{{ links.OAuth2AuthorizeClient }}">&raquo; Continue with authorization of {{ .client.Name }}</a>
<a href="{{ links.OAuth2AuthorizeClient }}" class="text-danger">
Finalize the authorization of {{ .client.Name }}
<i class="bi bi-chevron-double-right"></i>
</a>
</div>
{{ else if .user }}
<ul class="nav ml-1">
<li class="nav-item">
<ul class="nav ml-1 d-flex justify-content-around">
<li class="nav-item {{ if eq .activeNav "profile" }}active{{ end }}">
<a class="nav-link" href="{{ links.Profile }}">Your profile</a>
</li>
<li class="nav-item">
<li class="nav-item {{ if eq .activeNav "security" }}active{{ end }}">
<a class="nav-link" href="{{ links.Security }}">Security</a>
</li>
<li class="nav-item {{ if eq .activeNav "sessions" }}active{{ end }}">
<a class="nav-link" href="{{ links.Sessions }}">Login sessions</a>
</li>
{{ if .settings.ExternalEnabled }}
<li class="nav-item">
<li class="nav-item {{ if eq .activeNav "clients" }}active{{ end }}">
<a class="nav-link" href="{{ links.AuthorizedClients }}">Authorized clients</a>
</li>
{{ end }}
{{ if .settings.LocalEnabled }}
<li class="nav-item">
<a class="nav-link" href="{{ links.ChangePassword }}">Change password</a>
</li>
{{ end }}
</ul>
{{ end }}
{{ end }}
+16
View File
@@ -0,0 +1,16 @@
<div class="position-fixed bottom-0 right-0 p-3" style="z-index: 5; right: 0; bottom: 0;">
{{ range . }}
<div class="toast" role="alert" aria-live="polite" aria-atomic="true" data-delay="5000">
<div class="toast-header">
<span class="badge badge-{{ .Type }} mr-1 px-2">&nbsp;</span>
<strong class="mr-auto">Corteza</strong>
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body p-3">
{{ .Text | html }}
</div>
</div>
{{ end }}
</div>
+29 -29
View File
@@ -1,23 +1,22 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Login</h4>
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Log in</h4>
{{ if .settings.LocalEnabled }}
<form
method="POST"
onsubmit="buttonDisabler()"
action="{{ links.Login }}"
class="p-3"
>
{{ .csrfField }}
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger mb-4 font-weight-bold" role="alert">
{{ .form.error }}
</div>
{{ end }}
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-envelope"></i>
</span>
<div class="mb-3">
<label>
E-mail *
</label>
<input
type="email"
class="form-control"
@@ -28,10 +27,10 @@
autocomplete="username"
aria-label="Email">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-key-fill"></i>
</span>
<div class="mb-3">
<label>
Password *
</label>
<input
type="password"
required
@@ -42,14 +41,9 @@
aria-label="Password">
</div>
<div class="row">
<div class="col">
{{ if .settings.PasswordResetEnabled }}
<a href="{{ links.RequestPasswordReset }}" class="small">Forgot your password?</a>
{{ end }}
</div>
<div class="col text-right">
<button
class="btn btn-primary"
class="btn btn-primary btn-block btn-lg"
name="keep-session"
value="true"
type="submit"
@@ -57,7 +51,7 @@
Log in and remember me
</button>
<button
class="btn btn-secondary"
class="btn btn-light btn-block"
type="submit"
>
Log in
@@ -65,19 +59,25 @@
</div>
</div>
</form>
{{ if .settings.SignupEnabled }}
<div class="text-center my-5">
<a href="{{ links.Signup }}">Create new account</a>
<div class="row text-center">
{{ if .settings.PasswordResetEnabled }}
<div class="col cols-6 mb-5">
<a href="{{ links.RequestPasswordReset }}">Forgot your password?</a>
</div>
{{ end }}
{{ if .settings.SignupEnabled }}
<div class="col cols-6 mb-5">
<a href="{{ links.Signup }}">Create a new account</a>
</div>
{{ end }}
</div>
{{ end }}
{{ end }}
{{ if .settings.ExternalEnabled }}
<hr>
<div>
<div class="p-3">
{{ range .providers }}
<a href="{{ links.External }}/{{ .Handle }}" class="btn btn-outline-dark btn-block text-left mb-2">
<i class="bi bi-{{ .Icon }} mr-2"></i>
<small>Login with {{ coalesce .Label .Handle }}</small>
<a href="{{ links.External }}/{{ .Handle }}" class="btn btn-light btn-block btn-lg mb-2 text-dark">
<i class="bi bi-{{ .Icon }} mr-1"></i>
Login with {{ coalesce .Label .Handle }}
</a>
{{ end }}
</div>
+4 -6
View File
@@ -2,19 +2,17 @@
<div class="card-body">
<form>
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger font-weight-bold" role="alert">
{{ .form.error }}
</div>
{{ else }}
<div class="alert alert-primary" role="primary">
Logout successful
<div class="text-dark font-weight-bold" role="primary">
Log out successful.
</div>
{{ end }}
<hr />
<div class="text-center my-3">
<a href="{{ if .backlink }}{{ .backlink }}{{ else }}{{ links.Login }}{{ end }}">Login</a>
Click here to <a href="{{ if .backlink }}{{ .backlink }}{{ else }}{{ links.Login }}{{ end }}">Log in</a>
</div>
</form>
@@ -1,20 +1,18 @@
{{/* setting hideNav=true to root scope and passign it to header template */}}
{{ template "inc_header.html.tpl" set . "hideNav" true }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<div class="card-body p-0">
{{ if .invalidUser }}
<div class="alert alert-danger" role="alert">
<div class="text-danger font-weight-bold p-3" role="alert">
{{ .invalidUser }}
</div>
{{ end }}
<h4 class="card-title">Authorize "{{ coalesce .client.Name }}"</h4>
<h4 class="card-title p-3 border-bottom">Authorize "{{ coalesce .client.Name }}"</h4>
<form
action="{{ links.OAuth2AuthorizeClient }}"
method="POST"
onsubmit="buttonDisabler()"
class="p-3"
>
{{ .csrfField }}
<p>
@@ -25,28 +23,27 @@
</p>
<p class="text-center">
<button
type="submit"
name="deny"
class="btn btn-secondary btn-lg m-2"
style="width:180px;"
>
Deny
</button>
<button
type="submit"
name="allow"
{{ if .disabled }}disabled{{ end }}
class="btn btn-{{ if .disabled }}secondary{{ else }}primary{{ end }} btn-lg m-2"
style="width:180px;"
style="width:250px;"
>
Allow
</button>
<button
type="submit"
name="deny"
class="btn btn-danger btn-lg m-2"
style="width:250px;"
>
Deny
</button>
</p>
<hr />
If this is a mistake, <a href="{{ links.Logout }}">logout</a>.
<div class="text-center">
If this is a mistake, please <a href="{{ links.Logout }}">log out</a>.
</div>
</form>
</div>
@@ -1,14 +1,13 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Password reset requested</h4>
<div class="alert alert-primary" role="alert">
If entered email is found in our database you should receive password reset link to your inbox in a few moments.
</div>
<div class="text-center my-3 small">
<a href="{{ links.Signup }}">Create new account</a>
|
<a href="{{ links.Login }}">Login</a>
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Password reset requested</h4>
<div class="p-3" role="alert">
If the email you entered is found in our database, you'll receive a password reset link to your inbox in a few moments.
</div>
<div class="text-center my-3">
<a href="{{ links.Signup }}">Create new account</a>
or
<a href="{{ links.Login }}">Log in</a>
</div>
</div>
{{ template "inc_footer.html.tpl" . }}
@@ -1,14 +1,13 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Confirm your email</h4>
<div class="alert alert-primary" role="alert">
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Confirm your email</h4>
<div class="p-3" role="alert">
You should receive email confirmation link to your inbox in a few moments.
</div>
<div class="text-center my-3 small">
<a href="{{ links.Signup }}">Create new account</a>
|
<a href="{{ links.Login }}">Login</a>
</div>
<div class="text-center my-3">
<a href="{{ links.Signup }}">Create new account</a>
or
<a href="{{ links.Login }}">Log in</a>
</div>
</div>
{{ template "inc_footer.html.tpl" . }}
+55 -63
View File
@@ -1,82 +1,74 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Your profile</h4>
{{ template "inc_header.html.tpl" set . "activeNav" "profile" }}
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Your profile</h4>
<form
method="POST"
action="{{ links.Profile }}"
onsubmit="buttonDisabler()"
class="p-3"
>
{{ .csrfField }}
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger mb-4 font-weight-bold" role="alert">
{{ .form.error }}
</div>
{{ end }}
<div class="form-group row">
<label for="profileFormEmail" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input
type="email"
class="form-control"
name="email"
id="profileFormEmail"
placeholder="email@domain.ltd"
autocomplete="username"
readonly
value="{{ .form.email }}"
aria-label="Email">
<div class="mb-3">
<label for="profileFormEmail">Email</label>
<input
type="email"
class="form-control"
name="email"
id="profileFormEmail"
placeholder="email@domain.ltd"
autocomplete="username"
readonly
value="{{ .form.email }}"
aria-label="Email">
<div>
{{ if .emailConfirmationRequired }}
<div class="form-text text-danger">
Email is not verified, <a href="{{ links.PendingEmailConfirmation }}?resend">resend confirmation link.</a>
</div>
{{ end }}
</div>
</div>
{{ if .emailConfirmationRequired }}
<small class="form-text text-danger">
Email is not verified, <a href="{{ links.PendingEmailConfirmation }}?resend">resend confirmation link.</a>
</small>
{{ end }}
</div>
<div class="mb-3">
<label for="profileFormName">Full name</label>
<input
type="text"
class="form-control"
name="name"
id="profileFormName"
placeholder="Your full name"
value="{{ .form.name }}"
autocomplete="name"
aria-label="Full name">
</div>
<div class="form-group row">
<label for="profileFormName" class="col-sm-2 col-form-label">Full name</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
name="name"
id="profileFormName"
placeholder="Your full name"
value="{{ .form.name }}"
autocomplete="name"
aria-label="Full name">
</div>
<div class="mb-3">
<label for="profileFormHandle">Handle</label>
<input
type="text"
class="form-control"
name="handle"
id="profileFormHandle"
placeholder="Short name, nickname or handle"
value="{{ .form.handle }}"
autocomplete="handle"
aria-label="Handle">
</div>
<div class="form-group row">
<label for="profileFormHandle" class="col-sm-2 col-form-label">Handle</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
name="handle"
id="profileFormHandle"
placeholder="Short name, nickname or handle"
value="{{ .form.handle }}"
autocomplete="handle"
aria-label="Handle">
</div>
</div>
<div class="form-group row">
<div class="col-12 text-right">
<button
type="submit"
class="btn btn-primary"
>
Update profile
</button>
</div>
</div>
<div>
<button
type="submit"
class="btn btn-primary btn-block btn-lg"
>
Update profile
</button>
</div>
</form>
</div>
{{ template "inc_footer.html.tpl" . }}
@@ -1,22 +1,21 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Request password reset link</h4>
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Request password reset link</h4>
<form
method="POST"
onsubmit="buttonDisabler()"
action="{{ links.RequestPasswordReset }}"
class="p-3"
>
{{ .csrfField }}
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger font-weight-bold mb-4" role="alert">
{{ .form.error }}
</div>
{{ end }}
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-envelope"></i>
</span>
<div class="mb-3">
<label>
E-mail *
</label>
<input
type="email"
class="form-control"
@@ -28,13 +27,13 @@
aria-label="Email">
</div>
<div class="text-right">
<button class="btn btn-primary btn-block" type="submit">Request password reset link via email</button>
<button class="btn btn-primary btn-block btn-lg" type="submit">Request password reset link via email</button>
</div>
</form>
<div class="text-center my-3">
<a href="{{ links.Signup }}">Create new account</a>
|
<a href="{{ links.Login }}">Login</a>
or
<a href="{{ links.Login }}">Log in</a>
</div>
</div>
{{ template "inc_footer.html.tpl" . }}
+13 -14
View File
@@ -1,22 +1,21 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Reset your password</h4>
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Reset your password</h4>
<form
method="POST"
onsubmit="buttonDisabler()"
action="{{ links.ResetPassword }}"
class="p-3"
>
{{ .csrfField }}
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger font-weight-bold p-3" role="alert">
{{ .form.error }}
</div>
{{ end }}
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-envelope"></i>
</span>
<div class="mb-3">
<label>
E-mail *
</label>
<input
type="email"
class="form-control"
@@ -26,10 +25,10 @@
value="{{ .user.Email }}"
aria-label="Email">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-key-fill"></i>
</span>
<div class="mb-3">
<label>
New Password *
</label>
<input
type="password"
required
@@ -40,7 +39,7 @@
aria-label="Set new password">
</div>
<div class="text-right">
<button class="btn btn-primary btn-block" type="submit">Change your password</button>
<button class="btn btn-primary btn-block btn-lg" type="submit">Change your password</button>
</div>
</form>
</div>
+57 -5
View File
@@ -20,7 +20,8 @@ login:
providers:
- { Label: Google, Handle: google, Icon: google }
- { Label: Facebook, Handle: facebook, Icon: facebook }
- { Label: Corteza, Handle: corteza, Icon: oidc }
- { Label: GitHub, Handle: github, Icon: github }
- { Label: Corteza, Handle: corteza, Icon: shield-lock }
Only external:
settings:
@@ -29,7 +30,8 @@ login:
providers:
- { Label: Google, Handle: google, Icon: google }
- { Label: Facebook, Handle: facebook, Icon: facebook }
- { Label: Corteza, Handle: corteza, Icon: oidc }
- { Label: GitHub, Handle: github, Icon: github }
- { Label: Corteza, Handle: corteza, Icon: shield-lock }
Without signup and pass reset:
settings:
@@ -47,27 +49,77 @@ login:
logout:
Default: {}
With error:
form:
error: "There was an error..."
signup:
Default: {}
With error:
form:
error: "There was an error..."
reset-password:
Default: {}
request-password-reset:
Default: {}
With error:
form:
error: "There was an error..."
password-reset-requested:
Default: {}
pending-email-confirmation:
Default: {}
Default:
profile:
Default: {}
Default:
user:
ID: 123
Name: John Doe
settings:
ExternalEnabled: true
LocalEnabled: true
With errros:
user:
ID: 123
Name: John Doe
settings:
ExternalEnabled: true
LocalEnabled: true
form:
error: Profile change form submit error
name: foo
email: foo
With unconfirmed email:
user:
ID: 123
Name: John Doe
settings:
ExternalEnabled: true
LocalEnabled: true
form:
error: Profile change form submit error
name: foo
email: foo
emailConfirmationRequired: true
In OAuth2 flow:
user:
ID: 123
Name: John Doe
settings:
ExternalEnabled: true
LocalEnabled: true
client:
Name: foo
emailConfirmationRequired: true
change-password:
Default: {}
With error:
form:
error: "There was an error..."
authorized-clients:
Empty: {}
+10
View File
@@ -0,0 +1,10 @@
{{ template "inc_header.html.tpl" set . "activeNav" "security" }}
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Security</h4>
<ul>
{{ if .settings.LocalEnabled }}
<li><a href="{{ links.ChangePassword }}">Change your password</a></li>
{{ end }}
</ul>
</div>
{{ template "inc_footer.html.tpl" . }}
+57 -89
View File
@@ -1,101 +1,69 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
{{ template "inc_header.html.tpl" set . "activeNav" "sessions" }}
<div class="card-body p-0">
<div class="card-title p-3 border-bottom">
<h4 class="card-title d-inline">Your sessions</h4>
{{ if .sessions}}
<button
type="submit"
name="delete-all-but-current"
value="true"
class="btn btn-sm btn-danger float-right"
>
Delete all sessions
</button>
{{ end }}
</div>
<form
method="POST"
action="{{ links.Sessions }}"
onsubmit="buttonDisabler()"
class="p-3"
>
{{ if .sessions}}
<button
type="submit"
name="delete-all-but-current"
value="true"
class="btn btn-sm btn-link text-danger float-right"
>
Delete all
</button>
{{ end }}
<h4 class="card-title">Your sessions</h4>
{{ .csrfField }}
{{ range .sessions}}
<div class="card mb-3 shadow-sm rounded-lg">
<div class="mb-3 border-bottom">
{{ if .Current }}
<div class="card-header">
<b>Current session</b>
</div>
{{ end }}
<div class="card-body bg-light">
<div class="row clearfix">
<div class="col">
<dt>
Authorized on
</dt>
<dd>
<time datetime="{{ .CreatedAt }}">{{ .CreatedAt | date "Mon, 02 Jan 2006 15:04 MST" }}</time>
</dd>
</div>
<div class="col">
<dt>
{{ if .Expired }}
<span class="badge badge-warning float-right">expired</span>
{{ else if eq .ExpiresIn 0 }}
<span class="badge badge-warning float-right">today</span>
{{ else if eq .ExpiresIn 1 }}
<span class="badge badge-warning float-right">in 1 day</span>
{{ else }}
<span class="badge badge-info float-right">in {{ .ExpiresIn }} days</span>
{{ end }}
Expires
</dt>
<dd>
<time datetime="{{ .ExpiresAt }}">{{ .ExpiresAt | date "Mon, 02 Jan 2006 15:04 MST" }}</time>
</dd>
</div>
</div>
<div class="row">
<div class="col">
<dt>
{{ if .SameRemoteAddr}}
<span class="badge badge-info float-right">This machine</span>
{{ end }}
IP address
</dt>
<dd>
{{ .RemoteAddr }}
</dd>
</div>
<div class="col">
<dt>
{{ if .SameUserAgent}}
<span class="badge badge-info float-right">This browser</span>
{{ end }}
Browser
</dt>
<dd class="small">
{{ .UserAgent }}
</dd>
</div>
</div>
</div>
{{ if not .Current }}
<div class="card-footer">
<button
type="submit"
name="delete"
value="{{ .ID }}"
class="btn btn-sm btn-link text-danger"
>
Delete this session
</button>
</div>
<h5>Current session</h5>
{{ end }}
{{ if not .Current }}
<button
type="submit"
name="delete"
value="{{ .ID }}"
class="btn btn-sm btn-link text-danger float-right"
>
Delete this session
</button>
{{ end }}
<label class="mb-0 d-block">Authorized on</label>
<p class="w-75 d-inline-block">
<time datetime="{{ .CreatedAt }}">{{ .CreatedAt | date "Mon, 02 Jan 2006 15:04 MST" }}</time>
</p>
<label class="mb-0 d-block">IP Address</label>
<p class="w-75 d-inline-block">{{ .RemoteAddr }}</p>
{{ if .SameRemoteAddr}}
<span class="badge badge-light float-right">This machine</span>
{{ end }}
<label class="mb-0 d-block">Expires</label>
<p class="w-75 d-inline-block">
<time datetime="{{ .ExpiresAt }}">{{ .ExpiresAt | date "Mon, 02 Jan 2006 15:04 MST" }}</time>
</p>
{{ if .Expired }}
<span class="badge badge-warning float-right">expired</span>
{{ else if eq .ExpiresIn 0 }}
<span class="badge badge-warning float-right">today</span>
{{ else if eq .ExpiresIn 1 }}
<span class="badge badge-light float-right">in 1 day</span>
{{ else }}
<span class="badge badge-light float-right">in {{ .ExpiresIn }} days</span>
{{ end }}
<label class="mb-0 d-block">Browser</label>
<p class="small w-75 d-inline-block">
{{ .UserAgent }}
</p>
{{ if .SameUserAgent}}
<span class="badge badge-light float-right">This browser</span>
{{ end }}
</div>
{{ end }}
</form>
+36 -38
View File
@@ -1,38 +1,36 @@
{{ template "inc_header.html.tpl" . }}
<div class="card-body">
{{ template "inc_alerts.html.tpl" .alerts }}
<h4 class="card-title">Sign up</h4>
<div class="card-body p-0">
<h4 class="card-title p-3 border-bottom">Sign up</h4>
<form
method="POST"
onsubmit="buttonDisabler()"
action="{{ links.Signup }}"
class="p-3"
>
{{ .csrfField }}
{{ if .form.error }}
<div class="alert alert-danger" role="alert">
<div class="text-danger font-weight-bold mb-3" role="alert">
{{ .form.error }}
</div>
{{ end }}
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-envelope"></i>
</span>
<input
type="email"
class="form-control"
name="email"
required
placeholder="email@domain.ltd"
autocomplete="username"
value="{{ .form.email }}"
aria-label="Email">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-key-fill"></i>
</span>
<div class="mb-3">
<label>
E-mail *
</label>
<input
type="email"
class="form-control"
name="email"
required
placeholder="email@domain.ltd"
autocomplete="username"
value="{{ .form.email }}"
aria-label="Email">
</div>
<div class="mb-3">
<label>
Password *
</label>
<input
type="password"
class="form-control"
@@ -41,11 +39,11 @@
placeholder="Password"
autocomplete="new-password"
aria-label="Password">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-person-fill"></i>
</span>
</div>
<div class="mb-3">
<label>
Full Name
</label>
<input
type="text"
class="form-control"
@@ -54,11 +52,11 @@
value="{{ .form.name }}"
autocomplete="name"
aria-label="Full name">
</div>
<div class="input-group mb-3">
<span class="input-group-text">
<i class="bi bi-emoji-smile"></i>
</span>
</div>
<div class="mb-3">
<label>
Short name, nickname or handle
</label>
<input
type="text"
class="form-control"
@@ -67,17 +65,17 @@
value="{{ .form.handle }}"
autocomplete="handle"
aria-label="Handle">
</div>
<div class="text-right">
</div>
<div>
<button
id="submit"
class="btn btn-primary btn-block"
class="btn btn-primary btn-block btn-lg"
type="submit"
>Submit</button>
</div>
</form>
<div class="text-center my-3">Already have an account?
<a href="{{ links.Login }}">Login</a>
<a href="{{ links.Login }}">Log in here</a>
</div>
</div>
{{ template "inc_footer.html.tpl" . }}
+2 -1
View File
@@ -7,7 +7,7 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script type="application/javascript">
window.addEventListener('load', function() {
document.getElementsByID('preview').src=location.hash.substring(1)
document.getElementById('preview').src=location.hash.substring(1)
})
</script>
</head>
@@ -39,6 +39,7 @@
<div class="col-9 m-0 p-0">
<iframe
name="preview"
id="preview"
class="w-100 border-0"
style="height: 100vh;"
src="about:blank"
+7 -1
View File
@@ -10,6 +10,7 @@ func (h *AuthHandlers) profileForm(req *request.AuthReq) error {
req.Template = TmplProfile
if form := req.GetKV(); len(form) > 0 {
req.Data["form"] = form
req.SetKV(nil)
} else {
req.Data["form"] = map[string]string{
"email": req.User.Email,
@@ -23,7 +24,7 @@ func (h *AuthHandlers) profileForm(req *request.AuthReq) error {
}
func (h *AuthHandlers) profileProc(req *request.AuthReq) error {
req.RedirectTo = GetLinks().Signup
req.RedirectTo = GetLinks().Profile
req.SetKV(nil)
req.User.Handle = req.Request.PostFormValue("handle")
@@ -58,6 +59,11 @@ func (h *AuthHandlers) profileProc(req *request.AuthReq) error {
"name": req.User.Name,
})
req.NewAlerts = append(req.NewAlerts, request.Alert{
Type: "danger",
Text: "Could not update profile due to input errors",
})
h.Log.Warn("handled error", zap.Error(err))
return nil
+10
View File
@@ -0,0 +1,10 @@
package handlers
import (
"github.com/cortezaproject/corteza-server/auth/request"
)
func (h *AuthHandlers) security(req *request.AuthReq) error {
req.Template = TmplSecurity
return nil
}
+1
View File
@@ -84,6 +84,7 @@ const (
TmplRequestPasswordReset = "request-password-reset.html.tpl"
TmplPasswordResetRequested = "password-reset-requested.html.tpl"
TmplResetPassword = "reset-password.html.tpl"
TmplSecurity = "security.html.tpl"
TmplProfile = "profile.html.tpl"
TmplSessions = "sessions.html.tpl"
TmplSignup = "signup.html.tpl"
+4
View File
@@ -7,7 +7,10 @@ type (
ConfirmEmail,
PendingEmailConfirmation,
Login,
Security,
ChangePassword,
RequestPasswordReset,
PasswordResetRequested,
ResetPassword,
@@ -34,6 +37,7 @@ func GetLinks() Links {
ConfirmEmail: "/auth/confirm-email",
PendingEmailConfirmation: "/auth/pending-email-confirmation",
Login: "/auth/login",
Security: "/auth/security",
ChangePassword: "/auth/change-password",
RequestPasswordReset: "/auth/request-password-reset",
PasswordResetRequested: "/auth/password-reset-requested",
+1
View File
@@ -69,6 +69,7 @@ func (h *AuthHandlers) MountHttpRoutes(r chi.Router) {
r.Get(l.ResetPassword, h.handle(h.onlyIfPasswordResetEnabled(h.resetPasswordForm)))
r.Post(l.ResetPassword, h.handle(h.onlyIfPasswordResetEnabled(authOnly(h.resetPasswordProc))))
r.Get(l.Security, h.handle(authOnly(h.security)))
r.Get(l.ChangePassword, h.handle(h.onlyIfLocalEnabled(authOnly(h.changePasswordForm))))
r.Post(l.ChangePassword, h.handle(h.onlyIfLocalEnabled(authOnly(h.changePasswordProc))))
})