forked from Yara724/api
Fix 404 for invalid email of actors, added APIs for client settings
This commit is contained in:
@@ -31,7 +31,6 @@ import {
|
||||
LegalRegisterDto,
|
||||
} from "src/auth/dto/actor/register.actor.dto";
|
||||
import { LocalActorAuthGuard } from "src/auth/guards/actor-local.guard";
|
||||
import { ClientKey } from "src/decorators/clientKey.decorator";
|
||||
import { Roles } from "src/decorators/roles.decorator";
|
||||
import { CurrentUser } from "src/decorators/user.decorator";
|
||||
|
||||
@@ -136,9 +135,17 @@ export class ActorAuthController {
|
||||
},
|
||||
},
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 404,
|
||||
description: "No actor account exists for the given email and role",
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 401,
|
||||
description: "Wrong password or role mismatch",
|
||||
})
|
||||
@ApiAcceptedResponse()
|
||||
async login(@Body() body, @Req() req, @ClientKey() client) {
|
||||
return await this.actorAuthService.loginActors(req.user);
|
||||
async login(@Req() req: { user: Record<string, unknown> }) {
|
||||
return req.user;
|
||||
}
|
||||
|
||||
@Post("forget-password")
|
||||
|
||||
@@ -97,48 +97,95 @@ export class ActorAuthService {
|
||||
return res;
|
||||
}
|
||||
|
||||
async validateActor(username: string, pass: string, role): Promise<any> {
|
||||
const user = await this.dynamicDbController(role, username);
|
||||
if (user) {
|
||||
if (user.role !== role) {
|
||||
throw new UnauthorizedException("user not assigned to this role");
|
||||
}
|
||||
if (!(await this.hashService.compare(pass, user.password))) {
|
||||
throw new UnauthorizedException(
|
||||
"password is incorrect or access Denied",
|
||||
);
|
||||
} else {
|
||||
return user;
|
||||
}
|
||||
/** Normalizes `role` from login body (string or single-element array). */
|
||||
parseActorLoginRole(role: unknown): RoleEnum {
|
||||
const raw = Array.isArray(role) ? role[0] : role;
|
||||
if (
|
||||
typeof raw !== "string" ||
|
||||
!Object.values(RoleEnum).includes(raw as RoleEnum)
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Invalid role. Expected one of: ${Object.values(RoleEnum).join(", ")}`,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
return raw as RoleEnum;
|
||||
}
|
||||
|
||||
async loginActors(user: any) {
|
||||
let foundedUser = await this.dynamicDbController(user.role, user.username);
|
||||
if (foundedUser) {
|
||||
const payload = {
|
||||
username: foundedUser.username || foundedUser.email,
|
||||
sub: foundedUser._id,
|
||||
fullName:
|
||||
`${foundedUser.firstName || ""} ${foundedUser.lastName || ""}`.trim(),
|
||||
role: foundedUser.role || "User",
|
||||
userType: foundedUser.userType || "UserType",
|
||||
clientKey: foundedUser.clientKey || null,
|
||||
};
|
||||
|
||||
const accToken = this.jwtService.sign(payload, {
|
||||
secret: `${process.env.SECRET}`,
|
||||
expiresIn: "1h",
|
||||
});
|
||||
|
||||
return {
|
||||
...payload,
|
||||
access_token: accToken,
|
||||
};
|
||||
} else {
|
||||
throw new UnauthorizedException("expert or damage_expert not found");
|
||||
parseActorLoginUsername(body: Record<string, unknown>): string {
|
||||
const username = body?.username ?? body?.email;
|
||||
if (typeof username !== "string" || !username.trim()) {
|
||||
throw new BadRequestException("username (email) is required");
|
||||
}
|
||||
return username.trim();
|
||||
}
|
||||
|
||||
issueActorTokens(actor: {
|
||||
_id: Types.ObjectId;
|
||||
username?: string;
|
||||
email?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
role?: string;
|
||||
userType?: string;
|
||||
clientKey?: Types.ObjectId | string | null;
|
||||
}) {
|
||||
const payload = {
|
||||
username: actor.username || actor.email,
|
||||
sub: actor._id,
|
||||
fullName: `${actor.firstName || ""} ${actor.lastName || ""}`.trim(),
|
||||
role: actor.role || "User",
|
||||
userType: actor.userType || "UserType",
|
||||
clientKey: actor.clientKey ?? null,
|
||||
};
|
||||
|
||||
const access_token = this.jwtService.sign(payload, {
|
||||
secret: `${process.env.SECRET}`,
|
||||
expiresIn: "1h",
|
||||
});
|
||||
|
||||
return { ...payload, access_token };
|
||||
}
|
||||
|
||||
async validateActor(
|
||||
username: string,
|
||||
pass: string,
|
||||
role: RoleEnum,
|
||||
): Promise<any> {
|
||||
const user = await this.dynamicDbController(role, username);
|
||||
if (!user) {
|
||||
throw new NotFoundException("Actor account not found");
|
||||
}
|
||||
if (user.role !== role) {
|
||||
throw new UnauthorizedException("user not assigned to this role");
|
||||
}
|
||||
if (!(await this.hashService.compare(pass, user.password))) {
|
||||
throw new UnauthorizedException(
|
||||
"password is incorrect or access Denied",
|
||||
);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates an actor from a login request body (role, username/email, password).
|
||||
*/
|
||||
async loginFromCredentials(body: Record<string, unknown>) {
|
||||
const role = this.parseActorLoginRole(body?.role);
|
||||
const username = this.parseActorLoginUsername(body);
|
||||
const password = body?.password;
|
||||
if (typeof password !== "string" || !password) {
|
||||
throw new BadRequestException("password is required");
|
||||
}
|
||||
const actor = await this.validateActor(username, password, role);
|
||||
return this.issueActorTokens(actor);
|
||||
}
|
||||
|
||||
/** @deprecated Prefer {@link loginFromCredentials}. Kept for internal callers. */
|
||||
async loginActors(user: any) {
|
||||
if (user?.access_token && user?.sub) {
|
||||
return user;
|
||||
}
|
||||
return this.loginFromCredentials(user as Record<string, unknown>);
|
||||
}
|
||||
|
||||
async registerActors(
|
||||
|
||||
@@ -23,10 +23,12 @@ export class LocalActorAuthGuard extends AuthGuard("actor") {
|
||||
const path = request.url;
|
||||
|
||||
if (!token) {
|
||||
if (path === "/actor/login") {
|
||||
const loginData = await this.actorAuthService.loginActors(request.body);
|
||||
if (this.isActorLoginRequest(request)) {
|
||||
const loginData = await this.actorAuthService.loginFromCredentials(
|
||||
request.body ?? {},
|
||||
);
|
||||
request.user = loginData;
|
||||
request.identity = request;
|
||||
request.identity = loginData;
|
||||
return true;
|
||||
} else {
|
||||
throw new UnauthorizedException("Token not found");
|
||||
@@ -59,6 +61,17 @@ export class LocalActorAuthGuard extends AuthGuard("actor") {
|
||||
return true;
|
||||
}
|
||||
|
||||
private isActorLoginRequest(request: {
|
||||
url?: string;
|
||||
path?: string;
|
||||
route?: { path?: string };
|
||||
}): boolean {
|
||||
const path = (request.route?.path ?? request.url ?? request.path ?? "")
|
||||
.split("?")[0]
|
||||
.replace(/\/+$/, "");
|
||||
return path === "/actor/login" || path.endsWith("/actor/login");
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
//@ts-ignore
|
||||
const [type, token] = request.headers.authorization?.split(" ") ?? [];
|
||||
|
||||
Reference in New Issue
Block a user