simon_says 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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