mirror of
https://github.com/discourse/discourse.git
synced 2026-07-29 23:58:12 -05:00
FEATURE: Add scopes to API keys (#9844)
* Added scopes UI * Create scopes when creating a new API key * Show scopes on the API key show route * Apply scopes on API requests * Extend scopes from plugins * Add missing scopes. A mapping can be associated with multiple controller actions * Only send scopes if the use global key option is disabled. Use the discourse plugin registry to add new scopes * Add not null validations and index for api_key_id * Annotate model * DEV: Move default mappings to ApiKeyScope * Remove unused attribute and improve UI for existing keys * Support multiple parameters separated by a comma
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import RESTAdapter from "discourse/adapters/rest";
|
||||
|
||||
export default RESTAdapter.extend({
|
||||
jsonMode: true,
|
||||
|
||||
basePath() {
|
||||
return "/admin/api/";
|
||||
},
|
||||
|
||||
@@ -9,6 +9,8 @@ export default Controller.extend({
|
||||
{ id: "all", name: I18n.t("admin.api.all_users") },
|
||||
{ id: "single", name: I18n.t("admin.api.single_user") }
|
||||
],
|
||||
useGlobalKey: false,
|
||||
scopes: null,
|
||||
|
||||
@discourseComputed("userMode")
|
||||
showUserSelector(mode) {
|
||||
@@ -31,6 +33,16 @@ export default Controller.extend({
|
||||
},
|
||||
|
||||
save() {
|
||||
if (!this.useGlobalKey) {
|
||||
const selectedScopes = Object.values(this.scopes)
|
||||
.flat()
|
||||
.filter(action => {
|
||||
return action.selected;
|
||||
});
|
||||
|
||||
this.model.set("scopes", selectedScopes);
|
||||
}
|
||||
|
||||
this.model.save().catch(popupAjaxError);
|
||||
},
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ const ApiKey = RestModel.extend({
|
||||
},
|
||||
|
||||
createProperties() {
|
||||
return this.getProperties("description", "username");
|
||||
return this.getProperties("description", "username", "scopes");
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import Route from "@ember/routing/route";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default Route.extend({
|
||||
model() {
|
||||
return this.store.createRecord("api-key");
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
ajax("/admin/api/keys/scopes.json").then(data => {
|
||||
controller.setProperties({
|
||||
scopes: data.scopes,
|
||||
model
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,8 +31,40 @@
|
||||
}}
|
||||
{{/admin-form-row}}
|
||||
{{/if}}
|
||||
{{#admin-form-row}}
|
||||
{{d-button icon="check" label="admin.api.save" action=(action "save") class="btn-primary" disabled=saveDisabled}}
|
||||
|
||||
{{#admin-form-row label="admin.api.use_global_key"}}
|
||||
{{input type="checkbox" checked=useGlobalKey}}
|
||||
{{/admin-form-row}}
|
||||
|
||||
{{#unless useGlobalKey}}
|
||||
{{#each-in scopes as |resource actions|}}
|
||||
<table class="scopes-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>{{resource}}</b></td>
|
||||
<td></td>
|
||||
<td>{{i18n "admin.api.scopes.optional_allowed_parameters"}}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each actions as |act|}}
|
||||
<tr>
|
||||
<td>{{input type="checkbox" checked=act.selected}}</td>
|
||||
<td><b>{{act.name}}</b></td>
|
||||
<td>
|
||||
{{#each act.params as |p|}}
|
||||
<div>
|
||||
{{input maxlength="255" value=(get act p) placeholder=p}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/each-in}}
|
||||
{{/unless}}
|
||||
|
||||
{{d-button icon="check" label="admin.api.save" action=(action "save") class="btn-primary" disabled=saveDisabled}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@@ -79,4 +79,39 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/admin-form-row}}
|
||||
|
||||
{{#if model.api_key_scopes.length}}
|
||||
{{#admin-form-row label="admin.api.scopes.title"}}
|
||||
{{/admin-form-row}}
|
||||
|
||||
<table class="scopes-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{{i18n "admin.api.scopes.resource"}}</td>
|
||||
<td>{{i18n "admin.api.scopes.action"}}</td>
|
||||
<td>{{i18n "admin.api.scopes.allowed_parameters"}}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.api_key_scopes as |scope|}}
|
||||
<tr>
|
||||
<td>{{scope.resource}}</td>
|
||||
<td>{{scope.action}}</td>
|
||||
<td>
|
||||
{{#each scope.parameters as |p|}}
|
||||
<div>
|
||||
<b>{{p}}:</b>
|
||||
{{#if (get scope.allowed_parameters p)}}
|
||||
{{get scope.allowed_parameters p}}
|
||||
{{else}}
|
||||
{{i18n "admin.api.scopes.any_parameter"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user