From 48e084df3d4a6f18d5db228b8514b45ddacebdb9 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 13 Nov 2016 22:16:17 +0100 Subject: [PATCH] Improved oauth admin area. --- .../_application_controller_table.coffee | 9 +- .../javascripts/app/controllers/api.coffee | 102 ++++++++++++++++-- .../javascripts/app/models/application.coffee | 9 +- app/assets/javascripts/app/views/api.jst.eco | 1 + app/controllers/application_controller.rb | 4 + app/controllers/applications_controller.rb | 12 ++- .../routes/{doorkeeper.rb => applications.rb} | 1 + 7 files changed, 119 insertions(+), 19 deletions(-) rename config/routes/{doorkeeper.rb => applications.rb} (86%) diff --git a/app/assets/javascripts/app/controllers/_application_controller_table.coffee b/app/assets/javascripts/app/controllers/_application_controller_table.coffee index b1e9cbee8..41bd1b3f8 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_table.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_table.coffee @@ -76,14 +76,15 @@ class App.ControllerTable extends App.Controller e.preventDefault() console.log('checkboxClick', e.target) - callbackHeader = (header) -> - console.log('current header is', header) + callbackHeader = (headers) -> + console.log('current header is', headers) # add new header item attribute = name: 'some name' display: 'Some Name' - header.push attribute - console.log('new header is', header) + headers.push attribute + console.log('new header is', headers) + headers callbackAttributes = (value, object, attribute, header, refObject) -> console.log('data of item col', value, object, attribute, header, refObject) diff --git a/app/assets/javascripts/app/controllers/api.coffee b/app/assets/javascripts/app/controllers/api.coffee index 50cd78ce1..bcc0ab6fc 100644 --- a/app/assets/javascripts/app/controllers/api.coffee +++ b/app/assets/javascripts/app/controllers/api.coffee @@ -34,20 +34,47 @@ class Index extends App.ControllerSubContent App.Setting.unsubscribe(@subscribeApplicationId) table = => + + callbackHeader = (headers) -> + attribute = + name: 'view' + display: 'View' + headers.splice(3, 0, attribute) + attribute = + name: 'token' + display: 'Token' + headers.splice(4, 0, attribute) + headers + + callbackViewAttributes = (value, object, attribute, header, refObject) -> + value = 'X' + value + + callbackTokenAttributes = (value, object, attribute, header, refObject) -> + value = 'X' + value + new App.ControllerTable( - el: @$('.js-appList') - model: App.Application - table_id: 'applications' - objects: App.Application.all() + el: @$('.js-appList') + model: App.Application + table_id: 'applications' + objects: App.Application.all() bindRow: events: 'click': @appEdit + bindCol: + view: + events: + 'click': @appView + token: + events: + 'click': @appToken + callbackHeader: [callbackHeader] + callbackAttributes: + view: [callbackViewAttributes] + token: [callbackTokenAttributes] ) table() - #App.Application.fetchFull( - # table - # clear: true - #) @subscribeApplicationId = App.Application.subscribe(table, initFetch: true, clear: true) @@ -82,6 +109,18 @@ class Index extends App.ControllerSubContent value = @PasswordAccess.prop('checked') App.Setting.set('api_password_access', value) + appToken: (id, e) -> + e.preventDefault() + new ViewAppTokenModal( + app: App.Application.find(id) + ) + + appView: (id, e) -> + e.preventDefault() + new ViewAppModal( + app: App.Application.find(id) + ) + appNew: (e) -> e.preventDefault() new App.ControllerGenericNew( @@ -107,4 +146,51 @@ class Index extends App.ControllerSubContent container: @el.closest('.content') ) +class ViewAppModal extends App.ControllerModal + headPrefix: 'App' + buttonSubmit: false + buttonCancel: true + shown: true + small: true + events: + 'click .js-select': 'selectAll' + + constructor: (params) -> + @head = params.app.name + super + + content: -> + "AppID: +
+ Secret: " + +class ViewAppTokenModal extends App.ControllerModal + headPrefix: 'Generate Token' + buttonSubmit: 'Generate Token' + buttonCancel: true + shown: true + small: true + events: + 'click .js-select': 'selectAll' + + constructor: (params) -> + @head = params.app.name + super + + content: -> + "#{App.i18n.translateContent('Generate Access Token for |%s|', App.Session.get().displayNameLong())}" + + onSubmit: => + @ajax( + id: 'application_token' + type: 'POST' + url: "#{@apiPath}/applications/token" + processData: true + data: JSON.stringify(id: @app.id) + success: (data, status, xhr) => + @contentInline = "#{App.i18n.translateContent('New Access Token is')}: " + @update() + @$('.js-submit').remove() + ) + App.Config.set('API', { prio: 1200, name: 'API', parent: '#system', target: '#system/api', controller: Index, permission: ['admin.api'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/models/application.coffee b/app/assets/javascripts/app/models/application.coffee index 4bad86d8b..e31faa35e 100644 --- a/app/assets/javascripts/app/models/application.coffee +++ b/app/assets/javascripts/app/models/application.coffee @@ -1,17 +1,16 @@ class App.Application extends App.Model - @configure 'Application', 'name', 'redirect_uri', 'uid', 'secret' + @configure 'Application', 'name', 'redirect_uri' @extend Spine.Model.Ajax @url: @apiPath + '/applications' @configure_attributes = [ { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false }, - { name: 'redirect_uri', display: 'Redirect URI', tag: 'textarea', limit: 250, null: false, note: 'Use one line per URI' }, - { name: 'uid', display: 'Application ID', tag: 'input', type: 'text', null: true, readonly: 1 }, - { name: 'secret', display: 'Application secret', tag: 'input', type: 'text', null: true }, + { name: 'redirect_uri', display: 'Callback URL', tag: 'textarea', limit: 250, null: false, note: 'Use one line per URI' }, + { name: 'clients', display: 'Clients', tag: 'input', readonly: 1 }, { name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 }, { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }, ] @configure_overview = [ - 'name', 'uid' + 'name', 'redirect_uri', 'clients' ] @configure_delete = true diff --git a/app/assets/javascripts/app/views/api.jst.eco b/app/assets/javascripts/app/views/api.jst.eco index 86f412824..de29d157c 100644 --- a/app/assets/javascripts/app/views/api.jst.eco +++ b/app/assets/javascripts/app/views/api.jst.eco @@ -51,6 +51,7 @@ curl -u <%= @S('email') %>:some_password <%= @C('http_type') %>://<%= @C('fqdn') +

diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3c84b465c..d6c2a8451 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -308,6 +308,10 @@ class ApplicationController < ActionController::Base logger.debug "oauth2 token auth check '#{token}'" access_token = Doorkeeper::AccessToken.by_token(token) + if !access_token + raise Exceptions::NotAuthorized, 'Invalid token!' + end + # check expire if access_token.expires_in && (access_token.created_at + access_token.expires_in) < Time.zone.now raise Exceptions::NotAuthorized, 'OAuth2 token is expired!' diff --git a/app/controllers/applications_controller.rb b/app/controllers/applications_controller.rb index 00da58b5e..1b44c54c2 100644 --- a/app/controllers/applications_controller.rb +++ b/app/controllers/applications_controller.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ class ApplicationsController < ApplicationController before_action { authentication_check(permission: 'admin.api') } @@ -13,7 +13,9 @@ class ApplicationsController < ApplicationController if !assets[:Application] assets[:Application] = {} end - assets[:Application][item.id] = item.attributes + application = item.attributes + application[:clients] = Doorkeeper::AccessToken.where(application_id: item.id).count + assets[:Application][item.id] = application } render json: { record_ids: item_ids, @@ -25,6 +27,11 @@ class ApplicationsController < ApplicationController render json: all, status: :ok end + def token + access_token = Doorkeeper::AccessToken.create!(application_id: params[:id], resource_owner_id: current_user.id) + render json: { token: access_token.token }, status: :ok + end + def show application = Doorkeeper::Application.find(params[:id]) render json: application, status: :ok @@ -59,6 +66,7 @@ class ApplicationsController < ApplicationController params_data.delete('uid') params_data.delete('secret') params_data.delete('created_at') + params_data.delete('updated_at') params_data end end diff --git a/config/routes/doorkeeper.rb b/config/routes/applications.rb similarity index 86% rename from config/routes/doorkeeper.rb rename to config/routes/applications.rb index 9acd9e820..752e170ea 100644 --- a/config/routes/doorkeeper.rb +++ b/config/routes/applications.rb @@ -5,6 +5,7 @@ Zammad::Application.routes.draw do match api_path + '/applications/:id', to: 'applications#show', via: :get match api_path + '/applications', to: 'applications#create', via: :post match api_path + '/applications/:id', to: 'applications#update', via: :put + match api_path + '/applications/token', to: 'applications#token', via: :post # oauth2 provider routes use_doorkeeper do