create-warlock 4.0.138 → 4.0.140
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/package.json +1 -1
- package/templates/warlock/package.json +7 -7
- package/templates/warlock/src/app/auth/controllers/forgot-password.controller.ts +6 -29
- package/templates/warlock/src/app/auth/controllers/login.controller.ts +5 -11
- package/templates/warlock/src/app/auth/controllers/logout-all.controller.ts +2 -2
- package/templates/warlock/src/app/auth/controllers/logout.controller.ts +2 -2
- package/templates/warlock/src/app/auth/controllers/me.controller.ts +2 -2
- package/templates/warlock/src/app/auth/controllers/refresh-token.controller.ts +3 -10
- package/templates/warlock/src/app/auth/controllers/reset-password.controller.ts +2 -4
- package/templates/warlock/src/app/auth/main.ts +6 -11
- package/templates/warlock/src/app/auth/requests/guarded.request.ts +4 -3
- package/templates/warlock/src/app/auth/requests/login.request.ts +1 -1
- package/templates/warlock/src/app/auth/requests/reset-password.request.ts +1 -1
- package/templates/warlock/src/app/auth/routes.ts +12 -12
- package/templates/warlock/src/app/auth/services/auth.service.ts +22 -8
- package/templates/warlock/src/app/auth/services/forgot-password.service.ts +30 -0
- package/templates/warlock/src/app/auth/services/otp.service.ts +1 -1
- package/templates/warlock/src/app/auth/services/reset-password.service.ts +9 -3
- package/templates/warlock/src/app/users/controllers/{get-users.controller.ts → list-users.controller.ts} +2 -3
- package/templates/warlock/src/app/users/models/user/user.model.ts +5 -29
- package/templates/warlock/src/app/users/repositories/users.repository.ts +10 -10
- package/templates/warlock/src/app/users/resources/user.resource.ts +14 -0
- package/templates/warlock/src/app/users/routes.ts +5 -2
- package/templates/warlock/src/app/users/services/list-users.service.ts +14 -4
- package/templates/warlock/src/config/repository.ts +11 -0
- /package/templates/warlock/src/app/auth/{validation → schema}/login.schema.ts +0 -0
- /package/templates/warlock/src/app/auth/{validation → schema}/reset-password.schema.ts +0 -0
package/package.json
CHANGED
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"@mongez/reinforcements": "^2.3.17",
|
|
24
24
|
"@mongez/localization": "^3.2.1",
|
|
25
25
|
"@mongez/supportive-is": "^2.0.4",
|
|
26
|
-
"@warlock.js/auth": "4.0.
|
|
27
|
-
"@warlock.js/cache": "4.0.
|
|
28
|
-
"@warlock.js/cascade": "4.0.
|
|
29
|
-
"@warlock.js/scheduler": "4.0.
|
|
30
|
-
"@warlock.js/core": "4.0.
|
|
31
|
-
"@warlock.js/logger": "4.0.
|
|
32
|
-
"@warlock.js/seal": "4.0.
|
|
26
|
+
"@warlock.js/auth": "4.0.140",
|
|
27
|
+
"@warlock.js/cache": "4.0.140",
|
|
28
|
+
"@warlock.js/cascade": "4.0.140",
|
|
29
|
+
"@warlock.js/scheduler": "4.0.140",
|
|
30
|
+
"@warlock.js/core": "4.0.140",
|
|
31
|
+
"@warlock.js/logger": "4.0.140",
|
|
32
|
+
"@warlock.js/seal": "4.0.140",
|
|
33
33
|
"dayjs": "^1.11.19",
|
|
34
34
|
"mongodb": "^7.0.0"
|
|
35
35
|
},
|
|
@@ -5,52 +5,29 @@ import {
|
|
|
5
5
|
type RequestHandler,
|
|
6
6
|
type Response,
|
|
7
7
|
} from "@warlock.js/core";
|
|
8
|
-
import {
|
|
9
|
-
import { createOtpService } from "../services/otp.service";
|
|
8
|
+
import { forgotPasswordService } from "../services/forgot-password.service";
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Forgot password controller
|
|
13
12
|
* POST /auth/forgot-password
|
|
14
13
|
*/
|
|
15
|
-
export const
|
|
14
|
+
export const forgotPasswordController: RequestHandler = async (
|
|
16
15
|
request: Request,
|
|
17
16
|
response: Response,
|
|
18
17
|
) => {
|
|
19
18
|
const { email } = request.validated();
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
const user = await usersRepository.first({ email });
|
|
20
|
+
await forgotPasswordService(email);
|
|
23
21
|
|
|
24
|
-
if (!user) {
|
|
25
|
-
// Silent success - don't reveal if email exists
|
|
26
|
-
return response.success({
|
|
27
|
-
message: t("auth.otpSent"),
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Create OTP
|
|
32
|
-
const otp = await createOtpService({
|
|
33
|
-
target: email,
|
|
34
|
-
channel: "email",
|
|
35
|
-
type: "password-reset",
|
|
36
|
-
userId: user.id,
|
|
37
|
-
userType: user.userType,
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// TODO: Send email with OTP code
|
|
41
|
-
// await sendPasswordResetEmail(user, otp.get("code"));
|
|
42
|
-
console.log(`[DEV] Password reset OTP for ${email}: ${otp.get("code")}`);
|
|
43
|
-
|
|
44
|
-
// Always return success for security (don't reveal if email exists)
|
|
45
22
|
return response.success({
|
|
46
23
|
message: t("auth.otpSent"),
|
|
47
24
|
});
|
|
48
25
|
};
|
|
49
26
|
|
|
50
|
-
|
|
27
|
+
forgotPasswordController.description = "Request password reset";
|
|
51
28
|
|
|
52
|
-
|
|
29
|
+
forgotPasswordController.validation = {
|
|
53
30
|
schema: v.object({
|
|
54
|
-
email: v.
|
|
31
|
+
email: v.email().required(),
|
|
55
32
|
}),
|
|
56
33
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type RequestHandler, type Response } from "@warlock.js/core";
|
|
2
2
|
import { type LoginRequest } from "../requests/login.request";
|
|
3
|
+
import { loginSchema } from "../schema/login.schema";
|
|
3
4
|
import { loginService } from "../services/auth.service";
|
|
4
|
-
import { loginSchema } from "../validation/login.schema";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Login controller
|
|
8
8
|
* POST /auth/login
|
|
9
9
|
*/
|
|
10
|
-
export const
|
|
10
|
+
export const loginController: RequestHandler = async (
|
|
11
11
|
request: LoginRequest,
|
|
12
12
|
response: Response,
|
|
13
13
|
) => {
|
|
@@ -16,17 +16,11 @@ export const login: RequestHandler = async (
|
|
|
16
16
|
ip: request.ip,
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
if (!result) {
|
|
20
|
-
return response.unauthorized({
|
|
21
|
-
error: t("auth.invalidCredentials"),
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
19
|
return response.success(result);
|
|
26
20
|
};
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
loginController.description = "User Login";
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
loginController.validation = {
|
|
31
25
|
schema: loginSchema,
|
|
32
26
|
};
|
|
@@ -10,7 +10,7 @@ import { logoutAllService } from "../services/auth.service";
|
|
|
10
10
|
* Logout from all devices controller
|
|
11
11
|
* POST /auth/logout-all
|
|
12
12
|
*/
|
|
13
|
-
export const
|
|
13
|
+
export const logoutAllController: RequestHandler = async (
|
|
14
14
|
request: Request,
|
|
15
15
|
response: Response,
|
|
16
16
|
) => {
|
|
@@ -21,4 +21,4 @@ export const logoutAll: RequestHandler = async (
|
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
logoutAllController.description = "Logout from all devices";
|
|
@@ -10,7 +10,7 @@ import { logoutService } from "../services/auth.service";
|
|
|
10
10
|
* Logout controller
|
|
11
11
|
* POST /auth/logout
|
|
12
12
|
*/
|
|
13
|
-
export const
|
|
13
|
+
export const logoutController: RequestHandler = async (
|
|
14
14
|
request: Request,
|
|
15
15
|
response: Response,
|
|
16
16
|
) => {
|
|
@@ -21,4 +21,4 @@ export const logout: RequestHandler = async (
|
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
logoutController.description = "User Logout";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
* Get current user controller
|
|
9
9
|
* GET /auth/me
|
|
10
10
|
*/
|
|
11
|
-
export const
|
|
11
|
+
export const meController: RequestHandler = async (
|
|
12
12
|
request: Request,
|
|
13
13
|
response: Response,
|
|
14
14
|
) => {
|
|
@@ -17,4 +17,4 @@ export const me: RequestHandler = async (
|
|
|
17
17
|
});
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
meController.description = "Get Current User";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
t,
|
|
3
2
|
v,
|
|
4
3
|
type Request,
|
|
5
4
|
type RequestHandler,
|
|
@@ -11,7 +10,7 @@ import { refreshTokensService } from "../services/auth.service";
|
|
|
11
10
|
* Refresh token controller
|
|
12
11
|
* POST /auth/refresh-token
|
|
13
12
|
*/
|
|
14
|
-
export const
|
|
13
|
+
export const refreshTokenController: RequestHandler = async (
|
|
15
14
|
request: Request,
|
|
16
15
|
response: Response,
|
|
17
16
|
) => {
|
|
@@ -22,18 +21,12 @@ export const refreshToken: RequestHandler = async (
|
|
|
22
21
|
ip: request.ip,
|
|
23
22
|
});
|
|
24
23
|
|
|
25
|
-
if (!result) {
|
|
26
|
-
return response.unauthorized({
|
|
27
|
-
error: t("auth.invalidRefreshToken"),
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
24
|
return response.success(result);
|
|
32
25
|
};
|
|
33
26
|
|
|
34
|
-
|
|
27
|
+
refreshTokenController.description = "Refresh Access Token";
|
|
35
28
|
|
|
36
|
-
|
|
29
|
+
refreshTokenController.validation = {
|
|
37
30
|
schema: v.object({
|
|
38
31
|
refreshToken: v.string().required(),
|
|
39
32
|
}),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t, type Response } from "@warlock.js/core";
|
|
2
2
|
import { type ResetPasswordRequest } from "../requests/reset-password.request";
|
|
3
|
+
import { resetPasswordSchema } from "../schema/reset-password.schema";
|
|
3
4
|
import { resetPasswordService } from "../services/reset-password.service";
|
|
4
|
-
import { resetPasswordSchema } from "../validation/reset-password.schema";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Reset password controller
|
|
@@ -10,9 +10,7 @@ export const resetPasswordController = async (
|
|
|
10
10
|
request: ResetPasswordRequest,
|
|
11
11
|
response: Response,
|
|
12
12
|
) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
await resetPasswordService(email, code, newPassword);
|
|
13
|
+
await resetPasswordService(request.validated());
|
|
16
14
|
|
|
17
15
|
return response.success({
|
|
18
16
|
message: t("auth.passwordResetSuccess"),
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { authService } from "@warlock.js/auth";
|
|
2
|
-
import { onceConnected } from "@warlock.js/cascade";
|
|
3
2
|
import { scheduler } from "app/shared/services/scheduler.service";
|
|
4
3
|
import { cleanupExpiredOtpsService } from "./services/otp.service";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
scheduler
|
|
9
|
-
.newJob("cleanup-expired-otps", cleanupExpiredOtpsService)
|
|
10
|
-
.everyHour();
|
|
5
|
+
// Cleanup expired OTPs every hour
|
|
6
|
+
scheduler.newJob("cleanup-expired-otps", cleanupExpiredOtpsService).everyHour();
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
});
|
|
8
|
+
// Cleanup expired refresh tokens every hour
|
|
9
|
+
scheduler
|
|
10
|
+
.newJob("cleanup-expired-tokens", () => authService.cleanupExpiredTokens())
|
|
11
|
+
.everyHour();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Request } from "@warlock.js/core";
|
|
2
2
|
import type { User } from "app/users/models/user";
|
|
3
3
|
|
|
4
|
-
export type GuardedRequest<RequestPayload = unknown> =
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export type GuardedRequest<RequestPayload = unknown> =
|
|
5
|
+
Request<RequestPayload> & {
|
|
6
|
+
user: User;
|
|
7
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Request } from "@warlock.js/core";
|
|
2
|
-
import { type ResetPasswordSchema } from "../
|
|
2
|
+
import { type ResetPasswordSchema } from "../schema/reset-password.schema";
|
|
3
3
|
|
|
4
4
|
export type ResetPasswordRequest = Request<ResetPasswordSchema>;
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { router } from "@warlock.js/core";
|
|
2
2
|
import { guarded } from "app/shared/utils/router";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import { forgotPasswordController } from "./controllers/forgot-password.controller";
|
|
4
|
+
import { loginController } from "./controllers/login.controller";
|
|
5
|
+
import { logoutAllController } from "./controllers/logout-all.controller";
|
|
6
|
+
import { logoutController } from "./controllers/logout.controller";
|
|
7
|
+
import { meController } from "./controllers/me.controller";
|
|
8
|
+
import { refreshTokenController } from "./controllers/refresh-token.controller";
|
|
9
9
|
import { resetPasswordController } from "./controllers/reset-password.controller";
|
|
10
10
|
|
|
11
11
|
// Auth routes
|
|
12
12
|
router.prefix("/auth", () => {
|
|
13
|
-
router.post("/login",
|
|
14
|
-
router.post("/refresh-token",
|
|
15
|
-
router.post("/forgot-password",
|
|
13
|
+
router.post("/login", loginController);
|
|
14
|
+
router.post("/refresh-token", refreshTokenController);
|
|
15
|
+
router.post("/forgot-password", forgotPasswordController);
|
|
16
16
|
router.post("/reset-password", resetPasswordController);
|
|
17
17
|
guarded(() => {
|
|
18
|
-
router.post("/logout",
|
|
19
|
-
router.post("/logout-all",
|
|
20
|
-
router.get("/me",
|
|
18
|
+
router.post("/logout", logoutController);
|
|
19
|
+
router.post("/logout-all", logoutAllController);
|
|
20
|
+
router.get("/me", meController);
|
|
21
21
|
});
|
|
22
22
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Auth } from "@warlock.js/auth";
|
|
1
|
+
import type { AccessTokenOutput, Auth } from "@warlock.js/auth";
|
|
2
2
|
import { authService, type DeviceInfo, type TokenPair } from "@warlock.js/auth";
|
|
3
|
+
import { t, UnAuthorizedError } from "@warlock.js/core";
|
|
3
4
|
import { User } from "app/users/models/user/user.model";
|
|
4
5
|
|
|
5
6
|
export type LoginCredentials = {
|
|
@@ -9,12 +10,13 @@ export type LoginCredentials = {
|
|
|
9
10
|
|
|
10
11
|
export type LoginResult =
|
|
11
12
|
| {
|
|
12
|
-
user:
|
|
13
|
+
user: User;
|
|
13
14
|
tokens: TokenPair;
|
|
14
15
|
}
|
|
16
|
+
| null
|
|
15
17
|
| {
|
|
16
|
-
user:
|
|
17
|
-
accessToken:
|
|
18
|
+
user: User;
|
|
19
|
+
accessToken: AccessTokenOutput;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
/**
|
|
@@ -23,8 +25,14 @@ export type LoginResult =
|
|
|
23
25
|
export async function loginService(
|
|
24
26
|
credentials: LoginCredentials,
|
|
25
27
|
deviceInfo?: DeviceInfo,
|
|
26
|
-
): Promise<LoginResult
|
|
27
|
-
|
|
28
|
+
): Promise<LoginResult> {
|
|
29
|
+
const result = await authService.login(User, credentials, deviceInfo);
|
|
30
|
+
|
|
31
|
+
if (!result) {
|
|
32
|
+
throw new UnAuthorizedError(t("auth.invalidCredentials"));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return result;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
/**
|
|
@@ -47,6 +55,12 @@ export async function logoutAllService(user: Auth): Promise<void> {
|
|
|
47
55
|
export async function refreshTokensService(
|
|
48
56
|
refreshToken: string,
|
|
49
57
|
deviceInfo?: DeviceInfo,
|
|
50
|
-
): Promise<TokenPair
|
|
51
|
-
|
|
58
|
+
): Promise<TokenPair> {
|
|
59
|
+
const result = await authService.refreshTokens(refreshToken, deviceInfo);
|
|
60
|
+
|
|
61
|
+
if (!result) {
|
|
62
|
+
throw new UnAuthorizedError(t("auth.invalidRefreshToken"));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result;
|
|
52
66
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getFirstUserService } from "app/users/services/list-users.service";
|
|
2
|
+
import { createOtpService } from "./otp.service";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example Usage:
|
|
6
|
+
* await forgotPasswordService("user@example.com");
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Handle forgot password request
|
|
11
|
+
*
|
|
12
|
+
* @param email - User email address
|
|
13
|
+
* @returns Promise<void>
|
|
14
|
+
*/
|
|
15
|
+
export async function forgotPasswordService(email: string): Promise<void> {
|
|
16
|
+
// Find user by email (silent fail for security)
|
|
17
|
+
const user = await getFirstUserService({ email });
|
|
18
|
+
|
|
19
|
+
// Create OTP
|
|
20
|
+
const otp = await createOtpService({
|
|
21
|
+
target: email,
|
|
22
|
+
channel: "email",
|
|
23
|
+
type: "password-reset",
|
|
24
|
+
userId: user.id,
|
|
25
|
+
userType: user.userType,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// TODO: Send email with OTP code using a mail service
|
|
29
|
+
// await sendPasswordResetEmail(user, otp.get("code"));
|
|
30
|
+
}
|
|
@@ -4,14 +4,20 @@ import { User } from "app/users/models/user";
|
|
|
4
4
|
import { AuthErrorCode } from "../utils/auth-error-code";
|
|
5
5
|
import { verifyOtpService } from "./otp.service";
|
|
6
6
|
|
|
7
|
+
type ResetPasswordOptions = {
|
|
8
|
+
email: string;
|
|
9
|
+
code: string;
|
|
10
|
+
newPassword: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
7
13
|
/**
|
|
8
14
|
* Reset user password using OTP verification
|
|
9
15
|
*/
|
|
10
16
|
export async function resetPasswordService(
|
|
11
|
-
|
|
12
|
-
code: string,
|
|
13
|
-
newPassword: string,
|
|
17
|
+
options: ResetPasswordOptions,
|
|
14
18
|
): Promise<User> {
|
|
19
|
+
const { email, code, newPassword } = options;
|
|
20
|
+
|
|
15
21
|
// Verify OTP
|
|
16
22
|
const otp = await verifyOtpService(code, email, "password-reset");
|
|
17
23
|
|
|
@@ -5,13 +5,12 @@ import {
|
|
|
5
5
|
} from "@warlock.js/core";
|
|
6
6
|
import { usersRepository } from "../repositories/users.repository";
|
|
7
7
|
|
|
8
|
-
export const
|
|
8
|
+
export const listUsersController: RequestHandler = async (
|
|
9
9
|
request: Request,
|
|
10
10
|
response: Response,
|
|
11
11
|
) => {
|
|
12
12
|
const users = await usersRepository.listCached({
|
|
13
13
|
...request.all(),
|
|
14
|
-
simpleSelect: true,
|
|
15
14
|
});
|
|
16
15
|
|
|
17
16
|
return response.success({
|
|
@@ -19,4 +18,4 @@ export const getUsersController: RequestHandler = async (
|
|
|
19
18
|
});
|
|
20
19
|
};
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
listUsersController.description = "List Users Controller";
|
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
import { Auth } from "@warlock.js/auth";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
defineResource,
|
|
5
|
-
uploadedFileMetadataSchema,
|
|
6
|
-
useHashedPassword,
|
|
7
|
-
} from "@warlock.js/core";
|
|
2
|
+
import { RegisterModel } from "@warlock.js/cascade";
|
|
3
|
+
import { useHashedPassword } from "@warlock.js/core";
|
|
8
4
|
import { type Infer, v } from "@warlock.js/seal";
|
|
9
|
-
import { type Post } from "app/posts/models/post/post.model";
|
|
10
5
|
import { globalColumnsSchema } from "app/shared/utils/global-columns-schema";
|
|
11
|
-
|
|
12
|
-
const UserResource = defineResource({
|
|
13
|
-
schema: {
|
|
14
|
-
id: "number",
|
|
15
|
-
name: "string",
|
|
16
|
-
email: "string",
|
|
17
|
-
image: "storageUrl",
|
|
18
|
-
createdAt: "date",
|
|
19
|
-
updatedAt: "date",
|
|
20
|
-
isActive: "boolean",
|
|
21
|
-
type: () => "user",
|
|
22
|
-
},
|
|
23
|
-
});
|
|
6
|
+
import { UserResource } from "app/users/resources/user.resource";
|
|
24
7
|
|
|
25
8
|
export const userSchema = globalColumnsSchema.extend({
|
|
26
|
-
name: v.string().required()
|
|
27
|
-
email: v.email().requiredIfEmpty("id")
|
|
9
|
+
name: v.string().required(),
|
|
10
|
+
email: v.email().requiredIfEmpty("id"),
|
|
28
11
|
image: v.string(),
|
|
29
|
-
imageMetadata: uploadedFileMetadataSchema,
|
|
30
12
|
password: v
|
|
31
13
|
.string()
|
|
32
14
|
.min(6)
|
|
@@ -48,12 +30,6 @@ export class User extends Auth<UserSchema> {
|
|
|
48
30
|
*/
|
|
49
31
|
public static schema = userSchema;
|
|
50
32
|
|
|
51
|
-
public static relations = {
|
|
52
|
-
posts: hasMany("Post", { foreignKey: "authorId" }),
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
public posts?: Post[];
|
|
56
|
-
|
|
57
33
|
/**
|
|
58
34
|
* Embed fields when saving in another model
|
|
59
35
|
*/
|
|
@@ -2,22 +2,22 @@ import type { FilterRules, RepositoryOptions } from "@warlock.js/core";
|
|
|
2
2
|
import { RepositoryManager } from "@warlock.js/core";
|
|
3
3
|
import { User } from "../models/user";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
export type UserFilter = {
|
|
6
|
+
email?: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type UsersListOptions = RepositoryOptions & UserFilter;
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
class UsersRepository extends RepositoryManager<User, UserFilter> {
|
|
14
|
+
public source = User;
|
|
9
15
|
|
|
10
16
|
public filterBy: FilterRules = {
|
|
11
|
-
id: "
|
|
17
|
+
id: "=",
|
|
12
18
|
name: "like",
|
|
13
19
|
email: "=",
|
|
14
20
|
};
|
|
15
|
-
|
|
16
|
-
public defaultOptions: RepositoryOptions = {
|
|
17
|
-
orderBy: {
|
|
18
|
-
createdAt: "desc",
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export const usersRepository = new UsersRepository();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineResource } from "@warlock.js/core";
|
|
2
|
+
|
|
3
|
+
export const UserResource = defineResource({
|
|
4
|
+
schema: {
|
|
5
|
+
id: "number",
|
|
6
|
+
name: "string",
|
|
7
|
+
email: "string",
|
|
8
|
+
image: "storageUrl",
|
|
9
|
+
createdAt: "date",
|
|
10
|
+
updatedAt: "date",
|
|
11
|
+
isActive: "boolean",
|
|
12
|
+
type: () => "user",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { router } from "@warlock.js/core";
|
|
2
2
|
import { guarded } from "app/shared/utils/router";
|
|
3
3
|
import { createNewUserController } from "./controllers/create-new-user.controller";
|
|
4
|
-
import {
|
|
4
|
+
import { listUsersController } from "./controllers/list-users.controller";
|
|
5
5
|
|
|
6
6
|
guarded(() => {
|
|
7
|
-
router
|
|
7
|
+
router
|
|
8
|
+
.route("/users")
|
|
9
|
+
.list(listUsersController)
|
|
10
|
+
.post(createNewUserController);
|
|
8
11
|
});
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { ResourceNotFoundError } from "@warlock.js/core";
|
|
2
|
+
import type { UsersListOptions } from "../repositories/users.repository";
|
|
1
3
|
import { usersRepository } from "../repositories/users.repository";
|
|
2
4
|
|
|
3
|
-
export async function listUsersService() {
|
|
4
|
-
return usersRepository.
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
export async function listUsersService(filters: UsersListOptions = {}) {
|
|
6
|
+
return usersRepository.listActiveCached(filters);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function getFirstUserService(filters: UsersListOptions = {}) {
|
|
10
|
+
const user = await usersRepository.firstActiveCached(filters);
|
|
11
|
+
|
|
12
|
+
if (!user) {
|
|
13
|
+
throw new ResourceNotFoundError("No user found");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return user;
|
|
7
17
|
}
|
|
File without changes
|
|
File without changes
|