1
0
Fork 0

Improve flexibility and structure of send_to_api action

Dieser Commit ist enthalten in:
Angus McLeod 2019-08-13 14:11:46 +10:00
Ursprung 6ad821024a
Commit 30390e8264
10 geänderte Dateien mit 92 neuen und 56 gelöschten Zeilen

Datei anzeigen

@ -11,6 +11,8 @@ export default Ember.Controller.extend({
showRemove: Ember.computed.not('isNew'), showRemove: Ember.computed.not('isNew'),
showRedirectUri: Ember.computed.and('threeLeggedOauth', 'api.name'), showRedirectUri: Ember.computed.and('threeLeggedOauth', 'api.name'),
responseIcon: null, responseIcon: null,
contentTypes: ['application/json', 'application/x-www-form-urlencoded'],
successCodes: [100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 303, 304, 305, 306, 307, 308],
@computed('saveDisabled', 'api.authType', 'api.authUrl', 'api.tokenUrl', 'api.clientId', 'api.clientSecret', 'threeLeggedOauth') @computed('saveDisabled', 'api.authType', 'api.authUrl', 'api.tokenUrl', 'api.clientId', 'api.clientSecret', 'threeLeggedOauth')
authDisabled(saveDisabled, authType, authUrl, tokenUrl, clientId, clientSecret, threeLeggedOauth) { authDisabled(saveDisabled, authType, authUrl, tokenUrl, clientId, clientSecret, threeLeggedOauth) {
@ -24,7 +26,7 @@ export default Ember.Controller.extend({
return !name || !authType; return !name || !authType;
}, },
authorizationTypes: ['basic', 'oauth_2', 'oauth_3'], authorizationTypes: ['none', 'basic', 'oauth_2', 'oauth_3'],
isBasicAuth: Ember.computed.equal('api.authType', 'basic'), isBasicAuth: Ember.computed.equal('api.authType', 'basic'),
@computed('api.authType') @computed('api.authType')
@ -124,13 +126,15 @@ export default Ember.Controller.extend({
requiredParams = ['authUrl', 'tokenUrl', 'clientId', 'clientSecret']; requiredParams = ['authUrl', 'tokenUrl', 'clientId', 'clientSecret'];
} }
for (let rp of requiredParams) { if (requiredParams) {
if (!api[rp]) { for (let rp of requiredParams) {
let key = rp.replace('auth', ''); if (!api[rp]) {
error = `${I18n.t(`admin.wizard.api.auth.${key.underscore()}`)} is required for ${authType}`; let key = rp.replace('auth', '');
break; error = `${I18n.t(`admin.wizard.api.auth.${key.underscore()}`)} is required for ${authType}`;
break;
}
data[rp.underscore()] = api[rp];
} }
data[rp.underscore()] = api[rp];
} }
const params = api.authParams; const params = api.authParams;

Datei anzeigen

@ -228,18 +228,28 @@
<li> <li>
<div class="endpoint"> <div class="endpoint">
<div class="endpoint-"> <div class="endpoint-">
{{input value=endpoint.name <div class="top">
placeholder=(i18n 'admin.wizard.api.endpoint.name')}} {{input value=endpoint.name
{{combo-box content=endpointMethods placeholder=(i18n 'admin.wizard.api.endpoint.name')}}
value=endpoint.method {{input value=endpoint.url
none="admin.wizard.api.endpoint.method"}} placeholder=(i18n 'admin.wizard.api.endpoint.url')
{{input value=endpoint.url class='endpoint-url'}}
placeholder=(i18n 'admin.wizard.api.endpoint.url') {{d-button action=(action "removeEndpoint")
class='endpoint-url'}} actionParam=endpoint
{{d-button action=(action "removeEndpoint") icon='times'
actionParam=endpoint class='remove-endpoint'}}
icon='times' </div>
class='remove-endpoint'}} <div class="bottom">
{{combo-box content=endpointMethods
value=endpoint.method
none="admin.wizard.api.endpoint.method"}}
{{combo-box content=contentTypes
value=endpoint.content_type
none="admin.wizard.api.endpoint.content_type"}}
{{multi-select content=successCodes
values=endpoint.success_codes
none="admin.wizard.api.endpoint.success_codes"}}
</div>
</div> </div>
</div> </div>
</li> </li>

Datei anzeigen

@ -446,14 +446,19 @@
} }
.endpoint { .endpoint {
display: flex;
margin-top: 20px; margin-top: 20px;
.top, .bottom {
display: flex;
}
.top {
margin-bottom: 15px;
}
.combo-box { .combo-box {
width: 200px;
margin-right: 10px; margin-right: 10px;
margin-top: -2px; width: 210px;
width: 150px;
} }
input { input {
@ -462,7 +467,7 @@
} }
.endpoint-url { .endpoint-url {
width: 300px; flex: 1 1 auto;
} }
.remove-endpoint { .remove-endpoint {

Datei anzeigen

@ -211,6 +211,8 @@ en:
name: "Endpoint name" name: "Endpoint name"
method: "Select a method" method: "Select a method"
url: "Enter a url" url: "Enter a url"
content_type: "Select a content type"
success_codes: "Select success codes"
log: log:
label: "Logs" label: "Logs"

Datei anzeigen

@ -64,7 +64,7 @@ class CustomWizard::Api::Authorization
PluginStore.remove("custom_wizard_api_#{api_name}", "authorization") PluginStore.remove("custom_wizard_api_#{api_name}", "authorization")
end end
def self.get_header_authorization_string(name) def self.authorization_string(name)
auth = CustomWizard::Api::Authorization.get(name) auth = CustomWizard::Api::Authorization.get(name)
raise Discourse::InvalidParameters.new(:name) unless auth.present? raise Discourse::InvalidParameters.new(:name) unless auth.present?
@ -72,9 +72,11 @@ class CustomWizard::Api::Authorization
raise Discourse::InvalidParameters.new(:username) unless auth.username.present? raise Discourse::InvalidParameters.new(:username) unless auth.username.present?
raise Discourse::InvalidParameters.new(:password) unless auth.password.present? raise Discourse::InvalidParameters.new(:password) unless auth.password.present?
"Basic #{Base64.strict_encode64((auth.username + ":" + auth.password).chomp)}" "Basic #{Base64.strict_encode64((auth.username + ":" + auth.password).chomp)}"
else elsif ['oauth_3', 'oauth_2'].include?(auth.auth_type)
raise Discourse::InvalidParameters.new(auth.access_token) unless auth.access_token.present? raise Discourse::InvalidParameters.new(auth.access_token) unless auth.access_token.present?
"Bearer #{auth.access_token}" "Bearer #{auth.access_token}"
else
nil
end end
end end

Datei anzeigen

@ -5,7 +5,9 @@ class CustomWizard::Api::Endpoint
:name, :name,
:api_name, :api_name,
:method, :method,
:url :url,
:content_type,
:success_codes
def initialize(api_name, data={}) def initialize(api_name, data={})
@api_name = api_name @api_name = api_name
@ -62,40 +64,49 @@ class CustomWizard::Api::Endpoint
end end
end end
def self.request(user, api_name, endpoint_id, body) def self.request(user = Discourse.system_user, api_name, endpoint_id, body)
endpoint = self.get(api_name, endpoint_id) endpoint = self.get(api_name, endpoint_id)
auth = CustomWizard::Api::Authorization.get_header_authorization_string(api_name) auth_string = CustomWizard::Api::Authorization.authorization_string(api_name)
content_type = endpoint.content_type
headers = {}
headers["Authorization"] = auth_string if auth_string
headers["Content-Type"] = content_type if content_type
connection = Excon.new( connection = Excon.new(URI.parse(URI.encode(endpoint.url)).to_s, headers: headers)
URI.parse(URI.encode(endpoint.url)).to_s,
:headers => {
"Authorization" => auth,
"Accept" => "application/json, */*",
"Content-Type" => "application/json"
}
)
params = { params = { method: endpoint.method }
method: endpoint.method
}
if body if body
body = JSON.generate(body) if content_type === "application/json"
body.delete! '\\' body = JSON.generate(body)
elsif content_type === "application/x-www-form-urlencoded"
body = URI.encode_www_form(body)
end
params[:body] = body params[:body] = body
end end
begin response = connection.request(params)
response = connection.request(params)
log_params = {time: Time.now, user_id: user.id, status: 'SUCCESS', url: endpoint.url, error: ""} if endpoint.success_codes.include?(response.status)
begin
result = JSON.parse(response.body)
rescue JSON::ParserError
result = response.body
end
CustomWizard::Api::LogEntry.set(api_name, log_params) CustomWizard::Api::LogEntry.set(api_name, log_params(user, 'SUCCESS', endpoint.url))
return JSON.parse(response.body)
rescue result
# TODO: improve error detail else
log_params = {time: Time.now, user_id: user.id, status: 'FAILURE', url: endpoint.url, error: "API request failed"} message = "API request failed"
CustomWizard::Api::LogEntry.set(api_name, log_params) CustomWizard::Api::LogEntry.set(api_name, log_params(user, 'FAIL', endpoint.url, message))
return JSON.parse "[{\"error\":\"API request failed\"}]" { error: message }
end end
end end
def self.log_params(user, status, url, message = "")
{ time: Time.now, user_id: user.id, status: status, url: url, error: message }
end
end end

Datei anzeigen

@ -492,7 +492,7 @@ class CustomWizard::Builder
rescue JSON::ParserError rescue JSON::ParserError
raise Discourse::InvalidParameters, "Invalid API body definition: #{action['api_body']} for #{action['title']}" raise Discourse::InvalidParameters, "Invalid API body definition: #{action['api_body']} for #{action['title']}"
end end
api_body = CustomWizard::Builder.fill_placeholders(JSON.generate(api_body_parsed), user, data) api_body = JSON.parse(CustomWizard::Builder.fill_placeholders(JSON.generate(api_body_parsed), user, data))
end end
result = CustomWizard::Api::Endpoint.request(user, action['api'], action['api_endpoint'], api_body) result = CustomWizard::Api::Endpoint.request(user, action['api'], action['api_endpoint'], api_body)

Datei anzeigen

@ -101,7 +101,7 @@ after_initialize do
load File.expand_path('../lib/api/api.rb', __FILE__) load File.expand_path('../lib/api/api.rb', __FILE__)
load File.expand_path('../lib/api/authorization.rb', __FILE__) load File.expand_path('../lib/api/authorization.rb', __FILE__)
load File.expand_path('../lib/api/endpoint.rb', __FILE__) load File.expand_path('../lib/api/endpoint.rb', __FILE__)
load File.expand_path('../lib/api/logentry.rb', __FILE__) load File.expand_path('../lib/api/log_entry.rb', __FILE__)
load File.expand_path('../controllers/api.rb', __FILE__) load File.expand_path('../controllers/api.rb', __FILE__)
load File.expand_path('../serializers/api/api_serializer.rb', __FILE__) load File.expand_path('../serializers/api/api_serializer.rb', __FILE__)
load File.expand_path('../serializers/api/authorization_serializer.rb', __FILE__) load File.expand_path('../serializers/api/authorization_serializer.rb', __FILE__)

Datei anzeigen

@ -2,7 +2,9 @@ class CustomWizard::Api::EndpointSerializer < ApplicationSerializer
attributes :id, attributes :id,
:name, :name,
:method, :method,
:url :url,
:content_type,
:success_codes
def method def method
object.send('method') object.send('method')