maestrano-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +164 -0
  3. data/Rakefile +38 -0
  4. data/app/controllers/maestrano/rails/saml_base_controller.rb +39 -0
  5. data/lib/generators/active_record/maestrano_group_generator.rb +38 -0
  6. data/lib/generators/active_record/maestrano_user_generator.rb +38 -0
  7. data/lib/generators/active_record/templates/migration.rb +12 -0
  8. data/lib/generators/maestrano/USAGE +2 -0
  9. data/lib/generators/maestrano/group_generator.rb +11 -0
  10. data/lib/generators/maestrano/install_generator.rb +30 -0
  11. data/lib/generators/maestrano/orm_helpers.rb +75 -0
  12. data/lib/generators/maestrano/templates/maestrano.rb +84 -0
  13. data/lib/generators/maestrano/templates/saml_controller.rb +52 -0
  14. data/lib/generators/maestrano/user_generator.rb +11 -0
  15. data/lib/generators/mongoid/maestrano_group_generator.rb +26 -0
  16. data/lib/generators/mongoid/maestrano_user_generator.rb +26 -0
  17. data/lib/maestrano/rails/controllers/maestrano_security.rb +32 -0
  18. data/lib/maestrano/rails/models/maestrano_auth_resource.rb +96 -0
  19. data/lib/maestrano/rails/version.rb +5 -0
  20. data/lib/maestrano/rails.rb +10 -0
  21. data/lib/maestrano-rails.rb +1 -0
  22. data/test/controllers/generic_controller_test.rb +54 -0
  23. data/test/controllers/saml_controller_test.rb +117 -0
  24. data/test/dummy/README.rdoc +261 -0
  25. data/test/dummy/Rakefile +7 -0
  26. data/test/dummy/app/assets/javascripts/application.js +15 -0
  27. data/test/dummy/app/assets/javascripts/pages.js +2 -0
  28. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  29. data/test/dummy/app/assets/stylesheets/pages.css +4 -0
  30. data/test/dummy/app/controllers/application_controller.rb +3 -0
  31. data/test/dummy/app/controllers/maestrano/auth/saml_controller.rb +14 -0
  32. data/test/dummy/app/controllers/pages_controller.rb +4 -0
  33. data/test/dummy/app/helpers/application_helper.rb +2 -0
  34. data/test/dummy/app/helpers/pages_helper.rb +2 -0
  35. data/test/dummy/app/models/admin/monster.rb +2 -0
  36. data/test/dummy/app/models/admin.rb +5 -0
  37. data/test/dummy/app/models/mno_crew.rb +7 -0
  38. data/test/dummy/app/models/mno_monster.rb +9 -0
  39. data/test/dummy/app/models/monster.rb +2 -0
  40. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  41. data/test/dummy/app/views/pages/home.html.erb +2 -0
  42. data/test/dummy/config/application.rb +56 -0
  43. data/test/dummy/config/boot.rb +10 -0
  44. data/test/dummy/config/database.yml +25 -0
  45. data/test/dummy/config/environment.rb +5 -0
  46. data/test/dummy/config/environments/development.rb +37 -0
  47. data/test/dummy/config/environments/production.rb +67 -0
  48. data/test/dummy/config/environments/test.rb +37 -0
  49. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  50. data/test/dummy/config/initializers/inflections.rb +15 -0
  51. data/test/dummy/config/initializers/maestrano.rb +84 -0
  52. data/test/dummy/config/initializers/mime_types.rb +5 -0
  53. data/test/dummy/config/initializers/secret_token.rb +7 -0
  54. data/test/dummy/config/initializers/session_store.rb +8 -0
  55. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  56. data/test/dummy/config/locales/en.yml +5 -0
  57. data/test/dummy/config/routes.rb +70 -0
  58. data/test/dummy/config.ru +4 -0
  59. data/test/dummy/db/development.sqlite3 +0 -0
  60. data/test/dummy/db/migrate/20140526125222_create_monsters.rb +8 -0
  61. data/test/dummy/db/migrate/20140526125242_create_admin_monsters.rb +8 -0
  62. data/test/dummy/db/migrate/20140526144828_create_mno_monsters.rb +13 -0
  63. data/test/dummy/db/migrate/20140526151139_create_mno_crews.rb +11 -0
  64. data/test/dummy/db/schema.rb +44 -0
  65. data/test/dummy/db/test.sqlite3 +0 -0
  66. data/test/dummy/log/development.log +76 -0
  67. data/test/dummy/log/test.log +3732 -0
  68. data/test/dummy/public/404.html +26 -0
  69. data/test/dummy/public/422.html +26 -0
  70. data/test/dummy/public/500.html +25 -0
  71. data/test/dummy/public/favicon.ico +0 -0
  72. data/test/dummy/script/rails +6 -0
  73. data/test/dummy/test/fixtures/admin/monsters.yml +11 -0
  74. data/test/dummy/test/fixtures/mno_crews.yml +11 -0
  75. data/test/dummy/test/fixtures/mno_monsters.yml +15 -0
  76. data/test/dummy/test/fixtures/monsters.yml +11 -0
  77. data/test/dummy/test/functional/pages_controller_test.rb +9 -0
  78. data/test/dummy/test/unit/admin/monster_test.rb +7 -0
  79. data/test/dummy/test/unit/helpers/pages_helper_test.rb +4 -0
  80. data/test/dummy/test/unit/mno_crew_test.rb +7 -0
  81. data/test/dummy/test/unit/mno_monster_test.rb +7 -0
  82. data/test/dummy/test/unit/monster_test.rb +7 -0
  83. data/test/generators/group/active_record_generator_test.rb +79 -0
  84. data/test/generators/group/mongoid_generator_test.rb +76 -0
  85. data/test/generators/group_generator_test.rb +39 -0
  86. data/test/generators/install_generator_test.rb +36 -0
  87. data/test/generators/user/active_record_generator_test.rb +79 -0
  88. data/test/generators/user/mongoid_generator_test.rb +76 -0
  89. data/test/generators/user_generator_test.rb +39 -0
  90. data/test/maestrano-rails_test.rb +7 -0
  91. data/test/models/maestrano_group_via_test.rb +66 -0
  92. data/test/models/maestrano_user_via_test.rb +70 -0
  93. data/test/test_files/config/routes.rb +58 -0
  94. data/test/test_helper.rb +24 -0
  95. data/test/tmp/app/models/monster.rb +20 -0
  96. metadata +287 -0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Maestrano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,164 @@
1
+ <p align="center">
2
+ <img src="https://raw.github.com/maestrano/maestrano-rails/master/maestrano.png" alt="Maestrano Logo">
3
+ </p>
4
+
5
+ Maestrano Cloud Integration is currently in closed beta. Want to know more? Send us an email to <contact@maestrano.com>.
6
+
7
+ ## Getting Setup
8
+ Before integrating with us you will need an API Key. Maestrano Cloud Integration being still in closed beta you will need to contact us beforehand to gain production access.
9
+
10
+ For testing purpose we provide an API Sandbox where you can freely obtain an API Token. The sandbox is great to test single sign-on and API integration (e.g: billing API).
11
+
12
+ To get started just go to: http://api-sandbox.maestrano.io
13
+
14
+ ## Getting Started
15
+
16
+ maestrano-rails works with Rails 3.2 onwards. You can add it to your Gemfile with:
17
+
18
+ ```ruby
19
+ gem 'maestrano-rails'
20
+ ```
21
+
22
+ Run bundle to install the gem as well as the [maestrano ruby bindings](https://github.com/maestrano/maestrano-ruby) (dependency)
23
+
24
+ ```console
25
+ bundle
26
+ ```
27
+
28
+ After you install Maestrano and add it to your Gemfile, you need to run the generator:
29
+
30
+ ```console
31
+ rails generate maestrano:install
32
+ ```
33
+
34
+ The generator will install an initializer which describes ALL Maestrano's configuration options. You will need to take a look at it as this is where you set your API key.
35
+ The generator also generates a SamlController for single sign-on that you will need to customize (see below) as well as the required routes.
36
+
37
+ When you are done, you can start maestrano-izing your user and group model using the generators.
38
+
39
+ ### User model
40
+ Assuming your user model is called 'User' you can run the following generator to prepare this model for single sign-on:
41
+
42
+ ```console
43
+ rails generate maestrano:user User
44
+ ```
45
+
46
+ This generator will create a migration adding a :provider and :uid field to your user model. If you are already using multi-auth strategies (using [omniauth](https://github.com/intridea/omniauth) for example) then you can just ignore and delete this migration.
47
+
48
+ Run the migration with:
49
+ ```console
50
+ bundle exec rake db:migrate
51
+ ```
52
+
53
+ This generator also adds a configuration block to your user model which looks like this:
54
+ ```ruby
55
+ class User < ActiveRecord::Base
56
+ # Enable Maestrano for this user
57
+ maestrano_user_via :provider, :uid do |user,maestrano|
58
+ user.name = maestrano.first_name
59
+ user.surname = maestrano.last_name
60
+ user.email = maestrano.email
61
+ #user.company = maestrano.company_name
62
+ #user.country_alpha2 = maestrano.country
63
+ #user.some_required_field = 'some-appropriate-default-value'
64
+ end
65
+
66
+ ...
67
+
68
+ end
69
+ ```
70
+
71
+ This block is used to create a mapping between your user model fields and the attributes provided by Maestrano during the single sign-on handshake.
72
+
73
+ ### Group model
74
+ Because Maestrano works with businesses it expects your service to be able to manage groups of users. A group represents 1) a billing entity 2) a collaboration group. During the first single sign-on handshake both a user and a group should be created. Additional users logging in via the same group should then be added to this existing group (see controller setup below)
75
+
76
+ Assuming your group model is called 'Organization' you can run the following generator to prepare this model for single sign-on:
77
+
78
+ ```console
79
+ rails generate maestrano:group Organization
80
+ ```
81
+
82
+ This generator will create a migration adding a :provider and :uid field to your group model.
83
+
84
+ Run the migration with:
85
+ ```console
86
+ bundle exec rake db:migrate
87
+ ```
88
+
89
+ This generator also adds a configuration block to your group model which looks like this:
90
+
91
+ ```ruby
92
+ class Organization < ActiveRecord::Base
93
+ maestrano_group_via :provider, :uid do |group,maestrano|
94
+ group.name = maestrano.company_name || "Your Group"
95
+ end
96
+
97
+ ...
98
+
99
+ end
100
+ ```
101
+
102
+ ### Controller setup
103
+ The last step of integrating single sign-on with Maestrano is to customize the consume action of the SamlController. This action represents the last step of single sign-on handshake and should handle user finding/creation, group finding/creation, user-group relationship and finally user sign in.
104
+
105
+ The controller is located here: app/controllers/maestrano/auth/saml_controller.rb
106
+
107
+ The sample belows shows one possible way of writing this controller action:
108
+
109
+ ```ruby
110
+ class Maestrano::Auth::SamlController < Maestrano::Rails::SamlBaseController
111
+
112
+ #== POST '/maestrano/auth/saml/consume'
113
+ # -
114
+ # Assuming you have enabled maestrano on a user model
115
+ # called 'User' and a group model called 'Organization'
116
+ # the action could be written the following way
117
+ def consume
118
+ # 1)Find or create the user and the group
119
+ # --
120
+ # The class method 'find_or_create_for_maestrano' is provided
121
+ # by the maestrano-rails gem on the model you have maestrano-ized.
122
+ # The method uses the mapping defined in the model 'maestrano_*_via'
123
+ # block to create the resource if it does not exist
124
+ # The 'user_auth_hash' and 'group_auth_hash' methods are provided
125
+ # by the controller.
126
+ # --
127
+ user = User.find_or_create_for_maestrano(user_auth_hash)
128
+ organization = Organization.find_or_create_for_maestrano(group_auth_hash)
129
+
130
+
131
+ # 2) Add the user to the group if not already a member
132
+ # --
133
+ # The 'user_group_rel_hash' method is provided by the controller.
134
+ # The role attribute provided by maestrano is one of the following:
135
+ # 'Member', 'Power User', 'Admin', 'Super Admin'
136
+ # The 'member_of?' and 'add_member' methods are not provided by
137
+ # maestrano and are left to you to implement on your models
138
+ # --
139
+ unless user.member_of?(organization)
140
+ organization.add_member(user,role: user_group_rel_hash[:role])
141
+ end
142
+
143
+
144
+ # Sign the user in and redirect to application root
145
+ # --
146
+ # The 'sign_in' method is not provided by maestrano but should already
147
+ # be there if you are using an authentication framework like Devise
148
+ # --
149
+ sign_in(user)
150
+ redirect_to root_path
151
+ end
152
+ end
153
+ ```
154
+
155
+ ## Support
156
+ This README is still in the process of being written and improved. As such it might not cover some of the questions you might have.
157
+
158
+ So if you have any question or need help integrating with us just let us know at support@maestrano.com
159
+
160
+ ## License
161
+
162
+ MIT License. Copyright 2014 Maestrano Pty Ltd. https://maestrano.com
163
+
164
+ You are not granted rights or licenses to the trademarks of Maestrano.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
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 = 'Maestrano-rails'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,39 @@
1
+ class Maestrano::Rails::SamlBaseController < ApplicationController
2
+ attr_reader :saml_response, :user_auth_hash, :group_auth_hash, :user_group_rel_hash
3
+ around_filter :saml_response_transaction, only: [:consume]
4
+
5
+ # Initialize the SAML request and redirects the
6
+ # user to Maestrano
7
+ def init
8
+ redirect_to Maestrano::Saml::Request.new(params,session).redirect_url
9
+ end
10
+
11
+ #===================================
12
+ # Helper methods
13
+ #===================================
14
+ def saml_response_transaction
15
+ begin
16
+ process_saml_response
17
+ yield
18
+ Maestrano::SSO.set_session(session,@user_auth_hash)
19
+ rescue Exception => e
20
+ logger.error e
21
+ redirect_to "#{Maestrano::SSO.unauthorized_url}?err=internal"
22
+ end
23
+ end
24
+
25
+ def process_saml_response
26
+ if params[:SAMLResponse]
27
+ @saml_response = Maestrano::Saml::Response.new(params[:SAMLResponse])
28
+ if @saml_response.validate!
29
+ @user_auth_hash = Maestrano::SSO::BaseUser.new(@saml_response).to_hash
30
+ @group_auth_hash = Maestrano::SSO::BaseGroup.new(@saml_response).to_hash
31
+ @user_group_rel_hash = {
32
+ user_uid: @saml_response.attributes['uid'],
33
+ group_uid: @saml_response.attributes['group_uid'],
34
+ role: @saml_response.attributes['group_role']
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ require 'rails/generators/active_record'
2
+ require 'generators/maestrano/orm_helpers'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class MaestranoGroupGenerator < ActiveRecord::Generators::Base
7
+ include Maestrano::Generators::OrmHelpers
8
+ source_root File.expand_path("../templates", __FILE__)
9
+
10
+ def copy_maestrano_migration
11
+ migration_template "migration.rb", "db/migrate/add_maestrano_to_#{table_name}.rb"
12
+ end
13
+
14
+ def inject_maestrano_content
15
+ content = model_contents
16
+
17
+ class_path = if namespaced?
18
+ class_name.to_s.split("::")
19
+ else
20
+ [class_name]
21
+ end
22
+
23
+ indent_depth = class_path.size - 1
24
+ content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
25
+
26
+ inject_into_class(model_path, class_path.last, content) if model_exists?
27
+ end
28
+
29
+ def migration_data
30
+ <<RUBY
31
+ ## User source identification fields
32
+ t.string :provider
33
+ t.string :uid
34
+ RUBY
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ require 'rails/generators/active_record'
2
+ require 'generators/maestrano/orm_helpers'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class MaestranoUserGenerator < ActiveRecord::Generators::Base
7
+ include Maestrano::Generators::OrmHelpers
8
+ source_root File.expand_path("../templates", __FILE__)
9
+
10
+ def copy_maestrano_migration
11
+ migration_template "migration.rb", "db/migrate/add_maestrano_to_#{table_name}.rb"
12
+ end
13
+
14
+ def inject_maestrano_content
15
+ content = model_contents
16
+
17
+ class_path = if namespaced?
18
+ class_name.to_s.split("::")
19
+ else
20
+ [class_name]
21
+ end
22
+
23
+ indent_depth = class_path.size - 1
24
+ content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
25
+
26
+ inject_into_class(model_path, class_path.last, content) if model_exists?
27
+ end
28
+
29
+ def migration_data
30
+ <<RUBY
31
+ ## User source identification fields
32
+ t.string :provider
33
+ t.string :uid
34
+ RUBY
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ class AddMaestranoTo<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def self.up
3
+ change_table(:<%= table_name %>) do |t|
4
+ <%= migration_data -%>
5
+ end
6
+
7
+ def self.down
8
+ # By default, we don't want to make any assumption about how to roll back this migration.
9
+ # Please edit below which fields you would like to remove in this migration.
10
+ raise ActiveRecord::IrreversibleMigration
11
+ end
12
+ end
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Generates all files required to get your rails app setup with maestrano
@@ -0,0 +1,11 @@
1
+ module Maestrano
2
+ module Generators
3
+ class GroupGenerator < ::Rails::Generators::NamedBase
4
+ include ::Rails::Generators::ResourceHelpers
5
+
6
+ source_root File.expand_path("../templates", __FILE__)
7
+ desc "Configure group model <NAME> for maestrano and create migration"
8
+ hook_for :orm, as: :maestrano_group
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ module Maestrano
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+ desc "Creates a Maestrano initializer and a customizable controller for SAML Single Sign-On"
6
+
7
+ def copy_initializer
8
+ template "maestrano.rb", "config/initializers/maestrano.rb"
9
+ end
10
+
11
+ def copy_saml_controller
12
+ template "saml_controller.rb", "app/controllers/maestrano/auth/saml_controller.rb"
13
+ end
14
+
15
+ def add_maestrano_routes
16
+ maestrano_routes = <<-CONTENT
17
+ namespace :maestrano do
18
+ namespace :auth do
19
+ resources :saml, only:[] do
20
+ get 'init', on: :collection
21
+ post 'consume', on: :collection
22
+ end
23
+ end
24
+ end
25
+ CONTENT
26
+ route maestrano_routes
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,75 @@
1
+ module Maestrano
2
+ module Generators
3
+ module OrmHelpers
4
+
5
+ def model_contents
6
+
7
+ if model_type == 'user'
8
+ buffer = <<-CONTENT
9
+ # Enable Maestrano for this user
10
+ maestrano_user_via :provider, :uid do |user,maestrano|
11
+ user.name = maestrano.first_name
12
+ user.surname = maestrano.last_name
13
+ user.email = maestrano.email
14
+ #user.company = maestrano.company_name
15
+ #user.country_alpha2 = maestrano.country
16
+ #user.some_required_field = 'some-appropriate-default-value'
17
+ end
18
+
19
+ CONTENT
20
+ else
21
+ buffer = <<-CONTENT
22
+ # Enable Maestrano for this group
23
+ maestrano_group_via :provider, :uid do |group, maestrano|
24
+ group.name = (maestrano.company_name || "Default Group name")
25
+ #group.country_alpha2 = maestrano.country
26
+ #group.free_trial_end_at = maestrano.free_trial_end_at
27
+ #group.some_required_field = 'some-appropriate-default-value'
28
+ end
29
+
30
+ CONTENT
31
+ end
32
+
33
+ buffer += <<-CONTENT if needs_attr_accessible?
34
+ # Setup protected attributes for your model
35
+ attr_protected :provider, :uid
36
+
37
+ CONTENT
38
+ buffer
39
+ end
40
+
41
+ def model_type
42
+ self.class.name.split("::").last.gsub("Maestrano","").gsub("Generator","").downcase
43
+ end
44
+
45
+ def needs_attr_accessible?
46
+ rails_3? && !strong_parameters_enabled?
47
+ end
48
+
49
+ def rails_3?
50
+ ::Rails::VERSION::MAJOR == 3
51
+ end
52
+
53
+ def strong_parameters_enabled?
54
+ defined?(ActionController::StrongParameters)
55
+ end
56
+
57
+ private
58
+ def model_exists?
59
+ File.exists?(File.join(destination_root, model_path))
60
+ end
61
+
62
+ def migration_exists?(table_name)
63
+ Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_maestrano_to_#{table_name}.rb$/).first
64
+ end
65
+
66
+ def migration_path
67
+ @migration_path ||= File.join("db", "migrate")
68
+ end
69
+
70
+ def model_path
71
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,84 @@
1
+ # Use this block to configure the behaviour of Maestrano
2
+ # in your app
3
+ Maestrano.configure do |config|
4
+
5
+ # ==> Environment configuration
6
+ # The environment to connect to.
7
+ # If set to 'production' then all Single Sign-On (SSO) and API requests
8
+ # will be made to maestrano.com
9
+ # If set to 'test' then requests will be made to api-sandbox.maestrano.io
10
+ # The api-sandbox allows you to easily test integration scenarios.
11
+ # More details on http://api-sandbox.maestrano.io
12
+ config.environment = Rails.env.production? ? 'production' : 'test'
13
+
14
+ # ==> API key
15
+ # Your application API key which you can retrieve on http://maestrano.com
16
+ # via your cloud partner dashboard.
17
+ # For testing you can retrieve/generate an api_key from the API Sandbox directly
18
+ # on http://api-sandbox.maestrano.io
19
+ config.api_key = Rails.env.production? ? 'prod_api_key' : 'sandbox_api_key'
20
+
21
+ # ==> Single Sign-On activation
22
+ # Enable/Disable single sign-on. When troubleshooting authentication issues
23
+ # you might want to disable SSO temporarily
24
+ config.sso_enabled = true
25
+
26
+ # ==> Application host
27
+ # This is your application host (e.g: mysuperapp.com) which is ultimately
28
+ # used to redirect users to the right SAML url during SSO handshake.
29
+ config.app_host = Rails.env.production? ? 'https://my-production-app.com' : 'http://localhost::3000'
30
+
31
+ # ==> SSO Initialization endpoint
32
+ # This is your application path to the SAML endpoint that allows users to
33
+ # initialize SSO authentication. Upon reaching this endpoint users your
34
+ # application will automatically create a SAML request and redirect the user
35
+ # to Maestrano. Maestrano will then authenticate and authorize the user. Upon
36
+ # authorization the user gets redirected to your application consumer endpoint
37
+ # (see below) for initial setup and/or login.
38
+ # The controller for this path is automatically
39
+ # generated when you run 'rake maestrano:install' and is available at
40
+ # <rails_root>/app/controllers/maestrano/auth/saml.rb
41
+ config.sso_app_init_path = '/maestrano/auth/saml/init'
42
+
43
+ # ==> SSO Consumer endpoint
44
+ # This is your application path to the SAML endpoint that allows users to
45
+ # finalize SSO authentication. During the 'consume' action your application
46
+ # sets users (and associated group) up and/or log them in.
47
+ # The controller for this path is automatically
48
+ # generated when you run 'rake maestrano:install' and is available at
49
+ # <rails_root>/app/controllers/maestrano/auth/saml.rb
50
+ config.sso_app_consume_path = '/maestrano/auth/saml/consume'
51
+
52
+ # ==> SSO User creation mode
53
+ # !IMPORTANT
54
+ # On Maestrano users can take several "instances" of your service. You can consider
55
+ # each "instance" as 1) a billing entity and 2) a collaboration group (this is
56
+ # equivalent to a 'customer account' in a commercial world). When users login to
57
+ # your application via single sign-on they actually login via a specific group which
58
+ # is then supposed to determine which data they have access to inside your application.
59
+ #
60
+ # E.g: John and Jack are part of group 1. They should see the same data when they login to
61
+ # your application (employee info, analytics, sales etc..). John is also part of group 2
62
+ # but not Jack. Therefore only John should be able to see the data belonging to group 2.
63
+ #
64
+ # In most application this is done via collaboration/sharing/permission groups which is
65
+ # why a group is required to be created when a new user logs in via a new group (and
66
+ # also for billing purpose - you charge a group, not a user directly).
67
+ #
68
+ # == mode: 'real'
69
+ # In an ideal world a user should be able to belong to several groups in your application.
70
+ # In this case you would set the 'user_creation_mode' to 'real' which means that the uid
71
+ # and email we pass to you are the actual user email and maestrano universal id.
72
+ #
73
+ # == mode: 'virtual'
74
+ # Now let's say that due to technical constraint your application cannot authorize a user
75
+ # to belong to several groups. Well next time John logs in via a different group there will
76
+ # be a problem: the user already exists (based on uid or email) and cannot be assigned
77
+ # to a second group. To fix this you can set the 'user_creation_mode' to 'virtual'. In this
78
+ # mode users get assigned a truly unique uid and email across groups. So next time John logs
79
+ # in a whole new user account can be created for him without any validation problem. In this
80
+ # mode the email we assign to him looks like "usr-sdf54.cld-45aa2@mail.maestrano.com". But don't
81
+ # worry we take care of forwarding any email you would send to this address
82
+ #
83
+ config.user_creation_mode = 'virtual' # or 'real'
84
+ end
@@ -0,0 +1,52 @@
1
+ class Maestrano::Auth::SamlController < Maestrano::Rails::SamlBaseController
2
+
3
+ #== POST '/maestrano/auth/saml/consume'
4
+ # Final phase of the Single Sign-On handshake. Find or create
5
+ # the required resources (user and group) and sign the user
6
+ # in
7
+ #
8
+ # This action is left to you to customize based on your application
9
+ # requirements. Below is presented a potential way of writing
10
+ # the action.
11
+ #
12
+ # Assuming you have enabled maestrano on a user model
13
+ # called 'User' and a group model called 'Organization'
14
+ # the action could be written the following way
15
+ def consume
16
+ ### 1)Find or create the user and the group
17
+ ### --
18
+ ### The class method 'find_or_create_for_maestrano' is provided
19
+ ### by the maestrano-rails gem on the model you have maestrano-ized.
20
+ ### The method uses the mapping defined in the model 'maestrano_*_via'
21
+ ### block to create the resource if it does not exist
22
+ ### The 'user_auth_hash' and 'group_auth_hash' methods are provided
23
+ ### by the controller.
24
+ ### --
25
+ # user = User.find_or_create_for_maestrano(user_auth_hash)
26
+ # organization = Organization.find_or_create_for_maestrano(group_auth_hash)
27
+ #
28
+ #
29
+ ### 2) Add the user to the group if not already a member
30
+ ### --
31
+ ### The 'user_group_rel_hash' method is provided by the controller.
32
+ ### The role attribute provided by maestrano is one of the following:
33
+ ### 'Member', 'Power User', 'Admin', 'Super Admin'
34
+ ### The 'member_of?' and 'add_member' methods are not provided by
35
+ ### maestrano and are left to you to implement on your models
36
+ ### --
37
+ # unless user.member_of?(organization)
38
+ # organization.add_member(user,role: user_group_rel_hash[:role])
39
+ # end
40
+ #
41
+ #
42
+ ### Sign the user in and redirect to application root
43
+ ### --
44
+ ### The 'sign_in' method is not provided by maestrano but should already
45
+ ### be there if you are using an authentication framework like Devise
46
+ ### --
47
+ # sign_in(user)
48
+ # redirect_to root_path
49
+
50
+ raise NotImplemented.new("The consume action should be customized to fit your application needs")
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ module Maestrano
2
+ module Generators
3
+ class UserGenerator < ::Rails::Generators::NamedBase
4
+ include ::Rails::Generators::ResourceHelpers
5
+
6
+ source_root File.expand_path("../templates", __FILE__)
7
+ desc "Configure user model <NAME> for maestrano and create migration"
8
+ hook_for :orm, as: :maestrano_user
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ require 'rails/generators/named_base'
2
+ require 'generators/maestrano/orm_helpers'
3
+
4
+ module Mongoid
5
+ module Generators
6
+ class MaestranoGroupGenerator < Rails::Generators::NamedBase
7
+ include Maestrano::Generators::OrmHelpers
8
+
9
+ def inject_field_types
10
+ inject_into_file model_path, migration_data, after: "include Mongoid::Document\n" if model_exists?
11
+ end
12
+
13
+ def inject_maestrano_content
14
+ inject_into_file model_path, model_contents, after: "include Mongoid::Document\n" if model_exists?
15
+ end
16
+
17
+ def migration_data
18
+ <<RUBY
19
+ ## User source identification fields
20
+ field :provider, type: String, default: ""
21
+ field :uid, type: String, default: ""
22
+ RUBY
23
+ end
24
+ end
25
+ end
26
+ end