@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.
Files changed (136) hide show
  1. package/README.md +2 -0
  2. package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
  3. package/dist/components/auth/forms/SignupForm.js +55 -45
  4. package/dist/components/dashboard/block-editor/config-panel.d.ts.map +1 -1
  5. package/dist/components/dashboard/block-editor/config-panel.js +3 -2
  6. package/dist/components/dashboard/block-editor/entity-fields-sidebar.d.ts.map +1 -1
  7. package/dist/components/dashboard/block-editor/entity-fields-sidebar.js +3 -2
  8. package/dist/components/users/tables/UsersTable.d.ts.map +1 -1
  9. package/dist/components/users/tables/UsersTable.js +3 -4
  10. package/dist/hooks/useAuthReadiness.d.ts +1 -0
  11. package/dist/hooks/useAuthReadiness.d.ts.map +1 -1
  12. package/dist/hooks/useAuthReadiness.js +3 -1
  13. package/dist/lib/actions/entity.actions.js +2 -2
  14. package/dist/lib/actions/team.actions.js +2 -2
  15. package/dist/lib/actions/user.actions.js +4 -4
  16. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  17. package/dist/lib/api/auth/dual-auth.js +3 -2
  18. package/dist/lib/api/auth.d.ts.map +1 -1
  19. package/dist/lib/api/auth.js +7 -0
  20. package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
  21. package/dist/lib/api/entity/generic-handler.js +66 -12
  22. package/dist/lib/api/entity-handler.js +2 -2
  23. package/dist/lib/api/helpers.d.ts.map +1 -1
  24. package/dist/lib/api/helpers.js +4 -2
  25. package/dist/lib/api/post-categories.d.ts +29 -0
  26. package/dist/lib/api/post-categories.d.ts.map +1 -0
  27. package/dist/lib/api/post-categories.js +33 -0
  28. package/dist/lib/auth/auth-methods.d.ts +5 -2
  29. package/dist/lib/auth/auth-methods.d.ts.map +1 -1
  30. package/dist/lib/auth/auth-methods.js +4 -2
  31. package/dist/lib/auth/authorization-session.d.ts +14 -0
  32. package/dist/lib/auth/authorization-session.d.ts.map +1 -0
  33. package/dist/lib/auth/authorization-session.js +10 -0
  34. package/dist/lib/auth/request-session.d.ts +5 -0
  35. package/dist/lib/auth/request-session.d.ts.map +1 -1
  36. package/dist/lib/auth/request-session.js +3 -0
  37. package/dist/lib/auth/runtime-readiness.d.ts +7 -4
  38. package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
  39. package/dist/lib/auth/runtime-readiness.js +7 -6
  40. package/dist/lib/auth/sample-accounts.d.ts +2 -1
  41. package/dist/lib/auth/sample-accounts.d.ts.map +1 -1
  42. package/dist/lib/auth/sample-accounts.js +4 -1
  43. package/dist/lib/auth/suspension.d.ts +22 -0
  44. package/dist/lib/auth/suspension.d.ts.map +1 -0
  45. package/dist/lib/auth/suspension.js +43 -0
  46. package/dist/lib/auth.d.ts.map +1 -1
  47. package/dist/lib/auth.js +15 -15
  48. package/dist/lib/config/app.config.d.ts.map +1 -1
  49. package/dist/lib/config/app.config.js +6 -7
  50. package/dist/lib/config/types.d.ts +8 -6
  51. package/dist/lib/config/types.d.ts.map +1 -1
  52. package/dist/lib/db-pool.d.ts +31 -0
  53. package/dist/lib/db-pool.d.ts.map +1 -0
  54. package/dist/lib/db-pool.js +75 -0
  55. package/dist/lib/db.d.ts +1 -1
  56. package/dist/lib/db.d.ts.map +1 -1
  57. package/dist/lib/db.js +11 -14
  58. package/dist/lib/entities/api-generator.js +5 -5
  59. package/dist/lib/oauth/token-refresh.d.ts.map +1 -1
  60. package/dist/lib/oauth/token-refresh.js +3 -6
  61. package/dist/lib/permissions/check.d.ts +9 -0
  62. package/dist/lib/permissions/check.d.ts.map +1 -1
  63. package/dist/lib/permissions/check.js +11 -1
  64. package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
  65. package/dist/lib/services/generic-entity.service.js +39 -7
  66. package/dist/lib/services/transactional-meta.service.d.ts.map +1 -1
  67. package/dist/lib/services/transactional-meta.service.js +7 -8
  68. package/dist/lib/validation.d.ts +5 -0
  69. package/dist/lib/validation.d.ts.map +1 -1
  70. package/dist/lib/validation.js +2 -0
  71. package/dist/migrations/030_taxonomies_team_writes.sql +29 -0
  72. package/dist/migrations/031_users_role_suspended.sql +41 -0
  73. package/dist/routes/(auth)/signup/page.cc.d.ts +3 -1
  74. package/dist/routes/(auth)/signup/page.cc.d.ts.map +1 -1
  75. package/dist/routes/(auth)/signup/page.cc.js +2 -2
  76. package/dist/routes/(auth)/signup/page.d.ts +3 -1
  77. package/dist/routes/(auth)/signup/page.d.ts.map +1 -1
  78. package/dist/routes/(auth)/signup/page.js +4 -3
  79. package/dist/routes/_internal/area-access.js +2 -2
  80. package/dist/routes/api/devtools/config/entities/route.js +2 -2
  81. package/dist/routes/api/devtools/config/theme/route.js +2 -2
  82. package/dist/routes/api/devtools/tests/[...path]/route.js +2 -2
  83. package/dist/routes/api/devtools/tests/route.js +2 -2
  84. package/dist/routes/api/superadmin/subscriptions/route.js +2 -2
  85. package/dist/routes/api/superadmin/teams/[teamId]/route.js +2 -2
  86. package/dist/routes/api/superadmin/teams/route.js +2 -2
  87. package/dist/routes/api/superadmin/users/[userId]/route.d.ts +5 -3
  88. package/dist/routes/api/superadmin/users/[userId]/route.d.ts.map +1 -1
  89. package/dist/routes/api/superadmin/users/[userId]/route.js +46 -23
  90. package/dist/routes/api/superadmin/users/route.js +2 -2
  91. package/dist/routes/api/user/delete-account/route.d.ts.map +1 -1
  92. package/dist/routes/api/user/delete-account/route.js +2 -3
  93. package/dist/routes/api/user/plan-flags/route.d.ts.map +1 -1
  94. package/dist/routes/api/user/plan-flags/route.js +5 -5
  95. package/dist/routes/api/user/profile/route.js +3 -3
  96. package/dist/routes/api/v1/auth/signup-with-invite/route.d.ts.map +1 -1
  97. package/dist/routes/api/v1/auth/signup-with-invite/route.js +80 -44
  98. package/dist/routes/api/v1/post-categories/[id]/route.d.ts.map +1 -1
  99. package/dist/routes/api/v1/post-categories/[id]/route.js +39 -34
  100. package/dist/routes/api/v1/post-categories/route.d.ts.map +1 -1
  101. package/dist/routes/api/v1/post-categories/route.js +18 -14
  102. package/dist/routes/api/v1/team-invitations/route.d.ts.map +1 -1
  103. package/dist/routes/api/v1/team-invitations/route.js +12 -5
  104. package/dist/routes/superadmin/users/page.js +2 -2
  105. package/dist/templates/next.config.mjs +11 -31
  106. package/dist/templates/projects/blog/package.json +1 -1
  107. package/dist/templates/projects/crm/package.json +1 -1
  108. package/dist/templates/projects/productivity/package.json +1 -1
  109. package/dist/templates/projects/starter/config/app.config.ts +8 -0
  110. package/dist/templates/proxy.ts +6 -3
  111. package/migrations/030_taxonomies_team_writes.sql +29 -0
  112. package/migrations/031_users_role_suspended.sql +41 -0
  113. package/package.json +3 -3
  114. package/scripts/build/registry/__tests__/build-output.test.mjs +1 -1
  115. package/scripts/build/registry/__tests__/project-mode-root-first.test.mjs +6 -6
  116. package/scripts/build/registry/__tests__/write-places.test.mjs +1 -1
  117. package/scripts/build/registry/contracts/__tests__/contracts-wire.test.mjs +1 -1
  118. package/scripts/build/registry/contracts/__tests__/contracts.test.mjs +1 -1
  119. package/scripts/build/registry/host/README.md +2 -2
  120. package/scripts/build/registry/host/__tests__/facade-emitter.test.mjs +14 -13
  121. package/scripts/build/registry/host/__tests__/host-mode.test.mjs +1 -1
  122. package/scripts/build/registry/host/__tests__/host-project-composition.test.mjs +1 -1
  123. package/scripts/build/registry/host/__tests__/host-project.test.mjs +2 -2
  124. package/scripts/build/registry/host/__tests__/host-proxy-areas.test.mjs +29 -2
  125. package/scripts/build/registry/host/__tests__/host-robustness.test.mjs +1 -1
  126. package/scripts/build/registry/host/facade-emitter.mjs +1 -1
  127. package/scripts/build/registry/host/next-route-exports.json +2 -2
  128. package/scripts/build/registry/host/proxy-areas.mjs +29 -2
  129. package/scripts/db/verify-theme-migrations.mjs +1 -1
  130. package/templates/next.config.mjs +11 -31
  131. package/templates/projects/blog/package.json +1 -1
  132. package/templates/projects/crm/package.json +1 -1
  133. package/templates/projects/productivity/package.json +1 -1
  134. package/templates/projects/starter/config/app.config.ts +8 -0
  135. package/templates/proxy.ts +6 -3
  136. package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +5 -4
@@ -2,7 +2,7 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { Suspense } from "react";
3
3
  import { headers } from "next/headers";
4
4
  import { redirect } from "next/navigation";
5
- import { getRequestSession } from "@nextsparkjs/core/lib/auth/request-session";
5
+ import { getAuthorizationRequestSession } from "@nextsparkjs/core/lib/auth/request-session";
6
6
  const AREA_ROLES = {
7
7
  superadmin: ["superadmin", "developer"],
8
8
  devtools: ["developer"]
@@ -16,7 +16,7 @@ export function loginPathFor(area, pathname) {
16
16
  return `/login?callbackUrl=${encodeURIComponent(back)}`;
17
17
  }
18
18
  async function requestSession() {
19
- return { session: await getRequestSession(), pathname: (await headers()).get("x-pathname") };
19
+ return { session: await getAuthorizationRequestSession(), pathname: (await headers()).get("x-pathname") };
20
20
  }
21
21
  export async function requireAreaAccess(area) {
22
22
  var _a;
@@ -1,4 +1,4 @@
1
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
1
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
2
2
  import { NextResponse } from "next/server";
3
3
  import { getEntityRegistry } from "@nextsparkjs/core/lib/entities/queries";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
@@ -9,7 +9,7 @@ function isEntityConfig(entity) {
9
9
  export const GET = withRateLimitTier(async (request) => {
10
10
  var _a, _b;
11
11
  try {
12
- const session = await getTypedSession(request.headers);
12
+ const session = await getAuthorizationSession(request.headers);
13
13
  if (!(session == null ? void 0 : session.user) || session.user.role !== "developer") {
14
14
  return NextResponse.json(
15
15
  {
@@ -1,11 +1,11 @@
1
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
1
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
2
2
  import { NextResponse } from "next/server";
3
3
  import { ThemeService } from "@nextsparkjs/core/lib/services/theme.service";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
6
6
  export const GET = withRateLimitTier(async (request) => {
7
7
  try {
8
- const session = await getTypedSession(request.headers);
8
+ const session = await getAuthorizationSession(request.headers);
9
9
  if (!(session == null ? void 0 : session.user) || session.user.role !== "developer") {
10
10
  return NextResponse.json(
11
11
  {
@@ -1,4 +1,4 @@
1
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
1
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
2
2
  import { NextResponse } from "next/server";
3
3
  import { readFile, stat } from "fs/promises";
4
4
  import { join } from "path";
@@ -7,7 +7,7 @@ import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
7
7
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
8
8
  export const GET = withRateLimitTier(async (request, { params }) => {
9
9
  try {
10
- const session = await getTypedSession(request.headers);
10
+ const session = await getAuthorizationSession(request.headers);
11
11
  if (!(session == null ? void 0 : session.user) || session.user.role !== "developer") {
12
12
  return NextResponse.json(
13
13
  {
@@ -1,4 +1,4 @@
1
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
1
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
2
2
  import { NextResponse } from "next/server";
3
3
  import { readdir, stat } from "fs/promises";
4
4
  import { join } from "path";
@@ -35,7 +35,7 @@ async function buildFileTree(dirPath, basePath) {
35
35
  }
36
36
  export const GET = withRateLimitTier(async (request) => {
37
37
  try {
38
- const session = await getTypedSession(request.headers);
38
+ const session = await getAuthorizationSession(request.headers);
39
39
  if (!(session == null ? void 0 : session.user) || session.user.role !== "developer") {
40
40
  return NextResponse.json(
41
41
  {
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
@@ -7,7 +7,7 @@ import { getBillingGateway } from "@nextsparkjs/core/lib/billing/gateways/factor
7
7
  export const GET = withRateLimitTier(async (request) => {
8
8
  var _a;
9
9
  try {
10
- const session = await getTypedSession(request.headers);
10
+ const session = await getAuthorizationSession(request.headers);
11
11
  if (!(session == null ? void 0 : session.user)) {
12
12
  return NextResponse.json(
13
13
  { error: "Unauthorized - No session found" },
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
@@ -8,7 +8,7 @@ export const GET = withRateLimitTier(async (request, { params }) => {
8
8
  var _a;
9
9
  try {
10
10
  const { teamId } = await params;
11
- const session = await getTypedSession(request.headers);
11
+ const session = await getAuthorizationSession(request.headers);
12
12
  if (!(session == null ? void 0 : session.user)) {
13
13
  return NextResponse.json(
14
14
  { error: "Unauthorized - No session found" },
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { SYSTEM_ADMIN_TEAM_ID } from "@nextsparkjs/core/lib/api/auth/dual-auth";
5
5
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
@@ -7,7 +7,7 @@ import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
7
7
  export const GET = withRateLimitTier(async (request) => {
8
8
  var _a, _b, _c, _d;
9
9
  try {
10
- const session = await getTypedSession(request.headers);
10
+ const session = await getAuthorizationSession(request.headers);
11
11
  if (!(session == null ? void 0 : session.user)) {
12
12
  return NextResponse.json(
13
13
  { error: "Unauthorized - No session found" },
@@ -24,10 +24,12 @@ export declare const GET: (request: NextRequest, args_0: RouteParams) => Promise
24
24
  * Only accessible by superadmin or developer users.
25
25
  *
26
26
  * Actions:
27
- * - change-role: Change user's role (requires 'role' field)
28
- * - suspend: Suspend the user (sets role to 'suspended')
29
- * - unsuspend: Restore user's role to 'member'
27
+ * - change-role: Change user's role (requires 'role' field: member, or developer when a superadmin asks)
28
+ * - suspend: Suspend the user (role 'suspended'), sign out all their sessions and deactivate their API keys
29
+ * - unsuspend: Give a suspended user back the 'member' role (their API keys stay deactivated)
30
30
  * - verify-email: Manually verify user's email
31
+ *
32
+ * Nobody can act on their own account or on a superadmin, so the last superadmin is never suspended.
31
33
  */
32
34
  export declare const PATCH: (request: NextRequest, args_0: RouteParams) => Promise<NextResponse>;
33
35
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/superadmin/users/[userId]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AA+BxE,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG,sEA6KJ,CAAC;AAOb;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,sEA+JN,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,sEAgIP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/superadmin/users/[userId]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AA+BxE,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG,sEA6KJ,CAAC;AAOb;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,KAAK,sEAuLN,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,sEAgIP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
@@ -1,11 +1,12 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
+ import { suspendUser, unsuspendUser } from "@nextsparkjs/core/lib/auth/suspension";
3
4
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
5
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
6
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
6
7
  export const GET = withRateLimitTier(async (request, { params }) => {
7
8
  try {
8
- const session = await getTypedSession(request.headers);
9
+ const session = await getAuthorizationSession(request.headers);
9
10
  if (!(session == null ? void 0 : session.user)) {
10
11
  return NextResponse.json(
11
12
  { error: "Unauthorized - No session found" },
@@ -137,7 +138,7 @@ export const GET = withRateLimitTier(async (request, { params }) => {
137
138
  }, "strict");
138
139
  export const PATCH = withRateLimitTier(async (request, { params }) => {
139
140
  try {
140
- const session = await getTypedSession(request.headers);
141
+ const session = await getAuthorizationSession(request.headers);
141
142
  if (!(session == null ? void 0 : session.user)) {
142
143
  return NextResponse.json(
143
144
  { error: "Unauthorized - No session found" },
@@ -192,12 +193,24 @@ export const PATCH = withRateLimitTier(async (request, { params }) => {
192
193
  let updateParams = [];
193
194
  switch (action) {
194
195
  case "change-role":
195
- if (!role || !["member", "colaborator", "admin"].includes(role)) {
196
+ if (!role || !["member", "developer"].includes(role)) {
196
197
  return NextResponse.json(
197
- { error: "Invalid role. Must be one of: member, colaborator, admin" },
198
+ { error: "Invalid role. Must be one of: member, developer" },
198
199
  { status: 400 }
199
200
  );
200
201
  }
202
+ if (targetUser.role === "suspended") {
203
+ return NextResponse.json(
204
+ { error: "User is suspended. Use the unsuspend action to restore access, then change the role" },
205
+ { status: 400 }
206
+ );
207
+ }
208
+ if (role === "developer" && session.user.role !== "superadmin") {
209
+ return NextResponse.json(
210
+ { error: "Forbidden - Only a superadmin can grant the developer role" },
211
+ { status: 403 }
212
+ );
213
+ }
201
214
  updateQuery = `
202
215
  UPDATE "users"
203
216
  SET role = $1, "updatedAt" = NOW()
@@ -206,24 +219,34 @@ export const PATCH = withRateLimitTier(async (request, { params }) => {
206
219
  `;
207
220
  updateParams = [role, userId];
208
221
  break;
209
- case "suspend":
210
- updateQuery = `
211
- UPDATE "users"
212
- SET role = 'suspended', "updatedAt" = NOW()
213
- WHERE id = $1
214
- RETURNING id, role
215
- `;
216
- updateParams = [userId];
217
- break;
222
+ case "suspend": {
223
+ const suspended = await suspendUser(userId, session.user.id);
224
+ if (!suspended) {
225
+ return NextResponse.json({ error: "Failed to update user" }, { status: 500 });
226
+ }
227
+ return NextResponse.json({
228
+ success: true,
229
+ action,
230
+ userId,
231
+ message: `User ${action} successful`,
232
+ revoked: suspended,
233
+ metadata: { performedBy: session.user.id, performedAt: (/* @__PURE__ */ new Date()).toISOString(), source: "superadmin-api" }
234
+ });
235
+ }
218
236
  case "unsuspend":
219
- updateQuery = `
220
- UPDATE "users"
221
- SET role = 'member', "updatedAt" = NOW()
222
- WHERE id = $1
223
- RETURNING id, role
224
- `;
225
- updateParams = [userId];
226
- break;
237
+ if (targetUser.role !== "suspended") {
238
+ return NextResponse.json({ error: "User is not suspended" }, { status: 400 });
239
+ }
240
+ if (!await unsuspendUser(userId, session.user.id)) {
241
+ return NextResponse.json({ error: "Failed to update user" }, { status: 500 });
242
+ }
243
+ return NextResponse.json({
244
+ success: true,
245
+ action,
246
+ userId,
247
+ message: `User ${action} successful`,
248
+ metadata: { performedBy: session.user.id, performedAt: (/* @__PURE__ */ new Date()).toISOString(), source: "superadmin-api" }
249
+ });
227
250
  case "verify-email":
228
251
  updateQuery = `
229
252
  UPDATE "users"
@@ -265,7 +288,7 @@ export const PATCH = withRateLimitTier(async (request, { params }) => {
265
288
  }, "strict");
266
289
  export const DELETE = withRateLimitTier(async (request, { params }) => {
267
290
  try {
268
- const session = await getTypedSession(request.headers);
291
+ const session = await getAuthorizationSession(request.headers);
269
292
  if (!(session == null ? void 0 : session.user)) {
270
293
  return NextResponse.json(
271
294
  { error: "Unauthorized - No session found" },
@@ -1,12 +1,12 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
6
6
  export const GET = withRateLimitTier(async (request) => {
7
7
  var _a, _b, _c;
8
8
  try {
9
- const session = await getTypedSession(request.headers);
9
+ const session = await getAuthorizationSession(request.headers);
10
10
  if (!(session == null ? void 0 : session.user)) {
11
11
  return NextResponse.json(
12
12
  { error: "Unauthorized - No session found" },
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/delete-account/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,eAAO,MAAM,MAAM,iDAoDP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/delete-account/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,eAAO,MAAM,MAAM,iDAkDP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
@@ -1,13 +1,12 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { auth } from "@nextsparkjs/core/lib/auth";
3
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
4
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
5
6
  import { UserService } from "@nextsparkjs/core/lib/services";
6
7
  export const DELETE = withRateLimitTier(async (req) => {
7
8
  try {
8
- const session = await auth.api.getSession({
9
- headers: req.headers
10
- });
9
+ const session = await getAuthorizationSession(req.headers);
11
10
  if (!(session == null ? void 0 : session.user)) {
12
11
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
13
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/plan-flags/route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAMvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAavE;;;GAGG;AACH,eAAO,MAAM,GAAG,iDAwDN,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,KAAK,iDAgFP,CAAC;AAEZ;;;GAGG;AACH,eAAO,MAAM,IAAI,iDA4FL,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/plan-flags/route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAMvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAavE;;;GAGG;AACH,eAAO,MAAM,GAAG,iDAyDN,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,KAAK,iDAgFP,CAAC;AAEZ;;;GAGG;AACH,eAAO,MAAM,IAAI,iDA4FL,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { getUserPlanAndFlags, updateUserPlan, updateUserFlags } from "@nextsparkjs/core/lib/user-data";
4
4
  import * as z from "zod";
5
5
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
@@ -14,7 +14,7 @@ const planFlagsUpdateSchema = z.object({
14
14
  });
15
15
  export const GET = withRateLimitTier(async (request) => {
16
16
  try {
17
- const session = await getTypedSession(request.headers);
17
+ const session = await getAuthorizationSession(request.headers);
18
18
  if (!session) {
19
19
  return NextResponse.json(
20
20
  { error: "Authentication required" },
@@ -23,7 +23,7 @@ export const GET = withRateLimitTier(async (request) => {
23
23
  }
24
24
  const { searchParams } = new URL(request.url);
25
25
  const validation = planFlagsQuerySchema.safeParse({
26
- userId: searchParams.get("userId")
26
+ userId: searchParams.get("userId") ?? void 0
27
27
  });
28
28
  if (!validation.success) {
29
29
  return NextResponse.json(
@@ -60,7 +60,7 @@ export const GET = withRateLimitTier(async (request) => {
60
60
  }, "read");
61
61
  export const PATCH = withRateLimitTier(async (request) => {
62
62
  try {
63
- const session = await getTypedSession(request.headers);
63
+ const session = await getAuthorizationSession(request.headers);
64
64
  if (!session) {
65
65
  return NextResponse.json(
66
66
  { error: "Authentication required" },
@@ -125,7 +125,7 @@ export const PATCH = withRateLimitTier(async (request) => {
125
125
  }, "write");
126
126
  export const POST = withRateLimitTier(async (request) => {
127
127
  try {
128
- const session = await getTypedSession(request.headers);
128
+ const session = await getAuthorizationSession(request.headers);
129
129
  if (!session) {
130
130
  return NextResponse.json(
131
131
  { error: "Authentication required" },
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { auth } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryOneWithRLS, mutateWithRLS, queryOne } from "@nextsparkjs/core/lib/db";
4
4
  import { profileSchema } from "@nextsparkjs/core/lib/validation";
5
5
  import { MetaService, MetaValueTooLargeError } from "@nextsparkjs/core/lib/services/meta.service";
@@ -10,7 +10,7 @@ export const GET = withRateLimitTier(async (request) => {
10
10
  const includeMeta = url.searchParams.get("includeMeta") === "true";
11
11
  try {
12
12
  const sessionHeaders = request.headers;
13
- const session = await auth.api.getSession({ headers: sessionHeaders });
13
+ const session = await getAuthorizationSession(sessionHeaders);
14
14
  if (!(session == null ? void 0 : session.user)) {
15
15
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
16
16
  }
@@ -44,7 +44,7 @@ export const GET = withRateLimitTier(async (request) => {
44
44
  export const PATCH = withRateLimitTier(async (request) => {
45
45
  try {
46
46
  const sessionHeaders = request.headers;
47
- const session = await auth.api.getSession({ headers: sessionHeaders });
47
+ const session = await getAuthorizationSession(sessionHeaders);
48
48
  if (!(session == null ? void 0 : session.user)) {
49
49
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
50
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/auth/signup-with-invite/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAkBvD,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,kCAEjD;AAWD,eAAO,MAAM,IAAI,iDA8NP,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/auth/signup-with-invite/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAkBvD,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,kCAEjD;AAYD,eAAO,MAAM,IAAI,iDAsQP,CAAA"}
@@ -19,20 +19,12 @@ export const POST = withRateLimitTier(withApiLogging(
19
19
  async (req) => {
20
20
  var _a, _b;
21
21
  try {
22
- if (!isPasswordLoginEnabled(AUTH_CONFIG)) {
23
- const response = createApiError(
24
- "Password authentication is unavailable",
25
- 503,
26
- null,
27
- "AUTH_METHOD_UNAVAILABLE"
28
- );
29
- return addCorsHeaders(response, req);
30
- }
22
+ const passwordLogin = isPasswordLoginEnabled(AUTH_CONFIG);
31
23
  const body = await req.json();
32
24
  const { email, password, firstName, lastName, inviteToken } = body;
33
- if (!email || !password || !inviteToken) {
25
+ if (!email || passwordLogin && !password || !inviteToken) {
34
26
  const response = createApiError(
35
- "Email, password, and invitation token are required",
27
+ passwordLogin ? "Email, password, and invitation token are required" : "Email and invitation token are required",
36
28
  400,
37
29
  null,
38
30
  "MISSING_FIELDS"
@@ -44,7 +36,7 @@ export const POST = withRateLimitTier(withApiLogging(
44
36
  const response = createApiError("Invalid email format", 400, null, "INVALID_EMAIL");
45
37
  return addCorsHeaders(response, req);
46
38
  }
47
- if (password.length < 8) {
39
+ if (passwordLogin && password.length < 8) {
48
40
  const response = createApiError(
49
41
  "Password must be at least 8 characters",
50
42
  400,
@@ -86,45 +78,89 @@ export const POST = withRateLimitTier(withApiLogging(
86
78
  const response = createApiError("Invitation has expired", 410, null, "INVITATION_EXPIRED");
87
79
  return addCorsHeaders(response, req);
88
80
  }
89
- const signUpRequest = new Request(`${process.env.NEXT_PUBLIC_APP_URL}${withBasePath("/api/auth/sign-up/email")}`, {
90
- method: "POST",
91
- headers: {
92
- "Content-Type": "application/json"
93
- },
94
- body: JSON.stringify({
95
- email,
96
- password,
97
- name: firstName && lastName ? `${firstName} ${lastName}` : firstName || "",
98
- firstName,
99
- lastName,
100
- language: I18N_CONFIG.defaultLocale
101
- })
102
- });
103
- const signUpResponse = await withSignupContext(
104
- { skipTeamCreation: true, invitedTeamId: invitation.teamId },
105
- () => auth.handler(signUpRequest)
106
- );
107
- if (!signUpResponse.ok) {
108
- const errorData = await signUpResponse.json();
109
- if (((_a = errorData.message) == null ? void 0 : _a.includes("already exists")) || errorData.code === "USER_ALREADY_EXISTS") {
110
- const response2 = createApiError(
81
+ let userId;
82
+ const signupContext = { skipTeamCreation: true, invitedTeamId: invitation.teamId };
83
+ const name = firstName && lastName ? `${firstName} ${lastName}` : firstName || "";
84
+ if (passwordLogin) {
85
+ const signUpRequest = new Request(`${process.env.NEXT_PUBLIC_APP_URL}${withBasePath("/api/auth/sign-up/email")}`, {
86
+ method: "POST",
87
+ headers: {
88
+ "Content-Type": "application/json"
89
+ },
90
+ body: JSON.stringify({
91
+ email,
92
+ password,
93
+ name,
94
+ firstName,
95
+ lastName,
96
+ language: I18N_CONFIG.defaultLocale
97
+ })
98
+ });
99
+ const signUpResponse = await withSignupContext(signupContext, () => auth.handler(signUpRequest));
100
+ if (!signUpResponse.ok) {
101
+ const errorData = await signUpResponse.json();
102
+ if (((_a = errorData.message) == null ? void 0 : _a.includes("already exists")) || errorData.code === "USER_ALREADY_EXISTS") {
103
+ const response2 = createApiError(
104
+ "An account with this email already exists. Please sign in instead.",
105
+ 409,
106
+ null,
107
+ "USER_ALREADY_EXISTS"
108
+ );
109
+ return addCorsHeaders(response2, req);
110
+ }
111
+ const response = createApiError(
112
+ errorData.message || "Failed to create account",
113
+ signUpResponse.status,
114
+ null,
115
+ "SIGNUP_FAILED"
116
+ );
117
+ return addCorsHeaders(response, req);
118
+ }
119
+ const signUpData = await signUpResponse.json();
120
+ userId = (_b = signUpData.user) == null ? void 0 : _b.id;
121
+ } else {
122
+ const { internalAdapter } = await auth.$context;
123
+ if (await internalAdapter.findUserByEmail(email.toLowerCase())) {
124
+ const response = createApiError(
111
125
  "An account with this email already exists. Please sign in instead.",
112
126
  409,
113
127
  null,
114
128
  "USER_ALREADY_EXISTS"
115
129
  );
116
- return addCorsHeaders(response2, req);
130
+ return addCorsHeaders(response, req);
117
131
  }
118
- const response = createApiError(
119
- errorData.message || "Failed to create account",
120
- signUpResponse.status,
121
- null,
122
- "SIGNUP_FAILED"
123
- );
124
- return addCorsHeaders(response, req);
132
+ let user;
133
+ try {
134
+ user = await withSignupContext(signupContext, () => internalAdapter.createUser({
135
+ email: email.toLowerCase(),
136
+ emailVerified: true,
137
+ name,
138
+ firstName,
139
+ lastName,
140
+ language: I18N_CONFIG.defaultLocale
141
+ }));
142
+ } catch (error) {
143
+ const message = error instanceof Error ? error.message : "";
144
+ const refused = /^(DOMAIN_NOT_ALLOWED|SIGNUP_RESTRICTED): (.*)$/s.exec(message);
145
+ if (refused) {
146
+ return addCorsHeaders(createApiError(refused[2], 403, null, refused[1]), req);
147
+ }
148
+ if (error.code === "23505" || /duplicate key/i.test(message)) {
149
+ const response = createApiError(
150
+ "An account with this email already exists. Please sign in instead.",
151
+ 409,
152
+ null,
153
+ "USER_ALREADY_EXISTS"
154
+ );
155
+ return addCorsHeaders(response, req);
156
+ }
157
+ throw error;
158
+ }
159
+ if (!user) {
160
+ return addCorsHeaders(createApiError("Account creation was refused", 403, null, "SIGNUP_FAILED"), req);
161
+ }
162
+ userId = user.id;
125
163
  }
126
- const signUpData = await signUpResponse.json();
127
- const userId = (_b = signUpData.user) == null ? void 0 : _b.id;
128
164
  if (!userId) {
129
165
  const response = createApiError(
130
166
  "Failed to create account - no user ID returned",
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/post-categories/[id]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAKvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAevE,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAyBrC,CAAC;AAGX,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAwIpC,CAAC;AAGZ,eAAO,MAAM,MAAM;YAEK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAiEpC,CAAC;AAEZ,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/post-categories/[id]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAKvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAiCvE,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BA2BrC,CAAC;AAIX,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BA+HpC,CAAC;AAIZ,eAAO,MAAM,MAAM;YAEK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAuDpC,CAAC;AAEZ,eAAO,MAAM,OAAO,sBAAgB,CAAA"}