@nextsparkjs/core 0.1.0-beta.196 → 0.1.0-beta.197
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/README.md +2 -0
- package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
- package/dist/components/auth/forms/SignupForm.js +55 -45
- package/dist/components/dashboard/block-editor/config-panel.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/config-panel.js +3 -2
- package/dist/components/dashboard/block-editor/entity-fields-sidebar.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/entity-fields-sidebar.js +3 -2
- package/dist/components/users/tables/UsersTable.d.ts.map +1 -1
- package/dist/components/users/tables/UsersTable.js +3 -4
- package/dist/hooks/useAuthReadiness.d.ts +1 -0
- package/dist/hooks/useAuthReadiness.d.ts.map +1 -1
- package/dist/hooks/useAuthReadiness.js +3 -1
- package/dist/lib/actions/entity.actions.js +2 -2
- package/dist/lib/actions/team.actions.js +2 -2
- package/dist/lib/actions/user.actions.js +4 -4
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +3 -2
- package/dist/lib/api/auth.d.ts.map +1 -1
- package/dist/lib/api/auth.js +7 -0
- package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +66 -12
- package/dist/lib/api/entity-handler.js +2 -2
- package/dist/lib/api/helpers.d.ts.map +1 -1
- package/dist/lib/api/helpers.js +4 -2
- package/dist/lib/api/post-categories.d.ts +29 -0
- package/dist/lib/api/post-categories.d.ts.map +1 -0
- package/dist/lib/api/post-categories.js +33 -0
- package/dist/lib/auth/auth-methods.d.ts +5 -2
- package/dist/lib/auth/auth-methods.d.ts.map +1 -1
- package/dist/lib/auth/auth-methods.js +4 -2
- package/dist/lib/auth/authorization-session.d.ts +14 -0
- package/dist/lib/auth/authorization-session.d.ts.map +1 -0
- package/dist/lib/auth/authorization-session.js +10 -0
- package/dist/lib/auth/request-session.d.ts +5 -0
- package/dist/lib/auth/request-session.d.ts.map +1 -1
- package/dist/lib/auth/request-session.js +3 -0
- package/dist/lib/auth/runtime-readiness.d.ts +7 -4
- package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
- package/dist/lib/auth/runtime-readiness.js +7 -6
- package/dist/lib/auth/sample-accounts.d.ts +2 -1
- package/dist/lib/auth/sample-accounts.d.ts.map +1 -1
- package/dist/lib/auth/sample-accounts.js +4 -1
- package/dist/lib/auth/suspension.d.ts +22 -0
- package/dist/lib/auth/suspension.d.ts.map +1 -0
- package/dist/lib/auth/suspension.js +43 -0
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +15 -15
- package/dist/lib/config/app.config.d.ts.map +1 -1
- package/dist/lib/config/app.config.js +6 -7
- package/dist/lib/config/types.d.ts +8 -6
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/db-pool.d.ts +31 -0
- package/dist/lib/db-pool.d.ts.map +1 -0
- package/dist/lib/db-pool.js +75 -0
- package/dist/lib/db.d.ts +1 -1
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +11 -14
- package/dist/lib/entities/api-generator.js +5 -5
- package/dist/lib/oauth/token-refresh.d.ts.map +1 -1
- package/dist/lib/oauth/token-refresh.js +3 -6
- package/dist/lib/permissions/check.d.ts +9 -0
- package/dist/lib/permissions/check.d.ts.map +1 -1
- package/dist/lib/permissions/check.js +11 -1
- package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
- package/dist/lib/services/generic-entity.service.js +39 -7
- package/dist/lib/services/transactional-meta.service.d.ts.map +1 -1
- package/dist/lib/services/transactional-meta.service.js +7 -8
- package/dist/lib/validation.d.ts +5 -0
- package/dist/lib/validation.d.ts.map +1 -1
- package/dist/lib/validation.js +2 -0
- package/dist/migrations/030_taxonomies_team_writes.sql +29 -0
- package/dist/migrations/031_users_role_suspended.sql +41 -0
- package/dist/routes/(auth)/signup/page.cc.d.ts +3 -1
- package/dist/routes/(auth)/signup/page.cc.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.cc.js +2 -2
- package/dist/routes/(auth)/signup/page.d.ts +3 -1
- package/dist/routes/(auth)/signup/page.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.js +4 -3
- package/dist/routes/_internal/area-access.js +2 -2
- package/dist/routes/api/devtools/config/entities/route.js +2 -2
- package/dist/routes/api/devtools/config/theme/route.js +2 -2
- package/dist/routes/api/devtools/tests/[...path]/route.js +2 -2
- package/dist/routes/api/devtools/tests/route.js +2 -2
- package/dist/routes/api/superadmin/subscriptions/route.js +2 -2
- package/dist/routes/api/superadmin/teams/[teamId]/route.js +2 -2
- package/dist/routes/api/superadmin/teams/route.js +2 -2
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts +5 -3
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/users/[userId]/route.js +46 -23
- package/dist/routes/api/superadmin/users/route.js +2 -2
- package/dist/routes/api/user/delete-account/route.d.ts.map +1 -1
- package/dist/routes/api/user/delete-account/route.js +2 -3
- package/dist/routes/api/user/plan-flags/route.d.ts.map +1 -1
- package/dist/routes/api/user/plan-flags/route.js +5 -5
- package/dist/routes/api/user/profile/route.js +3 -3
- package/dist/routes/api/v1/auth/signup-with-invite/route.d.ts.map +1 -1
- package/dist/routes/api/v1/auth/signup-with-invite/route.js +80 -44
- package/dist/routes/api/v1/post-categories/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/[id]/route.js +39 -34
- package/dist/routes/api/v1/post-categories/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/route.js +18 -14
- package/dist/routes/api/v1/team-invitations/route.d.ts.map +1 -1
- package/dist/routes/api/v1/team-invitations/route.js +12 -5
- package/dist/routes/superadmin/users/page.js +2 -2
- package/dist/templates/next.config.mjs +11 -31
- package/dist/templates/projects/blog/package.json +1 -1
- package/dist/templates/projects/crm/package.json +1 -1
- package/dist/templates/projects/productivity/package.json +1 -1
- package/dist/templates/projects/starter/config/app.config.ts +8 -0
- package/dist/templates/proxy.ts +6 -3
- package/migrations/030_taxonomies_team_writes.sql +29 -0
- package/migrations/031_users_role_suspended.sql +41 -0
- package/package.json +3 -3
- package/scripts/build/registry/__tests__/build-output.test.mjs +1 -1
- package/scripts/build/registry/__tests__/project-mode-root-first.test.mjs +6 -6
- package/scripts/build/registry/__tests__/write-places.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts-wire.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts.test.mjs +1 -1
- package/scripts/build/registry/host/README.md +2 -2
- package/scripts/build/registry/host/__tests__/facade-emitter.test.mjs +14 -13
- package/scripts/build/registry/host/__tests__/host-mode.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project-composition.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project.test.mjs +2 -2
- package/scripts/build/registry/host/__tests__/host-proxy-areas.test.mjs +29 -2
- package/scripts/build/registry/host/__tests__/host-robustness.test.mjs +1 -1
- package/scripts/build/registry/host/facade-emitter.mjs +1 -1
- package/scripts/build/registry/host/next-route-exports.json +2 -2
- package/scripts/build/registry/host/proxy-areas.mjs +29 -2
- package/scripts/db/verify-theme-migrations.mjs +1 -1
- package/templates/next.config.mjs +11 -31
- package/templates/projects/blog/package.json +1 -1
- package/templates/projects/crm/package.json +1 -1
- package/templates/projects/productivity/package.json +1 -1
- package/templates/projects/starter/config/app.config.ts +8 -0
- package/templates/proxy.ts +6 -3
- package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +5 -4
package/README.md
CHANGED
|
@@ -19,6 +19,8 @@ pnpm db:migrate
|
|
|
19
19
|
pnpm dev
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
With lifecycle scripts disabled (`pnpm install --frozen-lockfile --ignore-scripts`) nothing else is needed: `nextspark dev`, `build` and `prepare` generate `src/app` and the registries. Only Cypress needs `pnpm exec cypress install` before `pnpm cy:run`.
|
|
23
|
+
|
|
22
24
|
Or initialize in an existing project:
|
|
23
25
|
|
|
24
26
|
```bash
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SignupForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/SignupForm.tsx"],"names":[],"mappings":"AA+BA,wBAAgB,UAAU,
|
|
1
|
+
{"version":3,"file":"SignupForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/SignupForm.tsx"],"names":[],"mappings":"AA+BA,wBAAgB,UAAU,4CAqnBzB"}
|
|
@@ -18,7 +18,7 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
|
|
|
18
18
|
import { Separator } from "../../ui/separator.js";
|
|
19
19
|
import { PasswordInput } from "../../ui/password-input.js";
|
|
20
20
|
import { Mail, User, Loader2, AlertCircle, ArrowRight, MailCheck, CheckCircle2, Users } from "lucide-react";
|
|
21
|
-
import { signupSchema } from "../../../lib/validation.js";
|
|
21
|
+
import { inviteSignupSchema, signupSchema } from "../../../lib/validation.js";
|
|
22
22
|
import { sel } from "../../../lib/selectors/auth-sel.js";
|
|
23
23
|
import { useTranslations } from "next-intl";
|
|
24
24
|
import { AuthTranslationPreloader } from "../../../lib/i18n/AuthTranslationPreloader.js";
|
|
@@ -43,6 +43,8 @@ function SignupForm() {
|
|
|
43
43
|
const callbackUrl = safeCallbackPath(searchParams.get("callbackUrl"));
|
|
44
44
|
const inviteToken = searchParams.get("inviteToken");
|
|
45
45
|
const passwordAvailable = inviteToken ? readiness.capabilities.invitationPasswordSignup : readiness.availableMethods.includes("email-password");
|
|
46
|
+
const invitePasswordless = Boolean(inviteToken) && !passwordAvailable && readiness.capabilities.invitationSignup;
|
|
47
|
+
const formAvailable = passwordAvailable || invitePasswordless;
|
|
46
48
|
const loginHref = callbackUrl ? `/login?callbackUrl=${encodeURIComponent(callbackUrl)}` : "/login";
|
|
47
49
|
const {
|
|
48
50
|
register,
|
|
@@ -50,7 +52,8 @@ function SignupForm() {
|
|
|
50
52
|
watch,
|
|
51
53
|
formState: { errors }
|
|
52
54
|
} = useForm({
|
|
53
|
-
|
|
55
|
+
// Without a password field the form validates the rest only
|
|
56
|
+
resolver: zodResolver(invitePasswordless ? inviteSignupSchema : signupSchema),
|
|
54
57
|
defaultValues: {
|
|
55
58
|
email: inviteEmail || ""
|
|
56
59
|
}
|
|
@@ -75,7 +78,7 @@ function SignupForm() {
|
|
|
75
78
|
},
|
|
76
79
|
body: JSON.stringify({
|
|
77
80
|
email: data.email,
|
|
78
|
-
password: data.password,
|
|
81
|
+
...invitePasswordless ? {} : { password: data.password },
|
|
79
82
|
firstName: data.firstName,
|
|
80
83
|
lastName: data.lastName,
|
|
81
84
|
inviteToken
|
|
@@ -100,7 +103,12 @@ function SignupForm() {
|
|
|
100
103
|
toast.success(t("signup.messages.inviteSuccess"), {
|
|
101
104
|
description: t("signup.messages.inviteJoinedTeam")
|
|
102
105
|
});
|
|
103
|
-
|
|
106
|
+
const redirectTo = ((_a = result.data) == null ? void 0 : _a.redirectTo) || "/dashboard/settings/teams";
|
|
107
|
+
if (invitePasswordless) {
|
|
108
|
+
router.push(`/login?${new URLSearchParams({ email: data.email, fromInvite: "true", callbackUrl: redirectTo })}`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
router.push(redirectTo);
|
|
104
112
|
return;
|
|
105
113
|
}
|
|
106
114
|
await signUp({
|
|
@@ -119,7 +127,7 @@ function SignupForm() {
|
|
|
119
127
|
} finally {
|
|
120
128
|
setLoadingProvider(null);
|
|
121
129
|
}
|
|
122
|
-
}, [agreedToTerms, signUp, t, inviteToken, router]);
|
|
130
|
+
}, [agreedToTerms, signUp, t, inviteToken, invitePasswordless, router]);
|
|
123
131
|
const handleGoogleSignUp = async () => {
|
|
124
132
|
setLoadingProvider("google");
|
|
125
133
|
setError(null);
|
|
@@ -147,7 +155,7 @@ function SignupForm() {
|
|
|
147
155
|
setResendingEmail(false);
|
|
148
156
|
}
|
|
149
157
|
};
|
|
150
|
-
if (readiness.state === "loading" || readiness.state === "error" || readiness.state === "unavailable" && !(inviteToken &&
|
|
158
|
+
if (readiness.state === "loading" || readiness.state === "error" || readiness.state === "unavailable" && !(inviteToken && formAvailable)) {
|
|
151
159
|
const isLoading = readiness.state === "loading";
|
|
152
160
|
const isError = readiness.state === "error";
|
|
153
161
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -341,7 +349,7 @@ function SignupForm() {
|
|
|
341
349
|
/* @__PURE__ */ jsx(Users, { className: "h-4 w-4" }),
|
|
342
350
|
/* @__PURE__ */ jsx(AlertDescription, { children: t("signup.inviteBanner") })
|
|
343
351
|
] }),
|
|
344
|
-
|
|
352
|
+
formAvailable && /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(onSubmit), className: "space-y-4", children: [
|
|
345
353
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [
|
|
346
354
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
347
355
|
/* @__PURE__ */ jsx(Label, { htmlFor: "firstName", children: t("signup.form.firstName") }),
|
|
@@ -402,41 +410,43 @@ function SignupForm() {
|
|
|
402
410
|
] }),
|
|
403
411
|
errors.email && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors.email.message })
|
|
404
412
|
] }),
|
|
405
|
-
/* @__PURE__ */ jsxs(
|
|
406
|
-
/* @__PURE__ */
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
/* @__PURE__ */
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
413
|
+
!invitePasswordless && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
414
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
415
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "password", children: t("signup.form.password") }),
|
|
416
|
+
/* @__PURE__ */ jsx(
|
|
417
|
+
PasswordInput,
|
|
418
|
+
{
|
|
419
|
+
...register("password"),
|
|
420
|
+
id: "password",
|
|
421
|
+
autoComplete: "new-password",
|
|
422
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
423
|
+
showRequirements: true,
|
|
424
|
+
password,
|
|
425
|
+
requirementLabels: {
|
|
426
|
+
minChars: t("signup.form.passwordRequirements.minChars"),
|
|
427
|
+
uppercase: t("signup.form.passwordRequirements.uppercase"),
|
|
428
|
+
lowercase: t("signup.form.passwordRequirements.lowercase"),
|
|
429
|
+
number: t("signup.form.passwordRequirements.number")
|
|
430
|
+
},
|
|
431
|
+
"data-cy": sel("auth.signup.password")
|
|
432
|
+
}
|
|
433
|
+
),
|
|
434
|
+
errors.password && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors.password.message })
|
|
435
|
+
] }),
|
|
436
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
437
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "confirmPassword", children: t("signup.form.confirmPassword") }),
|
|
438
|
+
/* @__PURE__ */ jsx(
|
|
439
|
+
PasswordInput,
|
|
440
|
+
{
|
|
441
|
+
...register("confirmPassword"),
|
|
442
|
+
id: "confirmPassword",
|
|
443
|
+
autoComplete: "new-password",
|
|
444
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
445
|
+
"data-cy": sel("auth.signup.confirmPassword")
|
|
446
|
+
}
|
|
447
|
+
),
|
|
448
|
+
errors.confirmPassword && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
|
|
449
|
+
] })
|
|
440
450
|
] }),
|
|
441
451
|
error && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", "data-cy": sel("auth.signup.error"), children: [
|
|
442
452
|
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
|
|
@@ -479,7 +489,7 @@ function SignupForm() {
|
|
|
479
489
|
}
|
|
480
490
|
)
|
|
481
491
|
] }),
|
|
482
|
-
!
|
|
492
|
+
!formAvailable && !googleAvailable && /* @__PURE__ */ jsxs(
|
|
483
493
|
Alert,
|
|
484
494
|
{
|
|
485
495
|
role: "alert",
|
|
@@ -495,12 +505,12 @@ function SignupForm() {
|
|
|
495
505
|
]
|
|
496
506
|
}
|
|
497
507
|
),
|
|
498
|
-
inviteToken && !
|
|
508
|
+
inviteToken && !formAvailable && googleAvailable && /* @__PURE__ */ jsxs(Alert, { role: "alert", className: "mb-4", "data-cy": sel("auth.signup.inviteUnavailable"), children: [
|
|
499
509
|
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
500
510
|
/* @__PURE__ */ jsx(AlertDescription, { children: t("signup.inviteUnavailable") })
|
|
501
511
|
] }),
|
|
502
512
|
googleAvailable && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
503
|
-
|
|
513
|
+
formAvailable && /* @__PURE__ */ jsxs("div", { className: "relative my-4", children: [
|
|
504
514
|
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx(Separator, { className: "w-full" }) }),
|
|
505
515
|
/* @__PURE__ */ jsx("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx("span", { className: "bg-background px-2 text-muted-foreground", children: t("signup.form.orContinueWith") }) })
|
|
506
516
|
] }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-panel.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/config-panel.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AACxF,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"config-panel.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/config-panel.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AACxF,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,uBAAuB,CAAA;AAmB1E,UAAU,gBAAgB;IACxB,YAAY,EAAE,kBAAkB,CAAA;IAChC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAA;CACvD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACrB,EAAE,gBAAgB,2CA6elB"}
|
|
@@ -36,7 +36,8 @@ import {
|
|
|
36
36
|
SelectTrigger,
|
|
37
37
|
SelectValue
|
|
38
38
|
} from "../../ui/select.js";
|
|
39
|
-
import {
|
|
39
|
+
import { withBasePathIfInApp } from "../../../lib/base-path.js";
|
|
40
|
+
import { fetchWithTeam } from "../../../lib/api/entities.js";
|
|
40
41
|
function ConfigPanel({
|
|
41
42
|
entityConfig,
|
|
42
43
|
entityFields,
|
|
@@ -59,7 +60,7 @@ function ConfigPanel({
|
|
|
59
60
|
queryKey: ["taxonomies", taxonomyApiPath],
|
|
60
61
|
queryFn: async () => {
|
|
61
62
|
if (!taxonomyApiPath) return { data: [] };
|
|
62
|
-
const response = await
|
|
63
|
+
const response = await fetchWithTeam(`/api/v1/${taxonomyApiPath}`);
|
|
63
64
|
if (!response.ok) return { data: [] };
|
|
64
65
|
return response.json();
|
|
65
66
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-fields-sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/entity-fields-sidebar.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;
|
|
1
|
+
{"version":3,"file":"entity-fields-sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/entity-fields-sidebar.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AAmBxF,UAAU,wBAAwB;IAChC,YAAY,EAAE,kBAAkB,CAAA;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACjD,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAChD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,kBAAuB,EACvB,gBAAgB,EACjB,EAAE,wBAAwB,2CAmS1B"}
|
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
SelectTrigger,
|
|
19
19
|
SelectValue
|
|
20
20
|
} from "../../ui/select.js";
|
|
21
|
-
import {
|
|
21
|
+
import { withBasePathIfInApp } from "../../../lib/base-path.js";
|
|
22
|
+
import { fetchWithTeam } from "../../../lib/api/entities.js";
|
|
22
23
|
function EntityFieldsSidebar({
|
|
23
24
|
entityConfig,
|
|
24
25
|
fields,
|
|
@@ -37,7 +38,7 @@ function EntityFieldsSidebar({
|
|
|
37
38
|
queryKey: ["taxonomies", taxonomyApiPath],
|
|
38
39
|
queryFn: async () => {
|
|
39
40
|
if (!taxonomyApiPath) return { data: [] };
|
|
40
|
-
const response = await
|
|
41
|
+
const response = await fetchWithTeam(`/api/v1/${taxonomyApiPath}`);
|
|
41
42
|
if (!response.ok) return { data: [] };
|
|
42
43
|
return response.json();
|
|
43
44
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersTable.d.ts","sourceRoot":"","sources":["../../../../src/components/users/tables/UsersTable.tsx"],"names":[],"mappings":"AAsCA,OAAO,EAEL,IAAI,EAUL,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAM1D,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AASD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"UsersTable.d.ts","sourceRoot":"","sources":["../../../../src/components/users/tables/UsersTable.tsx"],"names":[],"mappings":"AAsCA,OAAO,EAEL,IAAI,EAUL,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAM1D,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AASD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,eAAe,2CAwY1E"}
|
|
@@ -183,9 +183,9 @@ function UsersTable({ users, isLoading, onRefresh }) {
|
|
|
183
183
|
};
|
|
184
184
|
const getRoleBadgeVariant = (role) => {
|
|
185
185
|
switch (role) {
|
|
186
|
-
case "
|
|
186
|
+
case "suspended":
|
|
187
187
|
return "destructive";
|
|
188
|
-
case "
|
|
188
|
+
case "developer":
|
|
189
189
|
return "default";
|
|
190
190
|
case "member":
|
|
191
191
|
return "secondary";
|
|
@@ -284,8 +284,7 @@ function UsersTable({ users, isLoading, onRefresh }) {
|
|
|
284
284
|
onValueChange: (value) => handleRoleChange(user, value),
|
|
285
285
|
children: [
|
|
286
286
|
/* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "member", children: "Member" }),
|
|
287
|
-
/* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "
|
|
288
|
-
/* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "admin", children: "Admin" })
|
|
287
|
+
/* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "developer", children: "Developer" })
|
|
289
288
|
]
|
|
290
289
|
}
|
|
291
290
|
) })
|
|
@@ -2,6 +2,7 @@ import type { AuthLoginMethod } from '../lib/config/types';
|
|
|
2
2
|
export type AuthReadinessState = 'loading' | 'ready' | 'unavailable' | 'error';
|
|
3
3
|
/** Server-derived flows independent of the login UI methods; see runtime-readiness. */
|
|
4
4
|
export interface ClientAuthCapabilities {
|
|
5
|
+
invitationSignup: boolean;
|
|
5
6
|
invitationPasswordSignup: boolean;
|
|
6
7
|
passwordRecovery: boolean;
|
|
7
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuthReadiness.d.ts","sourceRoot":"","sources":["../../src/hooks/useAuthReadiness.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,OAAO,CAAA;AAE9E,uFAAuF;AACvF,MAAM,WAAW,sBAAsB;IACrC,wBAAwB,EAAE,OAAO,CAAA;IACjC,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,kBAAkB,CAAA;IACzB,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,YAAY,EAAE,sBAAsB,CAAA;CACrC;
|
|
1
|
+
{"version":3,"file":"useAuthReadiness.d.ts","sourceRoot":"","sources":["../../src/hooks/useAuthReadiness.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,OAAO,CAAA;AAE9E,uFAAuF;AACvF,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,OAAO,CAAA;IACzB,wBAAwB,EAAE,OAAO,CAAA;IACjC,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,kBAAkB,CAAA;IACzB,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,YAAY,EAAE,sBAAsB,CAAA;CACrC;AAyCD,qFAAqF;AACrF,wBAAgB,gBAAgB,IAAI,mBAAmB,CA8BtD"}
|
|
@@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import { withBasePath } from "../lib/base-path.js";
|
|
4
4
|
import { isAuthLoginMethod } from "../lib/auth/auth-methods.js";
|
|
5
5
|
const NO_CAPABILITIES = {
|
|
6
|
+
invitationSignup: false,
|
|
6
7
|
invitationPasswordSignup: false,
|
|
7
8
|
passwordRecovery: false
|
|
8
9
|
};
|
|
@@ -19,13 +20,14 @@ function parseReadiness(value) {
|
|
|
19
20
|
throw new Error("Ready auth response has no available method");
|
|
20
21
|
}
|
|
21
22
|
const capabilities = candidate.capabilities;
|
|
22
|
-
if (!capabilities || typeof capabilities !== "object" || typeof capabilities.invitationPasswordSignup !== "boolean" || typeof capabilities.passwordRecovery !== "boolean") {
|
|
23
|
+
if (!capabilities || typeof capabilities !== "object" || typeof capabilities.invitationSignup !== "boolean" || typeof capabilities.invitationPasswordSignup !== "boolean" || typeof capabilities.passwordRecovery !== "boolean") {
|
|
23
24
|
throw new Error("Invalid auth readiness capabilities");
|
|
24
25
|
}
|
|
25
26
|
return {
|
|
26
27
|
state: candidate.status,
|
|
27
28
|
availableMethods: [...new Set(candidate.availableMethods)],
|
|
28
29
|
capabilities: {
|
|
30
|
+
invitationSignup: capabilities.invitationSignup,
|
|
29
31
|
invitationPasswordSignup: capabilities.invitationPasswordSignup,
|
|
30
32
|
passwordRecovery: capabilities.passwordRecovery
|
|
31
33
|
}
|
|
@@ -6,12 +6,12 @@ import { ACTIVE_TEAM_COOKIE, activeTeamIdForSession } from "../teams/active-team
|
|
|
6
6
|
import { redirect } from "next/navigation";
|
|
7
7
|
import { GenericEntityService } from "../services/generic-entity.service.js";
|
|
8
8
|
import { entityRegistry } from "../entities/registry.js";
|
|
9
|
-
import {
|
|
9
|
+
import { getAuthorizationSession } from "../auth/authorization-session.js";
|
|
10
10
|
import { checkPermission } from "../permissions/check.js";
|
|
11
11
|
async function getAuthContext() {
|
|
12
12
|
var _a, _b, _c;
|
|
13
13
|
const headersList = await headers();
|
|
14
|
-
const session = await
|
|
14
|
+
const session = await getAuthorizationSession(headersList);
|
|
15
15
|
if (!((_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id)) {
|
|
16
16
|
return { success: false, error: "Authentication required" };
|
|
17
17
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { revalidatePath } from "next/cache";
|
|
3
3
|
import { headers } from "next/headers";
|
|
4
|
-
import {
|
|
4
|
+
import { getAuthorizationSession } from "../auth/authorization-session.js";
|
|
5
5
|
import { TeamService } from "../services/team.service.js";
|
|
6
6
|
import { TeamMemberService } from "../services/team-member.service.js";
|
|
7
7
|
import { getInvitableRoles } from "../teams/permissions.js";
|
|
@@ -9,7 +9,7 @@ import { APP_CONFIG_MERGED } from "../config/config-sync.js";
|
|
|
9
9
|
async function getAuthUser() {
|
|
10
10
|
var _a;
|
|
11
11
|
const headersList = await headers();
|
|
12
|
-
const session = await
|
|
12
|
+
const session = await getAuthorizationSession(headersList);
|
|
13
13
|
if (!((_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id)) {
|
|
14
14
|
return { success: false, error: "Authentication required" };
|
|
15
15
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { revalidatePath } from "next/cache";
|
|
3
3
|
import { headers } from "next/headers";
|
|
4
|
-
import {
|
|
4
|
+
import { getAuthorizationSession } from "../auth/authorization-session.js";
|
|
5
5
|
import { UserService } from "../services/user.service.js";
|
|
6
6
|
async function updateProfile(data) {
|
|
7
7
|
var _a;
|
|
8
8
|
try {
|
|
9
9
|
const headersList = await headers();
|
|
10
|
-
const session = await
|
|
10
|
+
const session = await getAuthorizationSession(headersList);
|
|
11
11
|
if (!((_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id)) {
|
|
12
12
|
return { success: false, error: "Authentication required" };
|
|
13
13
|
}
|
|
@@ -54,7 +54,7 @@ async function updateAvatar(formData) {
|
|
|
54
54
|
var _a;
|
|
55
55
|
try {
|
|
56
56
|
const headersList = await headers();
|
|
57
|
-
const session = await
|
|
57
|
+
const session = await getAuthorizationSession(headersList);
|
|
58
58
|
if (!((_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id)) {
|
|
59
59
|
return { success: false, error: "Authentication required" };
|
|
60
60
|
}
|
|
@@ -109,7 +109,7 @@ async function deleteAccount() {
|
|
|
109
109
|
var _a;
|
|
110
110
|
try {
|
|
111
111
|
const headersList = await headers();
|
|
112
|
-
const session = await
|
|
112
|
+
const session = await getAuthorizationSession(headersList);
|
|
113
113
|
if (!((_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id)) {
|
|
114
114
|
return { success: false, error: "Authentication required" };
|
|
115
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dual-auth.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/dual-auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"dual-auth.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/dual-auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAQvD,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAKrB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAK/F;;;GAGG;AACH,eAAO,MAAM,oBAAoB,uBAAuB,CAAA;AAExD;;GAEG;AACH,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AACnD,eAAO,MAAM,kBAAkB,8BAA8B,CAAA;AAE7D;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,kBAAkB,CAAA;AAOjD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAA;IACpC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,mHAAmH;IACnH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+GAA+G;IAC/G,iBAAiB,CAAC,EAAE,QAAQ,CAAA;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3D,0EAA0E;IAC1E,KAAK,CAAC,EAAE,eAAe,CAAA;CACxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,cAAc,CAAC,CA2DzB;AAsKD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAUtG;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,cAAc,GACzB,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC,CAsChC;AAMD;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,cAAc,EAC1B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC,CAkBlB;AA2BD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,MAAkC,EAAE,MAAM,GAAE,MAAY;;;;GAShG;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,cAAc,GAAG,YAAY,CAWlF"}
|
|
@@ -3,6 +3,7 @@ import { getUserDefaultTeamId } from "../../teams/dashboard-team.js";
|
|
|
3
3
|
import { NextResponse } from "next/server";
|
|
4
4
|
import { auth } from "../../auth.js";
|
|
5
5
|
import { validateApiKey } from "../auth.js";
|
|
6
|
+
import { isSuspendedRole } from "../../auth/suspension.js";
|
|
6
7
|
import { apiKeyRateLimitResponse } from "../rate-limit.js";
|
|
7
8
|
import { queryOne } from "../../db.js";
|
|
8
9
|
import { TeamMemberService } from "../../services/team-member.service.js";
|
|
@@ -141,8 +142,8 @@ async function tryApiKeyAuth(request) {
|
|
|
141
142
|
async function trySessionAuth(request) {
|
|
142
143
|
var _a;
|
|
143
144
|
try {
|
|
144
|
-
const session = await auth.api.getSession({ headers: request.headers });
|
|
145
|
-
if (!(session == null ? void 0 : session.user)) {
|
|
145
|
+
const session = await auth.api.getSession({ headers: request.headers, query: { disableCookieCache: true } });
|
|
146
|
+
if (!(session == null ? void 0 : session.user) || isSuspendedRole(session.user.role)) {
|
|
146
147
|
return { success: false, type: "none", user: null };
|
|
147
148
|
}
|
|
148
149
|
const defaultTeamId = await getUserDefaultTeamId(session.user.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/lib/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/lib/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAsHrF;AA8CD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E;AAID;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAM/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAMhF;AAiBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU;QAG1C,MAAM;WACH,MAAM;eACF,MAAM,GAAG,IAAI;cACd,MAAM,GAAG,IAAI;UACjB,MAAM;GAWjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC,CAyED"}
|
package/dist/lib/api/auth.js
CHANGED
|
@@ -11,6 +11,8 @@ function getValidatedApiKey(request) {
|
|
|
11
11
|
return validatedKeys.get(request) ?? null;
|
|
12
12
|
}
|
|
13
13
|
async function validateApiKey(request) {
|
|
14
|
+
const validatedBefore = validatedKeys.get(request);
|
|
15
|
+
if (validatedBefore) return validatedBefore;
|
|
14
16
|
const startTime = Date.now();
|
|
15
17
|
try {
|
|
16
18
|
const apiKey = presentedApiKey(request.headers);
|
|
@@ -63,6 +65,11 @@ async function validateApiKey(request) {
|
|
|
63
65
|
await constantTimeDelay(startTime);
|
|
64
66
|
return null;
|
|
65
67
|
}
|
|
68
|
+
const owner = await queryOne('SELECT role FROM "users" WHERE id = $1', [keyData.userId]);
|
|
69
|
+
if ((owner == null ? void 0 : owner.role) === "suspended") {
|
|
70
|
+
await constantTimeDelay(startTime);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
66
73
|
if (keyData.failedAttempts && keyData.failedAttempts > 0) {
|
|
67
74
|
resetFailedAttempts(keyData.id).catch(console.error);
|
|
68
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AA+wBvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEnF;AA8lBD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAErF;AAwcD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEpJ;AAoND;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AA4bD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AAwKD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtF"}
|
|
@@ -5,7 +5,7 @@ import { generateEntitySchemas } from "../../entities/schema-generator.js";
|
|
|
5
5
|
import { publicSlugIssue, otherBasePathSegments } from "../../entities/public-slug.js";
|
|
6
6
|
import { getAllEntityConfigs } from "../../entities/registry.js";
|
|
7
7
|
import { entityResponseSystemColumns, taxonomyResponseFields } from "../../entities/portable/response-shape.js";
|
|
8
|
-
import { queryWithRLS, mutateWithRLS, queryOneWithRLS } from "../../db.js";
|
|
8
|
+
import { queryWithRLS, mutateWithRLS, queryOneWithRLS, getTransactionClient } from "../../db.js";
|
|
9
9
|
import {
|
|
10
10
|
createApiResponse,
|
|
11
11
|
createApiError,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "../helpers.js";
|
|
23
23
|
import { beforeEntityCreate, afterEntityCreate, beforeEntityUpdate, afterEntityUpdate, beforeEntityDelete, afterEntityDelete, beforeEntityRead, afterEntityRead } from "../../entities/entity-hooks.js";
|
|
24
24
|
import { logGenericHandlerUsage } from "./audit-log.js";
|
|
25
|
-
import { checkPermission } from "../../permissions/check.js";
|
|
25
|
+
import { checkPermission, declaredPublishPermission, publishPermissionFor } from "../../permissions/check.js";
|
|
26
26
|
import { extractPatternIds } from "../../blocks/pattern-resolver.js";
|
|
27
27
|
import { isPatternReference } from "../../../types/pattern-reference.js";
|
|
28
28
|
import { PatternUsageService } from "../../services/pattern-usage.service.js";
|
|
@@ -122,7 +122,7 @@ async function includeTaxonomiesInData(entityConfig, items, userId) {
|
|
|
122
122
|
};
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
|
-
async function processTaxonomyRelations(entityConfig, entityId, data, userId, isUpdate = false) {
|
|
125
|
+
async function processTaxonomyRelations(entityConfig, entityId, data, userId, teamId, isUpdate = false) {
|
|
126
126
|
var _a, _b, _c;
|
|
127
127
|
if (!((_a = entityConfig.taxonomies) == null ? void 0 : _a.enabled) || !((_c = (_b = entityConfig.taxonomies) == null ? void 0 : _b.types) == null ? void 0 : _c.length)) {
|
|
128
128
|
return;
|
|
@@ -146,8 +146,9 @@ async function processTaxonomyRelations(entityConfig, entityId, data, userId, is
|
|
|
146
146
|
const taxonomyId = typeof taxonomyIds[i] === "object" && taxonomyIds[i] !== null ? taxonomyIds[i].id : taxonomyIds[i];
|
|
147
147
|
await mutateWithRLS(
|
|
148
148
|
`INSERT INTO entity_taxonomy_relations ("entityType", "entityId", "taxonomyId", "order")
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
SELECT $1, $2, id, $4 FROM taxonomies
|
|
150
|
+
WHERE id = $3 AND type = $5 AND ("teamId" IS NULL OR "teamId" = $6)`,
|
|
151
|
+
[entityType, entityId, taxonomyId, i + 1, taxonomyType.type, teamId],
|
|
151
152
|
userId
|
|
152
153
|
);
|
|
153
154
|
}
|
|
@@ -785,7 +786,7 @@ async function handleGenericCreate(request) {
|
|
|
785
786
|
return runWithAuditLog(request, (audit) => handleGenericCreateImpl(request, audit));
|
|
786
787
|
}
|
|
787
788
|
async function handleGenericCreateImpl(request, audit) {
|
|
788
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
789
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
789
790
|
try {
|
|
790
791
|
const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
|
|
791
792
|
if (!resolution.isValidEntity || !resolution.entityConfig) {
|
|
@@ -886,6 +887,13 @@ async function handleGenericCreateImpl(request, audit) {
|
|
|
886
887
|
);
|
|
887
888
|
return addCorsHeaders(response2, request);
|
|
888
889
|
}
|
|
890
|
+
const createStatusField = entityConfig.fields.find((f) => f.name === "status");
|
|
891
|
+
const createStatus = validatedData.status ?? (createStatusField == null ? void 0 : createStatusField.defaultValue);
|
|
892
|
+
if (publishPermissionFor(entityConfig.slug, createStatus)) {
|
|
893
|
+
const publishDenied = await checkAuthPermission(authResult, entityConfig.slug, "publish", teamId, request);
|
|
894
|
+
if (publishDenied) return publishDenied;
|
|
895
|
+
}
|
|
896
|
+
const checkStoredStatus = createStatus === void 0 && !!createStatusField && !!declaredPublishPermission(entityConfig.slug);
|
|
889
897
|
if (idStrategy === "serial") {
|
|
890
898
|
insertFields = ['"userId"', '"teamId"'];
|
|
891
899
|
placeholders = ["$1", "$2"];
|
|
@@ -984,8 +992,28 @@ async function handleGenericCreateImpl(request, audit) {
|
|
|
984
992
|
INSERT INTO "${tableName}" (${insertFields.join(", ")})
|
|
985
993
|
VALUES (${placeholders.join(", ")}) RETURNING *
|
|
986
994
|
`;
|
|
987
|
-
|
|
988
|
-
|
|
995
|
+
let insertResult;
|
|
996
|
+
if (checkStoredStatus) {
|
|
997
|
+
const tx = await getTransactionClient(authResult.user.id);
|
|
998
|
+
try {
|
|
999
|
+
insertResult = await tx.mutate(insertQuery, values);
|
|
1000
|
+
if (((_g = insertResult.rows[0]) == null ? void 0 : _g.status) === "published") {
|
|
1001
|
+
const publishDenied = await checkAuthPermission(authResult, entityConfig.slug, "publish", teamId, request);
|
|
1002
|
+
if (publishDenied) {
|
|
1003
|
+
await tx.rollback();
|
|
1004
|
+
return publishDenied;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
await tx.commit();
|
|
1008
|
+
} catch (error) {
|
|
1009
|
+
await tx.rollback().catch(() => {
|
|
1010
|
+
});
|
|
1011
|
+
throw error;
|
|
1012
|
+
}
|
|
1013
|
+
} else {
|
|
1014
|
+
insertResult = await mutateWithRLS(insertQuery, values, authResult.user.id);
|
|
1015
|
+
}
|
|
1016
|
+
const createdEntityId = String((_h = insertResult.rows[0]) == null ? void 0 : _h.id);
|
|
989
1017
|
if (limitSlug) {
|
|
990
1018
|
UsageService.track({
|
|
991
1019
|
teamId,
|
|
@@ -1015,8 +1043,8 @@ async function handleGenericCreateImpl(request, audit) {
|
|
|
1015
1043
|
`;
|
|
1016
1044
|
const createdItems = await queryWithRLS(selectQuery, [createdEntityId], authResult.user.id);
|
|
1017
1045
|
const createdItem = createdItems[0];
|
|
1018
|
-
if ((
|
|
1019
|
-
await processTaxonomyRelations(entityConfig, createdEntityId, body, authResult.user.id, false);
|
|
1046
|
+
if ((_i = entityConfig.taxonomies) == null ? void 0 : _i.enabled) {
|
|
1047
|
+
await processTaxonomyRelations(entityConfig, createdEntityId, body, authResult.user.id, teamId, false);
|
|
1020
1048
|
}
|
|
1021
1049
|
const metadataWasProvided = metas && typeof metas === "object" && Object.keys(metas).length > 0;
|
|
1022
1050
|
if (metadataWasProvided) {
|
|
@@ -1028,7 +1056,7 @@ async function handleGenericCreateImpl(request, audit) {
|
|
|
1028
1056
|
);
|
|
1029
1057
|
}
|
|
1030
1058
|
let responseItem = createdItem;
|
|
1031
|
-
if ((
|
|
1059
|
+
if ((_j = entityConfig.taxonomies) == null ? void 0 : _j.enabled) {
|
|
1032
1060
|
const itemsWithTaxonomies = await includeTaxonomiesInData(
|
|
1033
1061
|
entityConfig,
|
|
1034
1062
|
[createdItem],
|
|
@@ -1327,6 +1355,18 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1327
1355
|
);
|
|
1328
1356
|
return addCorsHeaders(response2, request);
|
|
1329
1357
|
}
|
|
1358
|
+
let statusRead;
|
|
1359
|
+
if ("status" in entityData && entityConfig.fields.some((f) => f.name === "status") && declaredPublishPermission(entityConfig.slug)) {
|
|
1360
|
+
statusRead = (await queryWithRLS(
|
|
1361
|
+
`SELECT "status" FROM "${tableName}" WHERE id = $1 AND "teamId" = $2`,
|
|
1362
|
+
[id, teamId],
|
|
1363
|
+
authResult.user.id
|
|
1364
|
+
))[0];
|
|
1365
|
+
if (statusRead && publishPermissionFor(entityConfig.slug, validatedData.status, statusRead.status)) {
|
|
1366
|
+
const publishDenied = await checkAuthPermission(authResult, entityConfig.slug, "publish", teamId, request);
|
|
1367
|
+
if (publishDenied) return publishDenied;
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1330
1370
|
const updates = [];
|
|
1331
1371
|
const values = [];
|
|
1332
1372
|
let paramCount = 1;
|
|
@@ -1425,6 +1465,10 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1425
1465
|
whereConditions.push(`"${updateOwnershipFilter.field}" = $${paramCount++}`);
|
|
1426
1466
|
values.push(updateOwnershipFilter.value);
|
|
1427
1467
|
}
|
|
1468
|
+
if (statusRead) {
|
|
1469
|
+
whereConditions.push(`"status" IS NOT DISTINCT FROM $${paramCount++}`);
|
|
1470
|
+
values.push(statusRead.status);
|
|
1471
|
+
}
|
|
1428
1472
|
const updateQuery = `
|
|
1429
1473
|
UPDATE "${tableName}"
|
|
1430
1474
|
SET ${updates.join(", ")}
|
|
@@ -1433,6 +1477,16 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1433
1477
|
`;
|
|
1434
1478
|
const result = await mutateWithRLS(updateQuery, values, authResult.user.id);
|
|
1435
1479
|
if (!result.rows || result.rows.length === 0) {
|
|
1480
|
+
if (statusRead) {
|
|
1481
|
+
const [now] = await queryWithRLS(
|
|
1482
|
+
`SELECT "status" FROM "${tableName}" WHERE id = $1 AND "teamId" = $2`,
|
|
1483
|
+
[id, teamId],
|
|
1484
|
+
authResult.user.id
|
|
1485
|
+
);
|
|
1486
|
+
if (now && now.status !== statusRead.status) {
|
|
1487
|
+
return addCorsHeaders(createApiError("The record changed while it was being saved. Reload it and try again.", 409, void 0, "STATUS_CHANGED"), request);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1436
1490
|
const response2 = createApiError("Item not found", 404);
|
|
1437
1491
|
return addCorsHeaders(response2, request);
|
|
1438
1492
|
}
|
|
@@ -1452,7 +1506,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1452
1506
|
updatedItem = result[0];
|
|
1453
1507
|
}
|
|
1454
1508
|
if ((_g = entityConfig.taxonomies) == null ? void 0 : _g.enabled) {
|
|
1455
|
-
await processTaxonomyRelations(entityConfig, id, body, authResult.user.id, true);
|
|
1509
|
+
await processTaxonomyRelations(entityConfig, id, body, authResult.user.id, teamId, true);
|
|
1456
1510
|
}
|
|
1457
1511
|
if (metadataWasProvided) {
|
|
1458
1512
|
await processEntityMetadata(
|