// API keys on the account page: list, make (with a permission picker of the maker's own permissions), rotate, revoke (function () { var card = document.getElementById('apiKeys'); if (!card) return; var accountId = card.dataset.account; var isSelf = card.dataset.self === '1'; var canCreate = card.dataset.canCreate === '1'; var $ = function (id) { return document.getElementById(id); }; var catalog = null; var titles = {}; var STATUS = { active: ['Active', 'success'], revoked: ['Revoked', 'secondary'], expired: ['Expired', 'secondary'], signed_out: ['Stopped by sign out', 'warning'] }; function loadCatalog() { if (catalog) return Promise.resolve(catalog); return api.get('/api/api_keys/permissions').then(function (d) { if (!d.success) throw new Error(d.error || 'Could not load permissions'); catalog = d; d.permissions.forEach(function (p) { titles[p.key] = p.title; }); return d; }); } function scopeCell(k) { var html = k.allPermissions ? fmt.badge('All of ' + (isSelf ? 'your' : 'their') + ' permissions', 'primary') : '' + esc(k.permissions.length) + ' permission' + (k.permissions.length === 1 ? '' : 's') + ''; if (k.readOnly) html += ' ' + fmt.badge('read-only', 'info'); if (k.lostPermissions.length) { html += '
' + esc(k.prefix) + '…' +
(k.note ? 'You have no permissions to give a key.
'; $('apiKeyRate').placeholder = 'Default (' + catalog.defaultRateLimit + ')'; $('apiKeyRate').max = catalog.maxRateLimit; } function showForm(show) { $('apiKeyForm').classList.toggle('d-none', !show); if (show) loadCatalog().then(renderPicker).catch(function (e) { toast(e.message, 'danger'); }); } function showSecret(key) { $('apiKeySecret').value = key; $('apiKeyCreated').classList.remove('d-none'); $('apiKeySecret').select(); } if ($('apiKeyNew')) $('apiKeyNew').addEventListener('click', function () { showForm(true); }); $('apiKeyCancel').addEventListener('click', function () { showForm(false); }); $('apiKeyCopy').addEventListener('click', function () { var box = $('apiKeySecret'); box.select(); if (navigator.clipboard) navigator.clipboard.writeText(box.value).then(function () { toast('Copied', 'success'); }); }); $('apiKeyScopeAll').addEventListener('change', function () { $('apiKeyPicker').classList.add('d-none'); }); $('apiKeyScopeSome').addEventListener('change', function () { $('apiKeyPicker').classList.remove('d-none'); }); $('apiKeyPicker').addEventListener('click', function (e) { var group = e.target.dataset.group; if (group === undefined) return; var boxes = $('apiKeyPicker').querySelectorAll('[data-group-of="' + group + '"]'); var check = Array.prototype.some.call(boxes, function (b) { return !b.checked; }); boxes.forEach(function (b) { b.checked = check; }); }); $('apiKeyForm').addEventListener('submit', function (e) { e.preventDefault(); var all = $('apiKeyScopeAll').checked; var picked = Array.prototype.map.call($('apiKeyPicker').querySelectorAll('input:checked'), function (b) { return b.value; }); if (!all && !picked.length) { toast('Pick at least one permission, or all of yours', 'warning'); return; } api.action('/api/api_keys', { name: $('apiKeyName').value, note: $('apiKeyNote').value, permissions: all ? '*' : picked, readOnly: $('apiKeyReadOnly').checked, allowedIps: $('apiKeyIps').value, allowedPaths: $('apiKeyPaths').value, rateLimit: parseInt($('apiKeyRate').value, 10) || 0, dailyQuota: parseInt($('apiKeyQuota').value, 10) || 0, expiresInDays: parseInt($('apiKeyExpiry').value, 10) || 0 }).then(function (d) { $('apiKeyForm').reset(); $('apiKeyPicker').classList.remove('d-none'); showForm(false); showSecret(d.key); load(); }).catch(function () {}); }); $('apiKeyRows').addEventListener('click', function (e) { var rotate = e.target.dataset.rotate, revoke = e.target.dataset.revoke; if (rotate) { if (!confirm('Make a new secret for this key? The current one stops working at once.')) return; api.action('/api/api_keys/' + rotate + '/rotate', {}).then(function (d) { showSecret(d.key); load(); }).catch(function () {}); } else if (revoke) { if (!confirm('Revoke this key? Anything using it stops working at once.')) return; api.action('/api/api_keys/' + revoke + '/revoke', {}, 'API key revoked').then(load).catch(function () {}); } }); load(); })();