Refactor auth forms (#624)
This commit is contained in:
parent
a5807efb75
commit
231c0f420f
17 changed files with 270 additions and 719 deletions
|
@ -17,7 +17,7 @@ def login_get(v):
|
|||
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
||||
elif redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
|
||||
|
||||
return render_template("login.html", failed=False, redirect=redir)
|
||||
return render_template("login/login.html", failed=False, redirect=redir)
|
||||
|
||||
|
||||
def check_for_alts(current_id):
|
||||
|
@ -95,18 +95,18 @@ def login_post():
|
|||
|
||||
if not account:
|
||||
time.sleep(random.uniform(0, 2))
|
||||
return render_template("login.html", failed=True)
|
||||
return render_template("login/login.html", failed=True)
|
||||
|
||||
if request.values.get("password"):
|
||||
|
||||
if not account.verifyPass(request.values.get("password")):
|
||||
time.sleep(random.uniform(0, 2))
|
||||
return render_template("login.html", failed=True)
|
||||
return render_template("login/login.html", failed=True)
|
||||
|
||||
if account.mfa_secret:
|
||||
now = int(time.time())
|
||||
hash = generate_hash(f"{account.id}+{now}+2fachallenge")
|
||||
return render_template("login_2fa.html",
|
||||
return render_template("login/login_2fa.html",
|
||||
v=account,
|
||||
time=now,
|
||||
hash=hash,
|
||||
|
@ -124,7 +124,7 @@ def login_post():
|
|||
|
||||
if not account.validate_2fa(request.values.get("2fa_token", "").strip()):
|
||||
hash = generate_hash(f"{account.id}+{time}+2fachallenge")
|
||||
return render_template("login_2fa.html",
|
||||
return render_template("login/login_2fa.html",
|
||||
v=account,
|
||||
time=now,
|
||||
hash=hash,
|
||||
|
@ -193,7 +193,7 @@ def sign_up_get(v):
|
|||
ref_user = None
|
||||
|
||||
if ref_user and (ref_user.id in session.get("history", [])):
|
||||
return render_template("sign_up_failed_ref.html")
|
||||
return render_template("login/sign_up_failed_ref.html")
|
||||
|
||||
now = int(time.time())
|
||||
token = token_hex(16)
|
||||
|
@ -209,7 +209,7 @@ def sign_up_get(v):
|
|||
error = request.values.get("error")
|
||||
|
||||
return render_template(
|
||||
"sign_up.html",
|
||||
"login/sign_up.html",
|
||||
formkey=formkey,
|
||||
now=now,
|
||||
ref_user=ref_user,
|
||||
|
@ -358,7 +358,7 @@ def sign_up_post(v):
|
|||
|
||||
@app.get("/forgot")
|
||||
def get_forgot():
|
||||
return render_template("forgot_password.html")
|
||||
return render_template("login/forgot_password.html")
|
||||
|
||||
|
||||
@app.post("/forgot")
|
||||
|
@ -370,7 +370,7 @@ def post_forgot():
|
|||
email = request.values.get("email",'').strip().lower()
|
||||
|
||||
if not email_regex.fullmatch(email):
|
||||
return render_template("forgot_password.html", error="Invalid email.")
|
||||
return render_template("login/forgot_password.html", error="Invalid email.")
|
||||
|
||||
username = username.lstrip('@')
|
||||
|
||||
|
@ -390,7 +390,7 @@ def post_forgot():
|
|||
v=user)
|
||||
)
|
||||
|
||||
return render_template("forgot_password.html",
|
||||
return render_template("login/forgot_password.html",
|
||||
msg="If the username and email matches an account, you will be sent a password reset email. You have ten minutes to complete the password reset process.")
|
||||
|
||||
|
||||
|
@ -420,7 +420,7 @@ def get_reset():
|
|||
|
||||
reset_token = generate_hash(f"{user.id}+{timestamp}+reset+{user.login_nonce}")
|
||||
|
||||
return render_template("reset_password.html",
|
||||
return render_template("login/reset_password.html",
|
||||
v=user,
|
||||
token=reset_token,
|
||||
time=timestamp,
|
||||
|
@ -456,7 +456,7 @@ def post_reset(v):
|
|||
abort(404)
|
||||
|
||||
if password != confirm_password:
|
||||
return render_template("reset_password.html",
|
||||
return render_template("login/reset_password.html",
|
||||
v=user,
|
||||
token=token,
|
||||
time=timestamp,
|
||||
|
@ -475,7 +475,7 @@ def post_reset(v):
|
|||
@auth_desired
|
||||
def lost_2fa(v):
|
||||
return render_template(
|
||||
"lost_2fa.html",
|
||||
"login/lost_2fa.html",
|
||||
v=v
|
||||
)
|
||||
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
{% include "analytics.html" %}
|
||||
|
||||
<meta name="description" content="{{config('DESCRIPTION')}}">
|
||||
{% include "csp.html" %}
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>{% block pagetitle %}{{SITE_TITLE}}{% endblock %}</title>
|
||||
|
||||
|
||||
{% if v %}
|
||||
<style>:root{--primary:#{{v.themecolor}}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~v.theme~'.css') | asset }}">
|
||||
{% if v.css %}
|
||||
<style>{{v.css | safe}}</style>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~config('DEFAULT_THEME')~'.css') | asset }}">
|
||||
{% endif %}
|
||||
|
||||
</head>
|
||||
|
||||
<body id="login">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-transparent fixed-top border-0">
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler d-none" role="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid position-absolute h-100 p-0">
|
||||
<div class="row no-gutters h-100">
|
||||
|
||||
<div class="col-12 col-md-6 my-auto p-3">
|
||||
|
||||
<div class="row justify-content-center">
|
||||
|
||||
<div class="col-10 col-md-7">
|
||||
|
||||
<div class="mb-5">
|
||||
<a href="/" class="text-decoration-none"><span class="h3 text-primary"></span></a>
|
||||
</div>
|
||||
|
||||
<h1 class="h2">{% block authtitle %}{% endblock %}</h1>
|
||||
|
||||
<p class="text-muted mb-md-5">{% block authtext %}{% endblock %}</p>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<span>
|
||||
{{error}}
|
||||
</span>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="far fa-times"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-info-circle my-auto" aria-hidden="true"></i>
|
||||
<span>
|
||||
{{msg}}
|
||||
</span>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="far fa-times"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 d-none d-md-block">
|
||||
|
||||
<div class="splash-wrapper">
|
||||
|
||||
<div class="splash-overlay"></div>
|
||||
|
||||
<img alt="cover" loading="lazy" class="splash-img" src="{{ ('images/'~SITE_ID~'/cover.webp') | asset }}"></img>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,30 +0,0 @@
|
|||
{% extends "authforms.html" %}
|
||||
|
||||
{% block pagetitle %}{{SITE_TITLE}} Password Reset{% endblock %}
|
||||
|
||||
{% block authtitle %}Reset your password.{% endblock %}
|
||||
|
||||
{% block authtext %}If there's an email address associated with your account, you can use it to recover your {{SITE_TITLE}} account and change your password.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="login-form" class="">
|
||||
|
||||
<form action="/forgot" method="post" class="mt-3">
|
||||
|
||||
<label for="username" class="mt-3">Username</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp"
|
||||
type="text" name="username" required="">
|
||||
|
||||
<label for="email" class="mt-3">Email</label>
|
||||
|
||||
<input type="email" pattern='[^@]+@[^@]+\.[^@]+' autocomplete="off" class="form-control" id="password" aria-describedby="passwordHelp" name="email" required>
|
||||
|
||||
<input autocomplete="off" class="btn btn-primary login w-100 mt-3" type="submit" value="Send recovery link">
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,124 +0,0 @@
|
|||
{%- import "util/forms.html" as forms -%}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
{% include "analytics.html" %}
|
||||
|
||||
<meta name="description" content="{{config('DESCRIPTION')}}">
|
||||
{% include "csp.html" %}
|
||||
|
||||
<script src="{{ 'js/bootstrap.js' | asset }}"></script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<meta name="author" content="">
|
||||
|
||||
{% block title %}
|
||||
<title>Login - {{SITE_TITLE}}</title>
|
||||
{% endblock %}
|
||||
|
||||
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~config('DEFAULT_THEME')~'.css') | asset }}">
|
||||
|
||||
</head>
|
||||
|
||||
<body id="login">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-transparent fixed-top border-0">
|
||||
<div class="container-fluid d-none">
|
||||
<button class="navbar-toggler d-none" role="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid position-absolute h-100 p-0 overflow-auto">
|
||||
<div class="row no-gutters h-100">
|
||||
|
||||
<div class="col-12 col-md-6 my-auto p-3">
|
||||
|
||||
<div class="row justify-content-center">
|
||||
|
||||
<div class="col-10 col-md-7">
|
||||
|
||||
<div class="mb-5">
|
||||
<a href="/" class="text-decoration-none"><span class="h3 text-primary"></span></a>
|
||||
</div>
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="login-form" class="">
|
||||
|
||||
<h1 class="h2">Welcome back.</h1>
|
||||
|
||||
<p class="text-muted mb-md-5">Glad to have you back!</p>
|
||||
|
||||
{% if failed %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<div>
|
||||
Incorrect username, email address, or password.
|
||||
<br>
|
||||
<a href="/forgot" class="alert-link">Forgot password?</a>
|
||||
</div>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form action="/login" method="post" class="mt-md-3" id="login">
|
||||
|
||||
<label for="username" class="mt-3">Username or Email Address</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp"
|
||||
type="text" name="username" required="">
|
||||
<input type="hidden" name="redirect" value="{{redirect}}">
|
||||
|
||||
<label for="password" class="mt-3">Password</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="password" aria-describedby="passwordHelp"
|
||||
type="password" name="password" required="">
|
||||
|
||||
|
||||
<small><a href="/forgot">Forgot password?</a></small>
|
||||
|
||||
<button class="btn btn-primary login w-100 mt-3" id="login_button">Sign in</button>
|
||||
|
||||
<div class="text-center text-muted text-small mt-5 mb-3">
|
||||
Don't have an account? <a href="/signup{{'?redirect='+redirect if redirect else ''}}" class="font-weight-bold toggle-login">Sign up</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 d-none d-md-block">
|
||||
|
||||
<div class="splash-wrapper">
|
||||
|
||||
<div class="splash-overlay"></div>
|
||||
|
||||
<img alt="cover" loading="lazy" class="splash-img" src="{{ ('images/'~SITE_ID~'/cover.webp') | asset }}"></img>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
63
files/templates/login/authforms.html
Normal file
63
files/templates/login/authforms.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
{% include "analytics.html" %}
|
||||
{% include "csp.html" %}
|
||||
<meta name="description" content="{{config('DESCRIPTION')}}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>{% block pagetitle %}{{SITE_TITLE}}{% endblock %}</title>
|
||||
{% if v %}
|
||||
<style>:root{--primary:#{{v.themecolor}}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~v.theme~'.css') | asset }}">
|
||||
{% if v.css %}
|
||||
<style>{{v.css | safe}}</style>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~config('DEFAULT_THEME')~'.css') | asset }}">
|
||||
{% endif %}
|
||||
</head>
|
||||
|
||||
<body id="login">
|
||||
<div class="container-fluid position-absolute h-100 p-0">
|
||||
<div class="row no-gutters h-100">
|
||||
<div class="col-12 col-md-6 my-auto p-3">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-10 col-md-7">
|
||||
<h2>{% block authtitle %}{% endblock %}</h2>
|
||||
<p class="text-muted mb-md-5">{% block authtext %}{% endblock %}</p>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<span>{{error}}</span>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="far fa-times"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-info-circle my-auto" aria-hidden="true"></i>
|
||||
<span>{{msg}}</span>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="far fa-times"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 d-mob-none h-100">
|
||||
<div class="splash-wrapper">
|
||||
<div class="splash-overlay"></div>
|
||||
<img alt="cover" loading="lazy" class="splash-img" src="{{ ('images/'~SITE_ID~'/cover.webp') | asset }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
15
files/templates/login/forgot_password.html
Normal file
15
files/templates/login/forgot_password.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "login/authforms.html" %}
|
||||
{% block pagetitle %}{{SITE_TITLE}} Password Reset{% endblock %}
|
||||
{% block authtitle %}Reset your password.{% endblock %}
|
||||
{% block authtext %}If there's an email address associated with your account, you can use it to recover your {{SITE_TITLE}} account and change your password.{% endblock %}
|
||||
{% block content %}
|
||||
<div id="login-form" class="">
|
||||
<form action="/forgot" method="post" class="mt-3">
|
||||
<label for="username" class="mt-3">Username</label>
|
||||
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp" type="text" name="username" required="">
|
||||
<label for="email" class="mt-3">Email</label>
|
||||
<input type="email" pattern='[^@]+@[^@]+\.[^@]+' autocomplete="off" class="form-control" id="password" aria-describedby="passwordHelp" name="email" required>
|
||||
<input autocomplete="off" class="btn btn-primary login w-100 mt-3" type="submit" value="Send recovery link">
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
33
files/templates/login/login.html
Normal file
33
files/templates/login/login.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
{%- extends 'login/authforms.html' -%}
|
||||
{% block authtitle %}Welcome back.{% endblock %}
|
||||
{% block authtext %}Glad to have you back!{% endblock %}
|
||||
{% block content %}
|
||||
<div id="login-form" class="">
|
||||
{% if failed %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<div>
|
||||
Incorrect username, email address, or password.
|
||||
<br>
|
||||
<a href="/forgot" class="alert-link">Forgot password?</a>
|
||||
</div>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form action="/login" method="post" class="mt-md-3" id="login">
|
||||
<label for="username" class="mt-3">Username or Email Address</label>
|
||||
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp" type="text" name="username" required="">
|
||||
<input type="hidden" name="redirect" value="{{redirect}}">
|
||||
<label for="password" class="mt-3">Password</label>
|
||||
<input autocomplete="off" class="form-control" id="password" aria-describedby="passwordHelp" type="password" name="password" required="">
|
||||
<small><a href="/forgot">Forgot password?</a></small>
|
||||
<button class="btn btn-primary login w-100 mt-3" id="login_button">Sign in</button>
|
||||
<div class="text-center text-muted text-small mt-5 mb-3">
|
||||
Don't have an account? <a href="/signup{{'?redirect='+redirect if redirect else ''}}" class="font-weight-bold toggle-login">Sign up</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
29
files/templates/login/login_2fa.html
Normal file
29
files/templates/login/login_2fa.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{%- extends "login/authforms.html" -%}
|
||||
{% block authtitle %}Two-step login{% endblock %}
|
||||
{% block authtext %}To login, please enter the 6-digit verification code generated in your authenticator app.{% endblock %}
|
||||
{%- block content -%}
|
||||
<div id="login-form" class="">
|
||||
{% if failed %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<div>
|
||||
Invalid verification code. Please try again.
|
||||
</div>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form action="/login" method="post" class="mt-md-3" id="login">
|
||||
<input type="hidden" name="username" value="{{v.username}}">
|
||||
<input type="hidden" name="redirect" value="{{redirect}}">
|
||||
<input type="hidden" name="time" value="{{time}}">
|
||||
<input type="hidden" name="hash" value="{{hash}}">
|
||||
<label for="2fa_token" class="mt-3">Your verification code</label>
|
||||
<input autocomplete="off" class="form-control" id="2fa_token" name="2fa_token" type="text" placeholder="6-digit code">
|
||||
<small><a href="/lost_2fa">Lost your 2FA device?</a></small>
|
||||
<button class="btn btn-primary login w-100 mt-3" id="login_button">Sign in</button>
|
||||
</form>
|
||||
</div>
|
||||
{%- endblock -%}
|
19
files/templates/login/lost_2fa.html
Normal file
19
files/templates/login/lost_2fa.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "login/authforms.html" %}
|
||||
{% block pagetitle %}{{SITE_TITLE}} Two-Factor Removal{% endblock %}
|
||||
{% block authtitle %}Remove the two-factor authentication from your account.{% endblock %}
|
||||
{% block authtext %}If all information is correct, you will be able to remove 2-factor authentication from your account in 24 hours.{% endblock %}
|
||||
{% block content %}
|
||||
<div id="login-form" class="">
|
||||
<form action="/request_2fa_disable" method="post" class="mt-3">
|
||||
<label for="username" class="mt-3">Username</label>
|
||||
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp"
|
||||
type="text" name="username" required=""{% if v %} value="{{v.username}}" disabled{% endif %}>
|
||||
<label for="email" class="mt-3">Password</label>
|
||||
<input autocomplete="off" class="form-control" id="password" aria-describedby="passwordHelp"
|
||||
type="password" name="password" required="">
|
||||
<label for="email" class="mt-3">Email</label>
|
||||
<input autocomplete="off" class="form-control" id="password" type="email" pattern='[^@]+@[^@]+\.[^@]+' name="email" required=""{% if v %} value="{{v.email}}" disabled{% endif %}>
|
||||
<input autocomplete="off" class="btn btn-primary login w-100 mt-3" type="submit" value="Send recovery link">
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
20
files/templates/login/reset_password.html
Normal file
20
files/templates/login/reset_password.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
{%- extends 'login/authforms.html' -%}
|
||||
{% block pagetitle %}{{SITE_TITLE}} Password Reset{% endblock %}
|
||||
{% block authtitle %}Change your password.{% endblock %}
|
||||
{% block content %}
|
||||
<div id="login-form" class="">
|
||||
<form action="/reset" method="post" class="mt-3">
|
||||
<input type="hidden" name="time" value="{{time}}">
|
||||
<input type="hidden" name="user_id" value="{{v.id}}">
|
||||
<input type="hidden" name="token" value="{{token}}">
|
||||
|
||||
<label for="passentry" class="mt-3">New Password</label>
|
||||
<input autocomplete="off" class="form-control" id="passentry" aria-describedby="usernameHelp" type="password" name="password" required="">
|
||||
|
||||
<label for="confentry" class="mt-3">Confirm New Password</label>
|
||||
<input autocomplete="off" class="form-control" id="confentry" aria-describedby="passwordHelp" type="password" name="confirm_password" required="">
|
||||
|
||||
<input autocomplete="off" class="btn btn-primary login w-100 mt-3" type="submit" value="Change password">
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
61
files/templates/login/sign_up.html
Normal file
61
files/templates/login/sign_up.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
{%- extends 'login/authforms.html' -%}
|
||||
|
||||
{% set login_namespace = namespace() %}
|
||||
{% if ref_user %}
|
||||
{% set login_namespace.authtitle = '@' ~ ref_user.username ~ ' has invited you!' %}
|
||||
{% set login_namespace.authtext = 'Looks like someone wants you to join ' ~ SITE_NAME ~ '.' %}
|
||||
{% else %}
|
||||
{% set login_namespace.authtitle = "Create your account." %}
|
||||
{% set login_namespace.authtext = "No email address required." %}
|
||||
{% endif %}
|
||||
{% block authtitle %}{{login_namespace.authtitle}}{% endblock %}
|
||||
{% block authtext %}{{login_namespace.authtext}}{% endblock %}
|
||||
|
||||
{%- block content -%}
|
||||
<div id="register-form" class="">
|
||||
<form action="/signup" method="post" class="mt-md-3" id="signup">
|
||||
{% if error %}<span class="text-danger">{{error}}</span><br>{% endif %}
|
||||
|
||||
<input type="hidden" name="formkey" value="{{formkey}}">
|
||||
<input type="hidden" name="now" value="{{now}}">
|
||||
|
||||
{% if redirect %}<input type="hidden" name="redirect" value="{{redirect}}">{% endif %}
|
||||
{% if ref_user %}<input type="hidden" name="referred_by" value="{{ref_user.id}}">{% endif %}
|
||||
<label for="username-register" class="mt-3">Username</label>
|
||||
<input autocomplete="off" class="form-control" id="username-register" aria-describedby="usernameHelpRegister" type="text" name="username" pattern="[a-zA-Z0-9_\-]{3,25}" min="3" max="25" required autofocus tabindex="1">
|
||||
<small id="usernameHelpRegister"></small>
|
||||
|
||||
<label for="email-register" class="mt-3">Email Address</label> <small class="d-inline-block text-muted ml-1">(optional)</small>
|
||||
<input style="background-color: var(--gray-800)" autocomplete="off" class="form-control" id="email-register" aria-describedby="emailHelpRegister" type="email" pattern='[^@]+@[^@]+\.[^@]+' name="email" tabindex="2">
|
||||
|
||||
<label for="password-register" class="mt-3">Password</label>
|
||||
<input autocomplete="off" class="form-control" id="password-register" aria-describedby="passwordHelpReigster" type="password" name="password" required tabindex="4">
|
||||
<small id="passwordHelpRegister" class="form-text font-weight-bold text-muted d-none mt-1">Minimum of 8 characters required.</small>
|
||||
<small id="passwordHelpSuccess" class="form-text font-weight-bold text-success d-none mt-1">Your password meets the requirements.</small>
|
||||
|
||||
<label for="password_confirm" class="mt-3">Confirm Password</label>
|
||||
<input autocomplete="off" class="form-control" id="password_confirm" aria-describedby="passwordConfirmHelp" type="password" name="password_confirm" required tabindex="5">
|
||||
|
||||
<div class="custom-control custom-checkbox mt-4">
|
||||
<input autocomplete="off" type="checkbox" class="custom-control-input" id="termsCheck" required tabindex="6">
|
||||
<label class="custom-control-label terms" for="termsCheck">I accept the <a href="/rules" tabindex="8">rules</a></label>
|
||||
</div>
|
||||
|
||||
{% if hcaptcha %}
|
||||
<div class="h-captcha" data-sitekey="{{hcaptcha}}"></div>
|
||||
{% endif %}
|
||||
|
||||
<button class="btn btn-primary login w-100 mt-3" id="register_button" tabindex="7">Register</button>
|
||||
|
||||
<div class="text-center text-muted text-small mt-2 mb-0">
|
||||
Already have an account? <a href="/login{{'?redirect='+redirect if redirect else ''}}" class="font-weight-bold toggle-login" tabindex="9">Log in</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{%- endblock -%}
|
||||
|
||||
<script src="{{ 'js/signup.js' | asset }}"></script>
|
||||
|
||||
{% if hcaptcha %}
|
||||
<script src="{{ 'js/hcaptcha.js' | asset }}"></script>
|
||||
{% endif %}
|
17
files/templates/login/sign_up_failed_ref.html
Normal file
17
files/templates/login/sign_up_failed_ref.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
{%- extends "login/authforms.html" -%}
|
||||
{%- block authtitle -%}Whoops! You can't refer yourself!{%- endblock -%}
|
||||
{%- block authtext -%}Send this link to a friend instead :){%- endblock -%}
|
||||
{%- block content -%}
|
||||
<div id="register-form" class="">
|
||||
<label>Referral code</label>
|
||||
<input autocomplete="off" type="text" class="form-control copy-link" readonly value="{{SITE_FULL}}/signup?ref={{request.values.get('ref')}}" data-clipboard-text="{{SITE_FULL}}/signup?ref={{request.values.get('ref')}}">
|
||||
|
||||
<div class="text-center mt-5 mb-3">
|
||||
Already have an account? <a href="/login" class="font-weight-bold text-small toggle-login">Log in.</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toast clipboard" id="toast-success" role="alert" aria-live="assertive" aria-atomic="true" data-bs-animation="true" data-bs-autohide="true" data-bs-delay="5000">
|
||||
<div class="toast-body text-center">
|
||||
<i class="fas fa-check-circle text-success mr-2"></i>Link copied to clipboard
|
||||
</div>
|
||||
{%- endblock -%}
|
|
@ -1,108 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
{% include "analytics.html" %}
|
||||
|
||||
<meta name="description" content="{{config('DESCRIPTION')}}">
|
||||
{% include "csp.html" %}
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>2-Step Login - {{SITE_TITLE}}</title>
|
||||
|
||||
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~config('DEFAULT_THEME')~'.css') | asset }}">
|
||||
|
||||
</head>
|
||||
|
||||
<body id="login">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-transparent fixed-top border-0">
|
||||
<div class="container-fluid d-none">
|
||||
<button class="navbar-toggler d-none" role="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid position-absolute h-100 p-0 overflow-auto">
|
||||
<div class="row no-gutters h-100">
|
||||
|
||||
<div class="col-12 col-md-6 my-auto p-3">
|
||||
|
||||
<div class="row justify-content-center">
|
||||
|
||||
<div class="col-10 col-md-7">
|
||||
|
||||
<div class="mb-5">
|
||||
<a href="/" class="text-decoration-none"><span class="h3 text-primary"></span></a>
|
||||
</div>
|
||||
|
||||
<div id="login-form" class="">
|
||||
|
||||
<h1 class="h2">Two-step login</h1>
|
||||
|
||||
<p class="text-muted mb-md-5">To login, please enter the 6-digit verification code generated in your authenticator app.</p>
|
||||
|
||||
{% if failed %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<div>
|
||||
Invalid verification code. Please try again.
|
||||
</div>
|
||||
<button class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form action="/login" method="post" class="mt-md-3" id="login">
|
||||
|
||||
<input type="hidden" name="username" value="{{v.username}}">
|
||||
<input type="hidden" name="redirect" value="{{redirect}}">
|
||||
|
||||
<input type="hidden" name="time" value="{{time}}">
|
||||
<input type="hidden" name="hash" value="{{hash}}">
|
||||
|
||||
<label for="2fa_token" class="mt-3">Your verification code</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="2fa_token" name="2fa_token" type="text" placeholder="6-digit code">
|
||||
<small><a href="/lost_2fa">Lost your 2FA device?</a></small>
|
||||
|
||||
<button class="btn btn-primary login w-100 mt-3" id="login_button">Sign in</button>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 d-none d-md-block">
|
||||
|
||||
<div class="splash-wrapper">
|
||||
|
||||
<div class="splash-overlay"></div>
|
||||
|
||||
<img alt="cover" loading="lazy" class="splash-img" src="{{ ('images/'~SITE_ID~'/cover.webp') | asset }}"></img>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,35 +0,0 @@
|
|||
{% extends "authforms.html" %}
|
||||
|
||||
{% block pagetitle %}{{SITE_TITLE}} Two-Factor Removal{% endblock %}
|
||||
|
||||
{% block authtitle %}Remove the two-factor authentication from your account.{% endblock %}
|
||||
|
||||
{% block authtext %}If all information is correct, you will be able to remove 2-factor authentication from your account in 24 hours.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="login-form" class="">
|
||||
|
||||
<form action="/request_2fa_disable" method="post" class="mt-3">
|
||||
|
||||
<label for="username" class="mt-3">Username</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp"
|
||||
type="text" name="username" required=""{% if v %} value="{{v.username}}" disabled{% endif %}>
|
||||
|
||||
<label for="email" class="mt-3">Password</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="password" aria-describedby="passwordHelp"
|
||||
type="password" name="password" required="">
|
||||
|
||||
<label for="email" class="mt-3">Email</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="password" type="email" pattern='[^@]+@[^@]+\.[^@]+' name="email" required=""{% if v %} value="{{v.email}}" disabled{% endif %}>
|
||||
|
||||
<input autocomplete="off" class="btn btn-primary login w-100 mt-3" type="submit" value="Send recovery link">
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,33 +0,0 @@
|
|||
{% extends "authforms.html" %}
|
||||
|
||||
{% block pagetitle %}{{SITE_TITLE}} Password Reset{% endblock %}
|
||||
|
||||
{% block authtitle %}Change your password.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="login-form" class="">
|
||||
|
||||
<form action="/reset" method="post" class="mt-3">
|
||||
|
||||
<input type="hidden" name="time" value="{{time}}">
|
||||
<input type="hidden" name="user_id" value="{{v.id}}">
|
||||
<input type="hidden" name="token" value="{{token}}">
|
||||
|
||||
<label for="passentry" class="mt-3">New Password</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="passentry" aria-describedby="usernameHelp"
|
||||
type="password" name="password" required="">
|
||||
|
||||
<label for="confentry" class="mt-3">Confirm New Password</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="confentry" aria-describedby="passwordHelp"
|
||||
type="password" name="confirm_password" required="">
|
||||
|
||||
<input autocomplete="off" class="btn btn-primary login w-100 mt-3" type="submit" value="Change password">
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,161 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{% include "analytics.html" %}
|
||||
|
||||
<meta name="description" content="{{config('DESCRIPTION')}}">
|
||||
{% include "csp.html" %}
|
||||
|
||||
<script src="{{ 'js/bootstrap.js' | asset }}"></script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<meta name="author" content="">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:title" content="{{SITE_TITLE}}">
|
||||
<meta property="og:site_name" content="{{request.host}}">
|
||||
<meta property="og:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
|
||||
<meta property="og:url" content="{{request.host}}">
|
||||
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">
|
||||
<meta property="og:author" name="author" content="{{SITE_FULL}}">
|
||||
<meta property="og:site_name" content="{{request.host}}">
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:site" content="{{SITE_FULL}}">
|
||||
<meta name="twitter:title" content="{{SITE_TITLE}}">
|
||||
<meta name="twitter:creator" content="{{SITE_FULL}}">
|
||||
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
|
||||
<meta name="twitter:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
|
||||
<meta name="twitter:url" content="{{request.host}}">
|
||||
|
||||
<title>{% if ref_user %}{{ref_user.username}} invites you to {{SITE_TITLE}}{% else %}Sign up - {{SITE_TITLE}}{% endif %}</title>
|
||||
|
||||
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~config('DEFAULT_THEME')~'.css') | asset }}">
|
||||
|
||||
</head>
|
||||
|
||||
<body id="login">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-transparent fixed-top border-0">
|
||||
<div class="container-fluid d-none">
|
||||
<button class="navbar-toggler d-none" role="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid position-absolute h-100 p-0 overflow-auto">
|
||||
<div class="row no-gutters h-100">
|
||||
|
||||
<div class="col-12 col-md-6 my-auto p-3">
|
||||
|
||||
<div class="row justify-content-center">
|
||||
|
||||
<div class="col-10 col-md-7">
|
||||
|
||||
<div class="mb-3">
|
||||
<a href="/" class="text-decoration-none"><span class="h3 text-primary"></span></a>
|
||||
</div>
|
||||
|
||||
<div id="register-form" class="">
|
||||
|
||||
{% if ref_user %}
|
||||
<h1 class="h2">@{{ref_user.username}} has invited you!</h1>
|
||||
<p class="text-muted mb-md-2">Looks like someone wants you to join {{SITE_TITLE}}.</p>
|
||||
{% else %}
|
||||
<h1 class="h2">Create your account.</h1>
|
||||
<p class="text-muted mb-md-2">No email address required.</p>
|
||||
{% endif %}
|
||||
|
||||
<form action="/signup" method="post" class="mt-md-3" id="signup">
|
||||
|
||||
{% if error %}<span class="text-danger">{{error}}</span><br>{% endif %}
|
||||
|
||||
<input type="hidden" name="formkey" value="{{formkey}}">
|
||||
<input type="hidden" name="now" value="{{now}}">
|
||||
|
||||
{% if redirect %}<input type="hidden" name="redirect" value="{{redirect}}">{% endif %}
|
||||
{% if ref_user %}
|
||||
<input type="hidden" name="referred_by" value="{{ref_user.id}}">{% endif %}
|
||||
|
||||
<label for="username-register" class="mt-3">Username</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="username-register"
|
||||
aria-describedby="usernameHelpRegister" type="text" name="username" pattern="[a-zA-Z0-9_\-]{3,25}" min="3" max="25" required autofocus tabindex="1">
|
||||
<small id="usernameHelpRegister"></small>
|
||||
|
||||
<label for="email-register" class="mt-3">Email Address</label>
|
||||
|
||||
<small class="d-inline-block text-muted ml-1">(optional)</small>
|
||||
|
||||
<input style="background-color: var(--gray-800)" autocomplete="off" class="form-control" id="email-register"
|
||||
aria-describedby="emailHelpRegister" type="email" pattern='[^@]+@[^@]+\.[^@]+' name="email" tabindex="2">
|
||||
|
||||
<label for="password-register" class="mt-3">Password</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="password-register"
|
||||
aria-describedby="passwordHelpReigster" type="password" name="password" required tabindex="4">
|
||||
<small id="passwordHelpRegister" class="form-text font-weight-bold text-muted d-none mt-1">Minimum of 8
|
||||
characters
|
||||
required.</small>
|
||||
<small id="passwordHelpSuccess" class="form-text font-weight-bold text-success d-none mt-1">Your password meets the requirements.
|
||||
</small>
|
||||
|
||||
<label for="password_confirm" class="mt-3">Confirm Password</label>
|
||||
|
||||
<input autocomplete="off" class="form-control" id="password_confirm"
|
||||
aria-describedby="passwordConfirmHelp" type="password" name="password_confirm"
|
||||
required tabindex="5">
|
||||
<div class="custom-control custom-checkbox mt-4">
|
||||
<input autocomplete="off" type="checkbox" class="custom-control-input" id="termsCheck" required tabindex="6">
|
||||
<label class="custom-control-label terms" for="termsCheck">I accept the <a href="/rules" tabindex="8">rules</a></label>
|
||||
</div>
|
||||
|
||||
{% if hcaptcha %}
|
||||
<div class="h-captcha" data-sitekey="{{hcaptcha}}"></div>
|
||||
{% endif %}
|
||||
|
||||
<button class="btn btn-primary login w-100 mt-3" id="register_button" tabindex="7">Register</button>
|
||||
|
||||
<div class="text-center text-muted text-small mt-2 mb-0">
|
||||
Already have an account? <a href="/login{{'?redirect='+redirect if redirect else ''}}" class="font-weight-bold toggle-login" tabindex="9">Log in</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 d-none d-md-block">
|
||||
|
||||
<div class="splash-wrapper">
|
||||
|
||||
<div class="splash-overlay"></div>
|
||||
|
||||
<img alt="cover" loading="lazy" class="splash-img" src="{{ ('images/'~SITE_ID~'/cover.webp') | asset }}"></img>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ 'js/signup.js' | asset }}"></script>
|
||||
|
||||
{% if hcaptcha %}
|
||||
<script src="{{ 'js/hcaptcha.js' | asset }}"></script>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,106 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
{% include "analytics.html" %}
|
||||
|
||||
<meta name="description" content="{{config('DESCRIPTION')}}">
|
||||
{% include "csp.html" %}
|
||||
|
||||
<script src="{{ 'js/bootstrap.js' | asset }}"></script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<meta name="author" content="">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:title" content="{{SITE_TITLE}}">
|
||||
<meta property="og:site_name" content="{{request.host}}">
|
||||
<meta property="og:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
|
||||
<meta property="og:url" content="{{request.host}}">
|
||||
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">
|
||||
<meta property="og:author" name="author" content="{{SITE_FULL}}">
|
||||
<meta property="og:site_name" content="{{request.host}}">
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:site" content="{{SITE_FULL}}">
|
||||
<meta name="twitter:title" content="{{SITE_TITLE}}">
|
||||
<meta name="twitter:creator" content="{{SITE_FULL}}">
|
||||
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
|
||||
<meta name="twitter:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
|
||||
<meta name="twitter:url" content="{{request.host}}">
|
||||
|
||||
<title>{% if ref_user %}{{ref_user.username}} invites you to {{SITE_TITLE}}{% else %}{{SITE_TITLE}}{% endif %}</title>
|
||||
|
||||
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
|
||||
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
|
||||
<link rel="stylesheet" href="{{ ('css/'~config('DEFAULT_THEME')~'.css') | asset }}">
|
||||
|
||||
</head>
|
||||
|
||||
<body id="login">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-transparent fixed-top border-0">
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler d-none" role="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid position-absolute h-100 p-0">
|
||||
<div class="row no-gutters h-100">
|
||||
|
||||
<div class="col-12 col-md-6 my-auto p-3">
|
||||
|
||||
<div class="row justify-content-center">
|
||||
|
||||
<div class="col-10 col-md-7">
|
||||
|
||||
<div class="text-center mb-5">
|
||||
<a href="/" class="text-decoration-none"><span class="h3 text-primary"></span></a>
|
||||
</div>
|
||||
|
||||
<div id="register-form" class="">
|
||||
<h1 class="h4 font-weight-normal text-center">Whoops! You can't refer yourself!</h1>
|
||||
<p class="text-center text-muted mb-md-5">Send this link to a friend instead :)</p>
|
||||
<label>Referral code</label>
|
||||
<input autocomplete="off" type="text" class="form-control copy-link" readonly value="{{SITE_FULL}}/signup?ref={{request.values.get('ref')}}" data-clipboard-text="{{SITE_FULL}}/signup?ref={{request.values.get('ref')}}">
|
||||
|
||||
<div class="text-center mt-5 mb-3">
|
||||
Already have an account? <a href="/login" class="font-weight-bold text-small toggle-login">Log in.</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 d-none d-md-block">
|
||||
|
||||
<div class="splash-wrapper">
|
||||
|
||||
<div class="splash-overlay"></div>
|
||||
|
||||
<img alt="cover" loading="lazy" class="splash-img" src="{{ ('images/'~SITE_ID~'/cover.webp') | asset }}"></img>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="toast clipboard" id="toast-success" role="alert" aria-live="assertive" aria-atomic="true" data-bs-animation="true" data-bs-autohide="true" data-bs-delay="5000">
|
||||
<div class="toast-body text-center">
|
||||
<i class="fas fa-check-circle text-success mr-2"></i>Link copied to clipboard
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue