@loomcore/api 0.2.18 → 0.2.19
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/controllers/auth.controller.d.ts +11 -1
- package/dist/controllers/auth.controller.js +26 -10
- package/dist/controllers/users.controller.d.ts +7 -2
- package/dist/controllers/users.controller.js +6 -4
- package/dist/middleware/is-authorized.js +2 -2
- package/dist/services/user.service.d.ts +2 -2
- package/dist/services/user.service.js +2 -2
- package/dist/utils/auth/attempt-login.util.d.ts +2 -1
- package/dist/utils/auth/attempt-login.util.js +2 -3
- package/dist/utils/auth/auth-user-specs.util.d.ts +15 -0
- package/dist/utils/auth/auth-user-specs.util.js +38 -0
- package/dist/utils/auth/change-password.util.d.ts +2 -1
- package/dist/utils/auth/change-password.util.js +1 -2
- package/dist/utils/auth/index.d.ts +1 -0
- package/dist/utils/auth/index.js +1 -0
- package/dist/utils/auth/log-user-in.util.d.ts +2 -1
- package/dist/utils/auth/log-user-in.util.js +2 -2
- package/dist/utils/auth/reset-password.util.d.ts +3 -2
- package/dist/utils/auth/reset-password.util.js +3 -4
- package/dist/utils/auth/update-last-logged-in.util.d.ts +2 -1
- package/dist/utils/auth/update-last-logged-in.util.js +1 -2
- package/package.json +1 -1
|
@@ -1,11 +1,21 @@
|
|
|
1
|
+
import { type IModelSpec } from "@loomcore/common/models";
|
|
1
2
|
import type { Application, Request, Response } from "express";
|
|
2
3
|
import type { IDatabase } from "../databases/models/index.js";
|
|
3
4
|
import { OrganizationService, UserService } from "../services/index.js";
|
|
5
|
+
export interface AuthControllerOptions {
|
|
6
|
+
userService?: UserService;
|
|
7
|
+
userSpec?: IModelSpec;
|
|
8
|
+
publicUserSpec?: IModelSpec;
|
|
9
|
+
}
|
|
4
10
|
export declare class AuthController {
|
|
5
11
|
database: IDatabase;
|
|
6
12
|
userService: UserService;
|
|
7
13
|
organizationService: OrganizationService;
|
|
8
|
-
|
|
14
|
+
userSpec: IModelSpec;
|
|
15
|
+
publicUserSpec: IModelSpec;
|
|
16
|
+
publicUserContextSpec: IModelSpec;
|
|
17
|
+
loginResponseSpec: IModelSpec;
|
|
18
|
+
constructor(app: Application, database: IDatabase, options?: AuthControllerOptions);
|
|
9
19
|
mapRoutes(app: Application): void;
|
|
10
20
|
login(req: Request, res: Response): Promise<void>;
|
|
11
21
|
requestTokenUsingRefreshToken(req: Request, res: Response): Promise<void>;
|
|
@@ -1,19 +1,35 @@
|
|
|
1
|
-
import { EmptyUserContext,
|
|
1
|
+
import { EmptyUserContext, passwordValidator, TokenResponseSpec, } from "@loomcore/common/models";
|
|
2
2
|
import { entityUtils } from "@loomcore/common/utils";
|
|
3
3
|
import { config } from "../config/base-api-config.js";
|
|
4
4
|
import { BadRequestError, UnauthenticatedError } from "../errors/index.js";
|
|
5
5
|
import { isAuthorized } from "../middleware/index.js";
|
|
6
6
|
import { OrganizationService, UserService } from "../services/index.js";
|
|
7
|
-
import { attemptLogin, changePassword, getAndSetDeviceIdCookie, getDeviceIdFromCookie, requestTokenUsingRefreshToken, resetPassword, sendResetPasswordEmail, } from "../utils/auth/index.js";
|
|
7
|
+
import { attemptLogin, changePassword, createUserContextSpec, getAndSetDeviceIdCookie, getDeviceIdFromCookie, requestTokenUsingRefreshToken, resetPassword, resolveAuthUserSpecs, sendResetPasswordEmail, setAuthUserContextSpec, } from "../utils/auth/index.js";
|
|
8
8
|
import { apiUtils } from "../utils/index.js";
|
|
9
9
|
export class AuthController {
|
|
10
10
|
database;
|
|
11
11
|
userService;
|
|
12
12
|
organizationService;
|
|
13
|
-
|
|
13
|
+
userSpec;
|
|
14
|
+
publicUserSpec;
|
|
15
|
+
publicUserContextSpec;
|
|
16
|
+
loginResponseSpec;
|
|
17
|
+
constructor(app, database, options = {}) {
|
|
14
18
|
this.database = database;
|
|
15
|
-
|
|
19
|
+
const resolved = resolveAuthUserSpecs({
|
|
20
|
+
userSpec: options.userSpec,
|
|
21
|
+
publicUserSpec: options.publicUserSpec,
|
|
22
|
+
});
|
|
23
|
+
this.userSpec = resolved.userSpec;
|
|
24
|
+
this.publicUserSpec = resolved.publicUserSpec;
|
|
25
|
+
this.publicUserContextSpec = resolved.publicUserContextSpec;
|
|
26
|
+
this.loginResponseSpec = resolved.loginResponseSpec;
|
|
27
|
+
this.userService =
|
|
28
|
+
options.userService ?? new UserService(database, this.userSpec);
|
|
16
29
|
this.organizationService = new OrganizationService(database);
|
|
30
|
+
if (options.userSpec) {
|
|
31
|
+
setAuthUserContextSpec(createUserContextSpec(this.userSpec));
|
|
32
|
+
}
|
|
17
33
|
this.mapRoutes(app);
|
|
18
34
|
}
|
|
19
35
|
mapRoutes(app) {
|
|
@@ -45,8 +61,8 @@ export class AuthController {
|
|
|
45
61
|
}
|
|
46
62
|
res.set("Content-Type", "application/json");
|
|
47
63
|
const deviceId = getAndSetDeviceIdCookie(req, res);
|
|
48
|
-
const loginResponse = await attemptLogin(this.database, email, password, deviceId, organization);
|
|
49
|
-
apiUtils.apiResponse(res, 200, { data: loginResponse },
|
|
64
|
+
const loginResponse = await attemptLogin(this.database, email, password, deviceId, organization, this.userService);
|
|
65
|
+
apiUtils.apiResponse(res, 200, { data: loginResponse }, this.loginResponseSpec);
|
|
50
66
|
}
|
|
51
67
|
async requestTokenUsingRefreshToken(req, res) {
|
|
52
68
|
const userContext = req.userContext;
|
|
@@ -66,7 +82,7 @@ export class AuthController {
|
|
|
66
82
|
}
|
|
67
83
|
async getUserContext(req, res) {
|
|
68
84
|
const userContext = req.userContext;
|
|
69
|
-
apiUtils.apiResponse(res, 200, { data: userContext },
|
|
85
|
+
apiUtils.apiResponse(res, 200, { data: userContext }, this.publicUserContextSpec);
|
|
70
86
|
}
|
|
71
87
|
afterAuth(_req, _res, _loginResponse) {
|
|
72
88
|
console.log("in afterAuth");
|
|
@@ -77,9 +93,9 @@ export class AuthController {
|
|
|
77
93
|
throw new BadRequestError("Missing required fields: userContext is required.");
|
|
78
94
|
}
|
|
79
95
|
const password = req.body?.password;
|
|
80
|
-
const validationErrors = entityUtils.validate(
|
|
96
|
+
const validationErrors = entityUtils.validate(this.userSpec, { password: password }, true, passwordValidator);
|
|
81
97
|
entityUtils.handleValidationResult(validationErrors, "AuthController.changePassword");
|
|
82
|
-
const updateResult = await changePassword(this.database, userContext, password);
|
|
98
|
+
const updateResult = await changePassword(this.database, userContext, password, this.userService);
|
|
83
99
|
apiUtils.apiResponse(res, 200, { data: updateResult });
|
|
84
100
|
}
|
|
85
101
|
async forgotPassword(req, res) {
|
|
@@ -127,7 +143,7 @@ export class AuthController {
|
|
|
127
143
|
throw new BadRequestError("Missing required fields: organization is required.");
|
|
128
144
|
}
|
|
129
145
|
}
|
|
130
|
-
const response = await resetPassword(this.database, email, token, password, organization);
|
|
146
|
+
const response = await resetPassword(this.database, email, token, password, organization, this.userService, this.userSpec);
|
|
131
147
|
apiUtils.apiResponse(res, 200, { data: response });
|
|
132
148
|
}
|
|
133
149
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { type IUser } from "@loomcore/common/models";
|
|
1
|
+
import { type IModelSpec, type IUser } from "@loomcore/common/models";
|
|
2
2
|
import type { Application } from "express";
|
|
3
3
|
import type { IDatabase } from "../databases/models/index.js";
|
|
4
4
|
import { UserService } from "../services/index.js";
|
|
5
5
|
import { ApiController } from "./api.controller.js";
|
|
6
|
+
export interface UsersControllerOptions {
|
|
7
|
+
userService?: UserService;
|
|
8
|
+
userSpec?: IModelSpec;
|
|
9
|
+
publicUserSpec?: IModelSpec;
|
|
10
|
+
}
|
|
6
11
|
export declare class UsersController extends ApiController<IUser> {
|
|
7
12
|
userService: UserService;
|
|
8
|
-
constructor(app: Application, database: IDatabase);
|
|
13
|
+
constructor(app: Application, database: IDatabase, options?: UsersControllerOptions);
|
|
9
14
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { PublicUserSpec, UserSpec } from "@loomcore/common/models";
|
|
1
|
+
import { PublicUserSpec, UserSpec, } from "@loomcore/common/models";
|
|
2
2
|
import { UserService } from "../services/index.js";
|
|
3
3
|
import { ApiController } from "./api.controller.js";
|
|
4
4
|
export class UsersController extends ApiController {
|
|
5
5
|
userService;
|
|
6
|
-
constructor(app, database) {
|
|
7
|
-
const
|
|
8
|
-
|
|
6
|
+
constructor(app, database, options = {}) {
|
|
7
|
+
const userSpec = options.userSpec ?? UserSpec;
|
|
8
|
+
const publicUserSpec = options.publicUserSpec ?? PublicUserSpec;
|
|
9
|
+
const userService = options.userService ?? new UserService(database, userSpec);
|
|
10
|
+
super("users", app, userService, "user", userSpec, publicUserSpec);
|
|
9
11
|
this.userService = userService;
|
|
10
12
|
}
|
|
11
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { UserContextSpec } from "@loomcore/common/models";
|
|
2
1
|
import jwt from "jsonwebtoken";
|
|
3
2
|
import { UnauthenticatedError, UnauthorizedError } from "../errors/index.js";
|
|
3
|
+
import { getAuthUserContextSpec } from "../utils/auth/auth-user-specs.util.js";
|
|
4
4
|
import { getAuthConfig } from "../utils/auth/get-auth-config.util.js";
|
|
5
5
|
const isAuthorized = (allowedFeatures) => {
|
|
6
6
|
return (req, _res, next) => {
|
|
@@ -18,7 +18,7 @@ const isAuthorized = (allowedFeatures) => {
|
|
|
18
18
|
const authConfig = getAuthConfig();
|
|
19
19
|
try {
|
|
20
20
|
const rawPayload = jwt.verify(token, authConfig.clientSecret);
|
|
21
|
-
const userContext =
|
|
21
|
+
const userContext = getAuthUserContextSpec().decode(rawPayload);
|
|
22
22
|
req.userContext = userContext;
|
|
23
23
|
if (userContext.authorizations.some((authorization) => authorization.feature === "admin")) {
|
|
24
24
|
next();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type IQueryOptions, type IUser, type IUserContext } from "@loomcore/common/models";
|
|
1
|
+
import { type IModelSpec, type IQueryOptions, type IUser, type IUserContext } from "@loomcore/common/models";
|
|
2
2
|
import type { AppIdType } from "@loomcore/common/types";
|
|
3
3
|
import type { IDatabase } from "../databases/models/index.js";
|
|
4
4
|
import { MultiTenantApiService } from "./multi-tenant-api.service.js";
|
|
5
5
|
export declare class UserService extends MultiTenantApiService<IUser> {
|
|
6
|
-
constructor(database: IDatabase);
|
|
6
|
+
constructor(database: IDatabase, modelSpec?: IModelSpec);
|
|
7
7
|
fullUpdateById(_userContext: IUserContext, _id: AppIdType, _entity: IUser): Promise<IUser>;
|
|
8
8
|
update(userContext: IUserContext, queryObject: IQueryOptions, entity: Partial<IUser>): Promise<IUser[]>;
|
|
9
9
|
batchUpdate(userContext: IUserContext, entities: Partial<IUser>[]): Promise<IUser[]>;
|
|
@@ -3,8 +3,8 @@ import { BadRequestError, ServerError } from "../errors/index.js";
|
|
|
3
3
|
import { passwordUtils } from "../utils/password.utils.js";
|
|
4
4
|
import { MultiTenantApiService } from "./multi-tenant-api.service.js";
|
|
5
5
|
export class UserService extends MultiTenantApiService {
|
|
6
|
-
constructor(database) {
|
|
7
|
-
super(database, "users", "user",
|
|
6
|
+
constructor(database, modelSpec = UserSpec) {
|
|
7
|
+
super(database, "users", "user", modelSpec);
|
|
8
8
|
}
|
|
9
9
|
async fullUpdateById(_userContext, _id, _entity) {
|
|
10
10
|
throw new ServerError("User full update is not allowed.");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { type ILoginResponse, type IOrganization } from "@loomcore/common/models";
|
|
2
2
|
import type { IDatabase } from "../../databases/models/index.js";
|
|
3
|
-
|
|
3
|
+
import { UserService } from "../../services/user.service.js";
|
|
4
|
+
export declare function attemptLogin(database: IDatabase, email: string, password: string, deviceId: string, organization: IOrganization | null, userService?: UserService): Promise<ILoginResponse | null>;
|
|
@@ -4,13 +4,12 @@ import { UserService } from "../../services/user.service.js";
|
|
|
4
4
|
import { getUserContextAuthorizations } from "../../services/utils/getUserContextAuthorizations.util.js";
|
|
5
5
|
import { passwordUtils } from "../password.utils.js";
|
|
6
6
|
import { logUserIn } from "./log-user-in.util.js";
|
|
7
|
-
export async function attemptLogin(database, email, password, deviceId, organization) {
|
|
7
|
+
export async function attemptLogin(database, email, password, deviceId, organization, userService = new UserService(database)) {
|
|
8
8
|
const lowerCaseEmail = email.toLowerCase();
|
|
9
9
|
const userContext = {
|
|
10
10
|
...EmptyUserContext,
|
|
11
11
|
organization: organization ?? undefined,
|
|
12
12
|
};
|
|
13
|
-
const userService = new UserService(database);
|
|
14
13
|
const user = await userService.findOne(userContext, {
|
|
15
14
|
filters: {
|
|
16
15
|
email: { eq: lowerCaseEmail },
|
|
@@ -29,7 +28,7 @@ export async function attemptLogin(database, email, password, deviceId, organiza
|
|
|
29
28
|
organization: organization ?? undefined,
|
|
30
29
|
authorizations: authorizations,
|
|
31
30
|
};
|
|
32
|
-
const tokens = await logUserIn(database, authenticatedUserContext, deviceId);
|
|
31
|
+
const tokens = await logUserIn(database, authenticatedUserContext, deviceId, userService);
|
|
33
32
|
return {
|
|
34
33
|
tokens,
|
|
35
34
|
userContext: authenticatedUserContext,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type IModelSpec } from "@loomcore/common/models";
|
|
2
|
+
export declare function createUserContextSpec(userModelSpec: IModelSpec): IModelSpec;
|
|
3
|
+
export declare function createLoginResponseSpec(publicUserContextSpec: IModelSpec): IModelSpec;
|
|
4
|
+
export declare function setAuthUserContextSpec(spec: IModelSpec): void;
|
|
5
|
+
export declare function getAuthUserContextSpec(): IModelSpec;
|
|
6
|
+
export declare function resetAuthUserContextSpec(): void;
|
|
7
|
+
export declare function resolveAuthUserSpecs(options: {
|
|
8
|
+
userSpec?: IModelSpec;
|
|
9
|
+
publicUserSpec?: IModelSpec;
|
|
10
|
+
}): {
|
|
11
|
+
userSpec: IModelSpec;
|
|
12
|
+
publicUserSpec: IModelSpec;
|
|
13
|
+
publicUserContextSpec: IModelSpec;
|
|
14
|
+
loginResponseSpec: IModelSpec;
|
|
15
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { OrganizationSpec, PublicUserSpec, TokenResponseSchema, UserContextAuthorizationSpec, UserContextSpec, UserSpec, } from "@loomcore/common/models";
|
|
2
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
3
|
+
import { Type } from "@sinclair/typebox";
|
|
4
|
+
export function createUserContextSpec(userModelSpec) {
|
|
5
|
+
return entityUtils.getModelSpec(Type.Object({
|
|
6
|
+
user: userModelSpec.fullSchema,
|
|
7
|
+
authorizations: Type.Array(UserContextAuthorizationSpec.fullSchema),
|
|
8
|
+
organization: OrganizationSpec.fullSchema,
|
|
9
|
+
}), { isEntity: false });
|
|
10
|
+
}
|
|
11
|
+
export function createLoginResponseSpec(publicUserContextSpec) {
|
|
12
|
+
return entityUtils.getModelSpec(Type.Object({
|
|
13
|
+
tokens: TokenResponseSchema,
|
|
14
|
+
userContext: publicUserContextSpec.fullSchema,
|
|
15
|
+
}), { isEntity: false });
|
|
16
|
+
}
|
|
17
|
+
let authUserContextSpec = UserContextSpec;
|
|
18
|
+
export function setAuthUserContextSpec(spec) {
|
|
19
|
+
authUserContextSpec = spec;
|
|
20
|
+
}
|
|
21
|
+
export function getAuthUserContextSpec() {
|
|
22
|
+
return authUserContextSpec;
|
|
23
|
+
}
|
|
24
|
+
export function resetAuthUserContextSpec() {
|
|
25
|
+
authUserContextSpec = UserContextSpec;
|
|
26
|
+
}
|
|
27
|
+
export function resolveAuthUserSpecs(options) {
|
|
28
|
+
const userSpec = options.userSpec ?? UserSpec;
|
|
29
|
+
const publicUserSpec = options.publicUserSpec ?? PublicUserSpec;
|
|
30
|
+
const publicUserContextSpec = createUserContextSpec(publicUserSpec);
|
|
31
|
+
const loginResponseSpec = createLoginResponseSpec(publicUserContextSpec);
|
|
32
|
+
return {
|
|
33
|
+
userSpec,
|
|
34
|
+
publicUserSpec,
|
|
35
|
+
publicUserContextSpec,
|
|
36
|
+
loginResponseSpec,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IUserContext } from "@loomcore/common/models";
|
|
2
2
|
import type { IDatabase } from "../../databases/models/index.js";
|
|
3
3
|
import type { UpdateResult } from "../../databases/models/update-result.js";
|
|
4
|
-
|
|
4
|
+
import { UserService } from "../../services/user.service.js";
|
|
5
|
+
export declare function changePassword(database: IDatabase, userContext: IUserContext, password: string, userService?: UserService): Promise<UpdateResult>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import moment from "moment";
|
|
2
2
|
import { UserService } from "../../services/user.service.js";
|
|
3
|
-
export async function changePassword(database, userContext, password) {
|
|
4
|
-
const userService = new UserService(database);
|
|
3
|
+
export async function changePassword(database, userContext, password, userService = new UserService(database)) {
|
|
5
4
|
const updates = {
|
|
6
5
|
password: password,
|
|
7
6
|
_lastPasswordChange: moment().utc().toDate(),
|
package/dist/utils/auth/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { ITokenResponse, IUserContext } from "@loomcore/common/models";
|
|
2
2
|
import type { IDatabase } from "../../databases/models/index.js";
|
|
3
|
-
|
|
3
|
+
import type { UserService } from "../../services/user.service.js";
|
|
4
|
+
export declare function logUserIn(database: IDatabase, userContext: IUserContext, deviceId: string, userService?: UserService): Promise<ITokenResponse>;
|
|
@@ -3,7 +3,7 @@ import { createNewRefreshToken } from "./create-new-refresh-token.util.js";
|
|
|
3
3
|
import { getAuthConfig } from "./get-auth-config.util.js";
|
|
4
4
|
import { getExpiresOnFromSeconds } from "./get-expires-on-from-seconds.util.js";
|
|
5
5
|
import { updateLastLoggedIn } from "./update-last-logged-in.util.js";
|
|
6
|
-
export async function logUserIn(database, userContext, deviceId) {
|
|
6
|
+
export async function logUserIn(database, userContext, deviceId, userService) {
|
|
7
7
|
const authConfig = getAuthConfig();
|
|
8
8
|
const accessToken = generateJwt(userContext);
|
|
9
9
|
const refreshTokenObject = await createNewRefreshToken(database, userContext.user._id, deviceId, userContext.organization?._id);
|
|
@@ -13,6 +13,6 @@ export async function logUserIn(database, userContext, deviceId) {
|
|
|
13
13
|
refreshToken: refreshTokenObject.token,
|
|
14
14
|
expiresOn: accessTokenExpiresOn,
|
|
15
15
|
};
|
|
16
|
-
updateLastLoggedIn(database, userContext.user._id).catch((err) => console.log(`Error updating lastLoggedIn: ${err}`));
|
|
16
|
+
updateLastLoggedIn(database, userContext.user._id, userService).catch((err) => console.log(`Error updating lastLoggedIn: ${err}`));
|
|
17
17
|
return tokenResponse;
|
|
18
18
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type IOrganization } from "@loomcore/common/models";
|
|
1
|
+
import { type IModelSpec, type IOrganization } from "@loomcore/common/models";
|
|
2
2
|
import type { IDatabase } from "../../databases/models/index.js";
|
|
3
3
|
import type { UpdateResult } from "../../databases/models/update-result.js";
|
|
4
|
-
|
|
4
|
+
import { UserService } from "../../services/user.service.js";
|
|
5
|
+
export declare function resetPassword(database: IDatabase, email: string, passwordResetToken: string, password: string, organization: IOrganization | null, userService?: UserService, userSpec?: IModelSpec): Promise<UpdateResult>;
|
|
@@ -4,12 +4,11 @@ import { BadRequestError, ServerError } from "../../errors/index.js";
|
|
|
4
4
|
import { PasswordResetTokenService } from "../../services/password-reset-token.service.js";
|
|
5
5
|
import { UserService } from "../../services/user.service.js";
|
|
6
6
|
import { changePassword } from "./change-password.util.js";
|
|
7
|
-
export async function resetPassword(database, email, passwordResetToken, password, organization) {
|
|
8
|
-
const validationErrors = entityUtils.validate(
|
|
7
|
+
export async function resetPassword(database, email, passwordResetToken, password, organization, userService = new UserService(database), userSpec = UserSpec) {
|
|
8
|
+
const validationErrors = entityUtils.validate(userSpec, { password: password }, true, passwordValidator);
|
|
9
9
|
entityUtils.handleValidationResult(validationErrors, "AuthService.resetPassword");
|
|
10
10
|
const lowerCaseEmail = email.toLowerCase();
|
|
11
11
|
const passwordResetTokenService = new PasswordResetTokenService(database);
|
|
12
|
-
const userService = new UserService(database);
|
|
13
12
|
const userContext = {
|
|
14
13
|
...EmptyUserContext,
|
|
15
14
|
organization: organization ?? undefined,
|
|
@@ -31,7 +30,7 @@ export async function resetPassword(database, email, passwordResetToken, passwor
|
|
|
31
30
|
throw new ServerError(`Unable to retrieve user for email: ${lowerCaseEmail}`);
|
|
32
31
|
}
|
|
33
32
|
userContext.user = user;
|
|
34
|
-
const result = await changePassword(database, userContext, password);
|
|
33
|
+
const result = await changePassword(database, userContext, password, userService);
|
|
35
34
|
console.log(`password changed using forgot-password for email: ${lowerCaseEmail}`);
|
|
36
35
|
await passwordResetTokenService.deleteById(userContext, retrievedPasswordResetToken._id);
|
|
37
36
|
console.log(`passwordResetToken deleted for email: ${lowerCaseEmail}`);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { AppIdType } from "@loomcore/common/types";
|
|
2
2
|
import type { IDatabase } from "../../databases/models/index.js";
|
|
3
|
-
|
|
3
|
+
import { UserService } from "../../services/user.service.js";
|
|
4
|
+
export declare function updateLastLoggedIn(database: IDatabase, userId: AppIdType, userService?: UserService): Promise<void>;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { getSystemUserContext } from "@loomcore/common/models";
|
|
2
2
|
import moment from "moment";
|
|
3
3
|
import { UserService } from "../../services/user.service.js";
|
|
4
|
-
export async function updateLastLoggedIn(database, userId) {
|
|
4
|
+
export async function updateLastLoggedIn(database, userId, userService = new UserService(database)) {
|
|
5
5
|
try {
|
|
6
6
|
const updates = {
|
|
7
7
|
_lastLoggedIn: moment().utc().toDate(),
|
|
8
8
|
};
|
|
9
|
-
const userService = new UserService(database);
|
|
10
9
|
await userService.update(getSystemUserContext(), { filters: { _id: { eq: userId } } }, updates);
|
|
11
10
|
}
|
|
12
11
|
catch (error) {
|