cbac 0.6.1 → 0.6.2

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