lapeh 1.0.12 → 2.0.1
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/.env.example +5 -6
- package/.vscode/settings.json +5 -0
- package/docker-compose.yml +8 -1
- package/package.json +4 -3
- package/prisma/migrations/20251226000329_create_pets_table/migration.sql +11 -0
- package/prisma/migrations/20251226001249_create_pets_table/migration.sql +82 -0
- package/prisma/migrations/20251226001717_restore_core_models/migration.sql +236 -0
- package/prisma/migrations/migration_lock.toml +3 -3
- package/prisma/schema.prisma +170 -155
- package/prisma/seed.ts +59 -0
- package/readme.md +38 -0
- package/scripts/compile-schema.js +2 -2
- package/scripts/init-project.js +16 -1
- package/scripts/make-controller.js +205 -0
- package/src/controllers/authController.ts +9 -9
- package/src/controllers/petController.ts +132 -0
- package/src/models/core.model +163 -0
- package/src/models/pets.model +9 -0
- package/src/prisma.ts +1 -1
- package/src/redis.ts +14 -6
- package/src/routes/pets.ts +12 -0
- package/src/schema/pet-schema.ts +14 -0
- package/src/server.ts +2 -0
- package/src/models/schema.prisma +0 -159
|
@@ -76,7 +76,7 @@ export async function login(req: Request, res: Response) {
|
|
|
76
76
|
include: {
|
|
77
77
|
user_roles: {
|
|
78
78
|
include: {
|
|
79
|
-
|
|
79
|
+
role: true,
|
|
80
80
|
},
|
|
81
81
|
},
|
|
82
82
|
},
|
|
@@ -102,8 +102,8 @@ export async function login(req: Request, res: Response) {
|
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
const primaryUserRole =
|
|
105
|
-
user.user_roles && user.user_roles.length > 0 && user.user_roles[0].
|
|
106
|
-
? user.user_roles[0].
|
|
105
|
+
user.user_roles && user.user_roles.length > 0 && user.user_roles[0].role
|
|
106
|
+
? user.user_roles[0].role.slug
|
|
107
107
|
: "user";
|
|
108
108
|
const accessExpiresInSeconds = ACCESS_TOKEN_EXPIRES_IN_SECONDS;
|
|
109
109
|
const accessExpiresAt = new Date(
|
|
@@ -145,7 +145,7 @@ export async function me(req: Request, res: Response) {
|
|
|
145
145
|
include: {
|
|
146
146
|
user_roles: {
|
|
147
147
|
include: {
|
|
148
|
-
|
|
148
|
+
role: true,
|
|
149
149
|
},
|
|
150
150
|
},
|
|
151
151
|
},
|
|
@@ -159,8 +159,8 @@ export async function me(req: Request, res: Response) {
|
|
|
159
159
|
...rest,
|
|
160
160
|
id: user.id.toString(),
|
|
161
161
|
role:
|
|
162
|
-
user.user_roles && user.user_roles.length > 0 && user.user_roles[0].
|
|
163
|
-
? user.user_roles[0].
|
|
162
|
+
user.user_roles && user.user_roles.length > 0 && user.user_roles[0].role
|
|
163
|
+
? user.user_roles[0].role.slug
|
|
164
164
|
: "user",
|
|
165
165
|
});
|
|
166
166
|
}
|
|
@@ -198,7 +198,7 @@ export async function refreshToken(req: Request, res: Response) {
|
|
|
198
198
|
include: {
|
|
199
199
|
user_roles: {
|
|
200
200
|
include: {
|
|
201
|
-
|
|
201
|
+
role: true,
|
|
202
202
|
},
|
|
203
203
|
},
|
|
204
204
|
},
|
|
@@ -208,8 +208,8 @@ export async function refreshToken(req: Request, res: Response) {
|
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
210
|
const primaryUserRole =
|
|
211
|
-
user.user_roles && user.user_roles.length > 0 && user.user_roles[0].
|
|
212
|
-
? user.user_roles[0].
|
|
211
|
+
user.user_roles && user.user_roles.length > 0 && user.user_roles[0].role
|
|
212
|
+
? user.user_roles[0].role.slug
|
|
213
213
|
: "user";
|
|
214
214
|
const accessExpiresInSeconds = ACCESS_TOKEN_EXPIRES_IN_SECONDS;
|
|
215
215
|
const accessExpiresAt = new Date(
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
|
|
2
|
+
import { Request, Response } from "express";
|
|
3
|
+
import { prisma } from "../prisma";
|
|
4
|
+
import { sendSuccess, sendError } from "../utils/response";
|
|
5
|
+
import { createPetSchema, updatePetSchema } from "../schema/pet-schema";
|
|
6
|
+
import { getPagination, buildPaginationMeta } from "../utils/pagination";
|
|
7
|
+
|
|
8
|
+
export async function index(req: Request, res: Response) {
|
|
9
|
+
const { page, perPage, skip, take } = getPagination(req.query);
|
|
10
|
+
const search = req.query.search as string;
|
|
11
|
+
|
|
12
|
+
const where: any = {};
|
|
13
|
+
if (search) {
|
|
14
|
+
where.OR = [
|
|
15
|
+
{ name: { contains: search, mode: "insensitive" } },
|
|
16
|
+
{ species: { contains: search, mode: "insensitive" } },
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const [data, total] = await Promise.all([
|
|
21
|
+
prisma.pets.findMany({
|
|
22
|
+
where,
|
|
23
|
+
skip,
|
|
24
|
+
take,
|
|
25
|
+
orderBy: { created_at: "desc" },
|
|
26
|
+
}),
|
|
27
|
+
prisma.pets.count({ where }),
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
const serialized = data.map((item: any) => ({
|
|
31
|
+
...item,
|
|
32
|
+
id: item.id.toString(),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
const meta = buildPaginationMeta(page, perPage, total);
|
|
36
|
+
|
|
37
|
+
sendSuccess(res, 200, "Pets retrieved successfully", {
|
|
38
|
+
data: serialized,
|
|
39
|
+
meta,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function show(req: Request, res: Response) {
|
|
44
|
+
const { id } = req.params;
|
|
45
|
+
const pet = await prisma.pets.findUnique({
|
|
46
|
+
where: { id: BigInt(id) },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!pet) {
|
|
50
|
+
sendError(res, 404, "Pet not found");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
sendSuccess(res, 200, "Pet retrieved successfully", {
|
|
55
|
+
...pet,
|
|
56
|
+
id: pet.id.toString(),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function store(req: Request, res: Response) {
|
|
61
|
+
const parsed = createPetSchema.safeParse(req.body);
|
|
62
|
+
if (!parsed.success) {
|
|
63
|
+
const errors = parsed.error.flatten().fieldErrors;
|
|
64
|
+
sendError(res, 422, "Validation error", errors);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const pet = await prisma.pets.create({
|
|
69
|
+
data: {
|
|
70
|
+
...parsed.data,
|
|
71
|
+
created_at: new Date(),
|
|
72
|
+
updated_at: new Date(),
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
sendSuccess(res, 201, "Pet created successfully", {
|
|
77
|
+
...pet,
|
|
78
|
+
id: pet.id.toString(),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function update(req: Request, res: Response) {
|
|
83
|
+
const { id } = req.params;
|
|
84
|
+
const parsed = updatePetSchema.safeParse(req.body);
|
|
85
|
+
|
|
86
|
+
if (!parsed.success) {
|
|
87
|
+
const errors = parsed.error.flatten().fieldErrors;
|
|
88
|
+
sendError(res, 422, "Validation error", errors);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const existing = await prisma.pets.findUnique({
|
|
93
|
+
where: { id: BigInt(id) },
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (!existing) {
|
|
97
|
+
sendError(res, 404, "Pet not found");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const updated = await prisma.pets.update({
|
|
102
|
+
where: { id: BigInt(id) },
|
|
103
|
+
data: {
|
|
104
|
+
...parsed.data,
|
|
105
|
+
updated_at: new Date(),
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
sendSuccess(res, 200, "Pet updated successfully", {
|
|
110
|
+
...updated,
|
|
111
|
+
id: updated.id.toString(),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function destroy(req: Request, res: Response) {
|
|
116
|
+
const { id } = req.params;
|
|
117
|
+
|
|
118
|
+
const existing = await prisma.pets.findUnique({
|
|
119
|
+
where: { id: BigInt(id) },
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (!existing) {
|
|
123
|
+
sendError(res, 404, "Pet not found");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
await prisma.pets.delete({
|
|
128
|
+
where: { id: BigInt(id) },
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
sendSuccess(res, 200, "Pet deleted successfully", null);
|
|
132
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
model cache {
|
|
2
|
+
key String @id @db.VarChar(255)
|
|
3
|
+
value String @db.Text
|
|
4
|
+
expiration Int
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
model cache_locks {
|
|
8
|
+
key String @id @db.VarChar(255)
|
|
9
|
+
owner String @db.VarChar(255)
|
|
10
|
+
expiration Int
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
model failed_jobs {
|
|
14
|
+
id BigInt @id @default(autoincrement())
|
|
15
|
+
uuid String @unique @db.VarChar(255)
|
|
16
|
+
connection String @db.Text
|
|
17
|
+
queue String @db.Text
|
|
18
|
+
payload String @db.Text
|
|
19
|
+
exception String @db.Text
|
|
20
|
+
failed_at DateTime @default(now()) @db.Timestamp(0)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
model job_batches {
|
|
24
|
+
id String @id @db.VarChar(255)
|
|
25
|
+
name String @db.VarChar(255)
|
|
26
|
+
total_jobs Int
|
|
27
|
+
pending_jobs Int
|
|
28
|
+
failed_jobs Int
|
|
29
|
+
failed_job_ids String @db.Text
|
|
30
|
+
options String? @db.Text
|
|
31
|
+
cancelled_at Int?
|
|
32
|
+
created_at Int
|
|
33
|
+
finished_at Int?
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
model jobs {
|
|
37
|
+
id BigInt @id @default(autoincrement())
|
|
38
|
+
queue String @db.VarChar(255)
|
|
39
|
+
payload String @db.Text
|
|
40
|
+
attempts Int @db.SmallInt
|
|
41
|
+
reserved_at Int?
|
|
42
|
+
available_at Int
|
|
43
|
+
created_at Int
|
|
44
|
+
|
|
45
|
+
@@index([queue])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
model migrations {
|
|
49
|
+
id Int @id @default(autoincrement())
|
|
50
|
+
migration String @db.VarChar(255)
|
|
51
|
+
batch Int
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
model password_reset_tokens {
|
|
55
|
+
email String @id @db.VarChar(255)
|
|
56
|
+
token String @db.VarChar(255)
|
|
57
|
+
created_at DateTime? @db.Timestamp(0)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
model personal_access_tokens {
|
|
61
|
+
id BigInt @id @default(autoincrement())
|
|
62
|
+
tokenable_type String @db.VarChar(255)
|
|
63
|
+
tokenable_id BigInt
|
|
64
|
+
name String @db.Text
|
|
65
|
+
token String @unique @db.VarChar(64)
|
|
66
|
+
abilities String? @db.Text
|
|
67
|
+
last_used_at DateTime? @db.Timestamp(0)
|
|
68
|
+
expires_at DateTime? @db.Timestamp(0)
|
|
69
|
+
created_at DateTime? @db.Timestamp(0)
|
|
70
|
+
updated_at DateTime? @db.Timestamp(0)
|
|
71
|
+
|
|
72
|
+
@@index([expires_at])
|
|
73
|
+
@@index([tokenable_type, tokenable_id])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
model sessions {
|
|
77
|
+
id String @id @db.VarChar(255)
|
|
78
|
+
user_id BigInt?
|
|
79
|
+
ip_address String? @db.VarChar(45)
|
|
80
|
+
user_agent String? @db.Text
|
|
81
|
+
payload String @db.Text
|
|
82
|
+
last_activity Int
|
|
83
|
+
|
|
84
|
+
@@index([last_activity])
|
|
85
|
+
@@index([user_id])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
model users {
|
|
89
|
+
id BigInt @id @default(autoincrement())
|
|
90
|
+
uuid String @unique @db.Uuid
|
|
91
|
+
name String @db.VarChar(255)
|
|
92
|
+
email String @unique @db.VarChar(255)
|
|
93
|
+
avatar String? @db.VarChar(255)
|
|
94
|
+
avatar_url String? @db.VarChar(255)
|
|
95
|
+
email_verified_at DateTime? @db.Timestamp(0)
|
|
96
|
+
password String @db.VarChar(255)
|
|
97
|
+
remember_token String? @db.VarChar(100)
|
|
98
|
+
created_at DateTime? @db.Timestamp(0)
|
|
99
|
+
updated_at DateTime? @db.Timestamp(0)
|
|
100
|
+
|
|
101
|
+
user_roles user_roles[]
|
|
102
|
+
user_permissions user_permissions[]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
model roles {
|
|
106
|
+
id BigInt @id @default(autoincrement())
|
|
107
|
+
name String @db.VarChar(255)
|
|
108
|
+
slug String @unique @db.VarChar(255)
|
|
109
|
+
description String? @db.Text
|
|
110
|
+
created_at DateTime? @db.Timestamp(0)
|
|
111
|
+
updated_at DateTime? @db.Timestamp(0)
|
|
112
|
+
|
|
113
|
+
user_roles user_roles[]
|
|
114
|
+
role_permissions role_permissions[]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
model permissions {
|
|
118
|
+
id BigInt @id @default(autoincrement())
|
|
119
|
+
name String @db.VarChar(255)
|
|
120
|
+
slug String @unique @db.VarChar(255)
|
|
121
|
+
description String? @db.Text
|
|
122
|
+
created_at DateTime? @db.Timestamp(0)
|
|
123
|
+
updated_at DateTime? @db.Timestamp(0)
|
|
124
|
+
|
|
125
|
+
role_permissions role_permissions[]
|
|
126
|
+
user_permissions user_permissions[]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
model user_roles {
|
|
130
|
+
id BigInt @id @default(autoincrement())
|
|
131
|
+
user_id BigInt
|
|
132
|
+
role_id BigInt
|
|
133
|
+
created_at DateTime? @db.Timestamp(0)
|
|
134
|
+
|
|
135
|
+
user users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
136
|
+
role roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
137
|
+
|
|
138
|
+
@@unique([user_id, role_id])
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
model role_permissions {
|
|
142
|
+
id BigInt @id @default(autoincrement())
|
|
143
|
+
role_id BigInt
|
|
144
|
+
permission_id BigInt
|
|
145
|
+
created_at DateTime? @db.Timestamp(0)
|
|
146
|
+
|
|
147
|
+
role roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
148
|
+
permission permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
149
|
+
|
|
150
|
+
@@unique([role_id, permission_id])
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
model user_permissions {
|
|
154
|
+
id BigInt @id @default(autoincrement())
|
|
155
|
+
user_id BigInt
|
|
156
|
+
permission_id BigInt
|
|
157
|
+
created_at DateTime? @db.Timestamp(0)
|
|
158
|
+
|
|
159
|
+
user users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
160
|
+
permission permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
161
|
+
|
|
162
|
+
@@unique([user_id, permission_id])
|
|
163
|
+
}
|
package/src/prisma.ts
CHANGED
package/src/redis.ts
CHANGED
|
@@ -38,12 +38,10 @@ redis.on("error", (err) => {
|
|
|
38
38
|
// Replace the global redis instance with mock
|
|
39
39
|
// Note: This is a runtime switch. Existing listeners might be lost if we don't handle carefully.
|
|
40
40
|
// However, for a simple fallback, we can just use the mock for future calls.
|
|
41
|
-
|
|
42
|
-
// Better approach: Since we exported 'redis' as a const (reference), we can't reassign it easily
|
|
41
|
+
// Better approach: Since we exported 'redis' as a const (reference), we can't reassign it easily
|
|
43
42
|
// if other modules already imported it.
|
|
44
43
|
// BUT, ioredis instance itself is an EventEmitter.
|
|
45
|
-
|
|
46
|
-
// Strategy: We keep 'redis' as the main interface.
|
|
44
|
+
// Strategy: We keep 'redis' as the main interface.
|
|
47
45
|
// If real redis fails, we just don't set isRedisConnected to true for the *real* one.
|
|
48
46
|
// But wait, the user wants 'bundle redis'.
|
|
49
47
|
// The best way is to detect failure during init and SWAP the implementation.
|
|
@@ -63,6 +61,7 @@ let activeRedis = redis; // Start with real redis attempt
|
|
|
63
61
|
export async function initRedis() {
|
|
64
62
|
if (process.env.NO_REDIS === "true") {
|
|
65
63
|
activeRedis = mockRedis;
|
|
64
|
+
console.log("✅ Redis: Active (Source: Zero-Config Redis [NO_REDIS=true])");
|
|
66
65
|
if (process.env.NODE_ENV === "production") {
|
|
67
66
|
console.warn(
|
|
68
67
|
"⚠️ WARNING: Running in PRODUCTION with in-memory Redis mock. Data will be lost on restart and not shared between instances."
|
|
@@ -75,9 +74,18 @@ export async function initRedis() {
|
|
|
75
74
|
await redis.connect();
|
|
76
75
|
activeRedis = redis; // Keep using real redis
|
|
77
76
|
isRedisConnected = true;
|
|
77
|
+
|
|
78
|
+
// Determine source label
|
|
79
|
+
const sourceLabel = process.env.REDIS_URL
|
|
80
|
+
? redisUrl
|
|
81
|
+
: "Zero-Config Redis (Localhost)";
|
|
82
|
+
|
|
83
|
+
console.log(`✅ Redis: Active (Source: ${sourceLabel})`);
|
|
78
84
|
} catch (err) {
|
|
79
85
|
// Connection failed, switch to mock
|
|
80
|
-
|
|
86
|
+
console.log(
|
|
87
|
+
`⚠️ Redis: Connection failed to ${redisUrl}, switching to fallback (Source: Zero-Config Redis [Mock])`
|
|
88
|
+
);
|
|
81
89
|
activeRedis = mockRedis;
|
|
82
90
|
isRedisConnected = true; // Mock is always "connected"
|
|
83
91
|
if (process.env.NODE_ENV === "production") {
|
|
@@ -118,4 +126,4 @@ export async function delCache(key: string) {
|
|
|
118
126
|
}
|
|
119
127
|
|
|
120
128
|
// Export the proxy as 'redis' so consumers use it transparently
|
|
121
|
-
export { redisProxy as redis };
|
|
129
|
+
export { redisProxy as redis };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import * as PetController from "../controllers/petController";
|
|
3
|
+
|
|
4
|
+
const router = Router();
|
|
5
|
+
|
|
6
|
+
router.get("/", PetController.index);
|
|
7
|
+
router.get("/:id", PetController.show);
|
|
8
|
+
router.post("/", PetController.store);
|
|
9
|
+
router.put("/:id", PetController.update);
|
|
10
|
+
router.delete("/:id", PetController.destroy);
|
|
11
|
+
|
|
12
|
+
export default router;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
export const createPetSchema = z.object({
|
|
5
|
+
name: z.string({ message: "Name is required" }),
|
|
6
|
+
species: z.string({ message: "Species is required" }),
|
|
7
|
+
age: z.number({ message: "Age is required" }).int().positive(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const updatePetSchema = z.object({
|
|
11
|
+
name: z.string().optional(),
|
|
12
|
+
species: z.string().optional(),
|
|
13
|
+
age: z.number().int().positive().optional(),
|
|
14
|
+
});
|
package/src/server.ts
CHANGED
|
@@ -3,6 +3,7 @@ import cors from "cors";
|
|
|
3
3
|
import helmet from "helmet";
|
|
4
4
|
import { authRouter } from "./routes/auth";
|
|
5
5
|
import { rbacRouter } from "./routes/rbac";
|
|
6
|
+
import petRouter from "./routes/pets";
|
|
6
7
|
import { visitorCounter } from "./middleware/visitor";
|
|
7
8
|
import { errorHandler } from "./middleware/error";
|
|
8
9
|
|
|
@@ -28,5 +29,6 @@ app.use(visitorCounter);
|
|
|
28
29
|
|
|
29
30
|
app.use("/api/auth", authRouter);
|
|
30
31
|
app.use("/api/rbac", rbacRouter);
|
|
32
|
+
app.use("/api/pets", petRouter);
|
|
31
33
|
|
|
32
34
|
app.use(errorHandler);
|
package/src/models/schema.prisma
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
model cache {
|
|
3
|
-
key String @id @db.VarChar(255)
|
|
4
|
-
value String
|
|
5
|
-
expiration Int
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
model cache_locks {
|
|
9
|
-
key String @id @db.VarChar(255)
|
|
10
|
-
owner String @db.VarChar(255)
|
|
11
|
-
expiration Int
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
model failed_jobs {
|
|
15
|
-
id BigInt @id @default(autoincrement())
|
|
16
|
-
uuid String @unique(map: "failed_jobs_uuid_unique") @db.VarChar(255)
|
|
17
|
-
connection String
|
|
18
|
-
queue String
|
|
19
|
-
payload String
|
|
20
|
-
exception String
|
|
21
|
-
failed_at DateTime @default(now()) @db.Timestamp(0)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
model job_batches {
|
|
25
|
-
id String @id @db.VarChar(255)
|
|
26
|
-
name String @db.VarChar(255)
|
|
27
|
-
total_jobs Int
|
|
28
|
-
pending_jobs Int
|
|
29
|
-
failed_jobs Int
|
|
30
|
-
failed_job_ids String
|
|
31
|
-
options String?
|
|
32
|
-
cancelled_at Int?
|
|
33
|
-
created_at Int
|
|
34
|
-
finished_at Int?
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
model jobs {
|
|
38
|
-
id BigInt @id @default(autoincrement())
|
|
39
|
-
queue String @db.VarChar(255)
|
|
40
|
-
payload String
|
|
41
|
-
attempts Int @db.SmallInt
|
|
42
|
-
reserved_at Int?
|
|
43
|
-
available_at Int
|
|
44
|
-
created_at Int
|
|
45
|
-
|
|
46
|
-
@@index([queue], map: "jobs_queue_index")
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
model migrations {
|
|
50
|
-
id Int @id @default(autoincrement())
|
|
51
|
-
migration String @db.VarChar(255)
|
|
52
|
-
batch Int
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
model password_reset_tokens {
|
|
56
|
-
email String @id @db.VarChar(255)
|
|
57
|
-
token String @db.VarChar(255)
|
|
58
|
-
created_at DateTime? @db.Timestamp(0)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
model personal_access_tokens {
|
|
62
|
-
id BigInt @id @default(autoincrement())
|
|
63
|
-
tokenable_type String @db.VarChar(255)
|
|
64
|
-
tokenable_id BigInt
|
|
65
|
-
name String
|
|
66
|
-
token String @unique(map: "personal_access_tokens_token_unique") @db.VarChar(64)
|
|
67
|
-
abilities String?
|
|
68
|
-
last_used_at DateTime? @db.Timestamp(0)
|
|
69
|
-
expires_at DateTime? @db.Timestamp(0)
|
|
70
|
-
created_at DateTime? @db.Timestamp(0)
|
|
71
|
-
updated_at DateTime? @db.Timestamp(0)
|
|
72
|
-
|
|
73
|
-
@@index([expires_at], map: "personal_access_tokens_expires_at_index")
|
|
74
|
-
@@index([tokenable_type, tokenable_id], map: "personal_access_tokens_tokenable_type_tokenable_id_index")
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
model sessions {
|
|
78
|
-
id String @id @db.VarChar(255)
|
|
79
|
-
user_id BigInt?
|
|
80
|
-
ip_address String? @db.VarChar(45)
|
|
81
|
-
user_agent String?
|
|
82
|
-
payload String
|
|
83
|
-
last_activity Int
|
|
84
|
-
|
|
85
|
-
@@index([last_activity], map: "sessions_last_activity_index")
|
|
86
|
-
@@index([user_id], map: "sessions_user_id_index")
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
|
90
|
-
model users {
|
|
91
|
-
id BigInt @id @default(autoincrement())
|
|
92
|
-
uuid String @unique(map: "users_uuid_unique") @db.Uuid
|
|
93
|
-
name String @db.VarChar(255)
|
|
94
|
-
email String @unique(map: "users_email_unique") @db.VarChar(255)
|
|
95
|
-
avatar String? @db.VarChar(255)
|
|
96
|
-
avatar_url String? @db.VarChar(255)
|
|
97
|
-
email_verified_at DateTime? @db.Timestamp(0)
|
|
98
|
-
password String @db.VarChar(255)
|
|
99
|
-
remember_token String? @db.VarChar(100)
|
|
100
|
-
created_at DateTime? @db.Timestamp(0)
|
|
101
|
-
updated_at DateTime? @db.Timestamp(0)
|
|
102
|
-
user_roles user_roles[]
|
|
103
|
-
user_permissions user_permissions[]
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
model roles {
|
|
107
|
-
id BigInt @id @default(autoincrement())
|
|
108
|
-
name String @db.VarChar(255)
|
|
109
|
-
slug String @unique @db.VarChar(255)
|
|
110
|
-
description String?
|
|
111
|
-
created_at DateTime? @db.Timestamp(0)
|
|
112
|
-
updated_at DateTime? @db.Timestamp(0)
|
|
113
|
-
user_roles user_roles[]
|
|
114
|
-
role_permissions role_permissions[]
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
model permissions {
|
|
118
|
-
id BigInt @id @default(autoincrement())
|
|
119
|
-
name String @db.VarChar(255)
|
|
120
|
-
slug String @unique @db.VarChar(255)
|
|
121
|
-
description String?
|
|
122
|
-
created_at DateTime? @db.Timestamp(0)
|
|
123
|
-
updated_at DateTime? @db.Timestamp(0)
|
|
124
|
-
user_permissions user_permissions[]
|
|
125
|
-
role_permissions role_permissions[]
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
model user_roles {
|
|
129
|
-
id BigInt @id @default(autoincrement())
|
|
130
|
-
user_id BigInt
|
|
131
|
-
role_id BigInt
|
|
132
|
-
created_at DateTime? @db.Timestamp(0)
|
|
133
|
-
users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
134
|
-
roles roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
135
|
-
|
|
136
|
-
@@unique([user_id, role_id])
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
model role_permissions {
|
|
140
|
-
id BigInt @id @default(autoincrement())
|
|
141
|
-
role_id BigInt
|
|
142
|
-
permission_id BigInt
|
|
143
|
-
created_at DateTime? @db.Timestamp(0)
|
|
144
|
-
roles roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
145
|
-
permissions permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
146
|
-
|
|
147
|
-
@@unique([role_id, permission_id])
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
model user_permissions {
|
|
151
|
-
id BigInt @id @default(autoincrement())
|
|
152
|
-
user_id BigInt
|
|
153
|
-
permission_id BigInt
|
|
154
|
-
created_at DateTime? @db.Timestamp(0)
|
|
155
|
-
users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
156
|
-
permissions permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
157
|
-
|
|
158
|
-
@@unique([user_id, permission_id])
|
|
159
|
-
}
|