ccls-simply_authorized 1.4.1
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.
- data/README.rdoc +53 -0
- data/app/models/role.rb +34 -0
- data/generators/ccls_simply_authorized/USAGE +0 -0
- data/generators/ccls_simply_authorized/ccls_simply_authorized_generator.rb +98 -0
- data/generators/ccls_simply_authorized/templates/autotest_simply_authorized.rb +3 -0
- data/generators/ccls_simply_authorized/templates/controllers/roles_controller.rb +38 -0
- data/generators/ccls_simply_authorized/templates/fixtures/roles.yml +36 -0
- data/generators/ccls_simply_authorized/templates/functional/roles_controller_test.rb +142 -0
- data/generators/ccls_simply_authorized/templates/migrations/create_roles.rb +14 -0
- data/generators/ccls_simply_authorized/templates/migrations/create_roles_users.rb +14 -0
- data/generators/ccls_simply_authorized/templates/simply_authorized.rake +6 -0
- data/generators/ccls_simply_authorized/templates/stylesheets/authorized.css +0 -0
- data/generators/ccls_simply_authorized/templates/unit/role_test.rb +30 -0
- data/lib/ccls-simply_authorized.rb +1 -0
- data/lib/simply_authorized.rb +42 -0
- data/lib/simply_authorized/authorization.rb +68 -0
- data/lib/simply_authorized/autotest.rb +33 -0
- data/lib/simply_authorized/controller.rb +87 -0
- data/lib/simply_authorized/core_extension.rb +16 -0
- data/lib/simply_authorized/factories.rb +15 -0
- data/lib/simply_authorized/factory_test_helper.rb +47 -0
- data/lib/simply_authorized/helper.rb +28 -0
- data/lib/simply_authorized/permissive_controller.rb +27 -0
- data/lib/simply_authorized/resourceful_controller.rb +83 -0
- data/lib/simply_authorized/tasks.rb +1 -0
- data/lib/simply_authorized/test_tasks.rb +47 -0
- data/lib/simply_authorized/user_model.rb +166 -0
- data/lib/tasks/application.rake +40 -0
- data/lib/tasks/common_lib.rake +7 -0
- data/lib/tasks/database.rake +52 -0
- data/lib/tasks/documentation.rake +68 -0
- data/lib/tasks/rcov.rake +44 -0
- data/rails/init.rb +4 -0
- data/test/unit/authorized/role_test.rb +30 -0
- metadata +141 -0
File without changes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class SimplyAuthorized::RoleTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
assert_should_act_as_list(:model => 'Role')
|
7
|
+
assert_should_require(:name,
|
8
|
+
:model => 'Role')
|
9
|
+
assert_should_require_unique(:name,
|
10
|
+
:model => 'Role')
|
11
|
+
assert_should_habtm(:users,
|
12
|
+
:model => 'Role')
|
13
|
+
|
14
|
+
test "should create role" do
|
15
|
+
assert_difference('Role.count',1) do
|
16
|
+
object = create_object
|
17
|
+
assert !object.new_record?,
|
18
|
+
"#{object.errors.full_messages.to_sentence}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def create_object(options = {})
|
25
|
+
record = Factory.build(:role,options)
|
26
|
+
record.save
|
27
|
+
record
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'simply_authorized'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SimplyAuthorized
|
2
|
+
# predefined namespace
|
3
|
+
end
|
4
|
+
require 'active_support'
|
5
|
+
|
6
|
+
gem 'ccls-common_lib'
|
7
|
+
require 'common_lib'
|
8
|
+
|
9
|
+
require 'acts_as_list'
|
10
|
+
|
11
|
+
require 'action_controller' # loads HTML
|
12
|
+
HTML::WhiteListSanitizer.allowed_attributes.merge(%w(
|
13
|
+
id class style
|
14
|
+
))
|
15
|
+
|
16
|
+
#%w{models controllers}.each do |dir|
|
17
|
+
# path = File.expand_path(File.join(File.dirname(__FILE__), '../app', dir))
|
18
|
+
# ActiveSupport::Dependencies.autoload_paths << path
|
19
|
+
# ActiveSupport::Dependencies.autoload_once_paths << path
|
20
|
+
#end
|
21
|
+
|
22
|
+
require 'simply_authorized/core_extension'
|
23
|
+
require 'simply_authorized/user_model'
|
24
|
+
require 'simply_authorized/authorization'
|
25
|
+
require 'simply_authorized/helper'
|
26
|
+
require 'simply_authorized/controller'
|
27
|
+
require 'simply_authorized/resourceful_controller'
|
28
|
+
require 'simply_authorized/permissive_controller'
|
29
|
+
|
30
|
+
if defined?(Rails) && Rails.env == 'test' && Rails.class_variable_defined?("@@configuration")
|
31
|
+
require 'active_support/test_case'
|
32
|
+
require 'factory_girl'
|
33
|
+
require 'simply_authorized/factories'
|
34
|
+
require 'simply_authorized/factory_test_helper'
|
35
|
+
# else
|
36
|
+
# running a rake task
|
37
|
+
end
|
38
|
+
|
39
|
+
#ActionController::Routing::Routes.add_configuration_file(
|
40
|
+
# File.expand_path(
|
41
|
+
# File.join(
|
42
|
+
# File.dirname(__FILE__), '../config/routes.rb')))
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module SimplyAuthorized
|
2
|
+
module Authorization
|
3
|
+
module Controller
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.send(:include, InstanceMethods)
|
7
|
+
base.alias_method_chain :method_missing, :authorization
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
|
12
|
+
def auth_redirections(permission_name)
|
13
|
+
if respond_to?(:redirections) &&
|
14
|
+
redirections.is_a?(Hash) &&
|
15
|
+
!redirections[permission_name].blank?
|
16
|
+
redirections[permission_name]
|
17
|
+
else
|
18
|
+
HashWithIndifferentAccess.new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing_with_authorization(symb,*args, &block)
|
23
|
+
method_name = symb.to_s
|
24
|
+
|
25
|
+
if method_name =~ /^may_(not_)?(.+)_required$/
|
26
|
+
full_permission_name = "#{$1}#{$2}"
|
27
|
+
negate = !!$1 # double bang converts to boolean
|
28
|
+
permission_name = $2
|
29
|
+
verb,target = permission_name.split(/_/,2)
|
30
|
+
|
31
|
+
# using target words where singular == plural won't work here
|
32
|
+
if !target.blank? && target == target.singularize
|
33
|
+
unless permission = current_user.try(
|
34
|
+
"may_#{permission_name}?",
|
35
|
+
instance_variable_get("@#{target}")
|
36
|
+
)
|
37
|
+
message = "You don't have permission to " <<
|
38
|
+
"#{verb} this #{target}."
|
39
|
+
end
|
40
|
+
else
|
41
|
+
# current_user may be nil so must use try and NOT send
|
42
|
+
unless permission = current_user.try("may_#{permission_name}?")
|
43
|
+
message = "You don't have permission to " <<
|
44
|
+
"#{permission_name.gsub(/_/,' ')}."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# exclusive or
|
49
|
+
unless negate ^ permission
|
50
|
+
# if message is nil, negate will be true
|
51
|
+
message ||= "Access denied. May #{(negate)?'not ':''}" <<
|
52
|
+
"#{permission_name.gsub(/_/,' ')}."
|
53
|
+
ar = auth_redirections(full_permission_name)
|
54
|
+
access_denied(
|
55
|
+
(ar[:message]||message),
|
56
|
+
(ar[:redirect_to]||root_path||"/")
|
57
|
+
)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
method_missing_without_authorization(symb, *args, &block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end # Controller
|
66
|
+
end # Authorization
|
67
|
+
end # SimplyAuthorized
|
68
|
+
ActionController::Base.send(:include,SimplyAuthorized::Authorization::Controller)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Autotest::Rails
|
2
|
+
|
3
|
+
#
|
4
|
+
# Need both the mapping and the extra files
|
5
|
+
#
|
6
|
+
def run_with_simply_authorized
|
7
|
+
add_exception %r%config/%
|
8
|
+
add_exception %r%versions/%
|
9
|
+
add_exception %r%\.git/%
|
10
|
+
self.extra_files << File.expand_path(File.join(
|
11
|
+
File.dirname(__FILE__),'/../../test/unit/authorized/'))
|
12
|
+
|
13
|
+
# self.extra_files << File.expand_path(File.join(
|
14
|
+
# File.dirname(__FILE__),'/../../test/functional/authorized/'))
|
15
|
+
#
|
16
|
+
# add_mapping(
|
17
|
+
# %r{^#{File.expand_path(File.join(File.dirname(__FILE__),'/../../test/'))}/(unit|functional)/authorized/.*_test\.rb$}
|
18
|
+
# ) do |filename, _|
|
19
|
+
# filename
|
20
|
+
# end
|
21
|
+
|
22
|
+
add_mapping(
|
23
|
+
%r{^#{File.expand_path(File.join(File.dirname(__FILE__),'/../../test/'))}/unit/authorized/.*_test\.rb$}
|
24
|
+
) do |filename, _|
|
25
|
+
filename
|
26
|
+
end
|
27
|
+
|
28
|
+
run_without_simply_authorized
|
29
|
+
end
|
30
|
+
alias_method_chain :run, :simply_authorized
|
31
|
+
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'ssl_requirement'
|
2
|
+
module SimplyAuthorized
|
3
|
+
module Controller
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
base.send(:include, SslRequirement)
|
8
|
+
# My ssl_required? overrides SslRequirement so MUST come AFTER!
|
9
|
+
base.send(:include, InstanceMethods)
|
10
|
+
base.class_eval do
|
11
|
+
class << self
|
12
|
+
alias_method_chain :inherited, :ccls_before_filters
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def inherited_with_ccls_before_filters(base)
|
22
|
+
identifier = 'ccls_ensure_proper_protocol'
|
23
|
+
unless filter_chain.select(&:before?).map(&:identifier
|
24
|
+
).include?(identifier)
|
25
|
+
before_filter :ensure_proper_protocol,
|
26
|
+
:identifier => identifier
|
27
|
+
end
|
28
|
+
# identifier = 'ccls_build_menu_js'
|
29
|
+
# unless filter_chain.select(&:before?).map(&:identifier
|
30
|
+
# ).include?(identifier)
|
31
|
+
# before_filter :build_menu_js,
|
32
|
+
# :identifier => identifier
|
33
|
+
# end
|
34
|
+
inherited_without_ccls_before_filters(base)
|
35
|
+
end
|
36
|
+
|
37
|
+
end # ClassMethods
|
38
|
+
|
39
|
+
module InstanceMethods
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def ssl_required?
|
44
|
+
# Force https everywhere (that doesn't have ssl_allowed set)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def redirect_to_referer_or_default(default)
|
49
|
+
redirect_to( session[:refer_to] ||
|
50
|
+
request.env["HTTP_REFERER"] || default )
|
51
|
+
session[:refer_to] = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# Flash error message and redirect
|
55
|
+
def access_denied(
|
56
|
+
message="You don't have permission to complete that action.",
|
57
|
+
default=root_path )
|
58
|
+
session[:return_to] = request.request_uri unless params[:format] == 'js'
|
59
|
+
flash[:error] = message
|
60
|
+
redirect_to default
|
61
|
+
end
|
62
|
+
|
63
|
+
# # The menu is on every page and this seems as the
|
64
|
+
# # only way for me to force it into the application
|
65
|
+
# # layout.
|
66
|
+
# def build_menu_js
|
67
|
+
# js = "" <<
|
68
|
+
# "if ( typeof(translatables) == 'undefined' ){\n" <<
|
69
|
+
# " var translatables = [];\n" <<
|
70
|
+
# "}\n"
|
71
|
+
# Page.roots.each do |page|
|
72
|
+
# js << "" <<
|
73
|
+
# "tmp={tag:'#menu_#{dom_id(page)}',locales:{}};\n"
|
74
|
+
# %w( en es ).each do |locale|
|
75
|
+
# js << "tmp.locales['#{locale}']='#{page.menu(locale)}'\n"
|
76
|
+
# end
|
77
|
+
# js << "translatables.push(tmp);\n"
|
78
|
+
# end
|
79
|
+
# @template.content_for :head do
|
80
|
+
# @template.javascript_tag js
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
|
84
|
+
end # InstanceMethods
|
85
|
+
end # Controller
|
86
|
+
end # CclsEngine
|
87
|
+
ActionController::Base.send(:include,SimplyAuthorized::Controller)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SimplyAuthorized
|
2
|
+
module CoreExtension
|
3
|
+
|
4
|
+
def class_exists?(full_class_name)
|
5
|
+
name_spaces = full_class_name.to_s.split('::')
|
6
|
+
class_name = name_spaces.pop
|
7
|
+
name_space = name_spaces.join('::')
|
8
|
+
klass = ((name_space.blank?) ? Module : name_space.constantize).const_get(class_name.to_s)
|
9
|
+
return klass.is_a?(Class)
|
10
|
+
rescue NameError
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
|
14
|
+
end # CoreExtension
|
15
|
+
end # SimplyAuthorized
|
16
|
+
include SimplyAuthorized::CoreExtension
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Factory.define :role do |f|
|
2
|
+
f.sequence(:name) { |n| "name#{n}" }
|
3
|
+
end
|
4
|
+
|
5
|
+
Factory.define :user do |f|
|
6
|
+
f.sequence(:uid) { |n| "UID#{n}" }
|
7
|
+
# f.sequence(:username) { |n| "username#{n}" }
|
8
|
+
# f.sequence(:email) { |n| "username#{n}@example.com" }
|
9
|
+
# f.password 'V@1!dP@55w0rd'
|
10
|
+
# f.password_confirmation 'V@1!dP@55w0rd'
|
11
|
+
# f.role_name 'user'
|
12
|
+
end
|
13
|
+
Factory.define :admin_user, :parent => :user do |f|
|
14
|
+
f.administrator true
|
15
|
+
end # parent must be defined first
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module SimplyAuthorized::FactoryTestHelper
|
2
|
+
|
3
|
+
def active_user(options={})
|
4
|
+
u = Factory(:user, options)
|
5
|
+
# leave this special save here just in case I change things.
|
6
|
+
# although this would need changed for UCB CAS.
|
7
|
+
# u.save_without_session_maintenance
|
8
|
+
# u
|
9
|
+
end
|
10
|
+
alias_method :user, :active_user
|
11
|
+
|
12
|
+
def superuser(options={})
|
13
|
+
u = active_user(options)
|
14
|
+
u.roles << Role.find_or_create_by_name('superuser')
|
15
|
+
u
|
16
|
+
end
|
17
|
+
alias_method :super_user, :superuser
|
18
|
+
|
19
|
+
def admin_user(options={})
|
20
|
+
u = active_user(options)
|
21
|
+
u.roles << Role.find_or_create_by_name('administrator')
|
22
|
+
u
|
23
|
+
end
|
24
|
+
alias_method :admin, :admin_user
|
25
|
+
alias_method :administrator, :admin_user
|
26
|
+
|
27
|
+
def interviewer(options={})
|
28
|
+
u = active_user(options)
|
29
|
+
u.roles << Role.find_or_create_by_name('interviewer')
|
30
|
+
u
|
31
|
+
end
|
32
|
+
|
33
|
+
def reader(options={})
|
34
|
+
u = active_user(options)
|
35
|
+
u.roles << Role.find_or_create_by_name('reader')
|
36
|
+
u
|
37
|
+
end
|
38
|
+
# alias_method :employee, :reader
|
39
|
+
|
40
|
+
def editor(options={})
|
41
|
+
u = active_user(options)
|
42
|
+
u.roles << Role.find_or_create_by_name('editor')
|
43
|
+
u
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
ActiveSupport::TestCase.send(:include,SimplyAuthorized::FactoryTestHelper)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SimplyAuthorized
|
2
|
+
module Helper
|
3
|
+
|
4
|
+
def user_roles
|
5
|
+
s = ''
|
6
|
+
if current_user.may_administrate?
|
7
|
+
s << "<ul>"
|
8
|
+
@roles.each do |role|
|
9
|
+
s << "<li>"
|
10
|
+
if @user.role_names.include?(role.name)
|
11
|
+
s << link_to( "Remove user role of '#{role.name}'",
|
12
|
+
user_role_path(@user,role.name),
|
13
|
+
:method => :delete )
|
14
|
+
else
|
15
|
+
s << link_to( "Assign user role of '#{role.name}'",
|
16
|
+
user_role_path(@user,role.name),
|
17
|
+
:method => :put )
|
18
|
+
end
|
19
|
+
s << "</li>\n"
|
20
|
+
end
|
21
|
+
s << "</ul>\n"
|
22
|
+
end
|
23
|
+
s
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
ActionView::Base.send(:include, SimplyAuthorized::Helper)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PermissiveController
|
2
|
+
def self.included(base)
|
3
|
+
base.extend(ClassMethods)
|
4
|
+
end
|
5
|
+
module ClassMethods
|
6
|
+
def permissive(*args)
|
7
|
+
options = args.extract_options!
|
8
|
+
resource = ActiveSupport::ModelName.new( options[:resource] ||
|
9
|
+
self.model_name.split('::').last.gsub(/Controller$/,'').singularize)
|
10
|
+
# resource = options[:resource] || ActiveSupport::ModelName.new(
|
11
|
+
# self.model_name.split('::').last.gsub(/Controller$/,'').singularize)
|
12
|
+
|
13
|
+
# remove NameSpace or create the may*required permission
|
14
|
+
|
15
|
+
before_filter "may_create_#{resource.plural}_required",
|
16
|
+
:only => [:new,:create]
|
17
|
+
before_filter "may_read_#{resource.plural}_required",
|
18
|
+
:only => [:show,:index]
|
19
|
+
before_filter "may_update_#{resource.plural}_required",
|
20
|
+
:only => [:edit,:update]
|
21
|
+
before_filter "may_destroy_#{resource.plural}_required",
|
22
|
+
:only => :destroy
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
ActionController::Base.send(:include,PermissiveController)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module ResourcefulController
|
2
|
+
def self.included(base)
|
3
|
+
base.extend(ClassMethods)
|
4
|
+
end
|
5
|
+
module ClassMethods
|
6
|
+
def resourceful(*args)
|
7
|
+
options = args.extract_options!
|
8
|
+
resource = ActiveSupport::ModelName.new( options[:resource] ||
|
9
|
+
self.model_name.split('::').last.gsub(/Controller$/,'').singularize)
|
10
|
+
# resource = options[:resource] || ActiveSupport::ModelName.new(
|
11
|
+
# self.model_name.split('::').last.gsub(/Controller$/,'').singularize)
|
12
|
+
|
13
|
+
permissive
|
14
|
+
|
15
|
+
before_filter :valid_id_required,
|
16
|
+
:only => [:show,:edit,:update,:destroy]
|
17
|
+
|
18
|
+
# by using before filters, the user
|
19
|
+
# can still add stuff to the action.
|
20
|
+
before_filter :get_all, :only => :index
|
21
|
+
before_filter :get_new, :only => :new
|
22
|
+
|
23
|
+
define_method :destroy do
|
24
|
+
instance_variable_get("@#{resource.singular}").send(:destroy)
|
25
|
+
redirect_to send("#{resource.plural}_path")
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method :create do
|
29
|
+
begin
|
30
|
+
instance_variable_set("@#{resource.singular}",
|
31
|
+
resource.constantize.send(:new,params[resource.singular]))
|
32
|
+
instance_variable_get("@#{resource.singular}").send(:save!)
|
33
|
+
flash[:notice] = 'Success!'
|
34
|
+
redirect_to instance_variable_get("@#{resource.singular}")
|
35
|
+
rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid
|
36
|
+
flash.now[:error] = "There was a problem creating " <<
|
37
|
+
"the #{resource.singular}"
|
38
|
+
render :action => "new"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
define_method :update do
|
43
|
+
begin
|
44
|
+
instance_variable_get("@#{resource.singular}").send(
|
45
|
+
:update_attributes!,params[resource.singular])
|
46
|
+
flash[:notice] = 'Success!'
|
47
|
+
redirect_to send(options[:update_redirect]||
|
48
|
+
"#{resource.plural}_path")
|
49
|
+
rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid
|
50
|
+
flash.now[:error] = "There was a problem updating " <<
|
51
|
+
"the #{resource.singular}"
|
52
|
+
render :action => "edit"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
define_method :get_all do
|
57
|
+
instance_variable_set("@#{resource.plural}",
|
58
|
+
resource.constantize.send(:all) )
|
59
|
+
end
|
60
|
+
protected :get_all
|
61
|
+
|
62
|
+
define_method :get_new do
|
63
|
+
instance_variable_set("@#{resource.singular}",
|
64
|
+
resource.constantize.send(:new) )
|
65
|
+
end
|
66
|
+
protected :get_new
|
67
|
+
|
68
|
+
define_method :valid_id_required do
|
69
|
+
if( !params[:id].blank? &&
|
70
|
+
resource.constantize.send(:exists?,params[:id]) )
|
71
|
+
instance_variable_set("@#{resource.singular}",
|
72
|
+
resource.constantize.send(:find,params[:id]) )
|
73
|
+
else
|
74
|
+
access_denied("Valid id required!",
|
75
|
+
send("#{resource.plural}_path") )
|
76
|
+
end
|
77
|
+
end
|
78
|
+
protected :valid_id_required
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
ActionController::Base.send(:include,ResourcefulController)
|