sinatra-fx-auth 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a6f47b09ab7c03c218d5f31d127b7ded750369b
4
+ data.tar.gz: 374c52ff11220a5726cd5238b3da53b0368de8f7
5
+ SHA512:
6
+ metadata.gz: a1428420f5b125f9b93190dfe1f2e1ac04ee21b813f57e2674d072e2f99672c50c0567e6c3ab120fdfd11d7da219ef6c4d69ff9248c76758873ea609f090db1b
7
+ data.tar.gz: 3cc1af4f9055ff0269e58aa985b56d71b5450a3d82ba96683c90005f3c22aaf78a81a67a252fe312250f9cc9f9a0161c5bb73fcd1fc15238c72e6db136328a14
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .idea
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Dave Jackson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Sinatra::Fx::Auth
2
+
3
+ Sinatra::Fx::Auth is a RESTful Authentication and Role-based Authorization extension for Sinatra.
4
+ No sessions or cookies required.
5
+
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'sinatra-fx-auth'
12
+
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install sinatra-fx-auth
22
+
23
+
24
+ ## Usage
25
+ ``` ruby
26
+ require 'sinatra/base'
27
+ require 'sinatra/fx-auth'
28
+
29
+ class MyApp < Sinatra::Base
30
+ register Sinatra::Fx::Auth
31
+
32
+ # Accessible by all
33
+ get '/products' do
34
+ # ...
35
+ end
36
+
37
+ # Requires an authenticated :admin
38
+ put '/products/:id', :auth => :admin do
39
+ # ...
40
+ end
41
+
42
+ # Requires an authenticated :admin or the :user with the given :id
43
+ get '/customers/:id/cart', :auth => [:admin, :user] do
44
+ # ...
45
+ end
46
+ end
47
+ ```
48
+
49
+
50
+ ## Contributing
51
+
52
+ 1. Fork it
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rubygems'
3
+ require 'cucumber'
4
+ require 'cucumber/rake/task'
5
+
6
+
7
+ Cucumber::Rake::Task.new :test do |task|
8
+ task.cucumber_opts = "features --format pretty"
9
+ end
File without changes
@@ -0,0 +1,9 @@
1
+ Feature: API Sign Off
2
+
3
+ Scenario: API Sign Off
4
+
5
+ Given I have a User Profile
6
+ And I sign on with valid credentials
7
+ And I am online
8
+ When the App signs me off
9
+ Then I am offline
@@ -0,0 +1,76 @@
1
+ Feature: API Sign On
2
+
3
+ Scenario: API Valid Credentials
4
+
5
+ Given I have a User Profile
6
+ And I am offline
7
+ When the App signs me on with valid credentials
8
+ Then the App receives a 201 response code
9
+ And the App receives an Auth Token
10
+ # And I am online
11
+
12
+
13
+
14
+ Scenario: API Invalid Credentials
15
+
16
+ Given I have a User Profile
17
+ And I am offline
18
+ When the App tries to sign me on with invalid credentials
19
+ Then the App receives a 401 response code
20
+ And the App receives an Invalid User error
21
+ # And I am offline
22
+
23
+
24
+
25
+ Scenario: API Locked Account
26
+
27
+ Given I have a User Profile
28
+ And I am offline
29
+ When the App tries to sign me on with invalid credentials
30
+ And the App tries to sign me on with invalid credentials
31
+ And the App tries to sign me on with invalid credentials
32
+ Then the App receives a 423 response code
33
+ And the App receives a Locked User error
34
+ # And I am locked out
35
+
36
+
37
+
38
+ Scenario: API Locked Valid Sign On Attempt
39
+
40
+ Given I have a Locked User Profile
41
+ When the App signs me on with valid credentials
42
+ Then the App receives a 423 response code
43
+ And the App receives a Locked User error
44
+ # And I am locked out
45
+
46
+
47
+
48
+ Scenario: API Locked Invalid Sign On Attempt
49
+
50
+ Given I have a Locked User Profile
51
+ When the App tries to sign me on with invalid credentials
52
+ Then the App receives a 423 response code
53
+ And the App receives a Locked User error
54
+ # And I am locked out
55
+
56
+
57
+
58
+ Scenario: API Online Valid Sign On Attempt
59
+
60
+ Given I have a User Profile
61
+ When the App signs me on with valid credentials
62
+ And the App signs me on with valid credentials
63
+ Then the App receives a 201 response code
64
+ And the App receives an Auth Token
65
+ # And I am online
66
+
67
+
68
+ # TODO FIX ME - How should this respond?
69
+ Scenario: API Online Invalid Sign On Attempt
70
+
71
+ Given I have a User Profile
72
+ When the App signs me on with valid credentials
73
+ And the App tries to sign me on with invalid credentials
74
+ Then the App receives a 201 response code
75
+ And the App receives an Auth Token
76
+ # And I am online
@@ -0,0 +1,38 @@
1
+ Feature: API Sign Up
2
+
3
+ Scenario: API Valid Sign Up
4
+
5
+ When the App signs me up with valid credentials
6
+ Then the App receives a 201 response code
7
+ And the App receives an Auth Token
8
+
9
+
10
+ Scenario: API Sign Up with Duplicate Email
11
+
12
+ When the App tries to sign me up with a duplicate email
13
+ Then the App receives a 409 response code
14
+ And the App receives a duplicate email error
15
+
16
+
17
+
18
+ Scenario: API Sign Up with Invalid Email
19
+
20
+ When the App tries to sign me up with an invalid email address
21
+ Then the App receives a 412 response code
22
+ And the App receive an invalid email error
23
+
24
+
25
+ # TODO Return 422 for semantic error?
26
+ Scenario: API Sign Up with Missing Email
27
+
28
+ When the App tries to sign me up with a missing email address
29
+ Then the App receives a 412 response code
30
+ And the App receives a missing email error
31
+
32
+
33
+
34
+ Scenario: API Sign Up with Missing Password
35
+
36
+ When the App tries to sign me up with a missing password
37
+ Then the App receives a 412 response code
38
+ And the App receives a missing password error
@@ -0,0 +1,13 @@
1
+
2
+ When /^the App signs me off$/ do
3
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
4
+ @client.header 'X-AUTH-TOKEN', @user.pass_key.token
5
+ @client.delete '/profiles/' + @user.id.to_s + '/key'
6
+ @user.reload # Refresh from the database
7
+ end
8
+
9
+
10
+ Then /^I am offline$/ do
11
+ @user.status.should == :offline
12
+ end
13
+
@@ -0,0 +1,18 @@
1
+
2
+ When /^the App tries to sign me on with invalid credentials$/ do
3
+ credentials = {
4
+ :profile => {
5
+ :email => "bad@email.com",
6
+ :pass_phrase => "bad-password"
7
+ }
8
+ }
9
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
10
+ @client.post '/profiles/' + @user.id.to_s + '/key', credentials
11
+ end
12
+
13
+
14
+ When /^the App receives an Invalid User error$/ do
15
+ received = JSON.parse @client.last_response.body
16
+ expected = JSON.parse({:error => "The email or pass phrase you provided doesn't match our records."}.to_json)
17
+ received.should == expected
18
+ end
@@ -0,0 +1,13 @@
1
+
2
+ When /^the App receives a Locked User error$/ do
3
+ received = JSON.parse @client.last_response.body
4
+ expected = JSON.parse({:error => "Your account is locked. You can try to sign on again in 30 minutes."}.to_json)
5
+ received.should == expected
6
+ end
7
+
8
+
9
+ Given /^I have a Locked User Profile$/ do
10
+ @user = FactoryGirl.create :user_profile
11
+ @user.status = :locked
12
+ @user.save
13
+ end
@@ -0,0 +1,27 @@
1
+
2
+ Given /^I have a User Profile$/ do
3
+ @user = FactoryGirl.create :user_profile
4
+ @user.save # TODO Determine why this is necessary
5
+ end
6
+
7
+
8
+ When /^the App signs me on with valid credentials$/ do
9
+ credentials = {
10
+ :profile => {
11
+ :email => @user.email,
12
+ :pass_phrase => "password"
13
+ }
14
+ }
15
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
16
+ @client.post '/profiles/' + @user.id.to_s + '/key', credentials
17
+ end
18
+
19
+
20
+ When /^I sign on with valid credentials$/ do
21
+ @user.sign_on @user.email, 'password'
22
+ end
23
+
24
+
25
+ When /^I am online$/ do
26
+ @user.status.should == :online
27
+ end
@@ -0,0 +1,20 @@
1
+
2
+ When /^the App tries to sign me up with a duplicate email$/ do
3
+ email = FactoryGirl.generate :email
4
+ @user = AuthFx::UserProfile.sign_up email, "password"
5
+ credentials = {
6
+ :profile => {
7
+ :email => email,
8
+ :pass_phrase => "password"
9
+ }
10
+ }
11
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
12
+ @client.post '/profiles/', credentials
13
+ end
14
+
15
+
16
+ Then /^the App receives a duplicate email error$/ do
17
+ received = JSON.parse @client.last_response.body
18
+ expected = JSON.parse({:error => "We already have that email."}.to_json)
19
+ received.should == expected
20
+ end
@@ -0,0 +1,18 @@
1
+
2
+ When /^the App tries to sign me up with an invalid email address$/ do
3
+ credentials = {
4
+ :profile => {
5
+ :email => "bad.email.com",
6
+ :pass_phrase => "password"
7
+ }
8
+ }
9
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
10
+ @client.post '/profiles/', credentials
11
+ end
12
+
13
+
14
+ Then /^the App receive an invalid email error$/ do
15
+ received = JSON.parse @client.last_response.body
16
+ expected = JSON.parse({:errors => {:email => ["Doesn't look like an email address to me ..."]}}.to_json)
17
+ received.should == expected
18
+ end
@@ -0,0 +1,18 @@
1
+
2
+ When /^the App tries to sign me up with a missing email address$/ do
3
+ credentials = {
4
+ :profile => {
5
+ :email => "",
6
+ :pass_phrase => "password"
7
+ }
8
+ }
9
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
10
+ @client.post '/profiles/', credentials
11
+ end
12
+
13
+
14
+ Then /^the App receives a missing email error$/ do
15
+ received = JSON.parse @client.last_response.body
16
+ expected = JSON.parse({:errors => {:email => ["We need your email address."]}}.to_json)
17
+ received.should == expected
18
+ end
@@ -0,0 +1,23 @@
1
+
2
+ When /^the App signs me up with valid credentials$/ do
3
+ email = FactoryGirl.generate :email
4
+ credentials = {
5
+ :profile => {
6
+ :email => email,
7
+ :pass_phrase => "password"
8
+ }
9
+ }
10
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
11
+ @client.post '/profiles/', credentials
12
+ end
13
+
14
+
15
+ Then /^the App receives a (\d+) response code$/ do |arg|
16
+ @client.last_response.status.should == arg.to_i
17
+ end
18
+
19
+
20
+ Then /^the App receives an Auth Token$/ do
21
+ token = @client.last_response.headers['X-AUTH-TOKEN']
22
+ token.should_not.nil?
23
+ end
@@ -0,0 +1,19 @@
1
+
2
+ When /^the App tries to sign me up with a missing password$/ do
3
+ email = FactoryGirl.generate :email
4
+ credentials = {
5
+ :profile => {
6
+ :email => email,
7
+ :pass_phrase => ""
8
+ }
9
+ }
10
+ @client = Rack::Test::Session.new Rack::MockSession.new Test::App
11
+ @client.post '/profiles/', credentials
12
+ end
13
+
14
+
15
+ Then /^the App receives a missing password error$/ do
16
+ received = JSON.parse @client.last_response.body
17
+ expected = JSON.parse({:errors => {:pass_phrase => ["Pass phrase must be between 5 and 50 characters long"]}}.to_json)
18
+ received.should == expected
19
+ end
@@ -0,0 +1,23 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/fx-auth'
3
+ require 'rack/test'
4
+
5
+ require 'fx-auth/models'
6
+ require './test/factories'
7
+
8
+
9
+ module Test
10
+ class App < Sinatra::Base
11
+ register Sinatra::Fx::Auth
12
+ end
13
+ end
14
+
15
+
16
+ module AppHelper
17
+ def app
18
+ Test::App
19
+ end
20
+ end
21
+
22
+
23
+ World(Rack::Test::Methods, AppHelper)
@@ -0,0 +1,263 @@
1
+ require 'fx-auth/models'
2
+
3
+
4
+ module Sinatra
5
+ module Fx
6
+ module Auth
7
+ include AuthFx
8
+
9
+ module Helpers
10
+
11
+ def authenticated?
12
+ authenticated = false
13
+ profile, token = token_credentials
14
+ authenticated = profile.authenticate? token if profile #, request.ip if profile
15
+ log_authentication_failure profile, token unless authenticated #, request.ip unless authenticated
16
+ authenticated
17
+ end
18
+
19
+
20
+ def authorized? *roles
21
+ authorized = false
22
+ profile, token = token_credentials
23
+ authorized = profile.authorized? roles if profile
24
+ log_authorization_failure profile, roles unless authorized
25
+ authorized
26
+ end
27
+
28
+
29
+ private
30
+
31
+
32
+ def token_credentials
33
+ profile = nil
34
+ token = request.env['HTTP_X_AUTH_TOKEN']
35
+ unless token.nil?
36
+ passkey = Auth::PassKey.first :token => token
37
+ profile = passkey.user_profile if passkey
38
+ end
39
+ return profile, token
40
+ end
41
+
42
+
43
+ def param_credentials
44
+ return params[:profile][:email], params[:profile][:pass_phrase]
45
+ end
46
+
47
+
48
+ def valid_params?
49
+ # TODO Handle JSON body as well as FORM encoding
50
+ # request.body.rewind # in case someone already read it
51
+ # profile = JSON.parse request.body.read
52
+
53
+ params[:profile] and params[:profile][:email] and params[:profile][:pass_phrase]
54
+ end
55
+
56
+
57
+ def error_message
58
+ message = env['sinatra.error'].message
59
+ logger.error '### Error: ' + message + ' ###'
60
+ {:error => message}.to_json
61
+ end
62
+
63
+
64
+ def find_user
65
+ profile = Auth::UserProfile.get params[:id]
66
+ raise Auth::MissingUserError unless profile
67
+ profile
68
+ end
69
+
70
+
71
+ def profile_exclusions
72
+ [
73
+ :created_at,
74
+ :updated_at,
75
+ :email_verification_code,
76
+ :pass_phrase,
77
+ :pass_phrase_crypt,
78
+ :pass_phrase_expires_at,
79
+ :sign_on_attempts,
80
+ :locked_until
81
+ ]
82
+ end
83
+
84
+
85
+ def pass_key_exclusions
86
+ [
87
+ :id,
88
+ :created_at,
89
+ :updated_at,
90
+ :user_profile_id
91
+ ]
92
+ end
93
+
94
+
95
+ def log_authentication_failure profile, token #, ip_address
96
+ logger.warn '### BEGIN Authentication FAILURE ###'
97
+ if profile
98
+ logger.warn ' Profile: ' + profile.id.to_s
99
+ logger.warn ' Status: ' + profile.status.to_s if profile.status != :online
100
+ if profile.pass_key
101
+ logger.warn ' Token: ' + profile.pass_key.token + ' != Attempted: ' + token if profile.pass_key.token != token
102
+ logger.warn ' Expired: ' + profile.pass_key.expires.to_s + ' < ' + Time.now.to_s if profile.pass_key.expired?
103
+ #logger.warn ' IP: ' + profile.pass_key.ip_address.to_s + ' != Attempted: ' + ip_address if profile.pass_key.ip_address != ip_address
104
+ else
105
+ logger.warn ' PassKey: Missing'
106
+ end
107
+ else
108
+ logger.warn ' Profile: Not Found'
109
+ end
110
+ logger.warn '### END Authentication FAILURE ###'
111
+ end
112
+
113
+
114
+ def log_authorization_failure profile, allowed_roles
115
+ logger.warn '### BEGIN Authorization FAILURE ###'
116
+ if profile
117
+ profile_roles = []
118
+ profile.roles.each { |role| profile_roles.push role.name.to_sym }
119
+ logger.warn ' Profile: ' + profile.id.to_s
120
+ logger.warn ' Allowed Roles: ' + allowed_roles.to_s
121
+ logger.warn ' Profile Roles: ' + profile_roles.to_s
122
+ else
123
+ logger.warn ' Profile: Not Found'
124
+ end
125
+ logger.warn '### END Authorization FAILURE ###'
126
+ end
127
+
128
+ end
129
+
130
+
131
+ def self.registered app
132
+ app.helpers Auth::Helpers
133
+
134
+ app.enable :logging
135
+
136
+ app.set :raise_errors, Proc.new { false }
137
+ app.set :show_exceptions, false
138
+
139
+
140
+ app.set :auth do |*roles|
141
+ condition do
142
+ unless authenticated? and authorized? *roles
143
+ halt 401 # TODO Return any additional info? Expired session, etc.?
144
+ end
145
+ end
146
+ end
147
+
148
+
149
+ app.before do
150
+ content_type 'application/json' # TODO Support other representations, XML, etc.
151
+ end
152
+
153
+
154
+ # Sign Up
155
+ app.post '/profiles/?' do
156
+ halt 422 unless valid_params?
157
+
158
+ email, pass_phrase = param_credentials
159
+ profile = UserProfile.sign_up email, pass_phrase #, request.ip
160
+
161
+ if profile.errors.length == 0
162
+ headers "location" => '/profiles/' + profile.id.to_s,
163
+ "X-AUTH-TOKEN" => profile.pass_key.token
164
+ body profile.to_json :exclude => profile_exclusions
165
+ status 201
166
+
167
+ else
168
+ errs = {:errors => profile.errors.to_h}
169
+ body errs.to_json
170
+ status 412
171
+ end
172
+ end
173
+
174
+
175
+ # Sign On
176
+ app.post '/profiles/:id/key/?' do
177
+ profile = find_user
178
+
179
+ raise InvalidUserError unless valid_params?
180
+ raise LockedUserError.new :locked_until => profile.locked_until if profile.status == :locked
181
+
182
+ email, pass_phrase = param_credentials
183
+ pass_key = profile.sign_on email, pass_phrase #, request.ip
184
+
185
+ if pass_key
186
+ headers "location" => '/profiles/' + profile.id.to_s + '/key',
187
+ "X-AUTH-TOKEN" => pass_key.token
188
+ body pass_key.to_json :exclude => pass_key_exclusions
189
+ status 201
190
+ end
191
+ end
192
+
193
+
194
+ # Sign Off
195
+ app.delete '/profiles/:id/key', :auth => [:admin, :user] do
196
+ profile = find_user
197
+ profile.sign_off
198
+ end
199
+
200
+
201
+ app.get '/profiles/:id', :auth => [:admin, :user] do
202
+ profile = find_user
203
+ profile.to_json :exclude => profile_exclusions
204
+ end
205
+
206
+
207
+ app.put '/profiles/:id', :auth => [:admin, :user] do
208
+ profile = find_user
209
+ if profile.update params[:profile]
210
+ profile.to_json :exclude => profile_exclusions
211
+ else
212
+ errs = {:errors => profile.errors.to_h}
213
+ body errs.to_json
214
+ status 412
215
+ end
216
+ end
217
+
218
+
219
+ app.get '/profiles/?', :auth => :admin do
220
+ UserProfile.all.to_json :exclude => profile_exclusions
221
+ end
222
+
223
+
224
+ app.delete '/profiles/:id', :auth => :admin do
225
+ profile = find_user
226
+ unless profile.destroy
227
+ errs = {:errors => profile.errors.to_h}
228
+ body errs.to_json
229
+ status 412
230
+ end
231
+ end
232
+
233
+
234
+ app.error InvalidUserError do
235
+ halt 401, error_message
236
+ end
237
+
238
+
239
+ app.error MissingUserError do
240
+ halt 404, error_message
241
+ end
242
+
243
+
244
+ app.error DuplicateUserError do
245
+ halt 409, error_message
246
+ end
247
+
248
+
249
+ app.error LockedUserError do
250
+ halt 423, error_message
251
+ end
252
+
253
+
254
+ app.error do
255
+ halt 500, error_message
256
+ end
257
+
258
+ end
259
+
260
+ #register Auth
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,9 @@
1
+ module Sinatra
2
+ module Fx
3
+
4
+ module Auth
5
+ VERSION = "0.1.0"
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ require "sinatra/version"
2
+ require "sinatra/fx-auth"
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'sinatra/version'
7
+
8
+
9
+ Gem::Specification.new do |gem|
10
+ gem.name = "sinatra-fx-auth"
11
+ gem.version = Sinatra::Fx::Auth::VERSION
12
+
13
+ gem.authors = ["Dave Jackson"]
14
+ gem.email = %w(dave.jackson@anywarefx.com)
15
+ gem.description = %q{Sinatra::Fx::Auth - RESTful Authentication with Role-based Authorization for Sinatra}
16
+ gem.summary = %q{Sinatra::Fx::Auth - RESTful Authentication with Role-based Authorization for Sinatra}
17
+ gem.homepage = ""
18
+
19
+ gem.files = `git ls-files`.split($/)
20
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
21
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
+ gem.require_paths = %w(lib)
23
+
24
+ gem.add_dependency 'sinatra'
25
+ gem.add_dependency 'fx-auth'
26
+
27
+ gem.add_development_dependency 'rake'
28
+ gem.add_development_dependency 'cucumber'
29
+ gem.add_development_dependency 'rspec'
30
+ gem.add_development_dependency 'factory_girl'
31
+ gem.add_development_dependency 'rack-test'
32
+ gem.add_development_dependency 'dm-sqlite-adapter'
33
+ end
data/test/factories.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'factory_girl'
2
+ require 'test/seeds'
3
+
4
+
5
+ FactoryGirl.define do
6
+
7
+ sequence :email do |n|
8
+ "profile#{n}@example.com"
9
+ end
10
+
11
+
12
+ factory :user_profile, :class => AuthFx::UserProfile do
13
+ email
14
+ pass_phrase "password"
15
+ end
16
+
17
+ end
data/test/seeds.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'fx-auth/models'
2
+
3
+
4
+ DataMapper::Logger.new $stdout, :debug
5
+ DataMapper.setup :default, 'sqlite::memory:'
6
+ DataMapper.auto_migrate!
7
+
8
+
9
+ AuthFx::UserProfile.create(
10
+ {
11
+ :email => 'admin@authfx.com',
12
+ :pass_phrase => 'password',
13
+
14
+ :roles => [
15
+ {
16
+ :name => 'admin'
17
+ },
18
+ {
19
+ :name => 'user'
20
+ }
21
+ ]
22
+ }
23
+ )
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-fx-auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dave Jackson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '>='
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ name: sinatra
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: fx-auth
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ name: rake
48
+ prerelease: false
49
+ type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ name: cucumber
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ name: rspec
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ name: factory_girl
90
+ prerelease: false
91
+ type: :development
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ name: rack-test
104
+ prerelease: false
105
+ type: :development
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ name: dm-sqlite-adapter
118
+ prerelease: false
119
+ type: :development
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Sinatra::Fx::Auth - RESTful Authentication with Role-based Authorization for Sinatra
126
+ email:
127
+ - dave.jackson@anywarefx.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - Gemfile
134
+ - LICENSE.txt
135
+ - README.md
136
+ - Rakefile
137
+ - features/api_profile_list.feature
138
+ - features/api_sign_off.feature
139
+ - features/api_sign_on.feature
140
+ - features/api_sign_up.feature
141
+ - features/step_definitions/api_sign_off/api_sign_off.rb
142
+ - features/step_definitions/api_sign_on/api_invalid_credentials.rb
143
+ - features/step_definitions/api_sign_on/api_locked_account.rb
144
+ - features/step_definitions/api_sign_on/api_valid_credentials.rb
145
+ - features/step_definitions/api_sign_up/api_duplicate_email.rb
146
+ - features/step_definitions/api_sign_up/api_invalid_email.rb
147
+ - features/step_definitions/api_sign_up/api_missing_email.rb
148
+ - features/step_definitions/api_sign_up/api_valid_sign_up.rb
149
+ - features/step_definitions/api_sign_up/missing_password.rb
150
+ - features/support/env.rb
151
+ - lib/sinatra-fx-auth.rb
152
+ - lib/sinatra/fx-auth.rb
153
+ - lib/sinatra/version.rb
154
+ - sinatra-fx-auth.gemspec
155
+ - test/factories.rb
156
+ - test/seeds.rb
157
+ homepage: ''
158
+ licenses: []
159
+ metadata: {}
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 2.1.9
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: Sinatra::Fx::Auth - RESTful Authentication with Role-based Authorization for Sinatra
180
+ test_files:
181
+ - features/api_profile_list.feature
182
+ - features/api_sign_off.feature
183
+ - features/api_sign_on.feature
184
+ - features/api_sign_up.feature
185
+ - features/step_definitions/api_sign_off/api_sign_off.rb
186
+ - features/step_definitions/api_sign_on/api_invalid_credentials.rb
187
+ - features/step_definitions/api_sign_on/api_locked_account.rb
188
+ - features/step_definitions/api_sign_on/api_valid_credentials.rb
189
+ - features/step_definitions/api_sign_up/api_duplicate_email.rb
190
+ - features/step_definitions/api_sign_up/api_invalid_email.rb
191
+ - features/step_definitions/api_sign_up/api_missing_email.rb
192
+ - features/step_definitions/api_sign_up/api_valid_sign_up.rb
193
+ - features/step_definitions/api_sign_up/missing_password.rb
194
+ - features/support/env.rb
195
+ - test/factories.rb
196
+ - test/seeds.rb