stormpath-rails 0.4.4 → 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +22 -3
- data/CHANGES.md +11 -0
- data/README.md +82 -24
- data/lib/stormpath/rails/account.rb +85 -30
- data/lib/stormpath/rails/client.rb +56 -27
- data/lib/stormpath/rails/railtie.rb +13 -0
- data/lib/stormpath/rails/version.rb +2 -1
- data/spec/client_spec.rb +222 -0
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/spec_helper.rb +91 -0
- data/spec/support/stormpath_account_shared_examples.rb +141 -49
- data/stormpath-rails.gemspec +14 -8
- metadata +98 -23
- data/lib/generators/stormpath/rails/install/install_generator.rb +0 -13
- data/lib/generators/stormpath/rails/templates/stormpath.yml +0 -11
- data/lib/stormpath/rails/config.rb +0 -14
- data/spec/fixtures/config/stormpath.yml +0 -12
- data/spec/generators/install_generator_spec.rb +0 -17
- data/spec/stormpath/rails/config_spec.rb +0 -41
- data/spec/support/rails.rb +0 -6
data/.gitignore
CHANGED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
stormpath-rails
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p429
|
data/.travis.yml
CHANGED
@@ -1,8 +1,27 @@
|
|
1
|
+
---
|
1
2
|
language: ruby
|
2
3
|
rvm:
|
3
|
-
|
4
|
+
- 1.9.3
|
4
5
|
gemfile:
|
5
|
-
|
6
|
+
- Gemfile
|
6
7
|
script: bundle exec rake spec
|
7
8
|
services:
|
8
|
-
|
9
|
+
- mongodb
|
10
|
+
env:
|
11
|
+
global:
|
12
|
+
- secure: |-
|
13
|
+
TFLI7BpxBBSoVV5x/tyr1iCqcQHcbzJeQPSR67J32VWbMDjM3mA9mz4SERvK
|
14
|
+
j9VD7pEAknEBNpYUYdBR4Ut0m5/0F+XiX1eDOVMbfpmEefJ8e38CgGz7HZbu
|
15
|
+
KdaWJhxTL8k/efyvJ+/UVPyzM4M0ADdyZIoDCDgRhj6AG5DqDJs=
|
16
|
+
- secure: |-
|
17
|
+
eu8VkY1iR5RYHvOobDQ7Miz8aG894F/BR/zEH8c3gpIhs7kItkBy0SKEMi5J
|
18
|
+
A1yMlQsONU7aq6pbqiJEiBKSDWf9OOoFBxHYm46fop+xaLVLuuK484O9VzDW
|
19
|
+
P6lV6Z06LolZaZsc2ENKf+2qfoO1XdN9gMTWD7QkT4x6OgRWiok=
|
20
|
+
- secure: |-
|
21
|
+
fMUOQUfUNkEDWmx5d4vIMIbqTuHIX1lu1PmbUnR25hHN9JFZnroxSvsvUlvH
|
22
|
+
qB+GCk5q7kMuvqYC+Mbx0Ndb3NSuLSKYGYhHw/39ZyMPHgBhPKQyZuDiK3OJ
|
23
|
+
g3Pv8Ot3lScgATu1lm5EzoGfN3ZVlSgmg5PJOwsafVaRlAUaHz4=
|
24
|
+
- secure: |-
|
25
|
+
UDTunvFjUyTaLHPa3iNOVwdAg37FzfKHRYdOiUoPH3aNA6pOgrtQYzkbhbJA
|
26
|
+
chBcZBdD+SnEyY6PmI1NsLzcNrqBP3tdyH4c5vVy3KQAzc5TfU6RocWTrqRP
|
27
|
+
FQKm/r0cbpjdydkpEzOKMk77Y56g6MTEk5cGFZjYoqhGKdz66O0=
|
data/CHANGES.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
stormpath-rails Changelog
|
2
|
+
=========================
|
3
|
+
|
4
|
+
Version 1.0.0.beta
|
5
|
+
------------------
|
6
|
+
|
7
|
+
Released on June 12, 2013
|
8
|
+
|
9
|
+
- Removed YML-generator in favor of reading APPLICATION_URL from ENV
|
10
|
+
- Allow flexible configuration of API key information (same as SDK client)
|
11
|
+
- Using new SDK (1.0.0.beta) API
|
data/README.md
CHANGED
@@ -1,36 +1,88 @@
|
|
1
1
|
[![Build Status](https://secure.travis-ci.org/stormpath/stormpath-rails.png)](http://travis-ci.org/stormpath/stormpath-rails)
|
2
2
|
[![Code Climate](https://codeclimate.com/github/stormpath/stormpath-rails.png)](https://codeclimate.com/github/stormpath/stormpath-rails)
|
3
|
+
# Stormpath Rails Gem
|
3
4
|
|
4
|
-
|
5
|
+
Stormpath is the first easy, secure user management and authentication service for developers.
|
6
|
+
This is the Rails gem to ease integration of its features with any Rails-based application.
|
5
7
|
|
6
|
-
##
|
8
|
+
## Setup
|
7
9
|
|
8
|
-
|
10
|
+
1. Install the <code>stormpath-rails</code> gem, either via the command line:
|
9
11
|
|
10
|
-
```
|
11
|
-
|
12
|
-
```
|
12
|
+
```
|
13
|
+
$ gem install stormpath-rails
|
14
|
+
```
|
13
15
|
|
14
|
-
|
16
|
+
or adding the gem to your [Bundler][bundler] Gemspec:
|
15
17
|
|
16
|
-
```
|
17
|
-
|
18
|
-
```
|
18
|
+
```
|
19
|
+
gem 'stormpath-rails'
|
20
|
+
```
|
21
|
+
|
22
|
+
or any other preferred dependency.
|
23
|
+
|
24
|
+
2. Create a [Stormpath][stormpath] developer account and [create your API Keys][create-api-keys]
|
25
|
+
downloading the <code>apiKey.properties</code> file into a <code>.stormpath</code>
|
26
|
+
folder under your local home directory. So that the Rails gem knows where to find this file,
|
27
|
+
add an environment variable called STORMPATH\_API\_KEY\_FILE\_LOCATION whose value is the full
|
28
|
+
path to this new .properties file:
|
29
|
+
|
30
|
+
```sh
|
31
|
+
export STORMPATH_API_KEY_FILE_LOCATION="/Users/john/.stormpath/apiKey.properties"
|
32
|
+
```
|
19
33
|
|
34
|
+
3. Create an application and a directory to store your users' accounts through the
|
35
|
+
[Stormpath Admin][stormpath-admin] interface. Make sure to add the newly-created
|
36
|
+
directory as a Login Source for your newly-created Application.
|
20
37
|
|
21
|
-
|
38
|
+
4. Through the [Stormpath Admin][stormpath-admin] interface, note your application's REST URL.
|
39
|
+
You'll want to create an environment variable called STORMPATH\_APPLICATION\_URL whose value
|
40
|
+
is this URL.
|
41
|
+
|
42
|
+
5. Generate and run migration, if you're on ActiveRecord. Skip this step for Mongoid.
|
43
|
+
```sh
|
44
|
+
rails g stormpath:rails:migration user
|
45
|
+
rake db:migrate
|
46
|
+
```
|
47
|
+
|
48
|
+
6. Update your model file.
|
49
|
+
```ruby
|
50
|
+
class User < ActiveRecord:Base
|
51
|
+
include Stormpath::Rails::Account
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
## Testing
|
56
|
+
|
57
|
+
To run the test suite, simple run:
|
22
58
|
|
23
59
|
```sh
|
24
|
-
|
25
|
-
rake db:migrate
|
60
|
+
$ rake spec
|
26
61
|
```
|
27
62
|
|
28
|
-
|
63
|
+
Note that this will make requests to the Stormpath API; you'll need to have set
|
64
|
+
environment variables enabling the client to interact with your Stormpath
|
65
|
+
account. You'll also need to have environment variables set that will enable
|
66
|
+
the client to interact with a test directory and application.
|
67
|
+
|
68
|
+
The test run will also generate a code-coverage report, viewable in the
|
69
|
+
coverage subdirectory.
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
You can make your own contributions by forking the <code>development</code>
|
74
|
+
branch, making your changes, and issuing pull-requests on the
|
75
|
+
<code>development</code> branch.
|
76
|
+
|
77
|
+
## Building the Gem
|
78
|
+
|
79
|
+
To build and install the development branch yourself from the latest source:
|
29
80
|
|
30
|
-
```
|
31
|
-
|
32
|
-
|
33
|
-
|
81
|
+
```
|
82
|
+
$ git clone git@github.com:stormpath/stormpath-rails.git
|
83
|
+
$ cd stormpath-rails
|
84
|
+
$ rake gem
|
85
|
+
$ gem install pkg/stormpath-rails-{version}.gem
|
34
86
|
```
|
35
87
|
|
36
88
|
## TODO
|
@@ -40,10 +92,16 @@ end
|
|
40
92
|
+ Preventive validation to not send invalid data to stormpath.
|
41
93
|
+ Solve n+1 request problem when requesting account collection.
|
42
94
|
|
43
|
-
##
|
95
|
+
## Copyright & Licensing
|
96
|
+
|
97
|
+
Copyright © 2012 Stormpath, Inc. and contributors.
|
98
|
+
|
99
|
+
This project is licensed under the [Apache 2.0 Open Source License](http://www.apache.org/licenses/LICENSE-2.0).
|
100
|
+
|
101
|
+
For additional information, please see the full [Project Documentation](https://www.stormpath.com/docs/ruby/product-guide).
|
44
102
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
103
|
+
[bundler]: http://gembundler.com/
|
104
|
+
[stormpath]: http://stormpath.com/
|
105
|
+
[create-api-keys]: http://www.stormpath.com/docs/ruby/product-guide#AssignAPIkeys
|
106
|
+
[stormpath_bootstrap]: https://github.com/stormpath/stormpath-sdk-ruby/wiki/Bootstrapping-Stormpath
|
107
|
+
[stormpath-admin]: https://api.stormpath.com/login
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require "stormpath-sdk"
|
3
|
-
include Stormpath::Client
|
4
|
-
include Stormpath::Resource
|
5
3
|
|
6
4
|
module Stormpath
|
7
5
|
module Rails
|
@@ -10,6 +8,28 @@ module Stormpath
|
|
10
8
|
|
11
9
|
STORMPATH_FIELDS = [ :email, :password, :username, :given_name, :middle_name, :surname, :status ]
|
12
10
|
|
11
|
+
module ClassMethods
|
12
|
+
def authenticate username, password
|
13
|
+
account = Stormpath::Rails::Client.authenticate_account username, password
|
14
|
+
self.where(stormpath_url: account.href).first
|
15
|
+
end
|
16
|
+
|
17
|
+
def send_password_reset_email email
|
18
|
+
account = Stormpath::Rails::Client.send_password_reset_email email
|
19
|
+
self.where(stormpath_url: account.href).first
|
20
|
+
end
|
21
|
+
|
22
|
+
def verify_password_reset_token token
|
23
|
+
account = Stormpath::Rails::Client.verify_password_reset_token token
|
24
|
+
self.where(stormpath_url: account.href).first
|
25
|
+
end
|
26
|
+
|
27
|
+
def verify_account_email token
|
28
|
+
account = Stormpath::Rails::Client.verify_account_email token
|
29
|
+
self.where(stormpath_url: account.href).first
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
13
33
|
included do
|
14
34
|
#AR specific workaround
|
15
35
|
self.partial_updates = false if self.respond_to?(:partial_updates)
|
@@ -18,48 +38,83 @@ module Stormpath
|
|
18
38
|
field(:stormpath_url, type: String) if self.respond_to?(:field)
|
19
39
|
index({ stormpath_url: 1 }, { unique: true }) if self.respond_to?(:index)
|
20
40
|
|
21
|
-
attr_accessor
|
22
|
-
attr_accessible
|
41
|
+
attr_accessor(*STORMPATH_FIELDS)
|
42
|
+
attr_accessible(*STORMPATH_FIELDS)
|
23
43
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
44
|
+
before_create :create_account_on_stormpath
|
45
|
+
before_update :update_account_on_stormpath
|
46
|
+
after_destroy :delete_account_on_stormpath
|
47
|
+
|
48
|
+
def stormpath_account
|
49
|
+
if stormpath_url
|
50
|
+
@stormpath_account ||= begin
|
51
|
+
Stormpath::Rails::Client.find_account(stormpath_url)
|
52
|
+
rescue Stormpath::Error => error
|
53
|
+
Stormpath::Rails.logger.warn "Error loading Stormpath account (#{error})"
|
54
|
+
end
|
31
55
|
end
|
32
56
|
end
|
33
57
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
58
|
+
def stormpath_pre_create_attrs
|
59
|
+
@stormpath_pre_create_attrs ||= {}
|
60
|
+
end
|
61
|
+
|
62
|
+
(STORMPATH_FIELDS - [:password]).each do |name|
|
63
|
+
define_method(name) do
|
64
|
+
if stormpath_account.present?
|
65
|
+
stormpath_account.send(name)
|
66
|
+
else
|
67
|
+
stormpath_pre_create_attrs[name]
|
68
|
+
end
|
40
69
|
end
|
41
|
-
self.stormpath_url = account.get_href
|
42
70
|
end
|
43
71
|
|
44
|
-
|
45
|
-
|
72
|
+
STORMPATH_FIELDS.each do |name|
|
73
|
+
define_method("#{name}=") do |val|
|
74
|
+
if stormpath_account.present?
|
75
|
+
stormpath_account.send("#{name}=", val)
|
76
|
+
else
|
77
|
+
stormpath_pre_create_attrs[name] = val
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_account_on_stormpath
|
46
83
|
begin
|
47
|
-
Client.
|
48
|
-
|
84
|
+
@stormpath_account = Stormpath::Rails::Client.create_account! stormpath_pre_create_attrs
|
85
|
+
stormpath_pre_create_attrs.clear
|
86
|
+
self.stormpath_url = @stormpath_account.href
|
87
|
+
rescue Stormpath::Error => error
|
49
88
|
self.errors[:base] << error.to_s
|
50
|
-
|
89
|
+
false
|
51
90
|
end
|
52
91
|
end
|
53
92
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
93
|
+
def update_account_on_stormpath
|
94
|
+
if self.stormpath_url.present?
|
95
|
+
begin
|
96
|
+
stormpath_account.save
|
97
|
+
rescue Stormpath::Error => error
|
98
|
+
self.errors[:base] << error.to_s
|
99
|
+
false
|
100
|
+
end
|
101
|
+
else
|
102
|
+
true
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def delete_account_on_stormpath
|
107
|
+
if self.stormpath_url.present?
|
108
|
+
begin
|
109
|
+
stormpath_account.delete
|
110
|
+
rescue Stormpath::Error => error
|
111
|
+
Stormpath::Rails.logger.warn "Error destroying Stormpath account (#{error})"
|
112
|
+
end
|
113
|
+
else
|
114
|
+
true
|
60
115
|
end
|
61
116
|
end
|
62
117
|
end
|
63
118
|
end
|
64
119
|
end
|
65
|
-
end
|
120
|
+
end
|
@@ -1,70 +1,99 @@
|
|
1
1
|
require "stormpath-sdk"
|
2
|
-
include Stormpath::Client
|
3
|
-
include Stormpath::Resource
|
4
|
-
include Stormpath::Authentication
|
5
2
|
|
6
3
|
module Stormpath
|
7
4
|
module Rails
|
5
|
+
class ConfigurationError < StandardError; end
|
6
|
+
|
8
7
|
class Client
|
9
8
|
class << self
|
10
|
-
attr_accessor :connection
|
9
|
+
attr_accessor :connection, :root_application
|
11
10
|
end
|
12
11
|
|
13
|
-
def self.authenticate_account(
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def self.authenticate_account(username, password)
|
13
|
+
auth_result = application.authenticate_account(
|
14
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(username, password)
|
15
|
+
)
|
16
|
+
auth_result.account
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.send_password_reset_email(
|
20
|
-
application
|
21
|
-
application.send_password_reset_email login_or_email
|
19
|
+
def self.send_password_reset_email(email)
|
20
|
+
application.send_password_reset_email email
|
22
21
|
end
|
23
22
|
|
24
23
|
def self.verify_password_reset_token(token)
|
25
|
-
application = self.ds.get_resource Config[:stormpath_url], ::Application
|
26
24
|
application.verify_password_reset_token token
|
27
25
|
end
|
28
26
|
|
29
27
|
def self.verify_account_email(token)
|
30
|
-
self.client.
|
28
|
+
self.client.accounts.verify_email_token token
|
31
29
|
end
|
32
30
|
|
33
31
|
def self.create_account!(attributes)
|
34
|
-
|
35
|
-
attributes.each { |field, value| account.send("set_#{field}", value) }
|
36
|
-
self.root_directory.create_account account
|
32
|
+
self.application.accounts.create attributes
|
37
33
|
end
|
38
34
|
|
39
35
|
def self.all_accounts
|
40
|
-
self.
|
36
|
+
self.application.accounts
|
41
37
|
end
|
42
38
|
|
43
39
|
def self.find_account(href)
|
44
|
-
self.
|
40
|
+
self.client.accounts.get href
|
45
41
|
end
|
46
42
|
|
47
43
|
def self.update_account!(href, attributes)
|
48
|
-
account = self.
|
49
|
-
attributes.each { |field, value| account.send("
|
44
|
+
account = self.find_account href
|
45
|
+
attributes.each { |field, value| account.send("#{field}=", value) }
|
50
46
|
account.save
|
51
47
|
end
|
52
48
|
|
53
49
|
def self.delete_account!(href)
|
54
|
-
self.
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.root_directory
|
58
|
-
self.ds.get_resource Config[:root], ::Directory
|
50
|
+
self.client.accounts.get(href).delete
|
59
51
|
end
|
60
52
|
|
61
53
|
def self.ds
|
62
54
|
self.client.data_store
|
63
55
|
end
|
64
56
|
|
57
|
+
def self.application
|
58
|
+
self.root_application ||= self.client.applications.get ENV["STORMPATH_APPLICATION_URL"]
|
59
|
+
end
|
60
|
+
|
65
61
|
def self.client
|
66
|
-
self.connection
|
67
|
-
|
62
|
+
unless self.connection
|
63
|
+
if ENV['STORMPATH_URL'].nil? && ENV['STORMPATH_APPLICATION_URL'].nil?
|
64
|
+
raise ConfigurationError, 'Either STORMPATH_URL or STORMPATH_APPLICATION_URL must be set'
|
65
|
+
end
|
66
|
+
|
67
|
+
composite_url = ENV['STORMPATH_URL']
|
68
|
+
|
69
|
+
if composite_url
|
70
|
+
self.root_application = Stormpath::Resource::Application.load composite_url
|
71
|
+
self.connection = self.root_application.client
|
72
|
+
else
|
73
|
+
self.connection = Stormpath::Client.new client_options
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
self.connection
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.client_options
|
81
|
+
Hash.new.tap do |o|
|
82
|
+
set_if_not_empty(o, "api_key_file_location", ENV["STORMPATH_API_KEY_FILE_LOCATION"])
|
83
|
+
set_if_not_empty(o, "api_key_id_property_name", ENV["STORMPATH_API_KEY_ID_PROPERTY_NAME"])
|
84
|
+
set_if_not_empty(o, "api_key_secret_property_name", ENV["STORMPATH_API_KEY_SECRET_PROPERTY_NAME"])
|
85
|
+
|
86
|
+
o[:api_key] = {
|
87
|
+
id: ENV["STORMPATH_API_KEY_ID"],
|
88
|
+
secret: ENV["STORMPATH_API_KEY_SECRET"]
|
89
|
+
} unless ENV["STORMPATH_API_KEY_ID"].blank? or ENV["STORMPATH_API_KEY_SECRET"].blank?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def self.set_if_not_empty(object, property, value)
|
96
|
+
object[property.to_sym] = value unless value.blank?
|
68
97
|
end
|
69
98
|
end
|
70
99
|
end
|