Update wizard api CRUD
- New api metadata model - New api id system - Minor UI updates
Dieser Commit ist enthalten in:
Ursprung
6345083c4d
Commit
f331f80cbb
19 geänderte Dateien mit 446 neuen und 208 gelöschten Zeilen
|
@ -1,7 +1,7 @@
|
||||||
# Uncomment tests runner when tests are added.
|
# Uncomment tests runner when tests are added.
|
||||||
|
|
||||||
sudo: required
|
sudo: required
|
||||||
#services:
|
#names:
|
||||||
#- docker
|
#- docker
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
|
|
@ -1,13 +1,32 @@
|
||||||
import { ajax } from 'discourse/lib/ajax';
|
import { ajax } from 'discourse/lib/ajax';
|
||||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||||
import CustomWizardApi from '../models/custom-wizard-api';
|
import CustomWizardApi from '../models/custom-wizard-api';
|
||||||
|
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||||
|
import DiscourseURL from 'discourse/lib/url';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
|
queryParams: ['refresh_list'],
|
||||||
loadingSubscriptions: false,
|
loadingSubscriptions: false,
|
||||||
notAuthorized: Ember.computed.not('api.authorized'),
|
notAuthorized: Ember.computed.not('api.authorized'),
|
||||||
authorizationTypes: ['oauth', 'basic'],
|
authorizationTypes: ['oauth', 'basic'],
|
||||||
isOauth: Ember.computed.equal('api.authType', 'oauth'),
|
isOauth: Ember.computed.equal('api.authType', 'oauth'),
|
||||||
endpointMethods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE'],
|
endpointMethods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE'],
|
||||||
|
saveDisabled: Ember.computed.empty('api.name'),
|
||||||
|
showRemove: Ember.computed.not('isNew'),
|
||||||
|
|
||||||
|
@computed('saveDisabled', 'authType', 'authUrl')
|
||||||
|
authDisabled(saveDisabled, authType, authUrl) {
|
||||||
|
return saveDisabled || !authType || !authUrl;
|
||||||
|
},
|
||||||
|
|
||||||
|
@observes('api.title')
|
||||||
|
titleWatcher() {
|
||||||
|
const title = this.get('api.title');
|
||||||
|
|
||||||
|
if (this.get('originalTitle')) {
|
||||||
|
this.set('originalTitle', title);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
addParam() {
|
addParam() {
|
||||||
|
@ -48,12 +67,25 @@ export default Ember.Controller.extend({
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
const api = this.get('api');
|
const api = this.get('api');
|
||||||
const service = api.service;
|
const name = api.name;
|
||||||
|
let refreshList = false;
|
||||||
|
|
||||||
let data = {};
|
if (!name ) return;
|
||||||
|
|
||||||
data['auth_type'] = api.authType;
|
let data = {
|
||||||
data['auth_url'] = api.authUrl;
|
title: api.title
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.get('isNew') || (api.title !== this.get('originalTitle'))) {
|
||||||
|
refreshList = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api.get('isNew')) {
|
||||||
|
data['new'] = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (api.authType) data['auth_type'] = api.authType;
|
||||||
|
if (api.authUrl) data['auth_url'] = api.authUrl;
|
||||||
|
|
||||||
if (data.auth_type === 'oauth') {
|
if (data.auth_type === 'oauth') {
|
||||||
data['client_id'] = api.clientId;
|
data['client_id'] = api.clientId;
|
||||||
|
@ -72,23 +104,43 @@ export default Ember.Controller.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
const endpoints = api.endpoints;
|
const endpoints = api.endpoints;
|
||||||
if (endpoints != undefined) {
|
|
||||||
if (endpoints.length) {
|
if (endpoints.length) {
|
||||||
data['endpoints'] = JSON.stringify(endpoints);
|
data['endpoints'] = JSON.stringify(endpoints);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.set('savingApi', true);
|
this.set('updating', true);
|
||||||
|
|
||||||
ajax(`/admin/wizards/apis/${service}`, {
|
ajax(`/admin/wizards/apis/${name.underscore()}`, {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data
|
data
|
||||||
}).catch(popupAjaxError)
|
}).catch(popupAjaxError)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
if (refreshList) {
|
||||||
|
this.transitionToRoute('adminWizardsApi', result.api.name.dasherize()).then(() => {
|
||||||
|
this.send('refreshModel');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.set('api', CustomWizardApi.create(result.api));
|
this.set('api', CustomWizardApi.create(result.api));
|
||||||
}
|
}
|
||||||
}).finally(() => this.set('savingApi', false));
|
}
|
||||||
|
}).finally(() => this.set('updating', false));
|
||||||
|
},
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
const name = this.get('api.name');
|
||||||
|
if (!name) return;
|
||||||
|
|
||||||
|
this.set('updating', true);
|
||||||
|
|
||||||
|
ajax(`/admin/wizards/apis/${name.underscore()}`, {
|
||||||
|
type: 'DELETE'
|
||||||
|
}).catch(popupAjaxError)
|
||||||
|
.then(result => {
|
||||||
|
if (result.success) {
|
||||||
|
DiscourseURL.routeTo('/admin/wizards/apis?refresh=true');
|
||||||
|
}
|
||||||
|
}).finally(() => this.set('updating', false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default Ember.Controller.extend({
|
||||||
|
queryParams: ['refresh']
|
||||||
|
});
|
|
@ -9,7 +9,7 @@ export default {
|
||||||
this.route('adminWizardSubmissions', { path: '/:wizard_id', resetNamespace: true });
|
this.route('adminWizardSubmissions', { path: '/:wizard_id', resetNamespace: true });
|
||||||
});
|
});
|
||||||
this.route('adminWizardsApis', { path: '/apis', resetNamespace: true }, function() {
|
this.route('adminWizardsApis', { path: '/apis', resetNamespace: true }, function() {
|
||||||
this.route('adminWizardsApi', { path: '/:service', resetNamespace: true });
|
this.route('adminWizardsApi', { path: '/:name', resetNamespace: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@ import { ajax } from 'discourse/lib/ajax';
|
||||||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||||
|
|
||||||
const CustomWizardApi = Discourse.Model.extend({
|
const CustomWizardApi = Discourse.Model.extend({
|
||||||
@computed('service')
|
@computed('name')
|
||||||
redirectUri(service) {
|
redirectUri(name) {
|
||||||
|
let nameParam = name.toString().dasherize();
|
||||||
const baseUrl = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port: '');
|
const baseUrl = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port: '');
|
||||||
return baseUrl + `/admin/wizards/apis/${service}/redirect`;
|
return baseUrl + `/admin/wizards/apis/${nameParam}/redirect`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,7 +17,8 @@ CustomWizardApi.reopenClass({
|
||||||
const endpoints = params.endpoints;
|
const endpoints = params.endpoints;
|
||||||
|
|
||||||
api.setProperties({
|
api.setProperties({
|
||||||
service: params.service,
|
name: params.name,
|
||||||
|
title: params.title,
|
||||||
authType: authorization.auth_type,
|
authType: authorization.auth_type,
|
||||||
authUrl: authorization.auth_url,
|
authUrl: authorization.auth_url,
|
||||||
tokenUrl: authorization.token_url,
|
tokenUrl: authorization.token_url,
|
||||||
|
@ -29,14 +31,15 @@ CustomWizardApi.reopenClass({
|
||||||
code: authorization.code,
|
code: authorization.code,
|
||||||
tokenExpiresAt: authorization.token_expires_at,
|
tokenExpiresAt: authorization.token_expires_at,
|
||||||
tokenRefreshAt: authorization.token_refresh_at,
|
tokenRefreshAt: authorization.token_refresh_at,
|
||||||
endpoints: Ember.A(endpoints)
|
endpoints: Ember.A(endpoints),
|
||||||
|
isNew: params.isNew
|
||||||
});
|
});
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
},
|
},
|
||||||
|
|
||||||
find(service) {
|
find(name) {
|
||||||
return ajax(`/admin/wizards/apis/${service}`, {
|
return ajax(`/admin/wizards/apis/${name}`, {
|
||||||
type: 'GET'
|
type: 'GET'
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
return CustomWizardApi.create(result);
|
return CustomWizardApi.create(result);
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import CustomWizardApi from '../models/custom-wizard-api';
|
import CustomWizardApi from '../models/custom-wizard-api';
|
||||||
|
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
|
queryParams: {
|
||||||
|
refresh_list: {
|
||||||
|
refreshModel: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
if (params.service === 'new') {
|
if (params.name === 'new') {
|
||||||
return CustomWizardApi.create();
|
return CustomWizardApi.create({ isNew: true });
|
||||||
} else {
|
} else {
|
||||||
return CustomWizardApi.find(params.service);
|
return CustomWizardApi.find(params.name);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,27 @@ export default Discourse.Route.extend({
|
||||||
return CustomWizardApi.list();
|
return CustomWizardApi.list();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
afterModel(model) {
|
||||||
|
const apiParams = this.paramsFor('admin-wizards-api');
|
||||||
|
|
||||||
|
if (model.length) {
|
||||||
|
if (!apiParams.name) {
|
||||||
|
this.transitionTo('adminWizardsApi', model[0].name.dasherize());
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.transitionTo('adminWizardsApi', 'new');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
setupController(controller, model){
|
setupController(controller, model){
|
||||||
controller.set("model", model);
|
controller.set("model", model);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
refreshModel() {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,51 +1,77 @@
|
||||||
<div class="wizard-api-header">
|
<div class="wizard-api-header page">
|
||||||
<div class="service">
|
<div class="metadata">
|
||||||
{{input value=api.service placeholder=(i18n 'admin.wizard.api.service')}}
|
<div class="title">
|
||||||
|
<label>{{i18n 'admin.wizard.api.title'}}</label>
|
||||||
|
{{input value=api.title placeholder=(i18n 'admin.wizard.api.title_placeholder')}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="name">
|
||||||
|
{{#if api.isNew}}
|
||||||
|
<label>{{i18n 'admin.wizard.api.name'}}</label>
|
||||||
|
{{input value=api.name placeholder=(i18n 'admin.wizard.api.name_placeholder')}}
|
||||||
|
{{else}}
|
||||||
|
{{api.name}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='buttons'>
|
<div class='buttons'>
|
||||||
{{#if savingApi}}
|
{{#if updating}}
|
||||||
{{loading-spinner size="small"}}
|
{{loading-spinner size="small"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{d-button label="admin.wizard.api.save" action="save" class="btn-primary"}}
|
|
||||||
{{d-button action="removeApi" label="admin.wizard.api.remove"}}
|
{{d-button label="admin.wizard.api.save" action="save" class="btn-primary" disabled=saveDisabled}}
|
||||||
|
|
||||||
|
{{#if showRemove}}
|
||||||
|
{{d-button action="remove" label="admin.wizard.api.remove"}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header">
|
<div class="wizard-api-header">
|
||||||
{{i18n 'admin.wizard.api.auth'}}
|
<div class="wizard-header">
|
||||||
|
{{i18n 'admin.wizard.api.auth.label'}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
{{d-button label="admin.wizard.api.auth.btn" action="authorize" disabled=authDisabled class="btn-primary"}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-api-authentication">
|
<div class="wizard-api-authentication">
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
|
|
||||||
<div class="wizard-header medium">
|
<div class="wizard-header medium">
|
||||||
{{i18n 'admin.wizard.api.auth_settings'}}
|
{{i18n 'admin.wizard.api.auth.settings'}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
{{#if api.name}}
|
||||||
|
<div class="control-group redirect-uri">
|
||||||
<div class="control-label">
|
<div class="control-label">
|
||||||
<span>{{i18n 'admin.wizard.api.redirect_uri'}}</span>
|
<label>{{i18n 'admin.wizard.api.auth.redirect_uri'}}</label>
|
||||||
<span>{{api.redirectUri}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label>{{i18n 'admin.wizard.api.auth_type'}}</label>
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{combo-box value=api.authType content=authorizationTypes none='admin.wizard.api.auth_type_none'}}
|
{{api.redirectUri}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="control-group auth-type">
|
||||||
|
<label>{{i18n 'admin.wizard.api.auth.type'}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{combo-box value=api.authType content=authorizationTypes none='admin.wizard.api.auth.type_none'}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n 'admin.wizard.api.auth_url'}}</label>
|
<label>{{i18n 'admin.wizard.api.auth.url'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.authUrl}}
|
{{input value=api.authUrl}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n 'admin.wizard.api.token_url'}}</label>
|
<label>{{i18n 'admin.wizard.api.auth.token_url'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.tokenUrl}}
|
{{input value=api.tokenUrl}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,85 +79,82 @@
|
||||||
|
|
||||||
{{#if isOauth}}
|
{{#if isOauth}}
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n 'admin.wizard.api.client_id'}}</label>
|
<label>{{i18n 'admin.wizard.api.auth.client_id'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.clientId}}
|
{{input value=api.clientId}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n 'admin.wizard.api.client_secret'}}</label>
|
<label>{{i18n 'admin.wizard.api.auth.client_secret'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.clientSecret}}
|
{{input value=api.clientSecret}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n 'admin.wizard.api.params'}}</label>
|
<label>{{i18n 'admin.wizard.api.auth.params.label'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{#each api.authParams as |param|}}
|
{{#each api.authParams as |param|}}
|
||||||
<div class="param">
|
<div class="param">
|
||||||
{{input value=param.key placeholder=(i18n 'admin.wizard.api.param_key')}}
|
{{input value=param.key placeholder=(i18n 'admin.wizard.api.auth.params.key')}}
|
||||||
{{input value=param.value placeholder=(i18n 'admin.wizard.api.param_value')}}
|
{{input value=param.value placeholder=(i18n 'admin.wizard.api.auth.params.value')}}
|
||||||
{{d-button action='removeParam' actionParam=param icon='times'}}
|
{{d-button action='removeParam' actionParam=param icon='times'}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{d-button label='admin.wizard.api.param_new' icon='plus' action='addParam'}}
|
{{d-button label='admin.wizard.api.auth.params.new' icon='plus' action='addParam'}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="actions">
|
|
||||||
{{d-button label="admin.wizard.api.authorize" action="authorize"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<div class="wizard-header medium">
|
|
||||||
{{i18n 'admin.wizard.api.auth_status'}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="authorization">
|
<div class="authorization">
|
||||||
{{#if api.authorized}}
|
{{#if api.authorized}}
|
||||||
<span class="authorization-indicator authorized"></span>
|
<span class="authorization-indicator authorized"></span>
|
||||||
<span>{{i18n "admin.wizard.api.authorized"}}</span>
|
<span>{{i18n "admin.wizard.api.status.authorized"}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="authorization-indicator not-authorized"></span>
|
<span class="authorization-indicator not-authorized"></span>
|
||||||
<span>{{i18n "admin.wizard.api.not_authorized"}}</span>
|
<span>{{i18n "admin.wizard.api.status.not_authorized"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="wizard-header medium">
|
||||||
|
{{i18n 'admin.wizard.api.status.label'}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>Access Token:</label>
|
<label>{{i18n 'admin.wizard.api.status.code'}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{api.code}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n 'admin.wizard.api.status.access_token'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{api.accessToken}}
|
{{api.accessToken}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>Expires At:</label>
|
<label>{{i18n 'admin.wizard.api.status.refresh_token'}}</label>
|
||||||
<div class="controls">
|
|
||||||
{{api.tokenExpiresAt}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label>Refresh At:</label>
|
|
||||||
<div class="controls">
|
|
||||||
{{api.tokenRefreshAt}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label>Refresh Token:</label>
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{api.refreshToken}}
|
{{api.refreshToken}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>Code:</label>
|
<label>{{i18n 'admin.wizard.api.status.expires_at'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{api.code}}
|
{{api.tokenExpiresAt}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n 'admin.wizard.api.status.refresh_at'}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{api.tokenRefreshAt}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -144,6 +167,7 @@
|
||||||
<div class="wizard-api-endpoints">
|
<div class="wizard-api-endpoints">
|
||||||
{{d-button action='addEndpoint' label='admin.wizard.api.endpoint.add' icon='plus'}}
|
{{d-button action='addEndpoint' label='admin.wizard.api.endpoint.add' icon='plus'}}
|
||||||
|
|
||||||
|
{{#if api.endpoints}}
|
||||||
<div class="endpoint-list">
|
<div class="endpoint-list">
|
||||||
<ul>
|
<ul>
|
||||||
{{#each api.endpoints as |endpoint|}}
|
{{#each api.endpoints as |endpoint|}}
|
||||||
|
@ -157,4 +181,5 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,13 @@
|
||||||
<ul>
|
<ul>
|
||||||
{{#each model as |api|}}
|
{{#each model as |api|}}
|
||||||
<li>
|
<li>
|
||||||
{{#link-to "adminWizardsApi" api.service}}{{api.service}}{{/link-to}}
|
{{#link-to "adminWizardsApi" (dasherize api.name)}}
|
||||||
|
{{#if api.title}}
|
||||||
|
{{api.title}}
|
||||||
|
{{else}}
|
||||||
|
{{api.name}}
|
||||||
|
{{/if}}
|
||||||
|
{{/link-to}}
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -308,12 +308,23 @@
|
||||||
.content-list {
|
.content-list {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.new-api {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata .title input {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-api-header {
|
.wizard-api-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&.page {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-api-authentication {
|
.wizard-api-authentication {
|
||||||
|
@ -324,8 +335,37 @@
|
||||||
|
|
||||||
.settings {
|
.settings {
|
||||||
border-right: 1px solid #333;
|
border-right: 1px solid #333;
|
||||||
margin-right: 10px;
|
margin-right: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
|
width: 50%;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redirect-uri .controls {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-type .select-kit {
|
||||||
|
min-width: 210px;
|
||||||
|
width: 210px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
width: 50%;
|
||||||
|
max-width: 50%;
|
||||||
|
|
||||||
|
.wizard-header {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.authorization {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,36 +127,47 @@ en:
|
||||||
wizard_field: "Wizard Field"
|
wizard_field: "Wizard Field"
|
||||||
user_field: "User Field"
|
user_field: "User Field"
|
||||||
api:
|
api:
|
||||||
|
label: "API"
|
||||||
nav_label: 'APIs'
|
nav_label: 'APIs'
|
||||||
new: 'New Api'
|
new: 'New Api'
|
||||||
|
name: "Name (can't be changed)"
|
||||||
auth: "Authentication"
|
name_placeholder: 'Underscored'
|
||||||
auth_settings: "Settings"
|
title: 'Title'
|
||||||
auth_status: "Status"
|
title_placeholder: 'Display name'
|
||||||
service: 'Api Service'
|
|
||||||
redirect_uri: "Redirect Uri"
|
|
||||||
auth_type: 'Authorization Type'
|
|
||||||
auth_type_none: 'Select a type'
|
|
||||||
token_url: "Token Url"
|
|
||||||
auth_url: 'Authorization Url'
|
|
||||||
client_id: 'Client Id'
|
|
||||||
client_secret: 'Client Secret'
|
|
||||||
|
|
||||||
status: "Status"
|
|
||||||
authorized: 'Authorized'
|
|
||||||
not_authorized: "Not Authorized"
|
|
||||||
params: 'Params'
|
|
||||||
param_new: 'New Param'
|
|
||||||
param_key: 'Param Key'
|
|
||||||
param_value: 'Param Value'
|
|
||||||
|
|
||||||
remove: 'Delete'
|
remove: 'Delete'
|
||||||
authorize: 'Authorize'
|
|
||||||
save: "Save"
|
save: "Save"
|
||||||
|
|
||||||
|
auth:
|
||||||
|
label: "Authorization"
|
||||||
|
btn: 'Authorize'
|
||||||
|
settings: "Settings"
|
||||||
|
status: "Status"
|
||||||
|
redirect_uri: "Redirect url"
|
||||||
|
type: 'Type'
|
||||||
|
type_none: 'Select a type'
|
||||||
|
url: "Authorization url"
|
||||||
|
token_url: "Token url"
|
||||||
|
client_id: 'Client id'
|
||||||
|
client_secret: 'Client secret'
|
||||||
|
params:
|
||||||
|
label: 'Params'
|
||||||
|
new: 'New param'
|
||||||
|
key: 'key'
|
||||||
|
value: 'value'
|
||||||
|
|
||||||
|
status:
|
||||||
|
label: "Status"
|
||||||
|
authorized: 'Authorized'
|
||||||
|
not_authorized: "Not authorized"
|
||||||
|
code: "Code"
|
||||||
|
access_token: "Access token"
|
||||||
|
refresh_token: "Refresh token"
|
||||||
|
expires_at: "Expires at"
|
||||||
|
refresh_at: "Refresh at"
|
||||||
|
|
||||||
endpoint:
|
endpoint:
|
||||||
label: "Endpoints"
|
label: "Endpoints"
|
||||||
add: "Add Endpoint"
|
add: "Add endpoint"
|
||||||
method: "Select a method"
|
method: "Select a method"
|
||||||
url: "Enter a url"
|
url: "Enter a url"
|
||||||
|
|
||||||
|
|
|
@ -11,55 +11,75 @@ class CustomWizard::ApiController < ::ApplicationController
|
||||||
CustomWizard::Api.list,
|
CustomWizard::Api.list,
|
||||||
each_serializer: CustomWizard::BasicApiSerializer
|
each_serializer: CustomWizard::BasicApiSerializer
|
||||||
)
|
)
|
||||||
|
|
||||||
render json: MultiJson.dump(serializer)
|
render json: MultiJson.dump(serializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def find
|
def find
|
||||||
params.require(:service)
|
render_serialized(CustomWizard::Api.get(api_params[:name]), CustomWizard::ApiSerializer, root: false)
|
||||||
render_serialized(CustomWizard::Api.new(params[:service]), CustomWizard::ApiSerializer, root: false)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
byebug
|
current = CustomWizard::Api.get(api_params[:name])
|
||||||
params.require(:service)
|
|
||||||
service = params.permit(:service)
|
|
||||||
auth_data = params[:auth_params]
|
|
||||||
endpoints_data = params[:endpoints]
|
|
||||||
|
|
||||||
service_auth_data = JSON.parse(auth_data) if !auth_data.nil?
|
if api_params[:new] && current
|
||||||
service_endpoints = JSON.parse(endpoints_data) if !endpoints_data.nil?
|
raise Discourse::InvalidParameters, "An API with that name already exists: '#{current.title || current.name}'"
|
||||||
|
|
||||||
if !service_auth_data.nil?
|
|
||||||
CustomWizard::Api::Authorization.set(service, service_auth_data)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if !service_endpoints.nil?
|
PluginStoreRow.transaction do
|
||||||
service_endpoints.each do |endpoint|
|
CustomWizard::Api.set(api_params[:name], title: api_params[:title])
|
||||||
CustomWizard::Api::Endpoint.set(service, endpoint)
|
|
||||||
|
if auth_data.present?
|
||||||
|
CustomWizard::Api::Authorization.set(api_params[:name], auth_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
if api_params[:endpoints].is_a? String
|
||||||
|
begin
|
||||||
|
endpoints = JSON.parse(api_params[:endpoints])
|
||||||
|
endpoints.each do |endpoint|
|
||||||
|
CustomWizard::Api::Endpoint.set(api_params[:name], endpoint)
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
puts e
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: success_json.merge(
|
render json: success_json.merge(
|
||||||
api: CustomWizard::ApiSerializer.new(params[:service], root: false)
|
api: CustomWizard::ApiSerializer.new(
|
||||||
|
CustomWizard::Api.new(api_params[:name]),
|
||||||
|
root: false
|
||||||
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove
|
||||||
|
PluginStoreRow.transaction do
|
||||||
|
CustomWizard::Api.remove(api_params[:name])
|
||||||
|
CustomWizard::Api::Authorization.remove(api_params[:name])
|
||||||
|
CustomWizard::Api::Endpoint.remove(api_params[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
render json: success_json
|
||||||
|
end
|
||||||
|
|
||||||
def redirect
|
def redirect
|
||||||
params.require(:service)
|
params.require(:name)
|
||||||
params.require(:code)
|
params.require(:code)
|
||||||
|
|
||||||
CustomWizard::Api::Authorization.set(params[:service], code: params[:code])
|
CustomWizard::Api::Authorization.set(params[:name], code: params[:code])
|
||||||
|
CustomWizard::Api::Authorization.get_token(params[:name])
|
||||||
|
|
||||||
CustomWizard::Api::Authorization.get_token(params[:service])
|
return redirect_to path('/admin/wizards/apis/' + params[:name])
|
||||||
|
|
||||||
return redirect_to path('/admin/wizards/apis/' + params[:service])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def auth_data
|
def api_params
|
||||||
@auth_data ||= params.permit(
|
params.require(:name)
|
||||||
|
|
||||||
|
data = params.permit(
|
||||||
|
:name,
|
||||||
|
:title,
|
||||||
:auth_type,
|
:auth_type,
|
||||||
:auth_url,
|
:auth_url,
|
||||||
:token_url,
|
:token_url,
|
||||||
|
@ -67,11 +87,30 @@ class CustomWizard::ApiController < ::ApplicationController
|
||||||
:client_secret,
|
:client_secret,
|
||||||
:username,
|
:username,
|
||||||
:password,
|
:password,
|
||||||
:auth_params
|
:auth_params,
|
||||||
|
:endpoints,
|
||||||
|
:new
|
||||||
).to_h
|
).to_h
|
||||||
|
|
||||||
|
data[:name] = data[:name].underscore
|
||||||
|
|
||||||
|
@api_params ||= data
|
||||||
end
|
end
|
||||||
|
|
||||||
def endpoint_data
|
def auth_data
|
||||||
@endpoint_data ||= JSON.parse(params.permit(endpoints: [:id, :type, :url]))
|
auth_data = api_params.slice(
|
||||||
|
:auth_type,
|
||||||
|
:auth_url,
|
||||||
|
:token_url,
|
||||||
|
:client_id,
|
||||||
|
:client_secret,
|
||||||
|
:username,
|
||||||
|
:password,
|
||||||
|
:params
|
||||||
|
)
|
||||||
|
|
||||||
|
auth_data[:params] = JSON.parse(auth_data[:params]) if auth_data[:params].present?
|
||||||
|
|
||||||
|
@auth_data ||= auth_data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module Jobs
|
module Jobs
|
||||||
class RefreshApiAccessToken < Jobs::Base
|
class RefreshApiAccessToken < Jobs::Base
|
||||||
def execute(args)
|
def execute(args)
|
||||||
CustomWizard::Api::Authorization.refresh_token(args[:service])
|
CustomWizard::Api::Authorization.refresh_token(args[:name])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
class CustomWizard::Api
|
class CustomWizard::Api
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
attr_accessor :service
|
attr_accessor :name,
|
||||||
|
:title
|
||||||
|
|
||||||
def initialize(service)
|
def initialize(name, data={})
|
||||||
@service = service
|
@name = name
|
||||||
|
@title = data['title']
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.set(name, data)
|
||||||
|
PluginStore.set("custom_wizard_api_#{name}", "metadata", data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get(name)
|
||||||
|
if data = PluginStore.get("custom_wizard_api_#{name}", "metadata")
|
||||||
|
self.new(name, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove(name)
|
||||||
|
PluginStore.remove("custom_wizard_api_#{name}", "metadata")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.list
|
def self.list
|
||||||
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_%' AND key = 'authorization'")
|
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_%' AND key = 'metadata'")
|
||||||
.map do |record|
|
.map do |record|
|
||||||
self.new(record['plugin_name'].split('_').last)
|
self.new(record['plugin_name'].sub("custom_wizard_api_", ""), ::JSON.parse(record['value']))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ class CustomWizard::Api::Authorization
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
attr_accessor :authorized,
|
attr_accessor :authorized,
|
||||||
:service,
|
:name,
|
||||||
:auth_type,
|
:auth_type,
|
||||||
:auth_url,
|
:auth_url,
|
||||||
:token_url,
|
:token_url,
|
||||||
|
@ -19,65 +19,72 @@ class CustomWizard::Api::Authorization
|
||||||
:username,
|
:username,
|
||||||
:password
|
:password
|
||||||
|
|
||||||
def initialize(service, params)
|
def initialize(name, data, opts = {})
|
||||||
@service = service
|
unless opts[:data_only]
|
||||||
data = params.is_a?(String) ? ::JSON.parse(params) : params
|
@name = name
|
||||||
|
end
|
||||||
|
|
||||||
|
if data = data.is_a?(String) ? ::JSON.parse(data) : data
|
||||||
data.each do |k, v|
|
data.each do |k, v|
|
||||||
self.send "#{k}=", v if self.respond_to?(k)
|
self.send "#{k}=", v if self.respond_to?(k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def authorized
|
def authorized
|
||||||
@authorized ||= @access_token && @token_expires_at.to_datetime > Time.now
|
@authorized ||= @access_token && @token_expires_at.to_datetime > Time.now
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.set(service, data)
|
def self.set(name, data = {})
|
||||||
model = self.get(service) || {}
|
record = self.get(name, data_only: true)
|
||||||
|
|
||||||
data.each do |k, v|
|
data.each do |k, v|
|
||||||
model.send "#{k}=", v if model.respond_to?(k)
|
record.send "#{k}=", v if record.respond_to?(k)
|
||||||
end
|
end
|
||||||
|
|
||||||
PluginStore.set("custom_wizard_api_#{service}", 'authorization', model.as_json)
|
PluginStore.set("custom_wizard_api_#{name}", 'authorization', record.as_json)
|
||||||
|
|
||||||
self.get(service)
|
self.get(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get(service)
|
def self.get(name, opts = {})
|
||||||
data = PluginStore.get("custom_wizard_api_#{service}", 'authorization')
|
data = PluginStore.get("custom_wizard_api_#{name}", 'authorization')
|
||||||
self.new(service, data)
|
self.new(name, data, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get_header_authorization_string(service)
|
def self.remove(name)
|
||||||
protocol = authentication_protocol(service)
|
PluginStore.remove("custom_wizard_api_#{name}", "authorization")
|
||||||
raise Discourse::InvalidParameters.new(:service) unless protocol.present?
|
end
|
||||||
|
|
||||||
|
def self.get_header_authorization_string(name)
|
||||||
|
protocol = authentication_protocol(name)
|
||||||
|
raise Discourse::InvalidParameters.new(:name) unless protocol.present?
|
||||||
raise Discourse::InvalidParameters.new(:protocol) unless [BASIC_AUTH, OAUTH2_AUTH].include? protocol
|
raise Discourse::InvalidParameters.new(:protocol) unless [BASIC_AUTH, OAUTH2_AUTH].include? protocol
|
||||||
|
|
||||||
if protocol = BASIC_AUTH
|
if protocol = BASIC_AUTH
|
||||||
username = username(service)
|
username = username(name)
|
||||||
raise Discourse::InvalidParameters.new(:username) unless username.present?
|
raise Discourse::InvalidParameters.new(:username) unless username.present?
|
||||||
password = password(service)
|
password = password(name)
|
||||||
raise Discourse::InvalidParameters.new(:password) unless password.present?
|
raise Discourse::InvalidParameters.new(:password) unless password.present?
|
||||||
authorization_string = (username + ":" + password).chomp
|
authorization_string = (username + ":" + password).chomp
|
||||||
"Basic #{Base64.strict_encode64(authorization_string)}"
|
"Basic #{Base64.strict_encode64(authorization_string)}"
|
||||||
else
|
else
|
||||||
# must be OAUTH2
|
# must be OAUTH2
|
||||||
access_token = access_token(service)
|
access_token = access_token(name)
|
||||||
raise Discourse::InvalidParameters.new(access_token) unless access_token.present?
|
raise Discourse::InvalidParameters.new(access_token) unless access_token.present?
|
||||||
"Bearer #{access_token}"
|
"Bearer #{access_token}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get_token(service)
|
def self.get_token(name)
|
||||||
authorization = CustomWizard::Api::Authorization.get(service)
|
authorization = CustomWizard::Api::Authorization.get(name)
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
client_id: authorization.client_id,
|
client_id: authorization.client_id,
|
||||||
client_secret: authorization.client_secret,
|
client_secret: authorization.client_secret,
|
||||||
code: authorization.code,
|
code: authorization.code,
|
||||||
grant_type: 'authorization_code',
|
grant_type: 'authorization_code',
|
||||||
redirect_uri: Discourse.base_url + "/admin/wizards/apis/#{service}/redirect"
|
redirect_uri: Discourse.base_url + "/admin/wizards/apis/#{name}/redirect"
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Excon.post(
|
result = Excon.post(
|
||||||
|
@ -88,11 +95,11 @@ class CustomWizard::Api::Authorization
|
||||||
:body => URI.encode_www_form(body)
|
:body => URI.encode_www_form(body)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.handle_token_result(service, result)
|
self.handle_token_result(name, result)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.refresh_token(service)
|
def self.refresh_token(name)
|
||||||
authorization = CustomWizard::Api::Authorization.get(service)
|
authorization = CustomWizard::Api::Authorization.get(name)
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
grant_type: 'refresh_token',
|
grant_type: 'refresh_token',
|
||||||
|
@ -110,10 +117,10 @@ class CustomWizard::Api::Authorization
|
||||||
:body => URI.encode_www_form(body)
|
:body => URI.encode_www_form(body)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.handle_token_result(service, result)
|
self.handle_token_result(name, result)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.handle_token_result(service, result)
|
def self.handle_token_result(name, result)
|
||||||
data = JSON.parse(result.body)
|
data = JSON.parse(result.body)
|
||||||
|
|
||||||
return false if (data['error'])
|
return false if (data['error'])
|
||||||
|
@ -124,12 +131,12 @@ class CustomWizard::Api::Authorization
|
||||||
refresh_at = expires_at.to_time - 2.hours
|
refresh_at = expires_at.to_time - 2.hours
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
service: service
|
name: name
|
||||||
}
|
}
|
||||||
|
|
||||||
Jobs.enqueue_at(refresh_at, :refresh_api_access_token, opts)
|
Jobs.enqueue_at(refresh_at, :refresh_api_access_token, opts)
|
||||||
|
|
||||||
CustomWizard::Api::Authorization.set(service,
|
CustomWizard::Api::Authorization.set(name,
|
||||||
access_token: access_token,
|
access_token: access_token,
|
||||||
refresh_token: refresh_token,
|
refresh_token: refresh_token,
|
||||||
token_expires_at: expires_at,
|
token_expires_at: expires_at,
|
||||||
|
|
|
@ -5,42 +5,46 @@ class CustomWizard::Api::Endpoint
|
||||||
:method,
|
:method,
|
||||||
:url
|
:url
|
||||||
|
|
||||||
def initialize(service, params)
|
def initialize(name, params)
|
||||||
@service = service
|
@name = name
|
||||||
data = params.is_a?(String) ? ::JSON.parse(params) : params
|
if data = params.is_a?(String) ? ::JSON.parse(params) : params
|
||||||
|
|
||||||
data.each do |k, v|
|
data.each do |k, v|
|
||||||
self.send "#{k}=", v if self.respond_to?(k)
|
self.send "#{k}=", v if self.respond_to?(k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.set(service, data)
|
def self.set(name, data)
|
||||||
model = data[:endpoint_id] ? self.get(service, data[:endpoint_id]) : {}
|
model = data[:endpoint_id] ? self.get(name, data[:endpoint_id]) : {}
|
||||||
endpoint_id = model[:endpoint_id] || SecureRandom.hex(8)
|
endpoint_id = model[:endpoint_id] || SecureRandom.hex(8)
|
||||||
|
|
||||||
data.each do |k, v|
|
data.each do |k, v|
|
||||||
model.send "#{k}=", v if model.respond_to?(k)
|
model.send "#{k}=", v if model.respond_to?(k)
|
||||||
end
|
end
|
||||||
|
|
||||||
PluginStore.set("custom_wizard_api_#{service}", "endpoint_#{endpoint_id}", model.as_json)
|
PluginStore.set("custom_wizard_api_#{name}", "endpoint_#{endpoint_id}", model.as_json)
|
||||||
|
|
||||||
self.get(service)
|
self.get(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get(service, endpoint_id)
|
def self.get(name, endpoint_id)
|
||||||
return nil if !endpoint_id
|
return nil if !endpoint_id
|
||||||
data = PluginStore.get("custom_wizard_api_#{service}", "endpoint_#{endpoint_id}")
|
data = PluginStore.get("custom_wizard_api_#{name}", "endpoint_#{endpoint_id}")
|
||||||
data[:id] = endpoint_id
|
data[:id] = endpoint_id
|
||||||
self.new(service, data)
|
self.new(name, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove(name)
|
||||||
|
PluginStoreRow.where("plugin_name = 'custom_wizard_api_#{name}' AND key LIKE 'endpoint_%'").destroy_all
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.list
|
def self.list
|
||||||
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_%' AND key LIKE 'endpoint_%'")
|
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_%' AND key LIKE 'endpoint_%'")
|
||||||
.map do |record|
|
.map do |record|
|
||||||
service = record['plugin_name'].split('_').last
|
name = record['plugin_name'].sub("custom_wizard_api_", "")
|
||||||
data = ::JSON.parse(record['value'])
|
data = ::JSON.parse(record['value'])
|
||||||
data[:id] = record['key'].split('_').last
|
data[:id] = record['key'].split('_').last
|
||||||
self.new(service, data)
|
self.new(name, data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,9 +69,10 @@ after_initialize do
|
||||||
get 'admin/wizards/submissions/:wizard_id' => 'admin#submissions'
|
get 'admin/wizards/submissions/:wizard_id' => 'admin#submissions'
|
||||||
get 'admin/wizards/apis' => 'api#list'
|
get 'admin/wizards/apis' => 'api#list'
|
||||||
get 'admin/wizards/apis/new' => 'api#index'
|
get 'admin/wizards/apis/new' => 'api#index'
|
||||||
get 'admin/wizards/apis/:service' => 'api#find'
|
get 'admin/wizards/apis/:name' => 'api#find'
|
||||||
put 'admin/wizards/apis/:service' => 'api#save'
|
put 'admin/wizards/apis/:name' => 'api#save'
|
||||||
get 'admin/wizards/apis/:service/redirect' => 'api#redirect'
|
delete 'admin/wizards/apis/:name' => 'api#remove'
|
||||||
|
get 'admin/wizards/apis/:name/redirect' => 'api#redirect'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
class CustomWizard::ApiSerializer < ApplicationSerializer
|
class CustomWizard::ApiSerializer < ApplicationSerializer
|
||||||
attributes :service,
|
attributes :name,
|
||||||
|
:title,
|
||||||
:authorization,
|
:authorization,
|
||||||
:endpoints
|
:endpoints
|
||||||
|
|
||||||
def authorization
|
def authorization
|
||||||
|
if authorization = CustomWizard::Api::Authorization.get(object.name)
|
||||||
CustomWizard::Api::AuthorizationSerializer.new(
|
CustomWizard::Api::AuthorizationSerializer.new(
|
||||||
CustomWizard::Api::Authorization.get(object.service),
|
authorization,
|
||||||
root: false
|
root: false
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def endpoints
|
def endpoints
|
||||||
|
if endpoints = CustomWizard::Api::Endpoint.list
|
||||||
ActiveModel::ArraySerializer.new(
|
ActiveModel::ArraySerializer.new(
|
||||||
CustomWizard::Api::Endpoint.list,
|
endpoints,
|
||||||
each_serializer: CustomWizard::Api::EndpointSerializer
|
each_serializer: CustomWizard::Api::EndpointSerializer
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
class CustomWizard::BasicApiSerializer < ApplicationSerializer
|
class CustomWizard::BasicApiSerializer < ApplicationSerializer
|
||||||
attributes :service
|
attributes :name, :title
|
||||||
end
|
end
|
||||||
|
|
Laden …
In neuem Issue referenzieren