master_api_key 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|