master_api_key 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/app/controllers/master_api_key/api_keys_controller.rb +54 -0
  5. data/app/controllers/master_api_key/application_controller.rb +11 -0
  6. data/app/models/master_api_key/api_key.rb +16 -0
  7. data/config/master_api_key.gemversion +1 -0
  8. data/config/routes.rb +5 -0
  9. data/db/migrate/20160329212147_create_master_api_key_api_keys.rb +9 -0
  10. data/db/migrate/20160330160153_add_group_column.rb +5 -0
  11. data/db/migrate/20160407194542_require_group_attribute.rb +5 -0
  12. data/db/migrate/20160411152807_create_master_key.rb +11 -0
  13. data/db/seeds.rb +10 -0
  14. data/lib/master_api_key.rb +4 -0
  15. data/lib/master_api_key/api_gatekeeper.rb +56 -0
  16. data/lib/master_api_key/engine.rb +14 -0
  17. data/lib/master_api_key/version.rb +9 -0
  18. data/spec/controllers/master_api_key/api_keys_controller_spec.rb +130 -0
  19. data/spec/dummy/Rakefile +6 -0
  20. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  21. data/spec/dummy/app/controllers/empty_group_controller.rb +7 -0
  22. data/spec/dummy/app/controllers/nil_group_controller.rb +7 -0
  23. data/spec/dummy/bin/bundle +3 -0
  24. data/spec/dummy/bin/rails +4 -0
  25. data/spec/dummy/bin/rake +4 -0
  26. data/spec/dummy/bin/setup +29 -0
  27. data/spec/dummy/config.ru +4 -0
  28. data/spec/dummy/config/application.rb +29 -0
  29. data/spec/dummy/config/boot.rb +4 -0
  30. data/spec/dummy/config/database.yml +23 -0
  31. data/spec/dummy/config/environment.rb +6 -0
  32. data/spec/dummy/config/environments/development.rb +41 -0
  33. data/spec/dummy/config/environments/production.rb +79 -0
  34. data/spec/dummy/config/environments/test.rb +42 -0
  35. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  36. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  37. data/spec/dummy/config/initializers/inflections.rb +16 -0
  38. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  39. data/spec/dummy/config/initializers/session_store.rb +3 -0
  40. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  41. data/spec/dummy/config/locales/en.yml +23 -0
  42. data/spec/dummy/config/routes.rb +6 -0
  43. data/spec/dummy/config/secrets.yml +22 -0
  44. data/spec/dummy/db/schema.rb +23 -0
  45. data/spec/dummy/db/seeds.rb +8 -0
  46. data/spec/dummy/log/development.log +17 -0
  47. data/spec/dummy/log/test.log +14668 -0
  48. data/spec/master_api_key/api_gatekeeper_spec.rb +94 -0
  49. data/spec/rails_helper.rb +57 -0
  50. data/spec/requests/master_api_key/integration_spec.rb +17 -0
  51. data/spec/requests/master_api_key/master_api_key_api_keys_spec.rb +98 -0
  52. data/spec/spec_helper.rb +92 -0
  53. metadata +258 -0
  54. metadata.gz.sig +1 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7095209e7a5c70fdb13ccca9ac51749ef7ea24fb
4
+ data.tar.gz: 4ba5cea4ae5a8c7cce16df468a4247cedfbcec30
5
+ SHA512:
6
+ metadata.gz: a8f08b1267c0bfc3637896efc5fd3a148853d83c1d12d51cf590f64d3dc187d1d9a7c6a74c2a7b0161dd5530e19b334f43595670c1c3979a0070eb4a2b8622a9
7
+ data.tar.gz: d26894146e18ef660868a18dc256cebe197994b733a678a39f0c3fbb75375d00c0810f8c279791e2b84b686feb977a9e368897cd30f77a4efada8a8e68459616
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig ADDED
Binary file
@@ -0,0 +1,54 @@
1
+ require_dependency 'master_api_key/application_controller'
2
+
3
+ module MasterApiKey
4
+ class ApiKeysController < ApplicationController
5
+ belongs_to_api_group :master_key
6
+ skip_before_action :verify_authenticity_token
7
+ before_action :authorize_action
8
+
9
+ # POST /api_keys
10
+ def create
11
+ begin
12
+ @api_key = ApiKey.create!(group:group_param)
13
+ render json: { apiKey: @api_key, status: :created }
14
+ rescue ActionController::ParameterMissing => e
15
+ respond_with_error(e.message, :bad_request)
16
+ end
17
+ end
18
+
19
+ # DELETE /api_keys/1
20
+ def destroy
21
+ begin
22
+ ApiKey.delete_all(['id = ?', access_id_param])
23
+ head :ok
24
+ rescue ActionController::ParameterMissing => e
25
+ respond_with_error(e.message, :bad_request)
26
+ end
27
+ end
28
+
29
+ # DELETE /api_keys
30
+ def destroy_by_access_token
31
+ begin
32
+ Rails.logger.warn "the api token is #{access_token_param}"
33
+ ApiKey.delete_all(['api_token = ?', access_token_param])
34
+ head :ok
35
+ rescue ActionController::ParameterMissing => e
36
+ respond_with_error(e.message, :bad_request)
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def group_param
43
+ params.require(:group)
44
+ end
45
+
46
+ def access_token_param
47
+ params.require(:api_token)
48
+ end
49
+
50
+ def access_id_param
51
+ params.require(:id)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,11 @@
1
+ module MasterApiKey
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+
5
+ protected
6
+
7
+ def respond_with_error(msg, error)
8
+ render :text => {:error => msg}.to_json, :content_type => 'application/json', :status => error
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module MasterApiKey
2
+ class ApiKey < ActiveRecord::Base
3
+ validates :group, presence: true
4
+ before_create :generate_api_token
5
+
6
+ def as_json(options = {})
7
+ super(options.reverse_merge({only: [:id, :api_token, :group]}))
8
+ end
9
+
10
+ private
11
+
12
+ def generate_api_token
13
+ self.api_token ||= SecureRandom.urlsafe_base64
14
+ end
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ 1.0.0
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+
2
+ MasterApiKey::Engine.routes.draw do
3
+ delete '/api_keys', to: 'api_keys#destroy_by_access_token'
4
+ resources :api_keys, only: [:create, :destroy]
5
+ end
@@ -0,0 +1,9 @@
1
+ class CreateMasterApiKeyApiKeys < ActiveRecord::Migration
2
+ def change
3
+ create_table :master_api_key_api_keys do |t|
4
+ t.string :api_token
5
+
6
+ t.timestamps null: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class AddGroupColumn < ActiveRecord::Migration
2
+ def change
3
+ add_column :master_api_key_api_keys, :group, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RequireGroupAttribute < ActiveRecord::Migration
2
+ def change
3
+ change_column_null :master_api_key_api_keys, :group, false
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class CreateMasterKey < ActiveRecord::Migration
2
+ def up
3
+ unless MasterApiKey::ApiKey.where(:group => :master_key).count > 0
4
+ MasterApiKey::ApiKey.create(:group => :master_key)
5
+ end
6
+ end
7
+
8
+ def down
9
+ MasterApiKey::ApiKey.where(:group => :master_key).delete_all
10
+ end
11
+ end
data/db/seeds.rb ADDED
@@ -0,0 +1,10 @@
1
+ # This file should contain all the record creation needed to seed the database with its default values.
2
+ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3
+ #
4
+ # Examples:
5
+ #
6
+ # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7
+ # Mayor.create(name: 'Emanuel', city: cities.first)
8
+ unless MasterApiKey::ApiKey.where(:group => :master_key).count > 0
9
+ MasterApiKey::ApiKey.create(:group => :master_key)
10
+ end
@@ -0,0 +1,4 @@
1
+ require 'master_api_key/api_gatekeeper'
2
+ require 'master_api_key/engine'
3
+
4
+ ActionController::Base.send :include, MasterApiKey::ApiGatekeeper
@@ -0,0 +1,56 @@
1
+ require 'active_support'
2
+
3
+ module MasterApiKey
4
+ module ApiGatekeeper
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def belongs_to_api_group(group_name)
9
+ raise ArgumentError, "MasterApiKey: Didn't define an api group name" unless group_name.present?
10
+
11
+ self.module_eval("def api_group() :#{group_name} end")
12
+ end
13
+ end
14
+
15
+ def api_group
16
+ nil
17
+ end
18
+
19
+ protected
20
+
21
+ def authorize_action
22
+ if user_authenticated?
23
+ raise ArgumentError, "MasterApiKey: Didn't define an api group name" unless self.api_group.present?
24
+ if @api_key.group.casecmp(self.api_group.to_s) == 0
25
+ yield if block_given?
26
+ else
27
+ on_forbidden_request
28
+ end
29
+ else
30
+ on_authentication_failure
31
+ end
32
+ end
33
+
34
+ def on_authentication_failure
35
+ head(:unauthorized)
36
+ end
37
+
38
+ def on_forbidden_request
39
+ head(:forbidden)
40
+ end
41
+
42
+ private
43
+
44
+ def user_authenticated?
45
+ api_token.present? and (@api_key = MasterApiKey::ApiKey.find_by_api_token(api_token)).present?
46
+ end
47
+
48
+ def api_token
49
+ header('X-API-TOKEN')
50
+ end
51
+
52
+ def header(header)
53
+ request.headers[header]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,14 @@
1
+ module MasterApiKey
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace MasterApiKey
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec, :fixture => false
7
+ g.integration_tool :rspec, :fixture => false, :views => false
8
+ #g.fixture_replacement :factory_girl, :dir => 'spec/factories'
9
+ g.assets false
10
+ g.helper false
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module MasterApiKey
2
+ VERSION = lambda {
3
+ version = '0.0.0'
4
+ File.open(File.join(File.dirname(__FILE__), '../../config/master_api_key.gemversion'), 'r') do |f|
5
+ version = f.readline
6
+ end
7
+ version
8
+ }.call
9
+ end
@@ -0,0 +1,130 @@
1
+ require 'rails_helper'
2
+
3
+ module MasterApiKey
4
+ RSpec.describe ApiKeysController, type: :controller do
5
+
6
+ before(:each) do
7
+ @routes = Engine.routes
8
+ end
9
+
10
+ # This should return the minimal set of values that should be in the session
11
+ # in order to pass any filters (e.g. authentication) defined in
12
+ # ApiKeysController. Be sure to keep this updated too.
13
+ let(:valid_session) { {} }
14
+
15
+ describe 'POST #create' do
16
+ context 'with master key' do
17
+ before(:each) do
18
+ @master_key = ApiKey.create!(:group => :master_key)
19
+ controller.request.headers['X-API-TOKEN'] = @master_key.api_token
20
+ end
21
+
22
+ context 'with valid params' do
23
+ before(:each) do
24
+ @valid_attributes = {:group => 'group_1'}
25
+ end
26
+
27
+ it 'creates a new ApiKey' do
28
+ expect {
29
+ post :create, @valid_attributes
30
+ }.to change(ApiKey, :count).by(1)
31
+ end
32
+
33
+ it 'assigns a newly created api_key as @api_key' do
34
+ post :create, @valid_attributes
35
+
36
+ expect(assigns(:api_key)).to be_a(ApiKey)
37
+ expect(assigns(:api_key)).to be_persisted
38
+ end
39
+ end
40
+
41
+ context 'with invalid params' do
42
+ before(:each) do
43
+ end
44
+
45
+ it 'should not change ApiKey count when group is nil' do
46
+ expect {
47
+ post :create, {:group => nil}
48
+ }.to_not change(ApiKey, :count)
49
+ end
50
+
51
+ it 'should not change ApiKey count when group param does not exist' do
52
+ expect {
53
+ post :create, {}
54
+ }.to_not change(ApiKey, :count)
55
+ end
56
+ end
57
+ end
58
+
59
+ context 'with incorrect api key' do
60
+ before(:each) do
61
+ @master_key = ApiKey.create!(:group => :wrong_group)
62
+ controller.request.headers['X-API-TOKEN'] = @master_key.api_token
63
+ @valid_attributes = {:group => 'group_1'}
64
+ end
65
+
66
+ it 'fails to create a new ApiKey' do
67
+ expect {
68
+ post :create, @valid_attributes
69
+ }.to_not change(ApiKey, :count)
70
+
71
+ expect(response.status).to be 403
72
+ end
73
+ end
74
+ end
75
+
76
+ describe 'DELETE #destroy' do
77
+ context 'with master key' do
78
+ before(:each) do
79
+ @master_key = ApiKey.create(:group => :master_key)
80
+ @api_key = ApiKey.create!(:group => 'group_1')
81
+ controller.request.headers['X-API-TOKEN'] = @master_key.api_token
82
+ end
83
+
84
+ it 'destroys the requested api_key with the id' do
85
+ expect {
86
+ delete :destroy, {:id => @api_key.to_param.to_i}
87
+ }.to change(ApiKey, :count).by(-1)
88
+ end
89
+
90
+ it 'destroys the requested api_key with the api token' do
91
+ expect {
92
+ delete :destroy_by_access_token, {:api_token => @api_key.api_token}
93
+ }.to change(ApiKey, :count).by(-1)
94
+ end
95
+
96
+ it 'does not change the ApiKey count when the key does not exist' do
97
+ expect {
98
+ delete :destroy_by_access_token, {:api_token => 'not_a_real_key'}
99
+ }.not_to change(ApiKey, :count)
100
+
101
+ expect(response).to be_success
102
+ end
103
+ end
104
+
105
+ context 'with incorrect api key' do
106
+ before(:each) do
107
+ @master_key = ApiKey.create!(:group => :wrong_group)
108
+ @api_key = ApiKey.create!(:group => 'group_1')
109
+ controller.request.headers['X-API-TOKEN'] = @master_key.api_token
110
+ end
111
+
112
+ it 'fails to destroy the ApiKey by id' do
113
+ expect {
114
+ delete :destroy, {:id => @api_key.to_param.to_i}
115
+ }.to_not change(ApiKey, :count)
116
+
117
+ expect(response.status).to be 403
118
+ end
119
+
120
+ it 'fails to destroy the ApiKey by api token' do
121
+ expect {
122
+ delete :destroy_by_access_token, {:api_token => @api_key.api_token}
123
+ }.to_not change(ApiKey, :count)
124
+
125
+ expect(response.status).to be 403
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,7 @@
1
+ class EmptyGroupController < ApplicationController
2
+ belongs_to_api_group('')
3
+
4
+ def index
5
+ head(:ok)
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class NilGroupController < ApplicationController
2
+ belongs_to_api_group(nil)
3
+
4
+ def index
5
+ head(:ok)
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ # path to your application root.
5
+ APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
6
+
7
+ Dir.chdir APP_ROOT do
8
+ # This script is a starting point to setup your application.
9
+ # Add necessary setup steps to this file:
10
+
11
+ puts "== Installing dependencies =="
12
+ system "gem install bundler --conservative"
13
+ system "bundle check || bundle install"
14
+
15
+ # puts "\n== Copying sample files =="
16
+ # unless File.exist?("config/database.yml")
17
+ # system "cp config/database.yml.sample config/database.yml"
18
+ # end
19
+
20
+ puts "\n== Preparing database =="
21
+ system "bin/rake db:setup"
22
+
23
+ puts "\n== Removing old logs and tempfiles =="
24
+ system "rm -f log/*"
25
+ system "rm -rf tmp/cache"
26
+
27
+ puts "\n== Restarting application server =="
28
+ system "touch tmp/restart.txt"
29
+ end