// Identity provider sync: status card and run requests (admin system page, identity provider tab).
// Runs are executed by the identity-sync cron (every minute); the card polls until the requested run is done.
var mailcowIdentity = (function($) {
'use strict';
var POLL_MS = 5000;
var POLL_MAX = 36;
var polls = 0;
var timer = null;
var STATUS_CLASS = {ok: 'bg-success', blocked: 'bg-warning text-dark', error: 'bg-danger', pending: 'bg-secondary', running: 'bg-info text-dark'};
// summary counts in display order
var COUNTS = ['creates', 'links', 'deactivate', 'restore', 'release', 'missing', 'found', 'updates', 'group_creates', 'group_renames',
'memberships', 'orphaned_groups', 'membership_removals', 'conflicts', 'errors', 'skipped'];
var DETAILS = ['conflicts', 'errors', 'deactivate', 'restore', 'missing', 'creates', 'group_creates'];
// admin.twig injects the admin lang section as `lang`
function L(key) {
var src = (typeof lang_admin !== 'undefined') ? lang_admin : ((typeof lang !== 'undefined') ? lang : {});
return (src[key] !== undefined) ? src[key] : key;
}
function esc(s) {
return escapeHtml(s === null || s === undefined ? '' : String(s));
}
function badge(label, value, cls) {
return '' + esc(label) + ': ' + esc(value) + '';
}
function changes(run) {
var s = run.summary;
if (!s) return '';
if (s.error) return '' + esc(s.error) + '';
var counts = s.counts || {};
var html = '';
$.each(COUNTS, function(i, key) {
if (counts[key] > 0) html += badge(L('iam_sync_count_' + key), counts[key], (key === 'errors' || key === 'conflicts') ? 'bg-danger' : null);
});
if (html === '') html = '' + esc(L('iam_sync_no_changes')) + '';
var details = $.extend({}, s.details || {}, {errors: s.errors || []});
var lists = '';
$.each(DETAILS, function(i, key) {
var items = details[key] || [];
if (!items.length) return;
lists += '
' + esc(L('iam_sync_count_' + key)) + '' +
$.map(items, function(item) { return '- ' + esc(item) + '
'; }).join('') + '
';
});
if (lists !== '') html += '' + esc(L('iam_sync_details')) + '
' + lists + ' ';
return html;
}
function render(status) {
var c = status.counts || {};
var counts = badge(L('iam_sync_accounts'), c.accounts || 0) + badge(L('iam_sync_linked'), c.linked || 0) +
badge(L('iam_sync_idp_disabled'), c.idp_disabled || 0, c.idp_disabled ? 'bg-warning text-dark' : null) +
badge(L('iam_sync_missing'), c.missing || 0, c.missing ? 'bg-warning text-dark' : null);
if (!status.sync_enabled) counts += '' + esc(L('iam_sync_off')) + '
';
$('#iam_sync_counts').html(counts);
var rows = $.map(status.runs || [], function(run) {
var state = '' + esc(L('iam_sync_status_' + run.status)) + '';
return '| ' + esc(run.started || run.created) + ' | ' +
'' + esc(L('iam_sync_mode_' + run.mode)) + (run.requested_by ? ' ' + esc(run.requested_by) + ' ' : '') + ' | ' +
'' + state + ' | ' + changes(run) + ' |
';
});
$('#iam_sync_runs tbody').html(rows.length ? rows.join('') : '| ' + esc(L('iam_sync_none')) + ' |
');
return status.runs && status.runs.length && (status.runs[0].status === 'pending' || status.runs[0].status === 'running');
}
function load() {
clearTimeout(timer);
$.get('/api/v1/get/identity-provider/sync-status', function(status) {
if (render(status || {}) && polls++ < POLL_MAX) timer = setTimeout(load, POLL_MS);
}, 'json');
}
function request(mode) {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/api/v1/edit/identity-provider-sync',
data: {items: JSON.stringify(['sync']), attr: JSON.stringify({mode: mode}), csrf_token: csrf_token},
success: function(res) {
var msg = (res && res[0]) ? res[0] : {type: 'danger', msg: 'generic_server_error'};
var key = $.isArray(msg.msg) ? msg.msg[0] : msg.msg;
var text = (msg.type === 'success' ? lang_success : lang_danger)[key] || key;
mailcow_alert_box(text, msg.type === 'success' ? 'success' : 'danger');
polls = 0;
load();
}
});
}
$(document).ready(function() {
if (!$('#iam_sync_status').length) return;
load();
$(document).on('click', '.iam_sync_request', function(e) {
e.preventDefault();
var mode = $(this).data('mode');
if (mode === 'force' && !confirm(L('iam_sync_force_confirm'))) return;
request(mode);
});
});
return {load: load};
})(jQuery);