mikras_utils 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5db4dc4f784bd24e9a739b4de231f2a52c6927e1b5cc4da48256bdfe318b27f3
4
- data.tar.gz: 15eb9d1dc3052833d5b8481c0043d3cb32610960ae8b781c63f5ea9f6a827d5a
3
+ metadata.gz: 3edb2b02216445f08fca3238457e20448bcb24c1dc27238ba4429dcc6814f25f
4
+ data.tar.gz: e8265ca5326412c5a793f5f056f7908c8c1e0e08945f8e309cd2cbad5347bc2e
5
5
  SHA512:
6
- metadata.gz: db57c96600c9fcd448dfd72a62e3008f59da9d91b14d1aed60c56032b68bec8e78643da77f1c2f42779466ab0a7cc4c69f5aa176b1f2fe8881eadaf990336fdb
7
- data.tar.gz: 3c9acdf983bdadeb7891bfa5211107a7a77e7c66001b1c78bdb470712ee7f727dbb98b8061a1cbf9af0516a249aa2767ad72b6f415492bd5bd7e7b8c4f881322
6
+ metadata.gz: 7eb69399a73f5a046b3ebcb9a356246ddf0b4dfbb72b13c141e2021d0f01750df3778a74c529e75e3e412925b4079038cdee7f767708410ee25e6ed14f48b1b4
7
+ data.tar.gz: 1db226b915c8ac98a5efbcde084e50d7547763489f07dbf4e6ee7291adaa5d4d69bd1ba921233fc3cf51a0a9d8671de61f8cc12f1159a830a5461b01cde45363
data/exe/mkacl CHANGED
@@ -22,9 +22,12 @@ SPEC = %(
22
22
  pollution)
23
23
 
24
24
  ROLES
25
- The following roles are recognized: LA, TA, KON, AKK. ADM is excluded
26
- because it is now a RBAC fole. PUP and NON is excluded because they are not
27
- implemented in Mikras
25
+ The following roles are recognized: RES, LA, TA, KON, AKK, CLA, CTA, ELA,
26
+ and ETA
27
+
28
+ Sagsys also defines the ADM role that is excluded because it is now a RBAC
29
+ fole, and PUP and NON that are excluded because they are not implemented in
30
+ Mikras
28
31
 
29
32
  OPTIONS
30
33
  -i,interactive
@@ -34,6 +37,10 @@ SPEC = %(
34
37
  Generate only the given modules. LIST is a comma-separated list of
35
38
  modules. The following modules are currently aavailable: id_functions,
36
39
  insert_triggers, rules, acl_functions, and role_functions
40
+
41
+ -W,no-warn
42
+ Do not emit warnings about tables in the application schema that are not
43
+ defined in the spec file
37
44
  )
38
45
 
39
46
  require 'yaml'
@@ -48,12 +55,17 @@ username ||= database || ENV['PRICK_USERNAME']
48
55
  database ||= ENV['PRICK_DATABASE']
49
56
  conn = PgConn.new database, username
50
57
 
58
+ if opts.generate?
59
+ modules = opts.generate.split(',').map(&:to_sym)
60
+ modules.each { |m| MkAcl::Generator::MODULES.include?(m) or ShellOpts.error("Unknown module - #{m}") }
61
+ else
62
+ modules = MkAcl::Generator::MODULES
63
+ end
64
+
51
65
  spec = MkAcl::Parser.parse(file)
52
- MkAcl::Analyzer.analyze(spec, conn)
66
+ MkAcl::Analyzer.analyze(spec, conn, warn: !opts.no_warn?)
53
67
  #spec.dump
54
- #puts
55
68
  #exit
56
-
57
- modules = opts.generate? ? opts.generate.split(',').map(&:to_sym) : MkAcl::Generator::MODULES
58
69
  MkAcl::Generator.generate(spec, conn, modules, interactive: opts.interactive?)
59
70
 
71
+
@@ -4,9 +4,14 @@ module MkAcl
4
4
  attr_reader :spec
5
5
  attr_reader :conn
6
6
 
7
- def initialize(spec, conn)
7
+ # Tables in the application schema that are not defined in the SPEC file
8
+ def uncovered_tables = @uncovered_tables.to_a
9
+
10
+ def initialize(spec, conn, warn: true)
8
11
  @spec = spec
9
12
  @conn = conn
13
+ @warn = warn
14
+ @uncovered_tables = Set.new
10
15
  end
11
16
 
12
17
  def analyze
@@ -17,15 +22,32 @@ module MkAcl
17
22
  schema_name || '.' || table_name,
18
23
  ref_schema_name || '.' || ref_table_name
19
24
  from meta.links
25
+ where schema_name = '#{spec.app_schema}'
26
+ and ref_schema_name = '#{spec.app_schema}'
20
27
  )
21
28
 
22
29
  # Link up tables
23
30
  for child_table_name, parent_table_name, child_table_uid, parent_table_uid in links
31
+ if !spec.key?(child_table_name)
32
+ @uncovered_tables << child_table_name
33
+ next
34
+ elsif !spec.key?(parent_table_name)
35
+ @uncovered_tables << parent_table_name
36
+ next
37
+ end
38
+
24
39
  spec[child_table_name].parents << spec[parent_table_name] if spec[parent_table_name]
25
40
  end
26
41
 
42
+ # if warn && !@uncovered_tables.empty?
43
+ # puts "Warning: Uncovered tables"
44
+ # indent { puts uncovered_tables }
45
+ # end
46
+
27
47
  # Assign domains
28
- spec.tables.each { |table| resolve_domain(table) }
48
+ spec.tables.each { |table|
49
+ resolve_domain(table)
50
+ }
29
51
 
30
52
  # Check that no table has more than one parent. FIXME
31
53
  spec.tables.each { |table|
@@ -35,11 +57,15 @@ module MkAcl
35
57
  spec
36
58
  end
37
59
 
38
- def self.analyze(spec, conn) self.new(spec, conn).analyze end
60
+ def self.analyze(spec, conn, **opts) self.new(spec, conn, **opts).analyze end
39
61
 
40
62
  private
63
+ def find_tables
64
+
65
+ end
66
+
41
67
  def resolve_domain(table)
42
- table.domain ||= resolve_domain(table.parents.first)
68
+ table.domain ||= table.parents.first && resolve_domain(table.parents.first)
43
69
  end
44
70
  end
45
71
  end
@@ -7,11 +7,32 @@ module MkAcl
7
7
  attr_reader :generator
8
8
  forward_to :generator, :conn, :spec, :app_schema, :acl_schema
9
9
 
10
+ # Map from domain table to list of [table, path, links] tuples. The
11
+ # entries describes the SQL link chain from the table to the given domain
12
+ # table (cases or events)
13
+ attr_reader :chains
14
+
10
15
  def initialize(generator)
11
16
  @generator = generator
17
+ @chains = {}
12
18
  end
13
19
 
20
+ # TODO: ACL checks so that a user can't get IDs of other users' records
14
21
  def generate
22
+ # Find chains
23
+ @chains = conn.multimap %(
24
+ select
25
+ dst_table_name as "key",
26
+ src_table_name as "table_name",
27
+ path as "tables",
28
+ links
29
+ from
30
+ meta.chains
31
+ where src_schema_name = '#{app_schema}'
32
+ and dst_schema_name = '#{app_schema}'
33
+ and dst_table_name in ('cases', 'events')
34
+ )
35
+
15
36
  generate_per_table_id_functions
16
37
  generate_general_id_functions
17
38
  generate_general_id_of_record_functions
@@ -20,33 +41,42 @@ module MkAcl
20
41
  def self.generate(generator) self.new(generator).generate end
21
42
 
22
43
  private
23
- # Generate a case_id_of_RECORD and event_id_of_RECORD, and a
24
- # domain_id_of_RECORD function for each table that returns the associated
25
- # case_id/event_id for a given record. Some examples:
44
+ # # SQL sequence of spec file tables
45
+ # def table_seq() @table_seq ||= spec.tables.map(&:uid).join(', ') end
46
+
47
+ # Generate a set of per-table functions that returns the associated
48
+ # case_id/event_id for the given record. The Functions are generated for
49
+ # each table in the spec file
26
50
  #
27
- # case_id_of_event(id integer)
28
- # event_id_of_noncompliance(id integer)
29
- # domain_id_of_noncompliance(id integer)
51
+ # The geneated functions are
30
52
  #
31
- # Returns null if not found. Note that the record has to exists because
32
- # we access it to read the foreign keys
53
+ # case_id_of_RECORD(id integer)
54
+ # event_id_of_RECORD(id integer)
55
+ # domain_id_of_RECORD(id integer)
56
+ #
57
+ # and the record variants
33
58
  #
34
- # The functions are used to find the roles IDs (case or event) when
35
- # inserting a record. The role ids are written into the various acl_*
36
- # fields by a trigger
59
+ # case_id_of_RECORD(r record)
60
+ # event_id_of_RECORD(r record)
61
+ # domain_id_of_RECORD(r record)
37
62
  #
38
- # The alternative would be to cascade case and event keys in all records.
39
- # Cascading keys are usually dereferred because it only gives a minor
40
- # speed-up in most queries but in this case it optimizes away a recursive
41
- # join up the hierarchy from the current table to the events or cases
42
- # table. It may be a better solution
63
+ # 'RECORD' is substituted with the record name of a table. Record names
64
+ # are the singular name of a table. TODO: Make it plural again
65
+ #
66
+ # The domain functions returns event_id if related to an event and
67
+ # case_id if not. It is meant to return the most specialized domin id for
68
+ # a record. TODO Is it used?
69
+ #
70
+ # Returns null if not found. Note that the record has to exists because
71
+ # we access it to read the foreign keys
43
72
  #
44
- # IDEA: Make the implementations also take a record type instead of an
45
- # id. This is useful in triggers because we already have the first record
46
- # in the acl chain
47
73
  def generate_per_table_id_functions
74
+ # Generate functions by domain
48
75
  for domain in %w(case event)
49
- # Create identity functions (makes some stuff easier)
76
+
77
+ # Create the identity functions first. The identity functions are
78
+ # case_id_of_case() and event_id_of_event(). This makes some stuff
79
+ # easier later on
50
80
  table = "#{domain}s"
51
81
  id_field = "#{domain}_id"
52
82
  signature = "#{acl_schema}.#{id_field}_of_#{domain}(_id integer)"
@@ -54,24 +84,14 @@ module MkAcl
54
84
  drop function if exists #{signature} cascade;
55
85
  create function #{signature} returns integer as $$
56
86
  select _id;
57
- $$ language sql;
87
+ $$ language sql
88
+ set search_path to ''; -- intentionally empty
58
89
  ).align
59
90
  puts
60
91
 
61
- # Create remaining funktions
62
- functions = conn.tuples %(
63
- select
64
- start_table as "table_uid",
65
- path as "tables",
66
- links
67
- from
68
- acl.paths
69
- where
70
- stop_table = '#{app_schema}.#{table}'
71
- )
72
-
73
- for table_uid, tables, links in functions
74
- table_name = table_uid.split(".").last
92
+ # Create functions
93
+ domain_table = Prick::Inflector.pluralize(domain)
94
+ for table_name, tables, links in chains[domain_table]
75
95
  record_name = Prick::Inflector.singularize(table_name)
76
96
  id_arg = "_#{id_field}"
77
97
  signature = "#{acl_schema}.#{id_field}_of_#{record_name}(#{id_arg} integer)"
@@ -92,25 +112,35 @@ module MkAcl
92
112
  }
93
113
  puts ";"
94
114
  }
95
- puts "$$ language sql;"
115
+ puts %(
116
+ $$ language sql
117
+ set search_path to ''; -- intentionally empty
118
+ ).align
96
119
  puts
97
-
98
120
  end
99
121
  end
100
122
 
101
- for table_uid in functions.map(&:first)
102
- table_name = table_uid.split(".").last
103
- record_name = Prick::Inflector.singularize(table_name)
104
- signature = "#{acl_schema}.domain_id_of_#{record_name}(_id integer)"
105
- case_function = "#{acl_schema}.case_id_of_#{record_name}"
106
- event_function = "#{acl_schema}.event_id_of_#{record_name}"
107
- puts %(
108
- drop function if exists #{signature} cascade;
109
- create function #{signature} returns integer as $$
110
- select coalesce(#{event_function}(_id), #{case_function}(_id));
111
- $$ language sql;
112
- ).align
113
- puts
123
+ # Tables that references events and cases
124
+ event_tables = chains['events'].map(&:first)
125
+
126
+ # Tables that references only cases
127
+ case_tables = chains['cases'].map(&:first) - event_tables
128
+
129
+ # Create domain functions
130
+ for domain, tables in { case: case_tables, event: event_tables }
131
+ for table_name in tables
132
+ record_name = Prick::Inflector.singularize(table_name)
133
+ signature = "#{acl_schema}.domain_id_of_#{record_name}(_id integer)"
134
+ domain_function = "#{acl_schema}.#{domain}_id_of_#{record_name}"
135
+ puts %(
136
+ drop function if exists #{signature} cascade;
137
+ create function #{signature} returns integer as $$
138
+ select #{domain_function}(_id);
139
+ $$ language sql
140
+ set search_path to ''; -- intentionally empty
141
+ ).align
142
+ puts
143
+ end
114
144
  end
115
145
  end
116
146
 
@@ -125,7 +155,7 @@ module MkAcl
125
155
  #
126
156
  def generate_general_id_functions
127
157
  for domain in %w(case event)
128
- domain_table = "#{domain}s"
158
+ domain_table = Prick::Inflector.pluralize(domain)
129
159
  field = "#{domain}_id"
130
160
  signature = "#{acl_schema}.#{field}_of(_table varchar, _id integer)"
131
161
 
@@ -136,14 +166,8 @@ module MkAcl
136
166
  ).align
137
167
  indent(2) {
138
168
  puts "case _table"
139
- tables = conn.values %(
140
- select start_table
141
- from acl.paths
142
- where stop_table = '#{app_schema}.#{domain}'
143
- ).align
144
169
  indent {
145
- for table_uid in tables
146
- table_name = table_uid.split(".").last
170
+ for table_name in chains[domain_table].map(&:first)
147
171
  record_name = Prick::Inflector.singularize(table_name)
148
172
  function_name = "#{field}_of_#{record_name}"
149
173
  puts "when '#{table_name}' then #{acl_schema}.#{function_name}(_id)"
@@ -171,12 +195,12 @@ module MkAcl
171
195
 
172
196
  # General domain-id-of-record functions
173
197
  #
174
- # case_id_of(record)
175
- # event_id_of(record)
176
- # domain_id_of(record)
198
+ # case_id_of(r record)
199
+ # event_id_of(r record)
200
+ # domain_id_of(r record)
177
201
  #
178
202
  # Returns the case or event id associated with the given record. The
179
- # record should be an ACL table record
203
+ # record should be an ACL table record type
180
204
  #
181
205
  # Very useful in before insert triggers because it takes a record (eg.
182
206
  # NEW) instead of an ID
@@ -188,9 +212,8 @@ module MkAcl
188
212
  column_name,
189
213
  ref_table_name
190
214
  from
191
- acl.links
192
- where
193
- schema_name = '#{app_schema}'
215
+ meta.links
216
+ where schema_name = '#{app_schema}'
194
217
  )).group_by(&:table_name)
195
218
 
196
219
  for domain in %w(case event)
@@ -210,9 +233,14 @@ module MkAcl
210
233
  ).align
211
234
  indent {
212
235
  indent {
236
+
237
+
213
238
  for table in spec.tables
214
239
  next if domain == "event" && table.domain == "case"
215
- link = links[table.name]&.first
240
+ # puts "------------------------"
241
+ # p table.name
242
+ # p links.keys
243
+ link = links[table.name]&.first or next
216
244
  if table.name == "cases"
217
245
  puts "when '#{table.uid}' then return _r.id;"
218
246
  elsif domain == "event" && table.name == "events"
@@ -222,7 +250,7 @@ module MkAcl
222
250
  elsif link.ref_table_name == "events" && table.domain == "event"
223
251
  puts "when '#{table.uid}' then return _r.#{link.column_name};"
224
252
  else
225
- ref_record = spec[link.ref_table_name].record_name
253
+ ref_record = spec[link.ref_table_name]&.record_name or next
226
254
  id_of_function = "#{acl_schema}.#{domain_id_field}_of_#{ref_record}"
227
255
  puts "when '#{table.uid}' then return #{id_of_function}(_r.#{link.column_name});"
228
256
  end
@@ -235,7 +263,7 @@ module MkAcl
235
263
  }
236
264
  puts %(
237
265
  $$ language plpgsql
238
- set search_path to '';
266
+ set search_path to ''; -- intentionally ''
239
267
  ).align
240
268
  puts
241
269
  end
@@ -253,7 +281,8 @@ module MkAcl
253
281
 
254
282
  return _id;
255
283
  end;
256
- $$ language plpgsql;
284
+ $$ language plpgsql
285
+ set search_path to ''; -- intentionally ''
257
286
  ).align
258
287
  puts
259
288
  end
@@ -1,11 +1,21 @@
1
1
 
2
2
  module MkAcl
3
3
  class Spec
4
- attr_reader :file # Only for informational purposes
4
+ # Source SPEC file. Only for informational purposes
5
+ attr_reader :file
6
+
7
+ # Application schema that contains the ACL controlled tables
5
8
  attr_reader :app_schema
9
+
10
+ # Schema for generated functions to keep the application schema
11
+ # (relatively) clean
6
12
  attr_reader :acl_schema
13
+
14
+ # List of tables. Initialized by Table::initialize through #attach_table
7
15
  attr_reader :tables
8
16
 
17
+ # Spec acts as a hash from table name to Table object. Initialized by
18
+ # Table::initialize through #attach_table
9
19
  forward_to :@table_hash, :[], :key?, :keys, :values
10
20
 
11
21
  def initialize(file, app_schema, acl_schema)
@@ -65,7 +75,7 @@ module MkAcl
65
75
  end
66
76
 
67
77
  def to_s() = name
68
- def inspect() "<<#{name}>>" end
78
+ def inspect() "<#{self.class}#name #{name.inspect}>" end
69
79
 
70
80
  def dump
71
81
  puts "#{name}:"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MikrasUtils
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/tests/acl.fox CHANGED
@@ -137,7 +137,7 @@ case_roles
137
137
  case: *case3
138
138
  role: AKK
139
139
 
140
- case_users
140
+ case_role_users
141
141
  - case_role: *case1_res
142
142
  user: *hdj
143
143
  - case_role: *case1_la
data/tests/acl.spec CHANGED
@@ -23,7 +23,7 @@ cases:
23
23
  case_roles: # TODO: RBAC
24
24
  select: internal KON AKK
25
25
 
26
- case_users:
26
+ case_role_users:
27
27
  insert: CLA admin
28
28
  select: internal
29
29
  delete: CLA admin
data/tests/acl.sql CHANGED
@@ -77,7 +77,7 @@ create view closures as
77
77
 
78
78
  \echo ACL_CLOSURES
79
79
  --select * from closures;
80
-
80
+ /*
81
81
  drop view if exists paths cascade;
82
82
  create view paths as
83
83
  with
@@ -129,4 +129,4 @@ create view paths as
129
129
 
130
130
  \echo ACL_PATHS
131
131
  --select * from paths;
132
-
132
+ */
@@ -12,7 +12,7 @@ create table acl_portal.attach_acls (
12
12
  unique (child_table, child_field, parent_table, parent_id, acls)
13
13
  );
14
14
 
15
- -- Acts as a materialized view. A user's record is updated whenever case_users
15
+ -- Acts as a materialized view. A user's record is updated whenever case_role_users
16
16
  -- or event_users are changed
17
17
  drop table if exists acl_portal.user_acls cascade;
18
18
  create table acl_portal.user_acls (
@@ -44,7 +44,7 @@ create view acl_portal.domain_users as
44
44
  cr.id as "domain_role_id",
45
45
  cu.user_id,
46
46
  cr.role
47
- from app_portal.case_users cu
47
+ from app_portal.case_role_users cu
48
48
  join app_portal.case_roles cr on cr.id = cu.case_role_id
49
49
  join app_portal.cases c on c.id = cr.case_id
50
50
  where (not c.closed or cr.role in ('CLA', 'ELA'))
@@ -45,7 +45,7 @@ create table case_roles (
45
45
  unique (case_id, "role")
46
46
  );
47
47
 
48
- create table case_users (
48
+ create table case_role_users (
49
49
  id integer generated by default as identity primary key,
50
50
  case_role_id integer not null references case_roles(id),
51
51
  user_id integer not null references auth.roles(id),
@@ -3,7 +3,7 @@
3
3
  -- Triggers that maintains acl_portal.user_acls.
4
4
  --
5
5
 
6
- -- Call acl_portal.update_user_acl on any change to either case_users or
6
+ -- Call acl_portal.update_user_acl on any change to either case_role_users or
7
7
  -- event_users. Note that this function is both cross-table and cross
8
8
  -- insert/delete
9
9
  create function domain_users_aiud() returns trigger as $$
@@ -13,7 +13,7 @@ create function domain_users_aiud() returns trigger as $$
13
13
  end;
14
14
  $$ language plpgsql;
15
15
 
16
- create trigger case_users_aiud_trg after insert or update or delete on app_portal.case_users
16
+ create trigger case_role_users_aiud_trg after insert or update or delete on app_portal.case_role_users
17
17
  for each row execute function domain_users_aiud()
18
18
  ;
19
19
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  set search_path to app_portal;
4
4
 
5
+ /*
6
+
5
7
  -- Union of case_roles and event_roles
6
8
  drop view if exists acl_portal.domain_roles cascade;
7
9
  create view acl_portal.domain_roles as
@@ -22,14 +24,14 @@ create view acl_portal.domain_roles as
22
24
  app_portal.event_roles
23
25
  ;
24
26
 
25
- -- Union of case_users and event_users
27
+ -- Union of case_role_users and event_users
26
28
  drop view if exists acl_portal.domain_users cascade;
27
29
  create view acl_portal.domain_users as
28
30
  select
29
31
  case_role_id as "domain_role_id",
30
32
  user_id
31
33
  from
32
- app_portal.case_users
34
+ app_portal.case_role_users
33
35
 
34
36
  union all
35
37
 
@@ -39,8 +41,10 @@ create view acl_portal.domain_users as
39
41
  from
40
42
  app_portal.event_users
41
43
  ;
44
+ */
42
45
 
43
- -- Combines cases, case_roles, and case_users and also computes the virtual CLA
46
+ /*
47
+ -- Combines cases, case_roles, and case_role_users and also computes the virtual CLA
44
48
  -- and CTA roles from the event ELA and ETA roles and assigns the CLA role to
45
49
  -- RES users. Only ACL roles are included
46
50
  drop view if exists case_role_users cascade;
@@ -55,7 +59,7 @@ create view case_role_users as
55
59
  cr.role
56
60
  from app_portal.role_kinds rk
57
61
  join app_portal.case_roles cr on cr.role = rk.kind
58
- join app_portal.case_users cu on cu.case_role_id = cr.id
62
+ join app_portal.case_role_users cu on cu.case_role_id = cr.id
59
63
  where rk.acl
60
64
  ),
61
65
  -- RES user is also CLA
@@ -95,7 +99,8 @@ create view case_role_users as
95
99
  select * from eta_ela_roles
96
100
  order by case_id, user_id -- FIXME: Yt
97
101
  ;
98
-
102
+ */
103
+ /*
99
104
  -- Combines case_role_users with event_roles and event_users. It is the set of
100
105
  -- roles (case or event) that is associated with an event. Users that are no
101
106
  -- longer associated with the case are excluded
@@ -200,4 +205,4 @@ create view agg_name.domain_role_users as
200
205
  username
201
206
  order by domain_id, username
202
207
  ;
203
-
208
+ */
data/tests/fox.sql CHANGED
@@ -15,7 +15,7 @@ insert into acl_portal.attach_acls (parent_table, parent_id, child_table, child_
15
15
  select
16
16
  'case_roles' as "parent_table",
17
17
  id as "parent_id",
18
- 'case_users' as "child_table",
18
+ 'case_role_users' as "child_table",
19
19
  'case_role_id' as "child_id",
20
20
  array[2] -- hdj
21
21
  from
@@ -28,7 +28,7 @@ insert into acl_portal.attach_acls (parent_table, parent_id, child_table, child_
28
28
  delete from auth.users;
29
29
  insert into auth.users select * from auth.roles;
30
30
 
31
- select acl_portal.update_acls();
31
+ --select acl_portal.update_acls();
32
32
  select acl_portal.update_user_acls();
33
33
 
34
34
  /*
data/tests/sys_portal.sql CHANGED
@@ -60,7 +60,7 @@ create view acl_users as
60
60
  cr.id as "role_id"
61
61
  from
62
62
  auth.roles u
63
- join app_portal.case_users cu on cu.user_id = u.id
63
+ join app_portal.case_role_users cu on cu.user_id = u.id
64
64
  join app_portal.case_roles cr on cr.id = cu.case_role_id
65
65
  join app_portal.cases c on c.id = cr.case_id
66
66
  where
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mikras_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-05 00:00:00.000000000 Z
11
+ date: 2024-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg_conn