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> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Log In - {{ SITE_NAME }}</title> <title>Log In - {{ SITE_NAME }}</title>
@ -9,162 +9,172 @@
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<META HTTP-EQUIV="REFRESH" CONTENT="{{ 60 * SETTING.get('session_timeout') }}"> <META HTTP-EQUIV="REFRESH" CONTENT="{{ 60 * SETTING.get('session_timeout') }}">
{% assets "css_login" -%} {% assets "css_login" -%}
<link rel="stylesheet" href="{{ ASSET_URL }}"> <link rel="stylesheet" href="{{ ASSET_URL }}">
{%- endassets %} {%- endassets %}
{% if SETTING.get('custom_css') %} {% if SETTING.get('custom_css') %}
<link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}"> <link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}">
{% endif %} {% endif %}
</head> </head>
<body class="hold-transition login-page"> <body class="hold-transition login-page">
<div class="login-box"> <div class="login-box">
<div class="card card-outline card-primary"> <div class="card card-outline card-primary shadow">
<div class="card-header text-center"> <div class="card-header text-center">
<a href="{{ url_for('index.index') }}" class="h3"> <a href="{{ url_for('index.index') }}" class="h3">
{% if SETTING.get('site_name') %} {% if SETTING.get('site_name') %}
{{ SITE_NAME }} {{ SITE_NAME }}
{% else %} {% else %}
<b>PowerDNS</b>-Admin <b>PowerDNS</b>-Admin
{% endif %} {% endif %}
</a> </a>
</div> </div>
<div class="card-body login-card-body"> <div class="card-body login-card-body">
{% if error %} {% if error %}
<div class="alert alert-danger alert-dismissible"> <div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ error }} {{ error }}
</div>
{% endif %}
{% if SETTING.get('ldap_enabled') or SETTING.get('local_db_enabled') %}
<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 %}>
<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 %}>
<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">
</div> </div>
{% endif %}
{% if SETTING.get('ldap_enabled') and SETTING.get('local_db_enabled') %}
<div class="form-group">
<select class="form-control" name="auth_method">
<option value="LOCAL">
LOCAL Authentication
</option>
{% if SETTING.get('login_ldap_first') %}
<option value="LDAP" selected="selected">
LDAP Authentication
</option>
{% else %}
<option value="LDAP">
LDAP Authentication
</option>
{% endif %}
</select>
</div>
{% elif SETTING.get('ldap_enabled') and not SETTING.get('local_db_enabled') %}
<div class="form-group">
<input type="hidden" name="auth_method" value="LDAP">
</div>
{% elif SETTING.get('local_db_enabled') and not SETTING.get('ldap_enabled') %}
<div class="form-group">
<input type="hidden" name="auth_method" value="LOCAL">
</div>
{% else %}
<div class="form-group">
<input type="hidden" name="auth_method" value="LOCAL">
</div>
{% endif %}
<div class="row">
<div class="col-8">
<div class="icheck-primary">
<input type="checkbox" id="remember">
<label for="remember">
Remember Me
</label>
</div>
</div>
<div class="col-4">
<button type="submit" class="btn btn-primary btn-block">Sign In</button>
</div>
</div>
</form>
{% endif %}
{% if SETTING.get('google_oauth_enabled') or SETTING.get('github_oauth_enabled') or SETTING.get('oidc_oauth_enabled') or SETTING.get('azure_oauth_enabled') %}
<div class="social-auth-links text-center">
{% if SETTING.get('ldap_enabled') or SETTING.get('local_db_enabled') %}
<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">
<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">
<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">
<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">
<i class="fa-brands fa-windows"></i>
Sign in using Microsoft Azure
</a>
{% endif %}
</div>
{% endif %}
{% if saml_enabled %}
<a href="{{ url_for('index.saml_login') }}">
SAML login
</a>
{% endif %}
{% if SETTING.get('signup_enabled') %}
<br>
<a href="{{ url_for('index.register') }}" class="text-center">
Create an account
</a>
{% if SETTING.get('verify_user_email') %}
<br/>
<a href="{{ url_for('index.resend_confirmation_email') }}" class="text-center">
Resend confirmation email
</a>
{% endif %} {% endif %}
{% endif %} {% if SETTING.get('ldap_enabled') or SETTING.get('local_db_enabled') %}
<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 %}>
<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 %}>
<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">
</div>
{% endif %}
{% if SETTING.get('ldap_enabled') and SETTING.get('local_db_enabled') %}
<div class="form-group">
<select class="form-control" name="auth_method">
<option value="LOCAL">
LOCAL Authentication
</option>
{% if SETTING.get('login_ldap_first') %}
<option value="LDAP" selected="selected">
LDAP Authentication
</option>
{% else %}
<option value="LDAP">
LDAP Authentication
</option>
{% endif %}
</select>
</div>
{% elif SETTING.get('ldap_enabled') and not SETTING.get('local_db_enabled') %}
<div class="form-group">
<input type="hidden" name="auth_method" value="LDAP">
</div>
{% elif SETTING.get('local_db_enabled') and not SETTING.get('ldap_enabled') %}
<div class="form-group">
<input type="hidden" name="auth_method" value="LOCAL">
</div>
{% else %}
<div class="form-group">
<input type="hidden" name="auth_method" value="LOCAL">
</div>
{% endif %}
<div class="row">
<div class="col-8">
<div class="icheck-primary">
<input type="checkbox" id="remember">
<label for="remember">
Remember Me
</label>
</div>
</div>
<div class="col-4">
<button type="submit" class="btn btn-primary btn-block">Sign In</button>
</div>
</div>
</form>
{% endif %}
{% if SETTING.get('google_oauth_enabled') or SETTING.get('github_oauth_enabled') or SETTING.get('oidc_oauth_enabled') or SETTING.get('azure_oauth_enabled') %}
<div class="social-auth-links text-center">
{% if SETTING.get('ldap_enabled') or SETTING.get('local_db_enabled') %}
<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">
<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">
<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">
<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">
<i class="fa-brands fa-windows"></i>
Sign in using Microsoft Azure
</a>
{% endif %}
</div>
{% endif %}
{% if saml_enabled %}
<a href="{{ url_for('index.saml_login') }}">
SAML login
</a>
{% endif %}
{% if SETTING.get('signup_enabled') %}
<br>
<a href="{{ url_for('index.register') }}" class="text-center">
Create an account
</a>
{% if SETTING.get('verify_user_email') %}
<br/>
<a href="{{ url_for('index.resend_confirmation_email') }}" class="text-center">
Resend confirmation email
</a>
{% endif %}
{% endif %}
</div> </div>
</div> <!-- /.card-body -->
<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> </div>
{% assets "js_login" -%} <!-- /.card -->
<script type="text/javascript" src="{{ ASSET_URL }}"></script> </div>
{%- endassets %} <!-- /.login-box -->
{% assets "js_validation" -%} <div class="text-center pt-3">
<script type="text/javascript" src="{{ ASSET_URL }}"></script> <p>Powered by <a href="https://powerdnsadmin.org" target="_blank">PowerDNS-Admin</a></p>
{%- endassets %} </div>
<script> {% assets "js_login" -%}
$(function () { <script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
<script>
$(function () {
$('input').iCheck({ $('input').iCheck({
checkboxClass: 'icheckbox_square-blue', checkboxClass: 'icheckbox_square-blue',
radioClass: 'iradio_square-blue', radioClass: 'iradio_square-blue',
increaseArea: '20%' // optional increaseArea: '20%' // optional
}); });
}); });
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,43 +1,49 @@
<!doctype html> <!DOCTYPE html>
<title>Site Maintenance</title> <html lang="en" class>
<style> <head>
body { <title>Site Maintenance</title>
text-align: center; <style>
padding: 150px; body {
} text-align: center;
padding: 150px;
}
h1 { h1 {
font-size: 50px; font-size: 50px;
} }
body { body {
font: 20px Helvetica, sans-serif; font: 20px Helvetica, sans-serif;
color: #333; color: #333;
} }
article { article {
display: block; display: block;
text-align: left; text-align: left;
width: 650px; width: 650px;
margin: 0 auto; margin: 0 auto;
} }
a { a {
color: #dc8100; color: #dc8100;
text-decoration: none; text-decoration: none;
} }
a:hover {
color: #333;
text-decoration: none;
}
</style>
a:hover {
color: #333;
text-decoration: none;
}
</style>
</head>
<body>
<article> <article>
<h1>We&rsquo;ll be back soon!</h1> <h1>We&rsquo;ll be back soon!</h1>
<div> <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
Administrator if you need more information, otherwise we&rsquo;ll be back online shortly!</p> System
<p>&mdash; Team</p> Administrator if you need more information, otherwise we&rsquo;ll be back online shortly!</p>
</div> <p>&mdash; Team</p>
</div>
</article> </article>
</body>
</html>

View File

@ -1,7 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Register - {{ SITE_NAME }}</title> <title>Register - {{ SITE_NAME }}</title>
@ -10,183 +9,201 @@
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css">
{% assets "css_login" -%} {% assets "css_login" -%}
<link rel="stylesheet" href="{{ ASSET_URL }}"> <link rel="stylesheet" href="{{ ASSET_URL }}">
{%- endassets %} {%- endassets %}
</head> </head>
<body class="hold-transition register-page"> <body class="hold-transition register-page">
<div class="register-box"> <div class="register-box">
<div class="card card-outline card-primary"> <div class="card card-outline card-primary shadow">
<div class="card-header text-center"> <div class="card-header text-center">
<a href="{{ url_for('index.index') }}" class="h3"> <a href="{{ url_for('index.index') }}" class="h3">
{% if SETTING.get('site_name') %} {% if SETTING.get('site_name') %}
{{ SITE_NAME }} {{ SITE_NAME }}
{% else %} {% else %}
<b>PowerDNS</b>-Admin <b>PowerDNS</b>-Admin
{% endif %} {% endif %}
</a> </a>
</div> </div>
<div class="card-body"> <div class="card-body">
{% if error %} {% if error %}
<div class="alert alert-danger alert-dismissible"> <div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ error }} {{ error }}
</div> </div>
{% endif %} {% endif %}
<p class="login-box-msg">Enter your personal details below</p> <p class="login-box-msg">Enter your personal details below</p>
<form action="{{ url_for('index.register') }}" method="post" validator> <form action="{{ url_for('index.register') }}" method="post" validator>
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}"> <input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
</span> </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>
{% if 'firstname' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['firstname'] }}
</div>
{% endif %}
</div>
</div> </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>
{% if 'firstname' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['firstname'] }}
</div>
{% endif %}
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
</span> </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>
{% if 'lastname' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['lastname'] }}
</div>
{% endif %}
</div>
</div> </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>
{% if 'lastname' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['lastname'] }}
</div>
{% endif %}
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
</span> </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>
{% if 'email' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['email'] }}
</div>
{% endif %}
</div>
</div> </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>
{% if 'email' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['email'] }}
</div>
{% endif %}
</div>
</div>
<p class="login-box-msg">Enter your account details below</p> <p class="login-box-msg">Enter your account details below</p>
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
</span> </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>
{% if 'username' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['username'] }}
</div>
{% endif %}
</div>
</div> </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>
{% if 'username' in error_messages %}
<div class="invalid-feedback">
<i class="fas fa-exclamation-triangle"></i>
{{ error_messages['username'] }}
</div>
{% endif %}
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-lock"></i> <i class="fas fa-lock"></i>
</span> </span>
</div>
<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>
{{ error_messages['password'] }}
</div>
{% endif %}
</div>
</div> </div>
<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>
{{ error_messages['password'] }}
</div>
{% endif %}
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-lock"></i> <i class="fas fa-lock"></i>
</span> </span>
</div>
<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>
{{ error_messages['rpassword'] }}
</div>
{% endif %}
</div>
</div> </div>
<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>
{{ error_messages['rpassword'] }}
</div>
{% endif %}
</div>
</div>
{% if captcha_enable %} {% if captcha_enable %}
<p class="login-box-msg">Please complete the CAPTCHA below</p> <p class="login-box-msg">Please complete the CAPTCHA below</p>
<div class="form-group"> <div class="form-group">
{{ captcha() }} {{ captcha() }}
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-shield-alt"></i> <i class="fas fa-shield-alt"></i>
</span> </span>
</div> </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"
{% if 'captcha_result' in error_messages %} class="form-control {{ 'is-invalid' if 'captcha_result' in error_messages else '' }}"
<div class="invalid-feedback"> placeholder="CAPTCHA" id="captcha" name="captcha" required>
<i class="fas fa-exclamation-triangle"></i> {% if 'captcha_result' in error_messages %}
{{ error_messages['captcha_result'] }} <div class="invalid-feedback">
</div> <i class="fas fa-exclamation-triangle"></i>
{% endif %} {{ error_messages['captcha_result'] }}
</div> </div>
{% endif %} {% endif %}
</div>
{% endif %}
<div class="row"> <div class="row">
<div class="d-flex justify-content-between mx-auto mt-3"> <div class="d-flex justify-content-between mx-auto mt-3">
<button type="button" class="btn btn-secondary" id="button_back">Back</button> <button type="button" class="btn btn-secondary" id="button_back">Back</button>
<button type="submit" class="btn btn-primary btn-block mx-3">Register</button> <button type="submit" class="btn btn-primary btn-block mx-3">Register</button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<div class="login-box-footer"> <!-- /.card-body -->
<center>
<p>Powered by <a href="https://github.com/PowerDNS-Admin/PowerDNS-Admin">PowerDNS-Admin</a></p>
</center>
</div>
</div> </div>
{% assets "js_login" -%} <!-- /.card -->
<script type="text/javascript" src="{{ ASSET_URL }}"></script> </div>
{%- endassets %} <!-- /.register-box -->
{% assets "js_validation" -%} <div class="text-center pt-3">
<script type="text/javascript" src="{{ ASSET_URL }}"></script> <p>Powered by <a href="https://powerdnsadmin.org" target="_blank">PowerDNS-Admin</a></p>
{%- endassets %} </div>
<script> {% assets "js_login" -%}
$(function () { <script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
<script>
$(function () {
$('#button_back').click(function () { $('#button_back').click(function () {
window.location.href = '{{ url_for('index.login') }}'; window.location.href = '{{ url_for('index.login') }}';
}) })
}); });
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,7 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Welcome - {{ SITE_NAME }}</title> <title>Welcome - {{ SITE_NAME }}</title>
@ -9,82 +8,82 @@
<!-- Tell the browser to be responsive to screen width --> <!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
{% assets "css_login" -%} {% assets "css_login" -%}
<link rel="stylesheet" href="{{ ASSET_URL }}"> <link rel="stylesheet" href="{{ ASSET_URL }}">
{%- endassets %} {%- endassets %}
{% if SETTING.get('custom_css') %} {% if SETTING.get('custom_css') %}
<link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}"> <link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}">
{% endif %} {% endif %}
</head> </head>
<body class="hold-transition register-page">
<body class="hold-transition register-page"> <div class="register-box">
<div class="register-box"> <div class="register-logo">
<div class="register-logo">
<a><b>PowerDNS</b>-Admin</a> <a><b>PowerDNS</b>-Admin</a>
</div> </div>
<div class="register-box-body"> <div class="register-box-body">
{% if error %} {% if error %}
<div class="alert alert-danger alert-dismissible"> <div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ error }} {{ error }}
</div> </div>
{% endif %} {% endif %}
Welcome, {{user.firstname}}! <br /> Welcome, {{ user.firstname }}! <br/>
You will need a Token on login. <br /> You will need a Token on login. <br/>
Your QR code is: Your QR code is:
<div id="token_information"> <div id="token_information">
{% if qrcode_image == None %} {% if qrcode_image == None %}
<p><img id="qrcode" src="{{ url_for('user.qrcode') }}"></p> <p><img id="qrcode" src="{{ url_for('user.qrcode') }}"></p>
{% else %} {% 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 %} {% endif %}
<p> <p>
Your secret key is: <br /> Your secret key is: <br/>
<form> <form>
<input type=text id="otp_secret" value={{user.otp_secret}} readonly> <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> <button type=button style="position:relative; right:28px" onclick="copy_otp_secret_to_clipboard()"><i
<br /><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font> class="fa fa-clipboard"></i></button>
<br/><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
</form> </form>
</p> </p>
You can use Google Authenticator (<a target="_blank" You can use Google Authenticator (<a target="_blank"
href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Android</a> href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Android</a>
- <a target="_blank" - <a target="_blank"
href="https://apps.apple.com/us/app/google-authenticator/id388497605">iOS</a>) href="https://apps.apple.com/us/app/google-authenticator/id388497605">iOS</a>)
<br /> <br/>
or FreeOTP (<a target="_blank" or FreeOTP (<a target="_blank"
href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en">Android</a> href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en">Android</a>
- <a target="_blank" - <a target="_blank"
href="https://itunes.apple.com/en/app/freeotp-authenticator/id872559395?mt=8">iOS</a>) 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. on your smartphone <br/> to scan the QR code or type the secret key.
<br /> <br /> <br/> <br/>
<font color="red"><strong><i>Make sure only you can see this QR Code <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> and secret key, and nobody can capture them.</i></strong></font>
</div> </div>
</br> </br>
Please input your OTP token to continue, to ensure the seed has been scanned correctly. Please input your OTP token to continue, to ensure the seed has been scanned correctly.
<form action="" method="post" data-toggle="validator"> <form action="" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}"> <input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<input type="text" class="form-control" placeholder="OTP Token" name="otptoken" <input type="text" class="form-control" placeholder="OTP Token" name="otptoken"
data-error="Please input your OTP token" required> data-error="Please input your OTP token" required>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-4"> <div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block">Continue</button> <button type="submit" class="btn btn-primary btn-block">Continue</button>
</div>
</div> </div>
</div>
</form> </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>
</div>
</div> </div>
</body> <!-- /.register-box-body -->
{% assets "js_login" -%} <div class="text-center">
<script type="text/javascript" src="{{ ASSET_URL }}"></script> <p>Powered by <a href="https://powerdnsadmin.org" target="_blank">PowerDNS-Admin</a></p>
{%- endassets %} </div>
{% assets "js_validation" -%} </div>
<script type="text/javascript" src="{{ ASSET_URL }}"></script> <!-- /.register-box -->
{%- endassets %} </body>
{% assets "js_login" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
</html> </html>

View File

@ -1,190 +1,219 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "user_profile" %} {% set active_page = "user_profile" %}
{% block title %}<title>Edit Profile - {{ SITE_NAME }}</title>{% endblock %}
{% block title %}
<title>
My Profile - {{ SITE_NAME }}
</title>
{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<div class="content-header"> <div class="content-header">
<div class="container-fluid"> <div class="container-fluid">
<div class="row mb-2"> <div class="row mb-2">
<div class="col-sm-6"> <div class="col-sm-6">
<h1 class="m-0 text-dark"> <h1 class="m-0 text-dark">Edit Profile</h1>
User </div>
<small>My Profile</small> <div class="col-sm-6">
</h1> <ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item active">Edit Profile</li>
</ol>
</div>
</div>
</div> </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>
</ol>
</div>
</div>
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<section class="content"> <section class="content">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-12 col-sm-6">
<div class="card"> <div class="card card-outline card-primary shadow">
<div class="card-header"> <div class="card-header">
<div class="nav-tabs-custom"> <h3 class="card-title">Profile Editor</h3>
<ul class="nav nav-tabs" role="tablist"> </div>
<li class="nav-item"> <!-- /.card-header -->
<a class="nav-link active" href="#tabs-personal" data-toggle="tab"> <div class="card-body">
Personal Info <div class="nav-tabs-custom mb-2">
</a> <ul class="nav nav-tabs" role="tablist">
</li> <li class="nav-item">
{% if session['authentication_type'] == 'LOCAL' %} <a class="nav-link active" href="#tabs-personal" data-toggle="tab">
<li class="nav-item"> Personal Info
<a class="nav-link" href="#tabs-password" data-toggle="tab"> </a>
Change Password </li>
</a> {% if session['authentication_type'] == 'LOCAL' %}
</li> <li class="nav-item">
{% endif %} <a class="nav-link" href="#tabs-password" data-toggle="tab">
{% if session['authentication_type'] in ['LOCAL', 'LDAP'] %} Change Password
<li class="nav-item"> </a>
<a class="nav-link" href="#tabs-authentication" data-toggle="tab"> </li>
Authentication {% endif %}
</a> {% if session['authentication_type'] in ['LOCAL', 'LDAP'] %}
</li> <li class="nav-item">
{% endif %} <a class="nav-link" href="#tabs-authentication" data-toggle="tab">
</ul> Authentication
<div class="card-body"> </a>
<div class="tab-content"> </li>
<div class="tab-pane fade show active" id="tabs-personal"> {% endif %}
<form role="form" method="post" action="{{ user_profile }}"> </ul>
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}"> </div>
<div class="form-group"> <!-- /.nav-tabs-custom -->
<label for="firstname">First Name</label>
<input type="text" class="form-control" name="firstname" id="firstname" placeholder="{{ current_user.firstname }}" <div class="tab-content">
{% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}> <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 }}"
{% 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 }}"
{% 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 }}"
{% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div>
{% if session['authentication_type'] == 'LOCAL' %}
<div class="form-group">
<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.
{% else %}
<form action="{{ user_profile }}" method="post">
<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">
</div>
<div class="form-group">
<label for="rpassword">Re-type New Password</label>
<input type="password" class="form-control" name="rpassword"
id="rpassword">
</div>
<div class="form-group">
<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 %}>
<label for="otp_toggle">Enable Two Factor Authentication</label>
{% if current_user.otp_secret %}
<div id="token_information">
<p>
<img id="qrcode" src="{{ url_for('user.qrcode') }}">
</p>
<div style="position: relative; left: 15px">
Your secret key is:
<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()">
<i class="fa-solid fa-clipboard"></i>
</button>
<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>)
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>)
on your smartphone to scan the QR code.
<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.
</p>
</div>
{% endif %}
</div>
<!-- /.form-group -->
</form>
</div>
<!-- /.tab-pane -->
</div>
<!-- /.tab-content -->
</div>
<!-- /.card-body -->
</div> </div>
<div class="form-group"> <!-- /.card -->
<label for="lastname">Last Name</label>
<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 }}"
{% 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>
</div>
{% endif %}
</form>
</div> </div>
{% if session['authentication_type'] == 'LOCAL' %} <!-- /.col -->
<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.
{% else %}
<form action="{{ user_profile }}" method="post">
<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">
</div>
<div class="form-group">
<label for="rpassword">Re-type New Password</label>
<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>
</div>
</form>
{% endif %}
</div>
{% 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 %}>
<label for="otp_toggle">Enable Two Factor Authentication</label>
{% if current_user.otp_secret %}
<div id="token_information">
<p>
<img id="qrcode" src="{{ url_for('user.qrcode') }}">
</p>
<div style="position: relative; left: 15px">
Your secret key is:
<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()">
<i class="fa-solid fa-clipboard"></i>
</button>
<br />
<font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
</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>)
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>)
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
nobody can capture them.
</i>
</strong>
</font>
</div>
{% endif %}
</div>
</form>
</div>
</div>
</div> </div>
</div> <!-- /.row -->
</div> </div>
</div> <!-- /.container-fluid -->
</div> </section>
</div>
</section>
{% endblock %} {% endblock %}
{% block extrascripts %} {% block extrascripts %}
<script> <script>
// initialize pretty checkboxes // initialize pretty checkboxes
$('.otp_toggle').iCheck({ $('.otp_toggle').iCheck({
checkboxClass: 'icheckbox_square-blue', checkboxClass: 'icheckbox_square-blue',
increaseArea: '20%' increaseArea: '20%'
}); });
// handle checkbox toggling // handle checkbox toggling
$('.otp_toggle').on('ifToggled', function(event) { $('.otp_toggle').on('ifToggled', function (event) {
var enable_otp = $(this).prop('checked'); var enable_otp = $(this).prop('checked');
var postdata = { var postdata = {
'action': 'enable_otp', 'action': 'enable_otp',
'data': { 'data': {
'enable_otp': enable_otp 'enable_otp': enable_otp
}, },
'_csrf_token': '{{ csrf_token() }}' '_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(); window.location.reload();
$('#tabs li:eq(2) a').tab('show'); $('#tabs li:eq(2) a').tab('show');
}); });
}); });
</script> </script>
{% endblock %} {% endblock %}