spine-framework 0.3.133 → 0.3.134
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.
|
@@ -175,12 +175,13 @@ export const checkDomain = createHandler(async (_ctx, _body) => {
|
|
|
175
175
|
|
|
176
176
|
const { data } = await adminDb
|
|
177
177
|
.from('people')
|
|
178
|
-
.select('
|
|
178
|
+
.select('account_id')
|
|
179
179
|
.ilike('email', `%@${domain}`)
|
|
180
180
|
.eq('status', 'active')
|
|
181
181
|
.limit(1)
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
const first = data?.[0]
|
|
184
|
+
return { match: !!first, account_id: first?.account_id ?? null }
|
|
184
185
|
})
|
|
185
186
|
// CIL[END chunk_id="invites_checkdomain_1783968140"]
|
|
186
187
|
// CIL[BEGIN chunk_id="invites_validatetoken_1783968140" type="function" identity="validateToken" parent="none"]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
-- Create trigger function to sync new auth users to people records
|
|
2
|
+
CREATE OR REPLACE FUNCTION public.handle_new_auth_user()
|
|
3
|
+
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$
|
|
4
|
+
DECLARE
|
|
5
|
+
v_account_id uuid;
|
|
6
|
+
v_type_id uuid;
|
|
7
|
+
v_role_id uuid;
|
|
8
|
+
v_is_first boolean;
|
|
9
|
+
v_design_schema jsonb;
|
|
10
|
+
v_validation_schema jsonb;
|
|
11
|
+
v_stub_id uuid;
|
|
12
|
+
v_stub_status text;
|
|
13
|
+
BEGIN
|
|
14
|
+
SELECT id INTO v_account_id FROM public.accounts WHERE slug = 'spine-system' LIMIT 1;
|
|
15
|
+
SELECT id, design_schema, validation_schema
|
|
16
|
+
INTO v_type_id, v_design_schema, v_validation_schema
|
|
17
|
+
FROM public.types WHERE kind = 'person' AND slug = 'person' LIMIT 1;
|
|
18
|
+
|
|
19
|
+
IF v_account_id IS NULL OR v_type_id IS NULL THEN
|
|
20
|
+
RAISE WARNING 'handle_new_auth_user: spine-system account or person type not found — skipping';
|
|
21
|
+
RETURN NEW;
|
|
22
|
+
END IF;
|
|
23
|
+
|
|
24
|
+
SELECT id, status
|
|
25
|
+
INTO v_stub_id, v_stub_status
|
|
26
|
+
FROM public.people
|
|
27
|
+
WHERE email = NEW.email
|
|
28
|
+
AND status IN ('invited', 'pending')
|
|
29
|
+
AND auth_uid IS NULL
|
|
30
|
+
LIMIT 1;
|
|
31
|
+
|
|
32
|
+
IF v_stub_id IS NOT NULL THEN
|
|
33
|
+
UPDATE public.people SET
|
|
34
|
+
auth_uid = NEW.id,
|
|
35
|
+
full_name = COALESCE(NEW.raw_user_meta_data->>'full_name', full_name, split_part(NEW.email, '@', 1)),
|
|
36
|
+
status = CASE WHEN v_stub_status = 'invited' THEN 'active' ELSE 'pending' END,
|
|
37
|
+
updated_at = now()
|
|
38
|
+
WHERE id = v_stub_id;
|
|
39
|
+
|
|
40
|
+
RETURN NEW;
|
|
41
|
+
END IF;
|
|
42
|
+
|
|
43
|
+
SELECT NOT EXISTS (SELECT 1 FROM public.people LIMIT 1) INTO v_is_first;
|
|
44
|
+
IF v_is_first THEN
|
|
45
|
+
SELECT id INTO v_role_id FROM public.roles WHERE slug = 'system_admin' LIMIT 1;
|
|
46
|
+
END IF;
|
|
47
|
+
|
|
48
|
+
INSERT INTO public.people (
|
|
49
|
+
id,
|
|
50
|
+
auth_uid,
|
|
51
|
+
email,
|
|
52
|
+
full_name,
|
|
53
|
+
account_id,
|
|
54
|
+
type_id,
|
|
55
|
+
role_id,
|
|
56
|
+
status,
|
|
57
|
+
is_active,
|
|
58
|
+
design_schema,
|
|
59
|
+
validation_schema
|
|
60
|
+
) VALUES (
|
|
61
|
+
NEW.id,
|
|
62
|
+
NEW.id,
|
|
63
|
+
NEW.email,
|
|
64
|
+
COALESCE(NEW.raw_user_meta_data->>'full_name', split_part(NEW.email, '@', 1)),
|
|
65
|
+
v_account_id,
|
|
66
|
+
v_type_id,
|
|
67
|
+
v_role_id,
|
|
68
|
+
'active',
|
|
69
|
+
true,
|
|
70
|
+
v_design_schema,
|
|
71
|
+
COALESCE(v_validation_schema, '{}'::jsonb)
|
|
72
|
+
)
|
|
73
|
+
ON CONFLICT (id) DO NOTHING;
|
|
74
|
+
|
|
75
|
+
RETURN NEW;
|
|
76
|
+
END;
|
|
77
|
+
$$;
|
|
78
|
+
|
|
79
|
+
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
|
|
80
|
+
CREATE TRIGGER on_auth_user_created
|
|
81
|
+
AFTER INSERT ON auth.users
|
|
82
|
+
FOR EACH ROW EXECUTE FUNCTION public.handle_new_auth_user();
|
|
@@ -262,8 +262,8 @@ export function RegisterPage() {
|
|
|
262
262
|
const result = await callInvitesApi('check-domain', { email })
|
|
263
263
|
setDomainCheckLoading(false)
|
|
264
264
|
|
|
265
|
-
if (result.data?.match) {
|
|
266
|
-
setDomainMatchAccountId(
|
|
265
|
+
if (result.data?.match && result.data?.account_id) {
|
|
266
|
+
setDomainMatchAccountId(result.data.account_id)
|
|
267
267
|
}
|
|
268
268
|
}, [email, inviteToken, useType, isFirstUser])
|
|
269
269
|
|
|
@@ -323,23 +323,22 @@ export function RegisterPage() {
|
|
|
323
323
|
|
|
324
324
|
const completeRegistrationParams: any = {
|
|
325
325
|
email: resolvedEmail,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
role: effectiveRole,
|
|
329
|
-
redirect: getPostRegistrationRedirect(regConfig, searchParams, false, effectiveRole),
|
|
326
|
+
path: 'new_account',
|
|
327
|
+
role_slug: effectiveRole,
|
|
330
328
|
}
|
|
331
329
|
|
|
332
330
|
if (useType === 'company') {
|
|
333
|
-
completeRegistrationParams.account_name = companyName
|
|
331
|
+
completeRegistrationParams.account_name = companyName || fullName || email.split('@')[0]
|
|
332
|
+
} else {
|
|
333
|
+
completeRegistrationParams.account_name = fullName || email.split('@')[0]
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
if (effectiveAccountStrategy === 'existing' && targetAccount) {
|
|
337
|
-
completeRegistrationParams.
|
|
338
|
-
completeRegistrationParams.
|
|
339
|
-
} else if (domainMatchAccountId
|
|
340
|
-
completeRegistrationParams.
|
|
341
|
-
|
|
342
|
-
completeRegistrationParams.strategy = 'new_account'
|
|
337
|
+
completeRegistrationParams.path = 'existing_account'
|
|
338
|
+
completeRegistrationParams.target_account = targetAccount
|
|
339
|
+
} else if (domainMatchAccountId && domainMatchChoice === 'join') {
|
|
340
|
+
completeRegistrationParams.path = 'join_request'
|
|
341
|
+
completeRegistrationParams.target_account_id = domainMatchAccountId
|
|
343
342
|
}
|
|
344
343
|
|
|
345
344
|
const result = await callInvitesApi('complete-registration', completeRegistrationParams, 'POST')
|
|
@@ -367,7 +366,7 @@ export function RegisterPage() {
|
|
|
367
366
|
const isInvite = !!inviteToken && !tokenError
|
|
368
367
|
const showPersonalCompanyToggle = !isInvite && !isFirstUser
|
|
369
368
|
const showCompanyName = showPersonalCompanyToggle && useType === 'company'
|
|
370
|
-
const showDomainMatchChoice = domainMatchAccountId
|
|
369
|
+
const showDomainMatchChoice = !!domainMatchAccountId && !isInvite && !isFirstUser
|
|
371
370
|
|
|
372
371
|
if (tokenLoading || isFirstUser === null || (!isFirstUser && !isInvite && !regConfig)) {
|
|
373
372
|
return (
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-framework",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.134",
|
|
4
4
|
"description": "Multi-tenant, modular application platform for modern SaaS systems",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
".framework/migrations/007_kb_article_list.sql",
|
|
26
26
|
".framework/migrations/008_items_target.sql",
|
|
27
27
|
".framework/migrations/009_roles_slug_unique.sql",
|
|
28
|
+
".framework/migrations/010_auth_user_trigger.sql",
|
|
28
29
|
".framework/public/",
|
|
29
30
|
".framework/scripts/",
|
|
30
31
|
".framework/seeds/",
|