simon_says 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitpublish +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +13 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +18 -0
- data/ROADMAP.md +9 -0
- data/Rakefile +24 -0
- data/SimonSays.png +0 -0
- data/lib/simon_says/authorizer.rb +157 -0
- data/lib/simon_says/roleable.rb +107 -0
- data/lib/simon_says/version.rb +3 -0
- data/lib/simon_says.rb +8 -0
- data/simon_says.gemspec +28 -0
- data/test/controllers/admin/reports_controller_test.rb +92 -0
- data/test/controllers/documents_controller_test.rb +87 -0
- data/test/models/admin_test.rb +7 -0
- data/test/models/membership_test.rb +7 -0
- data/test/rails_app/.gitignore +16 -0
- data/test/rails_app/README.rdoc +28 -0
- data/test/rails_app/Rakefile +6 -0
- data/test/rails_app/app/assets/images/.keep +0 -0
- data/test/rails_app/app/assets/javascripts/application.js +16 -0
- data/test/rails_app/app/assets/stylesheets/application.css +15 -0
- data/test/rails_app/app/controllers/admin/reports_controller.rb +40 -0
- data/test/rails_app/app/controllers/application_controller.rb +19 -0
- data/test/rails_app/app/controllers/concerns/.keep +0 -0
- data/test/rails_app/app/controllers/documents_controller.rb +48 -0
- data/test/rails_app/app/helpers/application_helper.rb +2 -0
- data/test/rails_app/app/mailers/.keep +0 -0
- data/test/rails_app/app/models/.keep +0 -0
- data/test/rails_app/app/models/admin/report.rb +2 -0
- data/test/rails_app/app/models/admin.rb +5 -0
- data/test/rails_app/app/models/concerns/.keep +0 -0
- data/test/rails_app/app/models/document.rb +4 -0
- data/test/rails_app/app/models/membership.rb +8 -0
- data/test/rails_app/app/models/user.rb +4 -0
- data/test/rails_app/app/views/layouts/application.html.erb +14 -0
- data/test/rails_app/bin/bundle +3 -0
- data/test/rails_app/bin/rails +8 -0
- data/test/rails_app/bin/rake +8 -0
- data/test/rails_app/bin/spring +18 -0
- data/test/rails_app/config/application.rb +29 -0
- data/test/rails_app/config/boot.rb +4 -0
- data/test/rails_app/config/database.yml +25 -0
- data/test/rails_app/config/environment.rb +5 -0
- data/test/rails_app/config/environments/development.rb +37 -0
- data/test/rails_app/config/environments/production.rb +78 -0
- data/test/rails_app/config/environments/test.rb +39 -0
- data/test/rails_app/config/initializers/assets.rb +8 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/cookies_serializer.rb +3 -0
- data/test/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/rails_app/config/initializers/inflections.rb +16 -0
- data/test/rails_app/config/initializers/mime_types.rb +4 -0
- data/test/rails_app/config/initializers/session_store.rb +3 -0
- data/test/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/test/rails_app/config/locales/en.yml +23 -0
- data/test/rails_app/config/routes.rb +7 -0
- data/test/rails_app/config/secrets.yml +22 -0
- data/test/rails_app/config.ru +4 -0
- data/test/rails_app/db/migrate/20141016142638_create_admins.rb +9 -0
- data/test/rails_app/db/migrate/20141016183619_create_users.rb +8 -0
- data/test/rails_app/db/migrate/20141016183633_create_memberships.rb +12 -0
- data/test/rails_app/db/migrate/20141016183642_create_documents.rb +9 -0
- data/test/rails_app/db/migrate/20141017140833_create_admin_reports.rb +9 -0
- data/test/rails_app/db/schema.rb +47 -0
- data/test/rails_app/db/seeds.rb +7 -0
- data/test/rails_app/lib/assets/.keep +0 -0
- data/test/rails_app/lib/tasks/.keep +0 -0
- data/test/rails_app/log/.keep +0 -0
- data/test/rails_app/public/404.html +67 -0
- data/test/rails_app/public/422.html +67 -0
- data/test/rails_app/public/500.html +66 -0
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_app/public/robots.txt +5 -0
- data/test/rails_app/test/controllers/.keep +0 -0
- data/test/rails_app/test/fixtures/.keep +0 -0
- data/test/rails_app/test/fixtures/admin/reports.yml +2 -0
- data/test/rails_app/test/fixtures/admins.yml +11 -0
- data/test/rails_app/test/fixtures/documents.yml +8 -0
- data/test/rails_app/test/fixtures/memberships.yml +10 -0
- data/test/rails_app/test/fixtures/users.yml +2 -0
- data/test/rails_app/test/helpers/.keep +0 -0
- data/test/rails_app/test/integration/.keep +0 -0
- data/test/rails_app/test/mailers/.keep +0 -0
- data/test/rails_app/test/models/.keep +0 -0
- data/test/rails_app/test/models/admin/report_test.rb +7 -0
- data/test/rails_app/test/models/document_test.rb +7 -0
- data/test/rails_app/test/models/membership_test.rb +7 -0
- data/test/rails_app/test/models/user_test.rb +7 -0
- data/test/rails_app/test/test_helper.rb +10 -0
- data/test/rails_app/vendor/assets/javascripts/.keep +0 -0
- data/test/rails_app/vendor/assets/stylesheets/.keep +0 -0
- data/test/simon_says/authorizer_test.rb +143 -0
- data/test/simon_says/roleable_test.rb +200 -0
- data/test/simon_says_test.rb +7 -0
- data/test/test_helper.rb +48 -0
- 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
data/.gitpublish
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
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
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
|
data/lib/simon_says.rb
ADDED
data/simon_says.gemspec
ADDED
@@ -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,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
|