mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2025-01-04 17:35:39 +00:00
Merge pull request #345 from ngoduykhanh/user_role_adjustment
Adding Operator role and Code adjustment
This commit is contained in:
commit
c8d72f5bba
10
.lgtm.yml
Normal file
10
.lgtm.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
extraction:
|
||||||
|
python:
|
||||||
|
python_setup:
|
||||||
|
version: 3
|
||||||
|
index:
|
||||||
|
exclude:
|
||||||
|
- .git
|
||||||
|
- upload
|
||||||
|
- flask
|
||||||
|
- node_modules
|
@ -29,7 +29,7 @@ login_manager = LoginManager()
|
|||||||
login_manager.init_app(app)
|
login_manager.init_app(app)
|
||||||
db = SQLAlchemy(app) # database
|
db = SQLAlchemy(app) # database
|
||||||
migrate = Migrate(app, db) # flask-migrate
|
migrate = Migrate(app, db) # flask-migrate
|
||||||
oauth = OAuth(app) # oauth
|
oauth_client = OAuth(app) # oauth
|
||||||
|
|
||||||
if app.config.get('SAML_ENABLED') and app.config.get('SAML_ENCRYPT'):
|
if app.config.get('SAML_ENABLED') and app.config.get('SAML_ENCRYPT'):
|
||||||
from app.lib import certutil
|
from app.lib import certutil
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
from flask import g, request, redirect, url_for
|
from flask import g, redirect, url_for
|
||||||
|
|
||||||
from app import app
|
from app.models import Setting
|
||||||
from app.models import Role, Setting
|
|
||||||
|
|
||||||
|
|
||||||
def admin_role_required(f):
|
def admin_role_required(f):
|
||||||
|
"""
|
||||||
|
Grant access if user is in Administrator role
|
||||||
|
"""
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
if g.user.role.name != 'Administrator':
|
if g.user.role.name != 'Administrator':
|
||||||
@ -14,10 +16,28 @@ def admin_role_required(f):
|
|||||||
return decorated_function
|
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)
|
@wraps(f)
|
||||||
def decorated_function(*args, **kwargs):
|
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')
|
domain_name = kwargs.get('domain_name')
|
||||||
user_domain = [d.name for d in g.user.get_domain()]
|
user_domain = [d.name for d in g.user.get_domain()]
|
||||||
|
|
||||||
@ -29,10 +49,30 @@ def can_access_domain(f):
|
|||||||
|
|
||||||
|
|
||||||
def can_configure_dnssec(f):
|
def can_configure_dnssec(f):
|
||||||
|
"""
|
||||||
|
Grant access if:
|
||||||
|
- user is in Operator role or higher, or
|
||||||
|
- dnssec_admins_only is off
|
||||||
|
"""
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
if g.user.role.name != 'Administrator' and Setting().get('dnssec_admins_only'):
|
if g.user.role.name not in ['Administrator', 'Operator'] and Setting().get('dnssec_admins_only'):
|
||||||
return redirect(url_for('error', code=401))
|
return redirect(url_for('error', code=401))
|
||||||
|
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
return decorated_function
|
||||||
|
|
||||||
|
|
||||||
|
def can_create_domain(f):
|
||||||
|
"""
|
||||||
|
Grant access if:
|
||||||
|
- user is in Operator role or higher, or
|
||||||
|
- allow_user_create_domain is on
|
||||||
|
"""
|
||||||
|
@wraps(f)
|
||||||
|
def decorated_function(*args, **kwargs):
|
||||||
|
if g.user.role.name not in ['Administrator', 'Operator'] and not Setting().get('allow_user_create_domain'):
|
||||||
|
return redirect(url_for('error', code=401))
|
||||||
|
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
class logger(object):
|
class logger(object):
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
import hashlib
|
import hashlib
|
||||||
@ -10,12 +9,10 @@ from urllib.parse import urlparse
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from .certutil import *
|
from .certutil import KEY_FILE, CERT_FILE
|
||||||
|
|
||||||
if app.config['SAML_ENABLED']:
|
if app.config['SAML_ENABLED']:
|
||||||
from onelogin.saml2.auth import OneLogin_Saml2_Auth
|
from onelogin.saml2.auth import OneLogin_Saml2_Auth
|
||||||
from onelogin.saml2.utils import OneLogin_Saml2_Utils
|
|
||||||
from onelogin.saml2.settings import OneLogin_Saml2_Settings
|
|
||||||
from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
|
from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
|
||||||
idp_timestamp = datetime(1970, 1, 1)
|
idp_timestamp = datetime(1970, 1, 1)
|
||||||
idp_data = None
|
idp_data = None
|
||||||
@ -227,7 +224,7 @@ def prepare_flask_request(request):
|
|||||||
|
|
||||||
def init_saml_auth(req):
|
def init_saml_auth(req):
|
||||||
own_url = ''
|
own_url = ''
|
||||||
if req['https'] is 'on':
|
if req['https'] == 'on':
|
||||||
own_url = 'https://'
|
own_url = 'https://'
|
||||||
else:
|
else:
|
||||||
own_url = 'http://'
|
own_url = 'http://'
|
||||||
@ -285,3 +282,12 @@ def init_saml_auth(req):
|
|||||||
settings['organization']['en-US']['url'] = own_url
|
settings['organization']['en-US']['url'] = own_url
|
||||||
auth = OneLogin_Saml2_Auth(req, settings)
|
auth = OneLogin_Saml2_Auth(req, settings)
|
||||||
return auth
|
return auth
|
||||||
|
|
||||||
|
|
||||||
|
def display_setting_state(value):
|
||||||
|
if value == 1:
|
||||||
|
return "ON"
|
||||||
|
elif value == 0:
|
||||||
|
return "OFF"
|
||||||
|
else:
|
||||||
|
return "UNKNOWN"
|
||||||
|
220
app/models.py
220
app/models.py
@ -1,17 +1,16 @@
|
|||||||
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import ldap
|
import ldap
|
||||||
import ldap.filter
|
import ldap.filter
|
||||||
import time
|
|
||||||
import base64
|
import base64
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import itertools
|
import itertools
|
||||||
import traceback
|
import traceback
|
||||||
import pyotp
|
import pyotp
|
||||||
import re
|
|
||||||
import dns.reversename
|
import dns.reversename
|
||||||
import dns.inet
|
import dns.inet
|
||||||
import dns.name
|
import dns.name
|
||||||
import sys
|
|
||||||
import logging as logger
|
import logging as logger
|
||||||
|
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
@ -150,7 +149,7 @@ class User(db.Model):
|
|||||||
logging.error(e)
|
logging.error(e)
|
||||||
logging.debug('baseDN: {0}'.format(baseDN))
|
logging.debug('baseDN: {0}'.format(baseDN))
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
raise
|
|
||||||
|
|
||||||
def ldap_auth(self, ldap_username, password):
|
def ldap_auth(self, ldap_username, password):
|
||||||
try:
|
try:
|
||||||
@ -165,6 +164,8 @@ class User(db.Model):
|
|||||||
"""
|
"""
|
||||||
Validate user credential
|
Validate user credential
|
||||||
"""
|
"""
|
||||||
|
role_name = 'User'
|
||||||
|
|
||||||
if method == 'LOCAL':
|
if method == 'LOCAL':
|
||||||
user_info = User.query.filter(User.username == self.username).first()
|
user_info = User.query.filter(User.username == self.username).first()
|
||||||
|
|
||||||
@ -179,12 +180,12 @@ class User(db.Model):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if method == 'LDAP':
|
if method == 'LDAP':
|
||||||
isadmin = False
|
|
||||||
LDAP_TYPE = Setting().get('ldap_type')
|
LDAP_TYPE = Setting().get('ldap_type')
|
||||||
LDAP_BASE_DN = Setting().get('ldap_base_dn')
|
LDAP_BASE_DN = Setting().get('ldap_base_dn')
|
||||||
LDAP_FILTER_BASIC = Setting().get('ldap_filter_basic')
|
LDAP_FILTER_BASIC = Setting().get('ldap_filter_basic')
|
||||||
LDAP_FILTER_USERNAME = Setting().get('ldap_filter_username')
|
LDAP_FILTER_USERNAME = Setting().get('ldap_filter_username')
|
||||||
LDAP_ADMIN_GROUP = Setting().get('ldap_admin_group')
|
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_USER_GROUP = Setting().get('ldap_user_group')
|
||||||
LDAP_GROUP_SECURITY_ENABLED = Setting().get('ldap_sg_enabled')
|
LDAP_GROUP_SECURITY_ENABLED = Setting().get('ldap_sg_enabled')
|
||||||
|
|
||||||
@ -206,24 +207,30 @@ class User(db.Model):
|
|||||||
try:
|
try:
|
||||||
if LDAP_TYPE == 'ldap':
|
if LDAP_TYPE == 'ldap':
|
||||||
if (self.ldap_search(searchFilter, LDAP_ADMIN_GROUP)):
|
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))
|
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)):
|
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))
|
logging.info('User {0} is part of the "{1}" group that allows user access to PowerDNS-Admin'.format(self.username, LDAP_USER_GROUP))
|
||||||
else:
|
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
|
return False
|
||||||
elif LDAP_TYPE == 'ad':
|
elif LDAP_TYPE == 'ad':
|
||||||
user_ldap_groups = [g.decode("utf-8") for g in ldap_result[0][0][1]['memberOf']]
|
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))
|
logging.debug('user_ldap_groups: {0}'.format(user_ldap_groups))
|
||||||
|
|
||||||
if (LDAP_ADMIN_GROUP in 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))
|
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):
|
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))
|
logging.info('User {0} is part of the "{1}" group that allows user access to PowerDNS-Admin'.format(self.username, LDAP_USER_GROUP))
|
||||||
else:
|
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
|
return False
|
||||||
else:
|
else:
|
||||||
logging.error('Invalid LDAP type')
|
logging.error('Invalid LDAP type')
|
||||||
@ -261,21 +268,17 @@ class User(db.Model):
|
|||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
|
|
||||||
# first register user will be in Administrator role
|
# first register user will be in Administrator role
|
||||||
self.role_id = Role.query.filter_by(name='User').first().id
|
|
||||||
if User.query.count() == 0:
|
if User.query.count() == 0:
|
||||||
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
||||||
|
else:
|
||||||
# user will be in Administrator role if part of LDAP Admin group
|
self.role_id = Role.query.filter_by(name=role_name).first().id
|
||||||
if LDAP_GROUP_SECURITY_ENABLED:
|
|
||||||
if isadmin == True:
|
|
||||||
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
|
||||||
|
|
||||||
self.create_user()
|
self.create_user()
|
||||||
logging.info('Created user "{0}" in the DB'.format(self.username))
|
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:
|
if LDAP_GROUP_SECURITY_ENABLED:
|
||||||
self.set_admin(isadmin)
|
self.set_role(role_name)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -430,9 +433,9 @@ class User(db.Model):
|
|||||||
User.query.filter(User.username == self.username).delete()
|
User.query.filter(User.username == self.username).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot delete user {0} from DB'.format(self.username))
|
logging.error('Cannot delete user {0} from DB. DETAIL: {1}'.format(self.username, e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def revoke_privilege(self):
|
def revoke_privilege(self):
|
||||||
@ -447,34 +450,21 @@ class User(db.Model):
|
|||||||
DomainUser.query.filter(DomainUser.user_id == user_id).delete()
|
DomainUser.query.filter(DomainUser.user_id == user_id).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot revoke user {0} privielges'.format(self.username))
|
logging.error('Cannot revoke user {0} privielges. DETAIL: {1}'.format(self.username, e))
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_admin(self, is_admin):
|
def set_role(self, role_name):
|
||||||
"""
|
role = Role.query.filter(Role.name==role_name).first()
|
||||||
Set role for a user:
|
if role:
|
||||||
is_admin == True => Administrator
|
user = User.query.filter(User.username==self.username).first()
|
||||||
is_admin == False => User
|
user.role_id = role.id
|
||||||
"""
|
db.session.commit()
|
||||||
user_role_name = 'Administrator' if is_admin else 'User'
|
return {'status': True, 'msg': 'Set user role successfully'}
|
||||||
role = Role.query.filter(Role.name==user_role_name).first()
|
else:
|
||||||
|
return {'status': False, 'msg': 'Role does not exist'}
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class Account(db.Model):
|
class Account(db.Model):
|
||||||
@ -580,9 +570,9 @@ class Account(db.Model):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot delete account {0} from DB'.format(self.username))
|
logging.error('Cannot delete account {0} from DB. DETAIL: {1}'.format(self.username, e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_user(self):
|
def get_user(self):
|
||||||
@ -611,18 +601,18 @@ class Account(db.Model):
|
|||||||
for uid in removed_ids:
|
for uid in removed_ids:
|
||||||
AccountUser.query.filter(AccountUser.user_id == uid).filter(AccountUser.account_id==account_id).delete()
|
AccountUser.query.filter(AccountUser.user_id == uid).filter(AccountUser.account_id==account_id).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot revoke user privielges on account {0}'.format(self.name))
|
logging.error('Cannot revoke user privielges on account {0}. DETAIL: {1}'.format(self.name, e))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for uid in added_ids:
|
for uid in added_ids:
|
||||||
au = AccountUser(account_id, uid)
|
au = AccountUser(account_id, uid)
|
||||||
db.session.add(au)
|
db.session.add(au)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot grant user privileges to account {0}'.format(self.name))
|
logging.error('Cannot grant user privileges to account {0}. DETAIL: {1}'.format(self.name, e))
|
||||||
|
|
||||||
def revoke_privileges_by_id(self, user_id):
|
def revoke_privileges_by_id(self, user_id):
|
||||||
"""
|
"""
|
||||||
@ -643,9 +633,9 @@ class Account(db.Model):
|
|||||||
db.session.add(au)
|
db.session.add(au)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot add user privielges on account {0}'.format(self.name))
|
logging.error('Cannot add user privielges on account {0}. DETAIL: {1}'.format(self.name, e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_user(self, user):
|
def remove_user(self, user):
|
||||||
@ -656,9 +646,9 @@ class Account(db.Model):
|
|||||||
AccountUser.query.filter(AccountUser.user_id == user.id).filter(AccountUser.account_id == self.id).delete()
|
AccountUser.query.filter(AccountUser.user_id == user.id).filter(AccountUser.account_id == self.id).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot revoke user privielges on account {0}'.format(self.name))
|
logging.error('Cannot revoke user privielges on account {0}. DETAIL: {1}'.format(self.name, e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -707,8 +697,8 @@ class DomainSetting(db.Model):
|
|||||||
self.value = value
|
self.value = value
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error('Unable to set DomainSetting value')
|
logging.error('Unable to set DomainSetting value. DETAIL: {0}'.format(e))
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
return False
|
return False
|
||||||
@ -784,7 +774,8 @@ class Domain(db.Model):
|
|||||||
try:
|
try:
|
||||||
domain = Domain.query.filter(Domain.name==name).first()
|
domain = Domain.query.filter(Domain.name==name).first()
|
||||||
return domain.id
|
return domain.id
|
||||||
except:
|
except Exception as e:
|
||||||
|
logging.error('Domain does not exist. ERROR: {0}'.format(e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
@ -818,8 +809,8 @@ class Domain(db.Model):
|
|||||||
# then remove domain
|
# then remove domain
|
||||||
Domain.query.filter(Domain.name == d).delete()
|
Domain.query.filter(Domain.name == d).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error('Can not delete domain from DB')
|
logging.error('Can not delete domain from DB. DETAIL: {0}'.format(e))
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
|
|
||||||
@ -911,7 +902,7 @@ class Domain(db.Model):
|
|||||||
return {'status': 'ok', 'msg': 'Added domain successfully'}
|
return {'status': 'ok', 'msg': 'Added domain successfully'}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error('Cannot add domain {0}'.format(domain_name))
|
logging.error('Cannot add domain {0}'.format(domain_name))
|
||||||
logging.debug(traceback.print_exc())
|
logging.debug(traceback.format_exc())
|
||||||
return {'status': 'error', 'msg': 'Cannot add this domain.'}
|
return {'status': 'error', 'msg': 'Cannot add this domain.'}
|
||||||
|
|
||||||
def update_soa_setting(self, domain_name, soa_edit_api):
|
def update_soa_setting(self, domain_name, soa_edit_api):
|
||||||
@ -980,7 +971,7 @@ class Domain(db.Model):
|
|||||||
domain_users.append(tmp.username)
|
domain_users.append(tmp.username)
|
||||||
if 0 != len(domain_users):
|
if 0 != len(domain_users):
|
||||||
self.name = domain_reverse_name
|
self.name = domain_reverse_name
|
||||||
self.grant_privielges(domain_users)
|
self.grant_privileges(domain_users)
|
||||||
return {'status': 'ok', 'msg': 'New reverse lookup domain created with granted privilages'}
|
return {'status': 'ok', 'msg': 'New reverse lookup domain created with granted privilages'}
|
||||||
return {'status': 'ok', 'msg': 'New reverse lookup domain created without users'}
|
return {'status': 'ok', 'msg': 'New reverse lookup domain created without users'}
|
||||||
return {'status': 'ok', 'msg': 'Reverse lookup domain already exists'}
|
return {'status': 'ok', 'msg': 'Reverse lookup domain already exists'}
|
||||||
@ -1009,12 +1000,12 @@ class Domain(db.Model):
|
|||||||
headers = {}
|
headers = {}
|
||||||
headers['X-API-Key'] = self.PDNS_API_KEY
|
headers['X-API-Key'] = self.PDNS_API_KEY
|
||||||
try:
|
try:
|
||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain_name)), headers=headers, method='DELETE')
|
utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain_name)), headers=headers, method='DELETE')
|
||||||
logging.info('Delete domain {0} successfully'.format(domain_name))
|
logging.info('Delete domain {0} successfully'.format(domain_name))
|
||||||
return {'status': 'ok', 'msg': 'Delete domain successfully'}
|
return {'status': 'ok', 'msg': 'Delete domain successfully'}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error('Cannot delete domain {0}'.format(domain_name))
|
logging.error('Cannot delete domain {0}'.format(domain_name))
|
||||||
logging.debug(traceback.print_exc())
|
logging.debug(traceback.format_exc())
|
||||||
return {'status': 'error', 'msg': 'Cannot delete domain'}
|
return {'status': 'error', 'msg': 'Cannot delete domain'}
|
||||||
|
|
||||||
def get_user(self):
|
def get_user(self):
|
||||||
@ -1027,7 +1018,7 @@ class Domain(db.Model):
|
|||||||
user_ids.append(q[0].user_id)
|
user_ids.append(q[0].user_id)
|
||||||
return user_ids
|
return user_ids
|
||||||
|
|
||||||
def grant_privielges(self, new_user_list):
|
def grant_privileges(self, new_user_list):
|
||||||
"""
|
"""
|
||||||
Reconfigure domain_user table
|
Reconfigure domain_user table
|
||||||
"""
|
"""
|
||||||
@ -1044,18 +1035,18 @@ class Domain(db.Model):
|
|||||||
for uid in removed_ids:
|
for uid in removed_ids:
|
||||||
DomainUser.query.filter(DomainUser.user_id == uid).filter(DomainUser.domain_id==domain_id).delete()
|
DomainUser.query.filter(DomainUser.user_id == uid).filter(DomainUser.domain_id==domain_id).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot revoke user privielges on domain {0}'.format(self.name))
|
logging.error('Cannot revoke user privielges on domain {0}. DETAIL: {1}'.format(self.name, e))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for uid in added_ids:
|
for uid in added_ids:
|
||||||
du = DomainUser(domain_id, uid)
|
du = DomainUser(domain_id, uid)
|
||||||
db.session.add(du)
|
db.session.add(du)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error('Cannot grant user privielges to domain {0}'.format(self.name))
|
logging.error('Cannot grant user privielges to domain {0}. DETAIL: {1}'.format(self.name, e))
|
||||||
|
|
||||||
def update_from_master(self, domain_name):
|
def update_from_master(self, domain_name):
|
||||||
"""
|
"""
|
||||||
@ -1066,9 +1057,10 @@ class Domain(db.Model):
|
|||||||
headers = {}
|
headers = {}
|
||||||
headers['X-API-Key'] = self.PDNS_API_KEY
|
headers['X-API-Key'] = self.PDNS_API_KEY
|
||||||
try:
|
try:
|
||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}/axfr-retrieve'.format(domain.name)), headers=headers, method='PUT')
|
utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}/axfr-retrieve'.format(domain.name)), headers=headers, method='PUT')
|
||||||
return {'status': 'ok', 'msg': 'Update from Master successfully'}
|
return {'status': 'ok', 'msg': 'Update from Master successfully'}
|
||||||
except:
|
except Exception as e:
|
||||||
|
logging.error('Cannot update from master. DETAIL: {0}'.format(e))
|
||||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
||||||
else:
|
else:
|
||||||
return {'status': 'error', 'msg': 'This domain doesnot exist'}
|
return {'status': 'error', 'msg': 'This domain doesnot exist'}
|
||||||
@ -1087,7 +1079,8 @@ class Domain(db.Model):
|
|||||||
return {'status': 'error', 'msg': 'DNSSEC is not enabled for this domain'}
|
return {'status': 'error', 'msg': 'DNSSEC is not enabled for this domain'}
|
||||||
else:
|
else:
|
||||||
return {'status': 'ok', 'dnssec': jdata}
|
return {'status': 'ok', 'dnssec': jdata}
|
||||||
except:
|
except Exception as e:
|
||||||
|
logging.error('Cannot get domain dnssec. DETAIL: {0}'.format(e))
|
||||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
||||||
else:
|
else:
|
||||||
return {'status': 'error', 'msg': 'This domain doesnot exist'}
|
return {'status': 'error', 'msg': 'This domain doesnot exist'}
|
||||||
@ -1120,8 +1113,9 @@ class Domain(db.Model):
|
|||||||
|
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error(traceback.print_exc())
|
logging.error('Cannot enable dns sec. DETAIL: {}'.format(e))
|
||||||
|
logging.debug(traceback.format_exc())
|
||||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -1151,8 +1145,9 @@ class Domain(db.Model):
|
|||||||
|
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error(traceback.print_exc())
|
logging.error('Cannot delete dnssec key. DETAIL: {0}'.format(e))
|
||||||
|
logging.debug(traceback.format_exc())
|
||||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator','domain': domain.name, 'id': key_id}
|
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator','domain': domain.name, 'id': key_id}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -1190,10 +1185,9 @@ class Domain(db.Model):
|
|||||||
if 'error' in jdata.keys():
|
if 'error' in jdata.keys():
|
||||||
logging.error(jdata['error'])
|
logging.error(jdata['error'])
|
||||||
return {'status': 'error', 'msg': jdata['error']}
|
return {'status': 'error', 'msg': jdata['error']}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.update()
|
self.update()
|
||||||
logging.info('account changed for domain {0} successfully'.format(domain_name))
|
logging.info('Account changed for domain {0} successfully'.format(domain_name))
|
||||||
return {'status': 'ok', 'msg': 'account changed successfully'}
|
return {'status': 'ok', 'msg': 'account changed successfully'}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -1202,8 +1196,6 @@ class Domain(db.Model):
|
|||||||
logging.error('Cannot change account for domain {0}'.format(domain_name))
|
logging.error('Cannot change account for domain {0}'.format(domain_name))
|
||||||
return {'status': 'error', 'msg': 'Cannot change account for this domain.'}
|
return {'status': 'error', 'msg': 'Cannot change account for this domain.'}
|
||||||
|
|
||||||
return {'status': True, 'msg': 'Domain association successful'}
|
|
||||||
|
|
||||||
def get_account(self):
|
def get_account(self):
|
||||||
"""
|
"""
|
||||||
Get current account associated with this domain
|
Get current account associated with this domain
|
||||||
@ -1273,8 +1265,8 @@ class Record(object):
|
|||||||
headers['X-API-Key'] = self.PDNS_API_KEY
|
headers['X-API-Key'] = self.PDNS_API_KEY
|
||||||
try:
|
try:
|
||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers)
|
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers)
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error("Cannot fetch domain's record data from remote powerdns api")
|
logging.error("Cannot fetch domain's record data from remote powerdns api. DETAIL: {0}".format(e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.NEW_SCHEMA:
|
if self.NEW_SCHEMA:
|
||||||
@ -1573,7 +1565,6 @@ class Record(object):
|
|||||||
self.add(domain_reverse_name)
|
self.add(domain_reverse_name)
|
||||||
for r in deleted_records:
|
for r in deleted_records:
|
||||||
if r['type'] in ['A', 'AAAA']:
|
if r['type'] in ['A', 'AAAA']:
|
||||||
r_name = r['name'] + '.'
|
|
||||||
r_content = r['content']
|
r_content = r['content']
|
||||||
reverse_host_address = dns.reversename.from_address(r_content).to_text()
|
reverse_host_address = dns.reversename.from_address(r_content).to_text()
|
||||||
domain_reverse_name = d.get_reverse_domain_name(reverse_host_address)
|
domain_reverse_name = d.get_reverse_domain_name(reverse_host_address)
|
||||||
@ -1606,8 +1597,8 @@ class Record(object):
|
|||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='PATCH', data=data)
|
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='PATCH', data=data)
|
||||||
logging.debug(jdata)
|
logging.debug(jdata)
|
||||||
return {'status': 'ok', 'msg': 'Record was removed successfully'}
|
return {'status': 'ok', 'msg': 'Record was removed successfully'}
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error("Cannot remove record {0}/{1}/{2} from domain {3}".format(self.name, self.type, self.data, domain))
|
logging.error("Cannot remove record {0}/{1}/{2} from domain {3}. DETAIL: {4}".format(self.name, self.type, self.data, domain, e))
|
||||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
||||||
|
|
||||||
def is_allowed_edit(self):
|
def is_allowed_edit(self):
|
||||||
@ -1683,7 +1674,7 @@ class Record(object):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='PATCH', data=data)
|
utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='PATCH', data=data)
|
||||||
logging.debug("dyndns data: {0}".format(data))
|
logging.debug("dyndns data: {0}".format(data))
|
||||||
return {'status': 'ok', 'msg': 'Record was updated successfully'}
|
return {'status': 'ok', 'msg': 'Record was updated successfully'}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -1730,8 +1721,8 @@ class Server(object):
|
|||||||
try:
|
try:
|
||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/{0}/config'.format(self.server_id)), headers=headers, method='GET')
|
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/{0}/config'.format(self.server_id)), headers=headers, method='GET')
|
||||||
return jdata
|
return jdata
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error("Can not get server configuration.")
|
logging.error("Can not get server configuration. DETAIL: {0}".format(e))
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -1745,8 +1736,8 @@ class Server(object):
|
|||||||
try:
|
try:
|
||||||
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/{0}/statistics'.format(self.server_id)), headers=headers, method='GET')
|
jdata = utils.fetch_json(urljoin(self.PDNS_STATS_URL, self.API_EXTENDED_URL + '/servers/{0}/statistics'.format(self.server_id)), headers=headers, method='GET')
|
||||||
return jdata
|
return jdata
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error("Can not get server statistics.")
|
logging.error("Can not get server statistics. DETAIL: {0}".format(e))
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -1784,13 +1775,13 @@ class History(db.Model):
|
|||||||
Remove all history from DB
|
Remove all history from DB
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
num_rows_deleted = db.session.query(History).delete()
|
db.session.query(History).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
logging.info("Removed all history")
|
logging.info("Removed all history")
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
logging.error("Cannot remove history")
|
logging.error("Cannot remove history. DETAIL: {0}".format(e))
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -1798,7 +1789,6 @@ class Setting(db.Model):
|
|||||||
id = db.Column(db.Integer, primary_key = True)
|
id = db.Column(db.Integer, primary_key = True)
|
||||||
name = db.Column(db.String(64))
|
name = db.Column(db.String(64))
|
||||||
value = db.Column(db.Text())
|
value = db.Column(db.Text())
|
||||||
view = db.Column(db.String(64))
|
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
'maintenance': False,
|
'maintenance': False,
|
||||||
@ -1808,9 +1798,10 @@ class Setting(db.Model):
|
|||||||
'default_record_table_size': 15,
|
'default_record_table_size': 15,
|
||||||
'default_domain_table_size': 10,
|
'default_domain_table_size': 10,
|
||||||
'auto_ptr': False,
|
'auto_ptr': False,
|
||||||
'allow_quick_edit': True,
|
'record_quick_edit': True,
|
||||||
'pretty_ipv6_ptr': False,
|
'pretty_ipv6_ptr': False,
|
||||||
'dnssec_admins_only': False,
|
'dnssec_admins_only': False,
|
||||||
|
'allow_user_create_domain': False,
|
||||||
'bg_domain_updates': False,
|
'bg_domain_updates': False,
|
||||||
'site_name': 'PowerDNS-Admin',
|
'site_name': 'PowerDNS-Admin',
|
||||||
'pdns_api_url': '',
|
'pdns_api_url': '',
|
||||||
@ -1827,8 +1818,9 @@ class Setting(db.Model):
|
|||||||
'ldap_filter_basic': '',
|
'ldap_filter_basic': '',
|
||||||
'ldap_filter_username': '',
|
'ldap_filter_username': '',
|
||||||
'ldap_sg_enabled': False,
|
'ldap_sg_enabled': False,
|
||||||
'ldap_admin_group': False,
|
'ldap_admin_group': '',
|
||||||
'ldap_user_group': False,
|
'ldap_operator_group': '',
|
||||||
|
'ldap_user_group': '',
|
||||||
'github_oauth_enabled': False,
|
'github_oauth_enabled': False,
|
||||||
'github_oauth_key': '',
|
'github_oauth_key': '',
|
||||||
'github_oauth_secret': '',
|
'github_oauth_secret': '',
|
||||||
@ -1873,8 +1865,8 @@ class Setting(db.Model):
|
|||||||
maintenance.value = mode
|
maintenance.value = mode
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error('Cannot set maintenance to {0}'.format(mode))
|
logging.error('Cannot set maintenance to {0}. DETAIL: {1}'.format(mode, e))
|
||||||
logging.debug(traceback.format_exec())
|
logging.debug(traceback.format_exec())
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
return False
|
return False
|
||||||
@ -1894,8 +1886,8 @@ class Setting(db.Model):
|
|||||||
current_setting.value = "True"
|
current_setting.value = "True"
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error('Cannot toggle setting {0}'.format(setting))
|
logging.error('Cannot toggle setting {0}. DETAIL: {1}'.format(setting, e))
|
||||||
logging.debug(traceback.format_exec())
|
logging.debug(traceback.format_exec())
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
return False
|
return False
|
||||||
@ -1913,8 +1905,8 @@ class Setting(db.Model):
|
|||||||
current_setting.value = value
|
current_setting.value = value
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error('Cannot edit setting {0}'.format(setting))
|
logging.error('Cannot edit setting {0}. DETAIL: {1}'.format(setting, e))
|
||||||
logging.debug(traceback.format_exec())
|
logging.debug(traceback.format_exec())
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
return False
|
return False
|
||||||
@ -1933,20 +1925,22 @@ class Setting(db.Model):
|
|||||||
return list(set(self.get_forward_records_allow_to_edit() + self.get_reverse_records_allow_to_edit()))
|
return list(set(self.get_forward_records_allow_to_edit() + self.get_reverse_records_allow_to_edit()))
|
||||||
|
|
||||||
def get_forward_records_allow_to_edit(self):
|
def get_forward_records_allow_to_edit(self):
|
||||||
records = literal_eval(self.get('forward_records_allow_edit'))
|
records = self.get('forward_records_allow_edit')
|
||||||
return [r for r in records if records[r]]
|
f_records = literal_eval(records) if isinstance(records, str) else records
|
||||||
|
r_name = [r for r in f_records if f_records[r]]
|
||||||
|
# Sort alphabetically if python version is smaller than 3.6
|
||||||
|
if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 6):
|
||||||
|
r_name.sort()
|
||||||
|
return r_name
|
||||||
|
|
||||||
def get_reverse_records_allow_to_edit(self):
|
def get_reverse_records_allow_to_edit(self):
|
||||||
records = literal_eval(self.get('reverse_records_allow_edit'))
|
records = self.get('reverse_records_allow_edit')
|
||||||
return [r for r in records if records[r]]
|
r_records = literal_eval(records) if isinstance(records, str) else records
|
||||||
|
r_name = [r for r in r_records if r_records[r]]
|
||||||
def get_view(self, view):
|
# Sort alphabetically if python version is smaller than 3.6
|
||||||
r = {}
|
if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 6):
|
||||||
settings = Setting.query.filter(Setting.view == view).all()
|
r_name.sort()
|
||||||
for setting in settings:
|
return r_name
|
||||||
d = setting.__dict__
|
|
||||||
r[d['name']] = d['value']
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
class DomainTemplate(db.Model):
|
class DomainTemplate(db.Model):
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
from flask import request, session, redirect, url_for
|
from flask import request, session, redirect, url_for
|
||||||
from flask_oauthlib.client import OAuth
|
|
||||||
|
|
||||||
from app import app, oauth
|
from app import app, oauth_client
|
||||||
from app.models import Setting
|
from app.models import Setting
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
@ -13,7 +12,7 @@ def github_oauth():
|
|||||||
if not Setting().get('github_oauth_enabled'):
|
if not Setting().get('github_oauth_enabled'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
github = oauth.remote_app(
|
github = oauth_client.remote_app(
|
||||||
'github',
|
'github',
|
||||||
consumer_key = Setting().get('github_oauth_key'),
|
consumer_key = Setting().get('github_oauth_key'),
|
||||||
consumer_secret = Setting().get('github_oauth_secret'),
|
consumer_secret = Setting().get('github_oauth_secret'),
|
||||||
@ -48,7 +47,7 @@ def google_oauth():
|
|||||||
if not Setting().get('google_oauth_enabled'):
|
if not Setting().get('google_oauth_enabled'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
google = oauth.remote_app(
|
google = oauth_client.remote_app(
|
||||||
'google',
|
'google',
|
||||||
consumer_key=Setting().get('google_oauth_client_id'),
|
consumer_key=Setting().get('google_oauth_client_id'),
|
||||||
consumer_secret=Setting().get('google_oauth_client_secret'),
|
consumer_secret=Setting().get('google_oauth_client_secret'),
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
var dnssecKeyList = []
|
var dnssecKeyList = []
|
||||||
|
|
||||||
function applyChanges(data, url, showResult, refreshPage) {
|
function applyChanges(data, url, showResult, refreshPage) {
|
||||||
var success = false;
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type : "POST",
|
type : "POST",
|
||||||
url : url,
|
url : url,
|
||||||
@ -22,16 +21,20 @@ function applyChanges(data, url, showResult, refreshPage) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
error : function(jqXHR, status) {
|
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);
|
console.log(jqXHR);
|
||||||
var modal = $("#modal_error");
|
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');
|
modal.modal('show');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyRecordChanges(data, domain) {
|
function applyRecordChanges(data, domain) {
|
||||||
var success = false;
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type : "POST",
|
type : "POST",
|
||||||
url : $SCRIPT_ROOT + '/domain/' + domain + '/apply',
|
url : $SCRIPT_ROOT + '/domain/' + domain + '/apply',
|
||||||
@ -62,8 +65,6 @@ function applyRecordChanges(data, domain) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTableData(table) {
|
function getTableData(table) {
|
||||||
var rData = []
|
|
||||||
|
|
||||||
// reformat - pretty format
|
// reformat - pretty format
|
||||||
var records = []
|
var records = []
|
||||||
table.rows().every(function() {
|
table.rows().every(function() {
|
||||||
@ -81,16 +82,14 @@ function getTableData(table) {
|
|||||||
|
|
||||||
function saveRow(oTable, nRow) {
|
function saveRow(oTable, nRow) {
|
||||||
|
|
||||||
|
var status = 'Disabled';
|
||||||
var jqInputs = $(oTable.row(nRow).node()).find("input");
|
var jqInputs = $(oTable.row(nRow).node()).find("input");
|
||||||
var jqSelect = $(oTable.row(nRow).node()).find("select");
|
var jqSelect = $(oTable.row(nRow).node()).find("select");
|
||||||
|
|
||||||
if (jqSelect[1].value == 'false') {
|
if (jqSelect[1].value == 'false') {
|
||||||
status = 'Active';
|
status = 'Active';
|
||||||
} else {
|
|
||||||
status = 'Disabled';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
oTable.cell(nRow,0).data(jqInputs[0].value);
|
oTable.cell(nRow,0).data(jqInputs[0].value);
|
||||||
oTable.cell(nRow,1).data(jqSelect[0].value);
|
oTable.cell(nRow,1).data(jqSelect[0].value);
|
||||||
oTable.cell(nRow,2).data(status);
|
oTable.cell(nRow,2).data(status);
|
||||||
@ -109,12 +108,12 @@ function saveRow(oTable, nRow) {
|
|||||||
|
|
||||||
function restoreRow(oTable, nRow) {
|
function restoreRow(oTable, nRow) {
|
||||||
var aData = oTable.row(nRow).data();
|
var aData = oTable.row(nRow).data();
|
||||||
var jqTds = $('>td', nRow);
|
|
||||||
oTable.row(nRow).data(aData);
|
oTable.row(nRow).data(aData);
|
||||||
oTable.draw();
|
oTable.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
function editRow(oTable, nRow) {
|
function editRow(oTable, nRow) {
|
||||||
|
var isDisabled = 'true';
|
||||||
var aData = oTable.row(nRow).data();
|
var aData = oTable.row(nRow).data();
|
||||||
var jqTds = oTable.cells(nRow,'').nodes();
|
var jqTds = oTable.cells(nRow,'').nodes();
|
||||||
var record_types = "";
|
var record_types = "";
|
||||||
@ -134,9 +133,6 @@ function editRow(oTable, nRow) {
|
|||||||
if (aData[2] == 'Active'){
|
if (aData[2] == 'Active'){
|
||||||
isDisabled = 'false';
|
isDisabled = 'false';
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
isDisabled = 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectElement('record_type', aData[1]);
|
SelectElement('record_type', aData[1]);
|
||||||
SelectElement('record_status', isDisabled);
|
SelectElement('record_status', isDisabled);
|
||||||
@ -167,13 +163,14 @@ function enable_dns_sec(url) {
|
|||||||
function getdnssec(url, domain){
|
function getdnssec(url, domain){
|
||||||
|
|
||||||
$.getJSON(url, function(data) {
|
$.getJSON(url, function(data) {
|
||||||
|
var dnssec_footer = '';
|
||||||
var modal = $("#modal_dnssec_info");
|
var modal = $("#modal_dnssec_info");
|
||||||
|
|
||||||
if (data['status'] == 'error'){
|
if (data['status'] == 'error'){
|
||||||
modal.find('.modal-body p').text(data['msg']);
|
modal.find('.modal-body p').text(data['msg']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dnssec_msg = '';
|
var dnssec_msg = '';
|
||||||
var dnssec = data['dnssec'];
|
var dnssec = data['dnssec'];
|
||||||
|
|
||||||
if (dnssec.length == 0 && parseFloat(PDNS_VERSION) >= 4.1) {
|
if (dnssec.length == 0 && parseFloat(PDNS_VERSION) >= 4.1) {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<h3 class="box-title">History Management</h3>
|
<h3 class="box-title">History Management</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body clearfix">
|
<div class="box-body clearfix">
|
||||||
<button type="button" class="btn btn-flat btn-danger pull-right" data-toggle="modal" data-target="#modal_clear_history">
|
<button type="button" class="btn btn-flat btn-danger pull-right" data-toggle="modal" data-target="#modal_clear_history" {% if current_user.role != 'Administrator' %}disabled{% endif %}>
|
||||||
Clear History <i class="fa fa-trash"></i>
|
Clear History <i class="fa fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<th>First Name</th>
|
<th>First Name</th>
|
||||||
<th>Last Name</th>
|
<th>Last Name</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th>Admin</th>
|
<th>Role</th>
|
||||||
<th>Privileges</th>
|
<th>Privileges</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -49,18 +49,22 @@
|
|||||||
<td>{{ user.lastname }}</td>
|
<td>{{ user.lastname }}</td>
|
||||||
<td>{{ user.email }}</td>
|
<td>{{ user.email }}</td>
|
||||||
<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>
|
||||||
<td width="6%">
|
<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>
|
Revoke <i class="fa fa-lock"></i>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td width="15%">
|
<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>
|
Edit <i class="fa fa-lock"></i>
|
||||||
</button>
|
</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>
|
Delete <i class="fa fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
@ -93,14 +97,6 @@
|
|||||||
"pageLength": 10
|
"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
|
// handle revocation of privileges
|
||||||
$(document.body).on('click', '.button_revoke', function() {
|
$(document.body).on('click', '.button_revoke', function() {
|
||||||
var modal = $("#modal_revoke");
|
var modal = $("#modal_revoke");
|
||||||
@ -129,24 +125,18 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// initialize pretty checkboxes
|
// handle user role changing
|
||||||
$('.admin_toggle').iCheck({
|
$('.user_role').on('change', function() {
|
||||||
checkboxClass : 'icheckbox_square-blue',
|
var role_name = this.value;
|
||||||
increaseArea : '20%' // optional
|
|
||||||
});
|
|
||||||
|
|
||||||
// handle checkbox toggling
|
|
||||||
$(document.body).on('ifToggled', '.admin_toggle', function() {
|
|
||||||
var is_admin = $(this).prop('checked');
|
|
||||||
var username = $(this).prop('id');
|
var username = $(this).prop('id');
|
||||||
postdata = {
|
postdata = {
|
||||||
'action' : 'set_admin',
|
'action' : 'update_user_role',
|
||||||
'data' : {
|
'data' : {
|
||||||
'username' : username,
|
'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>
|
</script>
|
||||||
{% endblock %}
|
{% 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') }}">
|
<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>
|
<span class="help-block with-errors"></span>
|
||||||
</div>
|
</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">
|
<div class="form-group">
|
||||||
<label for="ldap_user_group">User group</label>
|
<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') }}">
|
<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>
|
<li>
|
||||||
Admin group - Your LDAP admin group.
|
Admin group - Your LDAP admin group.
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
Operator group - Your LDAP operator group.
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
User group - Your LDAP user group.
|
User group - Your LDAP user group.
|
||||||
</li>
|
</li>
|
||||||
|
@ -34,23 +34,22 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for setting in settings %}
|
{% for setting in settings %}
|
||||||
<tr class="odd ">
|
<tr class="odd ">
|
||||||
<td>{{ setting.name }}</td>
|
<td>{{ setting }}</td>
|
||||||
{% if setting.value == "True" or setting.value == "False" %}
|
{% if SETTING.get(setting) in [True, False] %}
|
||||||
<td>{{ setting.value }}</td>
|
<td>{{ SETTING.get(setting)|display_setting_state }}</td>
|
||||||
{% else %}
|
|
||||||
<td><input name="value" id="value" value="{{ setting.value }}"></td>
|
|
||||||
{% endif %}
|
|
||||||
<td width="6%">
|
<td width="6%">
|
||||||
{% if setting.value == "True" or setting.value == "False" %}
|
<button type="button" class="btn btn-flat btn-warning setting-toggle-button" id="{{ setting }}">
|
||||||
<button type="button" class="btn btn-flat btn-warning setting-toggle-button" id="{{ setting.name }}">
|
|
||||||
Toggle <i class="fa fa-info"></i>
|
Toggle <i class="fa fa-info"></i>
|
||||||
</button>
|
</button>
|
||||||
{% else %}
|
</td>
|
||||||
<button type="button" class="btn btn-flat btn-warning setting-save-button" id="{{ setting.name }}">
|
{% else %}
|
||||||
|
<td><input name="value" id="value" value="{{ SETTING.get(setting) }}"></td>
|
||||||
|
<td width="6%">
|
||||||
|
<button type="button" class="btn btn-flat btn-warning setting-save-button" id="{{ setting }}">
|
||||||
Save <i class="fa fa-info"></i>
|
Save <i class="fa fa-info"></i>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
|
||||||
</td>
|
</td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -69,7 +68,7 @@
|
|||||||
<script>
|
<script>
|
||||||
// set up history data table
|
// set up history data table
|
||||||
$("#tbl_settings").DataTable({
|
$("#tbl_settings").DataTable({
|
||||||
"paging" : true,
|
"paging" : false,
|
||||||
"lengthChange" : false,
|
"lengthChange" : false,
|
||||||
"searching" : true,
|
"searching" : true,
|
||||||
"ordering" : true,
|
"ordering" : true,
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group has-feedback">
|
<div class="form-group has-feedback">
|
||||||
<label class="control-label" for="pdns_api_key">PDNS API KEY</label>
|
<label class="control-label" for="pdns_api_key">PDNS API KEY</label>
|
||||||
<input type="text" class="form-control" placeholder="PowerDNS API key" name="pdns_api_key" data-error="Please input a valid PowerDNS API key" required value="{{ pdns_api_key }}">
|
<input type="password" class="form-control" placeholder="PowerDNS API key" name="pdns_api_key" data-error="Please input a valid PowerDNS API key" required value="{{ pdns_api_key }}">
|
||||||
<span class="help-block with-errors"></span>
|
<span class="help-block with-errors"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group has-feedback">
|
<div class="form-group has-feedback">
|
||||||
|
@ -108,26 +108,28 @@
|
|||||||
<li class="{{ 'active' if active_page == 'dashboard' else '' }}">
|
<li class="{{ 'active' if active_page == 'dashboard' else '' }}">
|
||||||
<a href="{{ url_for('dashboard') }}"><i class="fa fa-dashboard"></i> Dashboard</a>
|
<a href="{{ url_for('dashboard') }}"><i class="fa fa-dashboard"></i> Dashboard</a>
|
||||||
</li>
|
</li>
|
||||||
{% if current_user.role.name == 'Administrator' %}
|
{% if SETTING.get('allow_user_create_domain') or current_user.role.name in ['Administrator', 'Operator'] %}
|
||||||
<li class="{{ 'active' if active_page == 'new_domain' else '' }}">
|
<li class="{{ 'active' if active_page == 'new_domain' else '' }}">
|
||||||
<a href="{{ url_for('domain_add') }}"><i class="fa fa-plus"></i> New Domain</a>
|
<a href="{{ url_for('domain_add') }}"><i class="fa fa-plus"></i> New Domain</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||||
<li class="header">ADMINISTRATION</li>
|
<li class="header">ADMINISTRATION</li>
|
||||||
<li class="{{ 'active' if active_page == 'admin_console' else '' }}">
|
<li class="{{ 'active' if active_page == 'admin_console' else '' }}">
|
||||||
<a href="{{ url_for('admin') }}"><i class="fa fa-wrench"></i> Admin Console</a>
|
<a href="{{ url_for('admin_pdns') }}"><i class="fa fa-info-circle"></i> PDNS</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>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="{{ 'active' if active_page == 'admin_history' else '' }}">
|
<li class="{{ 'active' if active_page == 'admin_history' else '' }}">
|
||||||
<a href="{{ url_for('admin_history') }}"><i class="fa fa-calendar"></i> History</a>
|
<a href="{{ url_for('admin_history') }}"><i class="fa fa-calendar"></i> History</a>
|
||||||
</li>
|
</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' }}">
|
<li class="{{ 'treeview active' if active_page == 'admin_settings' else 'treeview' }}">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<i class="fa fa-cog"></i> Settings
|
<i class="fa fa-cog"></i> Settings
|
||||||
@ -138,8 +140,10 @@
|
|||||||
<ul class="treeview-menu" {% if active_page == 'admin_settings' %}style="display: block;"{% endif %}>
|
<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_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>
|
<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_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>
|
<li><a href="{{ url_for('admin_setting_authentication') }}"><i class="fa fa-circle-o"></i> Authentication</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<!-- Main content -->
|
<!-- Main content -->
|
||||||
<section class="content">
|
<section class="content">
|
||||||
{% if current_user.role.name == 'Administrator' %}
|
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-3">
|
<div class="col-xs-3">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
@ -69,7 +69,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<a href="{{ url_for('admin') }}">
|
<a href="{{ url_for('admin_pdns') }}">
|
||||||
<div class="small-box bg-green">
|
<div class="small-box bg-green">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3><span style="font-size: 18px">{{ uptime|display_second_to_time }}</span></h3>
|
<h3><span style="font-size: 18px">{{ uptime|display_second_to_time }}</span></h3>
|
||||||
@ -102,17 +102,17 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for history in histories %}
|
{% for history in histories %}
|
||||||
<tr class="odd">
|
<tr class="odd">
|
||||||
<td>{{ history.created_by }}</td>
|
<td>{{ history.created_by }}</td>
|
||||||
<td>{{ history.msg }}</td>
|
<td>{{ history.msg }}</td>
|
||||||
<td>{{ history.created_on }}</td>
|
<td>{{ history.created_on }}</td>
|
||||||
<td width="6%">
|
<td width="6%">
|
||||||
<button type="button" class="btn btn-flat btn-primary history-info-button" value='{{ history.detail|replace("[]","None") }}'>
|
<button type="button" class="btn btn-flat btn-primary history-info-button" value='{{ history.detail|replace("[]","None") }}'>
|
||||||
Info <i class="fa fa-info"></i>
|
Info <i class="fa fa-info"></i>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -136,7 +136,7 @@
|
|||||||
<th>Serial</th>
|
<th>Serial</th>
|
||||||
<th>Master</th>
|
<th>Master</th>
|
||||||
<th>Account</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>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -156,7 +156,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block extrascripts %}
|
{% block extrascripts %}
|
||||||
<script>
|
<script>
|
||||||
PDNS_VERSION = '{{ SETTING.get("pdns_version") }}'
|
PDNS_VERSION = '{{ SETTING.get("pdns_version") }}';
|
||||||
// set up history data table
|
// set up history data table
|
||||||
$("#tbl_history").DataTable({
|
$("#tbl_history").DataTable({
|
||||||
"paging" : false,
|
"paging" : false,
|
||||||
@ -182,7 +182,7 @@
|
|||||||
"ordering" : true,
|
"ordering" : true,
|
||||||
"columnDefs": [
|
"columnDefs": [
|
||||||
{ "orderable": false, "targets": [-1] }
|
{ "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,
|
"processing" : true,
|
||||||
"serverSide" : true,
|
"serverSide" : true,
|
||||||
@ -236,7 +236,7 @@
|
|||||||
modal.modal('show');
|
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() {
|
$(document.body).on("click", ".button_dnssec", function() {
|
||||||
var domain = $(this).prop('id');
|
var domain = $(this).prop('id');
|
||||||
getdnssec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec', domain);
|
getdnssec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec', domain);
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro account(domain) %}
|
{% 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 }}]
|
{% if domain.account_description != "" %}{{ domain.account.description }} {% endif %}[{{ domain.account.name }}]
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro actions(domain) %}
|
{% macro actions(domain) %}
|
||||||
{% if current_user.role.name =='Administrator' %}
|
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
||||||
<td width="25%">
|
<td width="25%">
|
||||||
<button type="button" class="btn btn-flat btn-success button_template" id="{{ domain.name }}">
|
<button type="button" class="btn btn-flat btn-success button_template" id="{{ domain.name }}">
|
||||||
Template <i class="fa fa-clone"></i>
|
Template <i class="fa fa-clone"></i>
|
||||||
|
@ -57,13 +57,13 @@
|
|||||||
{{ record.type }}
|
{{ record.type }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ record.status }}
|
{{ record.status }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ record.ttl }}
|
{{ record.ttl }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ record.data }}
|
{{ record.data }}
|
||||||
</td>
|
</td>
|
||||||
{% if domain.type != 'Slave' %}
|
{% if domain.type != 'Slave' %}
|
||||||
<td width="6%">
|
<td width="6%">
|
||||||
@ -104,7 +104,6 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block extrascripts %}
|
{% block extrascripts %}
|
||||||
<script>
|
<script>
|
||||||
PDNS_VERSION = '{{ SETTING.get("pdns_version") }}'
|
|
||||||
// superglobals
|
// superglobals
|
||||||
window.records_allow_edit = {{ editable_records|tojson }};
|
window.records_allow_edit = {{ editable_records|tojson }};
|
||||||
window.nEditing = null;
|
window.nEditing = null;
|
||||||
@ -361,7 +360,7 @@
|
|||||||
record_data.val(data);
|
record_data.val(data);
|
||||||
modal.modal('hide');
|
modal.modal('hide');
|
||||||
})
|
})
|
||||||
modal.modal('show');
|
modal.modal('show');
|
||||||
} else if (record_type == "SOA") {
|
} else if (record_type == "SOA") {
|
||||||
var modal = $("#modal_custom_record");
|
var modal = $("#modal_custom_record");
|
||||||
if (record_data.val() == "") {
|
if (record_data.val() == "") {
|
||||||
|
@ -174,7 +174,7 @@
|
|||||||
<h3 class="box-title">Domain Deletion</h3>
|
<h3 class="box-title">Domain Deletion</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<p>This function is used to remove a domain from PowerDNS-Admin <b>AND</b> PowerDNS. All records and user privileges which associated to this domain will also be removed. This change cannot be reverted.</p>
|
<p>This function is used to remove a domain from PowerDNS-Admin <b>AND</b> PowerDNS. All records and user privileges associated with this domain will also be removed. This change cannot be reverted.</p>
|
||||||
<button type="button" class="btn btn-flat btn-danger pull-left delete_domain" id="{{ domain.name }}">
|
<button type="button" class="btn btn-flat btn-danger pull-left delete_domain" id="{{ domain.name }}">
|
||||||
<i class="fa fa-trash"></i> DELETE DOMAIN {{ domain.name }}
|
<i class="fa fa-trash"></i> DELETE DOMAIN {{ domain.name }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -20,22 +20,22 @@
|
|||||||
<section class="content">
|
<section class="content">
|
||||||
{% with errors = get_flashed_messages(category_filter=["error"]) %} {% if errors %}
|
{% with errors = get_flashed_messages(category_filter=["error"]) %} {% if errors %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="alert alert-danger alert-dismissible">
|
<div class="alert alert-danger alert-dismissible">
|
||||||
<button type="button" class="close" data-dismiss="alert"
|
<button type="button" class="close" data-dismiss="alert"
|
||||||
aria-hidden="true">×</button>
|
aria-hidden="true">×</button>
|
||||||
<h4>
|
<h4>
|
||||||
<i class="icon fa fa-ban"></i> Error!
|
<i class="icon fa fa-ban"></i> Error!
|
||||||
</h4>
|
</h4>
|
||||||
<div class="alert-message block-message error">
|
<div class="alert-message block-message error">
|
||||||
<a class="close" href="#">x</a>
|
<a class="close" href="#">x</a>
|
||||||
<ul>
|
<ul>
|
||||||
{%- for msg in errors %}
|
{%- for msg in errors %}
|
||||||
<li>{{ msg }}</li> {% endfor -%}
|
<li>{{ msg }}</li> {% endfor -%}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %} {% endwith %}
|
{% endif %} {% endwith %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -45,11 +45,11 @@
|
|||||||
<h3 class="box-title">Templates</h3>
|
<h3 class="box-title">Templates</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<a href="{{ url_for('create_template') }}">
|
<a href="{{ url_for('create_template') }}">
|
||||||
<button type="button" class="btn btn-flat btn-primary pull-left">
|
<button type="button" class="btn btn-flat btn-primary pull-left">
|
||||||
Create Template <i class="fa fa-plus"></i>
|
Create Template <i class="fa fa-plus"></i>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<table id="tbl_template_list" class="table table-bordered table-striped">
|
<table id="tbl_template_list" class="table table-bordered table-striped">
|
||||||
@ -75,15 +75,15 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ url_for('edit_template', template=template.name) }}">
|
<a href="{{ url_for('edit_template', template=template.name) }}">
|
||||||
<button type="button" class="btn btn-flat btn-warning button_edit" id="">
|
<button type="button" class="btn btn-flat btn-warning button_edit" id="btn_edit">
|
||||||
Edit <i class="fa fa-edit"></i>
|
Edit <i class="fa fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('delete_template', template=template.name) }}">
|
<a href="{{ url_for('delete_template', template=template.name) }}">
|
||||||
<button type="button" class="btn btn-flat btn-danger button_delete" id="">
|
<button type="button" class="btn btn-flat btn-danger button_delete" id="btn_delete">
|
||||||
Delete <i class="fa fa-trash"></i>
|
Delete <i class="fa fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -115,12 +115,23 @@
|
|||||||
"lengthMenu": " _MENU_ records"
|
"lengthMenu": " _MENU_ records"
|
||||||
},
|
},
|
||||||
"retrieve" : true,
|
"retrieve" : true,
|
||||||
"columnDefs": [{
|
"columnDefs": [
|
||||||
"targets": [ 7 ],
|
{
|
||||||
"visible": false,
|
type: 'natural',
|
||||||
"searchable": false
|
targets: [0, 4]
|
||||||
}]
|
},
|
||||||
|
{
|
||||||
|
// hidden column so that we can add new records on top
|
||||||
|
// regardless of whatever sorting is done
|
||||||
|
visible: false,
|
||||||
|
targets: [ 7 ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "length-break",
|
||||||
|
targets: [ 4 ]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"orderFixed": [[7, 'asc']]
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle delete button
|
// handle delete button
|
||||||
@ -132,15 +143,19 @@
|
|||||||
var nRow = $(this).parents('tr')[0];
|
var nRow = $(this).parents('tr')[0];
|
||||||
var info = "Are you sure you want to delete " + record + "?";
|
var info = "Are you sure you want to delete " + record + "?";
|
||||||
modal.find('.modal-body p').text(info);
|
modal.find('.modal-body p').text(info);
|
||||||
modal.find('#button_delete_confirm').click(function() {
|
|
||||||
table.row(nRow).remove().draw();
|
|
||||||
modal.modal('hide');
|
|
||||||
})
|
|
||||||
modal.modal('show');
|
modal.modal('show');
|
||||||
|
|
||||||
|
$("#button_delete_confirm").unbind().one('click', function(e) {
|
||||||
|
table.row(nRow).remove().draw();
|
||||||
|
modal.modal('hide');
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#button_delete_cancel").unbind().one('click', function(e) {
|
||||||
|
modal.modal('hide');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
// handle edit button
|
// handle edit button and record click
|
||||||
$(document.body).on("click", ".button_edit, .row_record", function(e) {
|
$(document.body).on("click", ".button_edit{% if quick_edit %}, .row_record{% endif %}", function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if ($(this).is('tr')) {
|
if ($(this).is('tr')) {
|
||||||
var nRow = $(this)[0];
|
var nRow = $(this)[0];
|
||||||
@ -176,7 +191,9 @@
|
|||||||
var template = $(this).prop('id');
|
var template = $(this).prop('id');
|
||||||
var info = "Are you sure you want to apply your changes?";
|
var info = "Are you sure you want to apply your changes?";
|
||||||
modal.find('.modal-body p').text(info);
|
modal.find('.modal-body p').text(info);
|
||||||
modal.find('#button_apply_confirm').click(function() {
|
|
||||||
|
// following unbind("click") is to avoid multiple times execution
|
||||||
|
modal.find('#button_apply_confirm').unbind("click").click(function() {
|
||||||
var data = getTableData(table);
|
var data = getTableData(table);
|
||||||
applyChanges(data, '/template/' + template + '/apply', true);
|
applyChanges(data, '/template/' + template + '/apply', true);
|
||||||
modal.modal('hide');
|
modal.modal('hide');
|
||||||
@ -188,15 +205,19 @@
|
|||||||
// handle add record button
|
// handle add record button
|
||||||
$(document.body).on("click", ".button_add_record", function (e) {
|
$(document.body).on("click", ".button_add_record", function (e) {
|
||||||
if (nNew || nEditing) {
|
if (nNew || nEditing) {
|
||||||
// TODO: replace this alert with modal
|
var modal = $("#modal_error");
|
||||||
alert("Previous record not saved. Please save it before adding more record.")
|
modal.find('.modal-body p').text("Previous record not saved. Please save it before adding more record.");
|
||||||
|
modal.modal('show');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var table = $("#tbl_records").DataTable();
|
// clear search first
|
||||||
|
$("#tbl_records").DataTable().search('').columns().search('').draw();
|
||||||
|
|
||||||
var aiNew = table.row.add(['', 'A', 'Active', 3600, '', '', '', '']).draw();
|
// add new row
|
||||||
var nRow = aiNew.index();
|
var default_type = records_allow_edit[0]
|
||||||
editRow(table, nRow);
|
var nRow = jQuery('#tbl_records').dataTable().fnAddData(['', default_type, 'Active', 3600, '', '', '', '0']);
|
||||||
|
editRow($("#tbl_records").DataTable(), nRow);
|
||||||
|
document.getElementById("edit-row-focus").focus();
|
||||||
nEditing = nRow;
|
nEditing = nRow;
|
||||||
nNew = true;
|
nNew = true;
|
||||||
});
|
});
|
||||||
@ -229,20 +250,50 @@
|
|||||||
$(document.body).on("focus", "#current_edit_record_data", function (e) {
|
$(document.body).on("focus", "#current_edit_record_data", function (e) {
|
||||||
var record_type = $(this).parents("tr").find('#record_type').val();
|
var record_type = $(this).parents("tr").find('#record_type').val();
|
||||||
var record_data = $(this);
|
var record_data = $(this);
|
||||||
if (record_type == "MX") {
|
if (record_type == "CAA") {
|
||||||
|
var modal = $("#modal_custom_record");
|
||||||
|
if (record_data.val() == "") {
|
||||||
|
var form = " <label for=\"caa_flag\">CAA Flag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_flag\" id=\"caa_flag\" placeholder=\"0\"> \
|
||||||
|
<label for=\"caa_tag\">CAA Tag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_tag\" id=\"caa_tag\" placeholder=\"issue\"> \
|
||||||
|
<label for=\"caa_value\">CAA Value</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_value\" id=\"caa_value\" placeholder=\"eg. letsencrypt.org\"> \
|
||||||
|
";
|
||||||
|
} else {
|
||||||
|
var parts = record_data.val().split(" ");
|
||||||
|
var form = " <label for=\"caa_flag\">CAA Flag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_flag\" id=\"caa_flag\" placeholder=\"0\" value=\"" + parts[0] + "\"> \
|
||||||
|
<label for=\"caa_tag\">CAA Tag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_tag\" id=\"caa_tag\" placeholder=\"issue\" value=\"" + parts[1] + "\"> \
|
||||||
|
<label for=\"caa_value\">CAA Value</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_value\" id=\"caa_value\" placeholder=\"eg. letsencrypt.org\" value=\"" + parts[2] + "\"> \
|
||||||
|
";
|
||||||
|
}
|
||||||
|
modal.find('.modal-body p').html(form);
|
||||||
|
modal.find('#button_save').click(function() {
|
||||||
|
caa_flag = modal.find('#caa_flag').val();
|
||||||
|
caa_tag = modal.find('#caa_tag').val();
|
||||||
|
caa_value = modal.find('#caa_value').val();
|
||||||
|
data = caa_flag + " " + caa_tag + " " + '"' + caa_value + '"';
|
||||||
|
record_data.val(data);
|
||||||
|
modal.modal('hide');
|
||||||
|
})
|
||||||
|
modal.modal('show');
|
||||||
|
} else if (record_type == "MX") {
|
||||||
var modal = $("#modal_custom_record");
|
var modal = $("#modal_custom_record");
|
||||||
if (record_data.val() == "") {
|
if (record_data.val() == "") {
|
||||||
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
||||||
<input type=\"text\" class=\"form-control\" name=\"mx_priority\" id=\"mx_priority\" placeholder=\"10\"> \
|
<input type=\"text\" class=\"form-control\" name=\"mx_priority\" id=\"mx_priority\" placeholder=\"eg. 10\"> \
|
||||||
<label for=\"mx_server\">MX Server</label> \
|
<label for=\"mx_server\">MX Server</label> \
|
||||||
<input type=\"text\" class=\"form-control\" name=\"mx_server\" id=\"mx_server\" placeholder=\"postfix.example.com\"> \
|
<input type=\"text\" class=\"form-control\" name=\"mx_server\" id=\"mx_server\" placeholder=\"eg. postfix.example.com\"> \
|
||||||
";
|
";
|
||||||
} else {
|
} else {
|
||||||
var parts = record_data.val().split(" ");
|
var parts = record_data.val().split(" ");
|
||||||
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
||||||
<input type=\"text\" class=\"form-control\" name=\"mx_priority\" id=\"mx_priority\" placeholder=\"10\" value=\"" + parts[0] + "\"> \
|
<input type=\"text\" class=\"form-control\" name=\"mx_priority\" id=\"mx_priority\" placeholder=\"eg. 10\" value=\"" + parts[0] + "\"> \
|
||||||
<label for=\"mx_server\">MX Server</label> \
|
<label for=\"mx_server\">MX Server</label> \
|
||||||
<input type=\"text\" class=\"form-control\" name=\"mx_server\" id=\"mx_server\" placeholder=\"postfix.example.com\" value=\"" + parts[1] + "\"> \
|
<input type=\"text\" class=\"form-control\" name=\"mx_server\" id=\"mx_server\" placeholder=\"eg. postfix.example.com\" value=\"" + parts[1] + "\"> \
|
||||||
";
|
";
|
||||||
}
|
}
|
||||||
modal.find('.modal-body p').html(form);
|
modal.find('.modal-body p').html(form);
|
||||||
@ -360,7 +411,7 @@
|
|||||||
<p></p>
|
<p></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-flat btn-default pull-left"
|
<button type="button" class="btn btn-flat btn-default pull-left" id="button_delete_cancel"
|
||||||
data-dismiss="modal">Close</button>
|
data-dismiss="modal">Close</button>
|
||||||
<button type="button" class="btn btn-flat btn-danger" id="button_delete_confirm">Delete</button>
|
<button type="button" class="btn btn-flat btn-danger" id="button_delete_confirm">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -161,8 +161,7 @@
|
|||||||
// 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 username = $(this).prop('id');
|
var postdata = {
|
||||||
postdata = {
|
|
||||||
'action' : 'enable_otp',
|
'action' : 'enable_otp',
|
||||||
'data' : {
|
'data' : {
|
||||||
'enable_otp' : enable_otp
|
'enable_otp' : enable_otp
|
||||||
|
180
app/views.py
180
app/views.py
@ -1,5 +1,4 @@
|
|||||||
import base64
|
import base64
|
||||||
import json
|
|
||||||
import logging as logger
|
import logging as logger
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
@ -10,22 +9,19 @@ from functools import wraps
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
|
|
||||||
import jinja2
|
|
||||||
import qrcode as qrc
|
import qrcode as qrc
|
||||||
import qrcode.image.svg as qrc_svg
|
import qrcode.image.svg as qrc_svg
|
||||||
from flask import g, request, make_response, jsonify, render_template, session, redirect, url_for, send_from_directory, abort, flash
|
from flask import g, request, make_response, jsonify, render_template, session, redirect, url_for, send_from_directory, abort, flash
|
||||||
from flask_login import login_user, logout_user, current_user, login_required
|
from flask_login import login_user, logout_user, current_user, login_required
|
||||||
from werkzeug import secure_filename
|
from werkzeug import secure_filename
|
||||||
from werkzeug.security import gen_salt
|
|
||||||
|
|
||||||
from .models import User, Account, Domain, Record, Role, Server, History, Anonymous, Setting, DomainSetting, DomainTemplate, DomainTemplateRecord
|
from .models import User, Account, Domain, Record, Role, Server, History, Anonymous, Setting, DomainSetting, DomainTemplate, DomainTemplateRecord
|
||||||
from app import app, login_manager
|
from app import app, login_manager
|
||||||
from app.lib import utils
|
from app.lib import utils
|
||||||
from app.oauth import github_oauth, google_oauth
|
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, can_create_domain
|
||||||
|
|
||||||
if app.config['SAML_ENABLED']:
|
if app.config['SAML_ENABLED']:
|
||||||
from onelogin.saml2.auth import OneLogin_Saml2_Auth
|
|
||||||
from onelogin.saml2.utils import OneLogin_Saml2_Utils
|
from onelogin.saml2.utils import OneLogin_Saml2_Utils
|
||||||
|
|
||||||
google = None
|
google = None
|
||||||
@ -38,6 +34,7 @@ app.jinja_env.filters['display_record_name'] = utils.display_record_name
|
|||||||
app.jinja_env.filters['display_master_name'] = utils.display_master_name
|
app.jinja_env.filters['display_master_name'] = utils.display_master_name
|
||||||
app.jinja_env.filters['display_second_to_time'] = utils.display_time
|
app.jinja_env.filters['display_second_to_time'] = utils.display_time
|
||||||
app.jinja_env.filters['email_to_gravatar_url'] = utils.email_to_gravatar_url
|
app.jinja_env.filters['email_to_gravatar_url'] = utils.email_to_gravatar_url
|
||||||
|
app.jinja_env.filters['display_setting_state'] = utils.display_setting_state
|
||||||
|
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
@ -68,7 +65,7 @@ def before_request():
|
|||||||
|
|
||||||
# check site maintenance mode
|
# check site maintenance mode
|
||||||
maintenance = Setting().get('maintenance')
|
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')
|
return render_template('maintenance.html')
|
||||||
|
|
||||||
|
|
||||||
@ -284,7 +281,6 @@ def saml_authorized():
|
|||||||
@app.route('/login', methods=['GET', 'POST'])
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
@login_manager.unauthorized_handler
|
@login_manager.unauthorized_handler
|
||||||
def login():
|
def login():
|
||||||
LOGIN_TITLE = app.config['LOGIN_TITLE'] if 'LOGIN_TITLE' in app.config.keys() else ''
|
|
||||||
SAML_ENABLED = app.config.get('SAML_ENABLED')
|
SAML_ENABLED = app.config.get('SAML_ENABLED')
|
||||||
|
|
||||||
if g.user is not None and current_user.is_authenticated:
|
if g.user is not None and current_user.is_authenticated:
|
||||||
@ -454,7 +450,7 @@ def dashboard():
|
|||||||
BG_DOMAIN_UPDATE = Setting().get('bg_domain_updates')
|
BG_DOMAIN_UPDATE = Setting().get('bg_domain_updates')
|
||||||
if not BG_DOMAIN_UPDATE:
|
if not BG_DOMAIN_UPDATE:
|
||||||
logging.debug('Update domains in foreground')
|
logging.debug('Update domains in foreground')
|
||||||
d = Domain().update()
|
Domain().update()
|
||||||
else:
|
else:
|
||||||
logging.debug('Update domains in background')
|
logging.debug('Update domains in background')
|
||||||
|
|
||||||
@ -476,7 +472,7 @@ def dashboard():
|
|||||||
@app.route('/dashboard-domains', methods=['GET'])
|
@app.route('/dashboard-domains', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard_domains():
|
def dashboard_domains():
|
||||||
if current_user.role.name == 'Administrator':
|
if current_user.role.name in ['Administrator', 'Operator']:
|
||||||
domains = Domain.query
|
domains = Domain.query
|
||||||
else:
|
else:
|
||||||
domains = User(id=current_user.id).get_domain_query()
|
domains = User(id=current_user.id).get_domain_query()
|
||||||
@ -508,7 +504,7 @@ def dashboard_domains():
|
|||||||
start = "" if search.startswith("^") else "%"
|
start = "" if search.startswith("^") else "%"
|
||||||
end = "" if search.endswith("$") 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) |
|
domains = domains.outerjoin(Account).filter(Domain.name.ilike(start + search.strip("^$") + end) |
|
||||||
Account.name.ilike(start + search.strip("^$") + end) |
|
Account.name.ilike(start + search.strip("^$") + end) |
|
||||||
Account.description.ilike(start + search.strip("^$") + end))
|
Account.description.ilike(start + search.strip("^$") + end))
|
||||||
@ -572,7 +568,7 @@ def domain(domain_name):
|
|||||||
# can not get any record, API server might be down
|
# can not get any record, API server might be down
|
||||||
return redirect(url_for('error', code=500))
|
return redirect(url_for('error', code=500))
|
||||||
|
|
||||||
quick_edit = Setting().get('allow_quick_edit')
|
quick_edit = Setting().get('record_quick_edit')
|
||||||
records_allow_to_edit = Setting().get_records_allow_to_edit()
|
records_allow_to_edit = Setting().get_records_allow_to_edit()
|
||||||
forward_records_allow_to_edit = Setting().get_forward_records_allow_to_edit()
|
forward_records_allow_to_edit = Setting().get_forward_records_allow_to_edit()
|
||||||
reverse_records_allow_to_edit = Setting().get_reverse_records_allow_to_edit()
|
reverse_records_allow_to_edit = Setting().get_reverse_records_allow_to_edit()
|
||||||
@ -580,7 +576,7 @@ def domain(domain_name):
|
|||||||
|
|
||||||
if StrictVersion(Setting().get('pdns_version')) >= StrictVersion('4.0.0'):
|
if StrictVersion(Setting().get('pdns_version')) >= StrictVersion('4.0.0'):
|
||||||
for jr in jrecords:
|
for jr in jrecords:
|
||||||
if jr['type'] in Setting().get_records_allow_to_edit():
|
if jr['type'] in records_allow_to_edit:
|
||||||
for subrecord in jr['records']:
|
for subrecord in jr['records']:
|
||||||
record = Record(name=jr['name'], type=jr['type'], status='Disabled' if subrecord['disabled'] else 'Active', ttl=jr['ttl'], data=subrecord['content'])
|
record = Record(name=jr['name'], type=jr['type'], status='Disabled' if subrecord['disabled'] else 'Active', ttl=jr['ttl'], data=subrecord['content'])
|
||||||
records.append(record)
|
records.append(record)
|
||||||
@ -591,7 +587,7 @@ def domain(domain_name):
|
|||||||
return render_template('domain.html', domain=domain, records=records, editable_records=editable_records, quick_edit=quick_edit)
|
return render_template('domain.html', domain=domain, records=records, editable_records=editable_records, quick_edit=quick_edit)
|
||||||
else:
|
else:
|
||||||
for jr in jrecords:
|
for jr in jrecords:
|
||||||
if jr['type'] in Setting().get_records_allow_to_edit():
|
if jr['type'] in records_allow_to_edit:
|
||||||
record = Record(name=jr['name'], type=jr['type'], status='Disabled' if jr['disabled'] else 'Active', ttl=jr['ttl'], data=jr['content'])
|
record = Record(name=jr['name'], type=jr['type'], status='Disabled' if jr['disabled'] else 'Active', ttl=jr['ttl'], data=jr['content'])
|
||||||
records.append(record)
|
records.append(record)
|
||||||
if not re.search('ip6\.arpa|in-addr\.arpa$', domain_name):
|
if not re.search('ip6\.arpa|in-addr\.arpa$', domain_name):
|
||||||
@ -603,7 +599,7 @@ def domain(domain_name):
|
|||||||
|
|
||||||
@app.route('/admin/domain/add', methods=['GET', 'POST'])
|
@app.route('/admin/domain/add', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@can_create_domain
|
||||||
def domain_add():
|
def domain_add():
|
||||||
templates = DomainTemplate.query.all()
|
templates = DomainTemplate.query.all()
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@ -632,6 +628,11 @@ def domain_add():
|
|||||||
if result['status'] == 'ok':
|
if result['status'] == 'ok':
|
||||||
history = History(msg='Add domain {0}'.format(domain_name), detail=str({'domain_type': domain_type, 'domain_master_ips': domain_master_ips, 'account_id': account_id}), created_by=current_user.username)
|
history = History(msg='Add domain {0}'.format(domain_name), detail=str({'domain_type': domain_type, 'domain_master_ips': domain_master_ips, 'account_id': account_id}), created_by=current_user.username)
|
||||||
history.add()
|
history.add()
|
||||||
|
|
||||||
|
# grant user access to the domain
|
||||||
|
Domain(name=domain_name).grant_privileges([current_user.username])
|
||||||
|
|
||||||
|
# apply template if needed
|
||||||
if domain_template != '0':
|
if domain_template != '0':
|
||||||
template = DomainTemplate.query.filter(DomainTemplate.id == domain_template).first()
|
template = DomainTemplate.query.filter(DomainTemplate.id == domain_template).first()
|
||||||
template_records = DomainTemplateRecord.query.filter(DomainTemplateRecord.template_id == domain_template).all()
|
template_records = DomainTemplateRecord.query.filter(DomainTemplateRecord.template_id == domain_template).all()
|
||||||
@ -651,7 +652,7 @@ def domain_add():
|
|||||||
else:
|
else:
|
||||||
return render_template('errors/400.html', msg=result['msg']), 400
|
return render_template('errors/400.html', msg=result['msg']), 400
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return redirect(url_for('error', code=500))
|
return redirect(url_for('error', code=500))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -661,7 +662,7 @@ def domain_add():
|
|||||||
|
|
||||||
@app.route('/admin/domain/<path:domain_name>/delete', methods=['GET'])
|
@app.route('/admin/domain/<path:domain_name>/delete', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def domain_delete(domain_name):
|
def domain_delete(domain_name):
|
||||||
d = Domain()
|
d = Domain()
|
||||||
result = d.delete(domain_name)
|
result = d.delete(domain_name)
|
||||||
@ -677,7 +678,7 @@ def domain_delete(domain_name):
|
|||||||
|
|
||||||
@app.route('/admin/domain/<path:domain_name>/manage', methods=['GET', 'POST'])
|
@app.route('/admin/domain/<path:domain_name>/manage', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def domain_management(domain_name):
|
def domain_management(domain_name):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||||
@ -697,12 +698,9 @@ def domain_management(domain_name):
|
|||||||
# username in right column
|
# username in right column
|
||||||
new_user_list = request.form.getlist('domain_multi_user[]')
|
new_user_list = request.form.getlist('domain_multi_user[]')
|
||||||
|
|
||||||
# get list of user ids to compare
|
|
||||||
d = Domain(name=domain_name)
|
|
||||||
domain_user_ids = d.get_user()
|
|
||||||
|
|
||||||
# grant/revoke user privielges
|
# grant/revoke user privielges
|
||||||
d.grant_privielges(new_user_list)
|
d = Domain(name=domain_name)
|
||||||
|
d.grant_privileges(new_user_list)
|
||||||
|
|
||||||
history = History(msg='Change domain {0} access control'.format(domain_name), detail=str({'user_has_access': new_user_list}), created_by=current_user.username)
|
history = History(msg='Change domain {0} access control'.format(domain_name), detail=str({'user_has_access': new_user_list}), created_by=current_user.username)
|
||||||
history.add()
|
history.add()
|
||||||
@ -712,13 +710,13 @@ def domain_management(domain_name):
|
|||||||
|
|
||||||
@app.route('/admin/domain/<path:domain_name>/change_soa_setting', methods=['POST'])
|
@app.route('/admin/domain/<path:domain_name>/change_soa_setting', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def domain_change_soa_edit_api(domain_name):
|
def domain_change_soa_edit_api(domain_name):
|
||||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||||
if not domain:
|
if not domain:
|
||||||
return redirect(url_for('error', code=404))
|
return redirect(url_for('error', code=404))
|
||||||
new_setting = request.form.get('soa_edit_api')
|
new_setting = request.form.get('soa_edit_api')
|
||||||
if new_setting == None:
|
if new_setting is None:
|
||||||
return redirect(url_for('error', code=500))
|
return redirect(url_for('error', code=500))
|
||||||
if new_setting == '0':
|
if new_setting == '0':
|
||||||
return redirect(url_for('domain_management', domain_name=domain_name))
|
return redirect(url_for('domain_management', domain_name=domain_name))
|
||||||
@ -738,7 +736,7 @@ def domain_change_soa_edit_api(domain_name):
|
|||||||
|
|
||||||
@app.route('/admin/domain/<path:domain_name>/change_account', methods=['POST'])
|
@app.route('/admin/domain/<path:domain_name>/change_account', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def domain_change_account(domain_name):
|
def domain_change_account(domain_name):
|
||||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||||
if not domain:
|
if not domain:
|
||||||
@ -787,7 +785,7 @@ def record_apply(domain_name):
|
|||||||
else:
|
else:
|
||||||
return make_response(jsonify( result ), 400)
|
return make_response(jsonify( result ), 400)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify( {'status': 'error', 'msg': 'Error when applying new changes'} ), 500)
|
return make_response(jsonify( {'status': 'error', 'msg': 'Error when applying new changes'} ), 500)
|
||||||
|
|
||||||
|
|
||||||
@ -810,13 +808,13 @@ def record_update(domain_name):
|
|||||||
else:
|
else:
|
||||||
return make_response(jsonify( {'status': 'error', 'msg': result['msg']} ), 500)
|
return make_response(jsonify( {'status': 'error', 'msg': result['msg']} ), 500)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify( {'status': 'error', 'msg': 'Error when applying new changes'} ), 500)
|
return make_response(jsonify( {'status': 'error', 'msg': 'Error when applying new changes'} ), 500)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/domain/<path:domain_name>/record/<path:record_name>/type/<path:record_type>/delete', methods=['GET'])
|
@app.route('/domain/<path:domain_name>/record/<path:record_name>/type/<path:record_type>/delete', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def record_delete(domain_name, record_name, record_type):
|
def record_delete(domain_name, record_name, record_type):
|
||||||
try:
|
try:
|
||||||
r = Record(name=record_name, type=record_type)
|
r = Record(name=record_name, type=record_type)
|
||||||
@ -824,7 +822,7 @@ def record_delete(domain_name, record_name, record_type):
|
|||||||
if result['status'] == 'error':
|
if result['status'] == 'error':
|
||||||
print(result['msg'])
|
print(result['msg'])
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return redirect(url_for('error', code=500)), 500
|
return redirect(url_for('error', code=500)), 500
|
||||||
return redirect(url_for('domain', domain_name=domain_name))
|
return redirect(url_for('domain', domain_name=domain_name))
|
||||||
|
|
||||||
@ -866,14 +864,14 @@ def domain_dnssec_disable(domain_name):
|
|||||||
dnssec = domain.get_domain_dnssec(domain_name)
|
dnssec = domain.get_domain_dnssec(domain_name)
|
||||||
|
|
||||||
for key in dnssec['dnssec']:
|
for key in dnssec['dnssec']:
|
||||||
response = domain.delete_dnssec_key(domain_name,key['id']);
|
domain.delete_dnssec_key(domain_name,key['id']);
|
||||||
|
|
||||||
return make_response(jsonify( { 'status': 'ok', 'msg': 'DNSSEC removed.' } ))
|
return make_response(jsonify( { 'status': 'ok', 'msg': 'DNSSEC removed.' } ))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/domain/<path:domain_name>/managesetting', methods=['GET', 'POST'])
|
@app.route('/domain/<path:domain_name>/managesetting', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_setdomainsetting(domain_name):
|
def admin_setdomainsetting(domain_name):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
#
|
#
|
||||||
@ -907,14 +905,14 @@ def admin_setdomainsetting(domain_name):
|
|||||||
else:
|
else:
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/templates', methods=['GET', 'POST'])
|
@app.route('/templates', methods=['GET', 'POST'])
|
||||||
@app.route('/templates/list', methods=['GET', 'POST'])
|
@app.route('/templates/list', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def templates():
|
def templates():
|
||||||
templates = DomainTemplate.query.all()
|
templates = DomainTemplate.query.all()
|
||||||
return render_template('template.html', templates=templates)
|
return render_template('template.html', templates=templates)
|
||||||
@ -922,7 +920,7 @@ def templates():
|
|||||||
|
|
||||||
@app.route('/template/create', methods=['GET', 'POST'])
|
@app.route('/template/create', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def create_template():
|
def create_template():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return render_template('template_add.html')
|
return render_template('template_add.html')
|
||||||
@ -938,6 +936,7 @@ def create_template():
|
|||||||
if DomainTemplate.query.filter(DomainTemplate.name == name).first():
|
if DomainTemplate.query.filter(DomainTemplate.name == name).first():
|
||||||
flash("A template with the name {0} already exists!".format(name), 'error')
|
flash("A template with the name {0} already exists!".format(name), 'error')
|
||||||
return redirect(url_for('create_template'))
|
return redirect(url_for('create_template'))
|
||||||
|
|
||||||
t = DomainTemplate(name=name, description=description)
|
t = DomainTemplate(name=name, description=description)
|
||||||
result = t.create()
|
result = t.create()
|
||||||
if result['status'] == 'ok':
|
if result['status'] == 'ok':
|
||||||
@ -948,14 +947,13 @@ def create_template():
|
|||||||
flash(result['msg'], 'error')
|
flash(result['msg'], 'error')
|
||||||
return redirect(url_for('create_template'))
|
return redirect(url_for('create_template'))
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return redirect(url_for('error', code=500))
|
return redirect(url_for('error', code=500))
|
||||||
return redirect(url_for('templates'))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/template/createfromzone', methods=['POST'])
|
@app.route('/template/createfromzone', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def create_template_from_zone():
|
def create_template_from_zone():
|
||||||
try:
|
try:
|
||||||
jdata = request.json
|
jdata = request.json
|
||||||
@ -1003,33 +1001,35 @@ def create_template_from_zone():
|
|||||||
if result_records['status'] == 'ok':
|
if result_records['status'] == 'ok':
|
||||||
return make_response(jsonify({'status': 'ok', 'msg': result['msg']}), 200)
|
return make_response(jsonify({'status': 'ok', 'msg': result['msg']}), 200)
|
||||||
else:
|
else:
|
||||||
result = t.delete_template()
|
t.delete_template()
|
||||||
return make_response(jsonify({'status': 'error', 'msg': result_records['msg']}), 500)
|
return make_response(jsonify({'status': 'error', 'msg': result_records['msg']}), 500)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return make_response(jsonify({'status': 'error', 'msg': result['msg']}), 500)
|
return make_response(jsonify({'status': 'error', 'msg': result['msg']}), 500)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify({'status': 'error', 'msg': 'Error when applying new changes'}), 500)
|
return make_response(jsonify({'status': 'error', 'msg': 'Error when applying new changes'}), 500)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/template/<path:template>/edit', methods=['GET'])
|
@app.route('/template/<path:template>/edit', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def edit_template(template):
|
def edit_template(template):
|
||||||
try:
|
try:
|
||||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||||
records_allow_to_edit = Setting().get_records_allow_to_edit()
|
records_allow_to_edit = Setting().get_records_allow_to_edit()
|
||||||
|
quick_edit = Setting().get('record_quick_edit')
|
||||||
if t is not None:
|
if t is not None:
|
||||||
records = []
|
records = []
|
||||||
for jr in t.records:
|
for jr in t.records:
|
||||||
if jr.type in records_allow_to_edit:
|
if jr.type in records_allow_to_edit:
|
||||||
record = DomainTemplateRecord(name=jr.name, type=jr.type, status='Disabled' if jr.status else 'Active', ttl=jr.ttl, data=jr.data)
|
record = DomainTemplateRecord(name=jr.name, type=jr.type, status='Disabled' if jr.status else 'Active', ttl=jr.ttl, data=jr.data)
|
||||||
records.append(record)
|
records.append(record)
|
||||||
|
|
||||||
return render_template('template_edit.html', template=t.name, records=records, editable_records=records_allow_to_edit)
|
return render_template('template_edit.html', template=t.name, records=records, editable_records=records_allow_to_edit, quick_edit=quick_edit)
|
||||||
except:
|
except Exception as e:
|
||||||
logging.error(traceback.print_exc())
|
logging.error('Cannot open domain template page. DETAIL: {0}'.format(e))
|
||||||
|
logging.debug(traceback.format_exc())
|
||||||
return redirect(url_for('error', code=500))
|
return redirect(url_for('error', code=500))
|
||||||
return redirect(url_for('templates'))
|
return redirect(url_for('templates'))
|
||||||
|
|
||||||
@ -1060,13 +1060,13 @@ def apply_records(template):
|
|||||||
else:
|
else:
|
||||||
return make_response(jsonify(result), 400)
|
return make_response(jsonify(result), 400)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify({'status': 'error', 'msg': 'Error when applying new changes'}), 500)
|
return make_response(jsonify({'status': 'error', 'msg': 'Error when applying new changes'}), 500)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/template/<path:template>/delete', methods=['GET'])
|
@app.route('/template/<path:template>/delete', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def delete_template(template):
|
def delete_template(template):
|
||||||
try:
|
try:
|
||||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||||
@ -1080,15 +1080,15 @@ def delete_template(template):
|
|||||||
flash(result['msg'], 'error')
|
flash(result['msg'], 'error')
|
||||||
return redirect(url_for('templates'))
|
return redirect(url_for('templates'))
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return redirect(url_for('error', code=500))
|
return redirect(url_for('error', code=500))
|
||||||
return redirect(url_for('templates'))
|
return redirect(url_for('templates'))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin', methods=['GET', 'POST'])
|
@app.route('/admin/pdns', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin():
|
def admin_pdns():
|
||||||
if not Setting().get('pdns_api_url') or not Setting().get('pdns_api_key') or not Setting().get('pdns_version'):
|
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'))
|
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/<user_username>', methods=['GET', 'POST'])
|
||||||
@app.route('/admin/user/edit', methods=['GET', 'POST'])
|
@app.route('/admin/user/edit', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_edituser(user_username=None):
|
def admin_edituser(user_username=None):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
if not user_username:
|
if not user_username:
|
||||||
@ -1150,11 +1150,12 @@ def admin_edituser(user_username=None):
|
|||||||
|
|
||||||
@app.route('/admin/manageuser', methods=['GET', 'POST'])
|
@app.route('/admin/manageuser', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_manageuser():
|
def admin_manageuser():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
|
roles = Role.query.all()
|
||||||
users = User.query.order_by(User.username).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':
|
if request.method == 'POST':
|
||||||
#
|
#
|
||||||
@ -1197,30 +1198,42 @@ def admin_manageuser():
|
|||||||
else:
|
else:
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Cannot revoke user privilege.' } ), 500)
|
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']
|
username = data['username']
|
||||||
|
role_name = data['role_name']
|
||||||
|
|
||||||
if username == current_user.username:
|
if username == current_user.username:
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'You cannot change you own admin rights.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'You cannot change you own roles.' } ), 400)
|
||||||
is_admin = data['is_admin']
|
|
||||||
|
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)
|
user = User(username=username)
|
||||||
result = user.set_admin(is_admin)
|
result = user.set_role(role_name)
|
||||||
if result:
|
if result['status']:
|
||||||
history = History(msg='Change user role of {0}'.format(username), created_by=current_user.username)
|
history = History(msg='Change user role of {0} to {1}'.format(username, role_name), created_by=current_user.username)
|
||||||
history.add()
|
history.add()
|
||||||
return make_response(jsonify( { 'status': 'ok', 'msg': 'Changed user role successfully.' } ), 200)
|
return make_response(jsonify( { 'status': 'ok', 'msg': 'Changed user role successfully.' } ), 200)
|
||||||
else:
|
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:
|
else:
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/account/edit/<account_name>', methods=['GET', 'POST'])
|
@app.route('/admin/account/edit/<account_name>', methods=['GET', 'POST'])
|
||||||
@app.route('/admin/account/edit', methods=['GET', 'POST'])
|
@app.route('/admin/account/edit', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_editaccount(account_name=None):
|
def admin_editaccount(account_name=None):
|
||||||
users = User.query.all()
|
users = User.query.all()
|
||||||
|
|
||||||
@ -1274,7 +1287,7 @@ def admin_editaccount(account_name=None):
|
|||||||
|
|
||||||
@app.route('/admin/manageaccount', methods=['GET', 'POST'])
|
@app.route('/admin/manageaccount', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_manageaccount():
|
def admin_manageaccount():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
accounts = Account.query.order_by(Account.name).all()
|
accounts = Account.query.order_by(Account.name).all()
|
||||||
@ -1302,21 +1315,23 @@ def admin_manageaccount():
|
|||||||
else:
|
else:
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.print_exc())
|
logging.error(traceback.format_exc())
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/history', methods=['GET', 'POST'])
|
@app.route('/admin/history', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_history():
|
def admin_history():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
if current_user.role != 'Administrator':
|
||||||
|
return make_response(jsonify( { 'status': 'error', 'msg': 'You do not have permission to remove history.' } ), 401)
|
||||||
|
|
||||||
h = History()
|
h = History()
|
||||||
result = h.remove_all()
|
result = h.remove_all()
|
||||||
if result:
|
if result:
|
||||||
history = History(msg='Remove all histories', created_by=current_user.username)
|
history = History(msg='Remove all histories', created_by=current_user.username)
|
||||||
history.add()
|
history.add()
|
||||||
|
|
||||||
return make_response(jsonify( { 'status': 'ok', 'msg': 'Changed user role successfully.' } ), 200)
|
return make_response(jsonify( { 'status': 'ok', 'msg': 'Changed user role successfully.' } ), 200)
|
||||||
else:
|
else:
|
||||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Can not remove histories.' } ), 500)
|
return make_response(jsonify( { 'status': 'error', 'msg': 'Can not remove histories.' } ), 500)
|
||||||
@ -1328,16 +1343,29 @@ def admin_history():
|
|||||||
|
|
||||||
@app.route('/admin/setting/basic', methods=['GET'])
|
@app.route('/admin/setting/basic', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_setting_basic():
|
def admin_setting_basic():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
settings = Setting.query.filter(Setting.view=='basic').all()
|
settings = ['maintenance',
|
||||||
|
'fullscreen_layout',
|
||||||
|
'record_helper',
|
||||||
|
'login_ldap_first',
|
||||||
|
'default_record_table_size',
|
||||||
|
'default_domain_table_size',
|
||||||
|
'auto_ptr',
|
||||||
|
'record_quick_edit',
|
||||||
|
'pretty_ipv6_ptr',
|
||||||
|
'dnssec_admins_only',
|
||||||
|
'allow_user_create_domain',
|
||||||
|
'bg_domain_updates',
|
||||||
|
'site_name']
|
||||||
|
|
||||||
return render_template('admin_setting_basic.html', settings=settings)
|
return render_template('admin_setting_basic.html', settings=settings)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/setting/basic/<path:setting>/edit', methods=['POST'])
|
@app.route('/admin/setting/basic/<path:setting>/edit', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_setting_basic_edit(setting):
|
def admin_setting_basic_edit(setting):
|
||||||
jdata = request.json
|
jdata = request.json
|
||||||
new_value = jdata['value']
|
new_value = jdata['value']
|
||||||
@ -1351,7 +1379,7 @@ def admin_setting_basic_edit(setting):
|
|||||||
|
|
||||||
@app.route('/admin/setting/basic/<path:setting>/toggle', methods=['POST'])
|
@app.route('/admin/setting/basic/<path:setting>/toggle', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_setting_basic_toggle(setting):
|
def admin_setting_basic_toggle(setting):
|
||||||
result = Setting().toggle(setting)
|
result = Setting().toggle(setting)
|
||||||
if (result):
|
if (result):
|
||||||
@ -1383,11 +1411,14 @@ def admin_setting_pdns():
|
|||||||
|
|
||||||
@app.route('/admin/setting/dns-records', methods=['GET', 'POST'])
|
@app.route('/admin/setting/dns-records', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_role_required
|
@operator_role_required
|
||||||
def admin_setting_records():
|
def admin_setting_records():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
f_records = literal_eval(Setting().get('forward_records_allow_edit'))
|
_fr = Setting().get('forward_records_allow_edit')
|
||||||
r_records = literal_eval(Setting().get('reverse_records_allow_edit'))
|
_rr = Setting().get('reverse_records_allow_edit')
|
||||||
|
f_records = literal_eval(_fr) if isinstance(_fr, str) else _fr
|
||||||
|
r_records = literal_eval(_rr) if isinstance(_rr, str) else _rr
|
||||||
|
|
||||||
return render_template('admin_setting_records.html', f_records=f_records, r_records=r_records)
|
return render_template('admin_setting_records.html', f_records=f_records, r_records=r_records)
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
fr = {}
|
fr = {}
|
||||||
@ -1438,6 +1469,7 @@ def admin_setting_authentication():
|
|||||||
Setting().set('ldap_filter_username', request.form.get('ldap_filter_username'))
|
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_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_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'))
|
Setting().set('ldap_user_group', request.form.get('ldap_user_group'))
|
||||||
result = {'status': True, 'msg': 'Saved successfully'}
|
result = {'status': True, 'msg': 'Saved successfully'}
|
||||||
elif conf_type == 'google':
|
elif conf_type == 'google':
|
||||||
|
@ -41,6 +41,11 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "===> Update PDNS API connection info"
|
echo "===> Update PDNS API connection info"
|
||||||
|
# initial setting if not available in the DB
|
||||||
|
mysql -h${PDA_DB_HOST} -u${PDA_DB_USER} -p${PDA_DB_PASSWORD} ${PDA_DB_NAME} -e "INSERT INTO setting (name, value) SELECT * FROM (SELECT 'pdns_api_url', 'http://${PDNS_HOST}:8081') AS tmp WHERE NOT EXISTS (SELECT name FROM setting WHERE name = 'pdns_api_url') LIMIT 1;"
|
||||||
|
mysql -h${PDA_DB_HOST} -u${PDA_DB_USER} -p${PDA_DB_PASSWORD} ${PDA_DB_NAME} -e "INSERT INTO setting (name, value) SELECT * FROM (SELECT 'pdns_api_key', '${PDNS_API_KEY}') AS tmp WHERE NOT EXISTS (SELECT name FROM setting WHERE name = 'pdns_api_key') LIMIT 1;"
|
||||||
|
|
||||||
|
# update pdns api setting if .env is changed.
|
||||||
mysql -h${PDA_DB_HOST} -u${PDA_DB_USER} -p${PDA_DB_PASSWORD} ${PDA_DB_NAME} -e "UPDATE setting SET value='http://${PDNS_HOST}:8081' WHERE name='pdns_api_url';"
|
mysql -h${PDA_DB_HOST} -u${PDA_DB_USER} -p${PDA_DB_PASSWORD} ${PDA_DB_NAME} -e "UPDATE setting SET value='http://${PDNS_HOST}:8081' WHERE name='pdns_api_url';"
|
||||||
mysql -h${PDA_DB_HOST} -u${PDA_DB_USER} -p${PDA_DB_PASSWORD} ${PDA_DB_NAME} -e "UPDATE setting SET value='${PDNS_API_KEY}' WHERE name='pdns_api_key';"
|
mysql -h${PDA_DB_HOST} -u${PDA_DB_USER} -p${PDA_DB_PASSWORD} ${PDA_DB_NAME} -e "UPDATE setting SET value='${PDNS_API_KEY}' WHERE name='pdns_api_key';"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from app import app, db
|
from app import db
|
||||||
from app.models import Role, Setting, DomainTemplate
|
from app.models import Role, DomainTemplate
|
||||||
|
|
||||||
admin_role = Role(name='Administrator', description='Administrator')
|
admin_role = Role(name='Administrator', description='Administrator')
|
||||||
user_role = Role(name='User', description='User')
|
user_role = Role(name='User', description='User')
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
"""Remove all setting in the DB
|
||||||
|
|
||||||
|
Revision ID: 31a4ed468b18
|
||||||
|
Revises: 4a666113c7bb
|
||||||
|
Create Date: 2018-08-21 17:12:30.058782
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '31a4ed468b18'
|
||||||
|
down_revision = '4a666113c7bb'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# delete all settings from "setting" table.
|
||||||
|
# PDA should work without initial settings in the DB
|
||||||
|
# Once user change the settings from UI, they will be
|
||||||
|
# written to the DB.
|
||||||
|
op.execute("DELETE FROM setting")
|
||||||
|
|
||||||
|
# drop view column since we don't need it
|
||||||
|
op.drop_column('setting', 'view')
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.add_column('setting', sa.Column('view', sa.String(length=64), nullable=True))
|
61
migrations/versions/4a666113c7bb_add_operator_role.py
Normal file
61
migrations/versions/4a666113c7bb_add_operator_role.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
"""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 new settings
|
||||||
|
op.bulk_insert(setting_table,
|
||||||
|
[
|
||||||
|
{'id': 44, 'name': 'ldap_operator_group', 'value': '', 'view': 'authentication'},
|
||||||
|
{'id': 45, 'name': 'allow_user_create_domain', 'value': 'False', 'view': 'basic'},
|
||||||
|
{'id': 46, 'name': 'record_quick_edit', 'value': 'True', 'view': 'basic'},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
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 settings
|
||||||
|
op.execute("DELETE FROM setting WHERE name = 'ldap_operator_group'")
|
||||||
|
op.execute("DELETE FROM setting WHERE name = 'allow_user_create_domain'")
|
6
run.py
6
run.py
@ -1,11 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from app import app
|
from app import app
|
||||||
from config import PORT
|
from config import PORT
|
||||||
|
from config import BIND_ADDRESS
|
||||||
try:
|
|
||||||
from config import BIND_ADDRESS
|
|
||||||
except:
|
|
||||||
BIND_ADDRESS = '127.0.0.1'
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug = True, host=BIND_ADDRESS, port=PORT)
|
app.run(debug = True, host=BIND_ADDRESS, port=PORT)
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
### Imports
|
### Imports
|
||||||
from app import app
|
|
||||||
from app.lib import log
|
|
||||||
from app.models import Domain
|
from app.models import Domain
|
||||||
from config import BG_DOMAIN_UPDATES
|
from config import BG_DOMAIN_UPDATES
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user