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.
Files changed (30) hide show
  1. data/README.md +46 -9
  2. data/app/controllers/cadenero/v1/account/dashboard_controller.rb +1 -1
  3. data/app/controllers/cadenero/v1/account/sessions_controller.rb +27 -0
  4. data/app/controllers/cadenero/v1/accounts_controller.rb +4 -0
  5. data/app/extenders/controllers/application_controller_decorator.rb +4 -3
  6. data/app/serializers/cadenero/user_serializer.rb +1 -0
  7. data/config/initializers/warden/strategies/password.rb +13 -4
  8. data/config/initializers/warden.rb +1 -0
  9. data/config/routes.rb +6 -11
  10. data/db/seeds.rb +8 -2
  11. data/lib/cadenero/engine.rb +1 -0
  12. data/lib/cadenero/version.rb +1 -1
  13. data/lib/cadenero.rb +25 -0
  14. data/lib/generators/cadenero/install/templates/initializer.rb +0 -3
  15. data/lib/generators/cadenero/install_generator.rb +40 -17
  16. data/spec/dummy/app/controllers/application_controller.rb +6 -0
  17. data/spec/dummy/db/seeds.rb +8 -0
  18. data/spec/dummy/log/development.log +527 -87
  19. data/spec/dummy/log/test.log +3117 -8571
  20. data/spec/dummy/tmp/cache/assets/D0B/E90/sprockets%2F2c56f5dc65ded8014ad1226c5c985124 +0 -0
  21. data/spec/dummy/tmp/cache/assets/D86/490/sprockets%2Faaf0d4667cf7ef62869d70539bc77af7 +0 -0
  22. data/spec/dummy/tmp/cache/assets/DA6/CC0/sprockets%2F1c575d7a7db598dfcf41536ccc83f01e +0 -0
  23. data/spec/dummy/tmp/cache/assets/DB6/250/sprockets%2F0f882b7b9528900cfec89e8b2fffcc38 +0 -0
  24. data/spec/dummy/tmp/cache/assets/E18/9D0/sprockets%2F1f79e8f926ea465ded9dcc552cd56bff +0 -0
  25. data/spec/dummy/tmp/restart.txt +0 -0
  26. data/spec/features/users/sign_in_spec.rb +29 -10
  27. data/spec/features/users/sign_up_spec.rb +2 -2
  28. data/spec/generators/install_generator_spec.rb +1 -24
  29. metadata +17 -3
  30. 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
- v1_users_new GET /v1/users/new(.:format) cadenero/v1/users#new
26
- v1_root /v1(.:format) cadenero/v1/account/dashboard#index
27
- v1_sign_in GET /v1/sign_in(.:format) cadenero/v1/account/sessions#new
28
- v1_sessions POST /v1/sign_in(.:format) cadenero/v1/account/sessions#create
29
- v1_user_sign_up GET /v1/sign_up(.:format) cadenero/v1/account/users#new
30
- v1_user_sign_up POST /v1/sign_up(.:format) cadenero/v1/account/users#create
31
- v1_sign_up GET /v1/sign_up(.:format) cadenero/v1/accounts#new
32
- v1_accounts POST /v1/accounts(.:format) cadenero/v1/accounts#create
33
- v1_root /v1(.:format) cadenero/v1/dashboard#index
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
@@ -5,7 +5,7 @@ module Cadenero
5
5
  before_filter :authenticate_user!
6
6
 
7
7
  def index
8
-
8
+ render json: {message: "Welcome #{current_user.email}"}, status: 201
9
9
  end
10
10
  end
11
11
  end
@@ -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.find(user_id)
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 = "Please sign in. posting the user json credentials to /v1/sign_in"
40
- render json: {errors: errors, links: "/v1/sign_in"}, status: 422
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
 
@@ -4,5 +4,6 @@ module Cadenero
4
4
  attributes :id, :email
5
5
  has_many :members, :class_name => "Cadenero::Member"
6
6
  has_many :accounts, :through => :members
7
+
7
8
  end
8
9
  end
@@ -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? && params["user"]
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(params["user"]["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(params["user"]["password"]) ? success!(u) : fail!
26
+ u.authenticate(json_params["user"]["password"]) ? success!(u) : fail!
18
27
  end
19
28
  else
20
29
  fail!
@@ -1,3 +1,4 @@
1
1
  Rails.application.config.middleware.use Warden::Manager do |manager|
2
+ manager.failure_app = Cadenero::V1::Account::DashboardController.action(:index)
2
3
  manager.default_strategies :password
3
4
  end
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
- get '/sign_in', :to => "sessions#new"
11
- post '/sign_in', :to => "sessions#create", :as => :sessions
12
- get '/sign_up', :to => "users#new", :as => :user_sign_up
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
- get '/sign_up', :to => "accounts#new", :as => :sign_up
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
- user = Cadenero::User.create(email: "testy@example.com", password: "changeme", password_confirmation: "changeme")
2
- Cadenero::V1::Account.create(name: 'Root Account for the Site', subdomain: 'www', owner: user)
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!
@@ -1,5 +1,6 @@
1
1
  require 'warden'
2
2
  module Cadenero
3
+
3
4
  class Engine < ::Rails::Engine
4
5
  isolate_namespace Cadenero
5
6
  config.middleware.use Warden::Manager do |manager|
@@ -1,3 +1,3 @@
1
1
  module Cadenero
2
- VERSION = "0.0.2.a"
2
+ VERSION = "0.0.2.a1"
3
3
  end
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 is your user class called? [User]").presence ||
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 is the current_user helper called in your app? [current_user]").presence ||
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 forum and topic were loaded into your database.\n")
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 \"/forums\" path at the end of this line to whatever you want.")
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
@@ -1,2 +1,8 @@
1
1
  class ApplicationController < ActionController::API
2
+
3
+ def cadenero_user
4
+ current_user
5
+ end
6
+ helper_method :cadenero_user
7
+
2
8
  end
@@ -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!