import Component from "@glimmer/component"; import { cached, tracked } from "@glimmer/tracking"; import { concat, fn, hash } from "@ember/helper"; import { action } from "@ember/object"; import { service } from "@ember/service"; import { eq } from "truth-helpers"; import BackButton from "discourse/components/back-button"; import ConditionalLoadingSection from "discourse/components/conditional-loading-section"; import DButton from "discourse/components/d-button"; import Form from "discourse/components/form"; import { ajax } from "discourse/lib/ajax"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { i18n } from "discourse-i18n"; import ApiKeyUrlsModal from "admin/components/modal/api-key-urls"; import EmailGroupUserChooser from "select-kit/components/email-group-user-chooser"; import DTooltip from "float-kit/components/d-tooltip"; export default class AdminConfigAreasApiKeysNew extends Component { @service router; @service modal; @service store; @tracked username; @tracked loadingScopes = false; @tracked scopes = null; @tracked generatedApiKey = null; userModes = [ { id: "all", name: i18n("admin.api.all_users") }, { id: "single", name: i18n("admin.api.single_user") }, ]; scopeModes = [ { id: "global", name: i18n("admin.api.scopes.global") }, { id: "read_only", name: i18n("admin.api.scopes.read_only") }, { id: "granular", name: i18n("admin.api.scopes.granular") }, ]; globalScopes = null; constructor() { super(...arguments); this.#loadScopes(); } @cached get formData() { let scopes = Object.keys(this.scopes).reduce((result, resource) => { result[resource] = this.scopes[resource].map((scope) => { const params = scope.params ? scope.params.reduce((acc, param) => { acc[param] = undefined; return acc; }, {}) : {}; return { key: scope.key, enabled: undefined, urls: scope.urls, ...(params && { params }), }; }); return result; }, {}); return { user_mode: "all", scope_mode: "global", scopes, }; } @action updateUsername(field, selected) { this.username = selected[0]; field.set(this.username); } @action async save(data) { const payload = { description: data.description }; if (data.user_mode === "single") { payload.username = data.user; } if (data.scope_mode === "granular") { payload.scopes = this.#selectedScopes(data.scopes); } else if (data.scope_mode === "read_only") { payload.scopes = this.globalScopes.filter( (scope) => scope.key === "read" ); } try { const result = await this.store.createRecord("api-key").save(payload); this.generatedApiKey = result.payload.key; } catch (error) { popupAjaxError(error); } } #selectedScopes(scopes) { const enabledScopes = []; for (const [resource, resourceScopes] of Object.entries(scopes)) { enabledScopes.push( resourceScopes .filter((s) => s.enabled) .map((s) => { return { scope_id: `${resource}:${s.key}`, key: s.key, name: s.key, params: Object.keys(s.params), ...s.params, }; }) ); } return enabledScopes.flat(); } @action async showURLs(urls) { await this.modal.show(ApiKeyUrlsModal, { model: { urls }, }); } async #loadScopes() { try { this.loadingScopes = true; const data = await ajax("/admin/api/keys/scopes.json"); this.globalScopes = data.scopes.global; delete data.scopes.global; this.scopes = data.scopes; } catch (error) { popupAjaxError(error); } finally { this.loadingScopes = false; } } }