@moneypot/hub 1.18.3 → 1.18.6
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/dist/dashboard/assets/index-BlgWJql2.js +418 -0
- package/dist/dashboard/index.html +1 -1
- package/dist/src/pg-sql2.d.ts +1 -0
- package/dist/src/pg-sql2.js +1 -0
- package/dist/src/pg-versions/001-schema.sql +23 -70
- package/dist/src/pg-versions/002-balance-id.sql +0 -3
- package/dist/src/pg-versions/003-take-request.sql +25 -47
- package/dist/src/pg-versions/004-rls-scope-to-experience.sql +8 -21
- package/dist/src/pg-versions/005-hash-chain.sql +8 -21
- package/dist/src/pg-versions/006-outcome-bet.sql +0 -11
- package/dist/src/pg-versions/007-notify-put.sql +1 -3
- package/dist/src/pg-versions/008-outcome-bet-hash.sql +5 -19
- package/dist/src/pg-versions/009-take-request-retry.sql +1 -2
- package/dist/src/pg-versions/011-audit-log.sql +11 -24
- package/dist/src/pg-versions/012-playground.sql +3 -11
- package/dist/src/pg-versions/013-chat.sql +8 -70
- package/dist/src/plugins/id-to-node-id.js +0 -3
- package/package.json +12 -8
- package/dist/dashboard/assets/index-DGxc3Ja9.js +0 -412
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Dashboard</title>
|
|
7
|
-
<script type="module" crossorigin src="/dashboard/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/dashboard/assets/index-BlgWJql2.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/dashboard/assets/index-32DtKox_.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "postgraphile/pg-sql2";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "postgraphile/pg-sql2";
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
-- Flattened migrations from 001-015
|
|
2
1
|
|
|
3
|
-
-- Schema Setup
|
|
4
2
|
drop schema if exists public cascade;
|
|
5
3
|
create schema public;
|
|
6
4
|
|
|
@@ -17,10 +15,6 @@ create extension if not exists pgcrypto;
|
|
|
17
15
|
create extension if not exists "uuid-ossp";
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
-- PostgreSQL role setup
|
|
21
|
-
-- We need an app_postgraphile role to exist here so that we can grant it permissions.
|
|
22
|
-
-- The user can either create it themselves before they run the migrations, or they
|
|
23
|
-
-- can update the password after the fact.
|
|
24
18
|
DO $$
|
|
25
19
|
DECLARE
|
|
26
20
|
random_password text := gen_random_uuid()::text;
|
|
@@ -30,21 +24,15 @@ BEGIN
|
|
|
30
24
|
END IF;
|
|
31
25
|
END $$;
|
|
32
26
|
|
|
33
|
-
-- TODO: We may want an hub_secret for things that postgraphile user can't even do (e.g. things we only manipulate in security definer functions)
|
|
34
27
|
|
|
35
|
-
-- UUID v7 generation functions
|
|
36
28
|
CREATE OR REPLACE FUNCTION hub_hidden.uuid_generate_v7() RETURNS uuid LANGUAGE plpgsql PARALLEL SAFE AS $$
|
|
37
29
|
DECLARE
|
|
38
|
-
-- The current UNIX timestamp in milliseconds
|
|
39
30
|
unix_time_ms CONSTANT bytea NOT NULL DEFAULT substring(int8send((extract(epoch FROM clock_timestamp()) * 1000)::bigint) from 3);
|
|
40
31
|
|
|
41
|
-
-- The buffer used to create the UUID, starting with the UNIX timestamp and followed by random bytes
|
|
42
32
|
buffer bytea NOT NULL DEFAULT unix_time_ms || gen_random_bytes(10);
|
|
43
33
|
BEGIN
|
|
44
|
-
-- Set most significant 4 bits of 7th byte to 7 (for UUID v7), keeping the last 4 bits unchanged
|
|
45
34
|
buffer = set_byte(buffer, 6, (b'0111' || get_byte(buffer, 6)::bit(4))::bit(8)::int);
|
|
46
35
|
|
|
47
|
-
-- Set most significant 2 bits of 9th byte to 2 (the UUID variant specified in RFC 4122), keeping the last 6 bits unchanged
|
|
48
36
|
buffer = set_byte(buffer, 8, (b'10' || get_byte(buffer, 8)::bit(6))::bit(8)::int);
|
|
49
37
|
|
|
50
38
|
RETURN encode(buffer, 'hex');
|
|
@@ -55,7 +43,6 @@ CREATE OR REPLACE FUNCTION extract_timestamp_from_uuid_v7(uuid_v7 UUID) RETURNS
|
|
|
55
43
|
SELECT to_timestamp(('x'||replace(uuid_v7::text, '-', ''))::bit(48)::bigint / 1000) AS result;
|
|
56
44
|
$$ LANGUAGE sql IMMUTABLE;
|
|
57
45
|
|
|
58
|
-
-- Helper functions for RLS
|
|
59
46
|
create or replace function hub_hidden.is_operator() returns boolean as $$
|
|
60
47
|
select nullif(current_setting('operator.api_key', true), '') is not null;
|
|
61
48
|
$$ language sql stable;
|
|
@@ -76,13 +63,11 @@ create or replace function hub_hidden.current_session_id() returns uuid as $$
|
|
|
76
63
|
select nullif(current_setting('session.id', true), '')::uuid;
|
|
77
64
|
$$ language sql stable;
|
|
78
65
|
|
|
79
|
-
-- Enums
|
|
80
66
|
create type hub.transfer_status_kind as enum ('PENDING', 'COMPLETED', 'CANCELED', 'UNCLAIMED', 'EXPIRED');
|
|
81
67
|
|
|
82
|
-
-- Tables
|
|
83
68
|
CREATE TABLE hub.casino(
|
|
84
69
|
id uuid PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
85
|
-
base_url TEXT NOT NULL,
|
|
70
|
+
base_url TEXT NOT NULL,
|
|
86
71
|
name TEXT NOT NULL,
|
|
87
72
|
graphql_url TEXT NOT NULL
|
|
88
73
|
);
|
|
@@ -92,7 +77,7 @@ create unique index casino_graphql_url_key on hub.casino(graphql_url);
|
|
|
92
77
|
|
|
93
78
|
create table hub.casino_secret(
|
|
94
79
|
id uuid primary key references hub.casino(id),
|
|
95
|
-
controller_id uuid not null,
|
|
80
|
+
controller_id uuid not null,
|
|
96
81
|
api_key uuid not null
|
|
97
82
|
);
|
|
98
83
|
|
|
@@ -102,7 +87,6 @@ create table hub.jwk_set (
|
|
|
102
87
|
updated_at timestamptz not null default now()
|
|
103
88
|
);
|
|
104
89
|
|
|
105
|
-
-- For audit/debugging
|
|
106
90
|
create table hub.jwk_set_snapshot (
|
|
107
91
|
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
108
92
|
casino_id uuid not null references hub.casino(id),
|
|
@@ -113,12 +97,11 @@ create index jwks_snapshot_casino_id_idx on hub.jwk_set_snapshot(casino_id);
|
|
|
113
97
|
|
|
114
98
|
create table hub.api_key (
|
|
115
99
|
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
116
|
-
key uuid unique not null default gen_random_uuid(),
|
|
100
|
+
key uuid unique not null default gen_random_uuid(),
|
|
117
101
|
last_used_at timestamptz null,
|
|
118
102
|
revoked_at timestamptz null
|
|
119
103
|
);
|
|
120
104
|
|
|
121
|
-
-- This will get populated from each casino graphql API.
|
|
122
105
|
create table hub.currency(
|
|
123
106
|
key text not null,
|
|
124
107
|
casino_id uuid not null references hub.casino(id),
|
|
@@ -133,10 +116,9 @@ create table hub.user (
|
|
|
133
116
|
id uuid NOT NULL PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
134
117
|
casino_id uuid NOT NULL references hub.casino(id),
|
|
135
118
|
mp_user_id uuid NOT NULL,
|
|
136
|
-
uname text NOT NULL
|
|
119
|
+
uname text NOT NULL
|
|
137
120
|
);
|
|
138
121
|
|
|
139
|
-
-- A user can only represent one mp_user_id (Moneypot record) per MP casino.
|
|
140
122
|
create unique index user_casino_id_mp_user_id_key on hub.user(casino_id, mp_user_id);
|
|
141
123
|
|
|
142
124
|
create table hub_hidden.transfer_cursor (
|
|
@@ -147,10 +129,9 @@ create table hub_hidden.transfer_cursor (
|
|
|
147
129
|
create table hub.experience (
|
|
148
130
|
id uuid NOT NULL PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
149
131
|
casino_id uuid NOT NULL references hub.casino(id),
|
|
150
|
-
mp_experience_id uuid NOT NULL,
|
|
132
|
+
mp_experience_id uuid NOT NULL,
|
|
151
133
|
name text NOT NULL
|
|
152
134
|
);
|
|
153
|
-
-- An experience can only represent one mp_experience_id (Moneypot record) per MP casino.
|
|
154
135
|
CREATE UNIQUE INDEX experience_casino_id_mp_experience_id_key ON hub.experience(casino_id, mp_experience_id);
|
|
155
136
|
CREATE INDEX experience_mp_experience_id_idx ON hub.experience(mp_experience_id);
|
|
156
137
|
|
|
@@ -170,11 +151,11 @@ CREATE UNIQUE INDEX bankroll_casino_id_currency_key_key ON hub.bankroll(casino_i
|
|
|
170
151
|
CREATE INDEX bankroll_casino_id_idx ON hub.bankroll(casino_id);
|
|
171
152
|
|
|
172
153
|
create table hub.session (
|
|
173
|
-
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
154
|
+
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
174
155
|
casino_id uuid NOT NULL references hub.casino(id),
|
|
175
|
-
user_id uuid not null references hub.user(id),
|
|
176
|
-
experience_id uuid not null references hub.experience(id),
|
|
177
|
-
user_token uuid not null,
|
|
156
|
+
user_id uuid not null references hub.user(id),
|
|
157
|
+
experience_id uuid not null references hub.experience(id),
|
|
158
|
+
user_token uuid not null,
|
|
178
159
|
expired_at timestamptz not null DEFAULT now() + interval '1 year',
|
|
179
160
|
key UUID NOT NULL DEFAULT gen_random_uuid()
|
|
180
161
|
);
|
|
@@ -182,17 +163,15 @@ create table hub.session (
|
|
|
182
163
|
CREATE INDEX session_casino_id_idx ON hub.session(casino_id);
|
|
183
164
|
CREATE INDEX session_user_id_idx ON hub.session(user_id);
|
|
184
165
|
CREATE INDEX session_experience_id_idx ON hub.session(experience_id);
|
|
185
|
-
-- TODO: Shouldn't these only be unique per casino/exp?
|
|
186
166
|
CREATE UNIQUE INDEX session_user_token_idx ON hub.session(user_token);
|
|
187
167
|
CREATE UNIQUE INDEX session_key_idx ON hub.session(key);
|
|
188
168
|
|
|
189
|
-
-- MP transfers turn into deposits and withdraws in hub
|
|
190
169
|
create table hub.deposit (
|
|
191
|
-
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
170
|
+
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
192
171
|
casino_id uuid not null references hub.casino(id),
|
|
193
|
-
mp_transfer_id text not null,
|
|
194
|
-
user_id uuid not null references hub.user(id),
|
|
195
|
-
experience_id uuid not null references hub.experience(id),
|
|
172
|
+
mp_transfer_id text not null,
|
|
173
|
+
user_id uuid not null references hub.user(id),
|
|
174
|
+
experience_id uuid not null references hub.experience(id),
|
|
196
175
|
amount float8 not null check (amount > 0),
|
|
197
176
|
currency_key text not null,
|
|
198
177
|
foreign key (currency_key, casino_id) references hub.currency(key, casino_id)
|
|
@@ -205,15 +184,12 @@ CREATE INDEX deposit_casino_id_idx ON hub.deposit(casino_id);
|
|
|
205
184
|
|
|
206
185
|
create table hub.withdrawal_request (
|
|
207
186
|
id uuid not null primary key default hub_hidden.uuid_generate_v7(),
|
|
208
|
-
-- Save all the things we need to make the MP transferCurrencyExperienceToUser request
|
|
209
187
|
casino_id uuid not null references hub.casino(id),
|
|
210
188
|
experience_id uuid not null references hub.experience(id),
|
|
211
189
|
user_id uuid not null references hub.user(id),
|
|
212
190
|
amount float not null check (amount > 0),
|
|
213
191
|
currency_key text not null,
|
|
214
192
|
|
|
215
|
-
-- This is set once we can confirm the transfer was created in MP
|
|
216
|
-
-- while submitting metadata={id: withdrawal_request.id}
|
|
217
193
|
mp_transfer_id text null,
|
|
218
194
|
|
|
219
195
|
foreign key (currency_key, casino_id) references hub.currency(key, casino_id)
|
|
@@ -223,15 +199,15 @@ CREATE INDEX withdrawal_request_user_id_idx ON hub.withdrawal_request(user_id);
|
|
|
223
199
|
CREATE INDEX withdrawal_request_experience_id_idx ON hub.withdrawal_request(experience_id);
|
|
224
200
|
CREATE INDEX withdrawal_request_casino_id_idx ON hub.withdrawal_request(casino_id);
|
|
225
201
|
|
|
226
|
-
CREATE UNIQUE INDEX withdrawal_request_casino_id_mp_transfer_id_key ON hub.withdrawal_request(casino_id, mp_transfer_id)
|
|
202
|
+
CREATE UNIQUE INDEX withdrawal_request_casino_id_mp_transfer_id_key ON hub.withdrawal_request(casino_id, mp_transfer_id)
|
|
227
203
|
WHERE mp_transfer_id IS NOT NULL;
|
|
228
204
|
|
|
229
205
|
create table hub.withdrawal (
|
|
230
|
-
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
231
|
-
casino_id uuid not null references hub.casino(id),
|
|
232
|
-
mp_transfer_id text not null,
|
|
233
|
-
user_id uuid not null references hub.user(id),
|
|
234
|
-
experience_id uuid not null references hub.experience(id),
|
|
206
|
+
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
207
|
+
casino_id uuid not null references hub.casino(id),
|
|
208
|
+
mp_transfer_id text not null,
|
|
209
|
+
user_id uuid not null references hub.user(id),
|
|
210
|
+
experience_id uuid not null references hub.experience(id),
|
|
235
211
|
amount float8 not null check (amount > 0),
|
|
236
212
|
currency_key text not null,
|
|
237
213
|
status hub.transfer_status_kind not null,
|
|
@@ -262,7 +238,6 @@ CREATE INDEX faucet_claim_experience_id_idx ON hub.faucet_claim(experience_id);
|
|
|
262
238
|
CREATE INDEX faucet_claim_casino_id_idx ON hub.faucet_claim(casino_id);
|
|
263
239
|
CREATE INDEX faucet_claim_currency_key_idx ON hub.faucet_claim(currency_key);
|
|
264
240
|
|
|
265
|
-
-- User balances derived from transfers per experience
|
|
266
241
|
create table hub.balance (
|
|
267
242
|
casino_id uuid not null references hub.casino(id),
|
|
268
243
|
user_id uuid not null references hub.user(id),
|
|
@@ -278,12 +253,9 @@ CREATE INDEX balance_user_id_idx ON hub.balance(user_id);
|
|
|
278
253
|
CREATE INDEX balance_experience_id_idx ON hub.balance(experience_id);
|
|
279
254
|
CREATE INDEX balance_casino_id_idx ON hub.balance(casino_id);
|
|
280
255
|
|
|
281
|
-
|
|
282
|
-
create view hub.active_session as
|
|
256
|
+
create view hub.active_session as
|
|
283
257
|
select * from hub.session where expired_at > now();
|
|
284
258
|
|
|
285
|
-
-- Triggers
|
|
286
|
-
-- Every time a new casino is inserted, a notification is sent to the channel 'new_casino'
|
|
287
259
|
CREATE OR REPLACE FUNCTION notify_new_casino()
|
|
288
260
|
RETURNS TRIGGER AS $$
|
|
289
261
|
BEGIN
|
|
@@ -301,34 +273,29 @@ EXECUTE FUNCTION notify_new_casino();
|
|
|
301
273
|
|
|
302
274
|
CREATE OR REPLACE FUNCTION hub.notify_balance_change() RETURNS TRIGGER AS $$
|
|
303
275
|
BEGIN
|
|
304
|
-
-- For INSERT operations, always notify
|
|
305
276
|
IF TG_OP = 'INSERT' THEN
|
|
306
277
|
PERFORM pg_notify(
|
|
307
278
|
'hub:user:' || NEW.user_id || ':balance_alert',
|
|
308
279
|
json_build_object('currency_key', NEW.currency_key)::text
|
|
309
280
|
);
|
|
310
|
-
-- For UPDATE operations, only notify if amount changed
|
|
311
281
|
ELSIF TG_OP = 'UPDATE' AND NEW.amount IS DISTINCT FROM OLD.amount THEN
|
|
312
282
|
PERFORM pg_notify(
|
|
313
283
|
'hub:user:' || NEW.user_id || ':balance_alert',
|
|
314
284
|
json_build_object('currency_key', NEW.currency_key)::text
|
|
315
285
|
);
|
|
316
286
|
END IF;
|
|
317
|
-
|
|
318
|
-
-- trigger wants us to return new row
|
|
287
|
+
|
|
319
288
|
RETURN NEW;
|
|
320
289
|
END;
|
|
321
290
|
$$ LANGUAGE plpgsql;
|
|
322
291
|
|
|
323
|
-
CREATE TRIGGER balance_change_alert
|
|
292
|
+
CREATE TRIGGER balance_change_alert
|
|
324
293
|
AFTER INSERT OR UPDATE OF amount ON hub.balance
|
|
325
|
-
FOR EACH ROW
|
|
294
|
+
FOR EACH ROW
|
|
326
295
|
EXECUTE FUNCTION hub.notify_balance_change();
|
|
327
296
|
|
|
328
|
-
-- Grants
|
|
329
297
|
grant usage on schema public to app_postgraphile;
|
|
330
298
|
grant usage on schema hub to app_postgraphile;
|
|
331
|
-
-- hub_hidden utils like hub_hidden.current_user_id() should be accessible to app_postgraphile
|
|
332
299
|
grant usage on schema hub_hidden to app_postgraphile;
|
|
333
300
|
|
|
334
301
|
grant select on table hub.currency to app_postgraphile;
|
|
@@ -351,7 +318,6 @@ grant select on table hub.withdrawal_request to app_postgraphile;
|
|
|
351
318
|
grant update on hub.casino to app_postgraphile;
|
|
352
319
|
grant update on table hub.bankroll to app_postgraphile;
|
|
353
320
|
|
|
354
|
-
-- Row Level Security
|
|
355
321
|
alter table hub.casino enable row level security;
|
|
356
322
|
alter table hub.casino_secret enable row level security;
|
|
357
323
|
alter table hub.user enable row level security;
|
|
@@ -368,14 +334,11 @@ alter table hub.jwk_set_snapshot enable row level security;
|
|
|
368
334
|
alter table hub.withdrawal_request enable row level security;
|
|
369
335
|
alter table hub.faucet_claim enable row level security;
|
|
370
336
|
|
|
371
|
-
-- RLS Policies
|
|
372
337
|
|
|
373
|
-
-- PUBLIC POLICIES
|
|
374
338
|
create policy select_casino on hub.casino for select using (true);
|
|
375
339
|
create policy select_currency on hub.currency for select using (true);
|
|
376
340
|
create policy select_bankroll on hub.bankroll for select using (true);
|
|
377
341
|
|
|
378
|
-
-- OPERATOR-ONLY POLICIES
|
|
379
342
|
create policy select_experience on hub.experience for select using (
|
|
380
343
|
hub_hidden.is_operator()
|
|
381
344
|
);
|
|
@@ -404,55 +367,45 @@ create policy update_bankroll on hub.bankroll for update using (
|
|
|
404
367
|
hub_hidden.is_operator()
|
|
405
368
|
);
|
|
406
369
|
|
|
407
|
-
-- MIXED-USE POLICIES
|
|
408
|
-
-- We should scope every user check to the current experience
|
|
409
|
-
-- Else you will accidentally see the user's rows for other experiences
|
|
410
370
|
|
|
411
371
|
create policy select_user on hub.user for select using (
|
|
412
372
|
hub_hidden.is_operator() or (
|
|
413
|
-
-- Users can only see their own records
|
|
414
373
|
id = hub_hidden.current_user_id()
|
|
415
374
|
)
|
|
416
375
|
);
|
|
417
376
|
|
|
418
377
|
create policy select_balance on hub.balance for select using (
|
|
419
378
|
hub_hidden.is_operator() OR (
|
|
420
|
-
-- Users can only see their own records
|
|
421
379
|
user_id = hub_hidden.current_user_id()
|
|
422
380
|
)
|
|
423
381
|
);
|
|
424
382
|
|
|
425
383
|
create policy select_deposit on hub.deposit for select using (
|
|
426
384
|
hub_hidden.is_operator() OR (
|
|
427
|
-
-- Users can only see their own records
|
|
428
385
|
user_id = hub_hidden.current_user_id()
|
|
429
386
|
)
|
|
430
387
|
);
|
|
431
388
|
|
|
432
389
|
create policy select_withdrawal on hub.withdrawal for select using (
|
|
433
390
|
hub_hidden.is_operator() OR (
|
|
434
|
-
-- Users can only see their own records
|
|
435
391
|
user_id = hub_hidden.current_user_id()
|
|
436
392
|
)
|
|
437
393
|
);
|
|
438
394
|
|
|
439
395
|
create policy select_session on hub.session for select using (
|
|
440
396
|
hub_hidden.is_operator() OR (
|
|
441
|
-
-- Users can only see their own records
|
|
442
397
|
user_id = hub_hidden.current_user_id()
|
|
443
398
|
)
|
|
444
399
|
);
|
|
445
400
|
|
|
446
401
|
create policy select_withdrawal_request on hub.withdrawal_request for select using (
|
|
447
402
|
hub_hidden.is_operator() OR (
|
|
448
|
-
-- Users can only see their own records
|
|
449
403
|
user_id = hub_hidden.current_user_id()
|
|
450
404
|
)
|
|
451
405
|
);
|
|
452
406
|
|
|
453
407
|
create policy select_faucet_claim on hub.faucet_claim for select using (
|
|
454
408
|
hub_hidden.is_operator() OR (
|
|
455
|
-
-- Users can only see their own records
|
|
456
409
|
user_id = hub_hidden.current_user_id()
|
|
457
410
|
)
|
|
458
411
|
);
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
-- Add balance.id UUID PK column
|
|
2
|
-
-- Migrate the existing surrogate PK to a unique index.
|
|
3
1
|
|
|
4
2
|
ALTER TABLE hub.balance ADD COLUMN id uuid default hub_hidden.uuid_generate_v7();
|
|
5
3
|
UPDATE hub.balance SET id = hub_hidden.uuid_generate_v7();
|
|
6
4
|
ALTER TABLE hub.balance ALTER COLUMN id SET NOT NULL;
|
|
7
5
|
|
|
8
|
-
-- Migrate old PK to unique index
|
|
9
6
|
ALTER TABLE hub.balance DROP CONSTRAINT balance_pkey;
|
|
10
7
|
ALTER TABLE hub.balance ADD CONSTRAINT balance_pkey PRIMARY KEY (id);
|
|
11
8
|
CREATE UNIQUE INDEX balance_casino_id_user_id_experience_id_currency_key_key ON hub.balance(casino_id, user_id, experience_id, currency_key);
|
|
@@ -1,107 +1,85 @@
|
|
|
1
|
-
-- Create a simplified take request system with a single table state machine
|
|
2
1
|
|
|
3
|
-
-- UNDO
|
|
4
2
|
|
|
5
|
-
-- DROP TABLE IF EXISTS hub.take_transfer;
|
|
6
|
-
-- DROP TABLE IF EXISTS hub.take_request;
|
|
7
|
-
-- DROP TYPE IF EXISTS hub.mp_take_request_status;
|
|
8
|
-
-- DROP TYPE IF EXISTS hub.mp_transfer_status;
|
|
9
3
|
|
|
10
|
-
-- Local take request status that doesn't map to MP's take_request_status kind
|
|
11
4
|
CREATE TYPE hub.take_request_status AS ENUM (
|
|
12
|
-
'PENDING',
|
|
13
|
-
'PROCESSING',
|
|
14
|
-
'COMPLETED',
|
|
15
|
-
'FAILED',
|
|
16
|
-
'REJECTED'
|
|
5
|
+
'PENDING',
|
|
6
|
+
'PROCESSING',
|
|
7
|
+
'COMPLETED',
|
|
8
|
+
'FAILED',
|
|
9
|
+
'REJECTED'
|
|
17
10
|
);
|
|
18
11
|
|
|
19
|
-
-- Maps to MP's app_public.take_request_status enum
|
|
20
12
|
CREATE TYPE hub.mp_take_request_status AS ENUM (
|
|
21
|
-
'PENDING',
|
|
22
|
-
'TRANSFERRED',
|
|
23
|
-
'CONTROLLER_REJECTED',
|
|
24
|
-
'USER_CANCELED'
|
|
13
|
+
'PENDING',
|
|
14
|
+
'TRANSFERRED',
|
|
15
|
+
'CONTROLLER_REJECTED',
|
|
16
|
+
'USER_CANCELED'
|
|
25
17
|
);
|
|
26
18
|
|
|
27
|
-
-- Maps to MP's app_public.transfer_status_kind enum
|
|
28
19
|
CREATE TYPE hub.mp_transfer_status AS ENUM (
|
|
29
|
-
'PENDING',
|
|
30
|
-
'COMPLETED',
|
|
31
|
-
'CANCELED',
|
|
32
|
-
'UNCLAIMED',
|
|
33
|
-
'EXPIRED'
|
|
20
|
+
'PENDING',
|
|
21
|
+
'COMPLETED',
|
|
22
|
+
'CANCELED',
|
|
23
|
+
'UNCLAIMED',
|
|
24
|
+
'EXPIRED'
|
|
34
25
|
);
|
|
35
26
|
|
|
36
|
-
-- Create the simplified take request table
|
|
37
27
|
CREATE TABLE hub.take_request (
|
|
38
28
|
id UUID PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
39
|
-
mp_take_request_id UUID UNIQUE NOT NULL,
|
|
29
|
+
mp_take_request_id UUID UNIQUE NOT NULL,
|
|
40
30
|
user_id UUID NOT NULL REFERENCES hub.user(id),
|
|
41
31
|
experience_id UUID NOT NULL REFERENCES hub.experience(id),
|
|
42
32
|
casino_id UUID NOT NULL REFERENCES hub.casino(id),
|
|
43
33
|
currency_key TEXT NOT NULL,
|
|
44
|
-
amount FLOAT NULL,
|
|
34
|
+
amount FLOAT NULL,
|
|
45
35
|
status hub.take_request_status NOT NULL DEFAULT 'PENDING',
|
|
46
|
-
mp_status hub.mp_take_request_status NOT NULL DEFAULT 'PENDING',
|
|
47
|
-
status_changed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
36
|
+
mp_status hub.mp_take_request_status NOT NULL DEFAULT 'PENDING',
|
|
37
|
+
status_changed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
48
38
|
reserved_amount FLOAT NOT NULL,
|
|
49
|
-
mp_transfer_id UUID NULL,
|
|
50
|
-
-- mp_transfer_status is just informational
|
|
39
|
+
mp_transfer_id UUID NULL,
|
|
51
40
|
mp_transfer_status hub.mp_transfer_status NULL,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-- When we last attempted to complete the transfer
|
|
55
|
-
transfer_completion_attempted_at TIMESTAMPTZ NULL,
|
|
41
|
+
transfer_needs_completion BOOLEAN NOT NULL DEFAULT TRUE,
|
|
42
|
+
transfer_completion_attempted_at TIMESTAMPTZ NULL,
|
|
56
43
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
57
|
-
|
|
44
|
+
|
|
58
45
|
FOREIGN KEY (currency_key, casino_id) REFERENCES hub.currency(key, casino_id)
|
|
59
46
|
);
|
|
60
47
|
|
|
61
|
-
-- Create indexes for queries we'll run frequently
|
|
62
48
|
CREATE INDEX take_request_casino_id_idx ON hub.take_request(casino_id);
|
|
63
49
|
CREATE INDEX take_request_user_id_idx ON hub.take_request(user_id);
|
|
64
50
|
CREATE INDEX take_request_experience_id_idx ON hub.take_request(experience_id);
|
|
65
51
|
CREATE INDEX take_request_status_idx ON hub.take_request(status);
|
|
66
52
|
CREATE INDEX take_request_updated_at_idx ON hub.take_request(updated_at);
|
|
67
|
-
|
|
68
|
-
CREATE UNIQUE INDEX take_request_casino_id_mp_take_request_id_key ON hub.take_request(casino_id, mp_take_request_id);
|
|
69
|
-
-- A mp_transfer_id is unique per casino
|
|
53
|
+
CREATE UNIQUE INDEX take_request_casino_id_mp_take_request_id_key ON hub.take_request(casino_id, mp_take_request_id);
|
|
70
54
|
CREATE UNIQUE INDEX take_request_casino_id_mp_transfer_id_key ON hub.take_request(casino_id, mp_transfer_id) WHERE mp_transfer_id IS NOT NULL;
|
|
71
55
|
|
|
72
56
|
|
|
73
|
-
-- Create a function to automatically update timestamps
|
|
74
57
|
CREATE OR REPLACE FUNCTION hub.update_take_request_timestamps()
|
|
75
58
|
RETURNS TRIGGER AS $$
|
|
76
59
|
BEGIN
|
|
77
60
|
NEW.updated_at = NOW();
|
|
78
|
-
|
|
79
|
-
-- Update status_changed_at if status is changing
|
|
61
|
+
|
|
80
62
|
IF OLD.status IS DISTINCT FROM NEW.status THEN
|
|
81
63
|
NEW.status_changed_at = NOW();
|
|
82
64
|
END IF;
|
|
83
|
-
|
|
65
|
+
|
|
84
66
|
RETURN NEW;
|
|
85
67
|
END;
|
|
86
68
|
$$ LANGUAGE plpgsql;
|
|
87
69
|
|
|
88
|
-
-- Create trigger to call the function
|
|
89
70
|
CREATE TRIGGER update_take_request_timestamps
|
|
90
71
|
BEFORE UPDATE ON hub.take_request
|
|
91
72
|
FOR EACH ROW
|
|
92
73
|
EXECUTE FUNCTION hub.update_take_request_timestamps();
|
|
93
74
|
|
|
94
|
-
-- GRANTS
|
|
95
75
|
|
|
96
76
|
GRANT SELECT ON hub.take_request TO app_postgraphile;
|
|
97
77
|
|
|
98
|
-
-- RLS
|
|
99
78
|
|
|
100
79
|
ALTER TABLE hub.take_request ENABLE ROW LEVEL SECURITY;
|
|
101
80
|
|
|
102
81
|
CREATE POLICY select_take_request ON hub.take_request FOR SELECT USING (
|
|
103
82
|
hub_hidden.is_operator() OR (
|
|
104
|
-
-- Users can only see their own records
|
|
105
83
|
user_id = hub_hidden.current_user_id()
|
|
106
84
|
)
|
|
107
85
|
);
|
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
drop policy if exists select_user on hub.user;
|
|
2
2
|
create policy select_user on hub.user for select using (
|
|
3
|
-
hub_hidden.is_operator() or
|
|
4
|
-
-- Users can only see their own records
|
|
5
|
-
-- Users are global and not scoped to experiences
|
|
3
|
+
hub_hidden.is_operator() or
|
|
6
4
|
(
|
|
7
5
|
id = hub_hidden.current_user_id() and
|
|
8
|
-
-- casino_id match is redundant but we'll include it for consistency
|
|
9
6
|
casino_id = hub_hidden.current_casino_id()
|
|
10
7
|
)
|
|
11
8
|
);
|
|
12
9
|
|
|
13
|
-
-- These are all scoped to the current experience
|
|
14
|
-
--
|
|
15
|
-
-- Technically, matching on (user_id, experience_id) is sufficient since
|
|
16
|
-
-- experience implies casino, but we'll match on all three to be explicit.
|
|
17
10
|
|
|
18
11
|
drop policy if exists select_balance on hub.balance;
|
|
19
12
|
create policy select_balance on hub.balance for select using (
|
|
20
|
-
hub_hidden.is_operator() OR
|
|
21
|
-
-- Users can only see their own records for current experience
|
|
13
|
+
hub_hidden.is_operator() OR
|
|
22
14
|
(
|
|
23
|
-
user_id = hub_hidden.current_user_id() and
|
|
15
|
+
user_id = hub_hidden.current_user_id() and
|
|
24
16
|
experience_id = hub_hidden.current_experience_id() and
|
|
25
17
|
casino_id = hub_hidden.current_casino_id()
|
|
26
18
|
)
|
|
@@ -29,9 +21,8 @@ create policy select_balance on hub.balance for select using (
|
|
|
29
21
|
drop policy if exists select_deposit on hub.deposit;
|
|
30
22
|
create policy select_deposit on hub.deposit for select using (
|
|
31
23
|
hub_hidden.is_operator() OR
|
|
32
|
-
-- Users can only see their own records for current experience
|
|
33
24
|
(
|
|
34
|
-
user_id = hub_hidden.current_user_id() and
|
|
25
|
+
user_id = hub_hidden.current_user_id() and
|
|
35
26
|
experience_id = hub_hidden.current_experience_id() and
|
|
36
27
|
casino_id = hub_hidden.current_casino_id()
|
|
37
28
|
)
|
|
@@ -40,9 +31,8 @@ create policy select_deposit on hub.deposit for select using (
|
|
|
40
31
|
drop policy if exists select_withdrawal on hub.withdrawal;
|
|
41
32
|
create policy select_withdrawal on hub.withdrawal for select using (
|
|
42
33
|
hub_hidden.is_operator() OR
|
|
43
|
-
-- Users can only see their own records for current experience
|
|
44
34
|
(
|
|
45
|
-
user_id = hub_hidden.current_user_id() and
|
|
35
|
+
user_id = hub_hidden.current_user_id() and
|
|
46
36
|
experience_id = hub_hidden.current_experience_id() and
|
|
47
37
|
casino_id = hub_hidden.current_casino_id()
|
|
48
38
|
)
|
|
@@ -51,9 +41,8 @@ create policy select_withdrawal on hub.withdrawal for select using (
|
|
|
51
41
|
drop policy if exists select_session on hub.session;
|
|
52
42
|
create policy select_session on hub.session for select using (
|
|
53
43
|
hub_hidden.is_operator() OR
|
|
54
|
-
-- Users can only see their own records for current experience
|
|
55
44
|
(
|
|
56
|
-
user_id = hub_hidden.current_user_id() and
|
|
45
|
+
user_id = hub_hidden.current_user_id() and
|
|
57
46
|
experience_id = hub_hidden.current_experience_id() and
|
|
58
47
|
casino_id = hub_hidden.current_casino_id()
|
|
59
48
|
)
|
|
@@ -62,9 +51,8 @@ create policy select_session on hub.session for select using (
|
|
|
62
51
|
drop policy if exists select_withdrawal_request on hub.withdrawal_request;
|
|
63
52
|
create policy select_withdrawal_request on hub.withdrawal_request for select using (
|
|
64
53
|
hub_hidden.is_operator() OR
|
|
65
|
-
-- Users can only see their own records for current experience
|
|
66
54
|
(
|
|
67
|
-
user_id = hub_hidden.current_user_id() and
|
|
55
|
+
user_id = hub_hidden.current_user_id() and
|
|
68
56
|
experience_id = hub_hidden.current_experience_id() and
|
|
69
57
|
casino_id = hub_hidden.current_casino_id()
|
|
70
58
|
)
|
|
@@ -73,9 +61,8 @@ create policy select_withdrawal_request on hub.withdrawal_request for select usi
|
|
|
73
61
|
drop policy if exists select_faucet_claim on hub.faucet_claim;
|
|
74
62
|
create policy select_faucet_claim on hub.faucet_claim for select using (
|
|
75
63
|
hub_hidden.is_operator() OR
|
|
76
|
-
-- Users can only see their own records for current experience
|
|
77
64
|
(
|
|
78
|
-
user_id = hub_hidden.current_user_id() and
|
|
65
|
+
user_id = hub_hidden.current_user_id() and
|
|
79
66
|
experience_id = hub_hidden.current_experience_id() and
|
|
80
67
|
casino_id = hub_hidden.current_casino_id()
|
|
81
68
|
)
|
|
@@ -10,58 +10,48 @@ CREATE TABLE hub.hash_chain (
|
|
|
10
10
|
current_iteration int NOT NULL check (current_iteration between 0 and max_iteration)
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
-
-- TODO: Should probably index current_iteration
|
|
14
|
-
-- CREATE INDEX hash_chain_current_iteration_idx ON hub.hash_chain(current_iteration);
|
|
15
13
|
|
|
16
14
|
CREATE INDEX hash_chain_user_id_idx ON hub.hash_chain(user_id);
|
|
17
15
|
CREATE INDEX hash_chain_experience_id_idx ON hub.hash_chain(experience_id);
|
|
18
16
|
CREATE INDEX hash_chain_casino_id_idx ON hub.hash_chain(casino_id);
|
|
19
17
|
|
|
20
|
-
-- Ensure only one active hash_chain per user per experience per casino
|
|
21
18
|
CREATE UNIQUE INDEX active_hash_chain_idx
|
|
22
19
|
ON hub.hash_chain (user_id, experience_id, casino_id)
|
|
23
20
|
WHERE active = true;
|
|
24
21
|
|
|
25
22
|
CREATE TYPE hub.hash_kind AS ENUM (
|
|
26
|
-
'TERMINAL',
|
|
27
|
-
'INTERMEDIATE',
|
|
28
|
-
'PREIMAGE'
|
|
23
|
+
'TERMINAL',
|
|
24
|
+
'INTERMEDIATE',
|
|
25
|
+
'PREIMAGE'
|
|
29
26
|
);
|
|
30
27
|
|
|
31
|
-
-- this is the base table for all bets events
|
|
32
28
|
CREATE TABLE hub.hash (
|
|
33
29
|
id uuid PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
34
30
|
kind hub.hash_kind NOT NULL,
|
|
35
31
|
hash_chain_id uuid NOT NULL REFERENCES hub.hash_chain(id),
|
|
36
|
-
iteration int NOT NULL check (iteration >= 0),
|
|
37
|
-
digest bytea NOT NULL,
|
|
38
|
-
metadata jsonb NOT NULL DEFAULT '{}'
|
|
32
|
+
iteration int NOT NULL check (iteration >= 0),
|
|
33
|
+
digest bytea NOT NULL,
|
|
34
|
+
metadata jsonb NOT NULL DEFAULT '{}'
|
|
39
35
|
);
|
|
40
36
|
|
|
41
37
|
CREATE INDEX hash_hash_chain_id_idx ON hub.hash(hash_chain_id);
|
|
42
38
|
|
|
43
|
-
-- Ensure iterations are unique per hash_chain to avoid dupe mistakes
|
|
44
39
|
CREATE UNIQUE INDEX hash_hash_chain_id_iteration_idx ON hub.hash(hash_chain_id, iteration);
|
|
45
40
|
|
|
46
|
-
-- Ensure a hash_chain only has of each end-type hash
|
|
47
41
|
CREATE UNIQUE INDEX hash_chain_terminal_hash_idx ON hub.hash (hash_chain_id)
|
|
48
42
|
WHERE kind = 'TERMINAL';
|
|
49
43
|
CREATE UNIQUE INDEX hash_chain_preimage_hash_idx ON hub.hash (hash_chain_id)
|
|
50
44
|
WHERE kind = 'PREIMAGE';
|
|
51
45
|
|
|
52
|
-
-- GRANTS
|
|
53
46
|
|
|
54
47
|
GRANT SELECT ON TABLE hub.hash_chain TO app_postgraphile;
|
|
55
48
|
GRANT SELECT ON TABLE hub.hash TO app_postgraphile;
|
|
56
49
|
|
|
57
|
-
-- RLS
|
|
58
50
|
ALTER TABLE hub.hash_chain ENABLE ROW LEVEL SECURITY;
|
|
59
51
|
ALTER TABLE hub.hash ENABLE ROW LEVEL SECURITY;
|
|
60
52
|
|
|
61
53
|
CREATE POLICY select_hash_chain ON hub.hash_chain FOR SELECT USING (
|
|
62
|
-
-- Operator can see all rows
|
|
63
54
|
hub_hidden.is_operator() OR
|
|
64
|
-
-- User can see their own rows
|
|
65
55
|
(
|
|
66
56
|
user_id = hub_hidden.current_user_id() AND
|
|
67
57
|
experience_id = hub_hidden.current_experience_id() AND
|
|
@@ -69,14 +59,11 @@ CREATE POLICY select_hash_chain ON hub.hash_chain FOR SELECT USING (
|
|
|
69
59
|
)
|
|
70
60
|
);
|
|
71
61
|
|
|
72
|
-
-- TODO: Since we have RLS we could just make hashes public for simplicity/perf
|
|
73
62
|
CREATE POLICY select_hash ON hub.hash FOR SELECT USING (
|
|
74
|
-
-- Operator can see all rows
|
|
75
63
|
hub_hidden.is_operator() OR
|
|
76
|
-
-- User can see their own rows by checking the associated hash_chain
|
|
77
64
|
EXISTS (
|
|
78
|
-
SELECT 1
|
|
79
|
-
FROM hub.hash_chain
|
|
65
|
+
SELECT 1
|
|
66
|
+
FROM hub.hash_chain
|
|
80
67
|
WHERE hub.hash_chain.id = hub.hash.hash_chain_id
|
|
81
68
|
AND hub.hash_chain.user_id = hub_hidden.current_user_id()
|
|
82
69
|
AND hub.hash_chain.experience_id = hub_hidden.current_experience_id()
|