forked from stadust/pointercrate
-
Notifications
You must be signed in to change notification settings - Fork 1
/
20190105154218_new_audit_log.up.sql
369 lines (286 loc) · 12.8 KB
/
20190105154218_new_audit_log.up.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
-- Alright, audit_log overhault
-- In audit log entries we cannot use foreign keys because that would force us to delete log entries
-- when objects are removed from the db, or disallow the deletion of objects
-- Thus, we need to make sure we references database objects by a non-modifiable primary key, which
-- we do not actually use as foreign key
--
-- The problem here is, that the "demons" relation doesn't have such a column -
-- position and name (while both unique and even primary in "name"'s case') are modifiable
-- This is the reason we do not allow the deletion of demons as of right now
--
-- (Once the new backend is running and we no longer need to be backwards compatible with the
-- python codebase, we can ofc modify the demons table)
-- Global fallback table in case no temporary 'active_user' table was created in the current session
CREATE TABLE active_user (id INTEGER PRIMARY KEY); -- primary key required because diesel migrations break otherwise
-- TODO: generate a dummy member with ID 0
INSERT INTO active_user VALUES (0);
CREATE TABLE audit_log2 (
time TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE 'utc') NOT NULL,
audit_id SERIAL PRIMARY KEY NOT NULL,
userid INTEGER NOT NULL -- REFERENCES members(member_id)
);
CREATE TABLE demon_additions (
-- Note that this currently forces us to not delete demons
name CITEXT REFERENCES demons(name) ON DELETE RESTRICT ON UPDATE CASCADE NOT NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_demon_addition() RETURNS trigger AS $demon_add_trigger$
BEGIN
INSERT INTO demon_additions (userid, name) (SELECT id, NEW.name FROM active_user LIMIT 1);
RETURN NEW;
END;
$demon_add_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER demon_addition_trigger AFTER INSERT ON demons FOR EACH ROW EXECUTE PROCEDURE audit_demon_addition();
CREATE TABLE demon_modifications (
-- Column that keeps track of the demon that was modified
-- Note that this currently forces us to not delete demons
demon CITEXT REFERENCES demons(name) ON DELETE RESTRICT ON UPDATE CASCADE NOT NULL,
-- Column that keeps track of changes to the demon's name
name CITEXT NULL,
position SMALLINT NULL,
requirement SMALLINT NULL,
video VARCHAR(200) NULL,
verifier INT NULL,
publisher INT NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_demon_modification() RETURNS trigger AS $demon_modification_trigger$
DECLARE
name_change CITEXT;
position_change SMALLINT;
requirement_change SMALLINT;
video_change VARCHAR(200);
verifier_change SMALLINT;
publisher_change SMALLINT;
BEGIN
IF (OLD.name <> NEW.name) THEN
name_change = OLD.name;
END IF;
IF (OLD.position <> NEW.position) THEN
position_change = OLD.position;
END IF;
IF (OLD.requirement <> NEW.requirement) THEN
requirement_change = OLD.requirement;
END IF;
IF (OLD.video <> NEW.video) THEN
video_change = OLD.video;
END IF;
IF (OLD.verifier <> NEW.verifier) THEN
verifier_change = OLD.verifier;
END IF;
IF (OLD.publisher <> NEW.publisher) THEN
publisher_change = OLD.publisher;
END IF;
INSERT INTO demon_modifications (userid, demon, name, position, requirement, video, verifier, publisher)
(SELECT id, NEW.name, name_change, position_change, requirement_change, video_change, verifier_change, publisher_change
FROM active_user LIMIT 1);
RETURN NEW;
END;
$demon_modification_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER demon_modification_trigger AFTER UPDATE ON demons FOR EACH ROW EXECUTE PROCEDURE audit_demon_modification();
CREATE TABLE record_additions (
id INTEGER NOT NULL -- REFERENCES records(id)
) INHERITS (audit_log2);
CREATE FUNCTION audit_record_addition() RETURNS trigger AS $record_add_trigger$
BEGIN
INSERT INTO record_additions (userid, id) (SELECT id, NEW.id FROM active_user LIMIT 1);
RETURN NEW;
END;
$record_add_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER record_addition_trigger AFTER INSERT ON records FOR EACH ROW EXECUTE PROCEDURE audit_record_addition();
CREATE TABLE record_modifications (
id INTEGER NOT NULL, -- REFERENCES records(id)
progress SMALLINT NULL,
video VARCHAR(200) NULL,
status_ RECORD_STATUS NULL,
player INT NULL, -- REFERENCES players(id)
demon CITEXT NULL -- REFERENCES demons(name)
) INHERITS (audit_log2);
CREATE FUNCTION audit_record_modification() RETURNS trigger AS $record_modification_trigger$
DECLARE
progress_change SMALLINT;
video_change VARCHAR(200);
status_change RECORD_STATUS;
player_change INT;
demon_change CITEXT;
BEGIN
if (OLD.progress <> NEW.progress) THEN
progress_change = OLD.progress;
END IF;
IF (OLD.video <> NEW.video) THEN
video_change = OLD.video;
END IF;
IF (OLD.status_ <> NEW.status_) THEN
status_change = OLD.status_;
END IF;
IF (OLD.player <> NEW.player) THEN
player_change = OLD.player;
END IF;
IF (OLD.demon <> NEW.demon) THEN
demon_change = OLD.demon;
END IF;
INSERT INTO record_modifications (userid, id, progress, video, status_, player, demon)
(SELECT id, NEW.id, progress_change, video_change, status_change, player_change, demon_change
FROM active_user LIMIT 1);
RETURN NEW;
END;
$record_modification_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER record_modification_trigger AFTER UPDATE ON records FOR EACH ROW EXECUTE PROCEDURE audit_record_modification();
-- Before deletion we add a `record_modifications` entry that's a copy of the record directly before deletion
CREATE TABLE record_deletions (
id INTEGER NOT NULL -- REFERENCES records(id)
) INHERITS (audit_log2);
CREATE FUNCTION audit_record_deletion() RETURNS trigger AS $record_deletion_trigger$
BEGIN
INSERT INTO record_modifications (userid, id, progress, video, status_, player, demon)
(SELECT id, OLD.id, OLD.progress, OLD.video, OLD.status_, OLD.player, OLD.demon
FROM active_user LIMIT 1);
INSERT INTO record_deletions (userid, id)
(SELECT id, OLD.id FROM active_user LIMIT 1);
RETURN NULL;
END;
$record_deletion_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER record_deletion_trigger AFTER DELETE ON records FOR EACH ROW EXECUTE PROCEDURE audit_record_deletion();
CREATE TABLE player_additions (
id INTEGER NOT NULL -- REFERENCES players(id)
) INHERITS (audit_log2);
CREATE FUNCTION audit_player_addition() RETURNS trigger AS $record_addition_trigger$
BEGIN
INSERT INTO player_additions(userid, id)
(SELECT id, NEW.id FROM active_user LIMIT 1);
RETURN NEW;
END;
$record_addition_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER player_addition_trigger AFTER INSERT ON players FOR EACH ROW EXECUTE PROCEDURE audit_player_addition();
CREATE TABLE player_modifications (
id INTEGER NOT NULL, -- REFERENCES players(id)
name CITEXT NULL,
banned BOOLEAN NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_player_modification() RETURNS trigger as $player_modification_trigger$
DECLARE
name_change CITEXT;
banned_change BOOLEAN;
BEGIN
IF (OLD.name <> NEW.name) THEN
name_change = OLD.name;
END IF;
IF (OLD.banned <> NEW.banned) THEN
banned_change = OLD.banned;
END IF;
INSERT INTO player_modifications (userid, id, name, banned)
(SELECT id, NEW.id, name_change, banned_change FROM active_user LIMIT 1);
RETURN NEW;
END;
$player_modification_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER player_modification_trigger AFTER UPDATE ON players FOR EACH ROW EXECUTE PROCEDURE audit_player_modification();
-- See handling of record_deletions
CREATE TABLE player_deletions (
id INTEGER NOT NULL -- REFERENCES players(id)
) INHERITS (audit_log2);
CREATE FUNCTION audit_player_deletion() RETURNS trigger AS $player_deletion_trigger$
BEGIN
INSERT INTO player_modifications (userid, id, name, banned)
(SELECT id, OLD.id, OLD.name, OLD.banned
FROM active_user LIMIT 1);
INSERT INTO player_deletions (userid, id)
(SELECT id, OLD.id FROM active_user LIMIT 1);
RETURN NULL;
END;
$player_deletion_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER player_deletion_trigger AFTER DELETE ON players FOR EACH ROW EXECUTE PROCEDURE audit_player_deletion();
CREATE TABLE creator_additions (
creator INTEGER NOT NULL,
demon CITEXT NOT NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_creator_addition() RETURNS trigger AS $audit_creator_addition$
BEGIN
INSERT INTO creator_additions (userid, creator, demon)
(SELECT id, NEW.creator, NEW.demon
FROM active_user LIMIT 1);
RETURN NEW;
END;
$audit_creator_addition$ LANGUAGE plpgsql;
CREATE TRIGGER creator_addition_trigger AFTER INSERT ON creators FOR EACH ROW EXECUTE PROCEDURE audit_creator_addition();
CREATE TABLE creator_deletions(
creator INTEGER NOT NULL,
demon CITEXT NOT NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_creator_deletion() RETURNS trigger AS $creator_deletion_trigger$
BEGIN
INSERT INTO creator_deletions (userid, creator, demon)
(SELECT id, OLD.creator, OLD.demon
FROM active_user LIMIT 1);
RETURN NULL;
END;
$creator_deletion_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER creator_deletion_trigger AFTER DELETE ON creators FOR EACH ROW EXECUTE PROCEDURE audit_creator_deletion();
CREATE TABLE submitter_modifications (
submitter INTEGER NOT NULL,
banned BOOLEAN NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_submitter_modification() RETURNS trigger as $submitter_modifications_trigger$
DECLARE
banned_change BOOLEAN;
BEGIN
IF (OLD.banned <> NEW.banned) THEN
banned_change = OLD.banned;
END IF;
INSERT INTO submitter_modifications (userid, submitter, banned)
(SELECT id, NEW.submitter_id, banned_change FROM active_user LIMIT 1);
RETURN NEW;
END;
$submitter_modifications_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER submitter_modification_trigger AFTER UPDATE ON submitters FOR EACH ROW EXECUTE PROCEDURE audit_submitter_modification();
CREATE TABLE user_additions (
id INTEGER NOT NULL -- REFERENCES members(member_id)
) INHERITS (audit_log2);
CREATE FUNCTION audit_user_addition() RETURNS trigger AS $audit_user_addition$
BEGIN
-- cannot be logged in during registration
INSERT INTO user_additions (userid, id) VALUES (0, NEW.member_id);
RETURN NEW;
END;
$audit_user_addition$ LANGUAGE plpgsql;
CREATE TRIGGER user_addition_trigger AFTER INSERT ON members FOR EACH ROW EXECUTE PROCEDURE audit_user_addition();
CREATE TABLE user_modifications (
id INTEGER NOT NULL, -- REFERENCES members(member_id)
-- fields updatable by user themself
display_name CITEXT NULL,
youtube_channel CITEXT NULL,
-- fields updatable by staff
permissions BIT(16) NULL
) INHERITS (audit_log2);
CREATE FUNCTION audit_user_modification() RETURNS trigger as $user_modification_trigger$
DECLARE
display_name_change CITEXT;
youtube_channel_change BOOLEAN;
permissions_change BIT(16);
BEGIN
IF (OLD.display_name <> NEW.display_name) THEN
display_name_change = OLD.display_name;
END IF;
IF (OLD.youtube_channel <> NEW.youtube_channel) THEN
youtube_channel_change = OLD.youtube_channel;
END IF;
IF (OLD.permissions <> NEW.permissions) THEN
permissions_change = OLD.permissions;
END IF;
INSERT INTO user_modifications (userid, id, display_name, youtube_channel, permissions)
(SELECT id, NEW.member_id, display_name_change, youtube_channel_change, permissions_change FROM active_user LIMIT 1);
RETURN NEW;
END;
$user_modification_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER user_modification_trigger AFTER UPDATE ON members FOR EACH ROW EXECUTE PROCEDURE audit_user_modification();
CREATE TABLE user_deletions (
id INTEGER NOT NULL -- REFERENCES members(member_id)
) INHERITS (audit_log2);
CREATE FUNCTION audit_user_deletion() RETURNS trigger AS $user_deletion_trigger$
BEGIN
INSERT INTO user_modifications (userid, id, display_name, youtube_channel, permissions)
(SELECT id, OLD.member_id, OLD.display_name, OLD.youtube_channel, OLD.permissions
FROM active_user LIMIT 1);
INSERT INTO user_deletions (userid, id)
(SELECT id, OLD.member_id FROM active_user LIMIT 1);
RETURN NULL;
END;
$user_deletion_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER user_deletion_trigger AFTER DELETE ON members FOR EACH ROW EXECUTE PROCEDURE audit_user_deletion();