letopis 1.1.0 → 1.3.0

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.
package/sql/70-read.sql CHANGED
@@ -40,7 +40,7 @@ return exists (select 1 from unnest(p_roles) r(role) where (p_links -> r.role) @
40
40
  -- не позже p_at; p_at null — последняя вообще), которые ссылаются на p_src: кандидаты — версии,
41
41
  -- ссылавшиеся на p_src (GIN log_ends), затем последняя версия каждого кандидата (log_id_rev); ссылку
42
42
  -- проверяет она. Класс и время кандидатов — после пробы (offset 0): иначе планировщик объединяет пробу
43
- -- с log_class_at и читает весь класс в индексе. Без прав: вызывают только функции владельца find_*,
43
+ -- с log_class_tenant_at и читает весь класс в индексе. Без прав: вызывают только функции владельца find_*,
44
44
  -- видимость — на них.
45
45
  create or replace function @SCHEMA@.log_refs_at(p_classes text[], p_src uuid, p_at timestamptz)
46
46
  returns setof @SCHEMA@.log
@@ -60,6 +60,10 @@ $$;
60
60
 
61
61
  -- id строк классов p_classes: по вложению в data (GIN entity_data), по целям концов (GIN entity_ends),
62
62
  -- по списку id (первичный ключ) или по классу (entity_class_tenant).
63
+ -- Арендатор строки — явным условием (доработки после точки Б): row_visible пропускает только строки арендатора
64
+ -- сессии и System и свои членства (member) в других арендаторах, поэтому поиск сразу берёт строки этих двух
65
+ -- арендаторов, а свои членства — отдельным запросом по концу User; иначе цена поиска росла с данными других
66
+ -- арендаторов с теми же именами классов. По списку id условие ничего не даёт — там первичный ключ.
63
67
  create or replace function @SCHEMA@.find_ids(p_classes text[], p_data jsonb, p_ends uuid[], p_ids uuid[],
64
68
  p_at timestamptz default null, p_dead boolean default false)
65
69
  returns table (id uuid, rev int)
@@ -72,6 +76,8 @@ declare
72
76
  c_tenant uuid := (a->>'tenant')::uuid;
73
77
  c_account uuid := (a->>'account')::uuid;
74
78
  c_plan jsonb := a->'plan';
79
+ v_tenants uuid[] := array[(a->>'tenant')::uuid, '@SYSTEM@'::uuid];
80
+ v_member boolean := 'member' = any (p_classes);
75
81
  begin
76
82
  if c_account is null then
77
83
  return;
@@ -83,21 +89,29 @@ begin
83
89
  where e.id = any (p_ids) and e.class = any (p_classes)
84
90
  and (p_data is null or e.data @> p_data) and (p_ends is null or e.ends @> p_ends)
85
91
  and @SCHEMA@.row_visible(e.tenant, e.class, e.id, e.owner, e.tags, e.data, e.links, c_tenant, c_account, c_plan);
92
+ return;
86
93
  elsif p_data is not null and p_ends is not null then
87
94
  return query select e.id, e.rev from @SCHEMA@.entity e
88
- where e.class = any (p_classes) and e.data @> p_data and e.ends @> p_ends
95
+ where e.class = any (p_classes) and e.tenant = any (v_tenants) and e.data @> p_data and e.ends @> p_ends
89
96
  and @SCHEMA@.row_visible(e.tenant, e.class, e.id, e.owner, e.tags, e.data, e.links, c_tenant, c_account, c_plan);
90
97
  elsif p_data is not null then
91
98
  return query select e.id, e.rev from @SCHEMA@.entity e
92
- where e.class = any (p_classes) and e.data @> p_data
99
+ where e.class = any (p_classes) and e.tenant = any (v_tenants) and e.data @> p_data
93
100
  and @SCHEMA@.row_visible(e.tenant, e.class, e.id, e.owner, e.tags, e.data, e.links, c_tenant, c_account, c_plan);
94
101
  elsif p_ends is not null then
95
102
  return query select e.id, e.rev from @SCHEMA@.entity e
96
- where e.class = any (p_classes) and e.ends @> p_ends
103
+ where e.class = any (p_classes) and e.tenant = any (v_tenants) and e.ends @> p_ends
97
104
  and @SCHEMA@.row_visible(e.tenant, e.class, e.id, e.owner, e.tags, e.data, e.links, c_tenant, c_account, c_plan);
98
105
  else
99
106
  return query select e.id, e.rev from @SCHEMA@.entity e
100
- where e.class = any (p_classes)
107
+ where e.class = any (p_classes) and e.tenant = any (v_tenants)
108
+ and @SCHEMA@.row_visible(e.tenant, e.class, e.id, e.owner, e.tags, e.data, e.links, c_tenant, c_account, c_plan);
109
+ end if;
110
+ -- свои членства в других арендаторах: по концу User (GIN entity_ends)
111
+ if v_member then
112
+ return query select e.id, e.rev from @SCHEMA@.entity e
113
+ where e.class = 'member' and e.ends @> array[c_account] and not (e.tenant = any (v_tenants))
114
+ and (p_data is null or e.data @> p_data) and (p_ends is null or e.ends @> p_ends)
101
115
  and @SCHEMA@.row_visible(e.tenant, e.class, e.id, e.owner, e.tags, e.data, e.links, c_tenant, c_account, c_plan);
102
116
  end if;
103
117
  elsif p_ids is not null then
@@ -111,20 +125,31 @@ begin
111
125
  and (p_data is null or v.data @> p_data) and (p_ends is null or @SCHEMA@.link_ids(v.links) @> p_ends)
112
126
  and @SCHEMA@.row_visible(v.tenant, v.class, v.id, v.owner, v.tags, v.data, v.links, c_tenant, c_account, c_plan);
113
127
  elsif p_ends is not null then
114
- -- по целям концов — от версий, ссылавшихся на первую цель (GIN log_ends)
128
+ -- по целям концов — от версий, ссылавшихся на первую цель (GIN log_ends); арендатор — после пробы
115
129
  return query select v.id, v.rev from @SCHEMA@.log_refs_at(p_classes, p_ends[1], p_at) v
116
- where (v.op = 'delete') = p_dead and v.op not in ('purge', 'trim', 'reset')
130
+ where (v.tenant = any (v_tenants) or v.class = 'member')
131
+ and (v.op = 'delete') = p_dead and v.op not in ('purge', 'trim', 'reset')
117
132
  and (p_data is null or v.data @> p_data) and @SCHEMA@.link_ids(v.links) @> p_ends
118
133
  and @SCHEMA@.row_visible(v.tenant, v.class, v.id, v.owner, v.tags, v.data, v.links, c_tenant, c_account, c_plan);
119
134
  else
135
+ -- арендатор id неизменен, записи purge и trim несут арендатора объекта: условие до distinct on не меняет, какая
136
+ -- версия id последняя (индекс log_class_tenant_at)
120
137
  return query select v.id, v.rev from (
121
138
  select distinct on (l.id) l.id, l.rev, l.op, l.class, l.tenant, l.owner, l.tags, l.data, l.links
122
139
  from @SCHEMA@.log l
123
- where l.class = any (p_classes) and l.at <= coalesce(p_at, 'infinity'::timestamptz)
140
+ where l.class = any (p_classes) and l.tenant = any (v_tenants) and l.at <= coalesce(p_at, 'infinity'::timestamptz)
124
141
  order by l.id, l.rev desc) v
125
142
  where (v.op = 'delete') = p_dead and v.op not in ('purge', 'trim', 'reset')
126
143
  and (p_data is null or v.data @> p_data) and (p_ends is null or @SCHEMA@.link_ids(v.links) @> p_ends)
127
144
  and @SCHEMA@.row_visible(v.tenant, v.class, v.id, v.owner, v.tags, v.data, v.links, c_tenant, c_account, c_plan);
145
+ -- свои членства в других арендаторах: версии, ссылавшиеся на аккаунт (GIN log_ends)
146
+ if v_member then
147
+ return query select v.id, v.rev from @SCHEMA@.log_refs_at(array['member'], c_account, p_at) v
148
+ where not (v.tenant = any (v_tenants))
149
+ and (v.op = 'delete') = p_dead and v.op not in ('purge', 'trim', 'reset')
150
+ and (p_data is null or v.data @> p_data) and (p_ends is null or @SCHEMA@.link_ids(v.links) @> p_ends)
151
+ and @SCHEMA@.row_visible(v.tenant, v.class, v.id, v.owner, v.tags, v.data, v.links, c_tenant, c_account, c_plan);
152
+ end if;
128
153
  end if;
129
154
  end $$;
130
155
 
package/sql/80-auth.sql CHANGED
@@ -17,7 +17,7 @@ return interval '10 minutes';
17
17
 
18
18
  create or replace function @SCHEMA@.auth_kind_ok(p_kind text) returns boolean
19
19
  language sql immutable parallel safe
20
- return p_kind ~ '^[A-Z][A-Z0-9_]{1,31}$' and p_kind not in ('SESSION', 'APIKEY', 'KEYSECRET', 'OTP', 'TOTP', 'KEY');
20
+ return p_kind ~ '^[A-Z][A-Z0-9_]{1,31}$' and p_kind not in ('SESSION', 'APIKEY', 'KEYSECRET', 'OTP', 'TOTP', 'KEY', 'PROJECTOR', 'LOCK');
21
21
 
22
22
  -- Действующая сессия обязательна (иначе no_session).
23
23
  create or replace function @SCHEMA@.auth_session_required(p_account uuid) returns void
@@ -617,7 +617,7 @@ begin
617
617
  coalesce((s.meta->>'confirmed')::boolean, false), coalesce((s.meta->>'enabled')::boolean, true),
618
618
  s.meta - 'confirmed' - 'enabled' - 'attempts' - 'last_step', s.created_at, s.expires_at
619
619
  from @SCHEMA@.secret s
620
- where s.account = p_account and s.kind not in ('SESSION', 'KEY') and s.deleted_at is null
620
+ where s.account = p_account and s.kind not in ('SESSION', 'KEY', 'PROJECTOR', 'LOCK') and s.deleted_at is null
621
621
  and (s.expires_at is null or s.expires_at > clock_timestamp())
622
622
  order by s.created_at, s.id;
623
623
  end $$;
@@ -639,7 +639,7 @@ begin
639
639
  perform @SCHEMA@.auth_session_required(c.account);
640
640
  select s.account, s.kind,
641
641
  (s.expires_at is null or s.expires_at > clock_timestamp()) and coalesce((s.meta->>'enabled')::boolean, true) as live
642
- into cr from @SCHEMA@.secret s where s.id = p_id and s.kind not in ('SESSION', 'KEY') and s.deleted_at is null;
642
+ into cr from @SCHEMA@.secret s where s.id = p_id and s.kind not in ('SESSION', 'KEY', 'PROJECTOR', 'LOCK') and s.deleted_at is null;
643
643
  if cr.account is null then
644
644
  return false;
645
645
  end if;
@@ -679,7 +679,7 @@ declare
679
679
  acc uuid;
680
680
  begin
681
681
  perform @SCHEMA@.acl_require('auth.credential');
682
- select s.account into acc from @SCHEMA@.secret s where s.id = p_id and s.kind not in ('SESSION', 'KEY') and s.deleted_at is null;
682
+ select s.account into acc from @SCHEMA@.secret s where s.id = p_id and s.kind not in ('SESSION', 'KEY', 'PROJECTOR', 'LOCK') and s.deleted_at is null;
683
683
  if acc is null then
684
684
  return false;
685
685
  end if;