Adding Flask-SeaSurf module for CSRF protection.

This commit is contained in:
Khanh Ngo 2018-11-21 10:24:33 +07:00
parent ea53ae340f
commit 5f049debe5
25 changed files with 93 additions and 77 deletions

View File

@ -5,6 +5,7 @@ from flask_sqlalchemy import SQLAlchemy as SA
from flask_migrate import Migrate
from authlib.flask.client import OAuth as AuthlibOAuth
from sqlalchemy.exc import OperationalError
from flask_seasurf import SeaSurf
# subclass SQLAlchemy to enable pool_pre_ping
class SQLAlchemy(SA):
@ -18,6 +19,7 @@ from app.assets import assets
app = Flask(__name__)
app.config.from_object('config')
app.wsgi_app = ProxyFix(app.wsgi_app)
csrf = SeaSurf(app)
assets.init_app(app)

View File

@ -145,8 +145,8 @@ function SelectElement(elementID, valueToSelect)
element.value = valueToSelect;
}
function enable_dns_sec(url) {
$.getJSON(url, function(data) {
function enable_dns_sec(url, csrf_token) {
$.post(url, {'_csrf_token': csrf_token}, function(data) {
var modal = $("#modal_dnssec_info");
if (data['status'] == 'error'){
@ -157,7 +157,7 @@ function enable_dns_sec(url) {
//location.reload();
window.location.reload(true);
}
})
}, 'json')
}
function getdnssec(url, domain){

View File

@ -28,6 +28,7 @@
<!-- /.box-header -->
<!-- form start -->
<form role="form" method="post" action="{% if create %}{{ url_for('admin_editaccount') }}{% else %}{{ url_for('admin_editaccount', account_name=account.name) }}{% endif %}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="create" value="{{ create }}">
<div class="box-body">
{% if error %}
@ -116,4 +117,4 @@
<script>
$("#account_multi_user").multiSelect();
</script>
{% endblock %}
{% endblock %}

View File

@ -28,6 +28,7 @@
<!-- /.box-header -->
<!-- form start -->
<form role="form" method="post" action="{% if create %}{{ url_for('admin_edituser') }}{% else %}{{ url_for('admin_edituser', user_username=user.username) }}{% endif %}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="create" value="{{ create }}">
<div class="box-body">
{% if error %}
@ -115,14 +116,14 @@
{% endblock %}
{% block extrascripts %}
<script>
// handle disabling two factor authentication
// handle disabling two factor authentication
$(document.body).on('click', '.button_otp_disable', function() {
var modal = $("#modal_otp_disable");
var username = $(this).prop('id');
var info = "Are you sure you want to disable two factor authentication for user " + username + "?";
var info = "Are you sure you want to disable two factor authentication for user " + username + "?";
modal.find('.modal-body p').text(info);
modal.find('#button_otp_disable_confirm').click(function() {
var postdata = {'action': 'user_otp_disable', 'data': username}
var postdata = {'action': 'user_otp_disable', 'data': username, '_csrf_token': '{{ csrf_token() }}'}
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser', false, true);
})
modal.modal('show');

View File

@ -60,7 +60,7 @@
</div>
<!-- /.row -->
</section>
{% endblock %}
{% endblock %}
{% block extrascripts %}
<script>
// set up history data table
@ -89,7 +89,7 @@
modal.modal('show');
});
</script>
{% endblock %}
{% endblock %}
{% block modals %}
<!-- Clear History Confirmation Box -->
<div class="modal fade modal-warning" id="modal_clear_history">
@ -108,7 +108,7 @@
<div class="modal-footer">
<button type="button" class="btn btn-flat btn-default pull-left"
data-dismiss="modal">Close</button>
<button type="button" class="btn btn-flat btn-danger" onclick="applyChanges('', $SCRIPT_ROOT + '/admin/history', false, true);">Clear History</button>
<button type="button" class="btn btn-flat btn-danger" onclick="applyChanges({'_csrf_token': '{{ csrf_token() }}'}, $SCRIPT_ROOT + '/admin/history', false, true);">Clear History</button>
</div>
</div>
<!-- /.modal-content -->

View File

@ -67,7 +67,7 @@
</div>
<!-- /.row -->
</section>
{% endblock %}
{% endblock %}
{% block extrascripts %}
<script>
// set up accounts data table
@ -90,16 +90,16 @@
$(document.body).on('click', '.button_delete', function() {
var modal = $("#modal_delete");
var accountname = $(this).prop('id');
var info = "Are you sure you want to delete " + accountname + "?";
var info = "Are you sure you want to delete " + accountname + "?";
modal.find('.modal-body p').text(info);
modal.find('#button_delete_confirm').click(function() {
var postdata = {'action': 'delete_account', 'data': accountname}
var postdata = {'action': 'delete_account', 'data': accountname, '_csrf_token': '{{ csrf_token() }}'}
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageaccount', false, true);
modal.modal('hide');
})
modal.modal('show');
});
</script>
{% endblock %}
{% block modals %}

View File

@ -81,7 +81,7 @@
</div>
<!-- /.row -->
</section>
{% endblock %}
{% endblock %}
{% block extrascripts %}
<script>
// set up user data table
@ -101,10 +101,10 @@
$(document.body).on('click', '.button_revoke', function() {
var modal = $("#modal_revoke");
var username = $(this).prop('id');
var info = "Are you sure you want to revoke all privileges for " + username + ". They will not able to access any domain.";
var info = "Are you sure you want to revoke all privileges for " + username + ". They will not able to access any domain.";
modal.find('.modal-body p').text(info);
modal.find('#button_revoke_confirm').click(function() {
var postdata = {'action': 'revoke_user_privileges', 'data': username}
var postdata = {'action': 'revoke_user_privileges', 'data': username, '_csrf_token': '{{ csrf_token() }}'}
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser');
modal.modal('hide');
})
@ -114,15 +114,15 @@
$(document.body).on('click', '.button_delete', function() {
var modal = $("#modal_delete");
var username = $(this).prop('id');
var info = "Are you sure you want to delete " + username + "?";
var info = "Are you sure you want to delete " + username + "?";
modal.find('.modal-body p').text(info);
modal.find('#button_delete_confirm').click(function() {
var postdata = {'action': 'delete_user', 'data': username}
var postdata = {'action': 'delete_user', 'data': username, '_csrf_token': '{{ csrf_token() }}'}
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser', false, true);
modal.modal('hide');
})
modal.modal('show');
});
// handle user role changing
@ -134,7 +134,8 @@
'data' : {
'username' : username,
'role_name' : role_name
}
},
'_csrf_token' : '{{ csrf_token() }}'
};
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser', showResult=true);
});

View File

@ -57,6 +57,7 @@
<div class="tab-content">
<div class="tab-pane active" id="tabs-general">
<form role="form" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="general" name="config_tab" />
<div class="form-group">
<input type="checkbox" id="local_db_enabled" name="local_db_enabled" class="checkbox" {% if SETTING.get('local_db_enabled') %}checked{% endif %}>
@ -75,6 +76,7 @@
<div class="row">
<div class="col-md-4">
<form role="form" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="ldap" name="config_tab" />
<fieldset>
<legend>GENERAL</legend>
@ -246,6 +248,7 @@
<div class="row">
<div class="col-md-4">
<form role="form" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="google" name="config_tab" />
<fieldset>
<legend>GENERAL</legend>
@ -303,6 +306,7 @@
<div class="row">
<div class="col-md-4">
<form role="form" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="github" name="config_tab" />
<fieldset>
<legend>GENERAL</legend>
@ -353,12 +357,13 @@
<legend>Help</legend>
<p>Fill in all the fields in the left form.</p>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="tabs-oidc">
<div class="row">
<div class="col-md-4">
<form role="form" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="oidc" name="config_tab" />
<fieldset>
<legend>GENERAL</legend>

View File

@ -63,7 +63,7 @@
</div>
<!-- /.row -->
</section>
{% endblock %}
{% endblock %}
{% block extrascripts %}
<script>
// set up history data table
@ -77,14 +77,14 @@
});
$(document.body).on('click', '.setting-toggle-button', function() {
var setting = $(this).prop('id');
applyChanges('', $SCRIPT_ROOT + '/admin/setting/basic/' + setting + '/toggle', false, true)
applyChanges({'_csrf_token': '{{ csrf_token() }}'}, $SCRIPT_ROOT + '/admin/setting/basic/' + setting + '/toggle', false, true)
});
$(document.body).on('click', '.setting-save-button', function() {
var setting = $(this).prop('id');
var value = $(this).parents('tr').find('#value')[0].value;
var postdata = {'value': value};
var postdata = {'value': value, '_csrf_token': '{{ csrf_token() }}'};
applyChanges(postdata, $SCRIPT_ROOT + '/admin/setting/basic/' + setting + '/edit', false, true)
});
</script>
{% endblock %}
{% endblock %}

View File

@ -26,6 +26,7 @@
<!-- /.box-header -->
<!-- form start -->
<form role="form" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="box-body">
{% if not SETTING.get('pdns_api_url') or not SETTING.get('pdns_api_key') or not SETTING.get('pdns_version') %}
<div class="alert alert-danger alert-dismissible">
@ -82,4 +83,4 @@
{% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %}
{% endblock %}
{% endblock %}

View File

@ -26,6 +26,7 @@
<!-- /.box-header -->
<!-- form start -->
<form role="form" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="create" value="{{ create }}">
<div class="box-body">
<table class="table table-bordered">
@ -75,4 +76,4 @@
increaseArea : '20%'
})
</script>
{% endblock %}
{% endblock %}

View File

@ -220,9 +220,9 @@
<input type=\"text\" class=\"form-control\" name=\"template_description\" id=\"template_description\" placeholder=\"Enter a template description (optional)\"> \
<input id=\"domain\" name=\"domain\" type=\"hidden\" value=\""+domain+"\"> \
";
modal.find('.modal-body p').html(form);
modal.find('#button_save').click(function() {
var data = {};
modal.find('.modal-body p').html(form);
modal.find('#button_save').click(function() {
var data = {'_csrf_token': '{{ csrf_token() }}'};
data['name'] = modal.find('#template_name').val();
data['description'] = modal.find('#template_description').val();
data['domain'] = modal.find('#domain').val();
@ -232,7 +232,7 @@
modal.find('#button_close').click(function() {
modal.modal('hide');
})
modal.modal('show');
});
@ -244,13 +244,13 @@
$(document.body).on("click", ".button_dnssec_enable", function() {
var domain = $(this).prop('id');
enable_dns_sec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec/enable');
enable_dns_sec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec/enable', '{{ csrf_token() }}');
});
$(document.body).on("click", ".button_dnssec_disable", function() {
var domain = $(this).prop('id');
enable_dns_sec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec/disable');
enable_dns_sec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec/disable', '{{ csrf_token() }}');
});
{% endif %}

View File

@ -203,13 +203,13 @@
var modal = $("#modal_apply_changes");
var table = $("#tbl_records").DataTable();
var domain = $(this).prop('id');
var serial = $(".button_apply_changes").val();
var serial = $(".button_apply_changes").val();
var info = "Are you sure you want to apply your changes?";
modal.find('.modal-body p').text(info);
// following unbind("click") is to avoid multiple times execution
modal.find('#button_apply_confirm').unbind("click").click(function() {
var data = {'serial': serial, 'record': getTableData(table)};
var data = {'serial': serial, 'record': getTableData(table), '_csrf_token': '{{ csrf_token() }}'};
applyRecordChanges(data, domain);
modal.modal('hide');
})
@ -263,7 +263,7 @@
//handle update_from_master button
$(document.body).on("click", ".button_update_from_master", function (e) {
var domain = $(this).prop('id');
applyChanges({'domain': domain}, $SCRIPT_ROOT + '/domain/' + domain + '/update');
applyChanges({'domain': domain, '_csrf_token': '{{ csrf_token() }}'}, $SCRIPT_ROOT + '/domain/' + domain + '/update');
});
{% if SETTING.get('record_helper') %}

View File

@ -28,6 +28,7 @@
<!-- /.box-header -->
<!-- form start -->
<form role="form" method="post" action="{{ url_for('domain_add') }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="box-body">
<div class="form-group">
<input type="text" class="form-control" name="domain_name" id="domain_name" placeholder="Enter a valid domain name (required)">

View File

@ -35,6 +35,7 @@
<div class="col-xs-12">
<div class="box">
<form method="post" action="{{ url_for('domain_management', domain_name=domain.name) }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="box-header">
<h3 class="box-title">Domain Access Control</h3>
</div>
@ -81,6 +82,7 @@
<div class="col-xs-12">
<div class="form-group">
<form method="post" action="{{ url_for('domain_change_account', domain_name=domain.name) }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<select name="accountid" class="form-control" style="width:15em;">
<option value="0">- No Account -</option>
{% for account in accounts %}
@ -108,7 +110,6 @@
{% for setting in domain.settings %}{% if setting.setting=='auto_ptr' and setting.value=='True' %}checked{% endif %}{% endfor %} {% if SETTING.get('auto_ptr') %}disabled="True"{% endif %}>
&nbsp;Allow automatic reverse pointer creation on record updates?{% if
SETTING.get('auto_ptr') %}</br><code>Auto-ptr is enabled globally on the PDA system!</code>{% endif %}</p>
</div>
</div>
</div>
@ -123,7 +124,6 @@
<p><input type="checkbox" id="{{ domain.name }}" class="dyndns_on_demand_toggle"
{% for setting in domain.settings %}{% if setting.setting=='create_via_dyndns' and setting.value=='True' %}checked{% endif %}{% endfor %}>
&nbsp;Allow on-demand creation of records via DynDNS updates?</p>
</div>
</div>
</div>
@ -152,6 +152,7 @@
</ul>
<b>New SOA-EDIT-API Setting:</b>
<form method="post" action="{{ url_for('domain_change_soa_edit_api', domain_name=domain.name) }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<select name="soa_edit_api" class="form-control" style="width:15em;">
<option selected value="0">- Unchanged -</option>
<option>DEFAULT</option>
@ -207,7 +208,8 @@ $('.dyndns_on_demand_toggle').on('ifToggled', function(event) {
'data' : {
'setting' : 'create_via_dyndns',
'value' : is_checked
}
},
'_csrf_token': '{{ csrf_token() }}'
};
applyChanges(postdata, $SCRIPT_ROOT + '/domain/' + domain + '/managesetting', true);
});
@ -219,7 +221,8 @@ $('.auto_ptr_toggle').on('ifToggled', function(event) {
'data' : {
'setting' : 'auto_ptr',
'value' : is_checked
}
},
'_csrf_token': '{{ csrf_token() }}'
};
applyChanges(postdata, $SCRIPT_ROOT + '/domain/' + domain + '/managesetting', true);
});
@ -231,13 +234,13 @@ $(document.body).on('click', '.delete_domain', function() {
var info = "Are you sure you want to delete " + domain + "?";
modal.find('.modal-body p').text(info);
modal.find('#button_delete_confirm').click(function() {
$.get($SCRIPT_ROOT + '/admin/domain/' + domain + '/delete', function() {
$.post($SCRIPT_ROOT + '/admin/domain/' + domain + '/delete', { '_csrf_token': '{{ csrf_token() }}' }, function() {
window.location.href = '{{ url_for('dashboard') }}';
});
modal.modal('hide');
})
modal.modal('show');
});
</script>
{% endblock %}

View File

@ -32,6 +32,7 @@
</div>
{% endif %}
<form action="" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<input type="text" class="form-control" placeholder="Username" name="username" data-error="Please input your username" required {% if username %}value="{{ username }}"{% endif %}>
<span class="help-block with-errors"></span>

View File

@ -32,6 +32,7 @@
{% endif %}
<p class="login-box-msg">Enter your personal details below</p>
<form action="{{ url_for('login') }}" method="post" data-toggle="validator">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group has-feedback">
<input type="text" class="form-control" placeholder="First Name" name="firstname" data-error="Please input your first name" required>
<span class="glyphicon glyphicon-user form-control-feedback"></span>

View File

@ -79,11 +79,9 @@
Edit&nbsp;<i class="fa fa-edit"></i>
</button>
</a>
<a href="{{ url_for('delete_template', template=template.name) }}">
<button type="button" class="btn btn-flat btn-danger button_delete" id="btn_delete">
Delete&nbsp;<i class="fa fa-trash"></i>
</button>
</a>
<button type="button" class="btn btn-flat btn-danger button_delete" id="{{template.name}}">
Delete&nbsp;<i class="fa fa-trash"></i>
</button>
</td>
</tr>
{% endfor %}
@ -111,6 +109,15 @@
"info" : false,
"autoWidth" : false
});
// handle delete button
$(document.body).on("click", ".button_delete", function(e) {
var template = $(this).prop('id');
$.post($SCRIPT_ROOT + '/template/' + template + '/delete', { '_csrf_token': '{{ csrf_token() }}' }, function() {
window.location.href = '{{ url_for('templates') }}';
});
});
</script>
{% endblock %}
{% block modals %}

View File

@ -50,6 +50,7 @@ if errors %}
<!-- form start -->
<form role="form" method="post"
action="{{ url_for('create_template') }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="box-body">
<div class="form-group">
<input type="text" class="form-control" name="name" id="name"

View File

@ -195,7 +195,7 @@
// following unbind("click") is to avoid multiple times execution
modal.find('#button_apply_confirm').unbind("click").click(function() {
var data = getTableData(table);
applyChanges(data, '/template/' + template + '/apply', true);
applyChanges( {'_csrf_token': '{{ csrf_token() }}', 'records': data}, '/template/' + template + '/apply', true);
modal.modal('hide');
})
modal.modal('show');

View File

@ -39,6 +39,7 @@
<div class="tab-content">
<div class="tab-pane active" id="tabs-personal">
<form role="form" method="post" action="{{ user_profile }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<label for="firstname">First Name</label> <input type="text"
class="form-control" name="firstname" id="firstname"
@ -62,6 +63,7 @@
<div class="tab-pane" id="tabs-avatar">
<form action="{{ user_profile }}" method="post"
enctype="multipart/form-data">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<div class="form-group">
<div class="thumbnail" style="width: 200px; height: 210px;">
@ -95,6 +97,7 @@
Your account password is managed via LDAP which isn't supported to change here.
{% else %}
<form action="{{ user_profile }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<label for="password">New Password</label> <input
type="password" class="form-control" name="password" id="newpassword"/>
@ -113,6 +116,7 @@
<!-- {% if session['authentication_type'] in ['LOCAL', 'LDAP'] %} -->
<div class="tab-pane" id="tabs-authentication">
<form action="{{ user_profile }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<div class="form-group">
<input type="checkbox" id="otp_toggle" class="otp_toggle" {% if current_user.otp_secret %}checked{% endif %}>
<label for="otp_toggle">Enable Two Factor Authentication</label>
@ -165,7 +169,8 @@
'action' : 'enable_otp',
'data' : {
'enable_otp' : enable_otp
}
},
'_csrf_token': '{{ csrf_token() }}'
};
applyChanges(postdata, $SCRIPT_ROOT + '/user/profile', false, true);
});

View File

@ -18,7 +18,7 @@ from flask_login import login_user, logout_user, current_user, login_required
from werkzeug import secure_filename
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, csrf
from app.lib import utils
from app.oauth import github_oauth, google_oauth, oidc_oauth
from app.decorators import admin_role_required, operator_role_required, can_access_domain, can_configure_dnssec, can_create_domain
@ -184,7 +184,6 @@ def oidc_login():
else:
redirect_uri = url_for('oidc_authorized', _external=True)
return oidc.authorize_redirect(redirect_uri)
@app.route('/saml/login')
def saml_login():
@ -215,6 +214,7 @@ def saml_metadata():
@app.route('/saml/authorized', methods=['GET', 'POST'])
@csrf.exempt
def saml_authorized():
errors = []
if not app.config.get('SAML_ENABLED'):
@ -710,7 +710,7 @@ def domain_add():
return render_template('domain_add.html', templates=templates, accounts=accounts)
@app.route('/admin/domain/<path:domain_name>/delete', methods=['GET'])
@app.route('/admin/domain/<path:domain_name>/delete', methods=['POST'])
@login_required
@operator_role_required
def domain_delete(domain_name):
@ -864,22 +864,6 @@ def record_update(domain_name):
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'])
@login_required
@operator_role_required
def record_delete(domain_name, record_name, record_type):
try:
r = Record(name=record_name, type=record_type)
result = r.delete(domain=domain_name)
if result['status'] == 'error':
print(result['msg'])
except Exception as e:
logging.error('Cannot delete record. Error: {0}'.format(e))
logging.debug(traceback.format_exc())
return redirect(url_for('error', code=500)), 500
return redirect(url_for('domain', domain_name=domain_name))
@app.route('/domain/<path:domain_name>/info', methods=['GET'])
@login_required
@can_access_domain
@ -898,7 +882,7 @@ def domain_dnssec(domain_name):
return make_response(jsonify(dnssec), 200)
@app.route('/domain/<path:domain_name>/dnssec/enable', methods=['GET'])
@app.route('/domain/<path:domain_name>/dnssec/enable', methods=['POST'])
@login_required
@can_access_domain
@can_configure_dnssec
@ -908,7 +892,7 @@ def domain_dnssec_enable(domain_name):
return make_response(jsonify(dnssec), 200)
@app.route('/domain/<path:domain_name>/dnssec/disable', methods=['GET'])
@app.route('/domain/<path:domain_name>/dnssec/disable', methods=['POST'])
@login_required
@can_access_domain
@can_configure_dnssec
@ -1097,7 +1081,7 @@ def apply_records(template):
jdata = request.json
records = []
for j in jdata:
for j in jdata['records']:
name = '@' if j['record_name'] in ['@', ''] else j['record_name']
type = j['record_type']
data = j['record_data']
@ -1121,7 +1105,7 @@ def apply_records(template):
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=['POST'])
@login_required
@operator_role_required
def delete_template(template):
@ -1418,7 +1402,7 @@ def admin_setting_basic():
'allow_user_create_domain',
'bg_domain_updates',
'site_name',
'session_timeout' ]
'session_timeout' ]
return render_template('admin_setting_basic.html', settings=settings)
@ -1638,6 +1622,7 @@ def qrcode():
@app.route('/nic/checkip.html', methods=['GET', 'POST'])
@csrf.exempt
def dyndns_checkip():
# route covers the default ddclient 'web' setting for the checkip service
return render_template('dyndns.html', response=request.environ.get('HTTP_X_REAL_IP', request.remote_addr))
@ -1645,6 +1630,7 @@ def dyndns_checkip():
@app.route('/nic/update', methods=['GET', 'POST'])
@dyndns_login_required
@csrf.exempt
def dyndns_update():
# dyndns protocol response codes in use are:
# good: update successful

View File

@ -2,7 +2,6 @@ import os
basedir = os.path.abspath(os.path.dirname(__file__))
# BASIC APP CONFIG
WTF_CSRF_ENABLED = True
SECRET_KEY = 'We are the world'
BIND_ADDRESS = '127.0.0.1'
PORT = 9191

View File

@ -2,7 +2,6 @@ import os
basedir = os.path.abspath(os.path.dirname(__file__))
# BASIC APP CONFIG
WTF_CSRF_ENABLED = True
SECRET_KEY = 'changeme'
LOG_LEVEL = 'DEBUG'
LOG_FILE = 'logs/log.txt'

View File

@ -19,3 +19,4 @@ pytz>=2017.3
cssmin==0.2.0
jsmin==2.2.2
Authlib==0.10
Flask-Seasurf