mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2025-06-16 13:06:06 +00:00
Merge branch 'master' into historyfix
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
from .base import (
|
||||
csrf, login_manager, handle_bad_request, handle_unauthorized_access,
|
||||
captcha, csrf, login_manager, handle_bad_request, handle_unauthorized_access,
|
||||
handle_access_forbidden, handle_page_not_found, handle_internal_server_error
|
||||
)
|
||||
|
||||
@ -14,6 +14,7 @@ from .api import api_bp, apilist_bp
|
||||
def init_app(app):
|
||||
login_manager.init_app(app)
|
||||
csrf.init_app(app)
|
||||
captcha.init_app(app)
|
||||
|
||||
app.register_blueprint(index_bp)
|
||||
app.register_blueprint(user_bp)
|
||||
|
@ -610,14 +610,21 @@ def manage_user():
|
||||
@operator_role_required
|
||||
def edit_account(account_name=None):
|
||||
users = User.query.all()
|
||||
account = Account.query.filter(
|
||||
Account.name == account_name).first()
|
||||
all_accounts = Account.query.all()
|
||||
accounts = {acc.id: acc for acc in all_accounts}
|
||||
domains = Domain.query.all()
|
||||
|
||||
if request.method == 'GET':
|
||||
if account_name is None:
|
||||
if account_name is None or not account:
|
||||
return render_template('admin_edit_account.html',
|
||||
account=None,
|
||||
account_user_ids=[],
|
||||
users=users,
|
||||
domains=domains,
|
||||
accounts=accounts,
|
||||
create=1)
|
||||
|
||||
else:
|
||||
account = Account.query.filter(
|
||||
Account.name == account_name).first()
|
||||
@ -626,11 +633,14 @@ def edit_account(account_name=None):
|
||||
account=account,
|
||||
account_user_ids=account_user_ids,
|
||||
users=users,
|
||||
domains=domains,
|
||||
accounts=accounts,
|
||||
create=0)
|
||||
|
||||
if request.method == 'POST':
|
||||
fdata = request.form
|
||||
new_user_list = request.form.getlist('account_multi_user')
|
||||
new_domain_list = request.form.getlist('account_domains')
|
||||
|
||||
# on POST, synthesize account and account_user_ids from form data
|
||||
if not account_name:
|
||||
@ -654,6 +664,8 @@ def edit_account(account_name=None):
|
||||
account=account,
|
||||
account_user_ids=account_user_ids,
|
||||
users=users,
|
||||
domains=domains,
|
||||
accounts=accounts,
|
||||
create=create,
|
||||
invalid_accountname=True)
|
||||
|
||||
@ -662,19 +674,33 @@ def edit_account(account_name=None):
|
||||
account=account,
|
||||
account_user_ids=account_user_ids,
|
||||
users=users,
|
||||
domains=domains,
|
||||
accounts=accounts,
|
||||
create=create,
|
||||
duplicate_accountname=True)
|
||||
|
||||
result = account.create_account()
|
||||
history = History(msg='Create account {0}'.format(account.name),
|
||||
created_by=current_user.username)
|
||||
|
||||
else:
|
||||
result = account.update_account()
|
||||
history = History(msg='Update account {0}'.format(account.name),
|
||||
created_by=current_user.username)
|
||||
|
||||
if result['status']:
|
||||
account = Account.query.filter(
|
||||
Account.name == account_name).first()
|
||||
old_domains = Domain.query.filter(Domain.account_id == account.id).all()
|
||||
|
||||
for domain_name in new_domain_list:
|
||||
domain = Domain.query.filter(
|
||||
Domain.name == domain_name).first()
|
||||
if account.id != domain.account_id:
|
||||
Domain(name=domain_name).assoc_account(account.id)
|
||||
|
||||
for domain in old_domains:
|
||||
if domain.name not in new_domain_list:
|
||||
Domain(name=domain.name).assoc_account(None)
|
||||
|
||||
history = History(msg='{0} account {1}'.format('Create' if create else 'Update', account.name),
|
||||
created_by=current_user.username)
|
||||
|
||||
account.grant_privileges(new_user_list)
|
||||
history.add()
|
||||
return redirect(url_for('admin.manage_account'))
|
||||
@ -769,7 +795,7 @@ class DetailedHistory():
|
||||
if 'domain_type' in detail_dict and 'account_id' in detail_dict: # this is a domain creation
|
||||
self.detailed_msg = render_template_string("""
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr><td>Domain type:</td><td>{{ domaintype }}</td></tr>
|
||||
<tr><td>Domain Type:</td><td>{{ domaintype }}</td></tr>
|
||||
<tr><td>Account:</td><td>{{ account }}</td></tr>
|
||||
</table>
|
||||
""",
|
||||
@ -778,22 +804,23 @@ class DetailedHistory():
|
||||
|
||||
elif 'authenticator' in detail_dict: # this is a user authentication
|
||||
self.detailed_msg = render_template_string("""
|
||||
<table class="table table-bordered table-striped" style="width:565px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="3" style="background: rgba({{ background_rgba }});">
|
||||
<p style="color:white;">User {{ username }} authentication {{ auth_result }}</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<table class="table table-bordered table-striped"">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authenticator Type:</td>
|
||||
<td colspan="2">{{ authenticator }}</td>
|
||||
<td>Username:</td>
|
||||
<td>{{ username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP Address</td>
|
||||
<td colspan="2">{{ ip_address }}</td>
|
||||
<td>Authentication Result:</td>
|
||||
<td>{{ auth_result }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Authenticator Type:</td>
|
||||
<td>{{ authenticator }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP Address:</td>
|
||||
<td>{{ ip_address }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -890,6 +917,16 @@ class DetailedHistory():
|
||||
''',
|
||||
history_status=DetailedHistory.get_key_val(detail_dict, 'status'),
|
||||
history_msg=DetailedHistory.get_key_val(detail_dict, 'msg'))
|
||||
|
||||
elif 'Update domain' in history.msg and 'associate account' in history.msg: # When an account gets associated or dissociate with domains
|
||||
self.detailed_msg = render_template_string('''
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr><td>Associate: </td><td>{{ history_assoc_account }}</td></tr>
|
||||
<tr><td>Dissociate:</td><td>{{ history_dissoc_account }}</td></tr>
|
||||
</table>
|
||||
''',
|
||||
history_assoc_account=DetailedHistory.get_key_val(detail_dict, 'assoc_account'),
|
||||
history_dissoc_account=DetailedHistory.get_key_val(detail_dict, 'dissoc_account'))
|
||||
|
||||
# check for lower key as well for old databases
|
||||
@staticmethod
|
||||
@ -927,6 +964,13 @@ def history():
|
||||
'msg': 'You do not have permission to remove history.'
|
||||
}), 401)
|
||||
|
||||
if Setting().get('preserve_history'):
|
||||
return make_response(
|
||||
jsonify({
|
||||
'status': 'error',
|
||||
'msg': 'History removal is not allowed (toggle preserve_history in settings).'
|
||||
}), 401)
|
||||
|
||||
h = History()
|
||||
result = h.remove_all()
|
||||
if result:
|
||||
@ -1282,6 +1326,7 @@ def setting_basic():
|
||||
'otp_field_enabled',
|
||||
'otp_force',
|
||||
'pdns_api_timeout',
|
||||
'preserve_history',
|
||||
'pretty_ipv6_ptr',
|
||||
'record_helper',
|
||||
'record_quick_edit',
|
||||
|
@ -1,22 +1,21 @@
|
||||
import json
|
||||
from urllib.parse import urljoin
|
||||
import secrets
|
||||
import string
|
||||
from base64 import b64encode
|
||||
from flask import (
|
||||
Blueprint, g, request, abort, current_app, make_response, jsonify,
|
||||
)
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from flask import (Blueprint, g, request, abort, current_app, make_response, jsonify)
|
||||
from flask_login import current_user
|
||||
|
||||
from .base import csrf
|
||||
from ..models.base import db
|
||||
from ..models import (
|
||||
User, Domain, DomainUser, Account, AccountUser, History, Setting, ApiKey,
|
||||
Role,
|
||||
from ..decorators import (
|
||||
api_basic_auth, api_can_create_domain, is_json, apikey_auth,
|
||||
apikey_can_create_domain, apikey_can_remove_domain,
|
||||
apikey_is_admin, apikey_can_access_domain, apikey_can_configure_dnssec,
|
||||
api_role_can, apikey_or_basic_auth,
|
||||
callback_if_request_body_contains_key, allowed_record_types, allowed_record_ttl
|
||||
)
|
||||
from ..lib import utils, helper
|
||||
from ..lib.schema import (
|
||||
ApiKeySchema, DomainSchema, ApiPlainKeySchema, UserSchema, AccountSchema,
|
||||
UserDetailedSchema,
|
||||
)
|
||||
from ..lib.errors import (
|
||||
StructuredException,
|
||||
DomainNotExists, DomainAlreadyExists, DomainAccessForbidden,
|
||||
@ -26,15 +25,15 @@ from ..lib.errors import (
|
||||
UserCreateFail, UserCreateDuplicate, UserUpdateFail, UserDeleteFail,
|
||||
UserUpdateFailEmail, InvalidAccountNameException
|
||||
)
|
||||
from ..decorators import (
|
||||
api_basic_auth, api_can_create_domain, is_json, apikey_auth,
|
||||
apikey_can_create_domain, apikey_can_remove_domain,
|
||||
apikey_is_admin, apikey_can_access_domain, apikey_can_configure_dnssec,
|
||||
api_role_can, apikey_or_basic_auth,
|
||||
callback_if_request_body_contains_key, allowed_record_types, allowed_record_ttl
|
||||
from ..lib.schema import (
|
||||
ApiKeySchema, DomainSchema, ApiPlainKeySchema, UserSchema, AccountSchema,
|
||||
UserDetailedSchema,
|
||||
)
|
||||
import secrets
|
||||
import string
|
||||
from ..models import (
|
||||
User, Domain, DomainUser, Account, AccountUser, History, Setting, ApiKey,
|
||||
Role,
|
||||
)
|
||||
from ..models.base import db
|
||||
|
||||
api_bp = Blueprint('api', __name__, url_prefix='/api/v1')
|
||||
apilist_bp = Blueprint('apilist', __name__, url_prefix='/')
|
||||
@ -56,10 +55,10 @@ def get_user_domains():
|
||||
.outerjoin(Account, Domain.account_id == Account.id) \
|
||||
.outerjoin(AccountUser, Account.id == AccountUser.account_id) \
|
||||
.filter(
|
||||
db.or_(
|
||||
DomainUser.user_id == current_user.id,
|
||||
AccountUser.user_id == current_user.id
|
||||
)).all()
|
||||
db.or_(
|
||||
DomainUser.user_id == current_user.id,
|
||||
AccountUser.user_id == current_user.id
|
||||
)).all()
|
||||
return domains
|
||||
|
||||
|
||||
@ -71,10 +70,10 @@ def get_user_apikeys(domain_name=None):
|
||||
.outerjoin(Account, Domain.account_id == Account.id) \
|
||||
.outerjoin(AccountUser, Account.id == AccountUser.account_id) \
|
||||
.filter(
|
||||
db.or_(
|
||||
DomainUser.user_id == User.id,
|
||||
AccountUser.user_id == User.id
|
||||
)
|
||||
db.or_(
|
||||
DomainUser.user_id == User.id,
|
||||
AccountUser.user_id == User.id
|
||||
)
|
||||
) \
|
||||
.filter(User.id == current_user.id)
|
||||
|
||||
@ -167,12 +166,7 @@ def handle_request_is_not_json(err):
|
||||
def before_request():
|
||||
# Check site is in maintenance mode
|
||||
maintenance = Setting().get('maintenance')
|
||||
if (
|
||||
maintenance and current_user.is_authenticated and
|
||||
current_user.role.name not in [
|
||||
'Administrator', 'Operator'
|
||||
]
|
||||
):
|
||||
if (maintenance and current_user.is_authenticated and current_user.role.name not in ['Administrator', 'Operator']):
|
||||
return make_response(
|
||||
jsonify({
|
||||
"status": False,
|
||||
@ -224,14 +218,13 @@ def api_login_create_zone():
|
||||
|
||||
history = History(msg='Add domain {0}'.format(
|
||||
data['name'].rstrip('.')),
|
||||
detail=json.dumps(data),
|
||||
created_by=current_user.username,
|
||||
domain_id=domain_id)
|
||||
detail=json.dumps(data),
|
||||
created_by=current_user.username,
|
||||
domain_id=domain_id)
|
||||
history.add()
|
||||
|
||||
if current_user.role.name not in ['Administrator', 'Operator']:
|
||||
current_app.logger.debug(
|
||||
"User is ordinary user, assigning created domain")
|
||||
current_app.logger.debug("User is ordinary user, assigning created domain")
|
||||
domain = Domain(name=data['name'].rstrip('.'))
|
||||
domain.update()
|
||||
domain.grant_privileges([current_user.id])
|
||||
@ -299,9 +292,9 @@ def api_login_delete_zone(domain_name):
|
||||
|
||||
history = History(msg='Delete domain {0}'.format(
|
||||
utils.pretty_domain_name(domain_name)),
|
||||
detail='',
|
||||
created_by=current_user.username,
|
||||
domain_id=domain_id)
|
||||
detail='',
|
||||
created_by=current_user.username,
|
||||
domain_id=domain_id)
|
||||
history.add()
|
||||
|
||||
except Exception as e:
|
||||
@ -326,14 +319,14 @@ def api_generate_apikey():
|
||||
|
||||
if 'domains' not in data:
|
||||
domains = []
|
||||
elif not isinstance(data['domains'], (list, )):
|
||||
elif not isinstance(data['domains'], (list,)):
|
||||
abort(400)
|
||||
else:
|
||||
domains = [d['name'] if isinstance(d, dict) else d for d in data['domains']]
|
||||
|
||||
if 'accounts' not in data:
|
||||
accounts = []
|
||||
elif not isinstance(data['accounts'], (list, )):
|
||||
elif not isinstance(data['accounts'], (list,)):
|
||||
abort(400)
|
||||
else:
|
||||
accounts = [a['name'] if isinstance(a, dict) else a for a in data['accounts']]
|
||||
@ -385,8 +378,7 @@ def api_generate_apikey():
|
||||
user_domain_list = [item.name for item in user_domain_obj_list]
|
||||
|
||||
current_app.logger.debug("Input domain list: {0}".format(domain_list))
|
||||
current_app.logger.debug(
|
||||
"User domain list: {0}".format(user_domain_list))
|
||||
current_app.logger.debug("User domain list: {0}".format(user_domain_list))
|
||||
|
||||
inter = set(domain_list).intersection(set(user_domain_list))
|
||||
|
||||
@ -539,14 +531,14 @@ def api_update_apikey(apikey_id):
|
||||
|
||||
if 'domains' not in data:
|
||||
domains = None
|
||||
elif not isinstance(data['domains'], (list, )):
|
||||
elif not isinstance(data['domains'], (list,)):
|
||||
abort(400)
|
||||
else:
|
||||
domains = [d['name'] if isinstance(d, dict) else d for d in data['domains']]
|
||||
|
||||
if 'accounts' not in data:
|
||||
accounts = None
|
||||
elif not isinstance(data['accounts'], (list, )):
|
||||
elif not isinstance(data['accounts'], (list,)):
|
||||
abort(400)
|
||||
else:
|
||||
accounts = [a['name'] if isinstance(a, dict) else a for a in data['accounts']]
|
||||
@ -963,9 +955,7 @@ def api_delete_account(account_id):
|
||||
account = account_list[0]
|
||||
else:
|
||||
abort(404)
|
||||
current_app.logger.debug(
|
||||
f'Deleting Account {account.name}'
|
||||
)
|
||||
current_app.logger.debug(f'Deleting Account {account.name}')
|
||||
|
||||
# Remove account association from domains first
|
||||
if len(account.domains) > 0:
|
||||
@ -1047,7 +1037,7 @@ def api_remove_account_user(account_id, user_id):
|
||||
user_list = User.query.join(AccountUser).filter(
|
||||
AccountUser.account_id == account_id,
|
||||
AccountUser.user_id == user_id,
|
||||
).all()
|
||||
).all()
|
||||
if not user_list:
|
||||
abort(404)
|
||||
if not account.remove_user(user):
|
||||
@ -1194,17 +1184,13 @@ def api_get_zones(server_id):
|
||||
return jsonify(domain_schema.dump(domain_obj_list)), 200
|
||||
else:
|
||||
resp = helper.forward_request()
|
||||
if (
|
||||
g.apikey.role.name not in ['Administrator', 'Operator']
|
||||
and resp.status_code == 200
|
||||
):
|
||||
if (g.apikey.role.name not in ['Administrator', 'Operator'] and resp.status_code == 200):
|
||||
domain_list = [d['name']
|
||||
for d in domain_schema.dump(g.apikey.domains)]
|
||||
|
||||
accounts_domains = [d.name for a in g.apikey.accounts for d in a.domains]
|
||||
allowed_domains = set(domain_list + accounts_domains)
|
||||
current_app.logger.debug("Account domains: {}".format(
|
||||
'/'.join(accounts_domains)))
|
||||
current_app.logger.debug("Account domains: {}".format('/'.join(accounts_domains)))
|
||||
content = json.dumps([i for i in json.loads(resp.content)
|
||||
if i['name'].rstrip('.') in allowed_domains])
|
||||
return content, resp.status_code, resp.headers.items()
|
||||
@ -1225,6 +1211,7 @@ def api_server_config_forward(server_id):
|
||||
resp = helper.forward_request()
|
||||
return resp.content, resp.status_code, resp.headers.items()
|
||||
|
||||
|
||||
# The endpoint to synchronize Domains in background
|
||||
@api_bp.route('/sync_domains', methods=['GET'])
|
||||
@apikey_or_basic_auth
|
||||
@ -1233,6 +1220,7 @@ def sync_domains():
|
||||
domain.update()
|
||||
return 'Finished synchronization in background', 200
|
||||
|
||||
|
||||
@api_bp.route('/health', methods=['GET'])
|
||||
@apikey_auth
|
||||
def health():
|
||||
@ -1246,7 +1234,8 @@ def health():
|
||||
try:
|
||||
domain.get_domain_info(domain_to_query.name)
|
||||
except Exception as e:
|
||||
current_app.logger.error("Health Check - Failed to query authoritative server for domain {}".format(domain_to_query.name))
|
||||
current_app.logger.error(
|
||||
"Health Check - Failed to query authoritative server for domain {}".format(domain_to_query.name))
|
||||
return make_response("Down", 503)
|
||||
|
||||
return make_response("Up", 200)
|
||||
|
@ -3,10 +3,12 @@ import base64
|
||||
from flask import render_template, url_for, redirect, session, request, current_app
|
||||
from flask_login import LoginManager
|
||||
from flask_seasurf import SeaSurf
|
||||
from flask_session_captcha import FlaskSessionCaptcha
|
||||
|
||||
from ..models.user import User
|
||||
|
||||
|
||||
captcha = FlaskSessionCaptcha()
|
||||
csrf = SeaSurf()
|
||||
login_manager = LoginManager()
|
||||
|
||||
|
@ -89,14 +89,14 @@ def domain(domain_name):
|
||||
# - Find a way to make it consistent, or
|
||||
# - Only allow one comment for that case
|
||||
if StrictVersion(Setting().get('pdns_version')) >= StrictVersion('4.0.0'):
|
||||
pretty_v6 = Setting().get('pretty_ipv6_ptr')
|
||||
for r in rrsets:
|
||||
if r['type'] in records_allow_to_edit:
|
||||
r_name = r['name'].rstrip('.')
|
||||
|
||||
# If it is reverse zone and pretty_ipv6_ptr setting
|
||||
# is enabled, we reformat the name for ipv6 records.
|
||||
if Setting().get('pretty_ipv6_ptr') and r[
|
||||
'type'] == 'PTR' and 'ip6.arpa' in r_name and '*' not in r_name:
|
||||
if pretty_v6 and r['type'] == 'PTR' and 'ip6.arpa' in r_name and '*' not in r_name:
|
||||
r_name = dns.reversename.to_address(
|
||||
dns.name.from_text(r_name))
|
||||
|
||||
|
@ -10,7 +10,7 @@ from yaml import Loader, load
|
||||
from flask import Blueprint, render_template, make_response, url_for, current_app, g, session, request, redirect, abort
|
||||
from flask_login import login_user, logout_user, login_required, current_user
|
||||
|
||||
from .base import csrf, login_manager
|
||||
from .base import captcha, csrf, login_manager
|
||||
from ..lib import utils
|
||||
from ..decorators import dyndns_login_required
|
||||
from ..models.base import db
|
||||
@ -400,7 +400,7 @@ def login():
|
||||
desc_prop = Setting().get('oidc_oauth_account_description_property')
|
||||
|
||||
account_to_add = []
|
||||
#If the name_property and desc_property exist in me (A variable that contains all the userinfo from the IdP).
|
||||
#If the name_property and desc_property exist in me (A variable that contains all the userinfo from the IdP).
|
||||
if name_prop in me and desc_prop in me:
|
||||
accounts_name_prop = [me[name_prop]] if type(me[name_prop]) is not list else me[name_prop]
|
||||
accounts_desc_prop = [me[desc_prop]] if type(me[desc_prop]) is not list else me[desc_prop]
|
||||
@ -415,7 +415,7 @@ def login():
|
||||
account_to_add.append(account)
|
||||
user_accounts = user.get_accounts()
|
||||
|
||||
# Add accounts
|
||||
# Add accounts
|
||||
for account in account_to_add:
|
||||
if account not in user_accounts:
|
||||
account.add_user(user)
|
||||
@ -581,7 +581,7 @@ def get_azure_groups(uri):
|
||||
def authenticate_user(user, authenticator, remember=False):
|
||||
login_user(user, remember=remember)
|
||||
signin_history(user.username, authenticator, True)
|
||||
if Setting().get('otp_force') and Setting().get('otp_field_enabled') and not user.otp_secret:
|
||||
if Setting().get('otp_force') and Setting().get('otp_field_enabled') and not user.otp_secret and session['authentication_type'] not in ['OAuth']:
|
||||
user.update_profile(enable_otp=True)
|
||||
user_id = current_user.id
|
||||
prepare_welcome_user(user_id)
|
||||
@ -651,50 +651,73 @@ def logout():
|
||||
|
||||
@index_bp.route('/register', methods=['GET', 'POST'])
|
||||
def register():
|
||||
if Setting().get('signup_enabled'):
|
||||
if request.method == 'GET':
|
||||
return render_template('register.html')
|
||||
elif request.method == 'POST':
|
||||
username = request.form.get('username', '').strip()
|
||||
password = request.form.get('password', '')
|
||||
firstname = request.form.get('firstname', '').strip()
|
||||
lastname = request.form.get('lastname', '').strip()
|
||||
email = request.form.get('email', '').strip()
|
||||
rpassword = request.form.get('rpassword', '')
|
||||
CAPTCHA_ENABLE = current_app.config.get('CAPTCHA_ENABLE')
|
||||
if Setting().get('signup_enabled'):
|
||||
if current_user.is_authenticated:
|
||||
return redirect(url_for('index.index'))
|
||||
if request.method == 'GET':
|
||||
return render_template('register.html', captcha_enable=CAPTCHA_ENABLE)
|
||||
elif request.method == 'POST':
|
||||
username = request.form.get('username', '').strip()
|
||||
password = request.form.get('password', '')
|
||||
firstname = request.form.get('firstname', '').strip()
|
||||
lastname = request.form.get('lastname', '').strip()
|
||||
email = request.form.get('email', '').strip()
|
||||
rpassword = request.form.get('rpassword', '')
|
||||
|
||||
if not username or not password or not email:
|
||||
return render_template(
|
||||
'register.html', error='Please input required information')
|
||||
is_valid_email = re.compile(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
|
||||
|
||||
if password != rpassword:
|
||||
return render_template(
|
||||
'register.html',
|
||||
error="Password confirmation does not match")
|
||||
error_messages = {}
|
||||
if not firstname:
|
||||
error_messages['firstname'] = 'First Name is required'
|
||||
if not lastname:
|
||||
error_messages['lastname'] = 'Last Name is required'
|
||||
if not username:
|
||||
error_messages['username'] = 'Username is required'
|
||||
if not password:
|
||||
error_messages['password'] = 'Password is required'
|
||||
if not rpassword:
|
||||
error_messages['rpassword'] = 'Password confirmation is required'
|
||||
if not email:
|
||||
error_messages['email'] = 'Email is required'
|
||||
if not is_valid_email.match(email):
|
||||
error_messages['email'] = 'Invalid email address'
|
||||
if password != rpassword:
|
||||
error_messages['password'] = 'Password confirmation does not match'
|
||||
error_messages['rpassword'] = 'Password confirmation does not match'
|
||||
|
||||
user = User(username=username,
|
||||
plain_text_password=password,
|
||||
firstname=firstname,
|
||||
lastname=lastname,
|
||||
email=email)
|
||||
if not captcha.validate():
|
||||
return render_template(
|
||||
'register.html', error='Invalid CAPTCHA answer', error_messages=error_messages, captcha_enable=CAPTCHA_ENABLE)
|
||||
|
||||
try:
|
||||
result = user.create_local_user()
|
||||
if result and result['status']:
|
||||
if Setting().get('verify_user_email'):
|
||||
send_account_verification(email)
|
||||
if Setting().get('otp_force') and Setting().get('otp_field_enabled'):
|
||||
user.update_profile(enable_otp=True)
|
||||
prepare_welcome_user(user.id)
|
||||
return redirect(url_for('index.welcome'))
|
||||
else:
|
||||
return redirect(url_for('index.login'))
|
||||
else:
|
||||
return render_template('register.html',
|
||||
error=result['msg'])
|
||||
except Exception as e:
|
||||
return render_template('register.html', error=e)
|
||||
if error_messages:
|
||||
return render_template('register.html', error_messages=error_messages, captcha_enable=CAPTCHA_ENABLE)
|
||||
|
||||
user = User(username=username,
|
||||
plain_text_password=password,
|
||||
firstname=firstname,
|
||||
lastname=lastname,
|
||||
email=email
|
||||
)
|
||||
|
||||
try:
|
||||
result = user.create_local_user()
|
||||
if result and result['status']:
|
||||
if Setting().get('verify_user_email'):
|
||||
send_account_verification(email)
|
||||
if Setting().get('otp_force') and Setting().get('otp_field_enabled'):
|
||||
user.update_profile(enable_otp=True)
|
||||
prepare_welcome_user(user.id)
|
||||
return redirect(url_for('index.welcome'))
|
||||
else:
|
||||
return redirect(url_for('index.login'))
|
||||
else:
|
||||
return render_template('register.html',
|
||||
error=result['msg'], captcha_enable=CAPTCHA_ENABLE)
|
||||
except Exception as e:
|
||||
return render_template('register.html', error=e, captcha_enable=CAPTCHA_ENABLE)
|
||||
else:
|
||||
return render_template('errors/404.html'), 404
|
||||
return render_template('errors/404.html'), 404
|
||||
|
||||
|
||||
# Show welcome page on first login if otp_force is enabled
|
||||
|
Reference in New Issue
Block a user