area_51 0.0.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,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ doc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in area_54.gemspec
4
+ gemspec
File without changes
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "area_51/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "area_51"
7
+ s.version = Area51::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Chad Boyd"]
10
+ s.email = ["hoverlover@gmail.com"]
11
+ s.homepage = "https://github.com/hoverlover"
12
+ s.summary = %q{Gem used for simple path-based access control.}
13
+ s.description = %q{Area51 allows you to define restricted and unrestricted sections of your application by defining paths in your controllers.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,192 @@
1
+ module Area51
2
+ autoload :AuthorizationTrigger, 'area_51/authorization_trigger'
3
+
4
+ module ApiMethod
5
+
6
+ # This is the entry point into the Area51 library. Here are some usage examples:
7
+ #
8
+ # class ApplicationController < ActionController::Base
9
+ # area_51 do
10
+ # authorization_trigger("current_user.active?", :unrestricted) do
11
+ # restricted_area "^/memers_only"
12
+ # unrestricted_area "^/$"
13
+ # end
14
+ #
15
+ # authorization_trigger(true, :restricted) do
16
+ # restricted_area "/top/secret/path"
17
+ # unrestricted_area "/anyone_allowed"
18
+ # end
19
+ #
20
+ # trigger = proc {
21
+ # # Some useful trigger condition here
22
+ # }
23
+ # authorization_trigger(trigger) do
24
+ # unrestricted_area %r{^/totally_open}
25
+ # unrestricted_area %r{^/anyone_allowed$}
26
+ # end
27
+ # end
28
+ # end
29
+ #
30
+ # See documentation for authorization_trigger for details on how to use this method.
31
+ #
32
+ def area_51(&block)
33
+ self.send :extend, ClassMethods
34
+ self.send :include, InstanceMethods
35
+
36
+ self.default_access = :restricted
37
+ self.before_filter :area_51_check_access
38
+
39
+ yield
40
+ end
41
+ end
42
+
43
+ module ClassMethods
44
+
45
+ def self.extended(klass)
46
+ klass.cattr_accessor :authorization_trigger_paths
47
+ klass.cattr_accessor :authorization_triggers
48
+ klass.cattr_accessor :safe_zone
49
+ klass.cattr_accessor :default_access
50
+ end
51
+
52
+ # Defines a trigger condition that when met, will cause authorization
53
+ # to be performed.
54
+ #
55
+ # The +trigger+ can be either a String, +lambda+, or Proc.
56
+ # If a String, it will be +eval+'d, if a +lambda+ or Proc, it will
57
+ # be called, and anything else will be returned as-is. If the result
58
+ # does not return an explicit +true+, authorization will not be performed.
59
+ #
60
+ # The +default_access+ parameter, if provided, must be one of +:restricted+ or
61
+ # +:unrestricted+. The default is +:restricted+. This specifies what type
62
+ # of access the undefined areas will have. For example:
63
+ #
64
+ # area_51 do
65
+ # authorization_trigger("current_user.active?", :unrestricted) do
66
+ # restricted_area "^/memers_only"
67
+ # unrestricted_area "^/$"
68
+ # end
69
+ # end
70
+ #
71
+ # Now if a user tries to access a path that isn't defined above, they will be granted access
72
+ # due to the +:unrestricted+ parameter.
73
+ #
74
+ def authorization_trigger(trigger, default_access = nil, &block)
75
+ trigger = AuthorizationTrigger.new(trigger, default_access)
76
+
77
+ yield
78
+
79
+ self.authorization_triggers ||= {}
80
+ self.authorization_triggers[trigger] = self.authorization_trigger_paths.dup
81
+ self.authorization_trigger_paths.clear
82
+ end
83
+
84
+ # Ties a restricted path to the authorization trigger. Must be
85
+ # called within an authorization_trigger block:
86
+ #
87
+ # authorization_trigger("current_user.signed_in?") do
88
+ # restricted_area %r{/top/secret/path/}
89
+ # end
90
+ #
91
+ # +path+ can be either a String or a Regexp. If a String, it will
92
+ # be converted to a Regexp.
93
+ #
94
+ def restricted_area(path)
95
+ add_path_to_trigger_paths path, :restricted
96
+ end
97
+
98
+ # Ties an unrestricted path to the authorization trigger. Must be
99
+ # called within an authorization_trigger block:
100
+ #
101
+ # authorization_trigger("current_user.signed_in?") do
102
+ # unrestricted_area %r{/top/secret/path/}
103
+ # end
104
+ #
105
+ # +path+ can be either a String or a Regexp. If a String, it will
106
+ # be converted to a Regexp.
107
+ #
108
+ def unrestricted_area(path)
109
+ add_path_to_trigger_paths path, :unrestricted
110
+ end
111
+
112
+ private
113
+
114
+ def add_path_to_trigger_paths(path, type)
115
+ path = Regexp.new(path) if path.is_a? String
116
+
117
+ self.authorization_trigger_paths ||= {}
118
+ (self.authorization_trigger_paths[type] ||= []) << path
119
+ end
120
+ end
121
+
122
+ # This module contains methods which will be added as instance methods
123
+ # to your controller.
124
+ #
125
+ module InstanceMethods
126
+
127
+ # A +before_filter+ that checks if authorization is needed to access
128
+ # the current path. If authorization is needed, and it fails, the user
129
+ # is redirected to the safe_zone, or to root_path if safe_zone is not defined.
130
+ # It also sets +flash#notice+ with a message, which should be defined
131
+ # in a locale file with the key +:restricted+.
132
+ #
133
+ def area_51_check_access
134
+ if entering_unauthorized_area?(request.path)
135
+ flash.notice = I18n.t(:restricted)
136
+ redirect_to self.class.safe_zone || self.root_path
137
+ end
138
+ end
139
+
140
+ # Checks to see if the user is entering a restricted zone. It does this
141
+ # by enumerating through the list of configured authorization triggers
142
+ # for this controller. If one of them returns +true+, the paths tied
143
+ # to the trigger are checked against the current path.
144
+ #
145
+ # If the current path matches one of the paths configured for the trigger, and the access type
146
+ # for the trigger is +:restricted+, the method returns +true+. If it is
147
+ # +:unrestricted+, or the current path is the same as the safe_zone, it returns +false.
148
+ #
149
+ def entering_unauthorized_area?(path)
150
+ return false if path == self.class.safe_zone
151
+
152
+ self.class.authorization_triggers.any? do |trigger, paths|
153
+ if authorization_triggered? trigger
154
+
155
+ # Now that we know an authorization should be performed, let's do it!
156
+
157
+ if path.match(combined_paths(paths[:restricted]))
158
+ true
159
+ elsif path.match(combined_paths(paths[:unrestricted]))
160
+ false
161
+ else
162
+ trigger.default_access == :restricted
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ private
169
+
170
+ def combined_paths(paths)
171
+ paths ||= []
172
+ Regexp.union(*(paths.compact))
173
+ end
174
+
175
+ def authorization_triggered?(trigger)
176
+ trigger = trigger.body
177
+
178
+ case
179
+ when trigger.is_a?(String)
180
+ result = eval trigger
181
+ when trigger.respond_to?(:call)
182
+ result = trigger.call
183
+ else
184
+ result = trigger
185
+ end
186
+
187
+ !!result
188
+ end
189
+ end
190
+ end
191
+
192
+ ActionController::Base.send :extend, Area51::ApiMethod
@@ -0,0 +1,16 @@
1
+ module Area51
2
+ class AuthorizationTrigger
3
+ attr_accessor :default_access
4
+ attr_accessor :body
5
+
6
+ def initialize(body, default_access = nil)
7
+ @body = body
8
+
9
+ if [:restricted, :unrestricted].include?(default_access)
10
+ @default_access = default_access
11
+ else
12
+ @default_access = :restricted
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module Area51
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: area_51
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Chad Boyd
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-03-04 00:00:00 -06:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Area51 allows you to define restricted and unrestricted sections of your application by defining paths in your controllers.
18
+ email:
19
+ - hoverlover@gmail.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files: []
25
+
26
+ files:
27
+ - .gitignore
28
+ - Gemfile
29
+ - README.md
30
+ - Rakefile
31
+ - area_51.gemspec
32
+ - lib/area_51.rb
33
+ - lib/area_51/authorization_trigger.rb
34
+ - lib/area_51/version.rb
35
+ has_rdoc: true
36
+ homepage: https://github.com/hoverlover
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.5.0
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Gem used for simple path-based access control.
63
+ test_files: []
64
+