Completed first-round updates for the user profile edit view.

This commit is contained in:
Matt Scott 2023-02-20 12:08:32 -05:00
parent 2980e5cec9
commit f977a42cea
5 changed files with 617 additions and 556 deletions

View File

@ -1,6 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Log In - {{ SITE_NAME }}</title>
@ -14,10 +14,10 @@
{% if SETTING.get('custom_css') %}
<link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}">
{% endif %}
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="card card-outline card-primary">
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="card card-outline card-primary shadow">
<div class="card-header text-center">
<a href="{{ url_for('index.index') }}" class="h3">
{% if SETTING.get('site_name') %}
@ -38,16 +38,21 @@
<form action="" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<input type="text" class="form-control" placeholder="Username" name="username" data-error="Please input your username" required {% if username %}value="{{ username }}" {% endif %}>
<input type="text" class="form-control" placeholder="Username" name="username"
data-error="Please input your username" required
{% if username %}value="{{ username }}" {% endif %}>
<span class="help-block with-errors"></span>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Password" name="password" data-error="Please input your password" required {% if password %}value="{{ password }}" {% endif %}>
<input type="password" class="form-control" placeholder="Password" name="password"
data-error="Please input your password" required
{% if password %}value="{{ password }}" {% endif %}>
<span class="help-block with-errors"></span>
</div>
{% if SETTING.get('otp_field_enabled') %}
<div class="form-group">
<input type="otptoken" class="form-control" placeholder="OTP Token" name="otptoken" autocomplete="off">
<input type="otptoken" class="form-control" placeholder="OTP Token" name="otptoken"
autocomplete="off">
</div>
{% endif %}
{% if SETTING.get('ldap_enabled') and SETTING.get('local_db_enabled') %}
@ -101,25 +106,29 @@
<p>- OR -</p>
{% endif %}
{% if SETTING.get('oidc_oauth_enabled') %}
<a href="{{ url_for('index.oidc_login') }}" class="btn btn-block btn-social btn-openid btn-flat">
<a href="{{ url_for('index.oidc_login') }}"
class="btn btn-block btn-social btn-openid btn-flat">
<i class="fa-brands fa-openid"></i>
Sign in using OpenID Connect
</a>
{% endif %}
{% if SETTING.get('github_oauth_enabled') %}
<a href="{{ url_for('index.github_login') }}" class="btn btn-block btn-social btn-github btn-flat">
<a href="{{ url_for('index.github_login') }}"
class="btn btn-block btn-social btn-github btn-flat">
<i class="fa-brands fa-github"></i>
Sign in using Github
</a>
{% endif %}
{% if SETTING.get('google_oauth_enabled') %}
<a href="{{ url_for('index.google_login') }}" class="btn btn-block btn-social btn-google btn-flat">
<a href="{{ url_for('index.google_login') }}"
class="btn btn-block btn-social btn-google btn-flat">
<i class="fa-brands fa-google"></i>
Sign in using Google
</a>
{% endif %}
{% if SETTING.get('azure_oauth_enabled') %}
<a href="{{ url_for('index.azure_login') }}" class="btn btn-block btn-social btn-microsoft btn-flat">
<a href="{{ url_for('index.azure_login') }}"
class="btn btn-block btn-social btn-microsoft btn-flat">
<i class="fa-brands fa-windows"></i>
Sign in using Microsoft Azure
</a>
@ -144,20 +153,21 @@
{% endif %}
{% endif %}
</div>
<!-- /.card-body -->
</div>
<div class="login-box-footer">
<center>
<p>Powered by <a href="https://github.com/PowerDNS-Admin/PowerDNS-Admin">PowerDNS-Admin</a></p>
</center>
</div>
</div>
{% assets "js_login" -%}
<!-- /.card -->
</div>
<!-- /.login-box -->
<div class="text-center pt-3">
<p>Powered by <a href="https://powerdnsadmin.org" target="_blank">PowerDNS-Admin</a></p>
</div>
{% assets "js_login" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% assets "js_validation" -%}
{%- endassets %}
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
<script>
{%- endassets %}
<script>
$(function () {
$('input').iCheck({
checkboxClass: 'icheckbox_square-blue',
@ -165,6 +175,6 @@
increaseArea: '20%' // optional
});
});
</script>
</body>
</script>
</body>
</html>

View File

@ -1,6 +1,8 @@
<!doctype html>
<title>Site Maintenance</title>
<style>
<!DOCTYPE html>
<html lang="en" class>
<head>
<title>Site Maintenance</title>
<style>
body {
text-align: center;
padding: 150px;
@ -31,13 +33,17 @@
color: #333;
text-decoration: none;
}
</style>
</style>
</head>
<body>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we&rsquo;re performing some maintenance at the moment. Please contact the System
<p>Sorry for the inconvenience but we&rsquo;re performing some maintenance at the moment. Please contact the
System
Administrator if you need more information, otherwise we&rsquo;ll be back online shortly!</p>
<p>&mdash; Team</p>
</div>
</article>
</body>
</html>

View File

@ -1,7 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Register - {{ SITE_NAME }}</title>
@ -12,11 +11,11 @@
{% assets "css_login" -%}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{%- endassets %}
</head>
</head>
<body class="hold-transition register-page">
<div class="register-box">
<div class="card card-outline card-primary">
<body class="hold-transition register-page">
<div class="register-box">
<div class="card card-outline card-primary shadow">
<div class="card-header text-center">
<a href="{{ url_for('index.index') }}" class="h3">
{% if SETTING.get('site_name') %}
@ -44,7 +43,10 @@
<i class="fas fa-user"></i>
</span>
</div>
<input type="text" class="form-control {{ 'is-invalid' if 'firstname' in error_messages else '' }}" placeholder="First Name" name="firstname" id="firstname" value="{{ request.form.firstname }}" required>
<input type="text"
class="form-control {{ 'is-invalid' if 'firstname' in error_messages else '' }}"
placeholder="First Name" name="firstname" id="firstname"
value="{{ request.form.firstname }}" required>
{% if 'firstname' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -61,7 +63,10 @@
<i class="fas fa-user"></i>
</span>
</div>
<input type="text" class="form-control {{ 'is-invalid' if 'lastname' in error_messages else '' }}" placeholder="Last name" name="lastname" id="lastname" value="{{ request.form.lastname }}" required>
<input type="text"
class="form-control {{ 'is-invalid' if 'lastname' in error_messages else '' }}"
placeholder="Last name" name="lastname" id="lastname" value="{{ request.form.lastname }}"
required>
{% if 'lastname' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -78,7 +83,8 @@
<i class="fas fa-envelope"></i>
</span>
</div>
<input type="email" class="form-control {{ 'is-invalid' if 'email' in error_messages else '' }}" placeholder="Email" name="email" id="email" value="{{ request.form.email }}" required>
<input type="email" class="form-control {{ 'is-invalid' if 'email' in error_messages else '' }}"
placeholder="Email" name="email" id="email" value="{{ request.form.email }}" required>
{% if 'email' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -97,7 +103,10 @@
<i class="fas fa-user"></i>
</span>
</div>
<input type="text" class="form-control {{ 'is-invalid' if 'username' in error_messages else '' }}" placeholder="Username" name="username" id="username" value="{{ request.form.username }}" required>
<input type="text"
class="form-control {{ 'is-invalid' if 'username' in error_messages else '' }}"
placeholder="Username" name="username" id="username" value="{{ request.form.username }}"
required>
{% if 'username' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -114,7 +123,9 @@
<i class="fas fa-lock"></i>
</span>
</div>
<input type="password" class="form-control {{ 'is-invalid' if 'password' in error_messages else '' }}" placeholder="Password" id="password" name="password" required>
<input type="password"
class="form-control {{ 'is-invalid' if 'password' in error_messages else '' }}"
placeholder="Password" id="password" name="password" required>
{% if 'password' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -131,7 +142,9 @@
<i class="fas fa-lock"></i>
</span>
</div>
<input type="password" class="form-control {{ 'is-invalid' if 'rpassword' in error_messages else '' }}" placeholder="Retype password" id="rpassword" name="rpassword" required>
<input type="password"
class="form-control {{ 'is-invalid' if 'rpassword' in error_messages else '' }}"
placeholder="Retype password" id="rpassword" name="rpassword" required>
{% if 'rpassword' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -151,7 +164,9 @@
<i class="fas fa-shield-alt"></i>
</span>
</div>
<input type="text" class="form-control {{ 'is-invalid' if 'captcha_result' in error_messages else '' }}" placeholder="CAPTCHA" id="captcha" name="captcha" required>
<input type="text"
class="form-control {{ 'is-invalid' if 'captcha_result' in error_messages else '' }}"
placeholder="CAPTCHA" id="captcha" name="captcha" required>
{% if 'captcha_result' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
@ -169,24 +184,26 @@
</div>
</form>
</div>
<div class="login-box-footer">
<center>
<p>Powered by <a href="https://github.com/PowerDNS-Admin/PowerDNS-Admin">PowerDNS-Admin</a></p>
</center>
<!-- /.card-body -->
</div>
</div>
{% assets "js_login" -%}
<!-- /.card -->
</div>
<!-- /.register-box -->
<div class="text-center pt-3">
<p>Powered by <a href="https://powerdnsadmin.org" target="_blank">PowerDNS-Admin</a></p>
</div>
{% assets "js_login" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% assets "js_validation" -%}
{%- endassets %}
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
<script>
{%- endassets %}
<script>
$(function () {
$('#button_back').click(function () {
window.location.href = '{{ url_for('index.login') }}';
})
});
</script>
</body>
</script>
</body>
</html>

View File

@ -1,7 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Welcome - {{ SITE_NAME }}</title>
@ -14,10 +13,9 @@
{% if SETTING.get('custom_css') %}
<link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}">
{% endif %}
</head>
<body class="hold-transition register-page">
<div class="register-box">
</head>
<body class="hold-transition register-page">
<div class="register-box">
<div class="register-logo">
<a><b>PowerDNS</b>-Admin</a>
</div>
@ -28,35 +26,36 @@
{{ error }}
</div>
{% endif %}
Welcome, {{user.firstname}}! <br />
You will need a Token on login. <br />
Welcome, {{ user.firstname }}! <br/>
You will need a Token on login. <br/>
Your QR code is:
<div id="token_information">
{% if qrcode_image == None %}
<p><img id="qrcode" src="{{ url_for('user.qrcode') }}"></p>
{% else %}
<p><img id="qrcode" src="data:image/svg+xml;utf8;base64, {{qrcode_image}}"></p>
<p><img id="qrcode" src="data:image/svg+xml;utf8;base64, {{ qrcode_image }}"></p>
{% endif %}
<p>
Your secret key is: <br />
Your secret key is: <br/>
<form>
<input type=text id="otp_secret" value={{user.otp_secret}} readonly>
<button type=button style="position:relative; right:28px" onclick="copy_otp_secret_to_clipboard()"> <i class="fa fa-clipboard"></i> </button>
<br /><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
<input type=text id="otp_secret" value={{ user.otp_secret }} readonly>
<button type=button style="position:relative; right:28px" onclick="copy_otp_secret_to_clipboard()"><i
class="fa fa-clipboard"></i></button>
<br/><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
</form>
</p>
You can use Google Authenticator (<a target="_blank"
href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Android</a>
- <a target="_blank"
href="https://apps.apple.com/us/app/google-authenticator/id388497605">iOS</a>)
<br />
<br/>
or FreeOTP (<a target="_blank"
href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en">Android</a>
- <a target="_blank"
href="https://itunes.apple.com/en/app/freeotp-authenticator/id872559395?mt=8">iOS</a>)
on your smartphone <br /> to scan the QR code or type the secret key.
<br /> <br />
<font color="red"><strong><i>Make sure only you can see this QR Code <br />
on your smartphone <br/> to scan the QR code or type the secret key.
<br/> <br/>
<font color="red"><strong><i>Make sure only you can see this QR Code <br/>
and secret key, and nobody can capture them.</i></strong></font>
</div>
</br>
@ -74,17 +73,17 @@
</div>
</form>
</div>
<div class="login-box-footer">
<center>
<p>Powered by <a href="https://github.com/PowerDNS-Admin/PowerDNS-Admin">PowerDNS-Admin</a></p>
</center>
<!-- /.register-box-body -->
<div class="text-center">
<p>Powered by <a href="https://powerdnsadmin.org" target="_blank">PowerDNS-Admin</a></p>
</div>
</div>
</body>
{% assets "js_login" -%}
</div>
<!-- /.register-box -->
</body>
{% assets "js_login" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% assets "js_validation" -%}
{%- endassets %}
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{%- endassets %}
</html>

View File

@ -1,27 +1,18 @@
{% extends "base.html" %}
{% set active_page = "user_profile" %}
{% block title %}
<title>
My Profile - {{ SITE_NAME }}
</title>
{% endblock %}
{% block title %}<title>Edit Profile - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %}
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark">
User
<small>My Profile</small>
</h1>
<h1 class="m-0 text-dark">Edit Profile</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item active">My Profile</li>
<li class="breadcrumb-item active">Edit Profile</li>
</ol>
</div>
</div>
@ -30,13 +21,17 @@
{% endblock %}
{% block content %}
<section class="content">
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-6">
<div class="card">
<div class="col-12 col-sm-6">
<div class="card card-outline card-primary shadow">
<div class="card-header">
<div class="nav-tabs-custom">
<h3 class="card-title">Profile Editor</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
<div class="nav-tabs-custom mb-2">
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" href="#tabs-personal" data-toggle="tab">
@ -58,63 +53,79 @@
</li>
{% endif %}
</ul>
<div class="card-body">
</div>
<!-- /.nav-tabs-custom -->
<div class="tab-content">
<div class="tab-pane fade show active" id="tabs-personal">
<form role="form" method="post" action="{{ user_profile }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<label for="firstname">First Name</label>
<input type="text" class="form-control" name="firstname" id="firstname" placeholder="{{ current_user.firstname }}"
<input type="text" class="form-control" name="firstname"
id="firstname" placeholder="{{ current_user.firstname }}"
{% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div>
<div class="form-group">
<label for="lastname">Last Name</label>
<input type="text" class="form-control" name="lastname" id="lastname" placeholder="{{ current_user.lastname }}"
<input type="text" class="form-control" name="lastname"
id="lastname" placeholder="{{ current_user.lastname }}"
{% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div>
<div class="form-group">
<label for="email">E-Mail</label> <input type="email" class="form-control" name="email" id="email" placeholder="{{ current_user.email }}"
<label for="email">E-Mail</label> <input type="email"
class="form-control"
name="email" id="email"
placeholder="{{ current_user.email }}"
{% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div>
{% if session['authentication_type'] == 'LOCAL' %}
<div class="form-group">
<button type="submit" class="btn btn-primary">
<i class="fa-solid fa-floppy-disk"></i>&nbsp;Save
<button type="submit" class="btn btn-primary" title="Save Profile">
<i class="fa-solid fa-floppy-disk"></i>&nbsp;Save Profile
</button>
</div>
{% endif %}
</form>
</div>
<!-- /.tab-pane -->
{% if session['authentication_type'] == 'LOCAL' %}
<div class="tab-pane fade" id="tabs-password">
{% if not current_user.password %}
Your account password is managed via LDAP which isn't supported to change here.
Your account password is managed via LDAP which isn't supported to
change here.
{% else %}
<form action="{{ user_profile }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="_csrf_token"
value="{{ csrf_token() }}">
<div class="form-group">
<label for="password">New Password</label>
<input type="password" class="form-control" name="password" id="newpassword">
<input type="password" class="form-control" name="password"
id="newpassword">
</div>
<div class="form-group">
<label for="rpassword">Re-type New Password</label>
<input type="password" class="form-control" name="rpassword" id="rpassword">
<input type="password" class="form-control" name="rpassword"
id="rpassword">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">
<i class="fa-solid fa-floppy-disk"></i>&nbsp;Save
<button type="submit" class="btn btn-primary" title="Save Password">
<i class="fa-solid fa-floppy-disk"></i>&nbsp;Save Password
</button>
</div>
</form>
{% endif %}
</div>
<!-- /.tab-pane -->
{% endif %}
<div class="tab-pane fade" id="tabs-authentication">
<form action="{{ user_profile }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<input type="checkbox" id="otp_toggle" class="otp_toggle" {% if current_user.otp_secret %}checked{% endif %}>
<input type="checkbox" id="otp_toggle" class="otp_toggle"
{% if current_user.otp_secret %}checked{% endif %}>
<label for="otp_toggle">Enable Two Factor Authentication</label>
{% if current_user.otp_secret %}
<div id="token_information">
@ -123,47 +134,65 @@
</p>
<div style="position: relative; left: 15px">
Your secret key is:
<br />
<br/>
<form>
<input type=text id="otp_secret" value={{current_user.otp_secret}} readonly>
<button type=button style="position:relative; right:28px" onclick="copy_otp_secret_to_clipboard()">
<input type=text id="otp_secret"
value={{ current_user.otp_secret }} readonly>
<button type=button
style="position:relative; right:28px"
onclick="copy_otp_secret_to_clipboard()">
<i class="fa-solid fa-clipboard"></i>
</button>
<br />
<font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
<br/>
<span style="color: red;" id="copy_tooltip"
style="visibility:collapse">Copied.</span>
</form>
</div>
You can use Google Authenticator
(<a target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2"><i class="fa-brands fa-google-play"></i>Android</a>
- <a target="_blank" href="https://apps.apple.com/us/app/google-authenticator/id388497605"><i class="fa-brands fa-app-store-ios"></i>iOS</a>)
(<a target="_blank"
href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2"><i
class="fa-brands fa-google-play"></i>Android</a>
- <a target="_blank"
href="https://apps.apple.com/us/app/google-authenticator/id388497605"><i
class="fa-brands fa-app-store-ios"></i>iOS</a>)
or FreeOTP
(<a target="_blank" href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en"><i class="fa-brands fa-google-play"></i>Android</a>
- <a target="_blank" href="https://itunes.apple.com/en/app/freeotp-authenticator/id872559395?mt=8"><i class="fa-brands fa-app-store-ios"></i>iOS</a>)
(<a target="_blank"
href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en"><i
class="fa-brands fa-google-play"></i>Android</a>
- <a target="_blank"
href="https://itunes.apple.com/en/app/freeotp-authenticator/id872559395?mt=8"><i
class="fa-brands fa-app-store-ios"></i>iOS</a>)
on your smartphone to scan the QR code.
<br />
<font color="red">
<strong>
<i>Make sure only you can see this QR Code and secret key and
<br/>
<p style="color: red; font-style: italic; font-weight: bold;">
Make sure only you can see this QR Code and
secret key and
nobody can capture them.
</i>
</strong>
</font>
</p>
</div>
{% endif %}
</div>
<!-- /.form-group -->
</form>
</div>
<!-- /.tab-pane -->
</div>
<!-- /.tab-content -->
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</div>
</div>
</section>
<!-- /.container-fluid -->
</section>
{% endblock %}
{% block extrascripts %}
<script>
<script>
// initialize pretty checkboxes
$('.otp_toggle').iCheck({
@ -172,7 +201,7 @@
});
// handle checkbox toggling
$('.otp_toggle').on('ifToggled', function(event) {
$('.otp_toggle').on('ifToggled', function (event) {
var enable_otp = $(this).prop('checked');
var postdata = {
'action': 'enable_otp',
@ -181,10 +210,10 @@
},
'_csrf_token': '{{ csrf_token() }}'
};
applyChanges(postdata, $SCRIPT_ROOT + '/user/profile', false, true, function() {
applyChanges(postdata, $SCRIPT_ROOT + '/user/profile', false, true, function () {
window.location.reload();
$('#tabs li:eq(2) a').tab('show');
});
});
</script>
</script>
{% endblock %}