@flowselections/admin-installatietechniek 1.0.5 → 1.0.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-lib/components/AdminForInstallatieTechniek.d.ts.map +1 -1
- package/dist-lib/components/AdminForInstallatieTechniek.js +154 -8
- package/dist-lib/hooks/useModulePermission.d.ts +2 -1
- package/dist-lib/hooks/useModulePermission.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +545 -12
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +545 -12
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +545 -12
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +568 -13
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +3 -0
- package/dist-lib/lib/admin.functions.d.ts +141905 -205
- package/dist-lib/lib/admin.functions.d.ts.map +1 -1
- package/dist-lib/lib/admin.functions.js +273 -15
- package/dist-lib/lib/permission-types.d.ts +7 -0
- package/dist-lib/lib/permission-types.d.ts.map +1 -0
- package/dist-lib/lib/permission-types.js +1 -0
- package/dist-lib/lib/permissions.server.d.ts +1 -1
- package/dist-lib/lib/permissions.server.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -53,6 +53,7 @@ const inviteUserInput = z.object({
|
|
|
53
53
|
email: z.string().trim().email().max(255),
|
|
54
54
|
displayName: z.string().trim().min(1).max(100),
|
|
55
55
|
roleId: z.string().uuid(),
|
|
56
|
+
profileId: z.string().uuid().optional(),
|
|
56
57
|
});
|
|
57
58
|
const deleteUserInput = z.object({
|
|
58
59
|
userId: z.string().uuid(),
|
|
@@ -65,6 +66,7 @@ const createTestUserInput = z.object({
|
|
|
65
66
|
displayName: z.string().trim().min(1).max(100),
|
|
66
67
|
roleId: z.string().uuid(),
|
|
67
68
|
email: z.string().trim().email().max(255).optional(),
|
|
69
|
+
profileId: z.string().uuid().optional(),
|
|
68
70
|
});
|
|
69
71
|
function slugify(value) {
|
|
70
72
|
return (value
|
|
@@ -94,13 +96,45 @@ async function assertMayUseRole(supabase, roleId, isAdmin) {
|
|
|
94
96
|
}
|
|
95
97
|
return role;
|
|
96
98
|
}
|
|
97
|
-
|
|
99
|
+
const profileScopeInput = z
|
|
100
|
+
.object({ profileId: z.string().uuid().optional() })
|
|
101
|
+
.optional();
|
|
102
|
+
/** Tenant + rol-/module-scope van een bedrijfsprofiel (of het actieve profiel). */
|
|
103
|
+
async function loadProfileScope(supabase, profileId) {
|
|
104
|
+
let query = supabase.from("profiles_org").select("id, name, tenant_id, is_default");
|
|
105
|
+
query = profileId ? query.eq("id", profileId) : query.eq("is_default", true);
|
|
106
|
+
const { data, error } = await query.maybeSingle();
|
|
107
|
+
if (error)
|
|
108
|
+
throw error;
|
|
109
|
+
if (!data)
|
|
110
|
+
return null;
|
|
111
|
+
const [{ data: roleRows }, { data: moduleRows }] = await Promise.all([
|
|
112
|
+
supabase.from("profile_roles").select("role_id").eq("profile_id", data.id),
|
|
113
|
+
supabase.from("profile_modules").select("module_id").eq("profile_id", data.id),
|
|
114
|
+
]);
|
|
115
|
+
return {
|
|
116
|
+
id: data.id,
|
|
117
|
+
name: data.name,
|
|
118
|
+
tenantId: (data.tenant_id ?? null),
|
|
119
|
+
roleIds: (Array.isArray(roleRows) ? roleRows : []).map((r) => r.role_id),
|
|
120
|
+
moduleIds: (Array.isArray(moduleRows) ? moduleRows : []).map((m) => m.module_id),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export const getUsersWithRoles = createServerFn({ method: "POST" })
|
|
98
124
|
.middleware([requireSupabaseAuth])
|
|
99
|
-
.
|
|
125
|
+
.inputValidator((data) => profileScopeInput.parse(data))
|
|
126
|
+
.handler(async ({ context, data }) => {
|
|
100
127
|
const { isAdmin } = await requireUserAdmin(context);
|
|
101
128
|
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
129
|
+
const scope = await loadProfileScope(supabaseAdmin, data?.profileId);
|
|
130
|
+
let profilesQuery = supabaseAdmin
|
|
131
|
+
.from("profiles")
|
|
132
|
+
.select("id, email, display_name, tenant_id")
|
|
133
|
+
.order("email", { ascending: true });
|
|
134
|
+
if (scope?.tenantId)
|
|
135
|
+
profilesQuery = profilesQuery.eq("tenant_id", scope.tenantId);
|
|
102
136
|
const [{ data: profiles, error: profilesError }, { data: assignments, error: assignmentsError }, { data: roles, error: rolesError }, { data: authList, error: authError },] = await Promise.all([
|
|
103
|
-
|
|
137
|
+
profilesQuery,
|
|
104
138
|
supabaseAdmin.from("role_assignments").select("user_id, role_id"),
|
|
105
139
|
supabaseAdmin.from("roles").select("id, key, name, is_protected").order("name", { ascending: true }),
|
|
106
140
|
supabaseAdmin.auth.admin.listUsers({ page: 1, perPage: 1000 }),
|
|
@@ -115,9 +149,12 @@ export const getUsersWithRoles = createServerFn({ method: "GET" })
|
|
|
115
149
|
throw authError;
|
|
116
150
|
const safeProfiles = Array.isArray(profiles) ? profiles : [];
|
|
117
151
|
const safeAssignments = Array.isArray(assignments) ? assignments : [];
|
|
118
|
-
const
|
|
152
|
+
const allRoles = Array.isArray(roles) ? roles : [];
|
|
153
|
+
const safeRoles = scope && scope.roleIds.length > 0
|
|
154
|
+
? allRoles.filter((r) => scope.roleIds.includes(r.id))
|
|
155
|
+
: allRoles;
|
|
119
156
|
const safeAuthUsers = Array.isArray(authList?.users) ? authList.users : [];
|
|
120
|
-
const roleById = new Map(
|
|
157
|
+
const roleById = new Map(allRoles.map((r) => [r.id, r]));
|
|
121
158
|
const confirmedById = new Map();
|
|
122
159
|
const isTestById = new Map();
|
|
123
160
|
for (const u of safeAuthUsers) {
|
|
@@ -149,6 +186,7 @@ export const getUsersWithRoles = createServerFn({ method: "GET" })
|
|
|
149
186
|
.filter((r) => isAdmin || r.key !== "admin")
|
|
150
187
|
.map((r) => ({ id: r.id, key: r.key, name: r.name, isProtected: r.is_protected })),
|
|
151
188
|
isAdmin,
|
|
189
|
+
activeProfile: scope ? { id: scope.id, name: scope.name, tenantId: scope.tenantId } : null,
|
|
152
190
|
};
|
|
153
191
|
});
|
|
154
192
|
export const assignRole = createServerFn({ method: "POST" })
|
|
@@ -193,10 +231,12 @@ export const removeRole = createServerFn({ method: "POST" })
|
|
|
193
231
|
return { ok: true };
|
|
194
232
|
});
|
|
195
233
|
/** Alle rollen met hun rechten, plus de geregistreerde modules en onderdelen. */
|
|
196
|
-
export const getRoles = createServerFn({ method: "
|
|
234
|
+
export const getRoles = createServerFn({ method: "POST" })
|
|
197
235
|
.middleware([requireSupabaseAuth])
|
|
198
|
-
.
|
|
236
|
+
.inputValidator((data) => profileScopeInput.parse(data))
|
|
237
|
+
.handler(async ({ context, data }) => {
|
|
199
238
|
await requireUserAdmin(context);
|
|
239
|
+
const scope = await loadProfileScope(context.supabase, data?.profileId);
|
|
200
240
|
const [{ data: roles, error: rolesError }, { data: perms, error: permsError }, { data: registry, error: registryError }, { data: featureRows, error: featuresError },] = await Promise.all([
|
|
201
241
|
context.supabase.from("roles").select("id, key, name, is_protected").order("name", { ascending: true }),
|
|
202
242
|
context.supabase.from("role_permissions").select("role_id, module_id, feature_id, can_view, can_edit"),
|
|
@@ -211,9 +251,15 @@ export const getRoles = createServerFn({ method: "GET" })
|
|
|
211
251
|
throw registryError;
|
|
212
252
|
if (featuresError)
|
|
213
253
|
throw featuresError;
|
|
214
|
-
const
|
|
254
|
+
const allRoles = Array.isArray(roles) ? roles : [];
|
|
255
|
+
const safeRoles = scope && scope.roleIds.length > 0
|
|
256
|
+
? allRoles.filter((r) => scope.roleIds.includes(r.id))
|
|
257
|
+
: allRoles;
|
|
215
258
|
const safePerms = Array.isArray(perms) ? perms : [];
|
|
216
|
-
const
|
|
259
|
+
const allRegistry = Array.isArray(registry) ? registry : [];
|
|
260
|
+
const safeRegistry = scope && scope.moduleIds.length > 0
|
|
261
|
+
? allRegistry.filter((m) => scope.moduleIds.includes(m.module_id))
|
|
262
|
+
: allRegistry;
|
|
217
263
|
const safeFeatures = Array.isArray(featureRows) ? featureRows : [];
|
|
218
264
|
return {
|
|
219
265
|
roles: safeRoles.map((r) => ({
|
|
@@ -239,6 +285,7 @@ export const getRoles = createServerFn({ method: "GET" })
|
|
|
239
285
|
canView: Boolean(p.can_view),
|
|
240
286
|
canEdit: Boolean(p.can_edit),
|
|
241
287
|
})),
|
|
288
|
+
activeProfile: scope ? { id: scope.id, name: scope.name, tenantId: scope.tenantId } : null,
|
|
242
289
|
};
|
|
243
290
|
});
|
|
244
291
|
async function writeRolePermissions(supabase, roleId, permissions) {
|
|
@@ -525,9 +572,13 @@ export const inviteUser = createServerFn({ method: "POST" })
|
|
|
525
572
|
throw new Error(/already|exists|registered/i.test(msg) ? "Deze gebruiker bestaat al." : msg);
|
|
526
573
|
}
|
|
527
574
|
const userId = invited.user.id;
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
575
|
+
const scope = await loadProfileScope(supabaseAdmin, data.profileId);
|
|
576
|
+
const { error: profileError } = await supabaseAdmin.from("profiles").upsert({
|
|
577
|
+
id: userId,
|
|
578
|
+
email: data.email,
|
|
579
|
+
display_name: data.displayName,
|
|
580
|
+
...(scope?.tenantId ? { tenant_id: scope.tenantId } : {}),
|
|
581
|
+
}, { onConflict: "id" });
|
|
531
582
|
if (profileError)
|
|
532
583
|
throw profileError;
|
|
533
584
|
const { error: roleError } = await supabaseAdmin
|
|
@@ -623,9 +674,13 @@ export const createTestUser = createServerFn({ method: "POST" })
|
|
|
623
674
|
throw new Error(/already|exists|registered/i.test(msg) ? "Deze gebruiker bestaat al." : msg);
|
|
624
675
|
}
|
|
625
676
|
const userId = created.user.id;
|
|
626
|
-
const
|
|
627
|
-
|
|
628
|
-
|
|
677
|
+
const scope = await loadProfileScope(supabaseAdmin, data.profileId);
|
|
678
|
+
const { error: profileError } = await supabaseAdmin.from("profiles").upsert({
|
|
679
|
+
id: userId,
|
|
680
|
+
email,
|
|
681
|
+
display_name: data.displayName,
|
|
682
|
+
...(scope?.tenantId ? { tenant_id: scope.tenantId } : {}),
|
|
683
|
+
}, { onConflict: "id" });
|
|
629
684
|
if (profileError)
|
|
630
685
|
throw profileError;
|
|
631
686
|
const { error: roleError } = await supabaseAdmin
|
|
@@ -635,3 +690,206 @@ export const createTestUser = createServerFn({ method: "POST" })
|
|
|
635
690
|
throw roleError;
|
|
636
691
|
return { ok: true, userId, email, password };
|
|
637
692
|
});
|
|
693
|
+
// ============================================================================
|
|
694
|
+
// Bedrijfsprofielen: bundelen rollen + modules per organisatie (tenant)
|
|
695
|
+
// ============================================================================
|
|
696
|
+
const profileIdInput = z.object({ profileId: z.string().uuid() });
|
|
697
|
+
const profileBodySchema = {
|
|
698
|
+
name: z.string().trim().min(1).max(120),
|
|
699
|
+
tenantId: z.string().uuid().nullable().optional(),
|
|
700
|
+
roleIds: z.array(z.string().uuid()).max(200).default([]),
|
|
701
|
+
moduleIds: z.array(z.string().trim().min(1).max(100)).max(200).default([]),
|
|
702
|
+
};
|
|
703
|
+
const createProfileInput = z.object(profileBodySchema);
|
|
704
|
+
const updateProfileInput = z.object({ profileId: z.string().uuid(), ...profileBodySchema });
|
|
705
|
+
async function writeProfileLinks(supabase, profileId, roleIds, moduleIds) {
|
|
706
|
+
const { error: delRoles } = await supabase.from("profile_roles").delete().eq("profile_id", profileId);
|
|
707
|
+
if (delRoles)
|
|
708
|
+
throw delRoles;
|
|
709
|
+
const { error: delModules } = await supabase.from("profile_modules").delete().eq("profile_id", profileId);
|
|
710
|
+
if (delModules)
|
|
711
|
+
throw delModules;
|
|
712
|
+
const uniqueRoles = Array.from(new Set(roleIds));
|
|
713
|
+
if (uniqueRoles.length > 0) {
|
|
714
|
+
const { error } = await supabase
|
|
715
|
+
.from("profile_roles")
|
|
716
|
+
.insert(uniqueRoles.map((roleId) => ({ profile_id: profileId, role_id: roleId })));
|
|
717
|
+
if (error)
|
|
718
|
+
throw error;
|
|
719
|
+
}
|
|
720
|
+
const uniqueModules = Array.from(new Set(moduleIds));
|
|
721
|
+
if (uniqueModules.length > 0) {
|
|
722
|
+
const { error } = await supabase
|
|
723
|
+
.from("profile_modules")
|
|
724
|
+
.insert(uniqueModules.map((moduleId) => ({ profile_id: profileId, module_id: moduleId })));
|
|
725
|
+
if (error)
|
|
726
|
+
throw error;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
/** Alle bedrijfsprofielen met hun rollen, modules en tellingen. */
|
|
730
|
+
export const getProfiles = createServerFn({ method: "GET" })
|
|
731
|
+
.middleware([requireSupabaseAuth])
|
|
732
|
+
.handler(async ({ context }) => {
|
|
733
|
+
await requireUserAdmin(context);
|
|
734
|
+
const [{ data: profilesOrg, error: profilesError }, { data: profileRoles, error: profileRolesError }, { data: profileModules, error: profileModulesError }, { data: tenants, error: tenantsError },] = await Promise.all([
|
|
735
|
+
context.supabase
|
|
736
|
+
.from("profiles_org")
|
|
737
|
+
.select("id, name, tenant_id, is_default")
|
|
738
|
+
.order("name", { ascending: true }),
|
|
739
|
+
context.supabase.from("profile_roles").select("profile_id, role_id"),
|
|
740
|
+
context.supabase.from("profile_modules").select("profile_id, module_id"),
|
|
741
|
+
context.supabase.from("tenants").select("id, name").order("name", { ascending: true }),
|
|
742
|
+
]);
|
|
743
|
+
if (profilesError)
|
|
744
|
+
throw profilesError;
|
|
745
|
+
if (profileRolesError)
|
|
746
|
+
throw profileRolesError;
|
|
747
|
+
if (profileModulesError)
|
|
748
|
+
throw profileModulesError;
|
|
749
|
+
if (tenantsError)
|
|
750
|
+
throw tenantsError;
|
|
751
|
+
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
752
|
+
const { data: userRows, error: userError } = await supabaseAdmin
|
|
753
|
+
.from("profiles")
|
|
754
|
+
.select("id, tenant_id");
|
|
755
|
+
if (userError)
|
|
756
|
+
throw userError;
|
|
757
|
+
const safeProfiles = Array.isArray(profilesOrg) ? profilesOrg : [];
|
|
758
|
+
const safeProfileRoles = Array.isArray(profileRoles) ? profileRoles : [];
|
|
759
|
+
const safeProfileModules = Array.isArray(profileModules) ? profileModules : [];
|
|
760
|
+
const safeTenants = Array.isArray(tenants) ? tenants : [];
|
|
761
|
+
const safeUsers = Array.isArray(userRows) ? userRows : [];
|
|
762
|
+
const usersByTenant = new Map();
|
|
763
|
+
for (const u of safeUsers) {
|
|
764
|
+
if (!u.tenant_id)
|
|
765
|
+
continue;
|
|
766
|
+
usersByTenant.set(u.tenant_id, (usersByTenant.get(u.tenant_id) ?? 0) + 1);
|
|
767
|
+
}
|
|
768
|
+
const tenantName = new Map(safeTenants.map((t) => [t.id, t.name]));
|
|
769
|
+
return {
|
|
770
|
+
profiles: safeProfiles.map((p) => ({
|
|
771
|
+
id: p.id,
|
|
772
|
+
name: p.name,
|
|
773
|
+
tenantId: (p.tenant_id ?? null),
|
|
774
|
+
tenantName: p.tenant_id ? tenantName.get(p.tenant_id) ?? null : null,
|
|
775
|
+
isDefault: Boolean(p.is_default),
|
|
776
|
+
roleIds: safeProfileRoles.filter((r) => r.profile_id === p.id).map((r) => r.role_id),
|
|
777
|
+
moduleIds: safeProfileModules
|
|
778
|
+
.filter((m) => m.profile_id === p.id)
|
|
779
|
+
.map((m) => m.module_id),
|
|
780
|
+
userCount: p.tenant_id ? usersByTenant.get(p.tenant_id) ?? 0 : 0,
|
|
781
|
+
})),
|
|
782
|
+
tenants: safeTenants.map((t) => ({ id: t.id, name: t.name })),
|
|
783
|
+
};
|
|
784
|
+
});
|
|
785
|
+
export const createProfile = createServerFn({ method: "POST" })
|
|
786
|
+
.middleware([requireSupabaseAuth])
|
|
787
|
+
.inputValidator((data) => createProfileInput.parse(data))
|
|
788
|
+
.handler(async ({ context, data }) => {
|
|
789
|
+
await requireAdmin(context);
|
|
790
|
+
const { data: created, error } = await context.supabase
|
|
791
|
+
.from("profiles_org")
|
|
792
|
+
.insert({ name: data.name, tenant_id: data.tenantId ?? null })
|
|
793
|
+
.select("id")
|
|
794
|
+
.single();
|
|
795
|
+
if (error)
|
|
796
|
+
throw error;
|
|
797
|
+
await writeProfileLinks(context.supabase, created.id, data.roleIds, data.moduleIds);
|
|
798
|
+
return { ok: true, profileId: created.id };
|
|
799
|
+
});
|
|
800
|
+
export const updateProfile = createServerFn({ method: "POST" })
|
|
801
|
+
.middleware([requireSupabaseAuth])
|
|
802
|
+
.inputValidator((data) => updateProfileInput.parse(data))
|
|
803
|
+
.handler(async ({ context, data }) => {
|
|
804
|
+
await requireAdmin(context);
|
|
805
|
+
const { error } = await context.supabase
|
|
806
|
+
.from("profiles_org")
|
|
807
|
+
.update({ name: data.name, tenant_id: data.tenantId ?? null, updated_at: new Date().toISOString() })
|
|
808
|
+
.eq("id", data.profileId);
|
|
809
|
+
if (error)
|
|
810
|
+
throw error;
|
|
811
|
+
await writeProfileLinks(context.supabase, data.profileId, data.roleIds, data.moduleIds);
|
|
812
|
+
return { ok: true };
|
|
813
|
+
});
|
|
814
|
+
export const duplicateProfile = createServerFn({ method: "POST" })
|
|
815
|
+
.middleware([requireSupabaseAuth])
|
|
816
|
+
.inputValidator((data) => profileIdInput.parse(data))
|
|
817
|
+
.handler(async ({ context, data }) => {
|
|
818
|
+
await requireAdmin(context);
|
|
819
|
+
const { data: source, error: sourceError } = await context.supabase
|
|
820
|
+
.from("profiles_org")
|
|
821
|
+
.select("name, tenant_id")
|
|
822
|
+
.eq("id", data.profileId)
|
|
823
|
+
.maybeSingle();
|
|
824
|
+
if (sourceError)
|
|
825
|
+
throw sourceError;
|
|
826
|
+
if (!source)
|
|
827
|
+
throw new Error("Profiel bestaat niet.");
|
|
828
|
+
const [{ data: roleRows }, { data: moduleRows }] = await Promise.all([
|
|
829
|
+
context.supabase.from("profile_roles").select("role_id").eq("profile_id", data.profileId),
|
|
830
|
+
context.supabase.from("profile_modules").select("module_id").eq("profile_id", data.profileId),
|
|
831
|
+
]);
|
|
832
|
+
const { data: created, error } = await context.supabase
|
|
833
|
+
.from("profiles_org")
|
|
834
|
+
.insert({ name: `${source.name} (kopie)`, tenant_id: source.tenant_id })
|
|
835
|
+
.select("id")
|
|
836
|
+
.single();
|
|
837
|
+
if (error)
|
|
838
|
+
throw error;
|
|
839
|
+
await writeProfileLinks(context.supabase, created.id, (Array.isArray(roleRows) ? roleRows : []).map((r) => r.role_id), (Array.isArray(moduleRows) ? moduleRows : []).map((m) => m.module_id));
|
|
840
|
+
return { ok: true, profileId: created.id };
|
|
841
|
+
});
|
|
842
|
+
export const deleteProfile = createServerFn({ method: "POST" })
|
|
843
|
+
.middleware([requireSupabaseAuth])
|
|
844
|
+
.inputValidator((data) => profileIdInput.parse(data))
|
|
845
|
+
.handler(async ({ context, data }) => {
|
|
846
|
+
await requireAdmin(context);
|
|
847
|
+
const { data: profile, error: profileError } = await context.supabase
|
|
848
|
+
.from("profiles_org")
|
|
849
|
+
.select("id, tenant_id, is_default")
|
|
850
|
+
.eq("id", data.profileId)
|
|
851
|
+
.maybeSingle();
|
|
852
|
+
if (profileError)
|
|
853
|
+
throw profileError;
|
|
854
|
+
if (!profile)
|
|
855
|
+
throw new Error("Profiel bestaat niet.");
|
|
856
|
+
if (profile.is_default)
|
|
857
|
+
throw new Error("Het actieve profiel kan niet verwijderd worden.");
|
|
858
|
+
if (profile.tenant_id) {
|
|
859
|
+
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
860
|
+
const { count, error: countError } = await supabaseAdmin
|
|
861
|
+
.from("profiles")
|
|
862
|
+
.select("id", { count: "exact", head: true })
|
|
863
|
+
.eq("tenant_id", profile.tenant_id);
|
|
864
|
+
if (countError)
|
|
865
|
+
throw countError;
|
|
866
|
+
if ((count ?? 0) > 0) {
|
|
867
|
+
throw new Error("Er zijn nog gebruikers aan dit bedrijf gekoppeld.");
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
const { error } = await context.supabase.from("profiles_org").delete().eq("id", data.profileId);
|
|
871
|
+
if (error)
|
|
872
|
+
throw error;
|
|
873
|
+
return { ok: true };
|
|
874
|
+
});
|
|
875
|
+
/** Zet precies één profiel als actief (is_default). */
|
|
876
|
+
export const setActiveProfile = createServerFn({ method: "POST" })
|
|
877
|
+
.middleware([requireSupabaseAuth])
|
|
878
|
+
.inputValidator((data) => profileIdInput.parse(data))
|
|
879
|
+
.handler(async ({ context, data }) => {
|
|
880
|
+
await requireAdmin(context);
|
|
881
|
+
const { error: clearError } = await context.supabase
|
|
882
|
+
.from("profiles_org")
|
|
883
|
+
.update({ is_default: false })
|
|
884
|
+
.eq("is_default", true)
|
|
885
|
+
.neq("id", data.profileId);
|
|
886
|
+
if (clearError)
|
|
887
|
+
throw clearError;
|
|
888
|
+
const { error } = await context.supabase
|
|
889
|
+
.from("profiles_org")
|
|
890
|
+
.update({ is_default: true, updated_at: new Date().toISOString() })
|
|
891
|
+
.eq("id", data.profileId);
|
|
892
|
+
if (error)
|
|
893
|
+
throw error;
|
|
894
|
+
return { ok: true };
|
|
895
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Losse types voor de check-laag (lezen/afdwingen van moduletoegang).
|
|
3
|
+
* Bewust zonder imports uit de rest van deze module, zodat de check-laag
|
|
4
|
+
* later 1-op-1 naar @flowselections/core kan verhuizen.
|
|
5
|
+
*/
|
|
6
|
+
export type ModulePermission = "none" | "view" | "edit";
|
|
7
|
+
//# sourceMappingURL=permission-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-types.d.ts","sourceRoot":"","sources":["../../src/lib/permission-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/lib/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/lib/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,UAAU,iBAAiB;IACzB,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAK,EACd,KAAK,GAAE,MAAM,GAAG,MAAe,6BA0BhC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowselections/admin-installatietechniek",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"flowselections": {
|
|
5
5
|
"moduleId": "admin-installatietechniek",
|
|
6
6
|
"pages": [
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@cloudflare/vite-plugin": "^1.25.5",
|
|
57
57
|
"@eslint/js": "^9.32.0",
|
|
58
|
-
"@flowselections/core": "1.0.
|
|
58
|
+
"@flowselections/core": "1.0.18",
|
|
59
59
|
"@lovable.dev/vite-tanstack-config": "2.13.1",
|
|
60
60
|
"@rsbuild/core": "^1.0.0",
|
|
61
61
|
"@tailwindcss/vite": "^4.2.1",
|