simon_says 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitpublish +3 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +13 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +18 -0
  9. data/ROADMAP.md +9 -0
  10. data/Rakefile +24 -0
  11. data/SimonSays.png +0 -0
  12. data/lib/simon_says/authorizer.rb +157 -0
  13. data/lib/simon_says/roleable.rb +107 -0
  14. data/lib/simon_says/version.rb +3 -0
  15. data/lib/simon_says.rb +8 -0
  16. data/simon_says.gemspec +28 -0
  17. data/test/controllers/admin/reports_controller_test.rb +92 -0
  18. data/test/controllers/documents_controller_test.rb +87 -0
  19. data/test/models/admin_test.rb +7 -0
  20. data/test/models/membership_test.rb +7 -0
  21. data/test/rails_app/.gitignore +16 -0
  22. data/test/rails_app/README.rdoc +28 -0
  23. data/test/rails_app/Rakefile +6 -0
  24. data/test/rails_app/app/assets/images/.keep +0 -0
  25. data/test/rails_app/app/assets/javascripts/application.js +16 -0
  26. data/test/rails_app/app/assets/stylesheets/application.css +15 -0
  27. data/test/rails_app/app/controllers/admin/reports_controller.rb +40 -0
  28. data/test/rails_app/app/controllers/application_controller.rb +19 -0
  29. data/test/rails_app/app/controllers/concerns/.keep +0 -0
  30. data/test/rails_app/app/controllers/documents_controller.rb +48 -0
  31. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  32. data/test/rails_app/app/mailers/.keep +0 -0
  33. data/test/rails_app/app/models/.keep +0 -0
  34. data/test/rails_app/app/models/admin/report.rb +2 -0
  35. data/test/rails_app/app/models/admin.rb +5 -0
  36. data/test/rails_app/app/models/concerns/.keep +0 -0
  37. data/test/rails_app/app/models/document.rb +4 -0
  38. data/test/rails_app/app/models/membership.rb +8 -0
  39. data/test/rails_app/app/models/user.rb +4 -0
  40. data/test/rails_app/app/views/layouts/application.html.erb +14 -0
  41. data/test/rails_app/bin/bundle +3 -0
  42. data/test/rails_app/bin/rails +8 -0
  43. data/test/rails_app/bin/rake +8 -0
  44. data/test/rails_app/bin/spring +18 -0
  45. data/test/rails_app/config/application.rb +29 -0
  46. data/test/rails_app/config/boot.rb +4 -0
  47. data/test/rails_app/config/database.yml +25 -0
  48. data/test/rails_app/config/environment.rb +5 -0
  49. data/test/rails_app/config/environments/development.rb +37 -0
  50. data/test/rails_app/config/environments/production.rb +78 -0
  51. data/test/rails_app/config/environments/test.rb +39 -0
  52. data/test/rails_app/config/initializers/assets.rb +8 -0
  53. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  54. data/test/rails_app/config/initializers/cookies_serializer.rb +3 -0
  55. data/test/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  56. data/test/rails_app/config/initializers/inflections.rb +16 -0
  57. data/test/rails_app/config/initializers/mime_types.rb +4 -0
  58. data/test/rails_app/config/initializers/session_store.rb +3 -0
  59. data/test/rails_app/config/initializers/wrap_parameters.rb +14 -0
  60. data/test/rails_app/config/locales/en.yml +23 -0
  61. data/test/rails_app/config/routes.rb +7 -0
  62. data/test/rails_app/config/secrets.yml +22 -0
  63. data/test/rails_app/config.ru +4 -0
  64. data/test/rails_app/db/migrate/20141016142638_create_admins.rb +9 -0
  65. data/test/rails_app/db/migrate/20141016183619_create_users.rb +8 -0
  66. data/test/rails_app/db/migrate/20141016183633_create_memberships.rb +12 -0
  67. data/test/rails_app/db/migrate/20141016183642_create_documents.rb +9 -0
  68. data/test/rails_app/db/migrate/20141017140833_create_admin_reports.rb +9 -0
  69. data/test/rails_app/db/schema.rb +47 -0
  70. data/test/rails_app/db/seeds.rb +7 -0
  71. data/test/rails_app/lib/assets/.keep +0 -0
  72. data/test/rails_app/lib/tasks/.keep +0 -0
  73. data/test/rails_app/log/.keep +0 -0
  74. data/test/rails_app/public/404.html +67 -0
  75. data/test/rails_app/public/422.html +67 -0
  76. data/test/rails_app/public/500.html +66 -0
  77. data/test/rails_app/public/favicon.ico +0 -0
  78. data/test/rails_app/public/robots.txt +5 -0
  79. data/test/rails_app/test/controllers/.keep +0 -0
  80. data/test/rails_app/test/fixtures/.keep +0 -0
  81. data/test/rails_app/test/fixtures/admin/reports.yml +2 -0
  82. data/test/rails_app/test/fixtures/admins.yml +11 -0
  83. data/test/rails_app/test/fixtures/documents.yml +8 -0
  84. data/test/rails_app/test/fixtures/memberships.yml +10 -0
  85. data/test/rails_app/test/fixtures/users.yml +2 -0
  86. data/test/rails_app/test/helpers/.keep +0 -0
  87. data/test/rails_app/test/integration/.keep +0 -0
  88. data/test/rails_app/test/mailers/.keep +0 -0
  89. data/test/rails_app/test/models/.keep +0 -0
  90. data/test/rails_app/test/models/admin/report_test.rb +7 -0
  91. data/test/rails_app/test/models/document_test.rb +7 -0
  92. data/test/rails_app/test/models/membership_test.rb +7 -0
  93. data/test/rails_app/test/models/user_test.rb +7 -0
  94. data/test/rails_app/test/test_helper.rb +10 -0
  95. data/test/rails_app/vendor/assets/javascripts/.keep +0 -0
  96. data/test/rails_app/vendor/assets/stylesheets/.keep +0 -0
  97. data/test/simon_says/authorizer_test.rb +143 -0
  98. data/test/simon_says/roleable_test.rb +200 -0
  99. data/test/simon_says_test.rb +7 -0
  100. data/test/test_helper.rb +48 -0
  101. metadata +312 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8bea95d0e9c7c97c12f1f3dabcd8b419ed9f3e40
4
+ data.tar.gz: 6faef8c22e188dea0013ad8e41f425079c88284c
5
+ SHA512:
6
+ metadata.gz: e599afe61d51efe4e44d286e7fd5cb14954642e8af3855d115dd0aea3cf4eae12c8c316aa74dd322b45ea62ea689cb650c76e3448edbfe316bb6a2560e7ae510
7
+ data.tar.gz: db9ffc036f4cbcb123109214d60c97334d534f43202b614a777341baaf39a7d9bda35b00c4b116abee98d0c0bb6ef884bc45b9a2eda7a56aa36f100bde90848c
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /docs/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+
16
+ *.gem
17
+
18
+ /test/rails_app/db/*.sqlite3
data/.gitpublish ADDED
@@ -0,0 +1,3 @@
1
+ export_dir=docs/
2
+ remote=origin
3
+ branch=gh-pages
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.1.4"
4
+ before_script:
5
+ - cd test/rails_app/
6
+ - bundle exec rake db:migrate db:fixtures:load
7
+ - cd ../..
8
+ script:
9
+ - bundle exec rake test
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in auth_lib.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'sqlite3'
8
+
9
+ gem 'rdoc'
10
+
11
+ gem 'guard'
12
+ gem 'guard-minitest'
13
+ end
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :minitest do
5
+ # with Minitest::Unit
6
+ watch(%r{^test/(.*)\/?(.*)_test\.rb$})
7
+ watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
8
+ watch(%r{^test/test_helper\.rb$}) { 'test' }
9
+
10
+ # watch test Rails app
11
+ watch(%r{^test/rails_app/app/models/(.*)\.rb$}) { |m| "test/models/#{m[1]}_test.rb" }
12
+ watch(%r{^test/rails_app/app/controllers/(.*)\.rb$}) { |m| "test/controllers/#{m[1]}_test.rb" }
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Michael Coyne
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # SimonSays!
2
+
3
+ ![SimonSays
4
+ Logo](https://raw.githubusercontent.com/SimplyBuilt/SimonSays/master/SimonSays.png)
5
+
6
+ This gem is a simple, declarative, role-based access control system for Rails that
7
+ works great with devise! Take a look at the [website](http://simonsays.onsimplybuilt.com) or
8
+ [docs](http://www.rubydoc.info/github/SimplyBuilt/SimonSays/) for more details!
9
+
10
+ ![Build Status](https://travis-ci.org/SimplyBuilt/SimonSays.svg)
11
+
12
+ ## Contributing
13
+
14
+ 1. Fork it ( https://github.com/SimplyBuilt/SimonSays/fork )
15
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
16
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
17
+ 4. Push to the branch (`git push origin my-new-feature`)
18
+ 5. Create a new Pull Request
data/ROADMAP.md ADDED
@@ -0,0 +1,9 @@
1
+ # SimonSays Road Map
2
+
3
+ ## v2
4
+
5
+ - Customization of authentication methods
6
+ - Currently we sort of assume you're using devise
7
+ - More expressive `find_and_authorize` syntax
8
+ - Add a way of authorizing against ALL roles not just any role
9
+ - `grep -r TODO .`
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require 'rdoc/task'
4
+
5
+ Rake::TestTask.new :test do |t|
6
+ t.libs << 'test'
7
+ t.pattern = 'test/**/*_test.rb'
8
+ t.verbose = false
9
+ end
10
+
11
+ namespace :docs do
12
+ RDoc::Task.new :generate do |rdoc|
13
+ rdoc.title = "SimonSays RDOC"
14
+ rdoc.main = "README.md"
15
+
16
+ rdoc.rdoc_dir = "docs"
17
+ rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
18
+
19
+ rdoc.options << "--all"
20
+ end
21
+ end
22
+
23
+
24
+ task :default => :test
data/SimonSays.png ADDED
Binary file
@@ -0,0 +1,157 @@
1
+ module SimonSays
2
+ module Authorizer
3
+ extend ActiveSupport::Concern
4
+
5
+ class Denied < Exception
6
+ def initialize(as, required, actual)
7
+ # TODO i18n for err message (as should be singluarized with 1 flag)
8
+ super "Access denied; #{required * ', '} role is required. Current access is #{actual * ', '}"
9
+ end
10
+ end
11
+
12
+ included do
13
+ class_attribute :default_authorization_scope
14
+ end
15
+
16
+ # Once +Authorizer+ is included these methods become
17
+ # available to your controllers.
18
+ module ClassMethods
19
+ # Authentication convenience method (to keep things declarative).
20
+ # This method just setups a +before_filter+
21
+ #
22
+ # * +scope+ is a symbol or string and should correspond to some sort
23
+ # of authentication scope (ie: +authenticate_user!+)
24
+ # * +opts+ filter options
25
+ #
26
+ # ====== Example
27
+ #
28
+ # authenticate :user, expect: :index
29
+ #
30
+ def authenticate(scope, opts = {})
31
+ before_filter :"authenticate_#{scope}!", filter_options(opts)
32
+ end
33
+
34
+ # Find and authorize a resource.
35
+ #
36
+ # * +resource+ the name of resource to find
37
+ # * +roles+ one or more role symbols
38
+ # * the last argument may also be a filter options hash
39
+ #
40
+ # ====== Example
41
+ #
42
+ # find_and_authorize :document, :create, :update :publish, through: :memberships
43
+ def find_and_authorize(resource, *roles)
44
+ opts = roles.extract_options!
45
+
46
+ before_filter(filter_options(opts)) do
47
+ find_resource resource, opts
48
+
49
+ authorize roles, opts unless roles.empty?
50
+ end
51
+ end
52
+
53
+ # Find a resource
54
+ #
55
+ # * +resource+ the name of the resource to find
56
+ # * +opts+ filter options
57
+ def find_resource(resource, opts = {})
58
+ before_filter(filter_options(opts)) do
59
+ find_resource resource, opts
60
+ end
61
+ end
62
+
63
+ # Authorize against a given resource
64
+ #
65
+ # * +resource+ the name of the resource to authorize against. The
66
+ # resource should include +Roleable+ and define some set of
67
+ # roles. This method also expect the record to be available as
68
+ # an instance variable (which is the case if +find_resource+ is
69
+ # called before hand)
70
+ # * +roles+ one or more role symbols
71
+ # * the last argument may also be a filter options hash
72
+ def authorize_resource(resource, *roles)
73
+ before_filter(filter_options(roles.extract_options!)) do
74
+ authorize(roles, { resource: resource })
75
+ end
76
+ end
77
+
78
+ def filter_options(options) # :nodoc:
79
+ { except: options.delete(:except), only: options.delete(:only) }
80
+ end
81
+ end
82
+
83
+ # @returns Primary resource found; need for +authorize+ calls
84
+ def find_resource(resource, options = {}) # :nodoc:
85
+ resource = resource.to_s
86
+
87
+ scope, query = resource_scope_and_query(resource, options)
88
+ through = options[:through] ? options[:through].to_s : nil
89
+
90
+ assoc = through || (options[:from] ? resource.pluralize : nil)
91
+ scope = scope.send(assoc) if assoc
92
+
93
+ record = scope.where(query).first!
94
+
95
+ if through
96
+ instance_variable_set "@#{through.singularize}", record
97
+ record = record.send(resource)
98
+ end
99
+
100
+ instance_variable_set "@#{resource}", record
101
+ end
102
+
103
+
104
+ def authorize(required = nil, options) # :nodoc:
105
+ if through = options[:through]
106
+ name = through.to_s.singularize.to_sym
107
+ else
108
+ name = options[:resource]
109
+ end
110
+
111
+ attr = Roleable.registry[name]
112
+ required ||= options[attr.to_sym]
113
+
114
+ required = [required] unless Array === required
115
+ record = instance_variable_get("@#{name}")
116
+
117
+ if record.nil? # must be devise scope
118
+ record = send("current_#{name}")
119
+ send "authenticate_#{name}!"
120
+ end
121
+
122
+ actual = record.send(attr)
123
+
124
+ # actual roles must have at least
125
+ # one required role (array intersection)
126
+ ((required & actual).size > 0).tap do |res|
127
+ raise Denied.new(attr, required, actual) unless res
128
+ end
129
+ end
130
+
131
+ private
132
+
133
+ def resource_scope_and_query(resource, options) # :nodoc:
134
+ if options[:through]
135
+ field = "#{resource}_id"
136
+
137
+ query = { field => params[field] } if params[field]
138
+ scope = send(self.class.default_authorization_scope)
139
+
140
+ elsif options[:from]
141
+ scope = instance_variable_get("@#{options[:from]}") || send(options[:from])
142
+
143
+ else
144
+ klass = (options[:class_name] || resource).to_s
145
+ # TODO support array of namespaces?
146
+ klass = "#{options[:namespace]}/#{klass}" if options[:namespace]
147
+
148
+ scope = klass.classify.constantize
149
+ end
150
+
151
+ field ||= :id
152
+ query ||= { field => params[:id] }
153
+
154
+ return scope, query
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,107 @@
1
+ module SimonSays
2
+ module Roleable
3
+ extend ActiveSupport::Concern
4
+
5
+ def self.registry # :nodoc:
6
+ # "global" registry we'll use when authorizing
7
+ @registry ||= {}
8
+ end
9
+
10
+ module ClassMethods
11
+ ##
12
+ # Provides a declarative method to introduce role based
13
+ # access controller through a give integer mask.
14
+ #
15
+ # By default it'll use an attributed named +role_mask+. You can
16
+ # use the +:as+ option to change the prefix for the +_mask+
17
+ # attribute. This will also alter the names of the dynamically
18
+ # generated methods.
19
+ #
20
+ # ===== Example
21
+ #
22
+ # class User < ActiveRecord::Base
23
+ # include SimonSays::Roleable
24
+ #
25
+ # has_roles :read, :write, :delete
26
+ # end
27
+ #
28
+ # class Editor < ActiveRecord::Base
29
+ # include SimonSays::Roleable
30
+ #
31
+ # has_roles :create, :update, :publish, as: :access
32
+ # end
33
+ #
34
+ # ===== Dynamic Methods
35
+ #
36
+ # Several methods are dynamically genreated when calling +has_roles+.
37
+ # The methods generated include a setter, a getter and a predicate
38
+ # method. For examples:
39
+ #
40
+ # User.new.roles
41
+ # => []
42
+ #
43
+ # User.new(roles: :read).roles
44
+ # => [:read]
45
+ #
46
+ # User.new.tap { |u| u.roles = :write, :read }.roles
47
+ # => [:read, :write]
48
+ #
49
+ # User.new(roles: [:read, :write]).has_roles? :read, :write
50
+ # => true
51
+ #
52
+ # User.new(roles: :read).has_role? :read
53
+ # => true
54
+ #
55
+ # Here's an example using the +:as+ prefix option:
56
+ #
57
+ # Editor.new(access: %w[create update publish]).access
58
+ # => [:create, :update, :publish]
59
+ #
60
+ # Editor.new(access: :publish).has_access? :create
61
+ # => false
62
+ #
63
+ def has_roles *roles
64
+ options = roles.extract_options!
65
+
66
+ name = (options[:as] || :roles).to_s
67
+ singular = name.singularize
68
+ const = name.upcase
69
+
70
+ Roleable.registry[model_name.to_s.downcase.to_sym] ||= name
71
+
72
+ roles.map!(&:to_sym)
73
+
74
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__
75
+ #{const} = %i[#{roles * ' '}]
76
+
77
+ def #{name}=(args)
78
+ args = [args] unless Array === args
79
+ args.map!(&:to_sym)
80
+
81
+ self[:#{name}_mask] = (args & #{const}).map { |i| 2 ** #{const}.index(i) }.sum
82
+ end
83
+
84
+ def #{name}
85
+ #{const}.reject { |i| ((#{name}_mask || 0) & 2 ** #{const}.index(i)).zero? }
86
+ end
87
+
88
+ def has_#{name}?(*args)
89
+ (#{name} & args).size > 0
90
+ end
91
+ RUBY_EVAL
92
+
93
+ if name != singular
94
+ class_eval <<-RUBY_EVAL
95
+ alias has_#{singular}? has_#{name}?
96
+ RUBY_EVAL
97
+ end
98
+
99
+ # Declare a scope for finding records with a given role set
100
+ # TODO support an array roles (must match ALL)
101
+ scope "with_#{name}", ->(role) {
102
+ where("(#{name}_mask & ?) > 0", 2**roles.index(role))
103
+ }
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,3 @@
1
+ module SimonSays
2
+ VERSION = "0.0.3"
3
+ end
data/lib/simon_says.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'active_support'
2
+
3
+ require "simon_says/version"
4
+ require "simon_says/roleable"
5
+ require "simon_says/authorizer"
6
+
7
+ module SimonSays
8
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simon_says/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simon_says"
8
+ spec.version = SimonSays::VERSION
9
+ spec.authors = ["Michael Coyne"]
10
+ spec.email = ["mikeycgto@gmail.com"]
11
+ spec.summary = %q{Light-weight, declarative authorization and access control for Rails}
12
+ spec.description = %q{This gem is a simple, easy-to-use declarative role-based access control system for Rails}
13
+ spec.homepage = "https://github.com/SimplyBuilt/SimonSays"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 4.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.7"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rails", "~> 4.1"
26
+ spec.add_development_dependency "responders", "~> 1.0"
27
+ spec.add_development_dependency "mocha", "~> 1.1"
28
+ end
@@ -0,0 +1,92 @@
1
+ require 'test_helper'
2
+
3
+ class Admin::ReportsControllerTest < ActionController::TestCase
4
+ setup do
5
+ @support = admins(:support)
6
+ @marketing = admins(:marketing)
7
+ end
8
+
9
+ test "index with access" do
10
+ @controller.current_admin = @support
11
+
12
+ get :index, format: :json
13
+
14
+ assert_response :success
15
+ end
16
+
17
+ test "index without access" do
18
+ @controller.current_admin = @marketing
19
+
20
+ assert_raises SimonSays::Authorizer::Denied do
21
+ get :index, format: :json
22
+ end
23
+ end
24
+
25
+ test "create with access" do
26
+ @controller.current_admin = @support
27
+
28
+ assert_difference 'Admin::Report.count' do
29
+ post :create, report: { title: 'Test' }, format: :json
30
+ end
31
+ end
32
+
33
+ test "create without access" do
34
+ @controller.current_admin = @marketing
35
+
36
+ assert_raises SimonSays::Authorizer::Denied do
37
+ post :create, report: { title: 'Test' }, format: :json
38
+ end
39
+ end
40
+
41
+ test "show with access" do
42
+ @controller.current_admin = @support
43
+
44
+ get :show, id: admin_reports(:report_one), format: :json
45
+
46
+ refute_nil assigns(:report)
47
+ assert_response :success
48
+ end
49
+
50
+ test "show without access" do
51
+ @controller.current_admin = @marketing
52
+
53
+ assert_raises SimonSays::Authorizer::Denied do
54
+ get :show, id: admin_reports(:report_one), format: :json
55
+ end
56
+ end
57
+
58
+ test "update with access" do
59
+ @controller.current_admin = @support
60
+
61
+ patch :show, id: admin_reports(:report_one), report: { title: 'Test' }, format: :json
62
+
63
+ refute_nil assigns(:report)
64
+ assert_response :success
65
+ end
66
+
67
+ test "update without access" do
68
+ @controller.current_admin = @marketing
69
+
70
+ assert_raises SimonSays::Authorizer::Denied do
71
+ patch :show, id: admin_reports(:report_one), report: { title: 'Test' }, format: :json
72
+ end
73
+ end
74
+
75
+ test "destroy with access" do
76
+ @controller.current_admin = @support
77
+
78
+ assert_difference 'Admin::Report.count', -1 do
79
+ delete :destroy, id: admin_reports(:report_one), format: :json
80
+ end
81
+
82
+ refute_nil assigns(:report)
83
+ end
84
+
85
+ test "destroy without access" do
86
+ @controller.current_admin = @marketing
87
+
88
+ assert_raises SimonSays::Authorizer::Denied do
89
+ delete :destroy, id: admin_reports(:report_one), format: :json
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,87 @@
1
+ require 'test_helper'
2
+
3
+ class DocumentsControllerTest < ActionController::TestCase
4
+ setup do
5
+ @alpha = documents(:alpha)
6
+ @beta = documents(:beta)
7
+
8
+ @bob = users(:bob)
9
+ @jim = users(:jim)
10
+ end
11
+
12
+ def as_bob!
13
+ @controller.current_user = @bob
14
+ end
15
+
16
+ def as_jim!
17
+ @controller.current_user = @jim
18
+ end
19
+
20
+ test "show" do
21
+ as_bob!
22
+
23
+ get :show, id: @alpha.id, format: :json
24
+
25
+ refute_nil assigns(:document)
26
+ assert_response :success
27
+ end
28
+
29
+ test "show without through relationship" do
30
+ as_jim!
31
+
32
+ assert_raises ActiveRecord::RecordNotFound do
33
+ get :show, id: @alpha.id, format: :json
34
+ end
35
+ end
36
+
37
+ test "update with access" do
38
+ as_bob!
39
+
40
+ patch :update, id: @alpha.id, document: { title: 'Test' }, format: :json
41
+
42
+ refute_nil assigns(:document)
43
+ assert_response :success
44
+ end
45
+
46
+ test "update without access" do
47
+ as_bob!
48
+
49
+ assert_raises SimonSays::Authorizer::Denied do
50
+ patch :update, id: @beta.id, document: { title: 'Test' }, format: :json
51
+ end
52
+ end
53
+
54
+ test "update without through relationship" do
55
+ as_jim!
56
+
57
+ assert_raises ActiveRecord::RecordNotFound do
58
+ patch :update, id: @alpha.id, document: { title: 'Test' }, format: :json
59
+ end
60
+ end
61
+
62
+ test "destroy with access" do
63
+ as_bob!
64
+
65
+ assert_difference 'Document.count', -1 do
66
+ delete :destroy, id: @alpha.id, format: :json
67
+ end
68
+
69
+ refute_nil assigns(:document)
70
+ end
71
+
72
+ test "destroy without access" do
73
+ as_bob!
74
+
75
+ assert_raises SimonSays::Authorizer::Denied do
76
+ delete :destroy, id: @beta.id, format: :json
77
+ end
78
+ end
79
+
80
+ test "destroy without through relationship" do
81
+ as_jim!
82
+
83
+ assert_raises ActiveRecord::RecordNotFound do
84
+ delete :destroy, id: @beta.id, format: :json
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class AdminModelTest < ActiveSupport::TestCase
4
+ test "Admin is in registry" do
5
+ assert_includes SimonSays::Roleable.registry, :admin
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class MembershipModelTest < ActiveSupport::TestCase
4
+ test "Membership is in registry" do
5
+ assert_includes SimonSays::Roleable.registry, :membership
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+ /db/*.sqlite3-journal
13
+
14
+ # Ignore all logfiles and tempfiles.
15
+ /log/*.log
16
+ /tmp