cadenero 0.0.2.a → 0.0.2.a1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +46 -9
- data/app/controllers/cadenero/v1/account/dashboard_controller.rb +1 -1
- data/app/controllers/cadenero/v1/account/sessions_controller.rb +27 -0
- data/app/controllers/cadenero/v1/accounts_controller.rb +4 -0
- data/app/extenders/controllers/application_controller_decorator.rb +4 -3
- data/app/serializers/cadenero/user_serializer.rb +1 -0
- data/config/initializers/warden/strategies/password.rb +13 -4
- data/config/initializers/warden.rb +1 -0
- data/config/routes.rb +6 -11
- data/db/seeds.rb +8 -2
- data/lib/cadenero/engine.rb +1 -0
- data/lib/cadenero/version.rb +1 -1
- data/lib/cadenero.rb +25 -0
- data/lib/generators/cadenero/install/templates/initializer.rb +0 -3
- data/lib/generators/cadenero/install_generator.rb +40 -17
- data/spec/dummy/app/controllers/application_controller.rb +6 -0
- data/spec/dummy/db/seeds.rb +8 -0
- data/spec/dummy/log/development.log +527 -87
- data/spec/dummy/log/test.log +3117 -8571
- data/spec/dummy/tmp/cache/assets/D0B/E90/sprockets%2F2c56f5dc65ded8014ad1226c5c985124 +0 -0
- data/spec/dummy/tmp/cache/assets/D86/490/sprockets%2Faaf0d4667cf7ef62869d70539bc77af7 +0 -0
- data/spec/dummy/tmp/cache/assets/DA6/CC0/sprockets%2F1c575d7a7db598dfcf41536ccc83f01e +0 -0
- data/spec/dummy/tmp/cache/assets/DB6/250/sprockets%2F0f882b7b9528900cfec89e8b2fffcc38 +0 -0
- data/spec/dummy/tmp/cache/assets/E18/9D0/sprockets%2F1f79e8f926ea465ded9dcc552cd56bff +0 -0
- data/spec/dummy/tmp/restart.txt +0 -0
- data/spec/features/users/sign_in_spec.rb +29 -10
- data/spec/features/users/sign_up_spec.rb +2 -2
- data/spec/generators/install_generator_spec.rb +1 -24
- metadata +17 -3
- data/app/controllers/cadenero/v1/sessions_controller.rb +0 -13
data/README.md
CHANGED
@@ -18,19 +18,56 @@ Authentication Engine for Rails.API multitenant RESTful APIs based on Warden. It
|
|
18
18
|
### Why Cadenero?
|
19
19
|
**"Cadenero"** is the spanish word for ["Bouncer (doorman)"](http://en.wikipedia.org/wiki/Bouncer_(doorman\)). The main function of **Cadenero** is to be a resource for authenticating consumers of the services that the API provides. As the real bouncers, **Cadenero** aims to provide security, check authorized access, to refuse entry for intoxication, aggressive behavior or non-compliance with statutory or establishment rules.
|
20
20
|
|
21
|
+
### Inatalling **Cadenero**
|
22
|
+
Generate first your Rails.API app as usual using:
|
23
|
+
```
|
24
|
+
> rails-api new your_app --skip-test-unit
|
25
|
+
```
|
26
|
+
In the `Gemfile` add the following lines:
|
27
|
+
```ruby
|
28
|
+
gem 'cadenero', '~> 0.0.2.a1'
|
29
|
+
gem 'pg'
|
30
|
+
```
|
31
|
+
In the `config/database.yml` replace the `sqlite3` adapter for `postgresql` as follow:
|
32
|
+
```
|
33
|
+
development:
|
34
|
+
adapter: postgresql
|
35
|
+
database: your_app_development
|
36
|
+
min_messages: warning
|
37
|
+
|
38
|
+
test:
|
39
|
+
adapter: postgresql
|
40
|
+
database: your_app_test
|
41
|
+
min_messages: warning
|
42
|
+
```
|
43
|
+
|
44
|
+
Then run bundle, create the databases and the generator:
|
45
|
+
```
|
46
|
+
> bundle install; rake db:create; rails-api g cadenero:install
|
47
|
+
```
|
48
|
+
Finally run the server:
|
49
|
+
```
|
50
|
+
rails-api s
|
51
|
+
```
|
52
|
+
|
53
|
+
Check that you can access the API using the default account `www` and user `testy@example.com` with password `changeme˜ for that you can use [cURL](http://curl.haxx.se/) or [RESTClient](http://restclient.net/)
|
54
|
+
|
55
|
+
Then have fun!
|
56
|
+
|
21
57
|
### Access Points
|
22
58
|
**Cadenero** creates the following versioned routes for exposing the authentication RESTful API
|
23
59
|
|
24
60
|
```
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
61
|
+
v1_root /v1(.:format) cadenero/v1/account/dashboard#index {:default=>:json}
|
62
|
+
v1_sessions POST /v1/sessions(.:format) cadenero/v1/account/sessions#create {:default=>:json}
|
63
|
+
DELETE /v1/sessions(.:format) cadenero/v1/account/sessions#delete {:default=>:json}
|
64
|
+
v1_users POST /v1/users(.:format) cadenero/v1/account/users#create {:default=>:json}
|
65
|
+
v1_accounts POST /v1/accounts(.:format) cadenero/v1/accounts#create {:default=>:json}
|
66
|
+
root / cadenero/v1/account/dashboard#index {:default=>:json}
|
67
|
+
```
|
68
|
+
You can check then running:
|
69
|
+
```
|
70
|
+
rake routes
|
34
71
|
```
|
35
72
|
|
36
73
|
### The Cadenero Task List
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_dependency "cadenero/application_controller"
|
2
|
+
|
3
|
+
module Cadenero::V1
|
4
|
+
class Account::SessionsController < Cadenero::ApplicationController
|
5
|
+
def create
|
6
|
+
Rails.logger.info "params: #{params}"
|
7
|
+
if env['warden'].authenticate(:password, :scope => :user)
|
8
|
+
render json: current_user, status: 201
|
9
|
+
else
|
10
|
+
render json: {errors: {user:["Invalid email or password"]}}, status: 422
|
11
|
+
end
|
12
|
+
end
|
13
|
+
def delete
|
14
|
+
user = Cadenero::User.find_by_id(params[:id])
|
15
|
+
Rails.logger.info "id: #{params[:id]}"
|
16
|
+
Rails.logger.info "user: #{user.to_json}"
|
17
|
+
Rails.logger.info "current_user.id: #{current_user}"
|
18
|
+
Rails.logger.info "user_signed_in?: #{user_signed_in?}"
|
19
|
+
if user_signed_in?
|
20
|
+
env['warden'].logout(:user)
|
21
|
+
render json: {message: "Successful logout"}, status: 201
|
22
|
+
else
|
23
|
+
render json: {message: "Unsuccessful logout user with id"}, status: 401
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -3,6 +3,10 @@ require_dependency "cadenero/application_controller"
|
|
3
3
|
module Cadenero
|
4
4
|
module V1
|
5
5
|
class AccountsController < Cadenero::ApplicationController
|
6
|
+
def new
|
7
|
+
errors = %Q{Please sign up. posting the account json data as {account: { name: "Testy", subdomain: "test", owner_attributes: {email: "testy@example.com", password: "changeme", password_confirmation: "changeme"} }} to /v1/accounts/sign_up}
|
8
|
+
render json: {errors: errors, links: "/v1/accounts/sign_up"}, status: 422
|
9
|
+
end
|
6
10
|
def create
|
7
11
|
@account = Cadenero::V1::Account.create_with_owner(params[:account])
|
8
12
|
if @account.valid?
|
@@ -23,7 +23,7 @@
|
|
23
23
|
if user_signed_in?
|
24
24
|
@current_user ||= begin
|
25
25
|
user_id = env['warden'].user(:scope => :user)
|
26
|
-
Cadenero::User.
|
26
|
+
Cadenero::User.find_by_id(user_id)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -35,9 +35,10 @@
|
|
35
35
|
|
36
36
|
# it the user is not authenticated returns a 422 and an informative error with the link for sign
|
37
37
|
def authenticate_user!
|
38
|
+
Rails.logger.info "env['warden'].authenticated?(:user): #{env['warden'].authenticated?(:user)}"
|
38
39
|
unless user_signed_in?
|
39
|
-
errors =
|
40
|
-
render json: {errors: errors, links: "/v1/
|
40
|
+
errors = %Q{Please sign in. posting the user json credentials as: {"user": {"email": "testy2@example.com", "password": "changeme"}} to /v1/sessions}
|
41
|
+
render json: {errors: errors, links: "/v1/sessions"}, status: 422
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
@@ -3,18 +3,27 @@ Warden::Strategies.add(:password) do
|
|
3
3
|
ActionDispatch::Http::URL.extract_subdomains(request.host, 1)
|
4
4
|
end
|
5
5
|
|
6
|
+
def json_params
|
7
|
+
unless params.empty?
|
8
|
+
params
|
9
|
+
else
|
10
|
+
@json ||= env['rack.input'].gets
|
11
|
+
JSON.parse(@json)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
def valid?
|
7
|
-
subdomain.present? &&
|
16
|
+
subdomain.present? && json_params["user"]
|
8
17
|
end
|
9
18
|
|
10
19
|
def authenticate!
|
11
20
|
account = Cadenero::V1::Account.find_by_subdomain(subdomain)
|
12
21
|
if account
|
13
|
-
u = account.users.find_by_email(
|
14
|
-
if u.nil?
|
22
|
+
u = account.users.find_by_email(json_params["user"]["email"])
|
23
|
+
if u.nil? || u.blank?
|
15
24
|
fail!
|
16
25
|
else
|
17
|
-
u.authenticate(
|
26
|
+
u.authenticate(json_params["user"]["password"]) ? success!(u) : fail!
|
18
27
|
end
|
19
28
|
else
|
20
29
|
fail!
|
data/config/routes.rb
CHANGED
@@ -2,23 +2,18 @@ require 'cadenero/constraints/subdomain_required'
|
|
2
2
|
|
3
3
|
Cadenero::Engine.routes.draw do
|
4
4
|
namespace :v1 do
|
5
|
-
get "users/new"
|
6
|
-
|
7
5
|
constraints(Cadenero::Constraints::SubdomainRequired) do
|
8
6
|
scope :module => "account" do
|
9
|
-
root :to => "dashboard#index"
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
post '/sign_up', :to => "users#create", :as => :user_sign_up
|
7
|
+
root :to => "dashboard#index", default: :json
|
8
|
+
post '/sessions', :to => "sessions#create", default: :json
|
9
|
+
delete '/sessions', :to => "sessions#delete", default: :json
|
10
|
+
post '/users', :to => "users#create", default: :json
|
14
11
|
end
|
15
12
|
end
|
16
|
-
|
17
|
-
post '/accounts', :to => "accounts#create", :as => :accounts
|
18
|
-
|
19
|
-
root :to => "dashboard#index"
|
13
|
+
post '/accounts', :to => "accounts#create", :as => :accounts, default: :json
|
20
14
|
|
21
15
|
end
|
16
|
+
root :to => "v1/account/dashboard#index", default: :json
|
22
17
|
# post '/v1/accounts', :to => "v1/accounts#create", :as => :accounts
|
23
18
|
|
24
19
|
end
|
data/db/seeds.rb
CHANGED
@@ -1,2 +1,8 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
@account = Cadenero::V1::Account.create!(name: Cadenero.default_account_name,
|
2
|
+
subdomain: Cadenero.default_account_subdomain,
|
3
|
+
owner: Cadenero::User.create!(email: Cadenero.default_user_email,
|
4
|
+
password: Cadenero.default_user_password,
|
5
|
+
password_confirmation: Cadenero.default_user_password))
|
6
|
+
|
7
|
+
@account.create_schema
|
8
|
+
@account.ensure_authentication_token!
|
data/lib/cadenero/engine.rb
CHANGED
data/lib/cadenero/version.rb
CHANGED
data/lib/cadenero.rb
CHANGED
@@ -26,4 +26,29 @@ require 'warden'
|
|
26
26
|
require 'apartment'
|
27
27
|
|
28
28
|
module Cadenero
|
29
|
+
mattr_accessor :base_path,
|
30
|
+
:user_class,
|
31
|
+
:default_account_name,
|
32
|
+
:default_account_subdomain,
|
33
|
+
:default_user_email,
|
34
|
+
:default_user_password
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def base_path
|
38
|
+
@@base_path ||= Rails.application.routes.named_routes[:cadenero].path
|
39
|
+
end
|
40
|
+
|
41
|
+
def user_class
|
42
|
+
if @@user_class.is_a?(Class)
|
43
|
+
raise "You can no longer set Cadenero.user_class to be a class. Please use a string instead."
|
44
|
+
elsif @@user_class.is_a?(String)
|
45
|
+
begin
|
46
|
+
Object.const_get(@@user_class)
|
47
|
+
rescue NameError
|
48
|
+
@@user_class.constantize
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
29
54
|
end
|
@@ -1,8 +1,5 @@
|
|
1
1
|
Cadenero.user_class = "<%= user_class %>"
|
2
|
-
Cadenero.email_from_address = "please-change-me@example.com"
|
3
2
|
# If you do not want to use gravatar for avatars then specify the method to use here:
|
4
|
-
# Cadenero.avatar_user_method = :custom_avatar_url
|
5
|
-
#Cadenero.per_page = <%= Cadenero.per_page.inspect %>
|
6
3
|
|
7
4
|
|
8
5
|
# Rails.application.config.to_prepare do
|
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'rails/generators'
|
2
2
|
module Cadenero
|
3
3
|
module Generators
|
4
|
-
class InstallGenerator < Rails::Generators::Base
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
5
|
class_option "user-class", :type => :string
|
6
|
+
class_option "default-account-name", :type => :string
|
7
|
+
class_option "default-account-subdomain", :type => :string
|
8
|
+
class_option "default-user-email", :type => :string
|
9
|
+
class_option "default-user-password", :type => :string
|
6
10
|
class_option "no-migrate", :type => :boolean
|
7
11
|
class_option "current-user-helper", :type => :string
|
8
12
|
|
@@ -18,13 +22,13 @@ module Cadenero
|
|
18
22
|
|
19
23
|
def determine_user_class
|
20
24
|
@user_class = options["user-class"].presence ||
|
21
|
-
ask("What
|
25
|
+
ask("What will be the name for your user class? [User]").presence ||
|
22
26
|
'User'
|
23
27
|
end
|
24
28
|
|
25
29
|
def determine_current_user_helper
|
26
30
|
current_user_helper = options["current-user-helper"].presence ||
|
27
|
-
ask("What
|
31
|
+
ask("What will be the current_user helper called in your app? [current_user]").presence ||
|
28
32
|
:current_user
|
29
33
|
|
30
34
|
puts "Defining cadenero_user method inside ApplicationController..."
|
@@ -43,6 +47,30 @@ module Cadenero
|
|
43
47
|
|
44
48
|
end
|
45
49
|
|
50
|
+
def determine_default_account_name
|
51
|
+
Cadenero.default_account_name = options["default-account-name"].presence ||
|
52
|
+
ask("What will be the name for the default account? [Root Account]").presence ||
|
53
|
+
'Root Account'
|
54
|
+
end
|
55
|
+
|
56
|
+
def determine_default_account_subdomain
|
57
|
+
Cadenero.default_account_subdomain = options["default-account-subdomain"].presence ||
|
58
|
+
ask("What will be the subdomain for the default account? [www]").presence ||
|
59
|
+
'www'
|
60
|
+
end
|
61
|
+
|
62
|
+
def determine_default_user_email
|
63
|
+
Cadenero.default_user_email = options["default-user-email"].presence ||
|
64
|
+
ask("What will be the email for the default user owner of the default account? [testy@example.com]").presence ||
|
65
|
+
'testy@example.com'
|
66
|
+
end
|
67
|
+
|
68
|
+
def determine_default_user_password
|
69
|
+
Cadenero.default_user_password = options["default-user-password "].presence ||
|
70
|
+
ask("What will be the password for the default user owner of the default account? [change-me]").presence ||
|
71
|
+
'change-me'
|
72
|
+
end
|
73
|
+
|
46
74
|
def add_cadenero_initializer
|
47
75
|
path = "#{Rails.root}/config/initializers/cadenero.rb"
|
48
76
|
if File.exists?(path)
|
@@ -62,6 +90,11 @@ module Cadenero
|
|
62
90
|
end
|
63
91
|
|
64
92
|
def seed_database
|
93
|
+
puts "default_account_name: #{Cadenero.default_account_name}"
|
94
|
+
puts "default_account_subdomain: #{Cadenero.default_account_subdomain}"
|
95
|
+
puts "default_user_email: #{Cadenero.default_user_email}"
|
96
|
+
puts "default_user_password: #{Cadenero.default_user_password}"
|
97
|
+
|
65
98
|
load "#{Rails.root}/config/initializers/cadenero.rb"
|
66
99
|
unless options["no-migrate"]
|
67
100
|
puts "Creating default cadenero account and owner"
|
@@ -73,10 +106,11 @@ module Cadenero
|
|
73
106
|
puts "Mounting Cadenero::Engine at \"/\" in config/routes.rb..."
|
74
107
|
insert_into_file("#{Rails.root}/config/routes.rb", :after => /routes.draw.do\n/) do
|
75
108
|
%Q{
|
76
|
-
# This line mounts Cadenero's routes at / by default.
|
109
|
+
mount Cadenero::Engine, :at => "/" # This line mounts Cadenero's routes at / by default.
|
77
110
|
# This means, any requests to the / URL of your application will go to Cadenero::V1:Account::DashboardController#index.
|
78
111
|
# If you would like to change where this extension is mounted, simply change the :at option to something different
|
79
112
|
# but that is discourage, the idea is to protect the whole site
|
113
|
+
|
80
114
|
}
|
81
115
|
end
|
82
116
|
end
|
@@ -88,8 +122,6 @@ module Cadenero
|
|
88
122
|
Here's what happened:\n\n}
|
89
123
|
|
90
124
|
output += step("Cadenero's migrations were copied over into db/migrate.\n")
|
91
|
-
output += step("We created a new migration called AddCadeneroAdminToTable.
|
92
|
-
This creates a new field called \"cadenero_admin\" on your #{user_class} model's table.\n")
|
93
125
|
output += step("A new method called `cadenero_user` was inserted into your ApplicationController.
|
94
126
|
This lets Cadenero know what the current user of your application is.\n")
|
95
127
|
output += step("A new file was created at config/initializers/cadenero.rb
|
@@ -97,25 +129,16 @@ Here's what happened:\n\n}
|
|
97
129
|
|
98
130
|
unless options["no-migrate"]
|
99
131
|
output += step("`rake db:migrate` was run, running all the migrations against your database.\n")
|
100
|
-
output += step("Seed
|
132
|
+
output += step("Seed account and user were loaded into your database.\n")
|
101
133
|
end
|
102
134
|
output += step("The engine was mounted in your config/routes.rb file using this line:
|
103
135
|
|
104
136
|
mount Cadenero::Engine, :at => \"/\"
|
105
137
|
|
106
|
-
If you want to change where the forums are located, just change the \"
|
138
|
+
If you want to change where the forums are located, just change the \"/\" path at the end of this line to whatever you want.")
|
107
139
|
output += %Q{\nAnd finally:
|
108
140
|
|
109
141
|
#{step("We told you that Cadenero has been successfully installed and walked you through the steps.")}}
|
110
|
-
unless defined?(Devise)
|
111
|
-
output += %Q{We have detected you're not using Devise (which is OK with us, really!), so there's one extra step you'll need to do.
|
112
|
-
|
113
|
-
You'll need to define a "sign_in_path" method for Cadenero to use that points to the sign in path for your application. You can set Cadenero.sign_in_path to a String inside config/initializers/cadenero.rb to do this, or you can define it in your config/routes.rb file with a line like this:
|
114
|
-
|
115
|
-
get '/users/sign_in', :to => "users#sign_in"
|
116
|
-
|
117
|
-
Either way, Cadenero needs one of these two things in order to work properly. Please define them!}
|
118
|
-
end
|
119
142
|
output += "\nIf you have any questions, comments or issues, please post them on our issues page: http://github.com/AgilTec/cadenero/issues.\n\n"
|
120
143
|
output += "Thanks for using Cadenero!"
|
121
144
|
puts output
|
@@ -0,0 +1,8 @@
|
|
1
|
+
@account = Cadenero::V1::Account.create!(name: 'Root Account',
|
2
|
+
subdomain: 'www',
|
3
|
+
owner: Cadenero::User.create!(email: 'testy@example.com',
|
4
|
+
password: '12345678',
|
5
|
+
password_confirmation: '12345678'))
|
6
|
+
|
7
|
+
@account.create_schema
|
8
|
+
@account.ensure_authentication_token!
|