@helyx/module-account-gate 1.0.1
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/CHANGELOG.md +22 -0
- package/LICENSE +725 -0
- package/README.md +90 -0
- package/dist/challenges.d.ts +16 -0
- package/dist/challenges.js +233 -0
- package/dist/configuration.d.ts +41 -0
- package/dist/configuration.js +224 -0
- package/dist/contracts.d.ts +82 -0
- package/dist/contracts.js +56 -0
- package/dist/enforcement.d.ts +19 -0
- package/dist/enforcement.js +110 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +3324 -0
- package/dist/managed-resource-summary.d.ts +3 -0
- package/dist/managed-resource-summary.js +6 -0
- package/dist/member-resource.d.ts +3 -0
- package/dist/member-resource.js +348 -0
- package/dist/panel-resource.d.ts +15 -0
- package/dist/panel-resource.js +527 -0
- package/dist/password-entry.d.ts +8 -0
- package/dist/password-entry.js +59 -0
- package/dist/password-resource.d.ts +8 -0
- package/dist/password-resource.js +208 -0
- package/dist/privacy.d.ts +4 -0
- package/dist/privacy.js +20 -0
- package/dist/public-channel-resource.d.ts +4 -0
- package/dist/public-channel-resource.js +135 -0
- package/dist/question-resource.d.ts +3 -0
- package/dist/question-resource.js +246 -0
- package/dist/records.d.ts +508 -0
- package/dist/records.js +456 -0
- package/dist/workflow.d.ts +43 -0
- package/dist/workflow.js +167 -0
- package/manifest.json +750 -0
- package/migrations/0001_account_gate_foundation.sql +303 -0
- package/migrations/0002_account_gate_panel_message.sql +27 -0
- package/migrations/0003_account_gate_revoked_member_status.sql +17 -0
- package/migrations/0004_account_gate_multiple_panels.sql +23 -0
- package/migrations/0005_account_gate_panel_passwords.sql +45 -0
- package/package.json +54 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS account_gate_gate_panels (
|
|
2
|
+
panel_id text PRIMARY KEY,
|
|
3
|
+
guild_id text NOT NULL UNIQUE,
|
|
4
|
+
channel_id text NOT NULL,
|
|
5
|
+
message_id text NOT NULL,
|
|
6
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
7
|
+
created_at timestamptz NOT NULL,
|
|
8
|
+
updated_at timestamptz NOT NULL,
|
|
9
|
+
CHECK (updated_at >= created_at)
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
CREATE TABLE IF NOT EXISTS account_gate_public_channels (
|
|
13
|
+
guild_id text NOT NULL,
|
|
14
|
+
channel_id text NOT NULL,
|
|
15
|
+
created_at timestamptz NOT NULL,
|
|
16
|
+
PRIMARY KEY (guild_id, channel_id)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE TABLE IF NOT EXISTS account_gate_questions (
|
|
20
|
+
question_id text PRIMARY KEY,
|
|
21
|
+
guild_id text NOT NULL,
|
|
22
|
+
question_text text NOT NULL CHECK (char_length(question_text) BETWEEN 1 AND 200),
|
|
23
|
+
answers_json text NOT NULL,
|
|
24
|
+
correct_option_index integer NOT NULL CHECK (correct_option_index BETWEEN 0 AND 4),
|
|
25
|
+
enabled boolean NOT NULL,
|
|
26
|
+
sort_order integer NOT NULL CHECK (sort_order BETWEEN 0 AND 1000),
|
|
27
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
28
|
+
created_at timestamptz NOT NULL,
|
|
29
|
+
updated_at timestamptz NOT NULL,
|
|
30
|
+
UNIQUE (guild_id, question_id),
|
|
31
|
+
CHECK (updated_at >= created_at)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
CREATE INDEX IF NOT EXISTS account_gate_questions_guild_order_idx
|
|
35
|
+
ON account_gate_questions (guild_id, sort_order, question_id);
|
|
36
|
+
CREATE TABLE IF NOT EXISTS account_gate_question_creators (
|
|
37
|
+
attribution_id text PRIMARY KEY,
|
|
38
|
+
question_id text NOT NULL UNIQUE,
|
|
39
|
+
guild_id text NOT NULL,
|
|
40
|
+
creator_user_id text NOT NULL,
|
|
41
|
+
created_at timestamptz NOT NULL
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE INDEX IF NOT EXISTS account_gate_question_creator_privacy_idx
|
|
45
|
+
ON account_gate_question_creators (
|
|
46
|
+
creator_user_id,
|
|
47
|
+
created_at,
|
|
48
|
+
attribution_id
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE IF NOT EXISTS account_gate_password_secrets (
|
|
52
|
+
guild_id text PRIMARY KEY,
|
|
53
|
+
encoded_hash text NOT NULL,
|
|
54
|
+
ignore_case boolean NOT NULL,
|
|
55
|
+
trim_whitespace boolean NOT NULL,
|
|
56
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
57
|
+
created_at timestamptz NOT NULL,
|
|
58
|
+
updated_at timestamptz NOT NULL,
|
|
59
|
+
CHECK (updated_at >= created_at)
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
CREATE TABLE IF NOT EXISTS account_gate_attempts (
|
|
63
|
+
attempt_id text PRIMARY KEY,
|
|
64
|
+
guild_id text NOT NULL,
|
|
65
|
+
member_user_id text NOT NULL,
|
|
66
|
+
session_id text NOT NULL,
|
|
67
|
+
challenge_type text NOT NULL CHECK (
|
|
68
|
+
challenge_type IN (
|
|
69
|
+
'quick_sum', 'button_sequence', 'number_order', 'symbol_match',
|
|
70
|
+
'modal_recall', 'server_question', 'password_entry', 'emoji_entry'
|
|
71
|
+
)
|
|
72
|
+
),
|
|
73
|
+
outcome text NOT NULL CHECK (outcome IN ('passed', 'failed', 'expired')),
|
|
74
|
+
reason_code text NOT NULL,
|
|
75
|
+
duration_ms bigint NOT NULL CHECK (duration_ms >= 0),
|
|
76
|
+
retention_until timestamptz NOT NULL,
|
|
77
|
+
created_at timestamptz NOT NULL,
|
|
78
|
+
UNIQUE (guild_id, attempt_id),
|
|
79
|
+
UNIQUE (guild_id, session_id, challenge_type)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
CREATE INDEX IF NOT EXISTS account_gate_attempts_member_privacy_idx
|
|
83
|
+
ON account_gate_attempts (member_user_id, created_at, attempt_id);
|
|
84
|
+
CREATE INDEX IF NOT EXISTS account_gate_attempts_retention_idx
|
|
85
|
+
ON account_gate_attempts (retention_until, attempt_id);
|
|
86
|
+
|
|
87
|
+
CREATE TABLE IF NOT EXISTS account_gate_member_summaries (
|
|
88
|
+
summary_id text NOT NULL UNIQUE,
|
|
89
|
+
guild_id text NOT NULL,
|
|
90
|
+
member_user_id text NOT NULL,
|
|
91
|
+
previous_success_at timestamptz,
|
|
92
|
+
failure_count integer NOT NULL CHECK (failure_count >= 0),
|
|
93
|
+
lockout_until timestamptz,
|
|
94
|
+
rejoin_count integer NOT NULL CHECK (rejoin_count >= 0),
|
|
95
|
+
join_generation integer NOT NULL CHECK (join_generation > 0),
|
|
96
|
+
account_created_at timestamptz NOT NULL,
|
|
97
|
+
joined_at timestamptz NOT NULL,
|
|
98
|
+
deadline_at timestamptz NOT NULL,
|
|
99
|
+
pending_reason text NOT NULL CHECK (
|
|
100
|
+
pending_reason IN ('none', 'account_too_new')
|
|
101
|
+
),
|
|
102
|
+
last_failure_terminal_id text,
|
|
103
|
+
left_at timestamptz,
|
|
104
|
+
last_decision text NOT NULL CHECK (
|
|
105
|
+
last_decision IN (
|
|
106
|
+
'pending', 'finalizing', 'passed', 'failed', 'review', 'kick_pending',
|
|
107
|
+
'kicked', 'dismissed'
|
|
108
|
+
)
|
|
109
|
+
),
|
|
110
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
111
|
+
retention_until timestamptz NOT NULL,
|
|
112
|
+
created_at timestamptz NOT NULL,
|
|
113
|
+
updated_at timestamptz NOT NULL,
|
|
114
|
+
PRIMARY KEY (guild_id, member_user_id),
|
|
115
|
+
CHECK (updated_at >= created_at)
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
CREATE INDEX IF NOT EXISTS account_gate_member_summary_privacy_idx
|
|
119
|
+
ON account_gate_member_summaries (member_user_id, created_at, guild_id);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS account_gate_member_summary_retention_idx
|
|
121
|
+
ON account_gate_member_summaries (retention_until, guild_id, member_user_id);
|
|
122
|
+
|
|
123
|
+
CREATE TABLE IF NOT EXISTS account_gate_reviews (
|
|
124
|
+
review_id text PRIMARY KEY,
|
|
125
|
+
pending_key text NOT NULL UNIQUE,
|
|
126
|
+
guild_id text NOT NULL,
|
|
127
|
+
member_user_id text NOT NULL,
|
|
128
|
+
join_generation integer NOT NULL CHECK (join_generation > 0),
|
|
129
|
+
status text NOT NULL CHECK (
|
|
130
|
+
status IN (
|
|
131
|
+
'pending', 'claim_approve', 'claim_retry', 'claim_kick',
|
|
132
|
+
'claim_dismiss', 'approved', 'retry', 'kicked', 'dismissed'
|
|
133
|
+
)
|
|
134
|
+
),
|
|
135
|
+
delivery_status text NOT NULL CHECK (
|
|
136
|
+
delivery_status IN ('pending', 'sent', 'failed')
|
|
137
|
+
),
|
|
138
|
+
claim_action text,
|
|
139
|
+
claim_expires_at timestamptz,
|
|
140
|
+
reason_code text NOT NULL,
|
|
141
|
+
challenge_types_json text NOT NULL,
|
|
142
|
+
failed_attempts integer NOT NULL CHECK (failed_attempts >= 0),
|
|
143
|
+
expired_attempts integer NOT NULL CHECK (expired_attempts >= 0),
|
|
144
|
+
review_channel_id text,
|
|
145
|
+
review_message_id text,
|
|
146
|
+
decided_by_user_id text,
|
|
147
|
+
decided_at timestamptz,
|
|
148
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
149
|
+
retention_until timestamptz NOT NULL,
|
|
150
|
+
created_at timestamptz NOT NULL,
|
|
151
|
+
updated_at timestamptz NOT NULL,
|
|
152
|
+
UNIQUE (guild_id, review_id),
|
|
153
|
+
UNIQUE (guild_id, review_message_id),
|
|
154
|
+
CHECK (updated_at >= created_at)
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
CREATE UNIQUE INDEX IF NOT EXISTS account_gate_one_pending_review_idx
|
|
158
|
+
ON account_gate_reviews (guild_id, member_user_id)
|
|
159
|
+
WHERE status = 'pending';
|
|
160
|
+
|
|
161
|
+
CREATE TABLE IF NOT EXISTS account_gate_terminal_finalizations (
|
|
162
|
+
finalization_id text PRIMARY KEY,
|
|
163
|
+
guild_id text NOT NULL,
|
|
164
|
+
member_user_id text NOT NULL,
|
|
165
|
+
session_id text NOT NULL,
|
|
166
|
+
join_generation integer NOT NULL CHECK (join_generation > 0),
|
|
167
|
+
outcome text NOT NULL CHECK (outcome IN ('passed', 'failed')),
|
|
168
|
+
challenge_type text NOT NULL,
|
|
169
|
+
challenge_types_json text NOT NULL,
|
|
170
|
+
work_created_at timestamptz NOT NULL,
|
|
171
|
+
status text NOT NULL CHECK (
|
|
172
|
+
status IN ('pending', 'failure_recorded', 'completed', 'cancelled')
|
|
173
|
+
),
|
|
174
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
175
|
+
retention_until timestamptz NOT NULL,
|
|
176
|
+
created_at timestamptz NOT NULL,
|
|
177
|
+
updated_at timestamptz NOT NULL,
|
|
178
|
+
UNIQUE (guild_id, session_id),
|
|
179
|
+
CHECK (updated_at >= created_at)
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
CREATE INDEX IF NOT EXISTS account_gate_terminal_finalization_status_idx
|
|
183
|
+
ON account_gate_terminal_finalizations (status, created_at, finalization_id);
|
|
184
|
+
|
|
185
|
+
CREATE INDEX IF NOT EXISTS account_gate_reviews_member_privacy_idx
|
|
186
|
+
ON account_gate_reviews (member_user_id, created_at, review_id);
|
|
187
|
+
CREATE INDEX IF NOT EXISTS account_gate_reviews_actor_privacy_idx
|
|
188
|
+
ON account_gate_reviews (decided_by_user_id, created_at, review_id)
|
|
189
|
+
WHERE decided_by_user_id IS NOT NULL;
|
|
190
|
+
CREATE INDEX IF NOT EXISTS account_gate_reviews_retention_idx
|
|
191
|
+
ON account_gate_reviews (retention_until, review_id);
|
|
192
|
+
|
|
193
|
+
CREATE TABLE IF NOT EXISTS account_gate_role_transitions (
|
|
194
|
+
transition_id text PRIMARY KEY,
|
|
195
|
+
guild_id text NOT NULL,
|
|
196
|
+
member_user_id text NOT NULL,
|
|
197
|
+
verified_role_id text NOT NULL,
|
|
198
|
+
pending_remove_role_ids_json text NOT NULL,
|
|
199
|
+
status text NOT NULL CHECK (status IN ('pending', 'partial', 'completed', 'review')),
|
|
200
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
201
|
+
next_retry_at timestamptz,
|
|
202
|
+
completed_at timestamptz,
|
|
203
|
+
created_at timestamptz NOT NULL,
|
|
204
|
+
updated_at timestamptz NOT NULL,
|
|
205
|
+
UNIQUE (guild_id, transition_id),
|
|
206
|
+
UNIQUE (guild_id, member_user_id),
|
|
207
|
+
CHECK (updated_at >= created_at)
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
CREATE INDEX IF NOT EXISTS account_gate_role_transition_privacy_idx
|
|
211
|
+
ON account_gate_role_transitions (member_user_id, created_at, transition_id);
|
|
212
|
+
CREATE INDEX IF NOT EXISTS account_gate_role_transition_retry_idx
|
|
213
|
+
ON account_gate_role_transitions (status, next_retry_at, transition_id)
|
|
214
|
+
WHERE status IN ('pending', 'partial');
|
|
215
|
+
|
|
216
|
+
CREATE TABLE IF NOT EXISTS account_gate_strict_modes (
|
|
217
|
+
guild_id text PRIMARY KEY,
|
|
218
|
+
status text NOT NULL CHECK (status IN ('active', 'expired', 'disabled')),
|
|
219
|
+
ends_at timestamptz NOT NULL,
|
|
220
|
+
generation integer NOT NULL CHECK (generation > 0),
|
|
221
|
+
activated_by_user_id text,
|
|
222
|
+
revision integer NOT NULL CHECK (revision > 0),
|
|
223
|
+
created_at timestamptz NOT NULL,
|
|
224
|
+
updated_at timestamptz NOT NULL,
|
|
225
|
+
CHECK (updated_at >= created_at)
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
CREATE INDEX IF NOT EXISTS account_gate_strict_mode_expiry_idx
|
|
229
|
+
ON account_gate_strict_modes (status, ends_at, guild_id)
|
|
230
|
+
WHERE status = 'active';
|
|
231
|
+
CREATE INDEX IF NOT EXISTS account_gate_strict_mode_actor_privacy_idx
|
|
232
|
+
ON account_gate_strict_modes (activated_by_user_id, created_at, guild_id)
|
|
233
|
+
WHERE activated_by_user_id IS NOT NULL;
|
|
234
|
+
|
|
235
|
+
CREATE TABLE IF NOT EXISTS account_gate_privacy_suppressions (
|
|
236
|
+
suppression_id text NOT NULL UNIQUE,
|
|
237
|
+
guild_id text NOT NULL,
|
|
238
|
+
member_user_id text NOT NULL,
|
|
239
|
+
suppressed_at timestamptz NOT NULL,
|
|
240
|
+
created_at timestamptz NOT NULL,
|
|
241
|
+
PRIMARY KEY (guild_id, member_user_id)
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
CREATE INDEX IF NOT EXISTS account_gate_privacy_suppression_subject_idx
|
|
245
|
+
ON account_gate_privacy_suppressions (member_user_id, created_at, guild_id);
|
|
246
|
+
|
|
247
|
+
CREATE OR REPLACE FUNCTION account_gate_install_privacy_suppression()
|
|
248
|
+
RETURNS trigger
|
|
249
|
+
LANGUAGE plpgsql
|
|
250
|
+
AS $$
|
|
251
|
+
BEGIN
|
|
252
|
+
INSERT INTO account_gate_privacy_suppressions (
|
|
253
|
+
suppression_id,
|
|
254
|
+
guild_id,
|
|
255
|
+
member_user_id,
|
|
256
|
+
suppressed_at,
|
|
257
|
+
created_at
|
|
258
|
+
)
|
|
259
|
+
VALUES (
|
|
260
|
+
OLD.guild_id || ':' || OLD.member_user_id,
|
|
261
|
+
OLD.guild_id,
|
|
262
|
+
OLD.member_user_id,
|
|
263
|
+
clock_timestamp(),
|
|
264
|
+
clock_timestamp()
|
|
265
|
+
)
|
|
266
|
+
ON CONFLICT (guild_id, member_user_id)
|
|
267
|
+
DO UPDATE SET suppressed_at = GREATEST(
|
|
268
|
+
account_gate_privacy_suppressions.suppressed_at,
|
|
269
|
+
EXCLUDED.suppressed_at
|
|
270
|
+
);
|
|
271
|
+
RETURN OLD;
|
|
272
|
+
END;
|
|
273
|
+
$$;
|
|
274
|
+
|
|
275
|
+
DROP TRIGGER IF EXISTS account_gate_attempt_privacy_suppressed
|
|
276
|
+
ON account_gate_attempts;
|
|
277
|
+
CREATE TRIGGER account_gate_attempt_privacy_suppressed
|
|
278
|
+
AFTER DELETE ON account_gate_attempts
|
|
279
|
+
FOR EACH ROW EXECUTE FUNCTION account_gate_install_privacy_suppression();
|
|
280
|
+
|
|
281
|
+
DROP TRIGGER IF EXISTS account_gate_summary_privacy_suppressed
|
|
282
|
+
ON account_gate_member_summaries;
|
|
283
|
+
CREATE TRIGGER account_gate_summary_privacy_suppressed
|
|
284
|
+
AFTER DELETE ON account_gate_member_summaries
|
|
285
|
+
FOR EACH ROW EXECUTE FUNCTION account_gate_install_privacy_suppression();
|
|
286
|
+
|
|
287
|
+
DROP TRIGGER IF EXISTS account_gate_review_privacy_suppressed
|
|
288
|
+
ON account_gate_reviews;
|
|
289
|
+
CREATE TRIGGER account_gate_review_privacy_suppressed
|
|
290
|
+
AFTER DELETE ON account_gate_reviews
|
|
291
|
+
FOR EACH ROW EXECUTE FUNCTION account_gate_install_privacy_suppression();
|
|
292
|
+
|
|
293
|
+
DROP TRIGGER IF EXISTS account_gate_transition_privacy_suppressed
|
|
294
|
+
ON account_gate_role_transitions;
|
|
295
|
+
CREATE TRIGGER account_gate_transition_privacy_suppressed
|
|
296
|
+
AFTER DELETE ON account_gate_role_transitions
|
|
297
|
+
FOR EACH ROW EXECUTE FUNCTION account_gate_install_privacy_suppression();
|
|
298
|
+
|
|
299
|
+
DROP TRIGGER IF EXISTS account_gate_terminal_privacy_suppressed
|
|
300
|
+
ON account_gate_terminal_finalizations;
|
|
301
|
+
CREATE TRIGGER account_gate_terminal_privacy_suppressed
|
|
302
|
+
AFTER DELETE ON account_gate_terminal_finalizations
|
|
303
|
+
FOR EACH ROW EXECUTE FUNCTION account_gate_install_privacy_suppression();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
ALTER TABLE account_gate_gate_panels
|
|
2
|
+
ADD COLUMN IF NOT EXISTS message_body text;
|
|
3
|
+
|
|
4
|
+
UPDATE account_gate_gate_panels
|
|
5
|
+
SET message_body =
|
|
6
|
+
'Complete a short human-interaction check to access the server. Press the button below when you are ready.'
|
|
7
|
+
WHERE message_body IS NULL;
|
|
8
|
+
|
|
9
|
+
ALTER TABLE account_gate_gate_panels
|
|
10
|
+
ALTER COLUMN message_body SET DEFAULT
|
|
11
|
+
'Complete a short human-interaction check to access the server. Press the button below when you are ready.',
|
|
12
|
+
ALTER COLUMN message_body SET NOT NULL;
|
|
13
|
+
|
|
14
|
+
DO $$
|
|
15
|
+
BEGIN
|
|
16
|
+
IF NOT EXISTS (
|
|
17
|
+
SELECT 1
|
|
18
|
+
FROM pg_constraint
|
|
19
|
+
WHERE conname = 'account_gate_gate_panels_message_body_length'
|
|
20
|
+
AND conrelid = 'account_gate_gate_panels'::regclass
|
|
21
|
+
) THEN
|
|
22
|
+
ALTER TABLE account_gate_gate_panels
|
|
23
|
+
ADD CONSTRAINT account_gate_gate_panels_message_body_length
|
|
24
|
+
CHECK (char_length(message_body) BETWEEN 1 AND 1000);
|
|
25
|
+
END IF;
|
|
26
|
+
END
|
|
27
|
+
$$;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
DO $$
|
|
2
|
+
BEGIN
|
|
3
|
+
IF to_regclass('account_gate_member_summaries') IS NOT NULL THEN
|
|
4
|
+
ALTER TABLE account_gate_member_summaries
|
|
5
|
+
DROP CONSTRAINT IF EXISTS account_gate_member_summaries_last_decision_check;
|
|
6
|
+
|
|
7
|
+
ALTER TABLE account_gate_member_summaries
|
|
8
|
+
ADD CONSTRAINT account_gate_member_summaries_last_decision_check
|
|
9
|
+
CHECK (
|
|
10
|
+
last_decision IN (
|
|
11
|
+
'pending', 'finalizing', 'passed', 'failed', 'review', 'kick_pending',
|
|
12
|
+
'kicked', 'dismissed', 'revoked'
|
|
13
|
+
)
|
|
14
|
+
);
|
|
15
|
+
END IF;
|
|
16
|
+
END
|
|
17
|
+
$$;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
ALTER TABLE account_gate_gate_panels
|
|
2
|
+
ADD COLUMN IF NOT EXISTS access_type text NOT NULL DEFAULT 'challenges';
|
|
3
|
+
|
|
4
|
+
DO $$
|
|
5
|
+
BEGIN
|
|
6
|
+
IF NOT EXISTS (
|
|
7
|
+
SELECT 1
|
|
8
|
+
FROM pg_constraint
|
|
9
|
+
WHERE conname = 'account_gate_gate_panels_access_type'
|
|
10
|
+
AND conrelid = 'account_gate_gate_panels'::regclass
|
|
11
|
+
) THEN
|
|
12
|
+
ALTER TABLE account_gate_gate_panels
|
|
13
|
+
ADD CONSTRAINT account_gate_gate_panels_access_type
|
|
14
|
+
CHECK (access_type IN ('challenges', 'password', 'emoji'));
|
|
15
|
+
END IF;
|
|
16
|
+
END
|
|
17
|
+
$$;
|
|
18
|
+
|
|
19
|
+
ALTER TABLE account_gate_gate_panels
|
|
20
|
+
DROP CONSTRAINT IF EXISTS account_gate_gate_panels_guild_id_key;
|
|
21
|
+
|
|
22
|
+
CREATE INDEX IF NOT EXISTS account_gate_gate_panels_guild_idx
|
|
23
|
+
ON account_gate_gate_panels (guild_id, created_at, panel_id);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
ALTER TABLE account_gate_gate_panels
|
|
2
|
+
ADD COLUMN IF NOT EXISTS password_hash text,
|
|
3
|
+
ADD COLUMN IF NOT EXISTS password_ignore_case boolean NOT NULL DEFAULT true,
|
|
4
|
+
ADD COLUMN IF NOT EXISTS password_trim_whitespace boolean NOT NULL DEFAULT true;
|
|
5
|
+
|
|
6
|
+
UPDATE account_gate_gate_panels AS panel
|
|
7
|
+
SET
|
|
8
|
+
password_hash = secret.encoded_hash,
|
|
9
|
+
password_ignore_case = secret.ignore_case,
|
|
10
|
+
password_trim_whitespace = secret.trim_whitespace
|
|
11
|
+
FROM account_gate_password_secrets AS secret
|
|
12
|
+
WHERE panel.guild_id = secret.guild_id
|
|
13
|
+
AND panel.access_type = 'password'
|
|
14
|
+
AND panel.password_hash IS NULL;
|
|
15
|
+
|
|
16
|
+
CREATE OR REPLACE FUNCTION account_gate_enforce_panel_limit()
|
|
17
|
+
RETURNS trigger
|
|
18
|
+
LANGUAGE plpgsql
|
|
19
|
+
AS $$
|
|
20
|
+
BEGIN
|
|
21
|
+
PERFORM pg_advisory_xact_lock(
|
|
22
|
+
hashtextextended(NEW.guild_id, 4815162342)
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
IF (
|
|
26
|
+
SELECT count(*)
|
|
27
|
+
FROM account_gate_gate_panels
|
|
28
|
+
WHERE guild_id = NEW.guild_id
|
|
29
|
+
) >= 10 THEN
|
|
30
|
+
RAISE EXCEPTION USING
|
|
31
|
+
ERRCODE = 'check_violation',
|
|
32
|
+
MESSAGE = 'Account Gate panel limit reached';
|
|
33
|
+
END IF;
|
|
34
|
+
|
|
35
|
+
RETURN NEW;
|
|
36
|
+
END
|
|
37
|
+
$$;
|
|
38
|
+
|
|
39
|
+
DROP TRIGGER IF EXISTS account_gate_gate_panels_limit
|
|
40
|
+
ON account_gate_gate_panels;
|
|
41
|
+
|
|
42
|
+
CREATE TRIGGER account_gate_gate_panels_limit
|
|
43
|
+
BEFORE INSERT ON account_gate_gate_panels
|
|
44
|
+
FOR EACH ROW
|
|
45
|
+
EXECUTE FUNCTION account_gate_enforce_panel_limit();
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@helyx/module-account-gate",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Require configurable Discord interaction checks before new members gain access.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"helyx",
|
|
7
|
+
"discord",
|
|
8
|
+
"account-gate"
|
|
9
|
+
],
|
|
10
|
+
"private": false,
|
|
11
|
+
"license": "HSAL 1.0",
|
|
12
|
+
"homepage": "https://helyx.gg/modules/",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/ZyC0R3/Helyx/issues"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/ZyC0R3/Helyx.git",
|
|
19
|
+
"directory": "modules/account-gate"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=24 <27",
|
|
23
|
+
"npm": ">=11"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"provenance": true
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"!dist/*.tsbuildinfo",
|
|
33
|
+
"!dist/**/*.map",
|
|
34
|
+
"migrations",
|
|
35
|
+
"manifest.json",
|
|
36
|
+
"README.md",
|
|
37
|
+
"CHANGELOG.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"exports": {
|
|
41
|
+
".": {
|
|
42
|
+
"types": "./dist/index.d.ts",
|
|
43
|
+
"default": "./dist/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./package.json": "./package.json"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc -b"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@helyx/module-manifest": "0.5.0",
|
|
52
|
+
"@helyx/sdk": "0.4.0"
|
|
53
|
+
}
|
|
54
|
+
}
|