songkick-oauth2-provider 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +12 -0
- data/example/environment.rb +7 -6
- data/example/models/connection.rb +4 -4
- data/example/schema.rb +4 -8
- data/lib/songkick/oauth2/model.rb +19 -0
- data/lib/songkick/oauth2/model/authorization.rb +29 -18
- data/lib/songkick/oauth2/model/client.rb +1 -3
- data/lib/songkick/oauth2/model/resource_owner.rb +7 -37
- data/lib/songkick/oauth2/provider.rb +22 -8
- data/lib/songkick/oauth2/provider/authorization.rb +6 -9
- data/lib/songkick/oauth2/router.rb +4 -5
- data/lib/songkick/oauth2/schema/20120828112156_songkick_oauth2_schema_original_schema.rb +1 -1
- data/lib/songkick/oauth2/schema/20121024180930_songkick_oauth2_schema_add_authorization_index.rb +14 -0
- data/lib/songkick/oauth2/schema/20121025180447_songkick_oauth2_schema_add_unique_indexes.rb +32 -0
- data/spec/factories.rb +0 -6
- data/spec/request_helpers.rb +10 -4
- data/spec/songkick/oauth2/model/authorization_spec.rb +31 -9
- data/spec/songkick/oauth2/model/client_spec.rb +1 -1
- data/spec/songkick/oauth2/model/resource_owner_spec.rb +3 -3
- data/spec/songkick/oauth2/provider/access_token_spec.rb +4 -2
- data/spec/songkick/oauth2/provider/authorization_spec.rb +3 -3
- data/spec/songkick/oauth2/provider/exchange_spec.rb +6 -6
- data/spec/songkick/oauth2/provider_spec.rb +19 -3
- data/spec/spec_helper.rb +23 -5
- metadata +162 -163
data/History.txt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
=== 0.10.1 / 2012-10-29
|
2
|
+
|
3
|
+
* Add uniqueness constraints to the database for various Authorization properties
|
4
|
+
* Make Authorization.new() and Authorization.create() private
|
5
|
+
* Disallow client_secret from being sent in a query string
|
6
|
+
* Use SecureRandom where available to generate tokens
|
7
|
+
|
8
|
+
|
9
|
+
=== 0.10.0 / 2012-08-27
|
10
|
+
|
11
|
+
* Initial release, implements http://tools.ietf.org/html/draft-ietf-oauth-v2-10
|
12
|
+
|
data/example/environment.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
$:.unshift(dir)
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
4
3
|
|
4
|
+
require 'active_record'
|
5
5
|
require 'songkick/oauth2/provider'
|
6
6
|
Songkick::OAuth2::Provider.realm = 'Notes App'
|
7
7
|
|
8
|
-
|
9
|
-
require 'models/
|
10
|
-
require 'models/
|
8
|
+
dir = File.expand_path('..', __FILE__)
|
9
|
+
require dir + '/models/connection'
|
10
|
+
require dir + '/models/user'
|
11
|
+
require dir + '/models/note'
|
11
12
|
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
require 'active_record'
|
1
|
+
require 'fileutils'
|
3
2
|
|
4
|
-
|
3
|
+
dbfile = File.expand_path('../../db/notes.sqlite3', __FILE__)
|
4
|
+
FileUtils.mkdir_p(File.dirname(dbfile))
|
5
5
|
|
6
6
|
ActiveRecord::Base.establish_connection(
|
7
7
|
:adapter => 'sqlite3',
|
8
|
-
:database =>
|
8
|
+
:database => dbfile)
|
9
9
|
|
data/example/schema.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
|
-
dir = File.expand_path('..', __FILE__)
|
2
|
-
$:.unshift(dir + '/../lib')
|
3
|
-
|
4
1
|
require 'rubygems'
|
5
|
-
require '
|
6
|
-
require 'fileutils'
|
2
|
+
require 'bundler/setup'
|
7
3
|
|
8
|
-
require
|
9
|
-
|
10
|
-
|
4
|
+
require 'songkick/oauth2/provider'
|
5
|
+
require 'active_record'
|
6
|
+
require File.expand_path('../models/connection', __FILE__)
|
11
7
|
|
12
8
|
ActiveRecord::Schema.define do |version|
|
13
9
|
create_table :users, :force => true do |t|
|
@@ -11,6 +11,25 @@ module Songkick
|
|
11
11
|
|
12
12
|
Schema = Songkick::OAuth2::Schema
|
13
13
|
|
14
|
+
DUPLICATE_RECORD_ERRORS = [
|
15
|
+
/^Mysql::Error:\s+Duplicate\s+entry\b/,
|
16
|
+
/^PG::Error:\s+ERROR:\s+duplicate\s+key\b/,
|
17
|
+
/\bConstraintException\b/
|
18
|
+
]
|
19
|
+
|
20
|
+
# ActiveRecord::RecordNotUnique was introduced in Rails 3.0 so referring
|
21
|
+
# to it while running earlier versions will raise an error. The above
|
22
|
+
# error strings should match PostgreSQL, MySQL and SQLite errors on
|
23
|
+
# Rails 2. If you're running a different adapter, add a suitable regex to
|
24
|
+
# the list:
|
25
|
+
#
|
26
|
+
# Songkick::OAuth2::Model::DUPLICATE_RECORD_ERRORS << /DB2 found a dup/
|
27
|
+
#
|
28
|
+
def self.duplicate_record_error?(error)
|
29
|
+
error.class.name == 'ActiveRecord::RecordNotUnique' or
|
30
|
+
DUPLICATE_RECORD_ERRORS.any? { |re| re =~ error.message }
|
31
|
+
end
|
32
|
+
|
14
33
|
def self.find_access_token(access_token)
|
15
34
|
Authorization.find_by_access_token_hash(Songkick::OAuth2.hashify(access_token))
|
16
35
|
end
|
@@ -19,14 +19,13 @@ module Songkick
|
|
19
19
|
|
20
20
|
attr_accessible nil
|
21
21
|
|
22
|
+
class << self
|
23
|
+
private :create, :new
|
24
|
+
end
|
25
|
+
|
22
26
|
extend Hashing
|
23
27
|
hashes_attributes :access_token, :refresh_token
|
24
28
|
|
25
|
-
def self.for(resource_owner, client)
|
26
|
-
return nil unless resource_owner and client
|
27
|
-
resource_owner.oauth2_authorizations.find_by_client_id(client.id)
|
28
|
-
end
|
29
|
-
|
30
29
|
def self.create_code(client)
|
31
30
|
Songkick::OAuth2.generate_id do |code|
|
32
31
|
client.authorizations.count(:conditions => {:code => code}).zero?
|
@@ -47,23 +46,29 @@ module Songkick
|
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
|
-
def self.
|
51
|
-
|
49
|
+
def self.for(owner, client, attributes = {})
|
50
|
+
return nil unless owner and client
|
51
|
+
|
52
|
+
unless client.is_a?(Client)
|
53
|
+
raise ArgumentError, "The argument should be a #{Client}, instead it was a #{client.class}"
|
54
|
+
end
|
55
|
+
|
56
|
+
instance = owner.oauth2_authorization_for(client) ||
|
52
57
|
new do |authorization|
|
53
|
-
authorization.owner =
|
54
|
-
authorization.client =
|
58
|
+
authorization.owner = owner
|
59
|
+
authorization.client = client
|
55
60
|
end
|
56
61
|
|
57
|
-
case response_type
|
62
|
+
case attributes[:response_type]
|
58
63
|
when CODE
|
59
|
-
instance.code ||= create_code(
|
64
|
+
instance.code ||= create_code(client)
|
60
65
|
when TOKEN
|
61
66
|
instance.access_token ||= create_access_token
|
62
|
-
instance.refresh_token ||= create_refresh_token(
|
67
|
+
instance.refresh_token ||= create_refresh_token(client)
|
63
68
|
when CODE_AND_TOKEN
|
64
|
-
instance.code = create_code(
|
69
|
+
instance.code = create_code(client)
|
65
70
|
instance.access_token ||= create_access_token
|
66
|
-
instance.refresh_token ||= create_refresh_token(
|
71
|
+
instance.refresh_token ||= create_refresh_token(client)
|
67
72
|
end
|
68
73
|
|
69
74
|
if attributes[:duration]
|
@@ -72,12 +77,18 @@ module Songkick
|
|
72
77
|
instance.expires_at = nil
|
73
78
|
end
|
74
79
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
80
|
+
scopes = instance.scopes + (attributes[:scopes] || [])
|
81
|
+
scopes += attributes[:scope].split(/\s+/) if attributes[:scope]
|
82
|
+
instance.scope = scopes.entries.join(' ')
|
79
83
|
|
80
84
|
instance.save && instance
|
85
|
+
|
86
|
+
rescue Object => error
|
87
|
+
if Model.duplicate_record_error?(error)
|
88
|
+
retry
|
89
|
+
else
|
90
|
+
raise error
|
91
|
+
end
|
81
92
|
end
|
82
93
|
|
83
94
|
def exchange!
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'bcrypt'
|
2
|
-
|
3
1
|
module Songkick
|
4
2
|
module OAuth2
|
5
3
|
module Model
|
@@ -13,7 +11,7 @@ module Songkick
|
|
13
11
|
|
14
12
|
has_many :authorizations, :class_name => 'Songkick::OAuth2::Model::Authorization', :dependent => :destroy
|
15
13
|
|
16
|
-
validates_uniqueness_of :client_id
|
14
|
+
validates_uniqueness_of :client_id, :name
|
17
15
|
validates_presence_of :name, :redirect_uri
|
18
16
|
validate :check_format_of_redirect_uri
|
19
17
|
|
@@ -2,50 +2,20 @@ module Songkick
|
|
2
2
|
module OAuth2
|
3
3
|
module Model
|
4
4
|
|
5
|
-
module AuthorizationAssociation
|
6
|
-
def find_or_create_for_client(client)
|
7
|
-
unless client.is_a?(Client)
|
8
|
-
raise ArgumentError, "The argument should be a #{Client}, instead it was a #{client.class}"
|
9
|
-
end
|
10
|
-
|
11
|
-
# find_or_create_by_client_id does not work across AR versions
|
12
|
-
authorization = find_by_client_id(client.id) || build
|
13
|
-
authorization.client = client
|
14
|
-
authorization.owner = owner
|
15
|
-
authorization.save
|
16
|
-
authorization
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def owner
|
22
|
-
respond_to?(:proxy_association) ? proxy_association.owner : proxy_owner
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
5
|
module ResourceOwner
|
27
6
|
def self.included(klass)
|
28
7
|
klass.has_many :oauth2_authorizations,
|
29
|
-
:class_name =>
|
8
|
+
:class_name => Authorization.name,
|
30
9
|
:as => :oauth2_resource_owner,
|
31
|
-
:dependent => :destroy
|
32
|
-
:extend => AuthorizationAssociation
|
10
|
+
:dependent => :destroy
|
33
11
|
end
|
34
12
|
|
35
13
|
def grant_access!(client, options = {})
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
if duration = options[:duration]
|
44
|
-
authorization.expires_at = Time.now + duration.to_i
|
45
|
-
end
|
46
|
-
|
47
|
-
authorization.save! if authorization.changed?
|
48
|
-
authorization
|
14
|
+
Authorization.for(self, client, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def oauth2_authorization_for(client)
|
18
|
+
oauth2_authorizations.find_by_client_id(client.id)
|
49
19
|
end
|
50
20
|
end
|
51
21
|
|
@@ -1,6 +1,15 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'bcrypt'
|
3
|
+
require 'cgi'
|
1
4
|
require 'digest/sha1'
|
2
5
|
require 'json'
|
3
6
|
require 'logger'
|
7
|
+
require 'rack'
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'securerandom'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
4
13
|
|
5
14
|
module Songkick
|
6
15
|
module OAuth2
|
@@ -12,7 +21,11 @@ module Songkick
|
|
12
21
|
autoload :Schema, ROOT + '/oauth2/schema'
|
13
22
|
|
14
23
|
def self.random_string
|
15
|
-
|
24
|
+
if defined? SecureRandom
|
25
|
+
SecureRandom.hex(TOKEN_SIZE / 8).to_i(16).to_s(36)
|
26
|
+
else
|
27
|
+
rand(2 ** TOKEN_SIZE).to_s(36)
|
28
|
+
end
|
16
29
|
end
|
17
30
|
|
18
31
|
def self.generate_id(&predicate)
|
@@ -63,6 +76,13 @@ module Songkick
|
|
63
76
|
ACCESS_DENIED = 'access_denied'
|
64
77
|
|
65
78
|
class Provider
|
79
|
+
EXPIRY_TIME = 3600
|
80
|
+
|
81
|
+
autoload :Authorization, ROOT + '/oauth2/provider/authorization'
|
82
|
+
autoload :Exchange, ROOT + '/oauth2/provider/exchange'
|
83
|
+
autoload :AccessToken, ROOT + '/oauth2/provider/access_token'
|
84
|
+
autoload :Error, ROOT + '/oauth2/provider/error'
|
85
|
+
|
66
86
|
class << self
|
67
87
|
attr_accessor :realm, :enforce_ssl
|
68
88
|
end
|
@@ -109,14 +129,8 @@ module Songkick
|
|
109
129
|
def self.access_token_from_request(*args)
|
110
130
|
Router.access_token_from_request(*args)
|
111
131
|
end
|
112
|
-
|
113
|
-
EXPIRY_TIME = 3600
|
114
|
-
|
115
|
-
autoload :Authorization, ROOT + '/oauth2/provider/authorization'
|
116
|
-
autoload :Exchange, ROOT + '/oauth2/provider/exchange'
|
117
|
-
autoload :AccessToken, ROOT + '/oauth2/provider/access_token'
|
118
|
-
autoload :Error, ROOT + '/oauth2/provider/error'
|
119
132
|
end
|
133
|
+
|
120
134
|
end
|
121
135
|
end
|
122
136
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
1
|
module Songkick
|
4
2
|
module OAuth2
|
5
3
|
class Provider
|
@@ -26,7 +24,7 @@ module Songkick
|
|
26
24
|
|
27
25
|
return unless @owner and not @error
|
28
26
|
|
29
|
-
@model =
|
27
|
+
@model = @owner.oauth2_authorization_for(@client)
|
30
28
|
return unless @model and @model.in_scope?(scopes) and not @model.expired?
|
31
29
|
|
32
30
|
@authorized = true
|
@@ -50,11 +48,10 @@ module Songkick
|
|
50
48
|
end
|
51
49
|
|
52
50
|
def grant_access!(options = {})
|
53
|
-
@model = Model::Authorization.
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:duration => options[:duration])
|
51
|
+
@model = Model::Authorization.for(@owner, @client,
|
52
|
+
:response_type => @params[RESPONSE_TYPE],
|
53
|
+
:scope => @scope,
|
54
|
+
:duration => options[:duration])
|
58
55
|
|
59
56
|
@code = @model.code
|
60
57
|
@access_token = @model.access_token
|
@@ -62,7 +59,7 @@ module Songkick
|
|
62
59
|
@expires_in = @model.expires_in
|
63
60
|
|
64
61
|
unless @params[RESPONSE_TYPE] == CODE
|
65
|
-
@expires_in
|
62
|
+
@expires_in = @model.expires_in
|
66
63
|
end
|
67
64
|
|
68
65
|
@authorized = true
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'rack'
|
3
|
-
|
4
1
|
module Songkick
|
5
2
|
module OAuth2
|
6
3
|
class Router
|
@@ -68,12 +65,14 @@ module Songkick
|
|
68
65
|
request = request_from(env)
|
69
66
|
|
70
67
|
if Provider.enforce_ssl and not request.ssl?
|
71
|
-
Provider::Error.new(
|
68
|
+
Provider::Error.new('must make requests using HTTPS')
|
69
|
+
elsif request.GET['client_secret']
|
70
|
+
Provider::Error.new('must not send client credentials in the URI')
|
72
71
|
end
|
73
72
|
end
|
74
73
|
end
|
75
74
|
|
76
75
|
end
|
77
76
|
end
|
78
|
-
|
77
|
+
end
|
79
78
|
|
@@ -9,7 +9,7 @@ class SongkickOauth2SchemaOriginalSchema < ActiveRecord::Migration
|
|
9
9
|
t.string :client_secret_hash
|
10
10
|
t.string :redirect_uri
|
11
11
|
end
|
12
|
-
add_index :oauth2_clients, :client_id
|
12
|
+
add_index :oauth2_clients, [:client_id]
|
13
13
|
|
14
14
|
create_table :oauth2_authorizations do |t|
|
15
15
|
t.timestamps
|
data/lib/songkick/oauth2/schema/20121024180930_songkick_oauth2_schema_add_authorization_index.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class SongkickOauth2SchemaAddAuthorizationIndex < ActiveRecord::Migration
|
2
|
+
INDEX_NAME = 'index_owner_client_pairs'
|
3
|
+
|
4
|
+
def self.up
|
5
|
+
remove_index :oauth2_authorizations, [:client_id, :access_token_hash]
|
6
|
+
add_index :oauth2_authorizations, [:client_id, :oauth2_resource_owner_type, :oauth2_resource_owner_id], :name => INDEX_NAME, :unique => true
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.down
|
10
|
+
remove_index :oauth2_authorizations, INDEX_NAME
|
11
|
+
add_index :oauth2_authorizations, [:client_id, :access_token_hash]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class SongkickOauth2SchemaAddUniqueIndexes < ActiveRecord::Migration
|
2
|
+
FIELDS = [:code, :refresh_token_hash]
|
3
|
+
|
4
|
+
def self.up
|
5
|
+
FIELDS.each do |field|
|
6
|
+
remove_index :oauth2_authorizations, [:client_id, field]
|
7
|
+
add_index :oauth2_authorizations, [:client_id, field], :unique => true
|
8
|
+
end
|
9
|
+
remove_index :oauth2_authorizations, [:access_token_hash]
|
10
|
+
add_index :oauth2_authorizations, [:access_token_hash], :unique => true
|
11
|
+
|
12
|
+
remove_index :oauth2_clients, [:client_id]
|
13
|
+
add_index :oauth2_clients, [:client_id], :unique => true
|
14
|
+
|
15
|
+
add_index :oauth2_clients, [:name], :unique => true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.down
|
19
|
+
FIELDS.each do |field|
|
20
|
+
remove_index :oauth2_authorizations, [:client_id, field]
|
21
|
+
add_index :oauth2_authorizations, [:client_id, field]
|
22
|
+
end
|
23
|
+
remove_index :oauth2_authorizations, [:access_token_hash]
|
24
|
+
add_index :oauth2_authorizations, [:access_token_hash]
|
25
|
+
|
26
|
+
remove_index :oauth2_clients, [:client_id]
|
27
|
+
add_index :oauth2_clients, [:client_id]
|
28
|
+
|
29
|
+
remove_clients :oauth2_clients, [:name]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/spec/factories.rb
CHANGED
@@ -19,9 +19,3 @@ Factory.define :client, :class => Songkick::OAuth2::Model::Client do |c|
|
|
19
19
|
c.redirect_uri 'https://client.example.com/cb'
|
20
20
|
end
|
21
21
|
|
22
|
-
Factory.define :authorization, :class => Songkick::OAuth2::Model::Authorization do |ac|
|
23
|
-
ac.client Factory(:client)
|
24
|
-
ac.code { Songkick::OAuth2.random_string }
|
25
|
-
ac.expires_at nil
|
26
|
-
end
|
27
|
-
|
data/spec/request_helpers.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
module RequestHelpers
|
2
2
|
require 'net/http'
|
3
3
|
|
4
|
+
def querystring(params)
|
5
|
+
params.map { |k,v| "#{ CGI.escape k.to_s }=#{ CGI.escape v.to_s }" }.join('&')
|
6
|
+
end
|
7
|
+
|
4
8
|
def get(query_params)
|
5
|
-
|
6
|
-
uri = URI.parse('http://localhost:8000/authorize?' + qs)
|
9
|
+
uri = URI.parse('http://localhost:8000/authorize?' + querystring(query_params))
|
7
10
|
Net::HTTP.get_response(uri)
|
8
11
|
end
|
9
12
|
|
@@ -16,8 +19,11 @@ module RequestHelpers
|
|
16
19
|
Net::HTTP.post_form(URI.parse(url), query_params)
|
17
20
|
end
|
18
21
|
|
19
|
-
def post(query_params)
|
20
|
-
|
22
|
+
def post(body_params, query_params = {})
|
23
|
+
uri = URI.parse('http://localhost:8000/authorize?' + querystring(query_params))
|
24
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
25
|
+
http.post(uri.path + '?' + uri.query.to_s, querystring(body_params))
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
29
|
def validate_response(response, status, body)
|
@@ -5,9 +5,10 @@ describe Songkick::OAuth2::Model::Authorization do
|
|
5
5
|
let(:impostor) { Factory :client }
|
6
6
|
let(:owner) { Factory :owner }
|
7
7
|
let(:user) { Factory :owner }
|
8
|
+
let(:tester) { Factory(:owner) }
|
8
9
|
|
9
10
|
let(:authorization) do
|
10
|
-
create_authorization(:owner =>
|
11
|
+
create_authorization(:owner => tester, :client => client)
|
11
12
|
end
|
12
13
|
|
13
14
|
it "is vaid" do
|
@@ -32,7 +33,7 @@ describe Songkick::OAuth2::Model::Authorization do
|
|
32
33
|
:access_token => 'existing_access_token')
|
33
34
|
|
34
35
|
create_authorization(
|
35
|
-
:owner =>
|
36
|
+
:owner => user,
|
36
37
|
:client => client,
|
37
38
|
:code => 'existing_code')
|
38
39
|
|
@@ -110,6 +111,27 @@ describe Songkick::OAuth2::Model::Authorization do
|
|
110
111
|
Songkick::OAuth2::Model::Authorization.create_refresh_token(impostor).should == 'existing_refresh_token'
|
111
112
|
end
|
112
113
|
end
|
114
|
+
|
115
|
+
describe "duplicate records" do
|
116
|
+
it "raises an error if a duplicate authorization is created" do
|
117
|
+
lambda {
|
118
|
+
authorization = Songkick::OAuth2::Model::Authorization.__send__(:new)
|
119
|
+
authorization.owner = user
|
120
|
+
authorization.client = client
|
121
|
+
authorization.save
|
122
|
+
}.should raise_error
|
123
|
+
end
|
124
|
+
|
125
|
+
it "finds an existing record after a race" do
|
126
|
+
user.stub(:oauth2_authorization_for) do
|
127
|
+
user.unstub(:oauth2_authorization_for)
|
128
|
+
raise TypeError, 'Mysql::Error: Duplicate entry'
|
129
|
+
end
|
130
|
+
authorization = Songkick::OAuth2::Model::Authorization.for(user, client)
|
131
|
+
authorization.owner.should == user
|
132
|
+
authorization.client.should == client
|
133
|
+
end
|
134
|
+
end
|
113
135
|
end
|
114
136
|
|
115
137
|
describe "#exchange!" do
|
@@ -150,7 +172,7 @@ describe Songkick::OAuth2::Model::Authorization do
|
|
150
172
|
|
151
173
|
describe "#grants_access?" do
|
152
174
|
it "returns true given the right user" do
|
153
|
-
authorization.grants_access?(
|
175
|
+
authorization.grants_access?(tester).should be_true
|
154
176
|
end
|
155
177
|
|
156
178
|
it "returns false given the wrong user" do
|
@@ -161,7 +183,7 @@ describe Songkick::OAuth2::Model::Authorization do
|
|
161
183
|
before { authorization.expires_at = 2.days.ago }
|
162
184
|
|
163
185
|
it "returns false in all cases" do
|
164
|
-
authorization.grants_access?(
|
186
|
+
authorization.grants_access?(tester).should be_false
|
165
187
|
authorization.grants_access?(user).should be_false
|
166
188
|
end
|
167
189
|
end
|
@@ -184,23 +206,23 @@ describe Songkick::OAuth2::Model::Authorization do
|
|
184
206
|
|
185
207
|
describe "#grants_access?" do
|
186
208
|
it "returns true given the right user and all authorization scopes" do
|
187
|
-
authorization.grants_access?(
|
209
|
+
authorization.grants_access?(tester, 'foo', 'bar').should be_true
|
188
210
|
end
|
189
211
|
|
190
212
|
it "returns true given the right user and some authorization scopes" do
|
191
|
-
authorization.grants_access?(
|
213
|
+
authorization.grants_access?(tester, 'bar').should be_true
|
192
214
|
end
|
193
215
|
|
194
216
|
it "returns false given the right user and some unauthorization scopes" do
|
195
|
-
authorization.grants_access?(
|
217
|
+
authorization.grants_access?(tester, 'foo', 'bar', 'qux').should be_false
|
196
218
|
end
|
197
219
|
|
198
220
|
it "returns false given an unauthorized scope" do
|
199
|
-
authorization.grants_access?(
|
221
|
+
authorization.grants_access?(tester, 'qux').should be_false
|
200
222
|
end
|
201
223
|
|
202
224
|
it "returns true given the right user" do
|
203
|
-
authorization.grants_access?(
|
225
|
+
authorization.grants_access?(tester).should be_true
|
204
226
|
end
|
205
227
|
|
206
228
|
it "returns false given the wrong user" do
|
@@ -4,7 +4,7 @@ describe Songkick::OAuth2::Model::Client do
|
|
4
4
|
before do
|
5
5
|
@client = Songkick::OAuth2::Model::Client.create(:name => 'App', :redirect_uri => 'http://example.com/cb')
|
6
6
|
@owner = Factory(:owner)
|
7
|
-
|
7
|
+
Songkick::OAuth2::Model::Authorization.for(@owner, @client)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "is valid" do
|
@@ -12,7 +12,7 @@ describe Songkick::OAuth2::Model::ResourceOwner do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "creates an authorization between the owner and the client" do
|
15
|
-
authorization = Songkick::OAuth2::Model::Authorization.new
|
15
|
+
authorization = Songkick::OAuth2::Model::Authorization.__send__(:new)
|
16
16
|
Songkick::OAuth2::Model::Authorization.should_receive(:new).and_return(authorization)
|
17
17
|
@owner.grant_access!(@client)
|
18
18
|
end
|
@@ -45,7 +45,7 @@ describe Songkick::OAuth2::Model::ResourceOwner do
|
|
45
45
|
|
46
46
|
describe "when there is an existing authorization" do
|
47
47
|
before do
|
48
|
-
@authorization =
|
48
|
+
@authorization = create_authorization(:owner => @owner, :client => @client)
|
49
49
|
end
|
50
50
|
|
51
51
|
it "does not create a new one" do
|
@@ -80,7 +80,7 @@ describe Songkick::OAuth2::Model::ResourceOwner do
|
|
80
80
|
end
|
81
81
|
|
82
82
|
it "destroys its authorizations on destroy" do
|
83
|
-
|
83
|
+
Songkick::OAuth2::Model::Authorization.for(@owner, @client)
|
84
84
|
@owner.destroy
|
85
85
|
Songkick::OAuth2::Model::Authorization.count.should be_zero
|
86
86
|
end
|
@@ -5,13 +5,15 @@ describe Songkick::OAuth2::Provider::AccessToken do
|
|
5
5
|
@alice = TestApp::User['Alice']
|
6
6
|
@bob = TestApp::User['Bob']
|
7
7
|
|
8
|
-
|
8
|
+
create_authorization(
|
9
9
|
:owner => @alice,
|
10
|
+
:client => Factory(:client),
|
10
11
|
:scope => 'profile',
|
11
12
|
:access_token => 'sesame')
|
12
13
|
|
13
|
-
@authorization =
|
14
|
+
@authorization = create_authorization(
|
14
15
|
:owner => @bob,
|
16
|
+
:client => Factory(:client),
|
15
17
|
:scope => 'profile',
|
16
18
|
:access_token => 'magic-key')
|
17
19
|
|
@@ -156,7 +156,7 @@ describe Songkick::OAuth2::Provider::Authorization do
|
|
156
156
|
describe "#grant_access!" do
|
157
157
|
describe "when there is an existing authorization with no code" do
|
158
158
|
before do
|
159
|
-
@model =
|
159
|
+
@model = create_authorization(
|
160
160
|
:owner => resource_owner,
|
161
161
|
:client => @client,
|
162
162
|
:code => nil)
|
@@ -172,7 +172,7 @@ describe Songkick::OAuth2::Provider::Authorization do
|
|
172
172
|
|
173
173
|
describe "when there is an existing authorization with scopes" do
|
174
174
|
before do
|
175
|
-
@model =
|
175
|
+
@model = create_authorization(
|
176
176
|
:owner => resource_owner,
|
177
177
|
:client => @client,
|
178
178
|
:code => nil,
|
@@ -190,7 +190,7 @@ describe Songkick::OAuth2::Provider::Authorization do
|
|
190
190
|
|
191
191
|
describe "when there is an existing expired authorization" do
|
192
192
|
before do
|
193
|
-
@model =
|
193
|
+
@model = create_authorization(
|
194
194
|
:owner => resource_owner,
|
195
195
|
:client => @client,
|
196
196
|
:expires_at => 2.months.ago,
|
@@ -5,7 +5,7 @@ describe Songkick::OAuth2::Provider::Exchange do
|
|
5
5
|
@client = Factory(:client)
|
6
6
|
@alice = TestApp::User['Alice']
|
7
7
|
@bob = TestApp::User['Bob']
|
8
|
-
@authorization =
|
8
|
+
@authorization = create_authorization(:client => @client, :owner => @bob, :code => 'a_fake_code', :scope => 'foo bar')
|
9
9
|
Songkick::OAuth2.stub(:random_string).and_return('random_string')
|
10
10
|
end
|
11
11
|
|
@@ -321,11 +321,11 @@ describe Songkick::OAuth2::Provider::Exchange do
|
|
321
321
|
|
322
322
|
describe "using refresh_token grant type" do
|
323
323
|
before do
|
324
|
-
@refresher =
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
324
|
+
@refresher = create_authorization(:client => @client,
|
325
|
+
:owner => @alice,
|
326
|
+
:scope => 'foo bar',
|
327
|
+
:code => nil,
|
328
|
+
:refresh_token => 'roflscale')
|
329
329
|
end
|
330
330
|
|
331
331
|
let(:params) { { 'client_id' => @client.client_id,
|
@@ -322,7 +322,11 @@ describe Songkick::OAuth2::Provider do
|
|
322
322
|
describe "access token request" do
|
323
323
|
before do
|
324
324
|
@client = Factory(:client)
|
325
|
-
@authorization =
|
325
|
+
@authorization = create_authorization(
|
326
|
+
:owner => @owner,
|
327
|
+
:client => @client,
|
328
|
+
:code => 'a_fake_code',
|
329
|
+
:expires_at => 3.hours.from_now)
|
326
330
|
end
|
327
331
|
|
328
332
|
let(:auth_params) { { 'client_id' => @client.client_id,
|
@@ -341,6 +345,7 @@ describe Songkick::OAuth2::Provider do
|
|
341
345
|
describe "with valid parameters" do
|
342
346
|
it "does not respond to GET" do
|
343
347
|
Songkick::OAuth2::Provider::Authorization.should_not_receive(:new)
|
348
|
+
params.delete('client_secret')
|
344
349
|
response = get(params)
|
345
350
|
validate_json_response(response, 400,
|
346
351
|
'error' => 'invalid_request',
|
@@ -348,6 +353,16 @@ describe Songkick::OAuth2::Provider do
|
|
348
353
|
)
|
349
354
|
end
|
350
355
|
|
356
|
+
it "does not allow client credentials to be passed in the query string" do
|
357
|
+
Songkick::OAuth2::Provider::Authorization.should_not_receive(:new)
|
358
|
+
query_string = {'client_id' => params.delete('client_id'), 'client_secret' => params.delete('client_secret')}
|
359
|
+
response = post(params, query_string)
|
360
|
+
validate_json_response(response, 400,
|
361
|
+
'error' => 'invalid_request',
|
362
|
+
'error_description' => 'Bad request: must not send client credentials in the URI'
|
363
|
+
)
|
364
|
+
end
|
365
|
+
|
351
366
|
describe "enforcing SSL" do
|
352
367
|
before { Songkick::OAuth2::Provider.enforce_ssl = true }
|
353
368
|
|
@@ -375,7 +390,7 @@ describe Songkick::OAuth2::Provider do
|
|
375
390
|
it "returns a successful response" do
|
376
391
|
Songkick::OAuth2.stub(:random_string).and_return('random_access_token')
|
377
392
|
response = post_basic_auth(auth_params, query_params)
|
378
|
-
validate_json_response(response, 200, 'access_token'
|
393
|
+
validate_json_response(response, 200, 'access_token' => 'random_access_token', 'expires_in' => 10800)
|
379
394
|
end
|
380
395
|
|
381
396
|
describe "with a scope parameter" do
|
@@ -445,8 +460,9 @@ describe Songkick::OAuth2::Provider do
|
|
445
460
|
|
446
461
|
describe "protected resource request" do
|
447
462
|
before do
|
448
|
-
@authorization =
|
463
|
+
@authorization = create_authorization(
|
449
464
|
:owner => @owner,
|
465
|
+
:client => @client,
|
450
466
|
:access_token => 'magic-key',
|
451
467
|
:scope => 'profile')
|
452
468
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,11 +2,29 @@ require 'rubygems'
|
|
2
2
|
require 'bundler/setup'
|
3
3
|
|
4
4
|
require 'active_record'
|
5
|
-
require
|
5
|
+
require 'songkick/oauth2/provider'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
ActiveRecord::Base.establish_connection(
|
7
|
+
case ENV['DB']
|
8
|
+
when 'mysql'
|
9
|
+
ActiveRecord::Base.establish_connection(
|
10
|
+
:adapter => 'mysql',
|
11
|
+
:host => '127.0.0.1',
|
12
|
+
:username => 'root',
|
13
|
+
:database => 'oauth2_test')
|
14
|
+
when 'postgres'
|
15
|
+
ActiveRecord::Base.establish_connection(
|
16
|
+
:adapter => 'postgresql',
|
17
|
+
:host => '127.0.0.1',
|
18
|
+
:username => 'postgres',
|
19
|
+
:database => 'oauth2_test')
|
20
|
+
else
|
21
|
+
dbfile = File.expand_path('../test.sqlite3', __FILE__)
|
22
|
+
File.unlink(dbfile) if File.file?(dbfile)
|
23
|
+
|
24
|
+
ActiveRecord::Base.establish_connection(
|
25
|
+
:adapter => 'sqlite3',
|
26
|
+
:database => dbfile)
|
27
|
+
end
|
10
28
|
|
11
29
|
require 'logger'
|
12
30
|
ActiveRecord::Base.logger = Logger.new(STDERR)
|
@@ -53,7 +71,7 @@ RSpec.configure do |config|
|
|
53
71
|
end
|
54
72
|
|
55
73
|
def create_authorization(params)
|
56
|
-
Songkick::OAuth2::Model::Authorization.create do |authorization|
|
74
|
+
Songkick::OAuth2::Model::Authorization.__send__(:create) do |authorization|
|
57
75
|
params.each do |key, value|
|
58
76
|
authorization.__send__ "#{key}=", value
|
59
77
|
end
|
metadata
CHANGED
@@ -1,193 +1,200 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: songkick-oauth2-provider
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.1
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 10
|
9
|
-
- 0
|
10
|
-
version: 0.10.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- James Coglan
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-10-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: activerecord
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: bcrypt-ruby
|
37
23
|
prerelease: false
|
38
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
25
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bcrypt-ruby
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
47
38
|
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: json
|
51
39
|
prerelease: false
|
52
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
41
|
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: json
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
61
54
|
type: :runtime
|
62
|
-
version_requirements: *id003
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: rack
|
65
55
|
prerelease: false
|
66
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rack
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
67
65
|
none: false
|
68
|
-
requirements:
|
69
|
-
- -
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
segments:
|
73
|
-
- 0
|
74
|
-
version: "0"
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
75
70
|
type: :runtime
|
76
|
-
version_requirements: *id004
|
77
|
-
- !ruby/object:Gem::Dependency
|
78
|
-
name: appraisal
|
79
71
|
prerelease: false
|
80
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: appraisal
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
81
|
none: false
|
82
|
-
requirements:
|
82
|
+
requirements:
|
83
83
|
- - ~>
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
hash: 15
|
86
|
-
segments:
|
87
|
-
- 0
|
88
|
-
- 4
|
89
|
-
- 0
|
84
|
+
- !ruby/object:Gem::Version
|
90
85
|
version: 0.4.0
|
91
86
|
type: :development
|
92
|
-
version_requirements: *id005
|
93
|
-
- !ruby/object:Gem::Dependency
|
94
|
-
name: activerecord
|
95
87
|
prerelease: false
|
96
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.4.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: activerecord
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
|
-
requirements:
|
98
|
+
requirements:
|
99
99
|
- - ~>
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
hash: 15
|
102
|
-
segments:
|
103
|
-
- 3
|
104
|
-
- 2
|
105
|
-
- 0
|
100
|
+
- !ruby/object:Gem::Version
|
106
101
|
version: 3.2.0
|
107
102
|
type: :development
|
108
|
-
version_requirements: *id006
|
109
|
-
- !ruby/object:Gem::Dependency
|
110
|
-
name: rspec
|
111
103
|
prerelease: false
|
112
|
-
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
105
|
none: false
|
114
|
-
requirements:
|
115
|
-
- -
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 3.2.0
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rspec
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
121
118
|
type: :development
|
122
|
-
version_requirements: *id007
|
123
|
-
- !ruby/object:Gem::Dependency
|
124
|
-
name: sqlite3
|
125
119
|
prerelease: false
|
126
|
-
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: sqlite3
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
127
129
|
none: false
|
128
|
-
requirements:
|
129
|
-
- -
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
|
132
|
-
segments:
|
133
|
-
- 0
|
134
|
-
version: "0"
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
135
134
|
type: :development
|
136
|
-
version_requirements: *id008
|
137
|
-
- !ruby/object:Gem::Dependency
|
138
|
-
name: sinatra
|
139
135
|
prerelease: false
|
140
|
-
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
137
|
none: false
|
142
|
-
requirements:
|
143
|
-
- -
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: sinatra
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
150
149
|
version: 1.3.0
|
151
150
|
type: :development
|
152
|
-
version_requirements: *id009
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: thin
|
155
151
|
prerelease: false
|
156
|
-
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
157
153
|
none: false
|
158
|
-
requirements:
|
159
|
-
- -
|
160
|
-
- !ruby/object:Gem::Version
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 1.3.0
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: thin
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
165
166
|
type: :development
|
166
|
-
version_requirements: *id010
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: factory_girl
|
169
167
|
prerelease: false
|
170
|
-
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
171
169
|
none: false
|
172
|
-
requirements:
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: factory_girl
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
173
179
|
- - ~>
|
174
|
-
- !ruby/object:Gem::Version
|
175
|
-
|
176
|
-
segments:
|
177
|
-
- 2
|
178
|
-
- 0
|
179
|
-
version: "2.0"
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '2.0'
|
180
182
|
type: :development
|
181
|
-
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ~>
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '2.0'
|
182
190
|
description:
|
183
191
|
email: james@songkick.com
|
184
192
|
executables: []
|
185
|
-
|
186
193
|
extensions: []
|
187
|
-
|
188
|
-
extra_rdoc_files:
|
194
|
+
extra_rdoc_files:
|
189
195
|
- README.rdoc
|
190
|
-
files:
|
196
|
+
files:
|
197
|
+
- History.txt
|
191
198
|
- README.rdoc
|
192
199
|
- example/public/style.css
|
193
200
|
- example/views/login.erb
|
@@ -218,7 +225,9 @@ files:
|
|
218
225
|
- lib/songkick/oauth2/provider/error.rb
|
219
226
|
- lib/songkick/oauth2/provider/access_token.rb
|
220
227
|
- lib/songkick/oauth2/schema.rb
|
228
|
+
- lib/songkick/oauth2/schema/20121024180930_songkick_oauth2_schema_add_authorization_index.rb
|
221
229
|
- lib/songkick/oauth2/schema/20120828112156_songkick_oauth2_schema_original_schema.rb
|
230
|
+
- lib/songkick/oauth2/schema/20121025180447_songkick_oauth2_schema_add_unique_indexes.rb
|
222
231
|
- lib/songkick/oauth2/router.rb
|
223
232
|
- lib/songkick/oauth2/model.rb
|
224
233
|
- spec/test_app/provider/views/authorize.erb
|
@@ -234,40 +243,30 @@ files:
|
|
234
243
|
- spec/songkick/oauth2/provider/access_token_spec.rb
|
235
244
|
- spec/songkick/oauth2/provider_spec.rb
|
236
245
|
- spec/spec_helper.rb
|
237
|
-
|
238
|
-
homepage: http://www.songkick.com
|
246
|
+
homepage: http://github.com/songkick/oauth2-provider
|
239
247
|
licenses: []
|
240
|
-
|
241
248
|
post_install_message:
|
242
|
-
rdoc_options:
|
249
|
+
rdoc_options:
|
243
250
|
- --main
|
244
251
|
- README.rdoc
|
245
|
-
require_paths:
|
252
|
+
require_paths:
|
246
253
|
- lib
|
247
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
254
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
248
255
|
none: false
|
249
|
-
requirements:
|
250
|
-
- -
|
251
|
-
- !ruby/object:Gem::Version
|
252
|
-
|
253
|
-
|
254
|
-
- 0
|
255
|
-
version: "0"
|
256
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
256
|
+
requirements:
|
257
|
+
- - ! '>='
|
258
|
+
- !ruby/object:Gem::Version
|
259
|
+
version: '0'
|
260
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
261
|
none: false
|
258
|
-
requirements:
|
259
|
-
- -
|
260
|
-
- !ruby/object:Gem::Version
|
261
|
-
|
262
|
-
segments:
|
263
|
-
- 0
|
264
|
-
version: "0"
|
262
|
+
requirements:
|
263
|
+
- - ! '>='
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: '0'
|
265
266
|
requirements: []
|
266
|
-
|
267
267
|
rubyforge_project:
|
268
|
-
rubygems_version: 1.
|
268
|
+
rubygems_version: 1.8.23
|
269
269
|
signing_key:
|
270
270
|
specification_version: 3
|
271
271
|
summary: Simple OAuth 2.0 provider toolkit
|
272
272
|
test_files: []
|
273
|
-
|