@arch-cadre/core 0.0.41 → 0.0.43
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/core/auth/augment.js +6 -14
- package/dist/core/auth/email-verification.js +33 -43
- package/dist/core/auth/events.js +1 -2
- package/dist/core/auth/logic.js +71 -90
- package/dist/core/auth/password-reset.js +46 -56
- package/dist/core/auth/rbac.js +73 -90
- package/dist/core/auth/session.js +51 -66
- package/dist/core/auth/types.js +1 -2
- package/dist/core/auth/utils/encode.js +5 -9
- package/dist/core/auth/utils/encryption.js +12 -18
- package/dist/core/auth/validation.js +25 -28
- package/dist/core/bootstrap.js +16 -19
- package/dist/core/config.js +1 -4
- package/dist/core/config.server.js +14 -54
- package/dist/core/event-bus.js +2 -5
- package/dist/core/filesystem/index.js +7 -24
- package/dist/core/filesystem/providers/local.js +7 -14
- package/dist/core/filesystem/service.js +2 -5
- package/dist/core/filesystem/types.js +1 -2
- package/dist/core/notifications/actions.js +22 -28
- package/dist/core/notifications/index.js +3 -19
- package/dist/core/notifications/service.js +6 -9
- package/dist/core/notifications/types.js +1 -2
- package/dist/core/setup.js +7 -10
- package/dist/core/types.js +1 -2
- package/dist/index.js +7 -23
- package/dist/server/auth/email.js +9 -13
- package/dist/server/auth/password.js +6 -14
- package/dist/server/auth/types.js +1 -17
- package/dist/server/auth/user.js +76 -91
- package/dist/server/database/inject.js +2 -6
- package/dist/server/database/schema.js +107 -110
- package/dist/server/database/types.js +1 -2
- package/dist/server/emails/index.js +4 -10
- package/dist/server.js +24 -40
- package/package.json +2 -4
package/dist/server/auth/user.js
CHANGED
|
@@ -1,42 +1,27 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
"use server";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
exports.updateUserPassword = updateUserPassword;
|
|
11
|
-
exports.updateUserName = updateUserName;
|
|
12
|
-
exports.updateUserAwatar = updateUserAwatar;
|
|
13
|
-
exports.updateUserEmailAndSetEmailAsVerified = updateUserEmailAndSetEmailAsVerified;
|
|
14
|
-
exports.setUserAsEmailVerifiedIfEmailMatches = setUserAsEmailVerifiedIfEmailMatches;
|
|
15
|
-
exports.getUserPasswordHash = getUserPasswordHash;
|
|
16
|
-
exports.getUserFromEmail = getUserFromEmail;
|
|
17
|
-
const drizzle_orm_1 = require("drizzle-orm");
|
|
18
|
-
const encode_1 = require("../../core/auth/utils/encode");
|
|
19
|
-
const encryption_1 = require("../../core/auth/utils/encryption");
|
|
20
|
-
const inject_1 = require("../database/inject");
|
|
21
|
-
const schema_1 = require("../database/schema");
|
|
22
|
-
const index_1 = require("../emails/index");
|
|
23
|
-
const password_1 = require("./password");
|
|
2
|
+
import { and, eq } from "drizzle-orm";
|
|
3
|
+
import { generateRandomRecoveryCode } from "../../core/auth/utils/encode";
|
|
4
|
+
import { decryptToString, encryptString, } from "../../core/auth/utils/encryption";
|
|
5
|
+
import { db } from "../database/inject";
|
|
6
|
+
import { rolesTable, usersToRolesTable, userTable } from "../database/schema";
|
|
7
|
+
import { sendRecoveryCode } from "../emails/index";
|
|
8
|
+
import { hashPassword } from "./password";
|
|
24
9
|
/**
|
|
25
10
|
* Validates the username input.
|
|
26
11
|
*/
|
|
27
|
-
async function verifyUsernameInput(username) {
|
|
12
|
+
export async function verifyUsernameInput(username) {
|
|
28
13
|
return (username.length > 3 && username.length < 32 && username.trim() === username);
|
|
29
14
|
}
|
|
30
15
|
/**
|
|
31
16
|
* Creates a new user with an initial recovery code and default 'user' role.
|
|
32
17
|
*/
|
|
33
|
-
async function createUser(email, username, password) {
|
|
34
|
-
const passwordHash = await
|
|
35
|
-
const recoveryCode =
|
|
36
|
-
const encryptedRecoveryCode =
|
|
37
|
-
return await
|
|
18
|
+
export async function createUser(email, username, password) {
|
|
19
|
+
const passwordHash = await hashPassword(password);
|
|
20
|
+
const recoveryCode = generateRandomRecoveryCode();
|
|
21
|
+
const encryptedRecoveryCode = encryptString(recoveryCode);
|
|
22
|
+
return await db.transaction(async (tx) => {
|
|
38
23
|
const [row] = await tx
|
|
39
|
-
.insert(
|
|
24
|
+
.insert(userTable)
|
|
40
25
|
.values({
|
|
41
26
|
email: email,
|
|
42
27
|
name: username,
|
|
@@ -50,31 +35,31 @@ async function createUser(email, username, password) {
|
|
|
50
35
|
// Assign default 'user' role
|
|
51
36
|
let [role] = await tx
|
|
52
37
|
.select()
|
|
53
|
-
.from(
|
|
54
|
-
.where(
|
|
38
|
+
.from(rolesTable)
|
|
39
|
+
.where(eq(rolesTable.name, "user"));
|
|
55
40
|
if (!role) {
|
|
56
41
|
[role] = await tx
|
|
57
|
-
.insert(
|
|
42
|
+
.insert(rolesTable)
|
|
58
43
|
.values({ name: "user", description: "Default user role" })
|
|
59
44
|
.returning();
|
|
60
45
|
}
|
|
61
|
-
await tx.insert(
|
|
46
|
+
await tx.insert(usersToRolesTable).values({
|
|
62
47
|
userId: row.id,
|
|
63
48
|
roleId: role.id,
|
|
64
49
|
});
|
|
65
|
-
await
|
|
50
|
+
await sendRecoveryCode(row.email, recoveryCode);
|
|
66
51
|
return row;
|
|
67
52
|
});
|
|
68
53
|
}
|
|
69
54
|
/**
|
|
70
55
|
* Creates a new user from an OAuth provider.
|
|
71
56
|
*/
|
|
72
|
-
async function createOAuthUser(email, name, image) {
|
|
73
|
-
const recoveryCode =
|
|
74
|
-
const encryptedRecoveryCode =
|
|
75
|
-
return await
|
|
57
|
+
export async function createOAuthUser(email, name, image) {
|
|
58
|
+
const recoveryCode = generateRandomRecoveryCode();
|
|
59
|
+
const encryptedRecoveryCode = encryptString(recoveryCode);
|
|
60
|
+
return await db.transaction(async (tx) => {
|
|
76
61
|
const [row] = await tx
|
|
77
|
-
.insert(
|
|
62
|
+
.insert(userTable)
|
|
78
63
|
.values({
|
|
79
64
|
email: email,
|
|
80
65
|
name: name,
|
|
@@ -86,15 +71,15 @@ async function createOAuthUser(email, name, image) {
|
|
|
86
71
|
// Assign default 'user' role
|
|
87
72
|
let [role] = await tx
|
|
88
73
|
.select()
|
|
89
|
-
.from(
|
|
90
|
-
.where(
|
|
74
|
+
.from(rolesTable)
|
|
75
|
+
.where(eq(rolesTable.name, "user"));
|
|
91
76
|
if (!role) {
|
|
92
77
|
[role] = await tx
|
|
93
|
-
.insert(
|
|
78
|
+
.insert(rolesTable)
|
|
94
79
|
.values({ name: "user", description: "Default user role" })
|
|
95
80
|
.returning();
|
|
96
81
|
}
|
|
97
|
-
await tx.insert(
|
|
82
|
+
await tx.insert(usersToRolesTable).values({
|
|
98
83
|
userId: row.id,
|
|
99
84
|
roleId: role.id,
|
|
100
85
|
});
|
|
@@ -104,11 +89,11 @@ async function createOAuthUser(email, name, image) {
|
|
|
104
89
|
/**
|
|
105
90
|
* Returns a user by ID.
|
|
106
91
|
*/
|
|
107
|
-
async function getUserById(userId) {
|
|
108
|
-
const [user] = await
|
|
92
|
+
export async function getUserById(userId) {
|
|
93
|
+
const [user] = await db
|
|
109
94
|
.select()
|
|
110
|
-
.from(
|
|
111
|
-
.where(
|
|
95
|
+
.from(userTable)
|
|
96
|
+
.where(eq(userTable.id, userId));
|
|
112
97
|
if (!user)
|
|
113
98
|
return null;
|
|
114
99
|
const { password, recovery_code, ...safeUser } = user;
|
|
@@ -117,106 +102,106 @@ async function getUserById(userId) {
|
|
|
117
102
|
/**
|
|
118
103
|
* Decrypts and returns the user's recovery code.
|
|
119
104
|
*/
|
|
120
|
-
async function getUserRecoverCode(userId) {
|
|
121
|
-
const [user] = await
|
|
105
|
+
export async function getUserRecoverCode(userId) {
|
|
106
|
+
const [user] = await db
|
|
122
107
|
.select({
|
|
123
|
-
recovery_code:
|
|
108
|
+
recovery_code: userTable.recovery_code,
|
|
124
109
|
})
|
|
125
|
-
.from(
|
|
126
|
-
.where(
|
|
110
|
+
.from(userTable)
|
|
111
|
+
.where(eq(userTable.id, userId));
|
|
127
112
|
if (!user || !user.recovery_code) {
|
|
128
113
|
throw new Error("Recovery code not found for user");
|
|
129
114
|
}
|
|
130
|
-
return
|
|
115
|
+
return decryptToString(user.recovery_code);
|
|
131
116
|
}
|
|
132
117
|
/**
|
|
133
118
|
* Generates and sets a new recovery code for the user.
|
|
134
119
|
*/
|
|
135
|
-
async function resetUserRecoveryCode(userId) {
|
|
136
|
-
const recoveryCode =
|
|
137
|
-
const encrypted =
|
|
138
|
-
const [currentUser] = await
|
|
139
|
-
.update(
|
|
120
|
+
export async function resetUserRecoveryCode(userId) {
|
|
121
|
+
const recoveryCode = generateRandomRecoveryCode();
|
|
122
|
+
const encrypted = encryptString(recoveryCode);
|
|
123
|
+
const [currentUser] = await db
|
|
124
|
+
.update(userTable)
|
|
140
125
|
.set({
|
|
141
126
|
recovery_code: Buffer.from(encrypted),
|
|
142
127
|
})
|
|
143
|
-
.where(
|
|
128
|
+
.where(eq(userTable.id, userId))
|
|
144
129
|
.returning();
|
|
145
130
|
if (!currentUser) {
|
|
146
131
|
throw new Error("User not found");
|
|
147
132
|
}
|
|
148
|
-
await
|
|
133
|
+
await sendRecoveryCode(currentUser.email, recoveryCode);
|
|
149
134
|
return recoveryCode;
|
|
150
135
|
}
|
|
151
136
|
/**
|
|
152
137
|
* Updates the user's password.
|
|
153
138
|
*/
|
|
154
|
-
async function updateUserPassword(userId, password) {
|
|
155
|
-
const passwordHash = await
|
|
156
|
-
await
|
|
157
|
-
.update(
|
|
139
|
+
export async function updateUserPassword(userId, password) {
|
|
140
|
+
const passwordHash = await hashPassword(password);
|
|
141
|
+
await db
|
|
142
|
+
.update(userTable)
|
|
158
143
|
.set({
|
|
159
144
|
password: passwordHash,
|
|
160
145
|
})
|
|
161
|
-
.where(
|
|
146
|
+
.where(eq(userTable.id, userId));
|
|
162
147
|
}
|
|
163
148
|
/**
|
|
164
149
|
* Updates the user's name.
|
|
165
150
|
*/
|
|
166
|
-
async function updateUserName(userId, name) {
|
|
167
|
-
await
|
|
168
|
-
.update(
|
|
151
|
+
export async function updateUserName(userId, name) {
|
|
152
|
+
await db
|
|
153
|
+
.update(userTable)
|
|
169
154
|
.set({
|
|
170
155
|
name: name,
|
|
171
156
|
})
|
|
172
|
-
.where(
|
|
157
|
+
.where(eq(userTable.id, userId));
|
|
173
158
|
}
|
|
174
159
|
/**
|
|
175
160
|
* Updates the user's image.
|
|
176
161
|
*/
|
|
177
|
-
async function updateUserAwatar(userId, image) {
|
|
178
|
-
await
|
|
179
|
-
.update(
|
|
162
|
+
export async function updateUserAwatar(userId, image) {
|
|
163
|
+
await db
|
|
164
|
+
.update(userTable)
|
|
180
165
|
.set({
|
|
181
166
|
image,
|
|
182
167
|
})
|
|
183
|
-
.where(
|
|
168
|
+
.where(eq(userTable.id, userId));
|
|
184
169
|
}
|
|
185
170
|
/**
|
|
186
171
|
* Updates the user's email and marks it as verified.
|
|
187
172
|
*/
|
|
188
|
-
async function updateUserEmailAndSetEmailAsVerified(userId, email) {
|
|
189
|
-
await
|
|
190
|
-
.update(
|
|
173
|
+
export async function updateUserEmailAndSetEmailAsVerified(userId, email) {
|
|
174
|
+
await db
|
|
175
|
+
.update(userTable)
|
|
191
176
|
.set({
|
|
192
177
|
email: email,
|
|
193
178
|
emailVerifiedAt: new Date(),
|
|
194
179
|
})
|
|
195
|
-
.where(
|
|
180
|
+
.where(eq(userTable.id, userId));
|
|
196
181
|
}
|
|
197
182
|
/**
|
|
198
183
|
* Sets the user as email verified if the provided email matches.
|
|
199
184
|
*/
|
|
200
|
-
async function setUserAsEmailVerifiedIfEmailMatches(userId, email) {
|
|
201
|
-
const result = await
|
|
202
|
-
.update(
|
|
185
|
+
export async function setUserAsEmailVerifiedIfEmailMatches(userId, email) {
|
|
186
|
+
const result = await db
|
|
187
|
+
.update(userTable)
|
|
203
188
|
.set({
|
|
204
189
|
emailVerifiedAt: new Date(),
|
|
205
190
|
})
|
|
206
|
-
.where(
|
|
207
|
-
.returning({ id:
|
|
191
|
+
.where(and(eq(userTable.id, userId), eq(userTable.email, email)))
|
|
192
|
+
.returning({ id: userTable.id });
|
|
208
193
|
return result.length > 0;
|
|
209
194
|
}
|
|
210
195
|
/**
|
|
211
196
|
* Returns the user's password hash.
|
|
212
197
|
*/
|
|
213
|
-
async function getUserPasswordHash(userId) {
|
|
214
|
-
const [user] = await
|
|
198
|
+
export async function getUserPasswordHash(userId) {
|
|
199
|
+
const [user] = await db
|
|
215
200
|
.select({
|
|
216
|
-
password:
|
|
201
|
+
password: userTable.password,
|
|
217
202
|
})
|
|
218
|
-
.from(
|
|
219
|
-
.where(
|
|
203
|
+
.from(userTable)
|
|
204
|
+
.where(eq(userTable.id, userId));
|
|
220
205
|
if (!user) {
|
|
221
206
|
throw new Error("User not found");
|
|
222
207
|
}
|
|
@@ -225,11 +210,11 @@ async function getUserPasswordHash(userId) {
|
|
|
225
210
|
/**
|
|
226
211
|
* Returns a user by email.
|
|
227
212
|
*/
|
|
228
|
-
async function getUserFromEmail(email) {
|
|
229
|
-
const [user] = await
|
|
213
|
+
export async function getUserFromEmail(email) {
|
|
214
|
+
const [user] = await db
|
|
230
215
|
.select()
|
|
231
|
-
.from(
|
|
232
|
-
.where(
|
|
216
|
+
.from(userTable)
|
|
217
|
+
.where(eq(userTable.email, email));
|
|
233
218
|
if (!user)
|
|
234
219
|
return null;
|
|
235
220
|
const { password, recovery_code, ...safeUser } = user;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.db = void 0;
|
|
4
|
-
exports.injectDb = injectDb;
|
|
5
1
|
// Use globalThis to persist the DB across multiple bundles/instances
|
|
6
2
|
const globalForDb = globalThis;
|
|
7
|
-
function injectDb(db) {
|
|
3
|
+
export function injectDb(db) {
|
|
8
4
|
if (globalForDb.__KRYO_DB__)
|
|
9
5
|
return;
|
|
10
6
|
console.log("[Kryo:Core] >>> DATABASE INJECTED <<<");
|
|
@@ -15,7 +11,7 @@ function injectDb(db) {
|
|
|
15
11
|
* Resolves to globalThis.__KRYO_DB__ on every property access.
|
|
16
12
|
* Safe to import statically at top-level.
|
|
17
13
|
*/
|
|
18
|
-
|
|
14
|
+
export const db = new Proxy({}, {
|
|
19
15
|
get(_, prop) {
|
|
20
16
|
var _a;
|
|
21
17
|
if (prop === "then")
|
|
@@ -1,151 +1,148 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const pg_core_1 = require("drizzle-orm/pg-core");
|
|
6
|
-
exports.userTable = (0, pg_core_1.pgTable)("users", {
|
|
7
|
-
id: (0, pg_core_1.text)("id")
|
|
1
|
+
import { defineRelations, sql } from "drizzle-orm";
|
|
2
|
+
import { boolean, bytea, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
|
3
|
+
export const userTable = pgTable("users", {
|
|
4
|
+
id: text("id")
|
|
8
5
|
.$defaultFn(() => crypto.randomUUID())
|
|
9
6
|
.notNull()
|
|
10
7
|
.primaryKey(),
|
|
11
|
-
email:
|
|
12
|
-
name:
|
|
13
|
-
password:
|
|
14
|
-
image:
|
|
15
|
-
recovery_code:
|
|
16
|
-
emailVerifiedAt:
|
|
17
|
-
createdAt:
|
|
18
|
-
updatedAt:
|
|
8
|
+
email: text("email").notNull().unique(),
|
|
9
|
+
name: text("name").notNull(),
|
|
10
|
+
password: text("password"),
|
|
11
|
+
image: text("image"),
|
|
12
|
+
recovery_code: bytea("recovery_code").notNull(),
|
|
13
|
+
emailVerifiedAt: timestamp("email_verified_at", { precision: 3 }),
|
|
14
|
+
createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(),
|
|
15
|
+
updatedAt: timestamp("updated_at", { precision: 3 }),
|
|
19
16
|
});
|
|
20
|
-
|
|
21
|
-
id:
|
|
17
|
+
export const rolesTable = pgTable("roles", {
|
|
18
|
+
id: text("id")
|
|
22
19
|
.$defaultFn(() => crypto.randomUUID())
|
|
23
20
|
.notNull()
|
|
24
21
|
.primaryKey(),
|
|
25
|
-
name:
|
|
26
|
-
description:
|
|
22
|
+
name: text("name").notNull().unique(), // np. "admin", "user"
|
|
23
|
+
description: text("description"),
|
|
27
24
|
});
|
|
28
|
-
|
|
29
|
-
id:
|
|
25
|
+
export const permissionsTable = pgTable("permissions", {
|
|
26
|
+
id: text("id")
|
|
30
27
|
.$defaultFn(() => crypto.randomUUID())
|
|
31
28
|
.notNull()
|
|
32
29
|
.primaryKey(),
|
|
33
|
-
name:
|
|
34
|
-
description:
|
|
30
|
+
name: text("name").notNull().unique(), // np. "blog:write"
|
|
31
|
+
description: text("description"),
|
|
35
32
|
});
|
|
36
|
-
|
|
37
|
-
userId:
|
|
33
|
+
export const usersToRolesTable = pgTable("users_to_roles", {
|
|
34
|
+
userId: text("user_id")
|
|
38
35
|
.notNull()
|
|
39
|
-
.references(() =>
|
|
40
|
-
roleId:
|
|
36
|
+
.references(() => userTable.id, { onDelete: "cascade" }),
|
|
37
|
+
roleId: text("role_id")
|
|
41
38
|
.notNull()
|
|
42
|
-
.references(() =>
|
|
43
|
-
}, (t) => [{ pk:
|
|
44
|
-
|
|
45
|
-
userId:
|
|
39
|
+
.references(() => rolesTable.id, { onDelete: "cascade" }),
|
|
40
|
+
}, (t) => [{ pk: sql `PRIMARY KEY (${t.userId}, ${t.roleId})` }]);
|
|
41
|
+
export const usersToPermissionsTable = pgTable("users_to_permissions", {
|
|
42
|
+
userId: text("user_id")
|
|
46
43
|
.notNull()
|
|
47
|
-
.references(() =>
|
|
48
|
-
permissionId:
|
|
44
|
+
.references(() => userTable.id, { onDelete: "cascade" }),
|
|
45
|
+
permissionId: text("permission_id")
|
|
49
46
|
.notNull()
|
|
50
|
-
.references(() =>
|
|
51
|
-
}, (t) => [{ pk:
|
|
52
|
-
|
|
53
|
-
roleId:
|
|
47
|
+
.references(() => permissionsTable.id, { onDelete: "cascade" }),
|
|
48
|
+
}, (t) => [{ pk: sql `PRIMARY KEY (${t.userId}, ${t.permissionId})` }]);
|
|
49
|
+
export const rolesToPermissionsTable = pgTable("roles_to_permissions", {
|
|
50
|
+
roleId: text("role_id")
|
|
54
51
|
.notNull()
|
|
55
|
-
.references(() =>
|
|
56
|
-
permissionId:
|
|
52
|
+
.references(() => rolesTable.id, { onDelete: "cascade" }),
|
|
53
|
+
permissionId: text("permission_id")
|
|
57
54
|
.notNull()
|
|
58
|
-
.references(() =>
|
|
59
|
-
}, (t) => [{ pk:
|
|
60
|
-
|
|
61
|
-
id:
|
|
55
|
+
.references(() => permissionsTable.id, { onDelete: "cascade" }),
|
|
56
|
+
}, (t) => [{ pk: sql `PRIMARY KEY (${t.roleId}, ${t.permissionId})` }]);
|
|
57
|
+
export const sessionTable = pgTable("sessions", {
|
|
58
|
+
id: text("id")
|
|
62
59
|
.$defaultFn(() => crypto.randomUUID())
|
|
63
60
|
.notNull()
|
|
64
61
|
.primaryKey(),
|
|
65
|
-
active_organization_id:
|
|
66
|
-
userId:
|
|
62
|
+
active_organization_id: text("active_organization_id"),
|
|
63
|
+
userId: text("user_id")
|
|
67
64
|
.notNull()
|
|
68
|
-
.references(() =>
|
|
65
|
+
.references(() => userTable.id, {
|
|
69
66
|
onDelete: "cascade",
|
|
70
67
|
onUpdate: "cascade",
|
|
71
68
|
}),
|
|
72
|
-
expiresAt:
|
|
73
|
-
createdAt:
|
|
74
|
-
updatedAt:
|
|
69
|
+
expiresAt: timestamp("expires_at", { precision: 3 }).notNull(),
|
|
70
|
+
createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(),
|
|
71
|
+
updatedAt: timestamp("updated_at", { precision: 3 }),
|
|
75
72
|
});
|
|
76
|
-
|
|
77
|
-
id:
|
|
73
|
+
export const emailVerificationTable = pgTable("email_verification_requests", {
|
|
74
|
+
id: text("id")
|
|
78
75
|
.$defaultFn(() => crypto.randomUUID())
|
|
79
76
|
.notNull()
|
|
80
77
|
.primaryKey(),
|
|
81
|
-
email:
|
|
82
|
-
code:
|
|
83
|
-
userId:
|
|
78
|
+
email: text("email").notNull(),
|
|
79
|
+
code: text("code").notNull(),
|
|
80
|
+
userId: text("user_id")
|
|
84
81
|
.notNull()
|
|
85
|
-
.references(() =>
|
|
82
|
+
.references(() => userTable.id, {
|
|
86
83
|
onDelete: "cascade",
|
|
87
84
|
onUpdate: "cascade",
|
|
88
85
|
}),
|
|
89
|
-
expiresAt:
|
|
90
|
-
createdAt:
|
|
91
|
-
updatedAt:
|
|
86
|
+
expiresAt: timestamp("expires_at", { precision: 3 }).notNull(),
|
|
87
|
+
createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(),
|
|
88
|
+
updatedAt: timestamp("updated_at", { precision: 3 }),
|
|
92
89
|
});
|
|
93
|
-
|
|
94
|
-
id:
|
|
90
|
+
export const passwordResetSessionTable = pgTable("password_reset_sessions", {
|
|
91
|
+
id: text("id")
|
|
95
92
|
.$defaultFn(() => crypto.randomUUID())
|
|
96
93
|
.notNull()
|
|
97
94
|
.primaryKey(),
|
|
98
|
-
email:
|
|
99
|
-
code:
|
|
100
|
-
emailVerified:
|
|
101
|
-
userId:
|
|
95
|
+
email: text("email").notNull(),
|
|
96
|
+
code: text("code").notNull(),
|
|
97
|
+
emailVerified: boolean("emailVerified").default(false),
|
|
98
|
+
userId: text("user_id")
|
|
102
99
|
.notNull()
|
|
103
|
-
.references(() =>
|
|
100
|
+
.references(() => userTable.id, {
|
|
104
101
|
onDelete: "cascade",
|
|
105
102
|
onUpdate: "cascade",
|
|
106
103
|
}),
|
|
107
|
-
expiresAt:
|
|
108
|
-
createdAt:
|
|
109
|
-
updatedAt:
|
|
104
|
+
expiresAt: timestamp("expires_at", { precision: 3 }).notNull(),
|
|
105
|
+
createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(),
|
|
106
|
+
updatedAt: timestamp("updated_at", { precision: 3 }),
|
|
110
107
|
});
|
|
111
|
-
|
|
112
|
-
id:
|
|
108
|
+
export const notificationTable = pgTable("notification", {
|
|
109
|
+
id: text("id")
|
|
113
110
|
.$defaultFn(() => crypto.randomUUID())
|
|
114
111
|
.notNull()
|
|
115
112
|
.primaryKey(),
|
|
116
|
-
title:
|
|
117
|
-
content:
|
|
118
|
-
target:
|
|
119
|
-
type:
|
|
120
|
-
isRead:
|
|
121
|
-
resourceId:
|
|
122
|
-
resourceType:
|
|
123
|
-
userId:
|
|
124
|
-
.notNull()
|
|
125
|
-
.references(() =>
|
|
113
|
+
title: text("title").notNull(),
|
|
114
|
+
content: text("content"),
|
|
115
|
+
target: text("target"),
|
|
116
|
+
type: text("type"),
|
|
117
|
+
isRead: boolean("isRead").notNull(),
|
|
118
|
+
resourceId: text("resource_id"),
|
|
119
|
+
resourceType: text("resource_type"),
|
|
120
|
+
userId: text("user_id")
|
|
121
|
+
.notNull()
|
|
122
|
+
.references(() => userTable.id, {
|
|
126
123
|
onDelete: "cascade",
|
|
127
124
|
onUpdate: "cascade",
|
|
128
125
|
}),
|
|
129
|
-
createdAt:
|
|
130
|
-
updatedAt:
|
|
126
|
+
createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(),
|
|
127
|
+
updatedAt: timestamp("updated_at", { precision: 3 }),
|
|
131
128
|
});
|
|
132
|
-
|
|
133
|
-
id:
|
|
134
|
-
enabled:
|
|
135
|
-
installed:
|
|
136
|
-
deleted:
|
|
137
|
-
system:
|
|
138
|
-
config:
|
|
139
|
-
lastStep:
|
|
140
|
-
updatedAt:
|
|
129
|
+
export const systemModulesTable = pgTable("system_modules", {
|
|
130
|
+
id: text("id").notNull().primaryKey(),
|
|
131
|
+
enabled: boolean("enabled").notNull().default(false),
|
|
132
|
+
installed: boolean("installed").notNull().default(false),
|
|
133
|
+
deleted: boolean("deleted").notNull().default(false),
|
|
134
|
+
system: boolean("system").notNull().default(false),
|
|
135
|
+
config: text("config"),
|
|
136
|
+
lastStep: text("last_step"), // Przechowuje aktualny etap (np. "Syncing DB")
|
|
137
|
+
updatedAt: timestamp("updated_at", { precision: 3 }).defaultNow(),
|
|
141
138
|
});
|
|
142
|
-
|
|
143
|
-
user:
|
|
144
|
-
emailVerification:
|
|
145
|
-
passwordResetSession:
|
|
146
|
-
session:
|
|
147
|
-
notification:
|
|
148
|
-
systemModulesTable:
|
|
139
|
+
export const relations = defineRelations({
|
|
140
|
+
user: userTable,
|
|
141
|
+
emailVerification: emailVerificationTable,
|
|
142
|
+
passwordResetSession: passwordResetSessionTable,
|
|
143
|
+
session: sessionTable,
|
|
144
|
+
notification: notificationTable,
|
|
145
|
+
systemModulesTable: systemModulesTable,
|
|
149
146
|
}, (r) => ({
|
|
150
147
|
user: {
|
|
151
148
|
sessions: r.many.session({
|
|
@@ -180,16 +177,16 @@ exports.relations = (0, drizzle_orm_1.defineRelations)({
|
|
|
180
177
|
}),
|
|
181
178
|
},
|
|
182
179
|
}));
|
|
183
|
-
|
|
184
|
-
userTable
|
|
185
|
-
rolesTable
|
|
186
|
-
permissionsTable
|
|
187
|
-
usersToRolesTable
|
|
188
|
-
usersToPermissionsTable
|
|
189
|
-
rolesToPermissionsTable
|
|
190
|
-
sessionTable
|
|
191
|
-
emailVerificationTable
|
|
192
|
-
passwordResetSessionTable
|
|
193
|
-
notificationTable
|
|
194
|
-
systemModulesTable
|
|
180
|
+
export const coreSchema = {
|
|
181
|
+
userTable,
|
|
182
|
+
rolesTable,
|
|
183
|
+
permissionsTable,
|
|
184
|
+
usersToRolesTable,
|
|
185
|
+
usersToPermissionsTable,
|
|
186
|
+
rolesToPermissionsTable,
|
|
187
|
+
sessionTable,
|
|
188
|
+
emailVerificationTable,
|
|
189
|
+
passwordResetSessionTable,
|
|
190
|
+
notificationTable,
|
|
191
|
+
systemModulesTable,
|
|
195
192
|
};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
"use server";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.sendVerifyEmail = sendVerifyEmail;
|
|
5
|
-
exports.sendResetPassword = sendResetPassword;
|
|
6
|
-
exports.sendRecoveryCode = sendRecoveryCode;
|
|
7
|
-
exports.send2FACode = send2FACode;
|
|
8
2
|
// import nodemailer from "nodemailer";
|
|
9
3
|
// Konfiguracja transportera SMTP
|
|
10
4
|
// const transporter = nodemailer.createTransport({
|
|
@@ -19,7 +13,7 @@ exports.send2FACode = send2FACode;
|
|
|
19
13
|
* @param email Recipient's email address.
|
|
20
14
|
* @param code Verification code.
|
|
21
15
|
*/
|
|
22
|
-
async function sendVerifyEmail(email, code) {
|
|
16
|
+
export async function sendVerifyEmail(email, code) {
|
|
23
17
|
// const { t } = await getTranslation();
|
|
24
18
|
// await transporter.sendMail({
|
|
25
19
|
// from: `Winkly <${process.env.GOOGLE_SMTP_APP_USERNAME}>`,
|
|
@@ -33,7 +27,7 @@ async function sendVerifyEmail(email, code) {
|
|
|
33
27
|
* @param email Recipient's email address.
|
|
34
28
|
* @param code Password reset code.
|
|
35
29
|
*/
|
|
36
|
-
async function sendResetPassword(email, code) {
|
|
30
|
+
export async function sendResetPassword(email, code) {
|
|
37
31
|
// const { t } = await getTranslation();
|
|
38
32
|
// await transporter.sendMail({
|
|
39
33
|
// from: `Winkly <${process.env.GOOGLE_SMTP_APP_USERNAME}>`,
|
|
@@ -47,7 +41,7 @@ async function sendResetPassword(email, code) {
|
|
|
47
41
|
* @param email Recipient's email address.
|
|
48
42
|
* @param recoveryCode Recovery code
|
|
49
43
|
*/
|
|
50
|
-
async function sendRecoveryCode(email, recoveryCode) {
|
|
44
|
+
export async function sendRecoveryCode(email, recoveryCode) {
|
|
51
45
|
// const { t } = await getTranslation();
|
|
52
46
|
// await transporter.sendMail({
|
|
53
47
|
// from: `Winkly <${process.env.GOOGLE_SMTP_APP_USERNAME}>`,
|
|
@@ -59,7 +53,7 @@ async function sendRecoveryCode(email, recoveryCode) {
|
|
|
59
53
|
/**
|
|
60
54
|
* Sends a 2FA code via email.
|
|
61
55
|
*/
|
|
62
|
-
async function send2FACode(email, code) {
|
|
56
|
+
export async function send2FACode(email, code) {
|
|
63
57
|
// const { t } = await getTranslation();
|
|
64
58
|
// await transporter.sendMail({
|
|
65
59
|
// from: `Winkly <${process.env.GOOGLE_SMTP_APP_USERNAME}>`,
|