diff --git a/addon/components/webhook/details.hbs b/addon/components/webhook/details.hbs
index 59714dd..9de67f7 100644
--- a/addon/components/webhook/details.hbs
+++ b/addon/components/webhook/details.hbs
@@ -7,7 +7,7 @@
diff --git a/addon/components/webhook/details.js b/addon/components/webhook/details.js
index 345e456..cdb5777 100644
--- a/addon/components/webhook/details.js
+++ b/addon/components/webhook/details.js
@@ -1,8 +1,24 @@
import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class WebhookDetailsComponent extends Component {
+ @service abilities;
+ @tracked permission;
+ @tracked doesntHavePermission = false;
+
+ constructor(owner, { permission }) {
+ super(...arguments);
+ this.permission = permission;
+ this.doesntHavePermission = permission && this.abilities.cannot(permission);
+ }
+
@action onClickUpdateWebhook() {
+ if (this.doesntHavePermission) {
+ return;
+ }
+
const { webhook, onClickUpdateWebhook } = this.args;
if (typeof onClickUpdateWebhook === 'function') {
diff --git a/addon/controllers/api-keys/index.js b/addon/controllers/api-keys/index.js
index a1c0826..3bf9f12 100644
--- a/addon/controllers/api-keys/index.js
+++ b/addon/controllers/api-keys/index.js
@@ -11,74 +11,15 @@ import { format as formatDate } from 'date-fns';
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
export default class ApiKeysIndexController extends Controller {
- /**
- * Inject the `currentUser` service
- *
- * @var {Service}
- */
@service currentUser;
-
- /**
- * Inject the `intl` service
- *
- * @var {Service}
- */
@service intl;
-
- /**
- * Inject the `modalsManager` service
- *
- * @var {Service}
- */
@service modalsManager;
-
- /**
- * Inject the `notifications` service
- *
- * @var {Service}
- */
@service notifications;
-
- /**
- * Inject the `store` service
- *
- * @var {Service}
- */
@service store;
-
- /**
- * Inject the `crud` service
- *
- * @var {Service}
- */
@service crud;
-
- /**
- * Inject the `fetch` service
- *
- * @var {Service}
- */
@service fetch;
-
- /**
- * Inject the `theme` service
- *
- * @var {Service}
- */
@service theme;
-
- /**
- * Inject the `hostRouter` service
- *
- * @var {Service}
- */
@service hostRouter;
-
- /**
- * Inject the `universe` service
- *
- * @var {Service}
- */
@service universe;
/**
@@ -142,7 +83,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @memberof ApiKeysIndexController
*/
- @computed('testMode') get isTestMode() {
+ @computed('testMode') get isTestMode () {
return this.testMode === true;
}
@@ -151,7 +92,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @memberof ApiKeysIndexController
*/
- @computed('currentUser.options.testKey') get testKey() {
+ @computed('currentUser.options.testKey') get testKey () {
return this.currentUser.getOption('testKey');
}
@@ -165,6 +106,7 @@ export default class ApiKeysIndexController extends Controller {
label: this.intl.t('developers.common.name'),
valuePath: 'name',
cellComponent: 'table/cell/anchor',
+ permission: 'developers view api-key',
action: this.editApiKey,
resizable: true,
width: '10%',
@@ -236,13 +178,26 @@ export default class ApiKeysIndexController extends Controller {
width: '10%',
align: 'right',
actions: [
- { label: this.intl.t('developers.api-keys.index.edit-key'), fn: this.editApiKey },
- { label: this.intl.t('developers.api-keys.index.roll-key'), fn: this.rollApiKey },
- { label: this.intl.t('developers.api-keys.index.view-logs'), fn: this.viewRequestLogs },
+ {
+ label: this.intl.t('developers.api-keys.index.edit-key'),
+ fn: this.editApiKey,
+ permission: 'developers view api-key',
+ },
+ {
+ label: this.intl.t('developers.api-keys.index.roll-key'),
+ fn: this.rollApiKey,
+ permission: 'developers roll api-key',
+ },
+ {
+ label: this.intl.t('developers.api-keys.index.view-logs'),
+ fn: this.viewRequestLogs,
+ permission: 'developers view log',
+ },
{
label: this.intl.t('developers.api-keys.index.delete-key'),
fn: this.deleteApiKey,
className: 'text-red-700 hover:text-red-800',
+ permission: 'developers delete api-key',
},
],
},
@@ -253,7 +208,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @task({ restartable: true }) *search({ target: { value } }) {
+ @task({ restartable: true }) *search ({ target: { value } }) {
// if no query don't search
if (isBlank(value)) {
this.query = null;
@@ -277,7 +232,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action toggleTestMode(testMode = false) {
+ @action toggleTestMode (testMode = false) {
this.currentUser.setOption('sandbox', testMode);
this.testMode = testMode;
this.theme.setEnvironment();
@@ -292,7 +247,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action toggleTestKey({ target: { value } }) {
+ @action toggleTestKey ({ target: { value } }) {
if (isBlank(value)) {
this.currentUser.setOption('testKey', null);
return;
@@ -306,7 +261,8 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action createApiKey() {
+ @action createApiKey () {
+ const formPermission = 'developers create api-key';
const apiKey = this.store.createRecord('api-credential', {
test_mode: this.testMode,
});
@@ -315,8 +271,27 @@ export default class ApiKeysIndexController extends Controller {
title: this.intl.t('developers.api-keys.index.new-api-key-title'),
acceptButtonIcon: 'check',
acceptButtonIconPrefix: 'fas',
+ acceptButtonDisabled: this.abilities.cannot(formPermission),
+ acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
successMessage: this.intl.t('developers.api-keys.index.new-api-key-message'),
+ formPermission,
apiKey,
+ confirm: async modal => {
+ modal.startLoading();
+
+ if (this.abilities.cannot(formPermission)) {
+ return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
+ }
+
+ try {
+ await apiKey.save();
+ this.notifications.success(modal.getOption('successMessage'));
+ return this.hostRouter.refresh();
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
+ },
});
}
@@ -325,32 +300,36 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action editApiKey(apiKey, options = {}) {
+ @action editApiKey (apiKey, options = {}) {
+ const formPermission = 'developers update api-key';
this.modalsManager.show('modals/api-key-form', {
title: this.intl.t('developers.api-keys.index.edit-api-key-title'),
acceptButtonIcon: 'save',
+ acceptButtonDisabled: this.abilities.cannot(formPermission),
+ acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
successMessage: this.intl.t('developers.api-keys.index.edit-api-key-message'),
expirationOptions: this.expirationOptions,
testMode: this.currentUser.getOption('sandbox') || false,
apiKey,
+ formPermission,
setExpiration: ({ target }) => {
apiKey.expires_at = target.value || null;
},
- confirm: (modal, done) => {
+ confirm: async modal => {
modal.startLoading();
- apiKey
- .save()
- .then(() => {
- this.notifications.success(modal.getOption('successMessage'));
- return this.hostRouter.refresh().finally(() => {
- done();
- });
- })
- .catch((error) => {
- this.notifications.serverError(error);
- modal.stopLoading();
- });
+ if (this.abilities.cannot(formPermission)) {
+ return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
+ }
+
+ try {
+ await apiKey.save();
+ this.notifications.success(modal.getOption('successMessage'));
+ return this.hostRouter.refresh();
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
},
...options,
});
@@ -361,25 +340,25 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action renameApiKey(apiKey) {
+ @action renameApiKey (apiKey) {
+ const formPermission = 'developers update api-key';
const apiKeyName = getWithDefault(apiKey, 'name', this.intl.t('developers.api-keys.index.untitled'));
this.modalsManager.show('modals/rename-api-key-form', {
title: this.intl.t('developers.api-keys.index.rename-api-key-title', { apiKeyName }),
apiKey,
- confirm: (modal, done) => {
+ formPermission,
+ confirm: async modal => {
modal.startLoading();
- apiKey
- .save()
- .then(() => {
- this.notifications.success(this.intl.t('developers.api-keys.index.rename-api-key-success-message', { apiKeyName }));
- return done();
- })
- .catch((error) => {
- this.notifications.serverError(error);
- modal.stopLoading();
- });
+ try {
+ await apiKey.save();
+ this.notifications.success(this.intl.t('developers.api-keys.index.rename-api-key-success-message', { apiKeyName }));
+ modal.done();
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
},
});
}
@@ -389,26 +368,22 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action deleteApiKey(apiKey) {
+ @action deleteApiKey (apiKey) {
const apiKeyName = getWithDefault(apiKey, 'name', this.intl.t('developers.api-keys.index.untitled'));
this.modalsManager.confirm({
title: this.intl.t('developers.api-keys.index.delete-api-key-title', { apiKeyName }),
body: this.intl.t('developers.api-keys.index.delete-api-key-body'),
- confirm: (modal, done) => {
+ confirm: async modal => {
modal.startLoading();
- apiKey
- .destroyRecord()
- .then(() => {
- this.notifications.success(this.intl.t('developers.api-keys.index.delete-api-key-title', { apiKeyName }));
- return this.hostRouter.refresh().finally(() => {
- done();
- });
- })
- .catch((error) => {
- this.notifications.serverError(error);
- modal.stopLoading();
- });
+ try {
+ await apiKey.destroyRecord();
+ this.notifications.success(this.intl.t('developers.api-keys.index.delete-api-key-title', { apiKeyName }));
+ return this.hostRouter.refresh();
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
},
});
}
@@ -419,7 +394,7 @@ export default class ApiKeysIndexController extends Controller {
* @param {Array} selected an array of selected models
* @void
*/
- @action bulkDeleteApiCredentials() {
+ @action bulkDeleteApiCredentials () {
const selected = this.table.selectedRows;
this.crud.bulkDelete(selected, {
@@ -435,7 +410,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action rollApiKey(apiKey) {
+ @action rollApiKey (apiKey) {
const apiKeyName = getWithDefault(apiKey, 'name', this.intl.t('developers.api-keys.index.untitled'));
this.modalsManager.show('modals/roll-api-key-form', {
@@ -450,25 +425,21 @@ export default class ApiKeysIndexController extends Controller {
viewRequestLogs: this.viewRequestLogs,
password: null,
apiKey,
- confirm: (modal, done) => {
+ confirm: async modal => {
modal.startLoading();
- this.fetch
- .patch(
+
+ try {
+ await this.fetch.patch(
`api-credentials/roll/${apiKey.id}`,
- {
- password: modal.getOption('password'),
- expiration: apiKey.get('expires_at'),
- },
+ { password: modal.getOption('password'), expiration: apiKey.get('expires_at') },
{ normalizeToEmberData: true }
- )
- .then(() => {
- this.notifications.success(this.intl.t('developers.api-keys.index.roll-api-key-success-message', { apiKeyName }));
- return done();
- })
- .catch((error) => {
- modal.stopLoading();
- this.notifications.serverError(error, this.intl.t('developers.api-keys.index.roll-api-key-error-message'));
- });
+ );
+ this.notifications.success(this.intl.t('developers.api-keys.index.roll-api-key-success-message', { apiKeyName }));
+ modal.done();
+ } catch (error) {
+ this.notifications.serverError(error, this.intl.t('developers.api-keys.index.roll-api-key-error-message'));
+ modal.stopLoading();
+ }
},
});
}
@@ -478,7 +449,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action viewRequestLogs(apiKey) {
+ @action viewRequestLogs (apiKey) {
return this.universe.transitionToEngineRoute('@fleetbase/dev-engine', 'logs.index', {
queryParams: { key: apiKey.id },
});
@@ -489,7 +460,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @void
*/
- @action exportApiKeys() {
+ @action exportApiKeys () {
this.modalsManager.show('modals/export-form', {
title: this.intl.t('developers.api-keys.index.export-api'),
acceptButtonText: this.intl.t('developers.api-keys.index.export-api-accept-button-text'),
@@ -498,13 +469,13 @@ export default class ApiKeysIndexController extends Controller {
setFormat: ({ target }) => {
this.modalsManager.setOption('format', target.value || null);
},
- confirm: (modal, done) => {
+ confirm: async modal => {
modal.startLoading();
const format = modal.getOption('format', 'xlsx');
- this.fetch
- .download(
+ try {
+ await this.fetch.download(
`api-credentials/export`,
{
format,
@@ -512,20 +483,18 @@ export default class ApiKeysIndexController extends Controller {
{
fileName: `api-credentials-${formatDate(new Date(), 'yyyy-MM-dd-HH:mm')}.${format}`,
}
- )
- .then(() => {
- later(
- this,
- () => {
- return done();
- },
- 600
- );
- })
- .catch((error) => {
- modal.stopLoading();
- this.notifications.serverError(error, this.intl.t('developers.api-keys.index.export-api-error-message'));
- });
+ );
+ later(
+ this,
+ () => {
+ return model.done();
+ },
+ 600
+ );
+ } catch (error) {
+ this.notifications.serverError(error, this.intl.t('developers.api-keys.index.export-api-error-message'));
+ modal.stopLoading();
+ }
},
});
}
@@ -533,7 +502,7 @@ export default class ApiKeysIndexController extends Controller {
/**
* Reload data.
*/
- @action reload() {
+ @action reload () {
return this.hostRouter.refresh();
}
}
diff --git a/addon/controllers/sockets/index.js b/addon/controllers/sockets/index.js
index 90af448..d554676 100644
--- a/addon/controllers/sockets/index.js
+++ b/addon/controllers/sockets/index.js
@@ -5,46 +5,11 @@ import { action, computed } from '@ember/object';
import fromStore from '@fleetbase/ember-core/decorators/from-store';
export default class SocketsIndexController extends BaseController {
- /**
- * Inject the `modalsManager` service
- *
- * @var {Service}
- */
@service modalsManager;
-
- /**
- * Inject the `intl` service
- *
- * @var {Service}
- */
@service intl;
-
- /**
- * Inject the `notifications` service
- *
- * @var {Service}
- */
@service notifications;
-
- /**
- * Inject the `currentUser` service
- *
- * @var {Service}
- */
@service currentUser;
-
- /**
- * Inject the `store` service
- *
- * @var {Service}
- */
@service store;
-
- /**
- * Inject the `hostRouter` service
- *
- * @var {Service}
- */
@service hostRouter;
/**
diff --git a/addon/controllers/webhooks/index.js b/addon/controllers/webhooks/index.js
index a21b9f2..5ab629b 100644
--- a/addon/controllers/webhooks/index.js
+++ b/addon/controllers/webhooks/index.js
@@ -64,7 +64,7 @@ export default class WebhooksIndexController extends BaseController {
*
* @var {Object}
*/
- @computed('webhookEvents.[]') get groupedApiEvents() {
+ @computed('webhookEvents.[]') get groupedApiEvents () {
return groupApiEvents(this.webhookEvents);
}
@@ -138,6 +138,7 @@ export default class WebhooksIndexController extends BaseController {
width: '40%',
sortable: false,
cellComponent: 'table/cell/link-to',
+ permission: 'developers view webhook',
route: 'webhooks.view',
cellClassNames: 'no-underline',
},
@@ -172,14 +173,17 @@ export default class WebhooksIndexController extends BaseController {
{
label: this.intl.t('developers.webhooks.index.view-logs'),
fn: this.viewWebhook,
+ permission: 'developers view webhook',
},
{
label: this.intl.t('developers.webhooks.index.edit-webhook'),
fn: this.editWebhook,
+ permission: 'developers update webhook',
},
{
label: this.intl.t('developers.webhooks.index.delete-webhook'),
fn: this.deleteWebhook,
+ permission: 'developers delete webhook',
},
],
sortable: false,
@@ -194,7 +198,7 @@ export default class WebhooksIndexController extends BaseController {
*
* @void
*/
- @task({ restartable: true }) *search({ target: { value } }) {
+ @task({ restartable: true }) *search ({ target: { value } }) {
// if no query don't search
if (isBlank(value)) {
this.query = null;
@@ -218,7 +222,8 @@ export default class WebhooksIndexController extends BaseController {
*
* @void
*/
- @action createWebhook() {
+ @action createWebhook () {
+ const formPermission = 'developers create webhook';
const webhook = this.store.createRecord('webhook-endpoint', {
events: [],
mode: this.currentUser.getOption('sandbox') ? 'test' : 'live',
@@ -229,7 +234,26 @@ export default class WebhooksIndexController extends BaseController {
acceptButtonText: this.intl.t('developers.webhooks.index.add-webhook-button-text'),
acceptButtonIcon: 'check',
acceptButtonIconPrefix: 'fas',
+ acceptButtonDisabled: this.abilities.cannot(formPermission),
+ acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
+ formPermission,
webhook,
+ confirm: async modal => {
+ modal.startLoading();
+
+ if (this.abilities.cannot(formPermission)) {
+ return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
+ }
+
+ try {
+ await webhook.save();
+ this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message'));
+ return this.hostRouter.refresh();
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
+ },
});
}
@@ -240,11 +264,15 @@ export default class WebhooksIndexController extends BaseController {
* @param {Object} options
* @void
*/
- @action editWebhook(webhook, options = {}) {
+ @action editWebhook (webhook, options = {}) {
+ const formPermission = 'developers update webhook';
this.modalsManager.show('modals/webhook-form', {
title: this.intl.t('developers.webhooks.index.edit-webhook-endpoint'),
acceptButtonText: this.intl.t('developers.webhooks.index.edit-webhook-endpoint-button-text'),
acceptButtonIcon: 'save',
+ acceptButtonDisabled: this.abilities.cannot(formPermission),
+ acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
+ formPermission,
declineButtonIcon: 'times',
declineButtonIconPrefix: 'fas',
eventOptions: this.groupedApiEvents,
@@ -257,14 +285,14 @@ export default class WebhooksIndexController extends BaseController {
setApiCredential: ({ target }) => {
webhook.api_credential_uuid = target.value || null;
},
- searchEvents: (query) => {
+ searchEvents: query => {
if (typeof query !== 'string') {
return;
}
const resources = Object.keys(this.groupedApiEvents);
const filteredEvents = {};
- resources.forEach((eventResource) => {
- filteredEvents[eventResource] = this.groupedApiEvents[eventResource].filter((event) => {
+ resources.forEach(eventResource => {
+ filteredEvents[eventResource] = this.groupedApiEvents[eventResource].filter(event => {
return event.toLowerCase().includes(query.toLowerCase());
});
// if 0 events remove from filter
@@ -274,14 +302,14 @@ export default class WebhooksIndexController extends BaseController {
});
this.modalsManager.setOption('eventOptions', filteredEvents);
},
- addEvent: (event) => {
+ addEvent: event => {
if (webhook.events.includes(event)) {
return;
}
webhook.events.pushObject(event);
},
- removeEvent: (event) => {
+ removeEvent: event => {
webhook.events.removeObject(event);
},
clearEvents: () => {
@@ -290,13 +318,21 @@ export default class WebhooksIndexController extends BaseController {
receiveAllEvents: () => {
webhook.events.pushObjects(this.webhookEvents);
},
- confirm: (modal) => {
+ confirm: async modal => {
modal.startLoading();
- return webhook.save().then(() => {
+ if (this.abilities.cannot(formPermission)) {
+ return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
+ }
+
+ try {
+ await webhook.save();
this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message'));
return this.hostRouter.refresh();
- });
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
},
...options,
});
@@ -309,17 +345,21 @@ export default class WebhooksIndexController extends BaseController {
* @param {Object} options
* @void
*/
- @action deleteWebhook(webhook, options = {}) {
+ @action deleteWebhook (webhook, options = {}) {
this.modalsManager.confirm({
title: this.intl.t('developers.webhooks.index.delete-webhook-endpoint'),
body: this.intl.t('developers.webhooks.index.delete-webhook-endpoint-body'),
- confirm: (modal) => {
+ confirm: async modal => {
modal.startLoading();
- return webhook.destroyRecord().then(() => {
+ try {
+ await webhook.destroyRecord();
this.notifications.success(this.intl.t('developers.webhooks.index.delete-webhook-success-message'));
return this.hostRouter.refresh();
- });
+ } catch (error) {
+ this.notifications.serverError(error);
+ modal.stopLoading();
+ }
},
...options,
});
@@ -332,14 +372,14 @@ export default class WebhooksIndexController extends BaseController {
* @return {Transition
}
* @memberof WebhooksIndexController
*/
- @action viewWebhook(webhook) {
+ @action viewWebhook (webhook) {
return this.transitionToRoute('webhooks.view', webhook);
}
/**
* Reload data.
*/
- @action reload() {
+ @action reload () {
return this.hostRouter.refresh();
}
}
diff --git a/addon/engine.js b/addon/engine.js
index 369e4dd..33bccd2 100644
--- a/addon/engine.js
+++ b/addon/engine.js
@@ -3,6 +3,7 @@ import loadInitializers from 'ember-load-initializers';
import Resolver from 'ember-resolver';
import config from './config/environment';
import services from '@fleetbase/ember-core/exports/services';
+import WidgetApiMetricsComponent from './components/widget/api-metrics';
const { modulePrefix } = config;
const externalRoutes = ['console', 'extensions'];
@@ -17,6 +18,19 @@ export default class DevEngine extends Engine {
setupExtension = function (app, engine, universe) {
// register menu item in header
universe.registerHeaderMenuItem('Developers', 'console.developers', { icon: 'code', priority: 2 });
+ // register metrics widget
+ const ApiMetricsWidgetDefinition = {
+ widgetId: 'dev-api-metrics-widget',
+ name: 'Developer API Metrics',
+ description: 'Key metrics from API Usage.',
+ icon: 'code',
+ component: WidgetApiMetricsComponent,
+ grid_options: { w: 12, h: 12, minW: 8, minH: 12 },
+ options: {
+ title: 'API Metrics',
+ },
+ };
+ universe.registerDashboardWidgets([ApiMetricsWidgetDefinition]);
};
}
diff --git a/addon/routes/api-keys/index.js b/addon/routes/api-keys/index.js
index c058825..9269106 100644
--- a/addon/routes/api-keys/index.js
+++ b/addon/routes/api-keys/index.js
@@ -6,6 +6,10 @@ export default class ApiKeysIndexRoute extends Route {
@service store;
@service loader;
@service currentUser;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
queryParams = {
page: {
@@ -26,6 +30,13 @@ export default class ApiKeysIndexRoute extends Route {
this.loader.showOnInitialTransition(transition, 'section.next-view-section', { loadingMessage: 'Loading api keys...' });
}
+ beforeModel () {
+ if (this.abilities.cannot('developers list api-key')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.home');
+ }
+ }
+
model(params) {
return this.store.query('api-credential', { ...params });
}
diff --git a/addon/routes/events/index.js b/addon/routes/events/index.js
index 384c6a9..c5f6427 100644
--- a/addon/routes/events/index.js
+++ b/addon/routes/events/index.js
@@ -5,6 +5,10 @@ import { action } from '@ember/object';
export default class EventsIndexRoute extends Route {
@service store;
@service loader;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
queryParams = {
query: {
@@ -31,6 +35,13 @@ export default class EventsIndexRoute extends Route {
this.loader.showOnInitialTransition(transition, 'section.next-view-section', { loadingMessage: 'Loading events...' });
}
+ beforeModel () {
+ if (this.abilities.cannot('developers list event')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.home');
+ }
+ }
+
model(params) {
return this.store.query('api-event', params);
}
diff --git a/addon/routes/events/view.js b/addon/routes/events/view.js
index 9ce118f..4b2fa85 100644
--- a/addon/routes/events/view.js
+++ b/addon/routes/events/view.js
@@ -3,6 +3,17 @@ import { inject as service } from '@ember/service';
export default class EventsViewRoute extends Route {
@service store;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
+
+ beforeModel () {
+ if (this.abilities.cannot('developers view event')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.events.index');
+ }
+ }
model({ public_id }) {
return this.store.findRecord('api-event', public_id);
diff --git a/addon/routes/logs/index.js b/addon/routes/logs/index.js
index 70e1eb3..970a866 100644
--- a/addon/routes/logs/index.js
+++ b/addon/routes/logs/index.js
@@ -5,6 +5,10 @@ import { action } from '@ember/object';
export default class LogsIndexRoute extends Route {
@service store;
@service loader;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
queryParams = {
query: {
@@ -37,6 +41,13 @@ export default class LogsIndexRoute extends Route {
this.loader.showOnInitialTransition(transition, 'section.next-view-section', { loadingMessage: 'Loading logs...' });
}
+ beforeModel () {
+ if (this.abilities.cannot('developers list log')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.home');
+ }
+ }
+
model(params) {
return this.store.query('api-request-log', params);
}
diff --git a/addon/routes/logs/view.js b/addon/routes/logs/view.js
index d704297..b001719 100644
--- a/addon/routes/logs/view.js
+++ b/addon/routes/logs/view.js
@@ -3,6 +3,17 @@ import { inject as service } from '@ember/service';
export default class LogsViewRoute extends Route {
@service store;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
+
+ beforeModel () {
+ if (this.abilities.cannot('developers view log')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.logs.index');
+ }
+ }
model({ public_id }) {
return this.store.findRecord('api-request-log', public_id);
diff --git a/addon/routes/sockets/index.js b/addon/routes/sockets/index.js
index 84e0fcf..b2ae4b2 100644
--- a/addon/routes/sockets/index.js
+++ b/addon/routes/sockets/index.js
@@ -4,8 +4,19 @@ import { action } from '@ember/object';
export default class SocketsIndexRoute extends Route {
@service loader;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
@action loading(transition) {
this.loader.showOnInitialTransition(transition, 'section.next-view-section', { loadingMessage: 'Loading websockets...' });
}
+
+ beforeModel () {
+ if (this.abilities.cannot('developers list socket')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.home');
+ }
+ }
}
diff --git a/addon/routes/sockets/view.js b/addon/routes/sockets/view.js
index 8990f70..e3cb09f 100644
--- a/addon/routes/sockets/view.js
+++ b/addon/routes/sockets/view.js
@@ -1,6 +1,19 @@
import Route from '@ember/routing/route';
+import { inject as service } from '@ember/service';
export default class SocketsViewRoute extends Route {
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
+
+ beforeModel () {
+ if (this.abilities.cannot('developers view socket')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.sockets.index');
+ }
+ }
+
model({ name }) {
return { name };
}
diff --git a/addon/routes/webhooks/index.js b/addon/routes/webhooks/index.js
index 37873a5..e6c7071 100644
--- a/addon/routes/webhooks/index.js
+++ b/addon/routes/webhooks/index.js
@@ -4,8 +4,11 @@ import { action } from '@ember/object';
export default class WebhooksIndexRoute extends Route {
@service store;
- @service fetch;
@service loader;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
queryParams = {
page: {
@@ -19,11 +22,18 @@ export default class WebhooksIndexRoute extends Route {
},
};
- @action loading(transition) {
+ @action loading (transition) {
this.loader.showOnInitialTransition(transition, 'section.next-view-section', { loadingMessage: 'Loading webhooks...' });
}
- model(params) {
+ beforeModel () {
+ if (this.abilities.cannot('developers list webhook')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.home');
+ }
+ }
+
+ model (params) {
return this.store.query('webhook-endpoint', params);
}
}
diff --git a/addon/routes/webhooks/view.js b/addon/routes/webhooks/view.js
index 48d01e4..03f78fe 100644
--- a/addon/routes/webhooks/view.js
+++ b/addon/routes/webhooks/view.js
@@ -3,6 +3,17 @@ import { inject as service } from '@ember/service';
export default class WebhooksViewRoute extends Route {
@service store;
+ @service abilities;
+ @service notifications;
+ @service hostRouter;
+ @service intl;
+
+ beforeModel () {
+ if (this.abilities.cannot('developers view webhook')) {
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
+ return this.hostRouter.transitionTo('console.developers.webhooks.index');
+ }
+ }
model({ id }) {
return this.store.findRecord('webhook-endpoint', id);
diff --git a/addon/templates/api-keys/index.hbs b/addon/templates/api-keys/index.hbs
index a5d9058..7b6ed13 100644
--- a/addon/templates/api-keys/index.hbs
+++ b/addon/templates/api-keys/index.hbs
@@ -1,4 +1,4 @@
-
+
{{#if (safe-has this.table "selectedRows")}}
-
+