cadenero 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +79 -0
  3. data/Rakefile +44 -0
  4. data/app/assets/javascripts/cadenero/application.js +15 -0
  5. data/app/assets/javascripts/cadenero/v1/accounts.js +2 -0
  6. data/app/assets/javascripts/cadenero/v1/users.js +2 -0
  7. data/app/assets/stylesheets/cadenero/application.css +13 -0
  8. data/app/assets/stylesheets/cadenero/v1/accounts.css +4 -0
  9. data/app/assets/stylesheets/cadenero/v1/users.css +4 -0
  10. data/app/controllers/cadenero/application_controller.rb +8 -0
  11. data/app/controllers/cadenero/v1/account/dashboard_controller.rb +11 -0
  12. data/app/controllers/cadenero/v1/account/users_controller.rb +27 -0
  13. data/app/controllers/cadenero/v1/accounts_controller.rb +23 -0
  14. data/app/controllers/cadenero/v1/sessions_controller.rb +13 -0
  15. data/app/extenders/controllers/application_controller_decorator.rb +51 -0
  16. data/app/helpers/cadenero/application_helper.rb +4 -0
  17. data/app/helpers/cadenero/v1/accounts_helper.rb +4 -0
  18. data/app/helpers/cadenero/v1/users_helper.rb +4 -0
  19. data/app/models/cadenero/member.rb +7 -0
  20. data/app/models/cadenero/user.rb +8 -0
  21. data/app/models/cadenero/v1/account.rb +60 -0
  22. data/app/serializers/cadenero/account_serializer.rb +9 -0
  23. data/app/serializers/cadenero/user_serializer.rb +8 -0
  24. data/config/initializers/apartment.rb +10 -0
  25. data/config/initializers/warden.rb +3 -0
  26. data/config/initializers/warden/strategies/password.rb +23 -0
  27. data/config/routes.rb +24 -0
  28. data/db/migrate/20130612061604_create_cadenero_v1_accounts.rb +12 -0
  29. data/db/migrate/20130612064652_create_cadenero_v1_users.rb +10 -0
  30. data/db/migrate/20130612073709_create_cadenero_v1_members.rb +12 -0
  31. data/db/migrate/20130612093908_add_authentication_token_to_accounts.rb +6 -0
  32. data/lib/cadenero.rb +29 -0
  33. data/lib/cadenero/active_record_extensions.rb +7 -0
  34. data/lib/cadenero/constraints/subdomain_required.rb +9 -0
  35. data/lib/cadenero/engine.rb +26 -0
  36. data/lib/cadenero/version.rb +3 -0
  37. data/lib/tasks/cadenero_tasks.rake +4 -0
  38. metadata +292 -0
@@ -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.
@@ -0,0 +1,79 @@
1
+ ![Cadenero Logo](https://raw.github.com/AgilTec/cadenero/master/cadenero.logo.png)
2
+ By [![Agiltec Logo](https://launchrock-assets.s3.amazonaws.com/logo-files/GpujzvLXPPqzAcz.png)](http://agiltec.github.io/).
3
+
4
+ [![Gem Version](https://fury-badge.herokuapp.com/rb/cadenero.png)](http://badge.fury.io/rb/cadenero)
5
+ [![Build Status](https://travis-ci.org/AgilTec/cadenero.png?branch=master)](https://travis-ci.org/AgilTec/cadenero)
6
+ [![Code Climate](https://codeclimate.com/github/AgilTec/cadenero.png)](https://codeclimate.com/github/AgilTec/cadenero)
7
+ [![Coverage Status](https://coveralls.io/repos/AgilTec/cadenero/badge.png?branch=master)](https://coveralls.io/r/AgilTec/cadenero?branch=master)
8
+ [![Dependency Status](https://gemnasium.com/AgilTec/cadenero.png)](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.
@@ -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,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -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,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,8 @@
1
+ # == Cadenero::ApplicationController main application controller
2
+ #
3
+ # Inherates methods from the [::ApplicationController] extender
4
+ #
5
+ module Cadenero
6
+ class ApplicationController < ::ApplicationController
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ require_dependency "cadenero/application_controller"
2
+
3
+ module Cadenero
4
+ class V1::Account::DashboardController < Cadenero::ApplicationController
5
+ before_filter :authenticate_user!
6
+
7
+ def index
8
+
9
+ end
10
+ end
11
+ end
@@ -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,4 @@
1
+ module Cadenero
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Cadenero
2
+ module V1::AccountsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Cadenero
2
+ module V1::UsersHelper
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Cadenero
2
+ class Member < ActiveRecord::Base
3
+ belongs_to :account, :class_name => "Cadenero::V1::Account"
4
+ belongs_to :user, :class_name => "Cadenero::User"
5
+ # attr_accessible :title, :body
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Cadenero
2
+ class User < ActiveRecord::Base
3
+ attr_accessible :email, :password, :password_confirmation
4
+ has_secure_password
5
+ has_many :members, :class_name => "Cadenero::Member"
6
+ has_many :accounts, :through => :members
7
+ end
8
+ 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,8 @@
1
+ module Cadenero
2
+ class UserSerializer < ActiveModel::Serializer
3
+ embed :ids
4
+ attributes :id, :email
5
+ has_many :members, :class_name => "Cadenero::Member"
6
+ has_many :accounts, :through => :members
7
+ end
8
+ 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,3 @@
1
+ Rails.application.config.middleware.use Warden::Manager do |manager|
2
+ manager.default_strategies :password
3
+ 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
@@ -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 CreateCadeneroV1Accounts < ActiveRecord::Migration
2
+ def change
3
+ create_table :cadenero_accounts do |t|
4
+ t.string :name
5
+ t.string :subdomain
6
+ t.references :owner
7
+
8
+ t.timestamps
9
+ end
10
+ add_index :cadenero_accounts, :owner_id
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class CreateCadeneroV1Users < ActiveRecord::Migration
2
+ def change
3
+ create_table :cadenero_users do |t|
4
+ t.string :email
5
+ t.string :password_digest
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ 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
@@ -0,0 +1,6 @@
1
+ class AddAuthenticationTokenToAccounts < ActiveRecord::Migration
2
+ def change
3
+ add_column :cadenero_accounts, :authentication_token, :string
4
+ add_index :cadenero_accounts, :authentication_token
5
+ end
6
+ end
@@ -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,7 @@
1
+ ActiveRecord::Base.class_eval do
2
+ def self.scoped_to_account
3
+ belongs_to :account, :class_name => "Cadenero::V1::Account"
4
+ association_name = self.to_s.downcase.pluralize
5
+ Cadenero::V1::Account.has_many association_name, :class_name => self.to_s
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Cadenero
2
+ module Constraints
3
+ class SubdomainRequired
4
+ def self.matches?(request)
5
+ request.subdomain.present? && request.subdomain != "www"
6
+ end
7
+ end
8
+ end
9
+ 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
@@ -0,0 +1,3 @@
1
+ module Cadenero
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :cadenero do
3
+ # # Task goes here
4
+ # 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: