cbac 0.6.1 → 0.6.2

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.
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