Added KnockoutJS NPM package.

Re-formatted and re-organized settings model.

Working on Knockout model integration into existing authentication settings editor view.
This commit is contained in:
Matt Scott 2023-04-09 10:11:00 -04:00
parent ece9626212
commit 737e104912
No known key found for this signature in database
GPG Key ID: A9A0AFFC0E079001
7 changed files with 541 additions and 268 deletions

View File

@ -12,6 +12,7 @@
"jquery-ui-dist": "^1.13.2",
"jquery.quicksearch": "^2.4.0",
"jtimeout": "^3.2.0",
"knockout": "^3.5.1",
"multiselect": "^0.9.12"
},
"resolutions": {

View File

@ -20,6 +20,7 @@ js_login = Bundle(
'node_modules/jquery/dist/jquery.js',
'node_modules/bootstrap/dist/js/bootstrap.js',
'node_modules/icheck/icheck.js',
'node_modules/knockout/build/output/knockout-latest.js',
'custom/js/custom.js',
filters=(ConcatFilter, 'rjsmin'),
output='generated/login.js')
@ -55,6 +56,7 @@ js_main = Bundle(
'node_modules/datatables.net-plugins/sorting/natural.js',
'node_modules/jtimeout/src/jTimeout.js',
'node_modules/jquery.quicksearch/src/jquery.quicksearch.js',
'node_modules/knockout/build/output/knockout-latest.js',
'custom/js/custom.js',
'node_modules/bootstrap-datepicker/dist/js/bootstrap-datepicker.js',
filters=(ConcatFilter, 'rjsmin'),

View File

@ -15,6 +15,7 @@ class Setting(db.Model):
value = db.Column(db.Text())
defaults = {
# General Settings
'maintenance': False,
'fullscreen_layout': True,
'record_helper': True,
@ -42,56 +43,79 @@ class Setting(db.Model):
'pdns_api_timeout': 30,
'pdns_version': '4.1.1',
'verify_ssl_connections': True,
'verify_user_email': False,
'enforce_api_ttl': False,
'ttl_options': '1 minute,5 minutes,30 minutes,60 minutes,24 hours',
'otp_field_enabled': True,
'custom_css': '',
'otp_force': False,
'max_history_records': 1000,
'deny_domain_override': False,
'account_name_extra_chars': False,
'gravatar_enabled': False,
# Local Authentication Settings
'local_db_enabled': True,
'signup_enabled': True,
'autoprovisioning': False,
'urn_value': '',
'autoprovisioning_attribute': '',
'purge': False,
'verify_user_email': False,
'pwd_enforce_characters': False,
'pwd_min_len': 10,
'pwd_min_lowercase': 3,
'pwd_min_uppercase': 2,
'pwd_min_digits': 2,
'pwd_min_special': 1,
'pwd_enforce_complexity': False,
'pwd_min_complexity': 11,
# LDAP Authentication Settings
'ldap_enabled': False,
'ldap_type': 'ldap',
'ldap_uri': '',
'ldap_base_dn': '',
'ldap_admin_username': '',
'ldap_admin_password': '',
'ldap_domain': '',
'ldap_filter_basic': '',
'ldap_filter_group': '',
'ldap_filter_username': '',
'ldap_filter_group': '',
'ldap_filter_groupname': '',
'ldap_sg_enabled': False,
'ldap_admin_group': '',
'ldap_operator_group': '',
'ldap_user_group': '',
'ldap_domain': '',
'autoprovisioning': False,
'autoprovisioning_attribute': '',
'urn_value': '',
'purge': False,
# Google OAuth2 Settings
'google_oauth_enabled': False,
'google_oauth_client_id': '',
'google_oauth_client_secret': '',
'google_oauth_scope': 'openid email profile',
'google_base_url': 'https://www.googleapis.com/oauth2/v3/',
'google_oauth_metadata_url': 'https://accounts.google.com/.well-known/openid-configuration',
'google_token_url': 'https://oauth2.googleapis.com/token',
'google_authorize_url': 'https://accounts.google.com/o/oauth2/v2/auth',
# GitHub OAuth2 Settings
'github_oauth_enabled': False,
'github_oauth_key': '',
'github_oauth_secret': '',
'github_oauth_scope': 'email',
'github_oauth_api_url': 'https://api.github.com/user',
'github_oauth_token_url':
'https://github.com/login/oauth/access_token',
'github_oauth_authorize_url':
'https://github.com/login/oauth/authorize',
'github_oauth_metadata_url': '',
'google_oauth_enabled': False,
'google_oauth_client_id': '',
'google_oauth_client_secret': '',
'google_token_url': 'https://oauth2.googleapis.com/token',
'google_oauth_scope': 'openid email profile',
'google_authorize_url': 'https://accounts.google.com/o/oauth2/v2/auth',
'google_oauth_metadata_url': '',
'google_base_url': 'https://www.googleapis.com/oauth2/v3/',
'github_oauth_token_url': 'https://github.com/login/oauth/access_token',
'github_oauth_authorize_url': 'https://github.com/login/oauth/authorize',
# Azure OAuth2 Settings
'azure_oauth_enabled': False,
'azure_oauth_key': '',
'azure_oauth_secret': '',
'azure_oauth_scope': 'User.Read openid email profile',
'azure_oauth_api_url': 'https://graph.microsoft.com/v1.0/',
'azure_oauth_token_url':
'https://login.microsoftonline.com/[tenancy]/oauth2/v2.0/token',
'azure_oauth_authorize_url':
'https://login.microsoftonline.com/[tenancy]/oauth2/v2.0/authorize',
'azure_oauth_metadata_url': '',
'azure_oauth_token_url': '',
'azure_oauth_authorize_url': '',
'azure_sg_enabled': False,
'azure_admin_group': '',
'azure_operator_group': '',
@ -101,22 +125,25 @@ class Setting(db.Model):
'azure_group_accounts_name_re': '',
'azure_group_accounts_description': 'description',
'azure_group_accounts_description_re': '',
# OIDC OAuth2 Settings
'oidc_oauth_enabled': False,
'oidc_oauth_key': '',
'oidc_oauth_secret': '',
'oidc_oauth_scope': 'email',
'oidc_oauth_api_url': '',
'oidc_oauth_metadata_url': '',
'oidc_oauth_token_url': '',
'oidc_oauth_authorize_url': '',
'oidc_oauth_metadata_url': '',
'oidc_oauth_logout_url': '',
'oidc_oauth_username': 'preferred_username',
'oidc_oauth_email': 'email',
'oidc_oauth_firstname': 'given_name',
'oidc_oauth_last_name': 'family_name',
'oidc_oauth_email': 'email',
'oidc_oauth_account_name_property': '',
'oidc_oauth_account_description_property': '',
'enforce_api_ttl': False,
# Zone Record Settings
'forward_records_allow_edit': {
'A': True,
'AAAA': True,
@ -193,22 +220,6 @@ class Setting(db.Model):
'TXT': True,
'URI': False
},
'ttl_options': '1 minute,5 minutes,30 minutes,60 minutes,24 hours',
'otp_field_enabled': True,
'custom_css': '',
'otp_force': False,
'max_history_records': 1000,
'deny_domain_override': False,
'account_name_extra_chars': False,
'gravatar_enabled': False,
'pwd_enforce_characters': False,
'pwd_min_len': 10,
'pwd_min_lowercase': 3,
'pwd_min_uppercase': 2,
'pwd_min_digits': 2,
'pwd_min_special': 1,
'pwd_enforce_complexity': False,
'pwd_min_complexity': 11
}
def __init__(self, id=None, name=None, value=None):

View File

@ -72,8 +72,8 @@ def get_record_changes(del_rrset, add_rrset):
"""For the given record, return the state dict."""
return {
"disabled": record['disabled'],
"content": record['content'],
"comment": record.get('comment', ''),
"content": record['content'],
"comment": record.get('comment', ''),
}
add_records = get_records(add_rrset)
@ -149,8 +149,8 @@ def extract_changelogs_from_a_history_entry(out_changes, history_entry, change_n
# Sort them by the record name
if change_num in out_changes:
out_changes[change_num].sort(key=lambda change:
change.del_rrset['name'] if change.del_rrset else change.add_rrset['name']
)
change.del_rrset['name'] if change.del_rrset else change.add_rrset['name']
)
# only used for changelog per record
if record_name != None and record_type != None: # then get only the records with the specific (record_name, record_type) tuple
@ -897,7 +897,8 @@ class DetailedHistory():
description=DetailedHistory.get_key_val(detail_dict,
"description"))
elif any(msg in history.msg for msg in ['Change zone','Change domain']) and 'access control' in history.msg: # added or removed a user from a zone
elif any(msg in history.msg for msg in ['Change zone',
'Change domain']) and 'access control' in history.msg: # added or removed a user from a zone
users_with_access = DetailedHistory.get_key_val(detail_dict, "user_has_access")
self.detailed_msg = render_template_string("""
<table class="table table-bordered table-striped">
@ -942,7 +943,7 @@ class DetailedHistory():
linked_domains=DetailedHistory.get_key_val(detail_dict,
"domains"))
elif any(msg in history.msg for msg in ['Update type for zone','Update type for domain']):
elif any(msg in history.msg for msg in ['Update type for zone', 'Update type for domain']):
self.detailed_msg = render_template_string("""
<table class="table table-bordered table-striped">
<tr><td>Zone: </td><td>{{ domain }}</td></tr>
@ -977,7 +978,8 @@ class DetailedHistory():
'status'),
history_msg=DetailedHistory.get_key_val(detail_dict, 'msg'))
elif any(msg in history.msg for msg in ['Update zone','Update domain']) and 'associate account' in history.msg: # When an account gets associated or dissociate with zones
elif any(msg in history.msg for msg in ['Update zone',
'Update domain']) and 'associate account' in history.msg: # When an account gets associated or dissociate with zones
self.detailed_msg = render_template_string('''
<table class="table table-bordered table-striped">
<tr><td>Associate: </td><td>{{ history_assoc_account }}</td></tr>
@ -1231,8 +1233,10 @@ def history_table(): # ajax call data
.filter(
db.and_(
db.or_(
History.msg.like("%domain " + domain_name) if domain_name != "*" else History.msg.like("%domain%"),
History.msg.like("%zone " + domain_name) if domain_name != "*" else History.msg.like("%zone%"),
History.msg.like("%domain " + domain_name) if domain_name != "*" else History.msg.like(
"%domain%"),
History.msg.like("%zone " + domain_name) if domain_name != "*" else History.msg.like(
"%zone%"),
History.msg.like(
"%domain " + domain_name + " access control") if domain_name != "*" else History.msg.like(
"%domain%access control"),
@ -1540,7 +1544,8 @@ def has_an_auth_method(local_db_enabled=None,
oidc_oauth_enabled = Setting().get('oidc_oauth_enabled')
if azure_oauth_enabled is None:
azure_oauth_enabled = Setting().get('azure_oauth_enabled')
return local_db_enabled or ldap_enabled or google_oauth_enabled or github_oauth_enabled or oidc_oauth_enabled or azure_oauth_enabled
return local_db_enabled or ldap_enabled or google_oauth_enabled or github_oauth_enabled or oidc_oauth_enabled \
or azure_oauth_enabled
@admin_bp.route('/setting/authentication', methods=['GET', 'POST'])
@ -1562,17 +1567,20 @@ def setting_authentication():
pwd_enforce_characters = True if request.form.get('pwd_enforce_characters') else False
pwd_min_len = safe_cast(request.form.get('pwd_min_len', Setting().defaults["pwd_min_len"]), int,
Setting().defaults["pwd_min_len"])
pwd_min_lowercase = safe_cast(request.form.get('pwd_min_lowercase', Setting().defaults["pwd_min_lowercase"]), int,
Setting().defaults["pwd_min_lowercase"])
pwd_min_uppercase = safe_cast(request.form.get('pwd_min_uppercase', Setting().defaults["pwd_min_uppercase"]), int,
Setting().defaults["pwd_min_uppercase"])
pwd_min_lowercase = safe_cast(
request.form.get('pwd_min_lowercase', Setting().defaults["pwd_min_lowercase"]), int,
Setting().defaults["pwd_min_lowercase"])
pwd_min_uppercase = safe_cast(
request.form.get('pwd_min_uppercase', Setting().defaults["pwd_min_uppercase"]), int,
Setting().defaults["pwd_min_uppercase"])
pwd_min_digits = safe_cast(request.form.get('pwd_min_digits', Setting().defaults["pwd_min_digits"]), int,
Setting().defaults["pwd_min_digits"])
pwd_min_special = safe_cast(request.form.get('pwd_min_special', Setting().defaults["pwd_min_special"]), int,
Setting().defaults["pwd_min_special"])
pwd_enforce_complexity = True if request.form.get('pwd_enforce_complexity') else False
pwd_min_complexity = safe_cast(request.form.get('pwd_min_complexity', Setting().defaults["pwd_min_complexity"]), int,
pwd_min_complexity = safe_cast(request.form.get('pwd_min_complexity',
Setting().defaults["pwd_min_complexity"]), int,
Setting().defaults["pwd_min_complexity"])
if not has_an_auth_method(local_db_enabled=local_db_enabled):
@ -1585,14 +1593,12 @@ def setting_authentication():
else:
Setting().set('local_db_enabled', local_db_enabled)
Setting().set('signup_enabled', signup_enabled)
Setting().set('pwd_enforce_characters', pwd_enforce_characters)
Setting().set('pwd_min_len', pwd_min_len)
Setting().set('pwd_min_lowercase', pwd_min_lowercase)
Setting().set('pwd_min_uppercase', pwd_min_uppercase)
Setting().set('pwd_min_digits', pwd_min_digits)
Setting().set('pwd_min_special', pwd_min_special)
Setting().set('pwd_enforce_complexity', pwd_enforce_complexity)
Setting().set('pwd_min_complexity', pwd_min_complexity)
@ -2097,16 +2103,16 @@ def global_search():
results = server.global_search(object_type='all', query=query)
# Filter results to domains to which the user has access permission
if current_user.role.name not in [ 'Administrator', 'Operator' ]:
if current_user.role.name not in ['Administrator', 'Operator']:
allowed_domains = db.session.query(Domain) \
.outerjoin(DomainUser, Domain.id == DomainUser.domain_id) \
.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
)) \
db.or_(
DomainUser.user_id == current_user.id,
AccountUser.user_id == current_user.id
)) \
.with_entities(Domain.name) \
.all()
allowed_domains = [value for value, in allowed_domains]

View File

@ -0,0 +1,273 @@
let model;
let AuthenticationSettingsModel = function (user_data, csrf_token, selector) {
let self = this;
let defaults = {
tab_active: '',
tab_default: 'local',
// Local Authentication Settings
local_db_enabled: true,
signup_enabled: true,
pwd_enforce_characters: false,
pwd_min_len: 10,
pwd_min_lowercase: 3,
pwd_min_uppercase: 2,
pwd_min_digits: 2,
pwd_min_special: 1,
pwd_enforce_complexity: false,
pwd_min_complexity: 11,
// LDAP Authentication Settings
ldap_enabled: false,
ldap_type: 'ldap',
ldap_uri: '',
ldap_base_dn: '',
ldap_admin_username: '',
ldap_admin_password: '',
ldap_domain: '',
ldap_filter_basic: '',
ldap_filter_username: '',
ldap_filter_group: '',
ldap_filter_groupname: '',
ldap_sg_enabled: false,
ldap_admin_group: '',
ldap_operator_group: '',
ldap_user_group: '',
autoprovisioning: false,
autoprovisioning_attribute: '',
urn_value: '',
purge: false,
// Google OAuth2 Settings
google_oauth_enabled: false,
google_oauth_client_id: '',
google_oauth_client_secret: '',
google_oauth_scope: '',
google_base_url: '',
google_oauth_auto_configure: false,
google_oauth_metadata_url: '',
google_token_url: '',
google_authorize_url: '',
// GitHub OAuth2 Settings
github_oauth_enabled: false,
github_oauth_key: '',
github_oauth_secret: '',
github_oauth_scope: '',
github_oauth_api_url: '',
github_oauth_auto_configure: false,
github_oauth_metadata_url: '',
github_oauth_token_url: '',
github_oauth_authorize_url: '',
// Azure AD OAuth2 Settings
azure_oauth_enabled: false,
azure_oauth_key: '',
azure_oauth_secret: '',
azure_oauth_scope: '',
azure_oauth_api_url: '',
azure_oauth_auto_configure: false,
azure_oauth_metadata_url: '',
azure_oauth_token_url: '',
azure_oauth_authorize_url: '',
azure_sg_enabled: false,
azure_admin_group: '',
azure_operator_group: '',
azure_user_group: '',
azure_group_accounts_enabled: false,
azure_group_accounts_name: '',
azure_group_accounts_name_re: '',
azure_group_accounts_description: '',
azure_group_accounts_description_re: '',
// OIDC OAuth2 Settings
oidc_oauth_enabled: false,
oidc_oauth_key: '',
oidc_oauth_secret: '',
oidc_oauth_scope: '',
oidc_oauth_api_url: '',
oidc_oauth_auto_configure: false,
oidc_oauth_metadata_url: '',
oidc_oauth_token_url: '',
oidc_oauth_authorize_url: '',
oidc_oauth_logout_url: '',
oidc_oauth_username: '',
oidc_oauth_email: '',
oidc_oauth_firstname: '',
oidc_oauth_last_name: '',
oidc_oauth_account_name_property: '',
oidc_oauth_account_description_property: '',
}
self.data = {};
self.setupObservables = function () {
self.tab_active = ko.observable(self.data.tab_active);
self.tab_default = ko.observable(self.data.tab_default);
// Local Authentication Settings
self.local_db_enabled = ko.observable(self.data.local_db_enabled);
self.signup_enabled = ko.observable(self.data.signup_enabled);
self.pwd_enforce_characters = ko.observable(self.data.pwd_enforce_characters);
self.pwd_min_len = ko.observable(self.data.pwd_min_len);
self.pwd_min_lowercase = ko.observable(self.data.pwd_min_lowercase);
self.pwd_min_uppercase = ko.observable(self.data.pwd_min_uppercase);
self.pwd_min_digits = ko.observable(self.data.pwd_min_digits);
self.pwd_min_special = ko.observable(self.data.pwd_min_special);
self.pwd_enforce_complexity = ko.observable(self.data.pwd_enforce_complexity);
self.pwd_min_complexity = ko.observable(self.data.pwd_min_complexity);
// LDAP Authentication Settings
self.ldap_enabled = ko.observable(self.data.ldap_enabled);
self.ldap_type = ko.observable(self.data.ldap_type);
self.ldap_uri = ko.observable(self.data.ldap_uri);
self.ldap_base_dn = ko.observable(self.data.ldap_base_dn);
self.ldap_admin_username = ko.observable(self.data.ldap_admin_username);
self.ldap_admin_password = ko.observable(self.data.ldap_admin_password);
self.ldap_domain = ko.observable(self.data.ldap_domain);
self.ldap_filter_basic = ko.observable(self.data.ldap_filter_basic);
self.ldap_filter_username = ko.observable(self.data.ldap_filter_username);
self.ldap_filter_group = ko.observable(self.data.ldap_filter_group);
self.ldap_filter_groupname = ko.observable(self.data.ldap_filter_groupname);
self.ldap_sg_enabled = ko.observable(self.data.ldap_sg_enabled);
self.ldap_admin_group = ko.observable(self.data.ldap_admin_group);
self.ldap_operator_group = ko.observable(self.data.ldap_operator_group);
self.ldap_user_group = ko.observable(self.data.ldap_user_group);
self.autoprovisioning = ko.observable(self.data.autoprovisioning);
self.autoprovisioning_attribute = ko.observable(self.data.autoprovisioning_attribute);
self.urn_value = ko.observable(self.data.urn_value);
self.purge = ko.observable(self.data.purge);
// Google OAuth2 Settings
self.google_oauth_enabled = ko.observable(self.data.google_oauth_enabled);
self.google_oauth_client_id = ko.observable(self.data.google_oauth_client_id);
self.google_oauth_client_secret = ko.observable(self.data.google_oauth_client_secret);
self.google_oauth_scope = ko.observable(self.data.google_oauth_scope);
self.google_base_url = ko.observable(self.data.google_base_url);
self.google_oauth_auto_configure = ko.observable(self.data.google_oauth_auto_configure);
self.google_oauth_metadata_url = ko.observable(self.data.google_oauth_metadata_url);
self.google_token_url = ko.observable(self.data.google_token_url);
self.google_authorize_url = ko.observable(self.data.google_authorize_url);
// GitHub OAuth2 Settings
self.github_oauth_enabled = ko.observable(self.data.github_oauth_enabled);
self.github_oauth_key = ko.observable(self.data.github_oauth_key);
self.github_oauth_secret = ko.observable(self.data.github_oauth_secret);
self.github_oauth_scope = ko.observable(self.data.github_oauth_scope);
self.github_oauth_api_url = ko.observable(self.data.github_oauth_api_url);
self.github_oauth_auto_configure = ko.observable(self.data.github_oauth_auto_configure);
self.github_oauth_metadata_url = ko.observable(self.data.github_oauth_metadata_url);
self.github_oauth_token_url = ko.observable(self.data.github_oauth_token_url);
self.github_oauth_authorize_url = ko.observable(self.data.github_oauth_authorize_url);
// Azure AD OAuth2 Settings
self.azure_oauth_enabled = ko.observable(self.data.azure_oauth_enabled);
self.azure_oauth_key = ko.observable(self.data.azure_oauth_key);
self.azure_oauth_secret = ko.observable(self.data.azure_oauth_secret);
self.azure_oauth_scope = ko.observable(self.data.azure_oauth_scope);
self.azure_oauth_api_url = ko.observable(self.data.azure_oauth_api_url);
self.azure_oauth_auto_configure = ko.observable(self.data.azure_oauth_auto_configure);
self.azure_oauth_metadata_url = ko.observable(self.data.azure_oauth_metadata_url);
self.azure_oauth_token_url = ko.observable(self.data.azure_oauth_token_url);
self.azure_oauth_authorize_url = ko.observable(self.data.azure_oauth_authorize_url);
self.azure_sg_enabled = ko.observable(self.data.azure_sg_enabled);
self.azure_admin_group = ko.observable(self.data.azure_admin_group);
self.azure_operator_group = ko.observable(self.data.azure_operator_group);
self.azure_user_group = ko.observable(self.data.azure_user_group);
self.azure_group_accounts_enabled = ko.observable(self.data.azure_group_accounts_enabled);
self.azure_group_accounts_name = ko.observable(self.data.azure_group_accounts_name);
self.azure_group_accounts_name_re = ko.observable(self.data.azure_group_accounts_name_re);
self.azure_group_accounts_description = ko.observable(self.data.azure_group_accounts_description);
self.azure_group_accounts_description_re = ko.observable(self.data.azure_group_accounts_description_re);
// OIDC OAuth2 Settings
self.oidc_oauth_enabled = ko.observable(self.data.oidc_oauth_enabled);
self.oidc_oauth_key = ko.observable(self.data.oidc_oauth_key);
self.oidc_oauth_secret = ko.observable(self.data.oidc_oauth_secret);
self.oidc_oauth_scope = ko.observable(self.data.oidc_oauth_scope);
self.oidc_oauth_api_url = ko.observable(self.data.oidc_oauth_api_url);
self.oidc_oauth_auto_configure = ko.observable(self.data.oidc_oauth_auto_configure);
self.oidc_oauth_metadata_url = ko.observable(self.data.oidc_oauth_metadata_url);
self.oidc_oauth_token_url = ko.observable(self.data.oidc_oauth_token_url);
self.oidc_oauth_authorize_url = ko.observable(self.data.oidc_oauth_authorize_url);
self.oidc_oauth_logout_url = ko.observable(self.data.oidc_oauth_logout_url);
self.oidc_oauth_username = ko.observable(self.data.oidc_oauth_username);
self.oidc_oauth_email = ko.observable(self.data.oidc_oauth_email);
self.oidc_oauth_firstname = ko.observable(self.data.oidc_oauth_firstname);
self.oidc_oauth_last_name = ko.observable(self.data.oidc_oauth_last_name);
self.oidc_oauth_account_name_property = ko.observable(self.data.oidc_oauth_account_name_property);
self.oidc_oauth_account_description_property = ko.observable(self.data.oidc_oauth_account_description_property);
}
self.updateWithDefaults = function (instance) {
self.data = $.extend(defaults, instance)
}
self.activateTab = function (tab) {
$('[role="tablist"] a.nav-link').blur();
self.tab_active(tab);
window.location.hash = tab;
}
self.activateDefaultTab = function () {
self.activateTab(self.tab_default());
}
self.initTabs = function() {
if (self.hasHash()) {
self.activateTab(self.getHash());
} else {
self.activateDefaultTab();
}
}
self.getHash = function () {
return window.location.hash.substring(1);
}
self.hasHash = function () {
return window.location.hash.length > 1;
}
self.setupListeners = function () {
if ('onhashchange' in window) {
$(window).bind('hashchange', self.onHashChange);
}
}
self.destroyListeners = function () {
if ('onhashchange' in window) {
$(window).unbind('hashchange', self.onHashChange);
}
}
self.onTabClick = function (model, event) {
self.activateTab($(event.target).data('tab'));
return false;
}
self.onHashChange = function (event) {
let hash = window.location.hash.trim();
if (hash.length > 1) {
self.activateTab(hash.substring(1));
} else {
self.activateDefaultTab();
}
}
self.updateWithDefaults(user_data);
self.setupObservables();
ko.applyBindings(self);
self.initTabs();
self.setupListeners();
}
$(function () {
// TODO: Load the data from the server and pass it to the model instantiation
loaded_data = {};
model = new AuthenticationSettingsModel(loaded_data, CSRF_TOKEN, '#settings-editor');
})

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@
resolved "https://registry.yarnpkg.com/@foliojs-fork/restructure/-/restructure-2.0.2.tgz#73759aba2aff1da87b7c4554e6839c70d43c92b4"
integrity sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==
"@fortawesome/fontawesome-free@6.3.0":
"@fortawesome/fontawesome-free@6.3.0", "@fortawesome/fontawesome-free@^5.15.4":
version "6.3.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.3.0.tgz#b5877182692a6f7a39d1108837bec24247ba4bd7"
integrity sha512-qVtd5i1Cc7cdrqnTWqTObKQHjPWAiRwjUPaXObaeNPcy7+WKxJumGBx66rfSFgK6LNpIasVKkEgW8oyf0tmPLA==
@ -1081,6 +1081,11 @@ jtimeout@^3.2.0:
dependencies:
jquery ">=1.7.1 <4.0.0"
knockout@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/knockout/-/knockout-3.5.1.tgz#62c81e81843bea2008fd23c575edd9ca978e75cf"
integrity sha512-wRJ9I4az0QcsH7A4v4l0enUpkS++MBx0BnL/68KaLzJg7x1qmbjSlwEoCNol7KTYZ+pmtI7Eh2J0Nu6/2Z5J/Q==
levn@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"