mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2024-11-08 22:50:26 +00:00
ac786f45be
Convert col-xs-* to just col-* as part of bootstrap v3 -> v4 Convert box-* -> card-* as part of bootstrap v3 -> v4 Moved domain actions on main dashboard to a dropdown menu to avoid clutter Added "Log Out" to top header left Hid OTP on admin edit user to only show the disable card & options if the user account has OTP enabled
456 lines
17 KiB
HTML
456 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" class>
|
|
<head>
|
|
{% block head %}
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<link rel="icon" href="{{ url_for('static', filename='img/favicon.png') }}">
|
|
{% block title %}
|
|
<title>
|
|
{{ SITE_NAME }}
|
|
</title>
|
|
{% endblock %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='assets/css/style.css') }}">
|
|
<!-- Get Google Fonts we like -->
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='assets/css/source_sans_pro.css') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='assets/css/roboto_mono.css') }}">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css">
|
|
<!-- 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">
|
|
<!-- Tell Safari to not recognise telephone numbers -->
|
|
<meta name="format-detection" content="telephone=no">
|
|
{% assets "css_main" -%}
|
|
<link rel="stylesheet" href="{{ ASSET_URL }}">
|
|
{%- endassets %}
|
|
{% if SETTING.get('custom_css') %}
|
|
<link rel="stylesheet" href="/static/custom/{{ SETTING.get('custom_css') }}">
|
|
{% endif %}
|
|
{% endblock %}
|
|
</head>
|
|
|
|
<body class="hold-transition sidebar-mini text-sm {% if not SETTING.get('fullscreen_layout') %}layout-boxed{% endif %}">
|
|
{% set user_image_url = url_for('user.image', username=current_user.username) %}
|
|
<div class="wrapper">
|
|
{% block pageheader %}
|
|
<nav class="main-header navbar navbar-expand navbar-dark">
|
|
<!-- Header Navbar: style can be found in header.less -->
|
|
<!-- Sidebar toggle button-->
|
|
<ul class="navbar-nav">
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
|
<i class="fas fa-bars"></i>
|
|
</a>
|
|
</li>
|
|
{% if current_user.id is defined %}
|
|
<li class="nav-item d-none d-inline-block">
|
|
<a class="nav-link" href="{{ url_for('index.logout') }}">
|
|
Logout
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
|
|
<ul class="navbar-nav ml-auto">
|
|
<!-- {% if current_user.id is defined %}
|
|
<li class="nav-item dropdown user-menu">
|
|
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
|
<img src="{{ user_image_url }}" class="user-image img-circle elevation-2" alt="User Image"/>
|
|
<span class="d-none d-md-inline">
|
|
{{ current_user.firstname }} {{ current_user.lastname }}
|
|
</span>
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li class="user-header bg-dark">
|
|
<img src="{{ user_image_url }}" class="img-circle elevation-2" alt="User Image"/>
|
|
<p>
|
|
{{ current_user.firstname }} {{ current_user.lastname }}
|
|
<small>{{ current_user.role.name }}</small>
|
|
</p>
|
|
</li>
|
|
<li class="user-footer">
|
|
<a href="{{ url_for('user.profile') }}" class="btn btn-primary">My Profile</a>
|
|
<a href="{{ url_for('index.logout') }}" class="btn btn-warning float-right">Log out</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
{% endif %}
|
|
-->
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-widget="fullscreen" href="#" role="button">
|
|
<i class="fas fa-expand-arrows-alt"></i>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
{% endblock %}
|
|
<!-- Left side column. contains the logo and sidebar -->
|
|
<aside class="main-sidebar sidebar-dark-primary">
|
|
<!-- Logo -->
|
|
<a href="{{ url_for('index.index') }}" class="brand-link">
|
|
<span class="brand-text font-weight-light">
|
|
{% if SETTING.get('site_name') %}
|
|
<b>{{ SITE_NAME }}</b>
|
|
{% else %}
|
|
<b>PowerDNS</b>-Admin
|
|
{% endif %}
|
|
</span>
|
|
</a>
|
|
<!-- sidebar: style can be found in sidebar.less -->
|
|
<div class="sidebar">
|
|
{% if current_user.id is defined %}
|
|
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
|
|
<div class="image">
|
|
<img src="{{ user_image_url }}" class="img-circle elevation-2" alt="User Image">
|
|
</div>
|
|
<div class="info">
|
|
<a href="{{ url_for('user.profile') }}" class="d-block">{{ current_user.firstname }} {{ current_user.lastname }}</a>
|
|
</div>
|
|
</div>
|
|
<!-- sidebar menu: : style can be found in sidebar.less -->
|
|
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu">
|
|
<li class="nav-header">USER ACTIONS</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'nav-item dashboard' else 'nav-item' }}">
|
|
<a href="{{ url_for('dashboard.dashboard') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-tachometer-alt"></i>
|
|
<p>Dashboard</p>
|
|
</a>
|
|
</li>
|
|
{% if SETTING.get('allow_user_create_domain') or current_user.role.name in ['Administrator', 'Operator'] %}
|
|
<li class="{{ 'nav-item active' if active_page == 'nav-item new_domain' else 'nav-item' }}">
|
|
<a href="{{ url_for('domain.add') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-plus"></i>
|
|
<p>New Domain</p>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if SETTING.get('allow_user_remove_domain') or current_user.role.name in ['Administrator', 'Operator'] %}
|
|
<li class="{{ 'nav-item active' if active_page == 'remove_domain' else 'nav-item' }}">
|
|
<a href="{{ url_for('domain.remove') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-trash-alt"></i>
|
|
<p>Remove Domain</p>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
|
<li class="nav-header">ADMINISTRATION</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_console' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.pdns_stats') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-info-circle"></i>
|
|
<p>PDNS</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_global_search' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.global_search') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-search"></i>
|
|
<p>Global Search</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_history' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.history') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-calendar-alt"></i>
|
|
<p>History</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_domain_template' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.templates') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-clone"></i>
|
|
<p>Domain Templates</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_accounts' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.manage_account') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-industry"></i>
|
|
<p>Accounts</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_users' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.manage_user') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-users"></i>
|
|
<p>Users</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_keys' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.manage_keys') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-key"></i>
|
|
<p>API Keys</p>
|
|
</a>
|
|
</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_settings' else 'nav-item' }}">
|
|
<a href="#" class="nav-link">
|
|
<i class="nav-icon fas fa-cog"></i>
|
|
<p>
|
|
Settings
|
|
<i class="right fas fa-angle-left"></i>
|
|
</p>
|
|
</a>
|
|
<ul class="nav nav-treeview" {% if active_page == 'admin_settings' %}style="display: block;"{% endif %}>
|
|
<li class="nav-item">
|
|
<a href="{{ url_for('admin.setting_basic') }}" class="nav-link">
|
|
<i class="nav-icon far fa-circle"></i>
|
|
<p>Basic</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="{{ url_for('admin.setting_records') }}" class="nav-link">
|
|
<i class="nav-icon far fa-circle"></i>
|
|
<p>Records</p>
|
|
</a>
|
|
</li>
|
|
{% if current_user.role.name == 'Administrator' %}
|
|
<li class="nav-item">
|
|
<a href="{{ url_for('admin.setting_pdns') }}" class="nav-link">
|
|
<i class="nav-icon far fa-circle"></i>
|
|
<p>PDNS</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="{{ url_for('admin.setting_authentication') }}" class="nav-link">
|
|
<i class="nav-icon far fa-circle"></i>
|
|
<p>Authentication</p>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</li>
|
|
{% elif SETTING.get('allow_user_view_history') %}
|
|
<li class="nav-header">ADMINISTRATION</li>
|
|
<li class="{{ 'nav-item active' if active_page == 'admin_history' else 'nav-item' }}">
|
|
<a href="{{ url_for('admin.history') }}" class="nav-link">
|
|
<i class="nav-icon fas fa-calendar-alt"></i>
|
|
<p>History</p>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
{% endif %}
|
|
</div>
|
|
<!-- /.sidebar -->
|
|
</aside>
|
|
|
|
<!-- Content Wrapper. Contains page content -->
|
|
<div class="content-wrapper">
|
|
{% block dashboard_stat %}
|
|
<!-- Content Header (Page header) -->
|
|
<div class="content-header">
|
|
<div class="container-fluid">
|
|
<div class="row mb-2">
|
|
<div class="col-sm-6">
|
|
<h1 class="m-0 text-dark">
|
|
Dashboard
|
|
<small>Control panel</small>
|
|
</h1>
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<ol class="breadcrumb float-sm-right">
|
|
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.dashboard') }}">Home</a></li>
|
|
<li class="breadcrumb-item active">Dashboard</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
{% block content %}
|
|
{% endblock %}
|
|
</div>
|
|
<!-- /.content-wrapper -->
|
|
<footer class="main-footer">
|
|
<strong><a href="https://github.com/PowerDNS-Admin/PowerDNS-Admin">PowerDNS-Admin</a></strong> - A PowerDNS web interface with advanced features.
|
|
</footer>
|
|
</div>
|
|
<!-- ./wrapper -->
|
|
<script type="text/javascript">
|
|
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
|
|
</script>
|
|
<script type="text/javascript">
|
|
var PDNS_VERSION = '{{ pdns_version }}'
|
|
</script>
|
|
{% block scripts %}
|
|
{% assets "js_main" -%}
|
|
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
|
|
{% if SETTING.get('warn_session_timeout') and current_user.is_authenticated %}
|
|
<script>
|
|
// close the session warning popup when receive
|
|
// a boradcast message
|
|
var bc = new BroadcastChannel('powerdnsadmin');
|
|
bc.addEventListener('message', function (e) {
|
|
if (e.data == 'close_session_timeout_modal'){
|
|
$("#modal_session_warning").modal('hide');
|
|
}
|
|
});
|
|
|
|
// Stay Signed In button click event
|
|
$(document.body).on("click", ".button_stay_signed_in", function (e) {
|
|
$.get({
|
|
url: $.jTimeout().options.extendUrl,
|
|
cache: false,
|
|
success: function(){
|
|
$.jTimeout().resetExpiration();
|
|
}
|
|
});
|
|
$.jTimeout().options.onClickExtend();
|
|
});
|
|
|
|
// Sign Out button click event
|
|
$(document.body).on("click", ".button_sign_out", function (e) {
|
|
window.location.replace("{{ url_for('index.logout') }}");
|
|
});
|
|
|
|
// Things happen when session warning popup shown
|
|
$(document).on('show.bs.modal','#modal_session_warning', function () {
|
|
var secondsLeft = jTimeout.getSecondsTillExpiration();
|
|
var t = timer($('#modal-time'), secondsLeft);
|
|
|
|
$(this).on('hidden.bs.modal', function () {
|
|
clearInterval(t);
|
|
$('#modal-time').text("");
|
|
$(this).off('hidden.bs.modal');
|
|
});
|
|
|
|
});
|
|
|
|
// jTimeout definition
|
|
$(function(){
|
|
$.jTimeout({
|
|
flashTitle: true,
|
|
flashTitleSpeed: 500,
|
|
flashingTitleText: '**WARNING**',
|
|
originalTitle: document.title,
|
|
timeoutAfter: {{ SETTING.get('session_timeout')|int * 60 }},
|
|
secondsPrior: 60,
|
|
heartbeat: 1,
|
|
extendOnMouseMove: true,
|
|
mouseDebounce: 30,
|
|
extendUrl: '{{ url_for("index.ping") }}',
|
|
logoutUrl: '{{ url_for("index.logout") }}',
|
|
loginUrl: '{{ url_for("index.login") }}',
|
|
|
|
onClickExtend: function(){
|
|
// broadcast a message to tell other tabes
|
|
// close the session warning popup
|
|
var bc = new BroadcastChannel('powerdnsadmin');
|
|
bc.postMessage('close_session_timeout_modal');
|
|
},
|
|
|
|
onMouseMove: function(){
|
|
// if the mouse is moving while popup is present, we
|
|
// don't extend the session.
|
|
if (!$('#modal_session_warning').hasClass('in')) {
|
|
$.get({
|
|
url: $.jTimeout().options.extendUrl,
|
|
cache: false,
|
|
success: function () {
|
|
$.jTimeout().resetExpiration();
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
onTimeout: function(jTimeout){
|
|
window.location.replace("{{ url_for('index.logout') }}");
|
|
},
|
|
|
|
onPriorCallback: function(jTimeout){
|
|
$("#modal_session_warning").modal('show');;
|
|
},
|
|
|
|
onSessionExtended:function(jTimeout){
|
|
$("#modal_session_warning").modal('hide');
|
|
}
|
|
});
|
|
});
|
|
|
|
function showErrorModal(message) {
|
|
var modal = $('#modal_error');
|
|
modal.find('.modal-body p').text(message);
|
|
modal.modal('show');
|
|
}
|
|
|
|
function showSuccessModal(message) {
|
|
var modal = $("#modal_success");
|
|
modal.find('.modal-body p').text(message);
|
|
modal.modal('show');
|
|
}
|
|
</script>
|
|
{% endif %}
|
|
{%- endassets %}
|
|
{% endblock %}
|
|
{% block extrascripts %}
|
|
{% endblock %}
|
|
{% block defaultmodals %}
|
|
<div class="modal fade modal-danger" id="modal_error">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal"
|
|
aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title">Error</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-flat btn-default pull-right"
|
|
data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
</div>
|
|
<!-- /.modal-dialog -->
|
|
</div>
|
|
<!-- /.modal -->
|
|
<div class="modal fade modal-success" id="modal_success">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal"
|
|
aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title">Success</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-flat btn-default pull-right"
|
|
data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
</div>
|
|
<!-- /.modal-dialog -->
|
|
</div>
|
|
<!-- /.modal -->
|
|
<!-- /.session-warning-modal -->
|
|
<div class="modal fade modal-warning" data-backdrop="static" id="modal_session_warning">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Session timeout warning</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Your session is about to expire. You will be automatically signed out in</p>
|
|
<h3><span id="modal-time"></span></h3>
|
|
<p>To coninue your ssession, select <strong>Stay Signed In</strong></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-flat btn-danger pull-left button_stay_signed_in"
|
|
data-dismiss="modal">Stay Signed In</button>
|
|
<button type="button" class="btn btn-flat btn-default pull-right button_sign_out"
|
|
data-dismiss="modal">Sign Out</button>
|
|
</div>
|
|
</div>
|
|
<!-- /.session-warning-modal-content -->
|
|
</div>
|
|
<!-- /.session-warning-modal-dialog -->
|
|
</div>
|
|
<!-- /.session-warning-modal -->
|
|
{% endblock %}
|
|
{% block modals %}
|
|
{% endblock %}
|
|
</body>
|
|
</html> |