From e200378dd672408fbdf229ac488a758bbf7fabcc Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 28 Jul 2016 12:09:32 +0200 Subject: [PATCH] Added api setting to admin interface and tokens to user preferences. --- .../_profile/calendar_subscriptions.coffee | 4 +- .../app/controllers/_profile/devices.coffee | 12 +- .../controllers/_profile/token_access.coffee | 92 ++++++++++ .../app/controllers/package.coffee | 2 +- .../app/controllers/session.coffee | 2 +- .../widget/translation_inline.coffee | 4 +- .../app/views/profile/devices.jst.eco | 2 +- .../app/views/profile/language.jst.eco | 6 +- .../app/views/profile/linked_accounts.jst.eco | 2 +- .../app/views/profile/password.jst.eco | 4 +- .../app/views/profile/token_access.jst.eco | 57 ++++++ .../profile/token_access_created.jst.eco | 7 + app/controllers/application_controller.rb | 40 ++++- .../user_access_token_controller.rb | 43 +++++ app/models/token.rb | 2 +- config/routes/user_access_token.rb | 9 + db/migrate/20120101000001_create_base.rb | 1 + .../20160727000001_update_setting_api.rb | 53 ++++++ db/seeds.rb | 49 ++++- test/browser/preferences_test.rb | 63 ++++++- test/controllers/api_auth_controller_test.rb | 170 ++++++++++++++++++ test/controllers/settings_controller_test.rb | 24 +-- test/unit/token_test.rb | 8 +- 23 files changed, 617 insertions(+), 39 deletions(-) create mode 100644 app/assets/javascripts/app/controllers/_profile/token_access.coffee create mode 100644 app/assets/javascripts/app/views/profile/token_access.jst.eco create mode 100644 app/assets/javascripts/app/views/profile/token_access_created.jst.eco create mode 100644 app/controllers/user_access_token_controller.rb create mode 100644 config/routes/user_access_token.rb create mode 100644 db/migrate/20160727000001_update_setting_api.rb create mode 100644 test/controllers/api_auth_controller_test.rb diff --git a/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee b/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee index 14abe6206..f9d67841a 100644 --- a/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee +++ b/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee @@ -66,7 +66,7 @@ class CalendarSubscriptions extends App.Controller @ajax( id: 'preferences' type: 'PUT' - url: @apiPath + '/users/preferences' + url: "#{@apiPath}/users/preferences" data: JSON.stringify data success: @success error: @error @@ -91,4 +91,4 @@ class CalendarSubscriptions extends App.Controller msg: App.i18n.translateContent(data.message) ) -App.Config.set( 'CalendarSubscriptions', { prio: 3000, name: 'Calendar', parent: '#profile', target: '#profile/calendar_subscriptions', role: ['Agent'], controller: CalendarSubscriptions }, 'NavBarProfile' ) +App.Config.set('CalendarSubscriptions', { prio: 3000, name: 'Calendar', parent: '#profile', target: '#profile/calendar_subscriptions', role: ['Agent'], controller: CalendarSubscriptions }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/devices.coffee b/app/assets/javascripts/app/controllers/_profile/devices.coffee index 167e8bec2..284c27ed0 100644 --- a/app/assets/javascripts/app/controllers/_profile/devices.coffee +++ b/app/assets/javascripts/app/controllers/_profile/devices.coffee @@ -15,12 +15,17 @@ class Index extends App.Controller ) # fetch data, render view - load: => + load: (force = false) => @ajax( id: 'user_devices' type: 'GET' url: "#{@apiPath}/user_devices" success: (data) => + + # verify is rerender is needed + if !force && @lastestUpdated && data && data[0] && @lastestUpdated.updated_at is data[0].updated_at + return + @lastestUpdated = data[0] @data = data @render() ) @@ -39,8 +44,9 @@ class Index extends App.Controller type: 'DELETE' url: "#{@apiPath}/user_devices/#{id}" processData: true - success: @load - error: @error + success: => + @load(true) + error: @error ) error: (xhr, status, error) => diff --git a/app/assets/javascripts/app/controllers/_profile/token_access.coffee b/app/assets/javascripts/app/controllers/_profile/token_access.coffee new file mode 100644 index 000000000..727ea3850 --- /dev/null +++ b/app/assets/javascripts/app/controllers/_profile/token_access.coffee @@ -0,0 +1,92 @@ +class Index extends App.Controller + events: + 'click [data-type=delete]': 'delete' + 'submit form.js-create': 'create' + + constructor: -> + super + return if !@authenticate() + @title 'Token Access', true + + @load() + @interval( + => + @load() + 12000 + ) + + # fetch data, render view + load: (force = false) => + @ajax( + id: 'user_access_token' + type: 'GET' + url: "#{@apiPath}/user_access_token" + success: (data) => + + # verify is rerender is needed + if !force && @lastestUpdated && data && data[0] && @lastestUpdated.updated_at is data[0].updated_at + return + @lastestUpdated = data[0] + @data = data + @render() + ) + + render: => + @html App.view('profile/token_access')( + tokens: @data + ) + + create: (e) => + e.preventDefault() + params = @formParam(e.target) + + @ajax( + id: 'user_access_token_create' + type: 'POST' + url: "#{@apiPath}/user_access_token" + data: JSON.stringify(params) + processData: true + success: @show + error: @error + ) + + show: (data) => + @load() + ui = @ + new App.ControllerModal( + head: 'Your New Personal Access Token' + buttonSubmit: 'OK, I\'ve copied my token' + content: -> + App.view('profile/token_access_created')( + name: data.name + ) + post: -> + @el.find('.js-select').on('click', ui.selectAll) + onCancel: -> + @close() + onSubmit: -> + @close() + ) + + delete: (e) => + e.preventDefault() + return if !confirm(App.i18n.translateInline('Sure?')) + id = $(e.target).closest('a').data('token-id') + @ajax( + id: 'user_access_token_delete' + type: 'DELETE' + url: "#{@apiPath}/user_access_token/#{id}" + processData: true + success: => + @load(true) + error: @error + ) + + error: (xhr, status, error) => + data = JSON.parse(xhr.responseText) + @notify( + type: 'error' + msg: App.i18n.translateContent(data.message) + ) + +App.Config.set('Token Access', { prio: 3200, name: 'Token Access', parent: '#profile', target: '#profile/token_access', controller: Index, role: [ 'Agent', 'Admin' ] }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/package.coffee b/app/assets/javascripts/app/controllers/package.coffee index a110789cd..bfc6074f0 100644 --- a/app/assets/javascripts/app/controllers/package.coffee +++ b/app/assets/javascripts/app/controllers/package.coffee @@ -58,4 +58,4 @@ class Index extends App.ControllerContent @load() ) -App.Config.set('Packages', { prio: 1000, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Packages', { prio: 3600, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, role: ['Admin'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/session.coffee b/app/assets/javascripts/app/controllers/session.coffee index 57161d118..479486566 100644 --- a/app/assets/javascripts/app/controllers/session.coffee +++ b/app/assets/javascripts/app/controllers/session.coffee @@ -53,4 +53,4 @@ class Index extends App.ControllerContent @load() ) -App.Config.set('Session', { prio: 3700, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Session', { prio: 3800, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file diff --git a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee index ac5faa1bb..7f2448365 100644 --- a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee +++ b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee @@ -63,8 +63,8 @@ class Widget extends App.Controller App.i18n.setMap(source, translation_new) # replace rest in page - source = source.replace('\'', '\\\'') - $(".translation[title='#{source}']").text(translation_new) + sourceQuoted = source.replace('\'', '\\\'') + $(".translation[title='#{sourceQuoted}']").text(translation_new) # update permanent translation mapString translation = App.Translation.findByAttribute('source', source) diff --git a/app/assets/javascripts/app/views/profile/devices.jst.eco b/app/assets/javascripts/app/views/profile/devices.jst.eco index c72378fa8..7ebea6e72 100644 --- a/app/assets/javascripts/app/views/profile/devices.jst.eco +++ b/app/assets/javascripts/app/views/profile/devices.jst.eco @@ -1,5 +1,5 @@
diff --git a/app/assets/javascripts/app/views/profile/language.jst.eco b/app/assets/javascripts/app/views/profile/language.jst.eco index efa08d7ec..4be350681 100644 --- a/app/assets/javascripts/app/views/profile/language.jst.eco +++ b/app/assets/javascripts/app/views/profile/language.jst.eco @@ -1,12 +1,12 @@
-

<%- @T( 'Change your language.' ) %>

+

<%- @T('Change your language.') %>

- +
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/profile/linked_accounts.jst.eco b/app/assets/javascripts/app/views/profile/linked_accounts.jst.eco index 8db0bb0c8..a056a8c9c 100644 --- a/app/assets/javascripts/app/views/profile/linked_accounts.jst.eco +++ b/app/assets/javascripts/app/views/profile/linked_accounts.jst.eco @@ -1,6 +1,6 @@
diff --git a/app/assets/javascripts/app/views/profile/password.jst.eco b/app/assets/javascripts/app/views/profile/password.jst.eco index 7d5453354..ba6016bd2 100644 --- a/app/assets/javascripts/app/views/profile/password.jst.eco +++ b/app/assets/javascripts/app/views/profile/password.jst.eco @@ -1,11 +1,11 @@
- +
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/profile/token_access.jst.eco b/app/assets/javascripts/app/views/profile/token_access.jst.eco new file mode 100644 index 000000000..207b4bfb0 --- /dev/null +++ b/app/assets/javascripts/app/views/profile/token_access.jst.eco @@ -0,0 +1,57 @@ + + +

<%- @T('You can generate a personal access token for each application you use that needs access to the Zammad API.') %>

+ +

<%- @T('Add a Personal Access Token') %>

+ +

<%- @T('Pick a name for the application, and we\'ll give you a unique token.') %>

+
+
+
+ +
+
+
+ +
+ +
+ +

<%- @T('Personal Access Tokens') %>

+ + + + + + + + + + + <% if _.isEmpty(@tokens): %> + + + + + + + <% end %> + <% end %> + +
<%- @T('Name') %><%- @T('Created') %><%- @T('Delete') %>
<%- @T('none') %> + <% else: %> + <% for token in @tokens: %> +
<%= token.label %><%- @humanTime(token.created_at) %> + +
+ diff --git a/app/assets/javascripts/app/views/profile/token_access_created.jst.eco b/app/assets/javascripts/app/views/profile/token_access_created.jst.eco new file mode 100644 index 000000000..a5bca0a9f --- /dev/null +++ b/app/assets/javascripts/app/views/profile/token_access_created.jst.eco @@ -0,0 +1,7 @@ +<%- @T('For security reasons, the API token is shown only once. You\'ll need to copy it somewhere safe before continuing.') %> + +
+
+
+
+
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 40e8ad027..60a9a2597 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -260,6 +260,12 @@ class ApplicationController < ActionController::Base # check http basic based authentication authenticate_with_http_basic do |username, password| logger.debug "http basic auth check '#{username}'" + if Setting.get('api_password_access') == false + return { + auth: false, + message: 'API password access disabled!', + } + end userdata = User.authenticate(username, password) next if !userdata if check_maintenance_only(userdata) @@ -276,10 +282,10 @@ class ApplicationController < ActionController::Base } end - # check http token based authentication + # check http token action based authentication if auth_param[:token_action] authenticate_with_http_token do |token, _options| - logger.debug "token auth check '#{token}'" + logger.debug "token action auth check '#{token}'" userdata = Token.check( action: auth_param[:token_action], name: token, @@ -293,13 +299,41 @@ class ApplicationController < ActionController::Base end current_user_set(userdata) user_device_log(userdata, 'token_auth') - logger.debug "token auth for '#{userdata.login}'" + logger.debug "token action auth for '#{userdata.login}'" return { auth: true } end end + # check http token based authentication + authenticate_with_http_token do |token, _options| + logger.debug "token auth check '#{token}'" + if Setting.get('api_token_access') == false + return { + auth: false, + message: 'API token access disabled!', + } + end + userdata = Token.check( + action: 'api', + name: token, + ) + next if !userdata + if check_maintenance_only(userdata) + return { + auth: false, + message: 'Maintenance mode enabled!', + } + end + current_user_set(userdata) + user_device_log(userdata, 'token_auth') + logger.debug "token auth for '#{userdata.login}'" + return { + auth: true + } + end + logger.debug error_message { auth: false, diff --git a/app/controllers/user_access_token_controller.rb b/app/controllers/user_access_token_controller.rb new file mode 100644 index 000000000..c1dab3f3e --- /dev/null +++ b/app/controllers/user_access_token_controller.rb @@ -0,0 +1,43 @@ +# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ + +class UserAccessTokenController < ApplicationController + before_action :authentication_check + + def index + tokens = Token.where(action: 'api', persistent: true, user_id: current_user.id).order('updated_at DESC, label ASC') + token_list = [] + tokens.each { |token| + attributes = token.attributes + attributes.delete('persistent') + attributes.delete('name') + token_list.push attributes + } + model_index_render_result(token_list) + end + + def create + if Setting.get('api_token_access') == false + raise Exceptions::UnprocessableEntity, 'API token access disabled!' + end + if params[:label].empty? + raise Exceptions::UnprocessableEntity, 'Need label!' + end + token = Token.create( + action: 'api', + label: params[:label], + persistent: true, + user_id: current_user.id, + ) + render json: { + name: token.name, + }, status: :ok + end + + def destroy + token = Token.find_by(action: 'api', user_id: current_user.id, id: params[:id]) + raise Exceptions::UnprocessableEntity, 'Unable to find api token!' if !token + token.destroy + render json: {}, status: :ok + end + +end diff --git a/app/models/token.rb b/app/models/token.rb index 625dbaf96..18f039a62 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -80,7 +80,7 @@ cleanup old token def generate_token loop do - self.name = SecureRandom.hex(30) + self.name = SecureRandom.urlsafe_base64(48) break if !Token.exists?(name: name) end end diff --git a/config/routes/user_access_token.rb b/config/routes/user_access_token.rb new file mode 100644 index 000000000..aaad0d1cc --- /dev/null +++ b/config/routes/user_access_token.rb @@ -0,0 +1,9 @@ +Zammad::Application.routes.draw do + api_path = Rails.configuration.api_path + + # access token + match api_path + '/user_access_token', to: 'user_access_token#index', via: :get + match api_path + '/user_access_token', to: 'user_access_token#create', via: :post + match api_path + '/user_access_token/:id', to: 'user_access_token#destroy', via: :delete + +end diff --git a/db/migrate/20120101000001_create_base.rb b/db/migrate/20120101000001_create_base.rb index 2e57b1d2f..4b5a3738f 100644 --- a/db/migrate/20120101000001_create_base.rb +++ b/db/migrate/20120101000001_create_base.rb @@ -188,6 +188,7 @@ class CreateBase < ActiveRecord::Migration t.boolean :persistent t.string :name, limit: 100, null: false t.string :action, limit: 40, null: false + t.string :label, limit: 255, null: true t.timestamps null: false end add_index :tokens, :user_id diff --git a/db/migrate/20160727000001_update_setting_api.rb b/db/migrate/20160727000001_update_setting_api.rb new file mode 100644 index 000000000..43c3f593c --- /dev/null +++ b/db/migrate/20160727000001_update_setting_api.rb @@ -0,0 +1,53 @@ +class UpdateSettingApi < ActiveRecord::Migration + def up + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + + Setting.create_or_update( + title: 'API Token Access', + name: 'api_token_access', + area: 'API::Base', + description: 'Enable REST API using tokens (not username/email addeess and password). Each user need to create own access tokens in user profile.', + options: { + form: [ + { + display: '', + null: true, + name: 'api_token_access', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: true, + frontend: false + ) + Setting.create_or_update( + title: 'API Password Access', + name: 'api_password_access', + area: 'API::Base', + description: 'Enable REST API access using the username/email address and password for the authentication user.', + options: { + form: [ + { + display: '', + null: true, + name: 'api_password_access', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: true, + frontend: false + ) + add_column :tokens, :label, :string, limit: 255, null: true + + end +end diff --git a/db/seeds.rb b/db/seeds.rb index eec1a7cdc..2d1fbd20c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -554,7 +554,7 @@ Setting.create_if_not_exists( title: 'Authentication via Google', name: 'auth_google_oauth2', area: 'Security::ThirdPartyAuthentication', - description: 'Enables user authentication via Google.', + description: 'Enables user authentication via Google. Register your app first at [Google API Console Site](https://console.developers.google.com/apis/credentials)', options: { form: [ { @@ -601,7 +601,7 @@ Setting.create_if_not_exists( title: 'Authentication via LinkedIn', name: 'auth_linkedin', area: 'Security::ThirdPartyAuthentication', - description: 'Enables user authentication via LinkedIn.', + description: 'Enables user authentication via LinkedIn. Register your app first at [Linkedin Developer Site](https://www.linkedin.com/developer/apps)', options: { form: [ { @@ -1210,6 +1210,51 @@ Setting.create_if_not_exists( frontend: false ) +Setting.create_or_update( + title: 'API Token Access', + name: 'api_token_access', + area: 'API::Base', + description: 'Enable REST API using tokens (not username/email addeess and password). Each user need to create own access tokens in user profile.', + options: { + form: [ + { + display: '', + null: true, + name: 'api_token_access', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: true, + frontend: false +) +Setting.create_or_update( + title: 'API Password Access', + name: 'api_password_access', + area: 'API::Base', + description: 'Enable REST API access using the username/email address and password for the authentication user.', + options: { + form: [ + { + display: '', + null: true, + name: 'api_password_access', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: true, + frontend: false +) + Setting.create_if_not_exists( title: 'Enable Chat', name: 'chat', diff --git a/test/browser/preferences_test.rb b/test/browser/preferences_test.rb index eaf9a256e..1b5360c6f 100644 --- a/test/browser/preferences_test.rb +++ b/test/browser/preferences_test.rb @@ -27,6 +27,10 @@ class PreferencesTest < TestCase css: '.content .NavBarProfile', value: 'Calendar', ) + match( + css: '.content .NavBarProfile', + value: 'Token Access', + ) end def test_permission_customer @@ -54,9 +58,13 @@ class PreferencesTest < TestCase css: '.content .NavBarProfile', value: 'Calendar', ) + match_not( + css: '.content .NavBarProfile', + value: 'Token Access', + ) end - def test_preferences + def test_lang_change @browser = browser_instance login( username: 'master@example.com', @@ -369,4 +377,57 @@ class PreferencesTest < TestCase value: 'Meine' ) end + + def test_token_access + @browser = browser_instance + login( + username: 'agent1@example.com', + password: 'test', + url: browser_url, + ) + tasks_close_all() + click(css: 'a[href="#current_user"]') + click(css: 'a[href="#profile"]') + click(css: 'a[href="#profile/token_access"]') + + set( + css: '#content .js-create .js-input', + value: 'Some App#1', + ) + click(css: '#content .js-create .js-submit') + watch_for( + css: '.modal .modal-title', + value: 'Your New Personal Access Token' + ) + click(css: '.modal .js-submit') + watch_for( + css: '#content .js-tokenList', + value: 'Some App#1' + ) + + set( + css: '#content .js-create .js-input', + value: 'Some App#2', + ) + click(css: '#content .js-create .js-submit') + watch_for( + css: '.modal .modal-title', + value: 'Your New Personal Access Token' + ) + click(css: '.modal .js-submit') + watch_for( + css: '#content .js-tokenList', + value: 'Some App#2' + ) + + click(css: '#content .js-tokenList a') + sleep 1 + alert = @browser.switch_to.alert + alert.accept() + watch_for_disappear( + css: '#content .js-tokenList', + value: 'Some App#2' + ) + + end end diff --git a/test/controllers/api_auth_controller_test.rb b/test/controllers/api_auth_controller_test.rb new file mode 100644 index 000000000..afd7312bd --- /dev/null +++ b/test/controllers/api_auth_controller_test.rb @@ -0,0 +1,170 @@ +# encoding: utf-8 +require 'test_helper' + +class ApiAuthControllerTest < ActionDispatch::IntegrationTest + setup do + + # set accept header + @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' } + + # create agent + roles = Role.where(name: %w(Admin Agent)) + groups = Group.all + + UserInfo.current_user_id = 1 + @admin = User.create_or_update( + login: 'api-admin', + firstname: 'API', + lastname: 'Admin', + email: 'api-admin@example.com', + password: 'adminpw', + active: true, + roles: roles, + groups: groups, + ) + + # create agent + roles = Role.where(name: 'Agent') + @agent = User.create_or_update( + login: 'api-agent@example.com', + firstname: 'API', + lastname: 'Agent', + email: 'api-agent@example.com', + password: 'agentpw', + active: true, + roles: roles, + groups: groups, + ) + + # create customer without org + roles = Role.where(name: 'Customer') + @customer = User.create_or_update( + login: 'api-customer1@example.com', + firstname: 'API', + lastname: 'Customer1', + email: 'api-customer1@example.com', + password: 'customer1pw', + active: true, + roles: roles, + ) + + end + + test 'basic auth - admin' do + + admin_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('api-admin@example.com', 'adminpw') + + Setting.set('api_password_access', false) + get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(401) + + Setting.set('api_password_access', true) + get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Array, result.class) + assert(result) + + end + + test 'basic auth - agent' do + + agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('api-agent@example.com', 'agentpw') + + Setting.set('api_password_access', false) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) + assert_response(401) + + Setting.set('api_password_access', true) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Array, result.class) + assert(result) + + end + + test 'basic auth - customer' do + + customer_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('api-customer1@example.com', 'customer1pw') + + Setting.set('api_password_access', false) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) + assert_response(401) + + Setting.set('api_password_access', true) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Array, result.class) + assert(result) + + end + + test 'token auth - admin' do + + admin_token = Token.create( + action: 'api', + persistent: true, + user_id: @admin.id, + ) + admin_credentials = "Token token=#{admin_token.name}" + + Setting.set('api_token_access', false) + get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(401) + + Setting.set('api_token_access', true) + get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Array, result.class) + assert(result) + + end + + test 'token auth - agent' do + + agent_token = Token.create( + action: 'api', + persistent: true, + user_id: @agent.id, + ) + agent_credentials = "Token token=#{agent_token.name}" + + Setting.set('api_token_access', false) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) + assert_response(401) + + Setting.set('api_token_access', true) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Array, result.class) + assert(result) + + end + + test 'token auth - customer' do + + customer_token = Token.create( + action: 'api', + persistent: true, + user_id: @customer.id, + ) + customer_credentials = "Token token=#{customer_token.name}" + + Setting.set('api_token_access', false) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) + assert_response(401) + + Setting.set('api_token_access', true) + get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Array, result.class) + assert(result) + + end + +end diff --git a/test/controllers/settings_controller_test.rb b/test/controllers/settings_controller_test.rb index bdb6ccb4e..8cfbfb393 100644 --- a/test/controllers/settings_controller_test.rb +++ b/test/controllers/settings_controller_test.rb @@ -13,10 +13,10 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest UserInfo.current_user_id = 1 @admin = User.create_or_update( - login: 'packages-admin', - firstname: 'Packages', + login: 'setting-admin', + firstname: 'Setting', lastname: 'Admin', - email: 'packages-admin@example.com', + email: 'setting-admin@example.com', password: 'adminpw', active: true, roles: roles, @@ -26,10 +26,10 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest # create agent roles = Role.where(name: 'Agent') @agent = User.create_or_update( - login: 'packages-agent@example.com', - firstname: 'Rest', + login: 'setting-agent@example.com', + firstname: 'Setting', lastname: 'Agent', - email: 'packages-agent@example.com', + email: 'setting-agent@example.com', password: 'agentpw', active: true, roles: roles, @@ -39,10 +39,10 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest # create customer without org roles = Role.where(name: 'Customer') @customer_without_org = User.create_or_update( - login: 'packages-customer1@example.com', - firstname: 'Packages', + login: 'setting-customer1@example.com', + firstname: 'Setting', lastname: 'Customer1', - email: 'packages-customer1@example.com', + email: 'setting-customer1@example.com', password: 'customer1pw', active: true, roles: roles, @@ -63,7 +63,7 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest test 'settings index with admin' do - credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-admin@example.com', 'adminpw') + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('setting-admin@example.com', 'adminpw') # index get '/api/v1/settings', {}, @headers.merge('Authorization' => credentials) @@ -76,7 +76,7 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest test 'settings index with agent' do - credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-agent@example.com', 'adminpw') + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('setting-agent@example.com', 'agentpw') # index get '/api/v1/settings', {}, @headers.merge('Authorization' => credentials) @@ -89,7 +89,7 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest test 'settings index with customer' do - credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-customer1@example.com', 'customer1pw') + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('setting-customer1@example.com', 'customer1pw') # index get '/api/v1/settings', {}, @headers.merge('Authorization' => credentials) diff --git a/test/unit/token_test.rb b/test/unit/token_test.rb index 2133bd1e0..9e5504d0c 100644 --- a/test/unit/token_test.rb +++ b/test/unit/token_test.rb @@ -86,20 +86,20 @@ class TokenTest < ActiveSupport::TestCase if test[:result] == true if !user - assert( false, test[:test_name] + ': token verification failed' ) + assert(false, test[:test_name] + ': token verification failed') else test[:verify].each { |key, value| - assert_equal( user[key], value, 'verify' ) + assert_equal(user[key], value, 'verify') } end else - assert_equal( test[:result], user, test[:test_name] + ': failed or not existing' ) + assert_equal(test[:result], user, test[:test_name] + ': failed or not existing') end if test[:name] #puts test[:test_name] + ': deleting token '+ test[:name] - token = Token.where( name: test[:name] ).first + token = Token.find_by(name: test[:name]) if token token.destroy