nuxt-auto-crud 1.19.1 → 1.20.0

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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-auto-crud",
3
3
  "configKey": "autoCrud",
4
- "version": "1.19.1",
4
+ "version": "1.20.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -5,7 +5,7 @@ import { db } from "hub:db";
5
5
  import { ensureResourceAccess, formatResourceResult } from "../../utils/handler.js";
6
6
  export default eventHandler(async (event) => {
7
7
  const { model, id } = getRouterParams(event);
8
- const isAdmin = await ensureResourceAccess(event, model, "delete");
8
+ const isAdmin = await ensureResourceAccess(event, model, "delete", { id });
9
9
  const table = getTableForModel(model);
10
10
  const singularName = getModelSingularName(model);
11
11
  const deletedRecord = await db.delete(table).where(eq(table.id, Number(id))).returning().get();
@@ -1,4 +1,5 @@
1
1
  import { eventHandler, getRouterParams, readBody, createError } from "h3";
2
+ import { getUserSession } from "#imports";
2
3
  import { eq } from "drizzle-orm";
3
4
  import { getTableForModel, filterUpdatableFields } from "../../utils/modelMapper.js";
4
5
  import { db } from "hub:db";
@@ -13,6 +14,15 @@ export default eventHandler(async (event) => {
13
14
  if ("updatedAt" in table) {
14
15
  payload.updatedAt = /* @__PURE__ */ new Date();
15
16
  }
17
+ try {
18
+ const session = await getUserSession(event);
19
+ if (session?.user?.id) {
20
+ if ("updatedBy" in table) {
21
+ payload.updatedBy = session.user.id;
22
+ }
23
+ }
24
+ } catch {
25
+ }
16
26
  const updatedRecord = await db.update(table).set(payload).where(eq(table.id, Number(id))).returning().get();
17
27
  if (!updatedRecord) {
18
28
  throw createError({
@@ -1,4 +1,5 @@
1
1
  import { eventHandler, getRouterParams, readBody } from "h3";
2
+ import { getUserSession } from "#imports";
2
3
  import { getTableForModel, filterUpdatableFields } from "../../utils/modelMapper.js";
3
4
  import { db } from "hub:db";
4
5
  import { ensureResourceAccess, formatResourceResult, hashPayloadFields } from "../../utils/handler.js";
@@ -9,6 +10,18 @@ export default eventHandler(async (event) => {
9
10
  const body = await readBody(event);
10
11
  const payload = filterUpdatableFields(model, body);
11
12
  await hashPayloadFields(payload);
13
+ try {
14
+ const session = await getUserSession(event);
15
+ if (session?.user?.id) {
16
+ if ("createdBy" in table) {
17
+ payload.createdBy = session.user.id;
18
+ }
19
+ if ("updatedBy" in table) {
20
+ payload.updatedBy = session.user.id;
21
+ }
22
+ }
23
+ } catch {
24
+ }
12
25
  const newRecord = await db.insert(table).values(payload).returning().get();
13
26
  return formatResourceResult(model, newRecord, isAdmin);
14
27
  });
@@ -37,10 +37,18 @@ export async function checkAdminAccess(event, model, action, context) {
37
37
  if (model === "users" && String(context.id) === String(user.id)) {
38
38
  return true;
39
39
  }
40
- if ("userId" in table) {
41
- const record = await db.select({ userId: table.userId }).from(table).where(eq(table.id, context.id)).get();
42
- if (record && String(record.userId) === String(user.id)) {
43
- return true;
40
+ const hasCreatedBy = "createdBy" in table;
41
+ const hasUserId = "userId" in table;
42
+ if (hasCreatedBy || hasUserId) {
43
+ const query = db.select().from(table).where(eq(table.id, Number(context.id)));
44
+ const record = await query.get();
45
+ if (record) {
46
+ if (hasCreatedBy) {
47
+ if (String(record.createdBy) === String(user.id)) return true;
48
+ }
49
+ if (hasUserId) {
50
+ if (String(record.userId) === String(user.id)) return true;
51
+ }
44
52
  }
45
53
  }
46
54
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auto-crud",
3
- "version": "1.19.1",
3
+ "version": "1.20.0",
4
4
  "description": "Exposes RESTful CRUD APIs for your Nuxt app based solely on your database migrations.",
5
5
  "author": "Cliford Pereira",
6
6
  "license": "MIT",
@@ -9,7 +9,7 @@ import { ensureResourceAccess, formatResourceResult } from '../../utils/handler'
9
9
 
10
10
  export default eventHandler(async (event) => {
11
11
  const { model, id } = getRouterParams(event) as { model: string, id: string }
12
- const isAdmin = await ensureResourceAccess(event, model, 'delete')
12
+ const isAdmin = await ensureResourceAccess(event, model, 'delete', { id })
13
13
 
14
14
  const table = getTableForModel(model) as TableWithId
15
15
  const singularName = getModelSingularName(model)
@@ -1,5 +1,7 @@
1
1
  // server/api/[model]/[id].patch.ts
2
2
  import { eventHandler, getRouterParams, readBody, createError } from 'h3'
3
+ import type { H3Event } from 'h3'
4
+ import { getUserSession } from '#imports'
3
5
  import { eq } from 'drizzle-orm'
4
6
  import { getTableForModel, filterUpdatableFields } from '../../utils/modelMapper'
5
7
  import type { TableWithId } from '../../types'
@@ -28,6 +30,20 @@ export default eventHandler(async (event) => {
28
30
  (payload as any).updatedAt = new Date()
29
31
  }
30
32
 
33
+ // Inject updatedBy if user is authenticated
34
+ try {
35
+ const session = await (getUserSession as (event: H3Event) => Promise<{ user: { id: string | number } | null }>)(event)
36
+ if (session?.user?.id) {
37
+ if ('updatedBy' in table) {
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ (payload as any).updatedBy = session.user.id
40
+ }
41
+ }
42
+ }
43
+ catch {
44
+ // No session available
45
+ }
46
+
31
47
  const updatedRecord = await db
32
48
  .update(table)
33
49
  .set(payload)
@@ -1,5 +1,7 @@
1
1
  // server/api/[model]/index.post.ts
2
2
  import { eventHandler, getRouterParams, readBody } from 'h3'
3
+ import type { H3Event } from 'h3'
4
+ import { getUserSession } from '#imports'
3
5
  import { getTableForModel, filterUpdatableFields } from '../../utils/modelMapper'
4
6
  // @ts-expect-error - hub:db is a virtual alias
5
7
  import { db } from 'hub:db'
@@ -17,6 +19,27 @@ export default eventHandler(async (event) => {
17
19
  // Auto-hash fields based on config (default: ['password'])
18
20
  await hashPayloadFields(payload)
19
21
 
22
+ // Inject createdBy/updatedBy if user is authenticated
23
+ try {
24
+ const session = await (getUserSession as (event: H3Event) => Promise<{ user: { id: string | number } | null }>)(event)
25
+ if (session?.user?.id) {
26
+ // Check if table has columns before assigning (optional but safer if we had strict types)
27
+ // Since we are passing payload to .values(), extra keys might be ignored or cause error depending on driver
28
+ // Using 'in' table check is good practice
29
+ if ('createdBy' in table) {
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ (payload as any).createdBy = session.user.id
32
+ }
33
+ if ('updatedBy' in table) {
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ (payload as any).updatedBy = session.user.id
36
+ }
37
+ }
38
+ }
39
+ catch {
40
+ // No session available
41
+ }
42
+
20
43
  const newRecord = await db.insert(table).values(payload).returning().get()
21
44
 
22
45
  return formatResourceResult(model, newRecord as Record<string, unknown>, isAdmin)
@@ -62,16 +62,27 @@ export async function checkAdminAccess(event: H3Event, model: string, action: st
62
62
  return true
63
63
  }
64
64
 
65
- // Standard case: Check 'userId' column for ownership
66
- // We need to check if table has userId column.
67
- // We cast to any to check property exist roughly or just try query
68
- if ('userId' in table) {
69
- // @ts-expect-error - dyanmic table access
70
- const record = await db.select({ userId: table.userId }).from(table).where(eq(table.id, context.id)).get()
71
-
72
- // If record exists and userId matches session user id
73
- if (record && String(record.userId) === String(user.id)) {
74
- return true
65
+ // Standard case: Check 'createdBy' or 'userId' column for ownership
66
+
67
+ // const columns = table.columns || {}
68
+
69
+ const hasCreatedBy = 'createdBy' in table
70
+ const hasUserId = 'userId' in table
71
+
72
+ if (hasCreatedBy || hasUserId) {
73
+ // @ts-expect-error - table is dynamic
74
+ const query = db.select().from(table).where(eq(table.id, Number(context.id)))
75
+ const record = await query.get()
76
+
77
+ if (record) {
78
+ // Check createdBy
79
+ if (hasCreatedBy) {
80
+ if (String(record.createdBy) === String(user.id)) return true
81
+ }
82
+ // Check userId (legacy)
83
+ if (hasUserId) {
84
+ if (String(record.userId) === String(user.id)) return true
85
+ }
75
86
  }
76
87
  }
77
88
  }