]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/dc/RealmSyncJob.js
ui: realm sync: add 'run now' button
[pve-manager.git] / www / manager6 / dc / RealmSyncJob.js
CommitLineData
f44ce595
DC
1Ext.define('PVE.dc.RealmSyncJobView', {
2 extend: 'Ext.grid.Panel',
3 alias: 'widget.pveRealmSyncJobView',
4
5 stateful: true,
6 stateId: 'grid-realmsyncjobs',
7
8 controller: {
9 xclass: 'Ext.app.ViewController',
10
11 addRealmSyncJob: function(button) {
12 let me = this;
13 Ext.create(`PVE.dc.RealmSyncJobEdit`, {
14 autoShow: true,
15 listeners: {
16 destroy: () => me.reload(),
17 },
18 });
19 },
20
21 editRealmSyncJob: function() {
22 let me = this;
23 let view = me.getView();
24 let selection = view.getSelection();
25 if (!selection || selection.length < 1) {
26 return;
27 }
28
29 Ext.create(`PVE.dc.RealmSyncJobEdit`, {
30 jobid: selection[0].data.id,
31 autoShow: true,
32 listeners: {
33 destroy: () => me.reload(),
34 },
35 });
36 },
37
ed65c1ca
DC
38 runNow: function() {
39 let me = this;
40 let view = me.getView();
41 let selection = view.getSelection();
42 if (!selection || selection.length < 1) {
43 return;
44 }
45
46 let params = selection[0].data;
47 let realm = params.realm;
48
49 let propertiesToDelete = ['comment', 'realm', 'id', 'type', 'schedule', 'last-run', 'next-run', 'enabled'];
50 for (const prop of propertiesToDelete) {
51 delete params[prop];
52 }
53
54 Proxmox.Utils.API2Request({
55 url: `/access/domains/${realm}/sync`,
56 params,
57 waitMsgTarget: view,
58 method: 'POST',
59 success: function(response, options) {
60 let upid = response.result.data;
61 let win = Ext.create('Proxmox.window.TaskProgress', {
62 upid: upid,
63 taskDone: () => { me.reload(); },
64 });
65 win.show();
66 },
67 failure: function(response, opts) {
68 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
69 },
70 });
71 },
72
f44ce595
DC
73 reload: function() {
74 this.getView().getStore().load();
75 },
76 },
77
78 store: {
79 autoLoad: true,
80 id: 'realm-syncs',
81 proxy: {
82 type: 'proxmox',
83 url: '/api2/json/cluster/jobs/realm-sync',
84 },
85 },
86
059abb7a
DC
87 viewConfig: {
88 getRowClass: (record, _index) => record.get('enabled') ? '' : 'proxmox-disabled-row',
89 },
90
f44ce595
DC
91 columns: [
92 {
93 header: gettext('Enabled'),
94 width: 80,
95 dataIndex: 'enabled',
f44ce595 96 sortable: true,
059abb7a 97 align: 'center',
f44ce595 98 stopSelection: false,
059abb7a 99 renderer: Proxmox.Utils.renderEnabledIcon,
f44ce595
DC
100 },
101 {
102 text: gettext('Name'),
103 flex: 1,
104 dataIndex: 'id',
105 hidden: true,
106 },
107 {
108 text: gettext('Realm'),
109 width: 200,
110 dataIndex: 'realm',
111 },
112 {
113 header: gettext('Schedule'),
114 width: 150,
115 dataIndex: 'schedule',
116 },
117 {
118 text: gettext('Next Run'),
119 dataIndex: 'next-run',
120 width: 150,
121 renderer: PVE.Utils.render_next_event,
122 },
123 {
124 header: gettext('Comment'),
125 dataIndex: 'comment',
126 renderer: Ext.htmlEncode,
127 sorter: (a, b) => (a.data.comment || '').localeCompare(b.data.comment || ''),
128 flex: 1,
129 },
130 ],
131
132 tbar: [
133 {
134 text: gettext('Add'),
135 handler: 'addRealmSyncJob',
136 },
137 {
138 text: gettext('Edit'),
139 xtype: 'proxmoxButton',
140 handler: 'editRealmSyncJob',
141 disabled: true,
142 },
143 {
144 xtype: 'proxmoxStdRemoveButton',
145 baseurl: `/api2/extjs/cluster/jobs/realm-sync`,
146 callback: 'reload',
147 },
ed65c1ca
DC
148 {
149 xtype: 'proxmoxButton',
150 handler: 'runNow',
151 disabled: true,
152 text: gettext('Run Now'),
153 },
f44ce595
DC
154 ],
155
156 listeners: {
157 itemdblclick: 'editRealmSyncJob',
158 },
159
160 initComponent: function() {
161 var me = this;
162
163 me.callParent();
164
165 Proxmox.Utils.monStoreErrors(me, me.getStore());
166 },
167});
168
169Ext.define('PVE.dc.RealmSyncJobEdit', {
170 extend: 'Proxmox.window.Edit',
171 mixins: ['Proxmox.Mixin.CBind'],
172
173 subject: gettext('Realm Sync Job'),
174 onlineHelp: 'pveum_ldap_sync',
175
176 // don't focus the schedule field on edit
177 defaultFocus: 'field[name=id]',
178
179 cbindData: function() {
180 let me = this;
181 me.isCreate = !me.jobid;
182 me.jobid = me.jobid || "";
183 let url = '/api2/extjs/cluster/jobs/realm-sync';
184 me.url = me.jobid ? `${url}/${me.jobid}` : url;
185 me.method = me.isCreate ? 'POST' : 'PUT';
186 if (!me.isCreate) {
187 me.subject = `${me.subject}: ${me.jobid}`;
188 }
189 return {};
190 },
191
192 submitUrl: function(url, values) {
193 return this.isCreate ? `${url}/${values.id}` : url;
194 },
195
196 controller: {
197 xclass: 'Ext.app.ViewController',
198
199 updateDefaults: function(_field, newValue) {
200 let me = this;
99e276c3
DC
201
202 ['scope', 'enable-new', 'schedule'].forEach((reference) => {
203 me.lookup(reference)?.setDisabled(false);
204 });
205
f44ce595
DC
206 // only update on create
207 if (!me.getView().isCreate) {
208 return;
209 }
210 Proxmox.Utils.API2Request({
211 url: `/access/domains/${newValue}`,
212 success: function(response) {
213 // first reset the fields to their default
214 ['acl', 'entry', 'properties'].forEach(opt => {
215 me.lookup(`remove-vanished-${opt}`)?.setValue(false);
216 });
217 me.lookup('enable-new')?.setValue('1');
218 me.lookup('scope')?.setValue(undefined);
219
220 let options = response?.result?.data?.['sync-defaults-options'];
221 if (options) {
222 let parsed = PVE.Parser.parsePropertyString(options);
223 if (parsed['remove-vanished']) {
224 let opts = parsed['remove-vanished'].split(';');
225 for (const opt of opts) {
226 me.lookup(`remove-vanished-${opt}`)?.setValue(true);
227 }
228 delete parsed['remove-vanished'];
229 }
230 for (const [name, value] of Object.entries(parsed)) {
231 me.lookup(name)?.setValue(value);
232 }
233 }
234 },
235 });
236 },
237 },
238
239 items: [
240 {
241 xtype: 'inputpanel',
242
243 cbind: {
244 isCreate: '{isCreate}',
245 },
246
247 onGetValues: function(values) {
248 let me = this;
249
250 let vanished_opts = [];
251 ['acl', 'entry', 'properties'].forEach((prop) => {
252 if (values[`remove-vanished-${prop}`]) {
253 vanished_opts.push(prop);
254 }
255 delete values[`remove-vanished-${prop}`];
256 });
257
258 if (!values.id && me.isCreate) {
259 values.id = 'realmsync-' + Ext.data.identifier.Uuid.Global.generate().slice(0, 13);
260 }
261
262 if (vanished_opts.length > 0) {
263 values['remove-vanished'] = vanished_opts.join(';');
264 } else {
265 values['remove-vanished'] = 'none';
266 }
267
268 PVE.Utils.delete_if_default(values, 'node', '');
269
270 if (me.isCreate) {
271 delete values.delete; // on create we cannot delete values
272 }
273
274 return values;
275 },
276
277 column1: [
278 {
279 xtype: 'pmxDisplayEditField',
280 editConfig: {
281 xtype: 'pmxRealmComboBox',
282 storeFilter: rec => rec.data.type === 'ldap' || rec.data.type === 'ad',
283 },
99e276c3
DC
284 listConfig: {
285 emptyText: `<div class="x-grid-empty">${gettext('No LDAP/AD Realm found')}</div>`,
286 },
f44ce595
DC
287 cbind: {
288 editable: '{isCreate}',
289 },
290 listeners: {
291 change: 'updateDefaults',
292 },
293 fieldLabel: gettext('Realm'),
294 name: 'realm',
295 reference: 'realm',
296 },
297 {
298 xtype: 'pveCalendarEvent',
299 fieldLabel: gettext('Schedule'),
99e276c3 300 disabled: true,
f44ce595
DC
301 allowBlank: false,
302 name: 'schedule',
303 reference: 'schedule',
304 },
305 {
306 xtype: 'proxmoxcheckbox',
307 fieldLabel: gettext('Enable'),
308 name: 'enabled',
309 reference: 'enabled',
310 uncheckedValue: 0,
311 defaultValue: 1,
312 checked: true,
313 },
314 ],
315
316 column2: [
317 {
318 xtype: 'proxmoxKVComboBox',
319 name: 'scope',
320 reference: 'scope',
99e276c3 321 disabled: true,
f44ce595
DC
322 fieldLabel: gettext('Scope'),
323 value: '',
324 emptyText: gettext('No default available'),
325 deleteEmpty: false,
326 allowBlank: false,
327 comboItems: [
328 ['users', gettext('Users')],
329 ['groups', gettext('Groups')],
330 ['both', gettext('Users and Groups')],
331 ],
332 },
333 {
334 xtype: 'proxmoxKVComboBox',
335 value: '1',
336 deleteEmpty: false,
99e276c3 337 disabled: true,
f44ce595
DC
338 allowBlank: false,
339 comboItems: [
340 ['1', Proxmox.Utils.yesText],
341 ['0', Proxmox.Utils.noText],
342 ],
343 name: 'enable-new',
344 reference: 'enable-new',
345 fieldLabel: gettext('Enable new'),
346 },
347 ],
348
349 columnB: [
350 {
351 xtype: 'fieldset',
352 title: gettext('Remove Vanished Options'),
353 items: [
354 {
355 xtype: 'proxmoxcheckbox',
356 fieldLabel: gettext('ACL'),
357 name: 'remove-vanished-acl',
358 reference: 'remove-vanished-acl',
359 boxLabel: gettext('Remove ACLs of vanished users and groups.'),
360 },
361 {
362 xtype: 'proxmoxcheckbox',
363 fieldLabel: gettext('Entry'),
364 name: 'remove-vanished-entry',
365 reference: 'remove-vanished-entry',
366 boxLabel: gettext('Remove vanished user and group entries.'),
367 },
368 {
369 xtype: 'proxmoxcheckbox',
370 fieldLabel: gettext('Properties'),
371 name: 'remove-vanished-properties',
372 reference: 'remove-vanished-properties',
373 boxLabel: gettext('Remove vanished properties from synced users.'),
374 },
375 ],
376 },
377 {
378 xtype: 'proxmoxtextfield',
379 name: 'comment',
380 fieldLabel: gettext('Job Comment'),
381 cbind: {
382 deleteEmpty: '{!isCreate}',
383 },
384 autoEl: {
385 tag: 'div',
386 'data-qtip': gettext('Description of the job'),
387 },
388 },
389 {
390 xtype: 'displayfield',
391 reference: 'defaulthint',
392 value: gettext('Default sync options can be set by editing the realm.'),
393 userCls: 'pmx-hint',
394 hidden: true,
395 },
396 ],
397 },
398 ],
399
400 initComponent: function() {
401 let me = this;
402 me.callParent();
403 if (me.jobid) {
404 me.load({
405 success: function(response, options) {
406 let values = response.result.data;
407
408 if (values['remove-vanished']) {
409 let opts = values['remove-vanished'].split(';');
410 for (const opt of opts) {
411 values[`remove-vanished-${opt}`] = 1;
412 }
413 }
414 me.down('inputpanel').setValues(values);
415 },
416 });
417 }
418 },
419});