chg: usr: add forgot password functionality #4
This commit is contained in:
60
templates/Security/forgot_password.html.twig
Normal file
60
templates/Security/forgot_password.html.twig
Normal file
@@ -0,0 +1,60 @@
|
||||
{% extends 'Game/index.html.twig' %}
|
||||
|
||||
{% block title %} - Forgot Password{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="auth-page">
|
||||
|
||||
{% for email in app.flashes('reset_sent') %}
|
||||
<div class="auth-card auth-card--sent">
|
||||
<div class="auth-sent-icon"><i class="fa fa-envelope-o"></i></div>
|
||||
<h2 class="auth-title">Check your inbox</h2>
|
||||
<p class="auth-sub">If an account exists for that address, we sent a reset link to</p>
|
||||
<p class="auth-sent-email">{{ email }}</p>
|
||||
<p class="auth-sent-note">
|
||||
Click the link in the email to reset your password.<br>
|
||||
The link expires in <strong>1 hour</strong>.
|
||||
</p>
|
||||
<a href="{{ path('MineSeekerBundle_login') }}" class="auth-submit"
|
||||
style="text-decoration:none; margin-top:16px;">
|
||||
Go to Sign In
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Forgot Password</h2>
|
||||
<p class="auth-sub">Enter your email and we'll send you a reset link</p>
|
||||
|
||||
<form class="auth-form" method="post" action="{{ path('MineSeekerBundle_forgot_password') }}">
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="email" class="auth-label">Email</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-envelope auth-input-icon"></i>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="_email"
|
||||
class="auth-input"
|
||||
autocomplete="email"
|
||||
autofocus
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-paper-plane"></i> Send Reset Link
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="auth-switch">
|
||||
Remembered it?
|
||||
<a href="{{ path('MineSeekerBundle_login') }}">Sign in</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -3,81 +3,85 @@
|
||||
{% block title %} - Sign In{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="auth-page">
|
||||
<div class="auth-page">
|
||||
|
||||
{% for message in app.flashes('success') %}
|
||||
<div class="auth-flash auth-flash--success">
|
||||
<i class="fa fa-check-circle"></i> {{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for message in app.flashes('success') %}
|
||||
<div class="auth-flash auth-flash--success">
|
||||
<i class="fa fa-check-circle"></i> {{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% for message in app.flashes('error') %}
|
||||
<div class="auth-flash auth-flash--error">
|
||||
<i class="fa fa-exclamation-triangle"></i> {{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for message in app.flashes('error') %}
|
||||
<div class="auth-flash auth-flash--error">
|
||||
<i class="fa fa-exclamation-triangle"></i> {{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Sign In</h2>
|
||||
<p class="auth-sub">Welcome back, commander</p>
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Sign In</h2>
|
||||
<p class="auth-sub">Welcome back, commander</p>
|
||||
|
||||
{% if error %}
|
||||
<div class="auth-error">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
{{ error.messageKey|trans(error.messageData, 'security') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if error %}
|
||||
<div class="auth-error">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
{{ error.messageKey|trans(error.messageData, 'security') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form class="auth-form" method="post" action="{{ path('MineSeekerBundle_login') }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
|
||||
<form class="auth-form" method="post" action="{{ path('MineSeekerBundle_login') }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="username" class="auth-label">Username</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-user auth-input-icon"></i>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="_username"
|
||||
class="auth-input"
|
||||
value="{{ last_username }}"
|
||||
autocomplete="username"
|
||||
autofocus
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password" class="auth-label">Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="_password"
|
||||
class="auth-input"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="auth-remember">
|
||||
<input type="checkbox" name="_remember_me"/>
|
||||
<span>Remember me</span>
|
||||
</label>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-sign-in"></i> Sign In
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="auth-switch">
|
||||
No account yet?
|
||||
<a href="{{ path('MineSeekerBundle_register') }}">Create one</a>
|
||||
</p>
|
||||
<div class="auth-field">
|
||||
<label for="username" class="auth-label">Username</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-user auth-input-icon"></i>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="_username"
|
||||
class="auth-input"
|
||||
value="{{ last_username }}"
|
||||
autocomplete="username"
|
||||
autofocus
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password" class="auth-label">Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="_password"
|
||||
class="auth-input"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="auth-remember">
|
||||
<input type="checkbox" name="_remember_me"/>
|
||||
<span>Remember me</span>
|
||||
</label>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-sign-in"></i> Sign In
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="auth-switch">
|
||||
<a href="{{ path('MineSeekerBundle_forgot_password') }}">Forgot your password?</a>
|
||||
</p>
|
||||
|
||||
<p class="auth-switch">
|
||||
No account yet?
|
||||
<a href="{{ path('MineSeekerBundle_register') }}">Create one</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
57
templates/Security/reset_password.html.twig
Normal file
57
templates/Security/reset_password.html.twig
Normal file
@@ -0,0 +1,57 @@
|
||||
{% extends 'Game/index.html.twig' %}
|
||||
|
||||
{% block title %} - Reset Password{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="auth-page">
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Reset Password</h2>
|
||||
<p class="auth-sub">Choose a new password for your account</p>
|
||||
|
||||
<form class="auth-form" method="post">
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password" class="auth-label">New Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="_password"
|
||||
class="auth-input{% if errors.password is defined %} auth-input--error{% endif %}"
|
||||
autocomplete="new-password"
|
||||
autofocus
|
||||
required
|
||||
minlength="6"
|
||||
/>
|
||||
</div>
|
||||
{% if errors.password is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password_confirm" class="auth-label">Confirm New Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password_confirm"
|
||||
name="_password_confirm"
|
||||
class="auth-input{% if errors.password_confirm is defined %} auth-input--error{% endif %}"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{% if errors.password_confirm is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.password_confirm }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-key"></i> Set New Password
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
121
templates/emails/reset_password.html.twig
Normal file
121
templates/emails/reset_password.html.twig
Normal file
@@ -0,0 +1,121 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<title>Reset your MineSeeker password</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #07090d;
|
||||
font-family: Arial, sans-serif;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
text-align: center;
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #0f1923;
|
||||
border: 1px solid rgba(35, 111, 135, 0.25);
|
||||
border-radius: 10px;
|
||||
padding: 40px 36px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 1px;
|
||||
margin: 0 0 10px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.sub {
|
||||
font-size: 14px;
|
||||
color: rgba(149, 207, 245, 0.7);
|
||||
margin: 0 0 28px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
line-height: 1.7;
|
||||
margin: 0 0 24px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
background: linear-gradient(to bottom, #ad0a05, #f67d52);
|
||||
color: #ffffff !important;
|
||||
text-decoration: none;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
padding: 16px 48px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.fallback {
|
||||
margin-top: 24px;
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.fallback a {
|
||||
color: rgba(149, 207, 245, 0.5);
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 32px;
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="logo">
|
||||
<img src="{{ absolute_url(asset('images/mine-logo-txt.png')) }}" alt="MineSeeker"/>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h1>Reset your password</h1>
|
||||
<p class="sub">This link expires in 1 hour</p>
|
||||
<p>
|
||||
Hi <strong>{{ username }}</strong>,<br>
|
||||
We received a request to reset the password for your MineSeeker account.
|
||||
Click the button below to choose a new password.
|
||||
</p>
|
||||
<p>
|
||||
<a class="btn" href="{{ reset_url }}">Reset Password</a>
|
||||
</p>
|
||||
<p class="fallback">
|
||||
If the button doesn't work, copy and paste this link into your browser:<br>
|
||||
<a href="{{ reset_url }}">{{ reset_url }}</a>
|
||||
</p>
|
||||
<p style="margin-top:24px; font-size:13px; color:rgba(255,255,255,0.35);">
|
||||
If you didn't request a password reset, you can safely ignore this email.
|
||||
Your password will not change.
|
||||
</p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© {{ "now"|date("Y") }} MineSeeker • This link expires in 1 hour.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user