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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/app/controllers/master_api_key/api_keys_controller.rb +54 -0
- data/app/controllers/master_api_key/application_controller.rb +11 -0
- data/app/models/master_api_key/api_key.rb +16 -0
- data/config/master_api_key.gemversion +1 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20160329212147_create_master_api_key_api_keys.rb +9 -0
- data/db/migrate/20160330160153_add_group_column.rb +5 -0
- data/db/migrate/20160407194542_require_group_attribute.rb +5 -0
- data/db/migrate/20160411152807_create_master_key.rb +11 -0
- data/db/seeds.rb +10 -0
- data/lib/master_api_key.rb +4 -0
- data/lib/master_api_key/api_gatekeeper.rb +56 -0
- data/lib/master_api_key/engine.rb +14 -0
- data/lib/master_api_key/version.rb +9 -0
- data/spec/controllers/master_api_key/api_keys_controller_spec.rb +130 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/empty_group_controller.rb +7 -0
- data/spec/dummy/app/controllers/nil_group_controller.rb +7 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +4 -0
- data/spec/dummy/config/database.yml +23 -0
- data/spec/dummy/config/environment.rb +6 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +6 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/schema.rb +23 -0
- data/spec/dummy/db/seeds.rb +8 -0
- data/spec/dummy/log/development.log +17 -0
- data/spec/dummy/log/test.log +14668 -0
- data/spec/master_api_key/api_gatekeeper_spec.rb +94 -0
- data/spec/rails_helper.rb +57 -0
- data/spec/requests/master_api_key/integration_spec.rb +17 -0
- data/spec/requests/master_api_key/master_api_key_api_keys_spec.rb +98 -0
- data/spec/spec_helper.rb +92 -0
- metadata +258 -0
- 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,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,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,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
|
data/spec/dummy/Rakefile
ADDED
data/spec/dummy/bin/rake
ADDED
@@ -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
|