remember me checkbox, slightly more useful email hint
This commit is contained in:
parent
545a71e57d
commit
9cebc2ca68
@ -32,3 +32,7 @@ input.form-control {
|
|||||||
border: 1px solid var(--form-border-hover);
|
border: 1px solid var(--form-border-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-checkbox {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
@ -50,10 +50,12 @@ export class LoginController {
|
|||||||
public async loginRequest(
|
public async loginRequest(
|
||||||
@Req() req: Request,
|
@Req() req: Request,
|
||||||
@Res() res: Response,
|
@Res() res: Response,
|
||||||
@Body() body: { username: string; password: string },
|
@Body() body: { username: string; password: string; remember: boolean },
|
||||||
@Query('redirectTo') redirectTo?: string,
|
@Query('redirectTo') redirectTo?: string,
|
||||||
) {
|
) {
|
||||||
const { username, password } = this.formUtil.trimmed(body, ['username']);
|
const { username, password, remember } = this.formUtil.trimmed(body, [
|
||||||
|
'username',
|
||||||
|
]);
|
||||||
const user = await this.userService.getByUsername(username);
|
const user = await this.userService.getByUsername(username);
|
||||||
|
|
||||||
// User exists and password matches
|
// User exists and password matches
|
||||||
@ -73,7 +75,7 @@ export class LoginController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (await this.totpService.userHasTOTP(user)) {
|
if (await this.totpService.userHasTOTP(user)) {
|
||||||
const challenge = { type: 'verify', user: user.uuid };
|
const challenge = { type: 'verify', user: user.uuid, remember };
|
||||||
req.session.challenge = await this.token.encryptChallenge(challenge);
|
req.session.challenge = await this.token.encryptChallenge(challenge);
|
||||||
res.redirect(
|
res.redirect(
|
||||||
'/login/verify' + (redirectTo ? '?redirectTo=' + redirectTo : ''),
|
'/login/verify' + (redirectTo ? '?redirectTo=' + redirectTo : ''),
|
||||||
@ -81,6 +83,13 @@ export class LoginController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extend session cookie to a month
|
||||||
|
if (remember) {
|
||||||
|
const month = 30 * 24 * 60 * 60 * 1000;
|
||||||
|
req.session.cookie.maxAge = month;
|
||||||
|
req.session.cookie.expires = new Date(Date.now() + month);
|
||||||
|
}
|
||||||
|
|
||||||
req.session.user = user.uuid;
|
req.session.user = user.uuid;
|
||||||
res.redirect(redirectTo ? decodeURIComponent(redirectTo) : '/');
|
res.redirect(redirectTo ? decodeURIComponent(redirectTo) : '/');
|
||||||
}
|
}
|
||||||
@ -114,6 +123,7 @@ export class LoginController {
|
|||||||
@Query('redirectTo') redirectTo?: string,
|
@Query('redirectTo') redirectTo?: string,
|
||||||
) {
|
) {
|
||||||
let user: User;
|
let user: User;
|
||||||
|
let remember = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!session.challenge) {
|
if (!session.challenge) {
|
||||||
@ -129,6 +139,8 @@ export class LoginController {
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error('Bad challenge');
|
throw new Error('Bad challenge');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remember = challenge.remember;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
req.flash('message', {
|
req.flash('message', {
|
||||||
error: true,
|
error: true,
|
||||||
@ -154,6 +166,12 @@ export class LoginController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extend session cookie to a month
|
||||||
|
if (remember) {
|
||||||
|
const month = 30 * 24 * 60 * 60 * 1000;
|
||||||
|
req.session.cookie.maxAge = month;
|
||||||
|
}
|
||||||
|
|
||||||
session.challenge = null;
|
session.challenge = null;
|
||||||
session.user = user.uuid;
|
session.user = user.uuid;
|
||||||
res.redirect(redirectTo ? decodeURIComponent(redirectTo) : '/');
|
res.redirect(redirectTo ? decodeURIComponent(redirectTo) : '/');
|
||||||
|
@ -172,7 +172,10 @@ export class SettingsController {
|
|||||||
@Render('settings/security')
|
@Render('settings/security')
|
||||||
public async security(@Req() req: Request) {
|
public async security(@Req() req: Request) {
|
||||||
const mailSplit = req.user.email.split('@');
|
const mailSplit = req.user.email.split('@');
|
||||||
const emailHint = `${mailSplit[0].substring(0, 1)}***@${mailSplit[1]}`;
|
const asterisks = ''.padStart(mailSplit[0].substring(1).length, '*');
|
||||||
|
const emailHint = `${mailSplit[0].substring(0, 1)}${asterisks}@${
|
||||||
|
mailSplit[1]
|
||||||
|
}`;
|
||||||
const twofactor = await this._totp.userHasTOTP(req.user);
|
const twofactor = await this._totp.userHasTOTP(req.user);
|
||||||
return this._form.populateTemplate(req, {
|
return this._form.populateTemplate(req, {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
|
@ -23,11 +23,18 @@ block body
|
|||||||
input.form-control#username(type="text", name="username", placeholder="Username", autofocus, value=form.username)
|
input.form-control#username(type="text", name="username", placeholder="Username", autofocus, value=form.username)
|
||||||
label.form-label(for="password") Password
|
label.form-label(for="password") Password
|
||||||
input.form-control#password(type="password", name="password", placeholder="Password")
|
input.form-control#password(type="password", name="password", placeholder="Password")
|
||||||
|
div.form-checkbox
|
||||||
|
input.form-control#remember(type="checkbox", name="remember", checked=form.remember)
|
||||||
|
label(for="remember") Remember me
|
||||||
button.btn.btn-primary(type="submit") Log in
|
button.btn.btn-primary(type="submit") Log in
|
||||||
div.btn-group.align-self-end
|
div.btn-group.align-self-end
|
||||||
a.btn.btn-link(type="button" href="/register" + (query ? ('?' + query) : '')) Create a new account
|
a.btn.btn-link(type="button" href="/register" + (query ? ('?' + query) : '')) Create a new account
|
||||||
|•
|
|•
|
||||||
a.btn.btn-link(type="button" href="/login/password") Forgot password?
|
a.btn.btn-link(type="button" href="/login/password") Forgot password?
|
||||||
div.center-box-addon
|
div.center-box-addon
|
||||||
p Icy Network is a Single-Sign-On service used by other applications.
|
p
|
||||||
p The website may use temporary cookies for storing your login session.
|
b Icy Network is a Single-Sign-On service used by other applications.
|
||||||
|
p The website may use temporary cookies for storing your login session and ensuring your security.
|
||||||
|
| This web service is
|
||||||
|
a(href="https://gitlab.icynet.eu/IcyNetwork/icynet-auth-server", target="_blank") completely open source
|
||||||
|
| and can be audited by anyone.
|
||||||
|
@ -36,13 +36,13 @@ block settings
|
|||||||
form(method="post", action="/account/avatar/delete")
|
form(method="post", action="/account/avatar/delete")
|
||||||
input(type="hidden", name="_csrf", value=csrf)
|
input(type="hidden", name="_csrf", value=csrf)
|
||||||
button.btn.btn-link#remove-avatar(type="submit") Remove avatar
|
button.btn.btn-link#remove-avatar(type="submit") Remove avatar
|
||||||
|
|
||||||
form(method="post", data-noscript, action="/account/avatar", enctype="multipart/form-data")
|
form(method="post", data-noscript, action="/account/avatar", enctype="multipart/form-data")
|
||||||
div.form-container
|
div.form-container
|
||||||
input(type="hidden", name="_csrf", value=csrf)
|
input(type="hidden", name="_csrf", value=csrf)
|
||||||
label.form-label(for="image") Image
|
label.form-label(for="image") Image
|
||||||
input.form-control#image(type="file", name="file")
|
input.form-control#image(type="file", name="file")
|
||||||
small.form-hint Must be less than 10 MB and 1:1 aspect ratio. Enable JavaScript to custom crop your image.
|
small.form-hint Must be less than 10 MB and 1:1 aspect ratio (square). Enable JavaScript to custom crop your image.
|
||||||
button.btn.btn-primary(type="submit") Change
|
button.btn.btn-primary(type="submit") Change
|
||||||
.modal#avatar-modal(data-modal="avatar", style="display: none")
|
.modal#avatar-modal(data-modal="avatar", style="display: none")
|
||||||
.modal__content
|
.modal__content
|
||||||
|
@ -17,7 +17,7 @@ block settings
|
|||||||
h2 Change Password
|
h2 Change Password
|
||||||
form(method="post", action="/account/security/password", autocomplete="off")
|
form(method="post", action="/account/security/password", autocomplete="off")
|
||||||
div.form-container
|
div.form-container
|
||||||
input#csrfa(type="hidden", name="_csrf", value=csrf)
|
input#csrf(type="hidden", name="_csrf", value=csrf)
|
||||||
label.form-label(for="password") Current Password
|
label.form-label(for="password") Current Password
|
||||||
input.form-control#password(type="password", name="password")
|
input.form-control#password(type="password", name="password")
|
||||||
label.form-label(for="new_password") New Password
|
label.form-label(for="new_password") New Password
|
||||||
@ -29,7 +29,7 @@ block settings
|
|||||||
h2 Change Email Address
|
h2 Change Email Address
|
||||||
form(method="post", action="/account/security/email", autocomplete="off")
|
form(method="post", action="/account/security/email", autocomplete="off")
|
||||||
div.form-container
|
div.form-container
|
||||||
input#csrfb(type="hidden", name="_csrf", value=csrf)
|
input(type="hidden", name="_csrf", value=csrf)
|
||||||
label.form-label(for="current_email") Current Email Address
|
label.form-label(for="current_email") Current Email Address
|
||||||
input.form-control#current_email(type="email", name="current_email")
|
input.form-control#current_email(type="email", name="current_email")
|
||||||
small.form-hint Hint: #{emailHint}
|
small.form-hint Hint: #{emailHint}
|
||||||
@ -42,9 +42,9 @@ block settings
|
|||||||
p Two-factor authentication is enabled.
|
p Two-factor authentication is enabled.
|
||||||
a.btn.btn-primary(href="/account/two-factor/disable") Disable
|
a.btn.btn-primary(href="/account/two-factor/disable") Disable
|
||||||
else
|
else
|
||||||
p You can enable two-factor authentication using an authenticator app of your choice, such as
|
p You can enable two-factor authentication using an authenticator app of your choice, such as
|
||||||
b Google Authenticator
|
b Google Authenticator
|
||||||
| or
|
| or
|
||||||
b andOTP
|
b andOTP
|
||||||
|.
|
|.
|
||||||
a.btn.btn-primary(href="/account/two-factor/activate") Activate
|
a.btn.btn-primary(href="/account/two-factor/activate") Activate
|
||||||
|
Reference in New Issue
Block a user