patrick-lockdown 2.0.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.
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+
3
+ module Lockdown
4
+ class Database
5
+ class << self
6
+ # This is very basic and could be handled better using orm specific
7
+ # functionality, but I wanted to keep it generic to avoid creating
8
+ # an interface for each the different orm implementations.
9
+ # We'll see how it works...
10
+ def sync_with_db
11
+ @permissions = Lockdown::Configuration.permission_names
12
+ @user_groups = Lockdown::Configuration.user_group_names
13
+
14
+ unless ::Permission.table_exists? && Lockdown.user_group_class.table_exists?
15
+ Lockdown.logger.info ">> Lockdown tables not found. Skipping database sync."
16
+ return
17
+ end
18
+
19
+ create_new_permissions
20
+
21
+ delete_extinct_permissions
22
+
23
+ maintain_user_groups
24
+ end
25
+
26
+ # Create permissions not found in the database
27
+ def create_new_permissions
28
+ @permissions.each do |name|
29
+ next if Lockdown::Configuration.permission_assigned_automatically?(name)
30
+ p = ::Permission.find(:first, :conditions => ["name = ?", name])
31
+ unless p
32
+ Lockdown.logger.info ">> Lockdown: Permission not found in db: #{name}, creating."
33
+ ::Permission.create(:name => name)
34
+ end
35
+ end
36
+ end
37
+
38
+ # Delete the permissions not found in init.rb
39
+ def delete_extinct_permissions
40
+ db_perms = ::Permission.find(:all).dup
41
+ db_perms.each do |dbp|
42
+ unless @permissions.include?(dbp.name)
43
+ Lockdown.logger.info ">> Lockdown: Permission no longer in init.rb: #{dbp.name}, deleting."
44
+ ug_table = Lockdown.user_groups_hbtm_reference.to_s
45
+ if "permissions" < ug_table
46
+ join_table = "permissions_#{ug_table}"
47
+ else
48
+ join_table = "#{ug_table}_permissions"
49
+ end
50
+ Lockdown.database_execute("delete from #{join_table} where permission_id = #{dbp.id}")
51
+ dbp.destroy
52
+ end
53
+ end
54
+ end
55
+
56
+ def maintain_user_groups
57
+ # Create user groups not found in the database
58
+ @user_groups.each do |name|
59
+ unless ug = Lockdown.user_group_class.find(:first, :conditions => ["name = ?", name])
60
+ create_user_group(name)
61
+ else
62
+ # Remove permissions from user group not found in init.rb
63
+ remove_invalid_permissions(ug)
64
+
65
+ # Add in permissions from init.rb not found in database
66
+ add_valid_permissions(ug)
67
+ end
68
+ end
69
+ end
70
+
71
+ def create_user_group(name)
72
+ Lockdown.logger.info ">> Lockdown: #{Lockdown::Configuration.user_group_model} not in the db: #{name}, creating."
73
+ ug = Lockdown.user_group_class.create(:name => name)
74
+ #Inefficient, definitely, but shouldn't have any issues across orms.
75
+ #
76
+ Lockdown::Configuration.user_group_permissions_names(name).each do |perm|
77
+
78
+ if Lockdown::Configuration.permission_assigned_automatically?(perm)
79
+ Lockdown.logger.info ">> Permission #{perm} cannot be assigned to #{name}. Already belongs to built in user group (public or protected)."
80
+ raise InvalidPermissionAssignment, "Invalid permission assignment"
81
+ end
82
+
83
+ p = ::Permission.find(:first, :conditions => ["name = ?", perm])
84
+
85
+ ug_table = Lockdown.user_groups_hbtm_reference.to_s
86
+ if "permissions" < ug_table
87
+ join_table = "permissions_#{ug_table}"
88
+ else
89
+ join_table = "#{ug_table}_permissions"
90
+ end
91
+ Lockdown.database_execute "insert into #{join_table}(permission_id, #{Lockdown.user_group_id_reference}) values(#{p.id}, #{ug.id})"
92
+ end
93
+ end
94
+
95
+ def remove_invalid_permissions(ug)
96
+ ug.permissions.each do |perm|
97
+ unless Lockdown::Configuration.user_group_permissions_names(ug.name).include?(perm.name)
98
+ Lockdown.logger.info ">> Lockdown: Permission: #{perm.name} no longer associated to User Group: #{ug.name}, deleting."
99
+ ug.permissions.delete(perm)
100
+ end
101
+ end
102
+ end
103
+
104
+ def add_valid_permissions(ug)
105
+ Lockdown::Configuration.user_group_permissions_names(ug.name).each do |perm_name|
106
+ found = false
107
+ # see if permission exists
108
+ ug.permissions.each do |p|
109
+ found = true if p.name == perm_name
110
+ end
111
+ # if not found, add it
112
+ unless found
113
+ Lockdown.logger.info ">> Lockdown: Permission: #{perm_name} not found for User Group: #{ug.name}, adding it."
114
+ p = ::Permission.find(:first, :conditions => ["name = ?", perm_name])
115
+ ug.permissions << p
116
+ end
117
+ end
118
+ end
119
+
120
+ end # class block
121
+ end # Database
122
+ end #Lockdown
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module Lockdown
4
+ class Delivery
5
+ class << self
6
+ # @return [true|false] if the given path is allowed
7
+ def allowed?(path, access_rights = nil)
8
+ begin
9
+ ::Authorization.configure
10
+ rescue NameError
11
+ end
12
+
13
+ access_rights ||= Lockdown::Configuration.public_access
14
+
15
+ access_rights_regex = Lockdown.regex(access_rights)
16
+
17
+ path += "/" unless path =~ /\/$/
18
+ path = "/" + path unless path =~ /^\//
19
+
20
+ if (access_rights_regex =~ path) == 0
21
+ return true
22
+ end
23
+
24
+ return false
25
+ end
26
+ end # class block
27
+ end # Delivery
28
+ end # Lockdown
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ module Lockdown
4
+ class PermissionNotFound < StandardError; end
5
+
6
+ class InvalidPermissionAssignment < StandardError; end
7
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.dirname(__FILE__), "rails", "controller")
4
+ require File.join(File.dirname(__FILE__), "rails", "view")
5
+
6
+ module Lockdown
7
+ module Frameworks
8
+ module Rails
9
+ class << self
10
+ def included(mod)
11
+ mod.extend Lockdown::Frameworks::Rails::Environment
12
+ mixin
13
+ end
14
+
15
+ def mixin
16
+ mixin_controller
17
+
18
+ Lockdown.view_helper.class_eval do
19
+ include Lockdown::Frameworks::Rails::View
20
+ end
21
+
22
+ Lockdown::Configuration.class_eval do
23
+ def self.skip_sync?
24
+ skip_db_sync_in.include?(::Rails.env)
25
+ end
26
+ end
27
+ end
28
+
29
+ def mixin_controller(klass = Lockdown.controller_parent)
30
+ klass.class_eval do
31
+ include Lockdown::Session
32
+ include Lockdown::Frameworks::Rails::Controller::Lock
33
+ end
34
+
35
+ klass.helper_method :authorized?
36
+
37
+ klass.hide_action(:set_current_user, :configure_lockdown, :check_request_authorization)
38
+
39
+ klass.before_filter do |c|
40
+ c.set_current_user
41
+ c.configure_lockdown
42
+ c.check_request_authorization
43
+ end
44
+
45
+ klass.filter_parameter_logging :password, :password_confirmation
46
+
47
+ klass.rescue_from SecurityError, :with => proc{|e| ld_access_denied(e)}
48
+ end
49
+ end # class block
50
+
51
+ module Environment
52
+
53
+ def project_root
54
+ ::RAILS_ROOT
55
+ end
56
+
57
+ def view_helper
58
+ ::ActionView::Base
59
+ end
60
+
61
+ # cache_classes is true in production and testing, need to
62
+ # modify the ApplicationController
63
+ def controller_parent
64
+ if caching?
65
+ ApplicationController
66
+ else
67
+ ActionController::Base
68
+ end
69
+ end
70
+
71
+ def caching?
72
+ ::Rails.configuration.cache_classes
73
+ end
74
+ end
75
+ end # Rails
76
+ end # Frameworks
77
+ end # Lockdown
@@ -0,0 +1,145 @@
1
+ module Lockdown
2
+ module Frameworks
3
+ module Rails
4
+ module Controller
5
+ # Locking methods
6
+ module Lock
7
+
8
+ def configure_lockdown
9
+ store_location
10
+ end
11
+
12
+ # Basic auth functionality needs to be reworked as
13
+ # Lockdown doesn't provide authentication functionality.
14
+ def set_current_user
15
+ if logged_in?
16
+ whodat = send(Lockdown::Configuration.who_did_it)
17
+ Thread.current[:who_did_it] = whodat
18
+ end
19
+ end
20
+
21
+ def check_request_authorization
22
+ unless authorized?(path_from_hash(params))
23
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
24
+ raise SecurityError, "Authorization failed! \nparams: #{parameters.inspect}\nsession: #{session.inspect}"
25
+ end
26
+ end
27
+
28
+ protected
29
+
30
+ def store_location
31
+ if request.get? && (session[:thispage] != sent_from_uri)
32
+ session[:prevpage] = session[:thispage] || ''
33
+ session[:thispage] = sent_from_uri
34
+ end
35
+ end
36
+
37
+ def sent_from_uri
38
+ request.fullpath
39
+ end
40
+
41
+ def authorized?(url, method = nil)
42
+ # Reset access unless caching?
43
+ add_lockdown_session_values unless Lockdown.caching?
44
+
45
+ return false unless url
46
+
47
+ method ||= (params[:method] || request.method)
48
+
49
+ url_parts = URI::split(url.strip)
50
+
51
+ path = url_parts[5]
52
+
53
+ subdir = Lockdown::Configuration.subdirectory
54
+ if subdir && subdir == path[1,subdir.length]
55
+ path = path[(subdir.length+1)..-1]
56
+ end
57
+
58
+ if Lockdown::Delivery.allowed?(path, session[:access_rights])
59
+ return true
60
+ end
61
+
62
+ path_parts = path.split('/')
63
+
64
+ if path_parts.last == "index"
65
+ path_parts.pop
66
+ new_path = path_parts.join('/')
67
+ return Lockdown::Delivery.allowed?(new_path, session[:access_rights])
68
+ end
69
+
70
+ begin
71
+ if ::Rails.respond_to?(:application)
72
+ router = ::Rails.application.routes
73
+ else
74
+ router = ActionController::Routing::Routes
75
+ end
76
+
77
+ hash = router.recognize_path(path, :method => method)
78
+
79
+ if hash
80
+ return Lockdown::Delivery.allowed?(path_from_hash(hash),
81
+ session[:access_rights])
82
+ end
83
+ rescue ActionController::RoutingError
84
+ # continue on
85
+ end
86
+
87
+ # Mailto link
88
+ if url =~ /^mailto:/
89
+ return true
90
+ end
91
+
92
+ # Public file
93
+ file = File.join(::Rails.root, 'public', url)
94
+ if File.exists?(file)
95
+ return true
96
+ end
97
+
98
+ # Passing in different domain
99
+ return remote_url?(url_parts[2])
100
+ end
101
+
102
+ def ld_access_denied(e)
103
+
104
+ Lockdown.logger.info "Access denied: #{e}"
105
+
106
+ if Lockdown::Configuration.logout_on_access_violation
107
+ reset_session
108
+ end
109
+ respond_to do |format|
110
+ format.html do
111
+ store_location
112
+ redirect_to Lockdown::Configuration.access_denied_path
113
+ return
114
+ end
115
+ format.xml do
116
+ headers["Status"] = "Unauthorized"
117
+ headers["WWW-Authenticate"] = %(Basic realm="Web Password")
118
+ render :text => e.message, :status => "401 Unauthorized"
119
+ return
120
+ end
121
+ end
122
+ end
123
+
124
+ def path_from_hash(hash)
125
+ hash[:controller].to_s + "/" + hash[:action].to_s
126
+ end
127
+
128
+ def remote_url?(domain = nil)
129
+ return false if domain.nil? || domain.strip.length == 0
130
+ request.host.downcase != domain.downcase
131
+ end
132
+
133
+ def redirect_back_or_default(default)
134
+ if session[:prevpage].nil? || session[:prevpage].blank?
135
+ redirect_to(default)
136
+ else
137
+ redirect_to(session[:prevpage])
138
+ end
139
+ end
140
+ end # Lock
141
+ end # Controller
142
+ end # Rails
143
+ end # Frameworks
144
+ end # Lockdown
145
+
@@ -0,0 +1,51 @@
1
+ module Lockdown
2
+ module Frameworks
3
+ module Rails
4
+ module View
5
+ def self.included(base)
6
+ base.class_eval do
7
+ alias_method :link_to_open, :link_to
8
+ alias_method :link_to, :link_to_secured
9
+
10
+ alias_method :button_to_open, :button_to
11
+ alias_method :button_to, :button_to_secured
12
+ end
13
+ end
14
+
15
+ def link_to_secured(name, options = {}, html_options = nil)
16
+ url = url_for(options)
17
+
18
+ method = html_options && html_options[:method] ? html_options[:method] : :get
19
+
20
+ if authorized?(url, method)
21
+ return link_to_open(name, url, html_options)
22
+ end
23
+ return ""
24
+ end
25
+
26
+ def button_to_secured(name, options = {}, html_options = nil)
27
+ url = url_for(options)
28
+
29
+ method = html_options ? html_options[:method] : :get
30
+
31
+ if authorized?(url, method)
32
+ return button_to_open(name, url, html_options)
33
+ end
34
+ return ""
35
+ end
36
+
37
+ def link_to_or_show(name, options = {}, html_options = nil)
38
+ lnk = link_to(name, options, html_options)
39
+ lnk.length == 0 ? name : lnk
40
+ end
41
+
42
+ def links(*lis)
43
+ rvalue = []
44
+ lis.each{|link| rvalue << link if link.length > 0 }
45
+ rvalue.join( Lockdown::Configuration.link_separator )
46
+ end
47
+ end # View
48
+ end # Rails
49
+ end # Frameworks
50
+ end # Lockdown
51
+
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ require 'active_support/core_ext'
4
+
5
+ module Lockdown
6
+ module Helper
7
+ # @return [Regexp] with \A \z boundaries
8
+ def regex(string)
9
+ Regexp.new(/\A#{string}\z/)
10
+ end
11
+
12
+ def administrator_group_name
13
+ 'Administrators'
14
+ end
15
+
16
+ def user_group_class
17
+ eval("::#{Lockdown::Configuration.user_group_model}")
18
+ end
19
+
20
+ def user_groups_hbtm_reference
21
+ Lockdown::Configuration.user_group_model.underscore.pluralize.to_sym
22
+ end
23
+
24
+ def user_group_id_reference
25
+ Lockdown::Configuration.user_group_model.underscore + "_id"
26
+ end
27
+
28
+ def user_class
29
+ eval("::#{Lockdown::Configuration.user_model}")
30
+ end
31
+
32
+ def users_hbtm_reference
33
+ Lockdown::Configuration.user_model.underscore.pluralize.to_sym
34
+ end
35
+
36
+ def user_id_reference
37
+ Lockdown::Configuration.user_model.underscore + "_id"
38
+ end
39
+ end
40
+ end