mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2024-12-04 19:15:30 +00:00
Adding Operator role
This commit is contained in:
parent
5e6806cc0f
commit
3457d9214a
@ -6,6 +6,9 @@ from app.models import Role, Setting
|
||||
|
||||
|
||||
def admin_role_required(f):
|
||||
"""
|
||||
Grant access if user is in Administrator role
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if g.user.role.name != 'Administrator':
|
||||
@ -14,10 +17,28 @@ def admin_role_required(f):
|
||||
return decorated_function
|
||||
|
||||
|
||||
def can_access_domain(f):
|
||||
def operator_role_required(f):
|
||||
"""
|
||||
Grant access if user is in Operator role or higher
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if g.user.role.name != 'Administrator':
|
||||
if g.user.role.name not in ['Administrator', 'Operator']:
|
||||
return redirect(url_for('error', code=401))
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
|
||||
def can_access_domain(f):
|
||||
"""
|
||||
Grant access if:
|
||||
- user is in Operator role or higher, or
|
||||
- user is in granted Account, or
|
||||
- user is in granted Domain
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if g.user.role.name not in ['Administrator', 'Operator']:
|
||||
domain_name = kwargs.get('domain_name')
|
||||
user_domain = [d.name for d in g.user.get_domain()]
|
||||
|
||||
@ -29,10 +50,15 @@ def can_access_domain(f):
|
||||
|
||||
|
||||
def can_configure_dnssec(f):
|
||||
"""
|
||||
Grant access if:
|
||||
- user is in Operator role or higher, or
|
||||
- dnssec_admins_only is off
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if g.user.role.name != 'Administrator' and Setting().get('dnssec_admins_only'):
|
||||
return redirect(url_for('error', code=401))
|
||||
if g.user.role.name not in ['Administrator', 'Operator'] and Setting().get('dnssec_admins_only'):
|
||||
return redirect(url_for('error', code=401))
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
@ -150,7 +150,7 @@ class User(db.Model):
|
||||
logging.error(e)
|
||||
logging.debug('baseDN: {0}'.format(baseDN))
|
||||
logging.debug(traceback.format_exc())
|
||||
raise
|
||||
|
||||
|
||||
def ldap_auth(self, ldap_username, password):
|
||||
try:
|
||||
@ -165,6 +165,8 @@ class User(db.Model):
|
||||
"""
|
||||
Validate user credential
|
||||
"""
|
||||
role_name = 'User'
|
||||
|
||||
if method == 'LOCAL':
|
||||
user_info = User.query.filter(User.username == self.username).first()
|
||||
|
||||
@ -179,12 +181,12 @@ class User(db.Model):
|
||||
return False
|
||||
|
||||
if method == 'LDAP':
|
||||
isadmin = False
|
||||
LDAP_TYPE = Setting().get('ldap_type')
|
||||
LDAP_BASE_DN = Setting().get('ldap_base_dn')
|
||||
LDAP_FILTER_BASIC = Setting().get('ldap_filter_basic')
|
||||
LDAP_FILTER_USERNAME = Setting().get('ldap_filter_username')
|
||||
LDAP_ADMIN_GROUP = Setting().get('ldap_admin_group')
|
||||
LDAP_OPERATOR_GROUP = Setting().get('ldap_operator_group')
|
||||
LDAP_USER_GROUP = Setting().get('ldap_user_group')
|
||||
LDAP_GROUP_SECURITY_ENABLED = Setting().get('ldap_sg_enabled')
|
||||
|
||||
@ -206,24 +208,30 @@ class User(db.Model):
|
||||
try:
|
||||
if LDAP_TYPE == 'ldap':
|
||||
if (self.ldap_search(searchFilter, LDAP_ADMIN_GROUP)):
|
||||
isadmin = True
|
||||
role_name = 'Administrator'
|
||||
logging.info('User {0} is part of the "{1}" group that allows admin access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP))
|
||||
elif (self.ldap_search(searchFilter, LDAP_OPERATOR_GROUP)):
|
||||
role_name = 'Operator'
|
||||
logging.info('User {0} is part of the "{1}" group that allows operator access to PowerDNS-Admin'.format(self.username, LDAP_OPERATOR_GROUP))
|
||||
elif (self.ldap_search(searchFilter, LDAP_USER_GROUP)):
|
||||
logging.info('User {0} is part of the "{1}" group that allows user access to PowerDNS-Admin'.format(self.username, LDAP_USER_GROUP))
|
||||
else:
|
||||
logging.error('User {0} is not part of the "{1}" or "{2}" groups that allow access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP, LDAP_USER_GROUP))
|
||||
logging.error('User {0} is not part of the "{1}", "{2}" or "{3}" groups that allow access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP, LDAP_OPERATOR_GROUP, LDAP_USER_GROUP))
|
||||
return False
|
||||
elif LDAP_TYPE == 'ad':
|
||||
user_ldap_groups = [g.decode("utf-8") for g in ldap_result[0][0][1]['memberOf']]
|
||||
logging.debug('user_ldap_groups: {0}'.format(user_ldap_groups))
|
||||
|
||||
if (LDAP_ADMIN_GROUP in user_ldap_groups):
|
||||
isadmin = True
|
||||
role_name = 'Administrator'
|
||||
logging.info('User {0} is part of the "{1}" group that allows admin access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP))
|
||||
elif (LDAP_OPERATOR_GROUP in user_ldap_groups):
|
||||
role_name = 'Operator'
|
||||
logging.info('User {0} is part of the "{1}" group that allows operator access to PowerDNS-Admin'.format(self.username, LDAP_OPERATOR_GROUP))
|
||||
elif (LDAP_USER_GROUP in user_ldap_groups):
|
||||
logging.info('User {0} is part of the "{1}" group that allows user access to PowerDNS-Admin'.format(self.username, LDAP_USER_GROUP))
|
||||
else:
|
||||
logging.error('User {0} is not part of the "{1}" or "{2}" groups that allow access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP, LDAP_USER_GROUP))
|
||||
logging.error('User {0} is not part of the "{1}", "{2}" or "{3}" groups that allow access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP, LDAP_OPERATOR_GROUP, LDAP_USER_GROUP))
|
||||
return False
|
||||
else:
|
||||
logging.error('Invalid LDAP type')
|
||||
@ -261,21 +269,17 @@ class User(db.Model):
|
||||
logging.debug(traceback.format_exc())
|
||||
|
||||
# first register user will be in Administrator role
|
||||
self.role_id = Role.query.filter_by(name='User').first().id
|
||||
if User.query.count() == 0:
|
||||
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
||||
|
||||
# user will be in Administrator role if part of LDAP Admin group
|
||||
if LDAP_GROUP_SECURITY_ENABLED:
|
||||
if isadmin == True:
|
||||
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
||||
else:
|
||||
self.role_id = Role.query.filter_by(name=role_name).first().id
|
||||
|
||||
self.create_user()
|
||||
logging.info('Created user "{0}" in the DB'.format(self.username))
|
||||
|
||||
# user already exists in database, set their admin status based on group membership (if enabled)
|
||||
# user already exists in database, set their role based on group membership (if enabled)
|
||||
if LDAP_GROUP_SECURITY_ENABLED:
|
||||
self.set_admin(isadmin)
|
||||
self.set_role(role_name)
|
||||
|
||||
return True
|
||||
else:
|
||||
@ -453,28 +457,15 @@ class User(db.Model):
|
||||
return False
|
||||
return False
|
||||
|
||||
def set_admin(self, is_admin):
|
||||
"""
|
||||
Set role for a user:
|
||||
is_admin == True => Administrator
|
||||
is_admin == False => User
|
||||
"""
|
||||
user_role_name = 'Administrator' if is_admin else 'User'
|
||||
role = Role.query.filter(Role.name==user_role_name).first()
|
||||
|
||||
try:
|
||||
if role:
|
||||
user = User.query.filter(User.username==self.username).first()
|
||||
user.role_id = role.id
|
||||
db.session.commit()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except:
|
||||
db.session.roleback()
|
||||
logging.error('Cannot change user role in DB')
|
||||
logging.debug(traceback.format_exc())
|
||||
return False
|
||||
def set_role(self, role_name):
|
||||
role = Role.query.filter(Role.name==role_name).first()
|
||||
if role:
|
||||
user = User.query.filter(User.username==self.username).first()
|
||||
user.role_id = role.id
|
||||
db.session.commit()
|
||||
return {'status': True, 'msg': 'Set user role successfully'}
|
||||
else:
|
||||
return {'status': False, 'msg': 'Role does not exist'}
|
||||
|
||||
|
||||
class Account(db.Model):
|
||||
@ -1825,8 +1816,9 @@ class Setting(db.Model):
|
||||
'ldap_filter_basic': '',
|
||||
'ldap_filter_username': '',
|
||||
'ldap_sg_enabled': False,
|
||||
'ldap_admin_group': False,
|
||||
'ldap_user_group': False,
|
||||
'ldap_admin_group': '',
|
||||
'ldap_operator_group': '',
|
||||
'ldap_user_group': '',
|
||||
'github_oauth_enabled': False,
|
||||
'github_oauth_key': '',
|
||||
'github_oauth_secret': '',
|
||||
|
@ -22,9 +22,14 @@ function applyChanges(data, url, showResult, refreshPage) {
|
||||
},
|
||||
|
||||
error : function(jqXHR, status) {
|
||||
// console.log(jqXHR);
|
||||
// var modal = $("#modal_error");
|
||||
// modal.find('.modal-body p').text(jqXHR["responseText"]);
|
||||
// modal.modal('show');
|
||||
console.log(jqXHR);
|
||||
var modal = $("#modal_error");
|
||||
modal.find('.modal-body p').text(jqXHR["responseText"]);
|
||||
var responseJson = jQuery.parseJSON(jqXHR.responseText);
|
||||
modal.find('.modal-body p').text(responseJson['msg']);
|
||||
modal.modal('show');
|
||||
}
|
||||
});
|
||||
|
@ -36,7 +36,7 @@
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Admin</th>
|
||||
<th>Role</th>
|
||||
<th>Privileges</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
@ -49,18 +49,22 @@
|
||||
<td>{{ user.lastname }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
<input type="checkbox" id="{{ user.username }}" class="admin_toggle" {% if user.role.name=='Administrator' %}checked{% endif %} {% if user.username==current_user.username %}disabled{% endif %}>
|
||||
<select id="{{ user.username }}" class="user_role" {% if user.username==current_user.username or (current_user.role.name=='Operator' and user.role.name=='Administrator') %}disabled{% endif %}>
|
||||
{% for role in roles %}
|
||||
<option value="{{ role.name }}" {% if role.id==user.role.id %}selected{% endif %}>{{ role.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-warning button_revoke" id="{{ user.username }}">
|
||||
<button type="button" class="btn btn-flat btn-warning button_revoke" id="{{ user.username }}" {% if current_user.role.name=='Operator' and user.role.name=='Administrator' %}disabled{% endif %}>
|
||||
Revoke <i class="fa fa-lock"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td width="15%">
|
||||
<button type="button" class="btn btn-flat btn-success button_edit" onclick="window.location.href='{{ url_for('admin_edituser', user_username=user.username) }}'">
|
||||
<button type="button" class="btn btn-flat btn-success button_edit" onclick="window.location.href='{{ url_for('admin_edituser', user_username=user.username) }}'" {% if current_user.role.name=='Operator' and user.role.name=='Administrator' %}disabled{% endif %}>
|
||||
Edit <i class="fa fa-lock"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-flat btn-danger button_delete" id="{{ user.username }}" {% if user.username==current_user.username %}disabled{% endif %}>
|
||||
<button type="button" class="btn btn-flat btn-danger button_delete" id="{{ user.username }}" {% if user.username==current_user.username or (current_user.role.name=='Operator' and user.role.name=='Administrator') %}disabled{% endif %}>
|
||||
Delete <i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
@ -93,14 +97,6 @@
|
||||
"pageLength": 10
|
||||
});
|
||||
|
||||
// avoid losing icheck box style when database refreshed
|
||||
$('#tbl_users').on('draw.dt', function () {
|
||||
$('.admin_toggle').iCheck({
|
||||
handle: 'checkbox',
|
||||
checkboxClass: 'icheckbox_square-blue'
|
||||
});
|
||||
});
|
||||
|
||||
// handle revocation of privileges
|
||||
$(document.body).on('click', '.button_revoke', function() {
|
||||
var modal = $("#modal_revoke");
|
||||
@ -129,24 +125,18 @@
|
||||
|
||||
});
|
||||
|
||||
// initialize pretty checkboxes
|
||||
$('.admin_toggle').iCheck({
|
||||
checkboxClass : 'icheckbox_square-blue',
|
||||
increaseArea : '20%' // optional
|
||||
});
|
||||
|
||||
// handle checkbox toggling
|
||||
$(document.body).on('ifToggled', '.admin_toggle', function() {
|
||||
var is_admin = $(this).prop('checked');
|
||||
// handle user role changing
|
||||
$('.user_role').on('change', function() {
|
||||
var role_name = this.value;
|
||||
var username = $(this).prop('id');
|
||||
postdata = {
|
||||
'action' : 'set_admin',
|
||||
'action' : 'update_user_role',
|
||||
'data' : {
|
||||
'username' : username,
|
||||
'is_admin' : is_admin
|
||||
'role_name' : role_name
|
||||
}
|
||||
};
|
||||
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser');
|
||||
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser', showResult=true);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -133,6 +133,11 @@
|
||||
<input type="text" class="form-control" name="ldap_admin_group" id="ldap_admin_group" placeholder="e.g. cn=sysops,dc=mydomain,dc=com" data-error="Please input LDAP DN for Admin group" value="{{ SETTING.get('ldap_admin_group') }}">
|
||||
<span class="help-block with-errors"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ldap_operator_group">Operator group</label>
|
||||
<input type="text" class="form-control" name="ldap_operator_group" id="ldap_operator_group" placeholder="e.g. cn=operators,dc=mydomain,dc=com" data-error="Please input LDAP DN for Operator group" value="{{ SETTING.get('ldap_operator_group') }}">
|
||||
<span class="help-block with-errors"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ldap_user_group">User group</label>
|
||||
<input type="text" class="form-control" name="ldap_user_group" id="ldap_user_group" placeholder="e.g. cn=users,dc=mydomain,dc=com" data-error="Please input LDAP DN for User group" value="{{ SETTING.get('ldap_user_group') }}">
|
||||
@ -197,6 +202,9 @@
|
||||
<li>
|
||||
Admin group - Your LDAP admin group.
|
||||
</li>
|
||||
<li>
|
||||
Operator group - Your LDAP operator group.
|
||||
</li>
|
||||
<li>
|
||||
User group - Your LDAP user group.
|
||||
</li>
|
||||
|
@ -108,26 +108,26 @@
|
||||
<li class="{{ 'active' if active_page == 'dashboard' else '' }}">
|
||||
<a href="{{ url_for('dashboard') }}"><i class="fa fa-dashboard"></i> Dashboard</a>
|
||||
</li>
|
||||
{% if current_user.role.name == 'Administrator' %}
|
||||
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||
<li class="{{ 'active' if active_page == 'new_domain' else '' }}">
|
||||
<a href="{{ url_for('domain_add') }}"><i class="fa fa-plus"></i> New Domain</a>
|
||||
</li>
|
||||
<li class="header">ADMINISTRATION</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_console' else '' }}">
|
||||
<a href="{{ url_for('admin') }}"><i class="fa fa-wrench"></i> Admin Console</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_domain_template' else '' }}">
|
||||
<a href="{{ url_for('templates') }}"><i class="fa fa-clone"></i> Domain Templates</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_users' else '' }}">
|
||||
<a href="{{ url_for('admin_manageuser') }}"><i class="fa fa-users"></i> Users</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_accounts' else '' }}">
|
||||
<a href="{{ url_for('admin_manageaccount') }}"><i class="fa fa-industry"></i> Accounts</a>
|
||||
<a href="{{ url_for('admin_pdns') }}"><i class="fa fa-info-circle"></i> PDNS</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_history' else '' }}">
|
||||
<a href="{{ url_for('admin_history') }}"><i class="fa fa-calendar"></i> History</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_domain_template' else '' }}">
|
||||
<a href="{{ url_for('templates') }}"><i class="fa fa-clone"></i> Domain Templates</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_accounts' else '' }}">
|
||||
<a href="{{ url_for('admin_manageaccount') }}"><i class="fa fa-industry"></i> Accounts</a>
|
||||
</li>
|
||||
<li class="{{ 'active' if active_page == 'admin_users' else '' }}">
|
||||
<a href="{{ url_for('admin_manageuser') }}"><i class="fa fa-users"></i> Users</a>
|
||||
</li>
|
||||
<li class="{{ 'treeview active' if active_page == 'admin_settings' else 'treeview' }}">
|
||||
<a href="#">
|
||||
<i class="fa fa-cog"></i> Settings
|
||||
@ -138,8 +138,10 @@
|
||||
<ul class="treeview-menu" {% if active_page == 'admin_settings' %}style="display: block;"{% endif %}>
|
||||
<li><a href="{{ url_for('admin_setting_basic') }}"><i class="fa fa-circle-o"></i></i> Basic</a></li>
|
||||
<li><a href="{{ url_for('admin_setting_records') }}"><i class="fa fa-circle-o"></i> Records</a></li>
|
||||
{% if current_user.role.name == 'Administrator' %}
|
||||
<li><a href="{{ url_for('admin_setting_pdns') }}"><i class="fa fa-circle-o"></i> PDNS</a></li>
|
||||
<li><a href="{{ url_for('admin_setting_authentication') }}"><i class="fa fa-circle-o"></i> Authentication</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
@ -19,7 +19,7 @@
|
||||
{% block content %}
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
{% if current_user.role.name == 'Administrator' %}
|
||||
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<div class="box">
|
||||
@ -69,7 +69,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<a href="{{ url_for('admin') }}">
|
||||
<a href="{{ url_for('admin_pdns') }}">
|
||||
<div class="small-box bg-green">
|
||||
<div class="inner">
|
||||
<h3><span style="font-size: 18px">{{ uptime|display_second_to_time }}</span></h3>
|
||||
@ -102,17 +102,17 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for history in histories %}
|
||||
<tr class="odd">
|
||||
<td>{{ history.created_by }}</td>
|
||||
<td>{{ history.msg }}</td>
|
||||
<td>{{ history.created_on }}</td>
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-primary history-info-button" value='{{ history.detail|replace("[]","None") }}'>
|
||||
Info <i class="fa fa-info"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="odd">
|
||||
<td>{{ history.created_by }}</td>
|
||||
<td>{{ history.msg }}</td>
|
||||
<td>{{ history.created_on }}</td>
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-primary history-info-button" value='{{ history.detail|replace("[]","None") }}'>
|
||||
Info <i class="fa fa-info"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -136,7 +136,7 @@
|
||||
<th>Serial</th>
|
||||
<th>Master</th>
|
||||
<th>Account</th>
|
||||
<th {% if current_user.role.name !='Administrator' %}width="6%"{% else %}width="25%"{% endif %}>Action</th>
|
||||
<th {% if current_user.role.name not in ['Administrator','Operator'] %}width="6%"{% else %}width="25%"{% endif %}>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -182,7 +182,7 @@
|
||||
"ordering" : true,
|
||||
"columnDefs": [
|
||||
{ "orderable": false, "targets": [-1] }
|
||||
{% if current_user.role.name != 'Administrator' %},{ "visible": false, "targets": [-2] }{% endif %}
|
||||
{% if current_user.role.name not in ['Administrator', 'Operator'] %},{ "visible": false, "targets": [-2] }{% endif %}
|
||||
],
|
||||
"processing" : true,
|
||||
"serverSide" : true,
|
||||
@ -236,7 +236,7 @@
|
||||
modal.modal('show');
|
||||
});
|
||||
|
||||
{% if current_user.role.name == 'Administrator' or not SETTING.get('dnssec_admins_only') %}
|
||||
{% if current_user.role.name in ['Administrator', 'Operator'] or not SETTING.get('dnssec_admins_only') %}
|
||||
$(document.body).on("click", ".button_dnssec", function() {
|
||||
var domain = $(this).prop('id');
|
||||
getdnssec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec', domain);
|
||||
|
@ -23,13 +23,13 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro account(domain) %}
|
||||
{% if current_user.role.name =='Administrator' %}
|
||||
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||
{% if domain.account_description != "" %}{{ domain.account.description }} {% endif %}[{{ domain.account.name }}]
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro actions(domain) %}
|
||||
{% if current_user.role.name =='Administrator' %}
|
||||
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||
<td width="25%">
|
||||
<button type="button" class="btn btn-flat btn-success button_template" id="{{ domain.name }}">
|
||||
Template <i class="fa fa-clone"></i>
|
||||
|
86
app/views.py
86
app/views.py
@ -22,7 +22,7 @@ from .models import User, Account, Domain, Record, Role, Server, History, Anonym
|
||||
from app import app, login_manager
|
||||
from app.lib import utils
|
||||
from app.oauth import github_oauth, google_oauth
|
||||
from app.decorators import admin_role_required, can_access_domain, can_configure_dnssec
|
||||
from app.decorators import admin_role_required, operator_role_required, can_access_domain, can_configure_dnssec
|
||||
|
||||
if app.config['SAML_ENABLED']:
|
||||
from onelogin.saml2.auth import OneLogin_Saml2_Auth
|
||||
@ -68,7 +68,7 @@ def before_request():
|
||||
|
||||
# check site maintenance mode
|
||||
maintenance = Setting().get('maintenance')
|
||||
if maintenance and current_user.is_authenticated and current_user.role.name != 'Administrator':
|
||||
if maintenance and current_user.is_authenticated and current_user.role.name not in ['Administrator', 'Operator']:
|
||||
return render_template('maintenance.html')
|
||||
|
||||
|
||||
@ -476,7 +476,7 @@ def dashboard():
|
||||
@app.route('/dashboard-domains', methods=['GET'])
|
||||
@login_required
|
||||
def dashboard_domains():
|
||||
if current_user.role.name == 'Administrator':
|
||||
if current_user.role.name in ['Administrator', 'Operator']:
|
||||
domains = Domain.query
|
||||
else:
|
||||
domains = User(id=current_user.id).get_domain_query()
|
||||
@ -508,7 +508,7 @@ def dashboard_domains():
|
||||
start = "" if search.startswith("^") else "%"
|
||||
end = "" if search.endswith("$") else "%"
|
||||
|
||||
if current_user.role.name == 'Administrator':
|
||||
if current_user.role.name in ['Administrator', 'Operator']:
|
||||
domains = domains.outerjoin(Account).filter(Domain.name.ilike(start + search.strip("^$") + end) |
|
||||
Account.name.ilike(start + search.strip("^$") + end) |
|
||||
Account.description.ilike(start + search.strip("^$") + end))
|
||||
@ -603,7 +603,7 @@ def domain(domain_name):
|
||||
|
||||
@app.route('/admin/domain/add', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def domain_add():
|
||||
templates = DomainTemplate.query.all()
|
||||
if request.method == 'POST':
|
||||
@ -661,7 +661,7 @@ def domain_add():
|
||||
|
||||
@app.route('/admin/domain/<path:domain_name>/delete', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def domain_delete(domain_name):
|
||||
d = Domain()
|
||||
result = d.delete(domain_name)
|
||||
@ -677,7 +677,7 @@ def domain_delete(domain_name):
|
||||
|
||||
@app.route('/admin/domain/<path:domain_name>/manage', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def domain_management(domain_name):
|
||||
if request.method == 'GET':
|
||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||
@ -712,7 +712,7 @@ def domain_management(domain_name):
|
||||
|
||||
@app.route('/admin/domain/<path:domain_name>/change_soa_setting', methods=['POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def domain_change_soa_edit_api(domain_name):
|
||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||
if not domain:
|
||||
@ -738,7 +738,7 @@ def domain_change_soa_edit_api(domain_name):
|
||||
|
||||
@app.route('/admin/domain/<path:domain_name>/change_account', methods=['POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def domain_change_account(domain_name):
|
||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||
if not domain:
|
||||
@ -816,7 +816,7 @@ def record_update(domain_name):
|
||||
|
||||
@app.route('/domain/<path:domain_name>/record/<path:record_name>/type/<path:record_type>/delete', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def record_delete(domain_name, record_name, record_type):
|
||||
try:
|
||||
r = Record(name=record_name, type=record_type)
|
||||
@ -873,7 +873,7 @@ def domain_dnssec_disable(domain_name):
|
||||
|
||||
@app.route('/domain/<path:domain_name>/managesetting', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_setdomainsetting(domain_name):
|
||||
if request.method == 'POST':
|
||||
#
|
||||
@ -914,7 +914,7 @@ def admin_setdomainsetting(domain_name):
|
||||
@app.route('/templates', methods=['GET', 'POST'])
|
||||
@app.route('/templates/list', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def templates():
|
||||
templates = DomainTemplate.query.all()
|
||||
return render_template('template.html', templates=templates)
|
||||
@ -922,7 +922,7 @@ def templates():
|
||||
|
||||
@app.route('/template/create', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def create_template():
|
||||
if request.method == 'GET':
|
||||
return render_template('template_add.html')
|
||||
@ -955,7 +955,7 @@ def create_template():
|
||||
|
||||
@app.route('/template/createfromzone', methods=['POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def create_template_from_zone():
|
||||
try:
|
||||
jdata = request.json
|
||||
@ -1015,7 +1015,7 @@ def create_template_from_zone():
|
||||
|
||||
@app.route('/template/<path:template>/edit', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def edit_template(template):
|
||||
try:
|
||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||
@ -1066,7 +1066,7 @@ def apply_records(template):
|
||||
|
||||
@app.route('/template/<path:template>/delete', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def delete_template(template):
|
||||
try:
|
||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||
@ -1085,10 +1085,10 @@ def delete_template(template):
|
||||
return redirect(url_for('templates'))
|
||||
|
||||
|
||||
@app.route('/admin', methods=['GET', 'POST'])
|
||||
@app.route('/admin/pdns', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def admin():
|
||||
@operator_role_required
|
||||
def admin_pdns():
|
||||
if not Setting().get('pdns_api_url') or not Setting().get('pdns_api_key') or not Setting().get('pdns_version'):
|
||||
return redirect(url_for('admin_setting_pdns'))
|
||||
|
||||
@ -1111,7 +1111,7 @@ def admin():
|
||||
@app.route('/admin/user/edit/<user_username>', methods=['GET', 'POST'])
|
||||
@app.route('/admin/user/edit', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_edituser(user_username=None):
|
||||
if request.method == 'GET':
|
||||
if not user_username:
|
||||
@ -1150,11 +1150,12 @@ def admin_edituser(user_username=None):
|
||||
|
||||
@app.route('/admin/manageuser', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_manageuser():
|
||||
if request.method == 'GET':
|
||||
roles = Role.query.all()
|
||||
users = User.query.order_by(User.username).all()
|
||||
return render_template('admin_manageuser.html', users=users)
|
||||
return render_template('admin_manageuser.html', users=users, roles=roles)
|
||||
|
||||
if request.method == 'POST':
|
||||
#
|
||||
@ -1197,19 +1198,31 @@ def admin_manageuser():
|
||||
else:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Cannot revoke user privilege.' } ), 500)
|
||||
|
||||
elif jdata['action'] == 'set_admin':
|
||||
elif jdata['action'] == 'update_user_role':
|
||||
username = data['username']
|
||||
role_name = data['role_name']
|
||||
|
||||
if username == current_user.username:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'You cannot change you own admin rights.' } ), 400)
|
||||
is_admin = data['is_admin']
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'You cannot change you own roles.' } ), 400)
|
||||
|
||||
user = User.query.filter(User.username==username).first()
|
||||
if not user:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'User does not exist.' } ), 404)
|
||||
|
||||
if user.role.name == 'Administrator' and current_user.role.name != 'Administrator':
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'You do not have permission to change Administrator users role.' } ), 400)
|
||||
|
||||
if role_name == 'Administrator' and current_user.role.name != 'Administrator':
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'You do not have permission to promote a user to Administrator role.' } ), 400)
|
||||
|
||||
user = User(username=username)
|
||||
result = user.set_admin(is_admin)
|
||||
if result:
|
||||
history = History(msg='Change user role of {0}'.format(username), created_by=current_user.username)
|
||||
result = user.set_role(role_name)
|
||||
if result['status']:
|
||||
history = History(msg='Change user role of {0} to {1}'.format(username, role_name), created_by=current_user.username)
|
||||
history.add()
|
||||
return make_response(jsonify( { 'status': 'ok', 'msg': 'Changed user role successfully.' } ), 200)
|
||||
else:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Cannot change user role.' } ), 500)
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Cannot change user role. {0}'.format(result['msg']) } ), 500)
|
||||
else:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
||||
except:
|
||||
@ -1220,7 +1233,7 @@ def admin_manageuser():
|
||||
@app.route('/admin/account/edit/<account_name>', methods=['GET', 'POST'])
|
||||
@app.route('/admin/account/edit', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_editaccount(account_name=None):
|
||||
users = User.query.all()
|
||||
|
||||
@ -1274,7 +1287,7 @@ def admin_editaccount(account_name=None):
|
||||
|
||||
@app.route('/admin/manageaccount', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_manageaccount():
|
||||
if request.method == 'GET':
|
||||
accounts = Account.query.order_by(Account.name).all()
|
||||
@ -1308,7 +1321,7 @@ def admin_manageaccount():
|
||||
|
||||
@app.route('/admin/history', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_history():
|
||||
if request.method == 'POST':
|
||||
h = History()
|
||||
@ -1328,7 +1341,7 @@ def admin_history():
|
||||
|
||||
@app.route('/admin/setting/basic', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_setting_basic():
|
||||
if request.method == 'GET':
|
||||
settings = Setting.query.filter(Setting.view=='basic').all()
|
||||
@ -1337,7 +1350,7 @@ def admin_setting_basic():
|
||||
|
||||
@app.route('/admin/setting/basic/<path:setting>/edit', methods=['POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_setting_basic_edit(setting):
|
||||
jdata = request.json
|
||||
new_value = jdata['value']
|
||||
@ -1351,7 +1364,7 @@ def admin_setting_basic_edit(setting):
|
||||
|
||||
@app.route('/admin/setting/basic/<path:setting>/toggle', methods=['POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_setting_basic_toggle(setting):
|
||||
result = Setting().toggle(setting)
|
||||
if (result):
|
||||
@ -1383,7 +1396,7 @@ def admin_setting_pdns():
|
||||
|
||||
@app.route('/admin/setting/dns-records', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@operator_role_required
|
||||
def admin_setting_records():
|
||||
if request.method == 'GET':
|
||||
f_records = literal_eval(Setting().get('forward_records_allow_edit'))
|
||||
@ -1438,6 +1451,7 @@ def admin_setting_authentication():
|
||||
Setting().set('ldap_filter_username', request.form.get('ldap_filter_username'))
|
||||
Setting().set('ldap_sg_enabled', True if request.form.get('ldap_sg_enabled')=='ON' else False)
|
||||
Setting().set('ldap_admin_group', request.form.get('ldap_admin_group'))
|
||||
Setting().set('ldap_operator_group', request.form.get('ldap_operator_group'))
|
||||
Setting().set('ldap_user_group', request.form.get('ldap_user_group'))
|
||||
result = {'status': True, 'msg': 'Saved successfully'}
|
||||
elif conf_type == 'google':
|
||||
|
58
migrations/versions/4a666113c7bb_add_operator_role.py
Normal file
58
migrations/versions/4a666113c7bb_add_operator_role.py
Normal file
@ -0,0 +1,58 @@
|
||||
"""Adding Operator Role
|
||||
|
||||
Revision ID: 4a666113c7bb
|
||||
Revises: 1274ed462010
|
||||
Create Date: 2018-08-30 13:28:06.836208
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '4a666113c7bb'
|
||||
down_revision = '1274ed462010'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def update_data():
|
||||
setting_table = sa.sql.table('setting',
|
||||
sa.sql.column('id', sa.Integer),
|
||||
sa.sql.column('name', sa.String),
|
||||
sa.sql.column('value', sa.String),
|
||||
sa.sql.column('view', sa.String)
|
||||
)
|
||||
|
||||
# add ldap_operator_group setting
|
||||
op.bulk_insert(setting_table,
|
||||
[
|
||||
{'id': 44, 'name': 'ldap_operator_group', 'value': '', 'view': 'authentication'},
|
||||
]
|
||||
)
|
||||
|
||||
role_table = sa.sql.table('role',
|
||||
sa.sql.column('id', sa.Integer),
|
||||
sa.sql.column('name', sa.String),
|
||||
sa.sql.column('description', sa.String)
|
||||
)
|
||||
|
||||
# add new role
|
||||
op.bulk_insert(role_table,
|
||||
[
|
||||
{'id': 3, 'name': 'Operator', 'description': 'Operator'}
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def upgrade():
|
||||
update_data()
|
||||
|
||||
|
||||
def downgrade():
|
||||
# remove user Operator role
|
||||
op.execute("UPDATE user SET role_id = 2 WHERE role_id=3")
|
||||
op.execute("DELETE FROM role WHERE name = 'Operator'")
|
||||
|
||||
# delete ldap setting
|
||||
op.execute("DELETE FROM setting WHERE name = 'ldap_operator_group'")
|
Loading…
Reference in New Issue
Block a user