diff --git a/app/__init__.py b/app/__init__.py index 897db56..c309b78 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -7,6 +7,10 @@ app = Flask(__name__) app.config.from_object('config') app.wsgi_app = ProxyFix(app.wsgi_app) +#### CONFIGURE LOGGER #### +from app.lib.log import logger +logging = logger('powerdns-admin', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config() + login_manager = LoginManager() login_manager.init_app(app) db = SQLAlchemy(app) diff --git a/app/lib/utils.py b/app/lib/utils.py index 84c4a75..934ee4d 100644 --- a/app/lib/utils.py +++ b/app/lib/utils.py @@ -130,7 +130,7 @@ def display_record_name(data): if record_name == domain_name: return '@' else: - return record_name.replace('.'+domain_name, '') + return re.sub('\.{}$'.format(domain_name), '', record_name) def display_master_name(data): @@ -196,6 +196,9 @@ def email_to_gravatar_url(email="", size=100): """ AD doesn't necessarily have email """ + if email is None: + email = "" + hash_string = hashlib.md5(email.encode('utf-8')).hexdigest() return "https://s.gravatar.com/avatar/{0}?s={1}".format(hash_string, size) diff --git a/app/models.py b/app/models.py index 25024b7..b0e0fcf 100644 --- a/app/models.py +++ b/app/models.py @@ -10,6 +10,7 @@ import pyotp import re import dns.reversename import sys +import logging as logger from datetime import datetime from urllib.parse import urljoin @@ -19,10 +20,8 @@ from flask_login import AnonymousUserMixin from app import app, db from app.lib import utils -from app.lib.log import logger -# LOG CONFIGS -logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config() +logging = logger.getLogger(__name__) if 'LDAP_TYPE' in app.config.keys(): LDAP_URI = app.config['LDAP_URI'] @@ -135,6 +134,9 @@ class User(db.Model): def get_hashed_password(self, plain_text_password=None): # Hash a password for the first time # (Using bcrypt, the salt is saved into the hash itself) + if plain_text_password == None: + return plain_text_password + pw = plain_text_password if plain_text_password else self.plain_text_password return bcrypt.hashpw(pw.encode('utf-8'), bcrypt.gensalt()) @@ -316,6 +318,9 @@ class User(db.Model): self.password = self.get_hashed_password(self.plain_text_password) + if self.password: + self.password = self.password.decode("utf-8") + db.session.add(self) db.session.commit() return {'status': True, 'msg': 'Created user successfully'} @@ -335,7 +340,9 @@ class User(db.Model): user.password = self.get_hashed_password(self.plain_text_password) if self.plain_text_password else user.password user.avatar = self.avatar if self.avatar else user.avatar - user.otp_secret = "" + if enable_otp is not None: + user.otp_secret = "" + if enable_otp == True: # generate the opt secret key user.otp_secret = base64.b32encode(os.urandom(10)).decode('utf-8') @@ -502,24 +509,18 @@ class Domain(db.Model): logging.error('Can not create setting {0} for domain {1}. {2}'.format(setting, self.name, e)) return False + def get_domain_info(self, domain_name): + """ + Get all domains which has in PowerDNS + """ + headers = {} + headers['X-API-Key'] = PDNS_API_KEY + jdata = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain_name)), headers=headers) + return jdata + def get_domains(self): """ Get all domains which has in PowerDNS - jdata example: - [ - { - "id": "example.org.", - "url": "/servers/localhost/zones/example.org.", - "name": "example.org", - "kind": "Native", - "dnssec": false, - "account": "", - "masters": [], - "serial": 2015101501, - "notified_serial": 0, - "last_check": 0 - } - ] """ headers = {} headers['X-API-Key'] = PDNS_API_KEY @@ -878,6 +879,7 @@ class Domain(db.Model): else: return {'status': 'error', 'msg': 'This domain doesnot exist'} + class DomainUser(db.Model): __tablename__ = 'domain_user' id = db.Column(db.Integer, primary_key = True) @@ -1175,6 +1177,7 @@ class Record(object): return {'status': 'error', 'msg': jdata2['error']} else: self.auto_ptr(domain, new_records, deleted_records) + self.update_db_serial(domain) logging.info('Record was applied successfully.') return {'status': 'ok', 'msg': 'Record was applied successfully'} except Exception as e: @@ -1327,6 +1330,20 @@ class Record(object): logging.error("Cannot add record {0}/{1}/{2} to domain {3}. DETAIL: {4}".format(self.name, self.type, self.data, domain, e)) return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'} + def update_db_serial(self, domain): + headers = {} + headers['X-API-Key'] = PDNS_API_KEY + jdata = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='GET') + serial = jdata['serial'] + + domain = Domain.query.filter(Domain.name==domain).first() + if domain: + domain.serial = serial + db.session.commit() + return {'status': True, 'msg': 'Synced local serial for domain name {0}'.format(domain)} + else: + return {'status': False, 'msg': 'Could not find domain name {0} in local db'.format(domain)} + class Server(object): """ @@ -1544,7 +1561,7 @@ class DomainTemplateRecord(db.Model): name = db.Column(db.String(255)) type = db.Column(db.String(64)) ttl = db.Column(db.Integer) - data = db.Column(db.String(255)) + data = db.Column(db.Text) status = db.Column(db.Boolean) template_id = db.Column(db.Integer, db.ForeignKey('domain_template.id')) template = db.relationship('DomainTemplate', back_populates='records') diff --git a/app/static/custom/js/custom.js b/app/static/custom/js/custom.js index 936b8ee..279463d 100644 --- a/app/static/custom/js/custom.js +++ b/app/static/custom/js/custom.js @@ -30,6 +30,37 @@ function applyChanges(data, url, showResult, refreshPage) { }); } +function applyRecordChanges(data, domain) { + var success = false; + $.ajax({ + type : "POST", + url : $SCRIPT_ROOT + '/domain/' + domain + '/apply', + data : JSON.stringify(data),// now data come in this function + contentType : "application/json; charset=utf-8", + crossDomain : true, + dataType : "json", + success : function(data, status, jqXHR) { + // update Apply button value + $.getJSON($SCRIPT_ROOT + '/domain/' + domain + '/info', function(data) { + $(".button_apply_changes").val(data['serial']); + }); + + console.log("Applied changes successfully.") + var modal = $("#modal_success"); + modal.find('.modal-body p').text("Applied changes successfully"); + modal.modal('show'); + }, + + error : function(jqXHR, status) { + console.log(jqXHR); + var modal = $("#modal_error"); + var responseJson = jQuery.parseJSON(jqXHR.responseText); + modal.find('.modal-body p').text(responseJson['msg']); + modal.modal('show'); + } + }); +} + function getTableData(table) { var rData = [] diff --git a/app/templates/admin_history.html b/app/templates/admin_history.html index 59773ac..6ce9469 100644 --- a/app/templates/admin_history.html +++ b/app/templates/admin_history.html @@ -96,7 +96,7 @@
diff --git a/app/templates/domain.html b/app/templates/domain.html index f91d374..203a8f1 100644 --- a/app/templates/domain.html +++ b/app/templates/domain.html @@ -25,7 +25,7 @@ -