1import $ from 'jquery';
2import {checkAppUrl} from '../common-global.js';
3import {hideElem, showElem, toggleElem} from '../../utils/dom.js';
4import {POST} from '../../modules/fetch.js';
5
6const {appSubUrl} = window.config;
7
8function onSecurityProtocolChange() {
9 if (Number(document.getElementById('security_protocol')?.value) > 0) {
10 showElem('.has-tls');
11 } else {
12 hideElem('.has-tls');
13 }
14}
15
16export function initAdminCommon() {
17 if (!document.querySelector('.page-content.admin')) return;
18
19 // check whether appUrl(ROOT_URL) is correct, if not, show an error message
20 checkAppUrl();
21
22 // New user
23 if ($('.admin.new.user').length > 0 || $('.admin.edit.user').length > 0) {
24 document.getElementById('login_type')?.addEventListener('change', function () {
25 if (this.value?.substring(0, 1) === '0') {
26 document.getElementById('user_name')?.removeAttribute('disabled');
27 document.getElementById('login_name')?.removeAttribute('required');
28 hideElem('.non-local');
29 showElem('.local');
30 document.getElementById('user_name')?.focus();
31
32 if (this.getAttribute('data-password') === 'required') {
33 document.getElementById('password')?.setAttribute('required', 'required');
34 }
35 } else {
36 if (document.querySelector('.admin.edit.user')) {
37 document.getElementById('user_name')?.setAttribute('disabled', 'disabled');
38 }
39 document.getElementById('login_name')?.setAttribute('required', 'required');
40 showElem('.non-local');
41 hideElem('.local');
42 document.getElementById('login_name')?.focus();
43
44 document.getElementById('password')?.removeAttribute('required');
45 }
46 });
47 }
48
49 function onUsePagedSearchChange() {
50 const searchPageSizeElements = document.querySelectorAll('.search-page-size');
51 if (document.getElementById('use_paged_search').checked) {
52 showElem('.search-page-size');
53 for (const el of searchPageSizeElements) {
54 el.querySelector('input')?.setAttribute('required', 'required');
55 }
56 } else {
57 hideElem('.search-page-size');
58 for (const el of searchPageSizeElements) {
59 el.querySelector('input')?.removeAttribute('required');
60 }
61 }
62 }
63
64 function onOAuth2Change(applyDefaultValues) {
65 hideElem('.open_id_connect_auto_discovery_url, .oauth2_use_custom_url, .oauth2_attribute_ssh_public_key');
66 for (const input of document.querySelectorAll('.open_id_connect_auto_discovery_url input[required]')) {
67 input.removeAttribute('required');
68 }
69
70 const provider = document.getElementById('oauth2_provider')?.value;
71 switch (provider) {
72 case 'openidConnect':
73 for (const input of document.querySelectorAll('.open_id_connect_auto_discovery_url input')) {
74 input.setAttribute('required', 'required');
75 }
76 showElem('.open_id_connect_auto_discovery_url');
77 break;
78 default: {
79 const customURLSettings = document.getElementById(`${provider}_customURLSettings`);
80 if (!customURLSettings) break;
81 const customURLRequired = (customURLSettings.getAttribute('data-required') === 'true');
82 document.getElementById('oauth2_use_custom_url').checked = customURLRequired;
83 if (customURLRequired || customURLSettings.getAttribute('data-available') === 'true') {
84 showElem('.oauth2_use_custom_url');
85 }
86 }
87 }
88 const canProvideSSHKeys = document.getElementById(`${provider}_canProvideSSHKeys`);
89 if (canProvideSSHKeys) {
90 showElem('.oauth2_attribute_ssh_public_key');
91 }
92 onOAuth2UseCustomURLChange(applyDefaultValues);
93 }
94
95 function onOAuth2UseCustomURLChange(applyDefaultValues) {
96 const provider = document.getElementById('oauth2_provider')?.value;
97 hideElem('.oauth2_use_custom_url_field');
98 for (const input of document.querySelectorAll('.oauth2_use_custom_url_field input[required]')) {
99 input.removeAttribute('required');
100 }
101
102 if (document.getElementById('oauth2_use_custom_url')?.checked) {
103 for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) {
104 const customInput = document.getElementById(`${provider}_${custom}`);
105 if (!customInput) continue;
106 if (applyDefaultValues) {
107 document.getElementById(`oauth2_${custom}`).value = customInput.value;
108 }
109 if (customInput.getAttribute('data-available') === 'true') {
110 for (const input of document.querySelectorAll(`.oauth2_${custom} input`)) {
111 input.setAttribute('required', 'required');
112 }
113 showElem(`.oauth2_${custom}`);
114 }
115 }
116 }
117 }
118
119 function onEnableLdapGroupsChange() {
120 toggleElem(document.getElementById('ldap-group-options'), $('.js-ldap-group-toggle')[0].checked);
121 }
122
123 // New authentication
124 if (document.querySelector('.admin.new.authentication')) {
125 document.getElementById('auth_type')?.addEventListener('change', function () {
126 hideElem('.ldap, .dldap, .smtp, .pam, .oauth2, .has-tls, .search-page-size');
127
128 for (const input of document.querySelectorAll('.ldap input[required], .binddnrequired input[required], .dldap input[required], .smtp input[required], .pam input[required], .oauth2 input[required], .has-tls input[required]')) {
129 input.removeAttribute('required');
130 }
131
132 document.querySelector('.binddnrequired')?.classList.remove('required');
133
134 const authType = this.value;
135 switch (authType) {
136 case '2': // LDAP
137 showElem('.ldap');
138 for (const input of document.querySelectorAll('.binddnrequired input, .ldap div.required:not(.dldap) input')) {
139 input.setAttribute('required', 'required');
140 }
141 document.querySelector('.binddnrequired')?.classList.add('required');
142 break;
143 case '3': // SMTP
144 showElem('.smtp');
145 showElem('.has-tls');
146 for (const input of document.querySelectorAll('.smtp div.required input, .has-tls')) {
147 input.setAttribute('required', 'required');
148 }
149 break;
150 case '4': // PAM
151 showElem('.pam');
152 for (const input of document.querySelectorAll('.pam input')) {
153 input.setAttribute('required', 'required');
154 }
155 break;
156 case '5': // LDAP
157 showElem('.dldap');
158 for (const input of document.querySelectorAll('.dldap div.required:not(.ldap) input')) {
159 input.setAttribute('required', 'required');
160 }
161 break;
162 case '6': // OAuth2
163 showElem('.oauth2');
164 for (const input of document.querySelectorAll('.oauth2 div.required:not(.oauth2_use_custom_url,.oauth2_use_custom_url_field,.open_id_connect_auto_discovery_url) input')) {
165 input.setAttribute('required', 'required');
166 }
167 onOAuth2Change(true);
168 break;
169 }
170 if (authType === '2' || authType === '5') {
171 onSecurityProtocolChange();
172 onEnableLdapGroupsChange();
173 }
174 if (authType === '2') {
175 onUsePagedSearchChange();
176 }
177 });
178 document.getElementById('auth_type').dispatchEvent(new Event('change'));
179 document.getElementById('security_protocol')?.addEventListener('change', onSecurityProtocolChange);
180 document.getElementById('use_paged_search')?.addEventListener('change', onUsePagedSearchChange);
181 document.getElementById('oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true));
182 document.getElementById('oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true));
183 $('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange);
184 }
185 // Edit authentication
186 if (document.querySelector('.admin.edit.authentication')) {
187 const authType = document.getElementById('auth_type')?.value;
188 if (authType === '2' || authType === '5') {
189 document.getElementById('security_protocol')?.addEventListener('change', onSecurityProtocolChange);
190 $('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange);
191 onEnableLdapGroupsChange();
192 if (authType === '2') {
193 document.getElementById('use_paged_search')?.addEventListener('change', onUsePagedSearchChange);
194 }
195 } else if (authType === '6') {
196 document.getElementById('oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true));
197 document.getElementById('oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false));
198 onOAuth2Change(false);
199 }
200 }
201
202 if (document.querySelector('.admin.edit.authentication, .admin.new.authentication')) {
203 const authNameEl = document.getElementById('auth_name');
204 authNameEl.addEventListener('input', (el) => {
205 // appSubUrl is either empty or is a path that starts with `/` and doesn't have a trailing slash.
206 document.getElementById('oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent(el.target.value)}/callback`;
207 });
208 authNameEl.dispatchEvent(new Event('input'));
209 }
210
211 // Notice
212 if (document.querySelector('.admin.notice')) {
213 const detailModal = document.getElementById('detail-modal');
214
215 // Attach view detail modals
216 $('.view-detail').on('click', function () {
217 const description = this.closest('tr').querySelector('.notice-description').textContent;
218 detailModal.querySelector('.content pre').textContent = description;
219 $(detailModal).modal('show');
220 return false;
221 });
222
223 // Select actions
224 const checkboxes = document.querySelectorAll('.select.table .ui.checkbox input');
225
226 $('.select.action').on('click', function () {
227 switch ($(this).data('action')) {
228 case 'select-all':
229 for (const checkbox of checkboxes) {
230 checkbox.checked = true;
231 }
232 break;
233 case 'deselect-all':
234 for (const checkbox of checkboxes) {
235 checkbox.checked = false;
236 }
237 break;
238 case 'inverse':
239 for (const checkbox of checkboxes) {
240 checkbox.checked = !checkbox.checked;
241 }
242 break;
243 }
244 });
245 document.getElementById('delete-selection')?.addEventListener('click', async function (e) {
246 e.preventDefault();
247 this.classList.add('is-loading', 'disabled');
248 const data = new FormData();
249 for (const checkbox of checkboxes) {
250 if (checkbox.checked) {
251 data.append('ids[]', checkbox.closest('.ui.checkbox').getAttribute('data-id'));
252 }
253 }
254 await POST(this.getAttribute('data-link'), {data});
255 window.location.href = this.getAttribute('data-redirect');
256 });
257 }
258}