songkick-oauth2-provider 0.10.0 → 0.10.1
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.
- 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
|
-
|