cbac 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/Manifest +71 -70
  2. data/README.rdoc +51 -51
  3. data/Rakefile +39 -39
  4. data/cbac.gemspec +30 -30
  5. data/config/cbac/context_roles.rb +21 -21
  6. data/config/cbac/privileges.rb +50 -50
  7. data/context_roles.rb +21 -21
  8. data/init.rb +3 -3
  9. data/lib/cbac.rb +132 -132
  10. data/lib/cbac/cbac_pristine/pristine.rb +138 -138
  11. data/lib/cbac/cbac_pristine/pristine_file.rb +179 -173
  12. data/lib/cbac/cbac_pristine/pristine_permission.rb +205 -205
  13. data/lib/cbac/cbac_pristine/pristine_role.rb +43 -42
  14. data/lib/cbac/config.rb +9 -9
  15. data/lib/cbac/context_role.rb +27 -27
  16. data/lib/cbac/generic_role.rb +7 -6
  17. data/lib/cbac/known_permission.rb +15 -14
  18. data/lib/cbac/membership.rb +3 -3
  19. data/lib/cbac/permission.rb +5 -5
  20. data/lib/cbac/privilege.rb +117 -117
  21. data/lib/cbac/privilege_new_api.rb +56 -56
  22. data/lib/cbac/privilege_set.rb +29 -29
  23. data/lib/cbac/privilege_set_record.rb +6 -6
  24. data/lib/cbac/setup.rb +37 -37
  25. data/lib/generators/cbac/USAGE +33 -33
  26. data/lib/generators/cbac/cbac_generator.rb +75 -75
  27. data/lib/generators/cbac/copy_files/config/cbac.pristine +2 -2
  28. data/lib/generators/cbac/copy_files/config/context_roles.rb +17 -17
  29. data/lib/generators/cbac/copy_files/config/privileges.rb +25 -25
  30. data/lib/generators/cbac/copy_files/controllers/generic_roles_controller.rb +30 -30
  31. data/lib/generators/cbac/copy_files/controllers/memberships_controller.rb +22 -22
  32. data/lib/generators/cbac/copy_files/controllers/permissions_controller.rb +61 -61
  33. data/lib/generators/cbac/copy_files/controllers/upgrade_controller.rb +23 -23
  34. data/lib/generators/cbac/copy_files/fixtures/cbac_generic_roles.yml +9 -9
  35. data/lib/generators/cbac/copy_files/fixtures/cbac_memberships.yml +8 -8
  36. data/lib/generators/cbac/copy_files/fixtures/cbac_permissions.yml +8 -8
  37. data/lib/generators/cbac/copy_files/initializers/cbac_config.rb +4 -4
  38. data/lib/generators/cbac/copy_files/migrate/create_cbac_from_scratch.rb +59 -59
  39. data/lib/generators/cbac/copy_files/migrate/create_cbac_upgrade_path.rb +40 -40
  40. data/lib/generators/cbac/copy_files/stylesheets/cbac.css +65 -65
  41. data/lib/generators/cbac/copy_files/tasks/cbac.rake +345 -345
  42. data/lib/generators/cbac/copy_files/views/generic_roles/index.html.erb +58 -58
  43. data/lib/generators/cbac/copy_files/views/layouts/cbac.html.erb +18 -18
  44. data/lib/generators/cbac/copy_files/views/memberships/_update.html.erb +11 -11
  45. data/lib/generators/cbac/copy_files/views/memberships/index.html.erb +23 -23
  46. data/lib/generators/cbac/copy_files/views/permissions/_update_context_role.html.erb +11 -11
  47. data/lib/generators/cbac/copy_files/views/permissions/_update_generic_role.html.erb +11 -11
  48. data/lib/generators/cbac/copy_files/views/permissions/index.html.erb +39 -39
  49. data/lib/generators/cbac/copy_files/views/upgrade/index.html.erb +31 -31
  50. data/migrations/20110211105533_add_pristine_files_to_cbac_upgrade_path.rb +16 -16
  51. data/privileges.rb +50 -50
  52. data/spec/cbac_pristine_file_spec.rb +329 -329
  53. data/spec/cbac_pristine_permission_spec.rb +358 -358
  54. data/spec/cbac_pristine_role_spec.rb +85 -85
  55. data/spec/rcov.opts +1 -1
  56. data/spec/spec.opts +4 -4
  57. data/spec/spec_helper.rb +11 -11
  58. data/tasks/cbac.rake +345 -345
  59. data/test/db/test.sqlite3 +0 -0
  60. data/test/fixtures/cbac_generic_roles.yml +9 -9
  61. data/test/fixtures/cbac_memberships.yml +8 -8
  62. data/test/fixtures/cbac_permissions.yml +14 -14
  63. data/test/fixtures/cbac_privilege_set.yml +18 -18
  64. data/test/test_cbac_actions.rb +71 -71
  65. data/test/test_cbac_authorize_context_roles.rb +39 -39
  66. data/test/test_cbac_authorize_generic_roles.rb +36 -36
  67. data/test/test_cbac_context_role.rb +50 -50
  68. data/test/test_cbac_privilege.rb +151 -151
  69. data/test/test_cbac_privilege_set.rb +50 -50
  70. data/test/test_helper.rb +28 -28
  71. metadata +33 -49
@@ -1,173 +1,179 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_role'))
2
- require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_permission'))
3
-
4
- module Cbac
5
- module CbacPristine
6
- class AbstractPristineFile < ActiveRecord::Base
7
- set_table_name "cbac_pristine_files"
8
- attr_accessor :permissions, :generic_roles
9
-
10
- def initialize(*args)
11
- super(*args)
12
- @generic_roles = []
13
- @context_roles = []
14
- @permissions = []
15
- end
16
-
17
- def parse(use_db = true)
18
- @generic_roles = []
19
- @context_roles = []
20
- @permissions = []
21
-
22
- f = File.open(file_name, "r")
23
- last_row_number = -1
24
- f.each_with_index do |l, line_number|
25
- pristine_permission = PristinePermission.new
26
- pristine_permission.pristine_file = self
27
- permission_line = l.chomp
28
- # if this is not a line we can convert into a permission, go to next line (or fail.....)
29
- next unless is_pristine_permission_line?(permission_line, line_number)
30
-
31
- # check if the row numbers are constructed properly.
32
- # this is needed for migration purposes, each permission should have an unique and persistent row number
33
- header_match = permission_line.match(/^(\d+):([\+-x]|=>):\s*/)
34
- pristine_permission.line_number = header_match.captures[0].to_i
35
- if pristine_permission.line_number != last_row_number.succ
36
- raise SyntaxError, "Error: row numbers in pristine file do not increase monotonously"
37
- else
38
- last_row_number = pristine_permission.line_number
39
- end
40
- pristine_permission.operation = header_match.captures[1]
41
- # parse the role and privilege set name
42
- pristine_permission.privilege_set_name = parse_privilege_set_name(permission_line, line_number)
43
- pristine_permission.pristine_role = parse_role(permission_line, line_number, use_db)
44
- # it's pristine, so changes should be treated as such
45
- # if a permission was created and later revoked, we should remove the pristine line which was created before
46
- case pristine_permission.operation
47
- when '+'
48
- @permissions.push(pristine_permission)
49
- when '-'
50
- permission_to_delete = nil
51
- #check if this is actually a permission that can be revoked.
52
- @permissions.each do |known_permission|
53
- if known_permission.privilege_set_name == pristine_permission.privilege_set_name and known_permission.pristine_role.name == pristine_permission.pristine_role.name
54
- permission_to_delete = known_permission
55
- break
56
- end
57
- end
58
- if permission_to_delete.nil?
59
- raise SyntaxError, "Error: trying to remove a privilege set with \"#{permission_line}\" on line #{(line_number + 1).to_s}, but this privilege set wasn't created!"
60
- else
61
- @permissions.push(pristine_permission)
62
- end
63
- when 'x', '=>'
64
- raise NotImplementedError, "Using an x or => in a pristine file is not implemented yet"
65
- end
66
- end
67
- end
68
-
69
- def is_pristine_permission_line?(line, line_number)
70
- if line.match(/^\s*(\d+)\s*:\s*([\+-x]|=>)\s*:(\s*[A-Za-z]+\(\s*[A-Za-z_]*\s*\))+\s*\Z/) #looks like pristine line.....
71
- return true
72
- end
73
- if line.match(/^\s*(#.*|\s*)$/) # line is whitespace or comment line
74
- return false
75
- end
76
- raise SyntaxError, "Error: garbage found in input file on line #{(line_number + 1).to_s}" #line is rubbish
77
- end
78
-
79
- def parse_privilege_set_name(line, line_number)
80
- if match_data= line.match(/^.*PrivilegeSet\(\s*([A-Za-z0-9_]+)\s*\)\s*/)
81
- return match_data.captures[0]
82
- end
83
- raise SyntaxError, "Error: PrivilegeSet expected, but found: \"#{line}\" on line #{(line_number + 1).to_s}"
84
- end
85
-
86
- def parse_role(line, line_number, use_db = true)
87
- raise NotImplementedError("Error: the AbstractPristineFile cannot parse roles, use a PristineFile or GenericPristineFile instead")
88
- end
89
-
90
- def permission_set
91
- permission_set = Array.new(@permissions)
92
- @permissions.each do |pristine_permission|
93
- case pristine_permission.operation
94
- when '+'
95
- permission_set.push(pristine_permission)
96
- when '-'
97
- permission_to_delete = nil
98
- #check if this is actually a permission that can be revoked.
99
- permission_set.each do |known_permission|
100
- if known_permission.privilege_set_name == pristine_permission.privilege_set_name and known_permission.pristine_role.name == pristine_permission.pristine_role.name and known_permission.operation == '+'
101
- permission_to_delete = known_permission
102
- break
103
- end
104
- end
105
- if permission_to_delete.nil?
106
- raise ArgumentError, "Error: trying to remove permission #{pristine_permission.privilege_set_name}\" for #{pristine_permission.pristine_role.name}, but this permission wasn't created!"
107
- else
108
- permission_set.delete(permission_to_delete)
109
- permission_set.delete(pristine_permission)
110
- end
111
- when 'x', '=>'
112
- raise NotImplementedError, "Using an x or => in a pristine file is not implemented yet"
113
- end
114
- end
115
- permission_set
116
- end
117
-
118
- end
119
-
120
-
121
- class PristineFile < Cbac::CbacPristine::AbstractPristineFile
122
- def parse_role(line, line_number, use_db = true)
123
- if line.match(/^.*Admin\(\)/)
124
- return @admin_role unless @admin_role.nil?
125
-
126
- @admin_role = PristineRole.admin_role(use_db)
127
- @generic_roles.push(@admin_role)
128
- return @admin_role
129
- end
130
- if context_role_name = line.match(/^.*ContextRole\(\s*([A-Za-z0-9_]+)\s*\)/)
131
- # NOTE: the 0 for an ID is very important! In CBAC a context role permission MUST have 0 as generic_role_id
132
- # if not, the context role is not found by CBAC and thus will not work
133
-
134
- # this may be a context role that's already in the database
135
- context_role = use_db ? PristineRole.first(:conditions => {:role_type => PristineRole.ROLE_TYPES[:context], :name => context_role_name.captures[0]}) : nil
136
-
137
- # this may still be a context role we've seen before...
138
- context_role = @context_roles.select do |cr| cr.role_type == PristineRole.ROLE_TYPES[:context] and cr.name == context_role_name.captures[0] end.first if context_role.nil?
139
-
140
- if context_role.nil?
141
- # this is a never-before-seen context role
142
- context_role = PristineRole.new(:role_id => 0, :role_type => PristineRole.ROLE_TYPES[:context], :name => context_role_name.captures[0]) if context_role.nil?
143
- context_role.save if use_db
144
- @context_roles.push context_role
145
- end
146
- return context_role
147
- end
148
- raise SyntaxError, "Error: ContextRole or Admin expected, but found: \"#{line}\" on line #{(line_number + 1).to_s}"
149
- end
150
-
151
-
152
- end
153
-
154
- class GenericPristineFile < Cbac::CbacPristine::AbstractPristineFile
155
- def parse_role(line, line_number, use_db = true)
156
- # generic pristine files differ, because they create generic roles when needed
157
- # but those generic roles should be re-used if one with that name already exists
158
- if generic_role= line.match(/^.*GenericRole\(\s*([A-Za-z0-9_]+)\s*\)/)
159
- @generic_roles.each do |generic_cbac_role|
160
- if generic_cbac_role.name == generic_role.captures[0]
161
- return generic_cbac_role
162
- end
163
- end
164
- role = use_db ? PristineRole.first(:conditions => {:role_type => PristineRole.ROLE_TYPES[:generic], :name => generic_role.captures[0]}) : nil
165
- role = PristineRole.new(:role_id => @generic_roles.length + 2, :role_type => PristineRole.ROLE_TYPES[:generic], :name => generic_role.captures[0]) if role.nil?
166
- @generic_roles.push(role)
167
- return role
168
- end
169
- raise SyntaxError, "Error: GenericRole expected, but found: \"#{line}\" on line #{(line_number + 1).to_s}"
170
- end
171
- end
172
- end
173
- end
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_role'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_permission'))
3
+
4
+ module Cbac
5
+ module CbacPristine
6
+ class AbstractPristineFile < ActiveRecord::Base
7
+ set_table_name "cbac_pristine_files"
8
+ attr_accessor :permissions, :generic_roles
9
+ attr_readonly :file_name
10
+
11
+ def initialize(*args)
12
+ super(*args)
13
+ @generic_roles = []
14
+ @context_roles = []
15
+ @permissions = []
16
+ end
17
+
18
+ def parse(use_db = true)
19
+ @generic_roles = []
20
+ @context_roles = []
21
+ @permissions = []
22
+
23
+ f = File.open(file_name, "r")
24
+ last_row_number = -1
25
+ f.each_with_index do |l, line_number|
26
+ pristine_permission = PristinePermission.new
27
+ pristine_permission.pristine_file = self
28
+ permission_line = l.chomp
29
+ # if this is not a line we can convert into a permission, go to next line (or fail.....)
30
+ next unless is_pristine_permission_line?(permission_line, line_number)
31
+
32
+ # check if the row numbers are constructed properly.
33
+ # this is needed for migration purposes, each permission should have an unique and persistent row number
34
+ header_match = permission_line.match(/^(\d+):([\+-x]|=>):\s*/)
35
+ pristine_permission.line_number = header_match.captures[0].to_i
36
+ if pristine_permission.line_number != last_row_number.succ
37
+ raise SyntaxError, "Error: row numbers in pristine file do not increase monotonously"
38
+ else
39
+ last_row_number = pristine_permission.line_number
40
+ end
41
+ pristine_permission.operation = header_match.captures[1]
42
+ # parse the role and privilege set name
43
+ pristine_permission.privilege_set_name = parse_privilege_set_name(permission_line, line_number)
44
+ pristine_permission.pristine_role = parse_role(permission_line, line_number, use_db)
45
+ # it's pristine, so changes should be treated as such
46
+ # if a permission was created and later revoked, we should remove the pristine line which was created before
47
+ case pristine_permission.operation
48
+ when '+'
49
+ @permissions.push(pristine_permission)
50
+ when '-'
51
+ permission_to_delete = nil
52
+ #check if this is actually a permission that can be revoked.
53
+ @permissions.each do |known_permission|
54
+ if known_permission.privilege_set_name == pristine_permission.privilege_set_name and known_permission.pristine_role.name == pristine_permission.pristine_role.name
55
+ permission_to_delete = known_permission
56
+ break
57
+ end
58
+ end
59
+ if permission_to_delete.nil?
60
+ raise SyntaxError, "Error: trying to remove a privilege set with \"#{permission_line}\" on line #{(line_number + 1).to_s}, but this privilege set wasn't created!"
61
+ else
62
+ @permissions.push(pristine_permission)
63
+ end
64
+ when 'x', '=>'
65
+ raise NotImplementedError, "Using an x or => in a pristine file is not implemented yet"
66
+ end
67
+ end
68
+ end
69
+
70
+ def is_pristine_permission_line?(line, line_number)
71
+ if line.match(/^\s*(\d+)\s*:\s*([\+-x]|=>)\s*:(\s*[A-Za-z]+\(\s*[A-Za-z_]*\s*\))+\s*\Z/) #looks like pristine line.....
72
+ return true
73
+ end
74
+ if line.match(/^\s*(#.*|\s*)$/) # line is whitespace or comment line
75
+ return false
76
+ end
77
+ raise SyntaxError, "Error: garbage found in input file on line #{(line_number + 1).to_s}" #line is rubbish
78
+ end
79
+
80
+ def parse_privilege_set_name(line, line_number)
81
+ if match_data= line.match(/^.*PrivilegeSet\(\s*([A-Za-z0-9_]+)\s*\)\s*/)
82
+ return match_data.captures[0]
83
+ end
84
+ raise SyntaxError, "Error: PrivilegeSet expected, but found: \"#{line}\" on line #{(line_number + 1).to_s}"
85
+ end
86
+
87
+ def parse_role(line, line_number, use_db = true)
88
+ raise NotImplementedError("Error: the AbstractPristineFile cannot parse roles, use a PristineFile or GenericPristineFile instead")
89
+ end
90
+
91
+ def permission_set
92
+ permission_set = Array.new(@permissions)
93
+ @permissions.each do |pristine_permission|
94
+ case pristine_permission.operation
95
+ when '+'
96
+ permission_set.push(pristine_permission)
97
+ when '-'
98
+ permission_to_delete = nil
99
+ #check if this is actually a permission that can be revoked.
100
+ permission_set.each do |known_permission|
101
+ if known_permission.privilege_set_name == pristine_permission.privilege_set_name and known_permission.pristine_role.name == pristine_permission.pristine_role.name and known_permission.operation == '+'
102
+ permission_to_delete = known_permission
103
+ break
104
+ end
105
+ end
106
+ if permission_to_delete.nil?
107
+ raise ArgumentError, "Error: trying to remove permission #{pristine_permission.privilege_set_name}\" for #{pristine_permission.pristine_role.name}, but this permission wasn't created!"
108
+ else
109
+ permission_set.delete(permission_to_delete)
110
+ permission_set.delete(pristine_permission)
111
+ end
112
+ when 'x', '=>'
113
+ raise NotImplementedError, "Using an x or => in a pristine file is not implemented yet"
114
+ end
115
+ end
116
+ permission_set
117
+ end
118
+
119
+ end
120
+
121
+
122
+ class PristineFile < Cbac::CbacPristine::AbstractPristineFile
123
+ def parse_role(line, line_number, use_db = true)
124
+ if line.match(/^.*Admin\(\)/)
125
+ return @admin_role unless @admin_role.nil?
126
+
127
+ @admin_role = PristineRole.admin_role(use_db)
128
+ @generic_roles.push(@admin_role)
129
+ return @admin_role
130
+ end
131
+ if context_role_name = line.match(/^.*ContextRole\(\s*([A-Za-z0-9_]+)\s*\)/)
132
+ # NOTE: the 0 for an ID is very important! In CBAC a context role permission MUST have 0 as generic_role_id
133
+ # if not, the context role is not found by CBAC and thus will not work
134
+
135
+ # this may be a context role that's already in the database
136
+ context_role = use_db ? PristineRole.first(:conditions => {:role_type => PristineRole.ROLE_TYPES[:context], :name => context_role_name.captures[0]}) : nil
137
+
138
+ # this may still be a context role we've seen before...
139
+ context_role = @context_roles.select do |cr| cr.role_type == PristineRole.ROLE_TYPES[:context] and cr.name == context_role_name.captures[0] end.first if context_role.nil?
140
+
141
+ if context_role.nil?
142
+ # this is a never-before-seen context role
143
+ context_role = PristineRole.new(:role_id => 0, :role_type => PristineRole.ROLE_TYPES[:context], :name => context_role_name.captures[0]) if context_role.nil?
144
+ context_role.save if use_db
145
+ @context_roles.push context_role
146
+ end
147
+ return context_role
148
+ end
149
+ raise SyntaxError, "Error: ContextRole or Admin expected, but found: \"#{line}\" on line #{(line_number + 1).to_s}"
150
+ end
151
+
152
+
153
+ end
154
+
155
+ class GenericPristineFile < Cbac::CbacPristine::AbstractPristineFile
156
+ def parse_role(line, line_number, use_db = true)
157
+ # generic pristine files differ, because they create generic roles when needed
158
+ # but those generic roles should be re-used if one with that name already exists
159
+ if generic_role= line.match(/^.*GenericRole\(\s*([A-Za-z0-9_]+)\s*\)/)
160
+ @generic_roles.each do |generic_cbac_role|
161
+ if generic_cbac_role.name == generic_role.captures[0]
162
+ return generic_cbac_role
163
+ end
164
+ end
165
+ role = use_db ? PristineRole.first(:conditions => {:role_type => PristineRole.ROLE_TYPES[:generic], :name => generic_role.captures[0]}) : nil
166
+
167
+ if role.nil?
168
+ role = PristineRole.new(:role_id => @generic_roles.length + 2, :role_type => PristineRole.ROLE_TYPES[:generic], :name => generic_role.captures[0])
169
+ role.save if use_db
170
+ end
171
+
172
+ @generic_roles.push(role)
173
+ return role
174
+ end
175
+ raise SyntaxError, "Error: GenericRole expected, but found: \"#{line}\" on line #{(line_number + 1).to_s}"
176
+ end
177
+ end
178
+ end
179
+ end
@@ -1,205 +1,205 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_role'))
2
- require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_permission'))
3
- require 'active_record'
4
-
5
- module Cbac
6
- module CbacPristine
7
- class PristinePermission < ActiveRecord::Base
8
- set_table_name 'cbac_staged_permissions'
9
-
10
- belongs_to :pristine_role, :class_name => "Cbac::CbacPristine::PristineRole"
11
- belongs_to :pristine_file, :class_name => "Cbac::CbacPristine::AbstractPristineFile"
12
-
13
- def privilege_set
14
- Cbac::PrivilegeSetRecord.first(:conditions => {:name => privilege_set_name})
15
- end
16
-
17
- def operation_string
18
- case operation
19
- when '+'
20
- return "add"
21
- when '-'
22
- return "revoke"
23
- else
24
- return "unknown"
25
- end
26
- end
27
-
28
- #convert this pristine line to a yml statement which can be used to create a yml fixtures file
29
- #executing this statement will result in one cbac_permission in the DB
30
- def to_yml_fixture(fixture_id = nil)
31
- raise ArgumentError, "Error: cannot convert line #{line_number.to_s} to yml because the role is not specified" if pristine_role.nil?
32
- raise ArgumentError, "Error: cannot convert line #{line_number.to_s} to yml because the privilege_set_name is not specified" if privilege_set_name.blank?
33
-
34
- fixture_id = line_number if fixture_id.nil?
35
-
36
- yml = "cbac_permission_00" << fixture_id.to_s << ":\n"
37
- yml << " id: " << fixture_id.to_s << "\n"
38
- yml << " context_role: "
39
- yml << pristine_role.name if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
40
- yml << "\n"
41
- yml << " generic_role_id: " << pristine_role.role_id.to_s << "\n"
42
- yml << " privilege_set_id: <%= Cbac::PrivilegeSetRecord.find(:first, :conditions => {:name => '" << privilege_set_name << "'}).id %>\n"
43
- yml << " created_at: " << Time.now.strftime("%Y-%m-%d %H:%M:%S") << "\n"
44
- yml << " updated_at: " << Time.now.strftime("%Y-%m-%d %H:%M:%S") << "\n"
45
- yml << "\n"
46
- end
47
-
48
- # checks if the current cbac permissions contains a permission which is exactly like this one
49
- def cbac_permission_exists?
50
- if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
51
- Cbac::Permission.count(:joins => [:privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :context_role => pristine_role.name}) > 0
52
- else
53
- Cbac::Permission.count(:joins => [:generic_role, :privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :cbac_generic_roles => {:name => pristine_role.name}}) > 0
54
- end
55
- end
56
-
57
- # checks if a pristine permission with the same properties(except line_number) exists in the database
58
- def exists?
59
- Cbac::CbacPristine::PristinePermission.count(:conditions => {:privilege_set_name => privilege_set_name, :pristine_role_id => pristine_role_id, :operation => operation}) > 0
60
- end
61
-
62
- # checks if a pristine permission with the exact same properties(except line_number), but the reverse operation exists in the database
63
- def reverse_exists?
64
- Cbac::CbacPristine::PristinePermission.count(:conditions => {:privilege_set_name => privilege_set_name, :pristine_role_id => pristine_role_id, :operation => reverse_operation}) > 0
65
- end
66
-
67
- # delete the pristine permission with the reverse operation of this one
68
- def delete_reverse_permission
69
- reverse_permission = Cbac::CbacPristine::PristinePermission.first(:conditions => {:privilege_set_name => privilege_set_name, :pristine_role_id => pristine_role_id, :operation => reverse_operation})
70
- reverse_permission.delete
71
- end
72
-
73
- # get the reverse operation of this one
74
- def reverse_operation
75
- case operation
76
- when '+'
77
- return '-'
78
- when '-'
79
- return '+'
80
- when 'x', '=>'
81
- raise NotImplementedError, "Error: using an x or => in a pristine file is not implemented yet"
82
- else
83
- raise ArgumentError, "Error: invalid operation #{operation} is used in the pristine file"
84
- end
85
- end
86
-
87
- # checks if the known_permissions table has an entry for this permission
88
- def known_permission_exists?
89
- Cbac::KnownPermission.count(:conditions => {:permission_type => pristine_role.known_permission_type, :permission_number => line_number}) > 0
90
- end
91
-
92
- # accept this permission and apply to the current cbac permission set
93
- def accept
94
- case operation
95
- when '+'
96
- handle_grant_permission
97
- when '-'
98
- handle_revoke_permission
99
- when 'x', '=>'
100
- raise NotImplementedError, "Error: using an x or => in a pristine file is not implemented yet"
101
- else
102
- raise ArgumentError, "Error: invalid operation #{operation} is used in the pristine file"
103
- end
104
- PristinePermission.delete(id) unless id.nil?
105
- end
106
-
107
- # reject this permission, but register it as a known permission. The user actually rejected this himself.
108
- def reject
109
- register_change
110
- PristinePermission.delete(id) unless id.nil?
111
- end
112
-
113
- # add this permission to the cbac permission set, unless it already exists
114
- def handle_grant_permission
115
- return if cbac_permission_exists?
116
-
117
- permission = Cbac::Permission.new
118
- permission.privilege_set = privilege_set
119
-
120
- if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
121
- permission.context_role = pristine_role.name
122
- else
123
- generic_role = Cbac::GenericRole.first(:conditions => {:name => pristine_role.name})
124
- permission.generic_role = generic_role.nil? ? Cbac::GenericRole.create(:name => pristine_role.name, :remarks => "Autogenerated by Cbac loading / upgrade system") : generic_role
125
- end
126
-
127
- register_change if permission.save
128
- permission
129
- end
130
-
131
- # revoke this permission from the current permission set, raises an error if it doesn't exist yet
132
- def handle_revoke_permission
133
- raise ArgumentError, "Error: trying to revoke permission #{privilege_set_name} for #{pristine_role.name}, but this permission does not exist" unless cbac_permission_exists?
134
-
135
- if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
136
- permission = Cbac::Permission.first(:joins => [:privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :context_role => pristine_role.name})
137
- else
138
- permission = Cbac::Permission.first(:joins => [:generic_role, :privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :cbac_generic_roles => {:name => pristine_role.name}})
139
- end
140
-
141
- register_change if permission.destroy
142
- end
143
-
144
- # register this permission as a known permission
145
- def register_change
146
- pristine_file.parse(true) unless pristine_file.permissions.present?
147
- line_numbers = [line_number]
148
-
149
- pristine_file.permissions.each do |permission|
150
- line_numbers.push(permission.line_number) if permission.privilege_set_name == self.privilege_set_name && permission.pristine_role_id = self.pristine_role_id && permission.line_number < self.line_number
151
- end
152
-
153
- line_numbers.each do |number|
154
- Cbac::KnownPermission.create(:permission_number => number, :permission_type => pristine_role.known_permission_type) if Cbac::KnownPermission.count(:conditions => {:permission_number => number, :permission_type => pristine_role.known_permission_type}) == 0
155
- end
156
-
157
- end
158
-
159
- # add this permission to the staging area
160
- def stage
161
- raise ArgumentError, "Error: this staged permission already exists. Record with line number #{line_number} is a duplicate permission." if exists?
162
- return if known_permission_exists?
163
-
164
- if operation == '-'
165
- # if the reverse permission is also staged, remove it and do not add this one
166
- if reverse_exists?
167
- delete_reverse_permission
168
- return
169
- end
170
- # if this is an attempt to revoke a permission, it should exist as a real cbac permission!
171
- save if cbac_permission_exists?
172
- elsif operation == '+'
173
- # if this is an attempt to add a permission, it MUST not exist yet
174
- save unless cbac_permission_exists?
175
- end
176
- end
177
-
178
-
179
-
180
- # clear the staging area of all generic pristine permissions
181
- def self.delete_generic_permissions
182
- generic_staged_permissions = all(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type = ?", PristineRole.ROLE_TYPES[:generic]])
183
- generic_staged_permissions.each do |permission|
184
- delete(permission.id)
185
- end
186
- end
187
-
188
- # clear the staging area of all non generic permissions
189
- def self.delete_non_generic_permissions
190
- staged_permissions = all(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type != ?", PristineRole.ROLE_TYPES[:generic]])
191
- staged_permissions.each do |permission|
192
- delete(permission.id)
193
- end
194
- end
195
-
196
- def self.count_generic_permissions
197
- count(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type = ?", PristineRole.ROLE_TYPES[:generic]])
198
- end
199
-
200
- def self.count_non_generic_permissions
201
- count(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type != ?", PristineRole.ROLE_TYPES[:generic]])
202
- end
203
- end
204
- end
205
- end
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_role'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'pristine_permission'))
3
+ require 'active_record'
4
+
5
+ module Cbac
6
+ module CbacPristine
7
+ class PristinePermission < ActiveRecord::Base
8
+ set_table_name 'cbac_staged_permissions'
9
+
10
+ belongs_to :pristine_role, :class_name => "Cbac::CbacPristine::PristineRole"
11
+ belongs_to :pristine_file, :class_name => "Cbac::CbacPristine::AbstractPristineFile"
12
+
13
+ def privilege_set
14
+ Cbac::PrivilegeSetRecord.first(:conditions => {:name => privilege_set_name})
15
+ end
16
+
17
+ def operation_string
18
+ case operation
19
+ when '+'
20
+ return "add"
21
+ when '-'
22
+ return "revoke"
23
+ else
24
+ return "unknown"
25
+ end
26
+ end
27
+
28
+ #convert this pristine line to a yml statement which can be used to create a yml fixtures file
29
+ #executing this statement will result in one cbac_permission in the DB
30
+ def to_yml_fixture(fixture_id = nil)
31
+ raise ArgumentError, "Error: cannot convert line #{line_number.to_s} to yml because the role is not specified" if pristine_role.nil?
32
+ raise ArgumentError, "Error: cannot convert line #{line_number.to_s} to yml because the privilege_set_name is not specified" if privilege_set_name.blank?
33
+
34
+ fixture_id = line_number if fixture_id.nil?
35
+
36
+ yml = "cbac_permission_00" << fixture_id.to_s << ":\n"
37
+ yml << " id: " << fixture_id.to_s << "\n"
38
+ yml << " context_role: "
39
+ yml << pristine_role.name if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
40
+ yml << "\n"
41
+ yml << " generic_role_id: " << pristine_role.role_id.to_s << "\n"
42
+ yml << " privilege_set_id: <%= Cbac::PrivilegeSetRecord.find(:first, :conditions => {:name => '" << privilege_set_name << "'}).id %>\n"
43
+ yml << " created_at: " << Time.now.strftime("%Y-%m-%d %H:%M:%S") << "\n"
44
+ yml << " updated_at: " << Time.now.strftime("%Y-%m-%d %H:%M:%S") << "\n"
45
+ yml << "\n"
46
+ end
47
+
48
+ # checks if the current cbac permissions contains a permission which is exactly like this one
49
+ def cbac_permission_exists?
50
+ if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
51
+ Cbac::Permission.count(:joins => [:privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :context_role => pristine_role.name}) > 0
52
+ else
53
+ Cbac::Permission.count(:joins => [:generic_role, :privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :cbac_generic_roles => {:name => pristine_role.name}}) > 0
54
+ end
55
+ end
56
+
57
+ # checks if a pristine permission with the same properties(except line_number) exists in the database
58
+ def exists?
59
+ Cbac::CbacPristine::PristinePermission.count(:conditions => {:privilege_set_name => privilege_set_name, :pristine_role_id => pristine_role_id, :operation => operation}) > 0
60
+ end
61
+
62
+ # checks if a pristine permission with the exact same properties(except line_number), but the reverse operation exists in the database
63
+ def reverse_exists?
64
+ Cbac::CbacPristine::PristinePermission.count(:conditions => {:privilege_set_name => privilege_set_name, :pristine_role_id => pristine_role_id, :operation => reverse_operation}) > 0
65
+ end
66
+
67
+ # delete the pristine permission with the reverse operation of this one
68
+ def delete_reverse_permission
69
+ reverse_permission = Cbac::CbacPristine::PristinePermission.first(:conditions => {:privilege_set_name => privilege_set_name, :pristine_role_id => pristine_role_id, :operation => reverse_operation})
70
+ reverse_permission.delete
71
+ end
72
+
73
+ # get the reverse operation of this one
74
+ def reverse_operation
75
+ case operation
76
+ when '+'
77
+ return '-'
78
+ when '-'
79
+ return '+'
80
+ when 'x', '=>'
81
+ raise NotImplementedError, "Error: using an x or => in a pristine file is not implemented yet"
82
+ else
83
+ raise ArgumentError, "Error: invalid operation #{operation} is used in the pristine file"
84
+ end
85
+ end
86
+
87
+ # checks if the known_permissions table has an entry for this permission
88
+ def known_permission_exists?
89
+ Cbac::KnownPermission.count(:conditions => {:permission_type => pristine_role.known_permission_type, :permission_number => line_number}) > 0
90
+ end
91
+
92
+ # accept this permission and apply to the current cbac permission set
93
+ def accept
94
+ case operation
95
+ when '+'
96
+ handle_grant_permission
97
+ when '-'
98
+ handle_revoke_permission
99
+ when 'x', '=>'
100
+ raise NotImplementedError, "Error: using an x or => in a pristine file is not implemented yet"
101
+ else
102
+ raise ArgumentError, "Error: invalid operation #{operation} is used in the pristine file"
103
+ end
104
+ PristinePermission.delete(id) unless id.nil?
105
+ end
106
+
107
+ # reject this permission, but register it as a known permission. The user actually rejected this himself.
108
+ def reject
109
+ register_change
110
+ PristinePermission.delete(id) unless id.nil?
111
+ end
112
+
113
+ # add this permission to the cbac permission set, unless it already exists
114
+ def handle_grant_permission
115
+ return if cbac_permission_exists?
116
+
117
+ permission = Cbac::Permission.new
118
+ permission.privilege_set = privilege_set
119
+
120
+ if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
121
+ permission.context_role = pristine_role.name
122
+ else
123
+ generic_role = Cbac::GenericRole.first(:conditions => {:name => pristine_role.name})
124
+ permission.generic_role = generic_role.nil? ? Cbac::GenericRole.create(:name => pristine_role.name, :remarks => "Autogenerated by Cbac loading / upgrade system") : generic_role
125
+ end
126
+
127
+ register_change if permission.save
128
+ permission
129
+ end
130
+
131
+ # revoke this permission from the current permission set, raises an error if it doesn't exist yet
132
+ def handle_revoke_permission
133
+ raise ArgumentError, "Error: trying to revoke permission #{privilege_set_name} for #{pristine_role.name}, but this permission does not exist" unless cbac_permission_exists?
134
+
135
+ if pristine_role.role_type == PristineRole.ROLE_TYPES[:context]
136
+ permission = Cbac::Permission.first(:joins => [:privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :context_role => pristine_role.name})
137
+ else
138
+ permission = Cbac::Permission.first(:joins => [:generic_role, :privilege_set], :conditions => {:cbac_privilege_set => {:name => privilege_set_name}, :cbac_generic_roles => {:name => pristine_role.name}})
139
+ end
140
+
141
+ register_change if permission.destroy
142
+ end
143
+
144
+ # register this permission as a known permission
145
+ def register_change
146
+ pristine_file.parse(true) unless pristine_file.permissions.present?
147
+ line_numbers = [line_number]
148
+
149
+ pristine_file.permissions.each do |permission|
150
+ line_numbers.push(permission.line_number) if permission.privilege_set_name == self.privilege_set_name && permission.pristine_role_id = self.pristine_role_id && permission.line_number < self.line_number
151
+ end
152
+
153
+ line_numbers.each do |number|
154
+ Cbac::KnownPermission.create(:permission_number => number, :permission_type => pristine_role.known_permission_type) if Cbac::KnownPermission.count(:conditions => {:permission_number => number, :permission_type => pristine_role.known_permission_type}) == 0
155
+ end
156
+
157
+ end
158
+
159
+ # add this permission to the staging area
160
+ def stage
161
+ raise ArgumentError, "Error: this staged permission already exists. Record with line number #{line_number} is a duplicate permission." if exists?
162
+ return if known_permission_exists?
163
+
164
+ if operation == '-'
165
+ # if the reverse permission is also staged, remove it and do not add this one
166
+ if reverse_exists?
167
+ delete_reverse_permission
168
+ return
169
+ end
170
+ # if this is an attempt to revoke a permission, it should exist as a real cbac permission!
171
+ save if cbac_permission_exists?
172
+ elsif operation == '+'
173
+ # if this is an attempt to add a permission, it MUST not exist yet
174
+ save unless cbac_permission_exists?
175
+ end
176
+ end
177
+
178
+
179
+
180
+ # clear the staging area of all generic pristine permissions
181
+ def self.delete_generic_permissions
182
+ generic_staged_permissions = all(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type = ?", PristineRole.ROLE_TYPES[:generic]])
183
+ generic_staged_permissions.each do |permission|
184
+ delete(permission.id)
185
+ end
186
+ end
187
+
188
+ # clear the staging area of all non generic permissions
189
+ def self.delete_non_generic_permissions
190
+ staged_permissions = all(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type != ?", PristineRole.ROLE_TYPES[:generic]])
191
+ staged_permissions.each do |permission|
192
+ delete(permission.id)
193
+ end
194
+ end
195
+
196
+ def self.count_generic_permissions
197
+ count(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type = ?", PristineRole.ROLE_TYPES[:generic]])
198
+ end
199
+
200
+ def self.count_non_generic_permissions
201
+ count(:joins => :pristine_role, :conditions => ["cbac_staged_roles.role_type != ?", PristineRole.ROLE_TYPES[:generic]])
202
+ end
203
+ end
204
+ end
205
+ end