portier 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +7 -0
  6. data/README.md +171 -0
  7. data/Rakefile +11 -0
  8. data/lib/portier/.reek +12 -0
  9. data/lib/portier/application_permission.rb +89 -0
  10. data/lib/portier/base.rb +75 -0
  11. data/lib/portier/base_permission.rb +36 -0
  12. data/lib/portier/engine.rb +7 -0
  13. data/lib/portier/errors.rb +19 -0
  14. data/lib/portier/implants/action_controller_implant.rb +37 -0
  15. data/lib/portier/railtie.rb +14 -0
  16. data/lib/portier/view_tags_permission.rb +14 -0
  17. data/lib/portier.rb +12 -0
  18. data/portier.gemspec +22 -0
  19. data/spec/controllers/application_controller_spec.rb +81 -0
  20. data/spec/dummy/Rakefile +6 -0
  21. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  22. data/spec/dummy/app/controllers/examples_controller.rb +11 -0
  23. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  24. data/spec/dummy/app/models/anonymou.rb +19 -0
  25. data/spec/dummy/app/permissions/anonymous_permission.rb +25 -0
  26. data/spec/dummy/app/permissions/products_permission.rb +9 -0
  27. data/spec/dummy/app/permissions/view_tags_permission.rb +5 -0
  28. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  29. data/spec/dummy/bin/bundle +3 -0
  30. data/spec/dummy/bin/rails +4 -0
  31. data/spec/dummy/bin/rake +4 -0
  32. data/spec/dummy/config/application.rb +18 -0
  33. data/spec/dummy/config/boot.rb +5 -0
  34. data/spec/dummy/config/database.yml +5 -0
  35. data/spec/dummy/config/environment.rb +5 -0
  36. data/spec/dummy/config/environments/development.rb +29 -0
  37. data/spec/dummy/config/environments/production.rb +80 -0
  38. data/spec/dummy/config/environments/test.rb +36 -0
  39. data/spec/dummy/config/initializers/standard_rails_initializers.rb +9 -0
  40. data/spec/dummy/config/routes.rb +3 -0
  41. data/spec/dummy/config.ru +4 -0
  42. data/spec/dummy/db/test.sqlite3 +0 -0
  43. data/spec/portier/application_permission_spec.rb +23 -0
  44. data/spec/portier/base_permission_spec.rb +4 -0
  45. data/spec/portier/base_spec.rb +28 -0
  46. data/spec/portier/view_tags_permission_spec.rb +31 -0
  47. data/spec/portier_spec.rb +4 -0
  48. data/spec/spec_helper.rb +26 -0
  49. data/spec/support/views_helper.rb +12 -0
  50. metadata +197 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c33d0423d1f9c49d68a3334e45a97174fcb13ab6
4
+ data.tar.gz: 5e359491e90f1d8cf608f5fd1caf589744f52ddc
5
+ SHA512:
6
+ metadata.gz: c1b7cb91f5b65f7fc17b2f1c68070cf865a4a58aae84c4080418bc484922146f8b03802f4b17a6083fa6a11f26a23d15b5e82f4d8122856fa8d068b4c1ea289c
7
+ data.tar.gz: 785f54d140c86965f58e90fd417cd5b56ea34f033f488f210d84733de1a79b17b049a02b8de7173e87f9fd6a5b28a03a2b07a5468149666bed0a695437e85c9e
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ .metrics
4
+ .rspec
5
+ Gemfile.lock
6
+ coverage/*
7
+ pkg/*
8
+ spec/dummy/log
9
+ tmp/*
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - 1.9.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in portier.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2014 Alchimik
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,171 @@
1
+ Portier
2
+ =======
3
+
4
+ Portier is an gem that manage permissions in a rails project. The permission rules are flexible, non-obstrusive, scalable and can be applied to the controller actions, and views.
5
+
6
+ Install
7
+ -------
8
+
9
+ In your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'portier'
13
+ ```
14
+
15
+ Authorizing the controller requests
16
+ -----------------------------------
17
+
18
+ ### Bootstrap Portier
19
+
20
+ In order to let portier control the requests to your application, you need to add the before_filter below in your application_controller.rb. You also need to define a current_user method
21
+
22
+ ```ruby
23
+ # app/controllers/application_controller.rb
24
+
25
+ class ApplicationController < ActionController::Base
26
+ protect_from_forgery with: :exception
27
+
28
+ # This filter the requests using the permission files
29
+ before_filter :protect_app
30
+
31
+ # You can define the current_user anyway you want as long as it return the current user record.
32
+ def current_user
33
+ # This is only an example of current_user method. Feel free to do it the way you want.
34
+ begin
35
+ @current_user ||= User.find session[:current_user]
36
+ rescue
37
+ @current_user = nil
38
+ end
39
+ end
40
+ ...
41
+ ```
42
+
43
+ ### The Permission Files
44
+
45
+ Once this is done, every controller will have to be match with a permission file. So, for the ```products_controller.rb``` you'll have to create the file ```app/permissions/products_permission.rb```.
46
+
47
+
48
+ ### Describing a permission file
49
+
50
+ The permission file will define the access rules to every action called on the controller.
51
+
52
+ ```ruby
53
+ # app/permissions/products_permission.rb
54
+
55
+ class ProductsPermission < Portier::ApplicationPermission
56
+ # User will have access to any undescribed actions
57
+ def default
58
+ true
59
+ end
60
+
61
+ # The access will only granted if the product is available.
62
+ # product is provided by ApplicationPermission.
63
+ # product return the current product record
64
+ def show
65
+ product.available?
66
+ end
67
+
68
+ # You can set a custom error message with the method set_access_denied_message.
69
+ # This message will be available in the controllers and views throught the
70
+ # method access_denied_message. If it's not set, this method will return nil.
71
+ # set_access_denied_message always return false.
72
+ def create
73
+ if not current_user
74
+ set_access_denied_message "You need to log in to create this product."
75
+ elsif not current_user.can_create_product?
76
+ set_access_denied_message "You don't have the right to create product."
77
+ else
78
+ true
79
+ end
80
+ end
81
+
82
+ # The access to the edit/update actions will only be available
83
+ # if the current user is and Administrator
84
+ # The current_user method must be defined in your ApplicationController
85
+ def modify
86
+ current_user and current_user.admin?
87
+ end
88
+
89
+ # Revoke access to the destroy action.
90
+ def destroy
91
+ false
92
+ end
93
+ end
94
+
95
+ # consult = index and show
96
+ # add = new and create
97
+ # modify = edit and update
98
+
99
+ # Define the parameters that can be sent by the user.
100
+ # In your products_controller, you can call the method permitted_params.
101
+ # This method will be the equivalent of :
102
+ # params.require(:product).permit(:picture, :name, :description)
103
+ def permitted_params
104
+ if current_user and current_user.employe?
105
+ [:picture, :name, :description]
106
+ elsif current_user and current_user.admin?
107
+ [:picture, :name, :description, :price]
108
+ else
109
+ []
110
+ end
111
+ end
112
+ ```
113
+
114
+ ### The View Tags
115
+
116
+ In order to filter content in the views, you can add tags in the special view_tags_permission.rb.
117
+
118
+ ```ruby
119
+ # app/permissions/view_tags_permission.rb
120
+
121
+ class ViewTagsPermission < Portier::ViewTagsPermission
122
+ # Only accept this tag if the user is an administrator
123
+ def show_the_admin_link
124
+ current_user.admin?
125
+ end
126
+ end
127
+ ```
128
+
129
+ In your views, you can then use the can_view? method to filter content.
130
+
131
+ ```erb
132
+ <%# app/views/products/show.html.erb %>
133
+
134
+ <%= link_to 'Admin', admin_path if can_view? :show_the_admin_link %>
135
+ ```
136
+
137
+ ### can?
138
+
139
+ In your views, you can also use the method ```can?``` to filter content.
140
+
141
+ ```erb
142
+ <%# app/views/products/show.html.erb %>
143
+
144
+ <%= link_to 'Edit product', edit_product_path(id: @product.id) if can? :edit, @product %>
145
+ ```
146
+
147
+ Both ```can?``` and ```can_view?``` methods can take options
148
+
149
+ ```erb
150
+ <%# app/views/products/show.html.erb %>
151
+
152
+ <%= link_to 'Admin', admin_path if can_view? :show_the_admin_link, special: true %>
153
+ ```
154
+
155
+ ```ruby
156
+ # app/permissions/view_tags_permission.rb
157
+
158
+ class ViewTagsPermission < Portier::ViewTagsPermission
159
+ # Only accept this tag if the user is a special administrator
160
+ def show_the_admin_link
161
+ current_user.admin? and options[:special]
162
+ end
163
+ end
164
+ ```
165
+
166
+
167
+
168
+ Copyright
169
+ ---------
170
+
171
+ Copyright (c) 2014 Alchimik. See LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ require "rspec/core/rake_task"
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ desc "Run all specs in spec directory"
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = "spec/**/*_spec.rb"
9
+ end
10
+
11
+ task default: :spec
data/lib/portier/.reek ADDED
@@ -0,0 +1,12 @@
1
+ ---
2
+ DuplicateMethodCall:
3
+ allow_calls: ['options', 'params']
4
+ max_calls: 3
5
+ IrresponsibleModule:
6
+ enabled: false
7
+ TooManyStatements:
8
+ max_statements: 10
9
+ UncommunicativeMethodName:
10
+ enabled: false
11
+ UncommunicativeVariableName:
12
+ enabled: false
@@ -0,0 +1,89 @@
1
+ #*************************************************************************************
2
+ # Control the access for each controller actions
3
+ #*************************************************************************************
4
+ class Portier::ApplicationPermission < Portier::BasePermission
5
+ def self.action_tree(action)
6
+ case action.to_s
7
+ when 'index' then [:index, :consult, :default]
8
+ when 'show' then [:show, :consult, :default]
9
+ when 'new' then [:new, :add, :default]
10
+ when 'create' then [:create, :add, :default]
11
+ when 'edit' then [:edit, :modify, :default]
12
+ when 'update' then [:update, :modify, :default]
13
+ when 'destroy' then [:destroy, :default]
14
+ else [action.to_sym, :default]
15
+ end
16
+ end
17
+
18
+
19
+ def build_permitted_params
20
+ ps = self.respond_to?(:permitted_params) ? permitted_params : []
21
+
22
+ begin
23
+ params.require(record_name).permit ps
24
+ rescue
25
+ {}
26
+ end
27
+ end
28
+
29
+ def can?(action, record, options={})
30
+ @current_record = record
31
+ @options = options
32
+
33
+ granted? action
34
+ end
35
+
36
+ def default
37
+ false
38
+ end
39
+
40
+ def granted?(action)
41
+ action_tree(action).each { |act| return self.send(act) if self.respond_to?(act) }
42
+ end
43
+
44
+
45
+ private
46
+
47
+ def action_tree(action)
48
+ Portier::ApplicationPermission.action_tree(action)
49
+ end
50
+
51
+ def current_record
52
+ @current_record = find_record if not @current_record
53
+
54
+ @current_record
55
+ end
56
+
57
+ def find_record
58
+ if params[:id]
59
+ field = model.respond_to?(:default_id) ? model.default_id : :id
60
+
61
+ model.find_by Hash[field, params[:id]]
62
+ else
63
+ nil
64
+ end
65
+ end
66
+
67
+ def model
68
+ controller_name.singularize.camelize.constantize
69
+ end
70
+
71
+ def model_exists?
72
+ defined? model
73
+ end
74
+
75
+ def record_name
76
+ controller_name.singularize.to_sym
77
+ end
78
+
79
+
80
+ def method_missing(*args, &block)
81
+ if args.first == record_name and model_exists?
82
+ current_record
83
+ elsif current_record.class.to_s.downcase == args.first.to_s
84
+ current_record
85
+ else
86
+ raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,75 @@
1
+ #*************************************************************************************
2
+ # Check if the access is granted or refused depending on the permission
3
+ # setted in the permission files.
4
+ #*************************************************************************************
5
+ class Portier::Base
6
+ attr_reader :application_controller, :current_user
7
+
8
+ delegate :request, to: :application_controller
9
+
10
+ def initialize(application_controller, current_user)
11
+ @application_controller = application_controller
12
+ @current_user = current_user
13
+ end
14
+
15
+ def access_denied_message
16
+ base_permission.access_denied_message
17
+ end
18
+
19
+ def authorize_action
20
+ raise Portier::AccessDenied if not base_permission.granted? action
21
+ end
22
+
23
+ def can?(action, object, options={})
24
+ object_name = if object.is_a? Symbol or object.is_a? String
25
+ object.to_s.singularize.pluralize
26
+ else
27
+ object.class.name.pluralize
28
+ end
29
+ permission = permission_for object_name
30
+ permission.can? action, object, options
31
+ end
32
+
33
+ def can_view?(tag, options={})
34
+ view_permission.can_view? tag, options
35
+ end
36
+
37
+ def permitted_params
38
+ base_permission.build_permitted_params if base_permission.respond_to? :permitted_params
39
+ end
40
+
41
+ private
42
+
43
+ def action
44
+ request[:action]
45
+ end
46
+
47
+ def base_permission
48
+ @base_permission ||= permission_for controller_name
49
+ end
50
+
51
+ def controller_name
52
+ request[:controller]
53
+ end
54
+
55
+ def permission_for(target)
56
+ begin
57
+ "#{target.camelize}Permission".constantize.new(application_controller, current_user)
58
+ rescue
59
+ raise Portier::Uninitalized, "You must define #{controller_name.camelize}Permission in app/permissions/#{controller_name}_permission.rb. See documentation for more details."
60
+ end
61
+ end
62
+
63
+ def view_permission
64
+ if not @view_permission_object
65
+ begin
66
+ @view_permission_object = "ViewTagsPermission".constantize.new(application_controller, current_user)
67
+ rescue
68
+ raise Portier::Uninitalized, "You must define ViewTagsPermission in app/permissions/view_tags_permission.rb in order to use view permission. See documentation for more details."
69
+ end
70
+ end
71
+
72
+ @view_permission_object
73
+ end
74
+
75
+ end
@@ -0,0 +1,36 @@
1
+ #*************************************************************************************
2
+ # Basic Permission object to cut some duplication.
3
+ # ApplicationPermission and ViewTagsPermission inherit from it
4
+ #*************************************************************************************
5
+ class Portier::BasePermission
6
+ attr_reader :access_denied_message, :application_controller, :current_user
7
+
8
+ delegate :params, to: :application_controller
9
+ delegate :request, to: :application_controller
10
+
11
+ def initialize(application_controller, current_user)
12
+ @application_controller = application_controller
13
+ @current_user = current_user
14
+ @access_denied_message = nil
15
+ end
16
+
17
+ def set_access_denied_message(message)
18
+ @access_denied_message = message
19
+
20
+ false
21
+ end
22
+
23
+ private
24
+
25
+ def controller
26
+ @application_controller
27
+ end
28
+
29
+ def controller_name
30
+ request[:controller]
31
+ end
32
+
33
+ def options
34
+ @options
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module Portier
2
+ #*************************************************************************************
3
+ # Make the gem behave as an engine.
4
+ #*************************************************************************************
5
+ class Engine < Rails::Engine
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ module Portier
2
+ #*************************************************************************************
3
+ # Error that will be raised if access to the action is denied
4
+ #*************************************************************************************
5
+ class AccessDenied < StandardError
6
+ end
7
+
8
+ #*************************************************************************************
9
+ # Error that will be raised if the permission wasn't defined
10
+ #*************************************************************************************
11
+ class NoPermissionError < StandardError
12
+ end
13
+
14
+ #*************************************************************************************
15
+ # Error that will be raised if the permission isn't initialized
16
+ #*************************************************************************************
17
+ class Uninitalized < StandardError
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ #*************************************************************************************
2
+ # Insert methods in the Action Controller of a Rails project.
3
+ #*************************************************************************************
4
+ module Portier::Implants::ActionControllerImplant
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ helper_method :access_denied_message, :can?, :can_view?
9
+
10
+ rescue_from Portier::AccessDenied, with: :render_access_denied
11
+ end
12
+
13
+ def access_denied_message
14
+ @portier.access_denied_message
15
+ end
16
+
17
+ def can?(action, object, options={})
18
+ @portier.can? action, object, options
19
+ end
20
+
21
+ def can_view?(tag, options={})
22
+ @portier.can_view? tag, options
23
+ end
24
+
25
+ def permitted_params
26
+ @portier.permitted_params
27
+ end
28
+
29
+ def protect_app
30
+ @portier = Portier::Base.new(self, current_user)
31
+ @portier.authorize_action
32
+ end
33
+
34
+ def render_access_denied
35
+ render text: "access_denied", status: 401
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ module Portier
2
+ class Railtie < Rails::Railtie
3
+ initializer "portier" do |app|
4
+ ActiveSupport.on_load :action_controller do
5
+ include Portier::Implants::ActionControllerImplant
6
+ end
7
+ end
8
+ end
9
+
10
+ module Implants
11
+ end
12
+ end
13
+
14
+ require 'portier/implants/action_controller_implant'
@@ -0,0 +1,14 @@
1
+ #*************************************************************************************
2
+ # Control the access using a tag.
3
+ #*************************************************************************************
4
+ class Portier::ViewTagsPermission < Portier::BasePermission
5
+ def can_view?(tag, options={})
6
+ if self.respond_to? tag.to_sym
7
+ @options = options
8
+
9
+ self.send(tag.to_sym)
10
+ else
11
+ raise Portier::NoPermissionError, "You must define the method \"#{tag}\" in the view tags file (app/permissions/view_tags_permission.rb). See documentation for more details."
12
+ end
13
+ end
14
+ end
data/lib/portier.rb ADDED
@@ -0,0 +1,12 @@
1
+ module Portier
2
+ end
3
+
4
+ require "portier/engine"
5
+ require 'portier/base'
6
+ require 'portier/base_permission'
7
+ require 'portier/application_permission'
8
+ require 'portier/view_tags_permission'
9
+ require 'portier/errors'
10
+ require 'portier/railtie'
11
+
12
+
data/portier.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = "portier"
3
+ gem.description = "Portier is an gem that manage permissions in a rails project. The permission rules are flexible, non-obstrusive, scalable and can be applied to the controller actions, and views."
4
+ gem.summary = "Portier is an gem that manage permissions in a rails project. The permission rules are flexible, non-obstrusive, scalable and can be applied to the controller actions, and views."
5
+ gem.homepage = "https://bitbucket.org/alchimikweb/portier"
6
+ gem.version = "1.0.3"
7
+ gem.licenses = ["MIT"]
8
+
9
+ gem.authors = ["Sebastien Rosa"]
10
+ gem.email = ["sebastien@alchimik.com"]
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ["lib"]
16
+
17
+ gem.add_dependency "rails", ['>= 4.0']
18
+ gem.add_development_dependency "sqlite3"
19
+ gem.add_development_dependency "rspec-rails"
20
+ gem.add_development_dependency "simplecov"
21
+ gem.add_development_dependency "simplecov-rcov-text"
22
+ end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ describe ApplicationController do
4
+ controller do
5
+ before_filter :protect_app
6
+
7
+ def current_user
8
+ @user
9
+ end
10
+
11
+ def index
12
+ if can_view?(:granted_response, show: true)
13
+ render text: 'Granted!'
14
+ else
15
+ render text: 'Nothing'
16
+ end
17
+ end
18
+
19
+ def create
20
+ if can?(:create, :products)
21
+ render text: "Created! #{permitted_params}"
22
+ else
23
+ render text: "Not Created!"
24
+ end
25
+ end
26
+
27
+ def edit
28
+ render text: 'Refused!'
29
+ end
30
+
31
+ def destroy
32
+ render text: 'Destroyed!'
33
+ end
34
+ end
35
+
36
+ describe "when calling an open action" do
37
+ it 'should grant access' do
38
+ get :index
39
+
40
+ expect(response.status).to eq(200)
41
+ expect(response.body).to eq "Granted!"
42
+ end
43
+ end
44
+
45
+ describe "when calling a restricted action" do
46
+ it 'should not grant access' do
47
+ get :edit, id: '123'
48
+
49
+ expect(response.status).to eq(401)
50
+ expect(response.body).to eq "access_denied"
51
+ end
52
+ end
53
+
54
+ describe "when sending the role and the role is not allowed to be sent" do
55
+ it 'should not have role in the permitted_params' do
56
+ post :create, anonymou: { name: '123', email: 'a@at.com', role: 'admin' }
57
+
58
+ expect(response.status).to eq(200)
59
+ expect(response.body).to include('email')
60
+ expect(response.body).not_to include('role')
61
+ end
62
+ end
63
+
64
+ describe "when deleting an open record" do
65
+ it 'should grant access' do
66
+ delete :destroy, id: 'open'
67
+
68
+ expect(response.status).to eq(200)
69
+ expect(response.body).to eq "Destroyed!"
70
+ end
71
+ end
72
+
73
+ describe "when deleting an restricted record" do
74
+ it 'should not grant access' do
75
+ delete :destroy, id: 'restricted'
76
+
77
+ expect(response.status).to eq(401)
78
+ expect(response.body).to eq "access_denied"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery with: :exception
3
+ end
@@ -0,0 +1,11 @@
1
+ class ExamplesController < ApplicationController
2
+ protect_from_forgery
3
+
4
+ def index
5
+ render text: 'dummy'
6
+ end
7
+
8
+ def show
9
+ render text: 'dummy'
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end