cadenero 0.0.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/MIT-LICENSE +20 -0
- data/README.md +79 -0
- data/Rakefile +44 -0
- data/app/assets/javascripts/cadenero/application.js +15 -0
- data/app/assets/javascripts/cadenero/v1/accounts.js +2 -0
- data/app/assets/javascripts/cadenero/v1/users.js +2 -0
- data/app/assets/stylesheets/cadenero/application.css +13 -0
- data/app/assets/stylesheets/cadenero/v1/accounts.css +4 -0
- data/app/assets/stylesheets/cadenero/v1/users.css +4 -0
- data/app/controllers/cadenero/application_controller.rb +8 -0
- data/app/controllers/cadenero/v1/account/dashboard_controller.rb +11 -0
- data/app/controllers/cadenero/v1/account/users_controller.rb +27 -0
- data/app/controllers/cadenero/v1/accounts_controller.rb +23 -0
- data/app/controllers/cadenero/v1/sessions_controller.rb +13 -0
- data/app/extenders/controllers/application_controller_decorator.rb +51 -0
- data/app/helpers/cadenero/application_helper.rb +4 -0
- data/app/helpers/cadenero/v1/accounts_helper.rb +4 -0
- data/app/helpers/cadenero/v1/users_helper.rb +4 -0
- data/app/models/cadenero/member.rb +7 -0
- data/app/models/cadenero/user.rb +8 -0
- data/app/models/cadenero/v1/account.rb +60 -0
- data/app/serializers/cadenero/account_serializer.rb +9 -0
- data/app/serializers/cadenero/user_serializer.rb +8 -0
- data/config/initializers/apartment.rb +10 -0
- data/config/initializers/warden.rb +3 -0
- data/config/initializers/warden/strategies/password.rb +23 -0
- data/config/routes.rb +24 -0
- data/db/migrate/20130612061604_create_cadenero_v1_accounts.rb +12 -0
- data/db/migrate/20130612064652_create_cadenero_v1_users.rb +10 -0
- data/db/migrate/20130612073709_create_cadenero_v1_members.rb +12 -0
- data/db/migrate/20130612093908_add_authentication_token_to_accounts.rb +6 -0
- data/lib/cadenero.rb +29 -0
- data/lib/cadenero/active_record_extensions.rb +7 -0
- data/lib/cadenero/constraints/subdomain_required.rb +9 -0
- data/lib/cadenero/engine.rb +26 -0
- data/lib/cadenero/version.rb +3 -0
- data/lib/tasks/cadenero_tasks.rake +4 -0
- metadata +292 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2013 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+

|
|
2
|
+
By [](http://agiltec.github.io/).
|
|
3
|
+
|
|
4
|
+
[](http://badge.fury.io/rb/cadenero)
|
|
5
|
+
[](https://travis-ci.org/AgilTec/cadenero)
|
|
6
|
+
[](https://codeclimate.com/github/AgilTec/cadenero)
|
|
7
|
+
[](https://coveralls.io/r/AgilTec/cadenero?branch=master)
|
|
8
|
+
[](https://gemnasium.com/AgilTec/cadenero)
|
|
9
|
+
|
|
10
|
+
Authentication Engine for Rails.API multitenant RESTful APIs based on Warden. It:
|
|
11
|
+
* Is Racked based
|
|
12
|
+
* Use token authentication as strategy for the API
|
|
13
|
+
* Is RESTful API
|
|
14
|
+
* Allows you to have multiple roles (or models/scopes) signed in at the same time
|
|
15
|
+
|
|
16
|
+
## Information
|
|
17
|
+
|
|
18
|
+
### Why Cadenero?
|
|
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
|
+
|
|
21
|
+
### Access Points
|
|
22
|
+
**Cadenero** creates the following versioned routes for exposing the authentication RESTful API
|
|
23
|
+
|
|
24
|
+
```
|
|
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
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### The Cadenero Task List
|
|
37
|
+
- [x] Specs for the code 100% Coverage using BDD with [Rspec](https://github.com/rspec/rspec) and [Capybara](https://github.com/jnicklas/capybara)
|
|
38
|
+
- [ ] Documatation for all the code
|
|
39
|
+
- [ ] Examples of use and demo
|
|
40
|
+
|
|
41
|
+
### Bug reports
|
|
42
|
+
|
|
43
|
+
If you discover a problem with **Cadenero**, we would like to know about it. However, we ask that you please review these guidelines before submitting a bug report:
|
|
44
|
+
|
|
45
|
+
https://github.com/agiltec/cadenero/wiki/Bug-reports
|
|
46
|
+
|
|
47
|
+
If you found a security bug, do *NOT* use the GitHub issue tracker. Send an email to the maintainers listed at the bottom of the README please.
|
|
48
|
+
|
|
49
|
+
### Contributing
|
|
50
|
+
|
|
51
|
+
We hope that you will consider contributing to **Cadenero**. Please read this short overview for some information about how to get started:
|
|
52
|
+
|
|
53
|
+
https://github.com/agiltec/devise/cadenero/Contributing
|
|
54
|
+
|
|
55
|
+
You will usually want to write tests for your changes using BDD tools as RSpec, Rack::Test and Capybara. To run the test suite, go into **Cadenero**'s top-level directory and run "bundle install" and "rspec". For the tests to pass, you will need to have a Postgresql server running on your system.
|
|
56
|
+
|
|
57
|
+
### Warden
|
|
58
|
+
|
|
59
|
+
**Cadenero** is based on Warden, which is a general Rack authentication framework created by Daniel Neighman. We encourage you to read more about Warden here: https://github.com/hassox/warden
|
|
60
|
+
|
|
61
|
+
### Rails::API
|
|
62
|
+
|
|
63
|
+
**Cadenero** is a Rails::API Engine, Rails::API is a subset of a normal Rails application, created for applications that don't require all functionality that a complete Rails application provides. It is a bit more lightweight, and consequently a bit faster than a normal Rails application. The main example for its usage is in API applications only, where you usually don't need the entire Rails middleware stack nor template generation. Rails::API was created by Santiago Pastorino. We encourage you to read more about Rails::API here: https://github.com/rails-api/rails-api
|
|
64
|
+
|
|
65
|
+
### Multitenancy with Rails And subscriptions too!
|
|
66
|
+
Parts of the code of **Cadenero** have been based on the excellent work of [Ryan Bigg](https://github.com/radar) in his book ["Multitenancy with Rails And subscriptions too!"](https://leanpub.com/multi-tenancy-rails) but modified to be use in a RESTful API
|
|
67
|
+
|
|
68
|
+
### Maintainers
|
|
69
|
+
|
|
70
|
+
* Manuel Vidaurre (https://github.com/mvidaurre)
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
MIT License. Copyright 2013 AgilTec. http://agiltec.com.mx
|
|
75
|
+
|
|
76
|
+
You are not granted rights or licenses to the trademarks of the AgilTec, including without limitation the **Cadenero** name or logo.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
6
|
+
end
|
|
7
|
+
begin
|
|
8
|
+
require 'rdoc/task'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
require 'rdoc/rdoc'
|
|
11
|
+
require 'rake/rdoctask'
|
|
12
|
+
RDoc::Task = Rake::RDocTask
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
17
|
+
rdoc.title = 'Cadenero'
|
|
18
|
+
rdoc.options << '--line-numbers'
|
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
24
|
+
load 'rails/tasks/engine.rake'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Bundler::GemHelper.install_tasks
|
|
29
|
+
|
|
30
|
+
require 'rake/testtask'
|
|
31
|
+
|
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
|
33
|
+
t.libs << 'lib'
|
|
34
|
+
t.libs << 'test'
|
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
|
36
|
+
t.verbose = false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
desc 'run Rspec specs'
|
|
40
|
+
task :spec do
|
|
41
|
+
sh 'rspec spec'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
task :default => :spec
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// the compiled file.
|
|
9
|
+
//
|
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
|
12
|
+
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require_tree .
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
|
10
|
+
*
|
|
11
|
+
*= require_self
|
|
12
|
+
*= require_tree .
|
|
13
|
+
*/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# == Cadenero::Account::UsersController for creating the users associated to an account
|
|
2
|
+
#
|
|
3
|
+
# Inherates methods from the [::ApplicationController] extender
|
|
4
|
+
# @author Manuel Vidaurre @mvidaurre <manuel.vidaurre@agiltec.com.mx>
|
|
5
|
+
|
|
6
|
+
require_dependency "cadenero/application_controller"
|
|
7
|
+
|
|
8
|
+
module Cadenero
|
|
9
|
+
module V1
|
|
10
|
+
class Account::UsersController < Cadenero::ApplicationController
|
|
11
|
+
# Create a [Cadenero::User] based on the params sended by the client as a JSON with the user inrormation
|
|
12
|
+
#
|
|
13
|
+
# @example Posting the user data to be created in an account via the subdomain
|
|
14
|
+
# post "http://#{account.subdomain}.example.com/v1/sign_up",
|
|
15
|
+
# user: { email: "user@example.com", password: "password", password_confirmation: "password" }
|
|
16
|
+
#
|
|
17
|
+
# @return render JSON of [Cadenero::User] created and the status 201 Created: The request has been
|
|
18
|
+
# fulfilled and resulted in a new resource being created..
|
|
19
|
+
def create
|
|
20
|
+
account = Cadenero::V1::Account.where(subdomain: request.subdomain).first
|
|
21
|
+
@user = account.users.create(params[:user])
|
|
22
|
+
force_authentication!(@user)
|
|
23
|
+
render json: @user, status: 201
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require_dependency "cadenero/application_controller"
|
|
2
|
+
|
|
3
|
+
module Cadenero
|
|
4
|
+
module V1
|
|
5
|
+
class AccountsController < Cadenero::ApplicationController
|
|
6
|
+
def create
|
|
7
|
+
@account = Cadenero::V1::Account.create_with_owner(params[:account])
|
|
8
|
+
if @account.valid?
|
|
9
|
+
force_authentication!(@account.owner)
|
|
10
|
+
@account.create_schema
|
|
11
|
+
@account.ensure_authentication_token!
|
|
12
|
+
data = {
|
|
13
|
+
account_id: @account.id,
|
|
14
|
+
auth_token: @account.authentication_token
|
|
15
|
+
}
|
|
16
|
+
render json: data, status: 201
|
|
17
|
+
else
|
|
18
|
+
render json: {errors: @account.errors}, status: 422
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require_dependency "cadenero/application_controller"
|
|
2
|
+
|
|
3
|
+
module Cadenero::V1
|
|
4
|
+
class Account::SessionsController < Cadenero::ApplicationController
|
|
5
|
+
def create
|
|
6
|
+
if env['warden'].authenticate(:scope => :user)
|
|
7
|
+
render json: current_user, status: 201
|
|
8
|
+
else
|
|
9
|
+
render json: {errors: {user:["Invalid email or password"]}}, status: 422
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# == ApplicationController Extensions for Authentication
|
|
2
|
+
#
|
|
3
|
+
# Provide methods for manage authentication of users in a multitenant account environment.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
::ApplicationController.class_eval do
|
|
7
|
+
|
|
8
|
+
# Returns the current account for the authenticated user.
|
|
9
|
+
#
|
|
10
|
+
# @return [Cadenero::V1::Account] the current account.
|
|
11
|
+
def current_account
|
|
12
|
+
if user_signed_in?
|
|
13
|
+
@current_account ||= begin
|
|
14
|
+
Cadenero::V1::Account.find_by_subdomain(request.subdomain)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns the current authenticated user.
|
|
20
|
+
#
|
|
21
|
+
# @return [Cadenero::User] the current account.
|
|
22
|
+
def current_user
|
|
23
|
+
if user_signed_in?
|
|
24
|
+
@current_user ||= begin
|
|
25
|
+
user_id = env['warden'].user(:scope => :user)
|
|
26
|
+
Cadenero::User.find(user_id)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Check to see if there is an authenticated user
|
|
32
|
+
def user_signed_in?
|
|
33
|
+
env['warden'].authenticated?(:user)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# it the user is not authenticated returns a 422 and an informative error with the link for sign
|
|
37
|
+
def authenticate_user!
|
|
38
|
+
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
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Authenticate the provided user.
|
|
45
|
+
#
|
|
46
|
+
# @param user [Cadenero::User] the user to be authenthicated
|
|
47
|
+
def force_authentication!(user)
|
|
48
|
+
env['warden'].set_user(user.id, :scope => :user)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Cadenero::V1
|
|
2
|
+
class Account < ActiveRecord::Base
|
|
3
|
+
belongs_to :owner, :class_name => "Cadenero::User"
|
|
4
|
+
has_many :members, :class_name => "Cadenero::Member"
|
|
5
|
+
has_many :users, :through => :members
|
|
6
|
+
|
|
7
|
+
accepts_nested_attributes_for :owner
|
|
8
|
+
attr_accessible :name, :subdomain, :owner_attributes
|
|
9
|
+
validates :subdomain, :presence => true, :uniqueness => true
|
|
10
|
+
|
|
11
|
+
# Creates an accout and assign the provided [Cadenero::User] as owner to the account
|
|
12
|
+
# @param [Hash] params list
|
|
13
|
+
# @example
|
|
14
|
+
# Example for the params JSON: {name: "Testy", subdomain: "test",
|
|
15
|
+
# owner_attributes: {email: "testy@example.com", password: "changeme",
|
|
16
|
+
# password_confirmation: "changeme"} }
|
|
17
|
+
# @return the [Cadenero::V1::Account] created
|
|
18
|
+
# @note because this model uses accepts_nested_attributes_for :owner the JSOB should have owner_attributes
|
|
19
|
+
def self.create_with_owner(params={})
|
|
20
|
+
account = new(params)
|
|
21
|
+
if account.save
|
|
22
|
+
account.users << account.owner
|
|
23
|
+
end
|
|
24
|
+
account
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Create a database schema using the subdomain
|
|
28
|
+
def create_schema
|
|
29
|
+
Apartment::Database.create(subdomain)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Generate authentication token unless already exists and save the record.
|
|
33
|
+
def ensure_authentication_token!
|
|
34
|
+
reset_authentication_token! if authentication_token.blank?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Generate new authentication token (a.k.a. "single access token").
|
|
38
|
+
def reset_authentication_token!
|
|
39
|
+
self.authentication_token = self.class.authentication_token
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Generate a token checking if one does not already exist in the database.
|
|
43
|
+
# @return the authentication_token
|
|
44
|
+
def authentication_token
|
|
45
|
+
generate_token(:authentication_token)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Generate a token by looping and ensuring does not already exist.
|
|
49
|
+
# @params [String] column is the name of the column that has the authentication token
|
|
50
|
+
# @return a unique generated authentication_token
|
|
51
|
+
def generate_token(column)
|
|
52
|
+
loop do
|
|
53
|
+
token = SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
|
|
54
|
+
break token unless Account.where({ column => token }).first
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module Cadenero
|
|
2
|
+
class AccountSerializer < ActiveModel::Serializer
|
|
3
|
+
embed :ids
|
|
4
|
+
attributes :id, :name, :subdomain
|
|
5
|
+
has_one :owner, :class_name => "Cadenero::User"
|
|
6
|
+
has_many :members, :class_name => "Cadenero::Member"
|
|
7
|
+
has_many :users, :through => :members
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Rails.application.config.middleware.use 'Apartment::Elevators::Subdomain'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Apartment.configure do |config|
|
|
5
|
+
config.excluded_models = ["Cadenero::V1::Account",
|
|
6
|
+
"Cadenero::Member",
|
|
7
|
+
"Cadenero::User"]
|
|
8
|
+
# Dynamically get database names to migrate
|
|
9
|
+
# config.database_names = lambda{ Account.pluck(:database_name) }
|
|
10
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Warden::Strategies.add(:password) do
|
|
2
|
+
def subdomain
|
|
3
|
+
ActionDispatch::Http::URL.extract_subdomains(request.host, 1)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def valid?
|
|
7
|
+
subdomain.present? && params["user"]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def authenticate!
|
|
11
|
+
account = Cadenero::V1::Account.find_by_subdomain(subdomain)
|
|
12
|
+
if account
|
|
13
|
+
u = account.users.find_by_email(params["user"]["email"])
|
|
14
|
+
if u.nil?
|
|
15
|
+
fail!
|
|
16
|
+
else
|
|
17
|
+
u.authenticate(params["user"]["password"]) ? success!(u) : fail!
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
fail!
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'cadenero/constraints/subdomain_required'
|
|
2
|
+
|
|
3
|
+
Cadenero::Engine.routes.draw do
|
|
4
|
+
namespace :v1 do
|
|
5
|
+
get "users/new"
|
|
6
|
+
|
|
7
|
+
constraints(Cadenero::Constraints::SubdomainRequired) do
|
|
8
|
+
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
|
|
14
|
+
end
|
|
15
|
+
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"
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
# post '/v1/accounts', :to => "v1/accounts#create", :as => :accounts
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateCadeneroV1Members < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :cadenero_members do |t|
|
|
4
|
+
t.references :account
|
|
5
|
+
t.references :user
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
add_index :cadenero_members, :account_id
|
|
10
|
+
add_index :cadenero_members, :user_id
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/cadenero.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2013 AgilTec. Manuel Vidaurre @mvidaurre
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require "cadenero/engine"
|
|
25
|
+
require 'warden'
|
|
26
|
+
require 'apartment'
|
|
27
|
+
|
|
28
|
+
module Cadenero
|
|
29
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'warden'
|
|
2
|
+
module Cadenero
|
|
3
|
+
class Engine < ::Rails::Engine
|
|
4
|
+
isolate_namespace Cadenero
|
|
5
|
+
config.middleware.use Warden::Manager do |manager|
|
|
6
|
+
manager.default_strategies :password
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
config.generators do |g|
|
|
10
|
+
g.test_framework :rspec
|
|
11
|
+
g.integration_tool :rspec
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
config.to_prepare do
|
|
15
|
+
root = Cadenero::Engine.root
|
|
16
|
+
extenders_path = root + "app/extenders/**/*.rb"
|
|
17
|
+
Dir.glob(extenders_path) do |file|
|
|
18
|
+
Rails.configuration.cache_classes ? require(file) : load(file)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
config.middleware.use ActionDispatch::Cookies
|
|
23
|
+
config.middleware.use ActionDispatch::Session::CookieStore
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: cadenero
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Manuel Vidaurre
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-06-25 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: rails-api
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ~>
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 0.1.0
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 0.1.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: 3.0.1
|
|
38
|
+
type: :runtime
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ~>
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 3.0.1
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: warden
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ~>
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 1.2.1
|
|
54
|
+
type: :runtime
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 1.2.1
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: apartment
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
none: false
|
|
66
|
+
requirements:
|
|
67
|
+
- - ~>
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 0.21.1
|
|
70
|
+
type: :runtime
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ~>
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 0.21.1
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: strong_parameters
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ~>
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: 0.2.1
|
|
86
|
+
type: :runtime
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ~>
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: 0.2.1
|
|
94
|
+
- !ruby/object:Gem::Dependency
|
|
95
|
+
name: active_model_serializers
|
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
|
97
|
+
none: false
|
|
98
|
+
requirements:
|
|
99
|
+
- - ~>
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: 0.8.1
|
|
102
|
+
type: :runtime
|
|
103
|
+
prerelease: false
|
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ~>
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 0.8.1
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: pg
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
none: false
|
|
114
|
+
requirements:
|
|
115
|
+
- - ! '>='
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
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: rspec-rails
|
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
|
129
|
+
none: false
|
|
130
|
+
requirements:
|
|
131
|
+
- - ~>
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: 2.13.2
|
|
134
|
+
type: :development
|
|
135
|
+
prerelease: false
|
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
137
|
+
none: false
|
|
138
|
+
requirements:
|
|
139
|
+
- - ~>
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: 2.13.2
|
|
142
|
+
- !ruby/object:Gem::Dependency
|
|
143
|
+
name: coveralls
|
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
|
145
|
+
none: false
|
|
146
|
+
requirements:
|
|
147
|
+
- - ! '>='
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '0'
|
|
150
|
+
type: :development
|
|
151
|
+
prerelease: false
|
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
153
|
+
none: false
|
|
154
|
+
requirements:
|
|
155
|
+
- - ! '>='
|
|
156
|
+
- !ruby/object:Gem::Version
|
|
157
|
+
version: '0'
|
|
158
|
+
- !ruby/object:Gem::Dependency
|
|
159
|
+
name: capybara
|
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
|
161
|
+
none: false
|
|
162
|
+
requirements:
|
|
163
|
+
- - ~>
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: 2.1.0
|
|
166
|
+
type: :development
|
|
167
|
+
prerelease: false
|
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
169
|
+
none: false
|
|
170
|
+
requirements:
|
|
171
|
+
- - ~>
|
|
172
|
+
- !ruby/object:Gem::Version
|
|
173
|
+
version: 2.1.0
|
|
174
|
+
- !ruby/object:Gem::Dependency
|
|
175
|
+
name: launchy
|
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
|
177
|
+
none: false
|
|
178
|
+
requirements:
|
|
179
|
+
- - ~>
|
|
180
|
+
- !ruby/object:Gem::Version
|
|
181
|
+
version: 2.3.0
|
|
182
|
+
type: :development
|
|
183
|
+
prerelease: false
|
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
185
|
+
none: false
|
|
186
|
+
requirements:
|
|
187
|
+
- - ~>
|
|
188
|
+
- !ruby/object:Gem::Version
|
|
189
|
+
version: 2.3.0
|
|
190
|
+
- !ruby/object:Gem::Dependency
|
|
191
|
+
name: factory_girl
|
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
|
193
|
+
none: false
|
|
194
|
+
requirements:
|
|
195
|
+
- - ~>
|
|
196
|
+
- !ruby/object:Gem::Version
|
|
197
|
+
version: 4.2.0
|
|
198
|
+
type: :development
|
|
199
|
+
prerelease: false
|
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
201
|
+
none: false
|
|
202
|
+
requirements:
|
|
203
|
+
- - ~>
|
|
204
|
+
- !ruby/object:Gem::Version
|
|
205
|
+
version: 4.2.0
|
|
206
|
+
- !ruby/object:Gem::Dependency
|
|
207
|
+
name: database_cleaner
|
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
|
209
|
+
none: false
|
|
210
|
+
requirements:
|
|
211
|
+
- - ~>
|
|
212
|
+
- !ruby/object:Gem::Version
|
|
213
|
+
version: 1.0.1
|
|
214
|
+
type: :development
|
|
215
|
+
prerelease: false
|
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
217
|
+
none: false
|
|
218
|
+
requirements:
|
|
219
|
+
- - ~>
|
|
220
|
+
- !ruby/object:Gem::Version
|
|
221
|
+
version: 1.0.1
|
|
222
|
+
description: An Engine tha use Warden and OAuth for authenticate users using a RESTful
|
|
223
|
+
API
|
|
224
|
+
email:
|
|
225
|
+
- manuel.vidaurre@agiltec.com.mx
|
|
226
|
+
executables: []
|
|
227
|
+
extensions: []
|
|
228
|
+
extra_rdoc_files: []
|
|
229
|
+
files:
|
|
230
|
+
- app/assets/javascripts/cadenero/application.js
|
|
231
|
+
- app/assets/javascripts/cadenero/v1/accounts.js
|
|
232
|
+
- app/assets/javascripts/cadenero/v1/users.js
|
|
233
|
+
- app/assets/stylesheets/cadenero/application.css
|
|
234
|
+
- app/assets/stylesheets/cadenero/v1/accounts.css
|
|
235
|
+
- app/assets/stylesheets/cadenero/v1/users.css
|
|
236
|
+
- app/controllers/cadenero/application_controller.rb
|
|
237
|
+
- app/controllers/cadenero/v1/account/dashboard_controller.rb
|
|
238
|
+
- app/controllers/cadenero/v1/account/users_controller.rb
|
|
239
|
+
- app/controllers/cadenero/v1/accounts_controller.rb
|
|
240
|
+
- app/controllers/cadenero/v1/sessions_controller.rb
|
|
241
|
+
- app/extenders/controllers/application_controller_decorator.rb
|
|
242
|
+
- app/helpers/cadenero/application_helper.rb
|
|
243
|
+
- app/helpers/cadenero/v1/accounts_helper.rb
|
|
244
|
+
- app/helpers/cadenero/v1/users_helper.rb
|
|
245
|
+
- app/models/cadenero/member.rb
|
|
246
|
+
- app/models/cadenero/user.rb
|
|
247
|
+
- app/models/cadenero/v1/account.rb
|
|
248
|
+
- app/serializers/cadenero/account_serializer.rb
|
|
249
|
+
- app/serializers/cadenero/user_serializer.rb
|
|
250
|
+
- config/initializers/apartment.rb
|
|
251
|
+
- config/initializers/warden/strategies/password.rb
|
|
252
|
+
- config/initializers/warden.rb
|
|
253
|
+
- config/routes.rb
|
|
254
|
+
- db/migrate/20130612061604_create_cadenero_v1_accounts.rb
|
|
255
|
+
- db/migrate/20130612064652_create_cadenero_v1_users.rb
|
|
256
|
+
- db/migrate/20130612073709_create_cadenero_v1_members.rb
|
|
257
|
+
- db/migrate/20130612093908_add_authentication_token_to_accounts.rb
|
|
258
|
+
- lib/cadenero/active_record_extensions.rb
|
|
259
|
+
- lib/cadenero/constraints/subdomain_required.rb
|
|
260
|
+
- lib/cadenero/engine.rb
|
|
261
|
+
- lib/cadenero/version.rb
|
|
262
|
+
- lib/cadenero.rb
|
|
263
|
+
- lib/tasks/cadenero_tasks.rake
|
|
264
|
+
- MIT-LICENSE
|
|
265
|
+
- Rakefile
|
|
266
|
+
- README.md
|
|
267
|
+
homepage: http://www.agiltec.com.mx/ruby/gems/cadenero
|
|
268
|
+
licenses: []
|
|
269
|
+
post_install_message:
|
|
270
|
+
rdoc_options: []
|
|
271
|
+
require_paths:
|
|
272
|
+
- lib
|
|
273
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
274
|
+
none: false
|
|
275
|
+
requirements:
|
|
276
|
+
- - ! '>='
|
|
277
|
+
- !ruby/object:Gem::Version
|
|
278
|
+
version: '0'
|
|
279
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
280
|
+
none: false
|
|
281
|
+
requirements:
|
|
282
|
+
- - ! '>='
|
|
283
|
+
- !ruby/object:Gem::Version
|
|
284
|
+
version: '0'
|
|
285
|
+
requirements: []
|
|
286
|
+
rubyforge_project:
|
|
287
|
+
rubygems_version: 1.8.23
|
|
288
|
+
signing_key:
|
|
289
|
+
specification_version: 3
|
|
290
|
+
summary: Rails.API Engine for manage multitenant authentication
|
|
291
|
+
test_files: []
|
|
292
|
+
has_rdoc:
|