stackkit 0.2.9 → 0.3.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/bin/stackkit.js +8 -5
- package/dist/cli/add.js +4 -9
- package/dist/cli/create.js +4 -9
- package/dist/cli/doctor.js +11 -32
- package/dist/lib/constants.js +3 -4
- package/dist/lib/conversion/js-conversion.js +20 -16
- package/dist/lib/discovery/installed-detection.js +28 -38
- package/dist/lib/discovery/module-discovery.d.ts +0 -15
- package/dist/lib/discovery/module-discovery.js +15 -50
- package/dist/lib/framework/framework-utils.d.ts +4 -5
- package/dist/lib/framework/framework-utils.js +38 -49
- package/dist/lib/generation/code-generator.d.ts +11 -12
- package/dist/lib/generation/code-generator.js +54 -134
- package/dist/lib/generation/generator-utils.js +3 -15
- package/dist/lib/project/detect.js +11 -19
- package/modules/auth/better-auth/files/express/middlewares/authorize.ts +66 -8
- package/modules/auth/better-auth/files/express/modules/auth/auth.controller.ts +7 -0
- package/modules/auth/better-auth/files/express/modules/auth/auth.route.ts +5 -0
- package/modules/auth/better-auth/files/express/modules/auth/auth.service.ts +145 -11
- package/modules/auth/better-auth/files/express/modules/auth/{auth.interface.ts → auth.type.ts} +16 -6
- package/modules/auth/better-auth/files/shared/config/env.ts +8 -4
- package/modules/auth/better-auth/files/shared/lib/auth.ts +24 -25
- package/modules/auth/better-auth/files/shared/mongoose/auth/constants.ts +11 -0
- package/modules/auth/better-auth/files/shared/mongoose/auth/helper.ts +51 -0
- package/modules/auth/better-auth/files/shared/utils/email.ts +0 -1
- package/modules/auth/better-auth/generator.json +24 -20
- package/modules/database/mongoose/files/lib/mongoose.ts +28 -3
- package/modules/database/mongoose/generator.json +1 -1
- package/package.json +2 -2
- package/templates/express/env.example +1 -0
- package/templates/express/src/config/env.ts +4 -2
|
@@ -8,16 +8,15 @@ exports.getRouterBasePath = getRouterBasePath;
|
|
|
8
8
|
exports.getLibPath = getLibPath;
|
|
9
9
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const constants_1 = require("../constants");
|
|
11
12
|
const installed_detection_1 = require("../discovery/installed-detection");
|
|
12
13
|
const package_root_1 = require("../utils/package-root");
|
|
13
14
|
async function detectProjectInfo(targetDir) {
|
|
14
|
-
const packageJsonPath = path_1.default.join(targetDir,
|
|
15
|
+
const packageJsonPath = path_1.default.join(targetDir, constants_1.FILE_NAMES.PACKAGE_JSON);
|
|
15
16
|
if (!(await fs_extra_1.default.pathExists(packageJsonPath))) {
|
|
16
|
-
throw new Error(
|
|
17
|
+
throw new Error(constants_1.ERROR_MESSAGES.NO_PACKAGE_JSON);
|
|
17
18
|
}
|
|
18
19
|
const packageJson = await fs_extra_1.default.readJSON(packageJsonPath);
|
|
19
|
-
// Detect framework by matching available templates' characteristic files
|
|
20
|
-
// Framework is dynamic and driven by templates; keep as string for discovery
|
|
21
20
|
let framework = "unknown";
|
|
22
21
|
try {
|
|
23
22
|
const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
|
|
@@ -41,19 +40,17 @@ async function detectProjectInfo(targetDir) {
|
|
|
41
40
|
bestMatch = { name: d, score };
|
|
42
41
|
}
|
|
43
42
|
catch {
|
|
44
|
-
|
|
43
|
+
continue;
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
if (bestMatch && bestMatch.score > 0) {
|
|
48
|
-
// Use the template folder name as the framework identifier
|
|
49
47
|
framework = bestMatch.name;
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
catch {
|
|
54
|
-
|
|
52
|
+
framework = "unknown";
|
|
55
53
|
}
|
|
56
|
-
// Fallback: simple dependency-based detection
|
|
57
54
|
if (framework === "unknown") {
|
|
58
55
|
const isNextJs = packageJson.dependencies?.next || packageJson.devDependencies?.next;
|
|
59
56
|
const isExpress = packageJson.dependencies?.express || packageJson.devDependencies?.express;
|
|
@@ -71,7 +68,6 @@ async function detectProjectInfo(targetDir) {
|
|
|
71
68
|
if (framework === "unknown") {
|
|
72
69
|
throw new Error("Unsupported project type or unable to detect framework from templates.");
|
|
73
70
|
}
|
|
74
|
-
// Detect router type (only for Next.js)
|
|
75
71
|
let router = "unknown";
|
|
76
72
|
if (framework === "nextjs") {
|
|
77
73
|
const appDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "app"));
|
|
@@ -79,14 +75,13 @@ async function detectProjectInfo(targetDir) {
|
|
|
79
75
|
const srcAppDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "src", "app"));
|
|
80
76
|
const srcPagesDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "src", "pages"));
|
|
81
77
|
if (appDirExists || srcAppDirExists) {
|
|
82
|
-
router =
|
|
78
|
+
router = constants_1.ROUTER_TYPES.APP;
|
|
83
79
|
}
|
|
84
80
|
else if (pagesDirExists || srcPagesDirExists) {
|
|
85
|
-
router =
|
|
81
|
+
router = constants_1.ROUTER_TYPES.PAGES;
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
|
-
|
|
89
|
-
const tsconfigExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "tsconfig.json"));
|
|
84
|
+
const tsconfigExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, constants_1.FILE_NAMES.TSCONFIG_JSON));
|
|
90
85
|
const jsconfigExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "jsconfig.json"));
|
|
91
86
|
let language;
|
|
92
87
|
if (tsconfigExists) {
|
|
@@ -98,10 +93,9 @@ async function detectProjectInfo(targetDir) {
|
|
|
98
93
|
else {
|
|
99
94
|
language = "ts";
|
|
100
95
|
}
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
const bunLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "bun.lockb"));
|
|
96
|
+
const yarnLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, constants_1.LOCK_FILES.yarn));
|
|
97
|
+
const pnpmLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, constants_1.LOCK_FILES.pnpm));
|
|
98
|
+
const bunLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, constants_1.LOCK_FILES.bun));
|
|
105
99
|
let packageManager = "pnpm";
|
|
106
100
|
if (pnpmLockExists) {
|
|
107
101
|
packageManager = "pnpm";
|
|
@@ -112,8 +106,6 @@ async function detectProjectInfo(targetDir) {
|
|
|
112
106
|
else if (bunLockExists) {
|
|
113
107
|
packageManager = "bun";
|
|
114
108
|
}
|
|
115
|
-
// Detect installed modules by comparing project dependencies against
|
|
116
|
-
// declared dependencies in `modules/*/generator.json` and `module.json`.
|
|
117
109
|
const detectedAuth = await (0, installed_detection_1.detectAuthModules)(packageJson);
|
|
118
110
|
const detectedDbs = await (0, installed_detection_1.detectDatabaseModules)(packageJson);
|
|
119
111
|
const hasAuth = detectedAuth.length > 0;
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { Role, UserStatus } from "@prisma/client";
|
|
2
1
|
import { NextFunction, Request, Response } from "express";
|
|
3
2
|
import status from "http-status";
|
|
4
3
|
import { envVars } from "../../config/env";
|
|
5
|
-
import { prisma } from "../../database/prisma";
|
|
6
4
|
import { AppError } from "../errors/app-error";
|
|
7
5
|
import { cookieUtils } from "../utils/cookie";
|
|
8
6
|
import { jwtUtils } from "../utils/jwt";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
{{#if database == "prisma"}}
|
|
8
|
+
import { Role, UserStatus } from "@prisma/client";
|
|
9
|
+
import { prisma } from "../../database/prisma";
|
|
10
|
+
{{/if}}
|
|
11
|
+
{{#if database == "mongoose"}}
|
|
12
|
+
import { Role, UserStatus } from "../../modules/auth/auth.constants";
|
|
13
|
+
import { getAuthCollections } from "../../modules/auth/auth.helper";
|
|
14
|
+
{{/if}}
|
|
15
|
+
|
|
16
|
+
{{#if database == "prisma"}}
|
|
17
|
+
export const authorize = (...authRoles: Role[]) =>
|
|
18
|
+
{{/if}}
|
|
19
|
+
{{#if database == "mongoose"}}
|
|
20
|
+
type AuthRole = (typeof Role)[keyof typeof Role];
|
|
21
|
+
|
|
22
|
+
export const authorize = (...authRoles: AuthRole[]) =>
|
|
23
|
+
{{/if}}
|
|
12
24
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
13
25
|
try {
|
|
14
26
|
//Session Token Verification
|
|
@@ -22,7 +34,8 @@ export const authorize =
|
|
|
22
34
|
}
|
|
23
35
|
|
|
24
36
|
if (sessionToken) {
|
|
25
|
-
|
|
37
|
+
{{#if database == "prisma"}}
|
|
38
|
+
const sessionExists = await prisma.session.findFirst({
|
|
26
39
|
where: {
|
|
27
40
|
token: sessionToken,
|
|
28
41
|
expiresAt: {
|
|
@@ -33,10 +46,30 @@ export const authorize =
|
|
|
33
46
|
user: true,
|
|
34
47
|
},
|
|
35
48
|
});
|
|
49
|
+
{{/if}}
|
|
50
|
+
{{#if database == "mongoose"}}
|
|
51
|
+
const { sessions, users } = await getAuthCollections();
|
|
52
|
+
const sessionExists = await sessions.findOne({
|
|
53
|
+
token: sessionToken,
|
|
54
|
+
expiresAt: { $gt: new Date() },
|
|
55
|
+
});
|
|
36
56
|
|
|
57
|
+
const user = sessionExists
|
|
58
|
+
? await users.findOne({
|
|
59
|
+
id: sessionExists.userId,
|
|
60
|
+
})
|
|
61
|
+
: null;
|
|
62
|
+
{{/if}}
|
|
63
|
+
|
|
64
|
+
{{#if database == "prisma"}}
|
|
37
65
|
if (sessionExists && sessionExists.user) {
|
|
38
66
|
const user = sessionExists.user;
|
|
67
|
+
{{/if}}
|
|
68
|
+
{{#if database == "mongoose"}}
|
|
69
|
+
if (sessionExists && user) {
|
|
70
|
+
{{/if}}
|
|
39
71
|
|
|
72
|
+
{{#if database == "prisma"}}
|
|
40
73
|
const now = new Date();
|
|
41
74
|
const expiresAt = new Date(sessionExists.expiresAt);
|
|
42
75
|
const createdAt = new Date(sessionExists.createdAt);
|
|
@@ -52,6 +85,26 @@ export const authorize =
|
|
|
52
85
|
|
|
53
86
|
console.log("Session Expiring Soon!!");
|
|
54
87
|
}
|
|
88
|
+
{{/if}}
|
|
89
|
+
{{#if database == "mongoose"}}
|
|
90
|
+
if (sessionExists.expiresAt && sessionExists.createdAt) {
|
|
91
|
+
const now = new Date();
|
|
92
|
+
const expiresAt = new Date(sessionExists.expiresAt);
|
|
93
|
+
const createdAt = new Date(sessionExists.createdAt);
|
|
94
|
+
|
|
95
|
+
const sessionLifeTime = expiresAt.getTime() - createdAt.getTime();
|
|
96
|
+
const timeRemaining = expiresAt.getTime() - now.getTime();
|
|
97
|
+
const percentRemaining = (timeRemaining / sessionLifeTime) * 100;
|
|
98
|
+
|
|
99
|
+
if (percentRemaining < 20) {
|
|
100
|
+
res.setHeader("X-Session-Refresh", "true");
|
|
101
|
+
res.setHeader("X-Session-Expires-At", expiresAt.toISOString());
|
|
102
|
+
res.setHeader("X-Time-Remaining", timeRemaining.toString());
|
|
103
|
+
|
|
104
|
+
console.log("Session Expiring Soon!!");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
{{/if}}
|
|
55
108
|
|
|
56
109
|
if (
|
|
57
110
|
user.status === UserStatus.BLOCKED ||
|
|
@@ -70,7 +123,12 @@ export const authorize =
|
|
|
70
123
|
);
|
|
71
124
|
}
|
|
72
125
|
|
|
126
|
+
{{#if database == "prisma"}}
|
|
73
127
|
if (authRoles.length > 0 && !authRoles.includes(user.role)) {
|
|
128
|
+
{{/if}}
|
|
129
|
+
{{#if database == "mongoose"}}
|
|
130
|
+
if (authRoles.length > 0 && !authRoles.includes(user.role as AuthRole)) {
|
|
131
|
+
{{/if}}
|
|
74
132
|
throw new AppError(
|
|
75
133
|
status.FORBIDDEN,
|
|
76
134
|
"Forbidden access! You do not have permission to access this resource.",
|
|
@@ -119,7 +177,7 @@ export const authorize =
|
|
|
119
177
|
|
|
120
178
|
if (
|
|
121
179
|
authRoles.length > 0 &&
|
|
122
|
-
!authRoles.includes(verifiedToken.data!.role
|
|
180
|
+
!authRoles.includes(verifiedToken.data!.role)
|
|
123
181
|
) {
|
|
124
182
|
throw new AppError(
|
|
125
183
|
status.FORBIDDEN,
|
|
@@ -131,4 +189,4 @@ export const authorize =
|
|
|
131
189
|
} catch (error: unknown) {
|
|
132
190
|
next(error);
|
|
133
191
|
}
|
|
134
|
-
|
|
192
|
+
};
|
|
@@ -39,6 +39,13 @@ const loginUser = catchAsync(
|
|
|
39
39
|
const result = await authService.loginUser(payload);
|
|
40
40
|
const { accessToken, refreshToken, token, ...rest } = result
|
|
41
41
|
|
|
42
|
+
if (!token) {
|
|
43
|
+
throw new AppError(
|
|
44
|
+
status.INTERNAL_SERVER_ERROR,
|
|
45
|
+
"Session token is missing",
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
tokenUtils.setAccessTokenCookie(res, accessToken);
|
|
43
50
|
tokenUtils.setRefreshTokenCookie(res, refreshToken);
|
|
44
51
|
tokenUtils.setBetterAuthSessionCookie(res, token);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
{{#if database == "prisma"}}
|
|
1
2
|
import { Role } from "@prisma/client";
|
|
3
|
+
{{/if}}
|
|
4
|
+
{{#if database == "mongoose"}}
|
|
5
|
+
import { Role } from './auth.constants';
|
|
6
|
+
{{/if}}
|
|
2
7
|
import { Router } from "express";
|
|
3
8
|
import { authorize } from "../../shared/middlewares/authorize.middleware";
|
|
4
9
|
import { authController } from "./auth.controller";
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import status from "http-status";
|
|
2
2
|
import { JwtPayload } from "jsonwebtoken";
|
|
3
3
|
import { envVars } from "../../config/env";
|
|
4
|
+
{{#if database == "prisma"}}
|
|
4
5
|
import { prisma } from "../../database/prisma";
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{#if database == "mongoose"}}
|
|
8
|
+
import {
|
|
9
|
+
deleteAuthUserById,
|
|
10
|
+
getAuthCollections,
|
|
11
|
+
} from "./auth.helper";
|
|
12
|
+
{{/if}}
|
|
5
13
|
import { auth } from "../../lib/auth";
|
|
6
14
|
import { AppError } from "../../shared/errors/app-error";
|
|
7
15
|
import { jwtUtils } from "../../shared/utils/jwt";
|
|
@@ -11,7 +19,7 @@ import {
|
|
|
11
19
|
ILoginUserPayload,
|
|
12
20
|
IRegisterUserPayload,
|
|
13
21
|
IRequestUser,
|
|
14
|
-
} from "./auth.
|
|
22
|
+
} from "./auth.type";
|
|
15
23
|
|
|
16
24
|
const registerUser = async (payload: IRegisterUserPayload) => {
|
|
17
25
|
const { name, email, password } = payload;
|
|
@@ -56,11 +64,16 @@ const registerUser = async (payload: IRegisterUserPayload) => {
|
|
|
56
64
|
user: data.user,
|
|
57
65
|
};
|
|
58
66
|
} catch (error) {
|
|
67
|
+
{{#if database == "prisma"}}
|
|
59
68
|
await prisma.user.delete({
|
|
60
69
|
where: {
|
|
61
70
|
id: data.user.id,
|
|
62
71
|
},
|
|
63
72
|
});
|
|
73
|
+
{{/if}}
|
|
74
|
+
{{#if database == "mongoose"}}
|
|
75
|
+
await deleteAuthUserById(data.user.id);
|
|
76
|
+
{{/if}}
|
|
64
77
|
throw error;
|
|
65
78
|
}
|
|
66
79
|
|
|
@@ -112,12 +125,18 @@ const loginUser = async (payload: ILoginUserPayload) => {
|
|
|
112
125
|
}
|
|
113
126
|
|
|
114
127
|
const getMe = async (user : IRequestUser) => {
|
|
115
|
-
|
|
128
|
+
{{#if database == "prisma"}}
|
|
129
|
+
const isUserExists = await prisma.user.findUnique({
|
|
116
130
|
where: {
|
|
117
131
|
id: user.id,
|
|
118
132
|
},
|
|
119
133
|
// Include other related models if needed
|
|
120
134
|
});
|
|
135
|
+
{{/if}}
|
|
136
|
+
{{#if database == "mongoose"}}
|
|
137
|
+
const { users } = await getAuthCollections();
|
|
138
|
+
const isUserExists = await users.findOne({ id: user.id });
|
|
139
|
+
{{/if}}
|
|
121
140
|
|
|
122
141
|
if (!isUserExists) {
|
|
123
142
|
throw new AppError(status.NOT_FOUND, "User not found");
|
|
@@ -127,8 +146,8 @@ const getMe = async (user : IRequestUser) => {
|
|
|
127
146
|
}
|
|
128
147
|
|
|
129
148
|
const getNewToken = async (refreshToken : string, sessionToken : string) => {
|
|
130
|
-
|
|
131
|
-
|
|
149
|
+
{{#if database == "prisma"}}
|
|
150
|
+
const isSessionTokenExists = await prisma.session.findUnique({
|
|
132
151
|
where : {
|
|
133
152
|
token : sessionToken,
|
|
134
153
|
},
|
|
@@ -136,6 +155,14 @@ const getNewToken = async (refreshToken : string, sessionToken : string) => {
|
|
|
136
155
|
user : true,
|
|
137
156
|
}
|
|
138
157
|
})
|
|
158
|
+
{{/if}}
|
|
159
|
+
{{#if database == "mongoose"}}
|
|
160
|
+
const { sessions } = await getAuthCollections();
|
|
161
|
+
|
|
162
|
+
const isSessionTokenExists = await sessions.findOne({
|
|
163
|
+
token: sessionToken,
|
|
164
|
+
});
|
|
165
|
+
{{/if}}
|
|
139
166
|
|
|
140
167
|
if(!isSessionTokenExists){
|
|
141
168
|
throw new AppError(status.UNAUTHORIZED, "Invalid session token");
|
|
@@ -169,7 +196,8 @@ const getNewToken = async (refreshToken : string, sessionToken : string) => {
|
|
|
169
196
|
emailVerified: data.emailVerified,
|
|
170
197
|
});
|
|
171
198
|
|
|
172
|
-
|
|
199
|
+
{{#if database == "prisma"}}
|
|
200
|
+
const { token } = await prisma.session.update({
|
|
173
201
|
where : {
|
|
174
202
|
token : sessionToken
|
|
175
203
|
},
|
|
@@ -179,13 +207,33 @@ const getNewToken = async (refreshToken : string, sessionToken : string) => {
|
|
|
179
207
|
updatedAt: new Date(),
|
|
180
208
|
}
|
|
181
209
|
})
|
|
210
|
+
{{/if}}
|
|
211
|
+
{{#if database == "mongoose"}}
|
|
212
|
+
const updatedSession = await sessions.findOneAndUpdate(
|
|
213
|
+
{ token: sessionToken },
|
|
214
|
+
{
|
|
215
|
+
$set: {
|
|
216
|
+
token: sessionToken,
|
|
217
|
+
expiresAt: new Date(Date.now() + 60 * 60 * 60 * 24 * 1000),
|
|
218
|
+
updatedAt: new Date(),
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
returnDocument: "after",
|
|
223
|
+
},
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
if (!updatedSession) {
|
|
227
|
+
throw new AppError(status.UNAUTHORIZED, "Session not found");
|
|
228
|
+
}
|
|
229
|
+
const token = updatedSession.token;
|
|
230
|
+
{{/if}}
|
|
182
231
|
|
|
183
232
|
return {
|
|
184
233
|
accessToken : newAccessToken,
|
|
185
234
|
refreshToken : newRefreshToken,
|
|
186
235
|
sessionToken : token,
|
|
187
|
-
}
|
|
188
|
-
|
|
236
|
+
};
|
|
189
237
|
}
|
|
190
238
|
|
|
191
239
|
const changePassword = async (payload : IChangePasswordPayload, sessionToken : string) =>{
|
|
@@ -213,6 +261,7 @@ const changePassword = async (payload : IChangePasswordPayload, sessionToken : s
|
|
|
213
261
|
})
|
|
214
262
|
|
|
215
263
|
if(session.user.needPasswordChange){
|
|
264
|
+
{{#if database == "prisma"}}
|
|
216
265
|
await prisma.user.update({
|
|
217
266
|
where: {
|
|
218
267
|
id: session.user.id,
|
|
@@ -221,6 +270,20 @@ const changePassword = async (payload : IChangePasswordPayload, sessionToken : s
|
|
|
221
270
|
needPasswordChange: false,
|
|
222
271
|
}
|
|
223
272
|
})
|
|
273
|
+
{{/if}}
|
|
274
|
+
{{#if database == "mongoose"}}
|
|
275
|
+
const { users } = await getAuthCollections();
|
|
276
|
+
await users.updateOne(
|
|
277
|
+
{
|
|
278
|
+
id: session.user.id,
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
$set: {
|
|
282
|
+
needPasswordChange: false,
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
);
|
|
286
|
+
{{/if}}
|
|
224
287
|
}
|
|
225
288
|
|
|
226
289
|
const accessToken = tokenUtils.getAccessToken({
|
|
@@ -271,6 +334,7 @@ const verifyEmail = async (email : string, otp : string) => {
|
|
|
271
334
|
})
|
|
272
335
|
|
|
273
336
|
if(result.status && !result.user.emailVerified){
|
|
337
|
+
{{#if database == "prisma"}}
|
|
274
338
|
await prisma.user.update({
|
|
275
339
|
where : {
|
|
276
340
|
email,
|
|
@@ -279,15 +343,37 @@ const verifyEmail = async (email : string, otp : string) => {
|
|
|
279
343
|
emailVerified: true,
|
|
280
344
|
}
|
|
281
345
|
})
|
|
346
|
+
{{/if}}
|
|
347
|
+
{{#if database == "mongoose"}}
|
|
348
|
+
const { users } = await getAuthCollections();
|
|
349
|
+
await users.updateOne(
|
|
350
|
+
{
|
|
351
|
+
email,
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
$set: {
|
|
355
|
+
emailVerified: true,
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
);
|
|
359
|
+
{{/if}}
|
|
282
360
|
}
|
|
283
361
|
}
|
|
284
362
|
|
|
285
363
|
const forgetPassword = async (email : string) => {
|
|
364
|
+
{{#if database == "prisma"}}
|
|
286
365
|
const isUserExist = await prisma.user.findUnique({
|
|
287
366
|
where : {
|
|
288
367
|
email,
|
|
289
368
|
}
|
|
290
369
|
})
|
|
370
|
+
{{/if}}
|
|
371
|
+
{{#if database == "mongoose"}}
|
|
372
|
+
const { users } = await getAuthCollections();
|
|
373
|
+
const isUserExist = await users.findOne({
|
|
374
|
+
email,
|
|
375
|
+
});
|
|
376
|
+
{{/if}}
|
|
291
377
|
|
|
292
378
|
if(!isUserExist){
|
|
293
379
|
throw new AppError(status.NOT_FOUND, "User not found");
|
|
@@ -309,11 +395,19 @@ const forgetPassword = async (email : string) => {
|
|
|
309
395
|
}
|
|
310
396
|
|
|
311
397
|
const resetPassword = async (email : string, otp : string, newPassword : string) => {
|
|
398
|
+
{{#if database == "prisma"}}
|
|
312
399
|
const isUserExist = await prisma.user.findUnique({
|
|
313
|
-
where: {
|
|
400
|
+
where : {
|
|
314
401
|
email,
|
|
315
402
|
}
|
|
316
403
|
})
|
|
404
|
+
{{/if}}
|
|
405
|
+
{{#if database == "mongoose"}}
|
|
406
|
+
const { users } = await getAuthCollections();
|
|
407
|
+
const isUserExist = await users.findOne({
|
|
408
|
+
email,
|
|
409
|
+
});
|
|
410
|
+
{{/if}}
|
|
317
411
|
|
|
318
412
|
if (!isUserExist) {
|
|
319
413
|
throw new AppError(status.NOT_FOUND, "User not found");
|
|
@@ -335,10 +429,11 @@ const resetPassword = async (email : string, otp : string, newPassword : string)
|
|
|
335
429
|
}
|
|
336
430
|
})
|
|
337
431
|
|
|
432
|
+
{{#if database == "prisma"}}
|
|
338
433
|
if (isUserExist.needPasswordChange) {
|
|
339
434
|
await prisma.user.update({
|
|
340
435
|
where: {
|
|
341
|
-
|
|
436
|
+
email,
|
|
342
437
|
},
|
|
343
438
|
data: {
|
|
344
439
|
needPasswordChange: false,
|
|
@@ -351,17 +446,37 @@ const resetPassword = async (email : string, otp : string, newPassword : string)
|
|
|
351
446
|
userId : isUserExist.id,
|
|
352
447
|
}
|
|
353
448
|
})
|
|
449
|
+
{{/if}}
|
|
450
|
+
{{#if database == "mongoose"}}
|
|
451
|
+
if (isUserExist.needPasswordChange) {
|
|
452
|
+
await users.updateOne(
|
|
453
|
+
{
|
|
454
|
+
email,
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
$set: {
|
|
458
|
+
needPasswordChange: false,
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
const { sessions } = await getAuthCollections();
|
|
464
|
+
await sessions.deleteMany({
|
|
465
|
+
userId: isUserExist.id,
|
|
466
|
+
});
|
|
467
|
+
{{/if}}
|
|
354
468
|
}
|
|
355
469
|
|
|
356
470
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
357
471
|
const googleLoginSuccess = async (session : Record<string, any>) =>{
|
|
358
|
-
|
|
472
|
+
{{#if database == "prisma"}}
|
|
473
|
+
const isUserExists = await prisma.user.findUnique({
|
|
359
474
|
where: {
|
|
360
475
|
id: session.user.id,
|
|
361
476
|
},
|
|
362
477
|
});
|
|
363
478
|
|
|
364
|
-
if (!
|
|
479
|
+
if (!isUserExists) {
|
|
365
480
|
await prisma.user.create({
|
|
366
481
|
data: {
|
|
367
482
|
id: session.user.id,
|
|
@@ -370,6 +485,25 @@ const googleLoginSuccess = async (session : Record<string, any>) =>{
|
|
|
370
485
|
},
|
|
371
486
|
});
|
|
372
487
|
}
|
|
488
|
+
{{/if}}
|
|
489
|
+
{{#if database == "mongoose"}}
|
|
490
|
+
const { users } = await getAuthCollections();
|
|
491
|
+
const isUserExists = await users.findOne({ id: session.user.id });
|
|
492
|
+
|
|
493
|
+
if (!isUserExists) {
|
|
494
|
+
await users.insertOne({
|
|
495
|
+
id: session.user.id,
|
|
496
|
+
name: session.user.name,
|
|
497
|
+
email: session.user.email,
|
|
498
|
+
role: "USER",
|
|
499
|
+
status: "ACTIVE",
|
|
500
|
+
needPasswordChange: false,
|
|
501
|
+
emailVerified: true,
|
|
502
|
+
isDeleted: false,
|
|
503
|
+
deletedAt: null,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
{{/if}}
|
|
373
507
|
|
|
374
508
|
const accessToken = tokenUtils.getAccessToken({
|
|
375
509
|
userId: session.user.id,
|
package/modules/auth/better-auth/files/express/modules/auth/{auth.interface.ts → auth.type.ts}
RENAMED
|
@@ -1,5 +1,21 @@
|
|
|
1
|
+
{{#if database == "prisma"}}
|
|
1
2
|
import { Role } from "@prisma/client";
|
|
2
3
|
|
|
4
|
+
export interface IRequestUser {
|
|
5
|
+
id: string;
|
|
6
|
+
role: Role | string;
|
|
7
|
+
email: string;
|
|
8
|
+
}
|
|
9
|
+
{{/if}}
|
|
10
|
+
{{#if database == "mongoose"}}
|
|
11
|
+
import { Role } from './auth.constants';
|
|
12
|
+
export interface IRequestUser {
|
|
13
|
+
id: string;
|
|
14
|
+
role: typeof Role | string;
|
|
15
|
+
email: string;
|
|
16
|
+
}
|
|
17
|
+
{{/if}}
|
|
18
|
+
|
|
3
19
|
export interface ILoginUserPayload {
|
|
4
20
|
email: string;
|
|
5
21
|
password: string;
|
|
@@ -15,9 +31,3 @@ export interface IChangePasswordPayload {
|
|
|
15
31
|
currentPassword: string;
|
|
16
32
|
newPassword: string;
|
|
17
33
|
}
|
|
18
|
-
|
|
19
|
-
export interface IRequestUser {
|
|
20
|
-
id: string;
|
|
21
|
-
role: Role | string;
|
|
22
|
-
email: string;
|
|
23
|
-
}
|
|
@@ -9,11 +9,12 @@ dotenv.config({ path: path.join(process.cwd(), ".env") });
|
|
|
9
9
|
|
|
10
10
|
interface EnvConfig {
|
|
11
11
|
APP_URL?: string;
|
|
12
|
+
DATABASE_URL: string;
|
|
12
13
|
FRONTEND_URL?: string;
|
|
13
14
|
BETTER_AUTH_URL: string;
|
|
14
15
|
BETTER_AUTH_SECRET: string;
|
|
15
|
-
GOOGLE_CLIENT_ID
|
|
16
|
-
GOOGLE_CLIENT_SECRET
|
|
16
|
+
GOOGLE_CLIENT_ID: string;
|
|
17
|
+
GOOGLE_CLIENT_SECRET: string;
|
|
17
18
|
GOOGLE_CALLBACK_URL: string;
|
|
18
19
|
EMAIL_SENDER: {
|
|
19
20
|
SMTP_USER: string;
|
|
@@ -38,6 +39,8 @@ interface EnvConfig {
|
|
|
38
39
|
|
|
39
40
|
const loadEnvVars = (): EnvConfig => {
|
|
40
41
|
const requiredEnvVars = [
|
|
42
|
+
"APP_URL",
|
|
43
|
+
"DATABASE_URL",
|
|
41
44
|
"FRONTEND_URL",
|
|
42
45
|
"BETTER_AUTH_URL",
|
|
43
46
|
"BETTER_AUTH_SECRET",
|
|
@@ -80,11 +83,12 @@ const loadEnvVars = (): EnvConfig => {
|
|
|
80
83
|
|
|
81
84
|
return {
|
|
82
85
|
APP_URL: process.env.APP_URL as string,
|
|
86
|
+
DATABASE_URL: process.env.DATABASE_URL as string,
|
|
83
87
|
FRONTEND_URL: process.env.FRONTEND_URL as string,
|
|
84
88
|
BETTER_AUTH_URL: process.env.BETTER_AUTH_URL as string,
|
|
85
89
|
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET as string,
|
|
86
|
-
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
|
|
87
|
-
GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
|
|
90
|
+
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID as string,
|
|
91
|
+
GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET as string,
|
|
88
92
|
GOOGLE_CALLBACK_URL: process.env.GOOGLE_CALLBACK_URL as string,
|
|
89
93
|
EMAIL_SENDER: {
|
|
90
94
|
SMTP_USER: process.env.EMAIL_SENDER_SMTP_USER as string,
|