Skip to content

Commit

Permalink
fix: log error if duplicated user or invalid role
Browse files Browse the repository at this point in the history
  • Loading branch information
yxuo committed Feb 16, 2024
1 parent b5b0173 commit 54b7418
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 68 deletions.
4 changes: 2 additions & 2 deletions src/auth-google/auth-google.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OAuth2Client } from 'google-auth-library';
import { SocialInterface } from '../social/interfaces/social.interface';
import { AuthGoogleLoginDto } from './dto/auth-google-login.dto';
import { AllConfigType } from 'src/config/config.type';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';

@Injectable()
export class AuthGoogleService {
Expand Down Expand Up @@ -32,7 +32,7 @@ export class AuthGoogleService {
if (!data) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
user: 'wrongToken',
},
Expand Down
3 changes: 2 additions & 1 deletion src/auth-licensee/auth-licensee.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { AuthLicenseeLoginDto } from './dto/auth-licensee-login.dto';
import { AuthRegisterLicenseeDto } from './dto/auth-register-licensee.dto';
import { IALConcludeRegistration } from './interfaces/al-conclude-registration.interface';
import { IALInviteProfile } from './interfaces/al-invite-profile.interface';
import { RoleEnum } from 'src/roles/roles.enum';

@ApiTags('Auth')
@Controller({
Expand All @@ -34,7 +35,7 @@ export class AuthLicenseeController {
@Body()
loginDto: AuthLicenseeLoginDto,
): Promise<LoginResponseType> {
return this.authLicenseeService.validateLogin(loginDto, false);
return this.authLicenseeService.validateLogin(loginDto, RoleEnum.user);
}

@Post('invite/:hash')
Expand Down
105 changes: 67 additions & 38 deletions src/auth-licensee/auth-licensee.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import * as bcrypt from 'bcryptjs';
import { AuthProvidersEnum } from 'src/auth/auth-providers.enum';
import { InviteStatusEnum } from 'src/mail-history-statuses/mail-history-status.enum';
import { MailHistoryService } from 'src/mail-history/mail-history.service';
import { MailService } from 'src/mail/mail.service';
import { RoleEnum } from 'src/roles/roles.enum';
import { Status } from 'src/statuses/entities/status.entity';
import { StatusEnum } from 'src/statuses/statuses.enum';
import { User } from 'src/users/entities/user.entity';
import { UsersService } from 'src/users/users.service';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';
import { CommonHttpException } from 'src/utils/http-exception/common-http-exception';
import { LoginResponseType } from 'src/utils/types/auth/login-response.type';
import { BaseValidator } from 'src/utils/validators/base-validator';
import { NullableType } from '../utils/types/nullable.type';
import { AuthLicenseeLoginDto } from './dto/auth-licensee-login.dto';
import { AuthRegisterLicenseeDto } from './dto/auth-register-licensee.dto';
import { IALConcludeRegistration } from './interfaces/al-conclude-registration.interface';
Expand All @@ -27,43 +28,26 @@ export class AuthLicenseeService {
private jwtService: JwtService,
private usersService: UsersService,
private mailHistoryService: MailHistoryService,
private baseValidator: BaseValidator,
private mailService: MailService,
) {}

async validateLogin(
loginDto: AuthLicenseeLoginDto,
onlyAdmin: boolean,
role: RoleEnum,
): Promise<LoginResponseType> {
const user = await this.usersService.findOne({
const user = await this.usersService.getOne({
permitCode: loginDto.permitCode,
});

if (
!user ||
(user?.role &&
!(onlyAdmin ? [RoleEnum.admin] : [RoleEnum.user]).includes(
user.role.id,
))
) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
details: {
email: 'notFound',
},
},
HttpStatus.UNAUTHORIZED,
);
}
await this.validateDuplicatedUser(user);
this.validateRole(user, role);

if (
user?.status?.id === undefined ||
user?.status?.id !== StatusEnum.active
) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
status: 'notActive',
},
Expand All @@ -75,7 +59,7 @@ export class AuthLicenseeService {
if (user.provider !== AuthProvidersEnum.email) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
email: `needLoginViaProvider:${user.provider}`,
},
Expand All @@ -90,13 +74,9 @@ export class AuthLicenseeService {
);

if (!isValidPassword) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
details: {
password: 'incorrectPassword',
},
},
throw CommonHttpException.simpleDetail(
'password',
'incorrectPassword',
HttpStatus.UNAUTHORIZED,
);
}
Expand All @@ -109,13 +89,62 @@ export class AuthLicenseeService {
return { token, user };
}

validateRole(user: User, role: RoleEnum) {
if (!user?.role || user.role.id !== role) {
throw new HttpException(
{
error: HttpStatusMessage.UNAUTHORIZED,
details: {
user: {
error: 'invalidRole',
role: user?.role?.id,
expectedRole: role,
},
},
},
HttpStatus.UNAUTHORIZED,
);
}
}

async validateDuplicatedUser(user: NullableType<User>) {
if (!user) {
return;
}
const duplicatedMail = user.email
? await this.usersService.findMany({ email: user.email })
: [];
const duplicatedPermitCode = user.permitCode
? await this.usersService.findMany({ permitCode: user.permitCode })
: [];
if (duplicatedMail.length > 1 || duplicatedPermitCode.length > 1) {
throw new HttpException(
{
error: HttpStatusMessage.UNAUTHORIZED,
details: {
...(duplicatedMail.length > 1
? { email: 'duplicated', emailValue: duplicatedMail[0]?.email }
: {}),
...(duplicatedPermitCode.length > 1
? {
permitCode: 'duplicated',
permitCodeValue: duplicatedPermitCode[0]?.permitCode,
}
: {}),
},
},
HttpStatus.UNAUTHORIZED,
);
}
}

async getInviteProfile(hash: string): Promise<IALInviteProfile> {
const invite = await this.mailHistoryService.getOne({ hash });

if (invite.inviteStatus.id !== InviteStatusEnum.sent) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
invite: {
inviteStatus: `Invite is not 'sent' yet`,
Expand All @@ -136,7 +165,7 @@ export class AuthLicenseeService {
) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
user: {
...(user.id !== invite.user.id && {
Expand Down Expand Up @@ -171,7 +200,7 @@ export class AuthLicenseeService {
if (!invite) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
invite: {
hash: 'inviteHashNotFound',
Expand All @@ -185,7 +214,7 @@ export class AuthLicenseeService {
if (invite.inviteStatus.id !== InviteStatusEnum.sent) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
invite: {
inviteStatus: `inviteAlreadyUsed'`,
Expand All @@ -205,7 +234,7 @@ export class AuthLicenseeService {
) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
user: {
...(user.id !== invite.user.id && {
Expand Down
4 changes: 2 additions & 2 deletions src/auth-licensee/dto/auth-licensee-login.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HttpStatus } from '@nestjs/common';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, Validate } from 'class-validator';
import { customValidationOptions } from 'src/utils/all-exteptions-filter/custom-validation-options';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';
import { IsExist } from 'src/utils/validators/is-exists.validator';

export class AuthLicenseeLoginDto {
Expand All @@ -13,7 +13,7 @@ export class AuthLicenseeLoginDto {
['User'],
customValidationOptions({
statusCode: HttpStatus.UNAUTHORIZED,
message: HttpErrorMessages.UNAUTHORIZED,
message: HttpStatusMessage.UNAUTHORIZED,
details: 'permitCodeNotExists',
}),
)
Expand Down
14 changes: 7 additions & 7 deletions src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { SocialInterface } from 'src/social/interfaces/social.interface';
import { Status } from 'src/statuses/entities/status.entity';
import { StatusEnum } from 'src/statuses/statuses.enum';
import { UsersService } from 'src/users/users.service';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';
import { formatLog } from 'src/utils/logging';
import { User } from '../users/entities/user.entity';
import { LoginResponseType } from '../utils/types/auth/login-response.type';
Expand Down Expand Up @@ -56,7 +56,7 @@ export class AuthService {
) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
email: 'notFound',
},
Expand All @@ -68,7 +68,7 @@ export class AuthService {
if (user.provider !== AuthProvidersEnum.email) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
email: `needLoginViaProvider:${user.provider}`,
},
Expand All @@ -85,7 +85,7 @@ export class AuthService {
if (!isValidPassword) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
password: 'incorrectPassword',
},
Expand Down Expand Up @@ -155,7 +155,7 @@ export class AuthService {
if (!user) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
user: 'userNotFound',
},
Expand Down Expand Up @@ -408,7 +408,7 @@ export class AuthService {
else {
throw new HttpException(
{
error: HttpErrorMessages.INTERNAL_SERVER_ERROR,
error: HttpStatusMessage.INTERNAL_SERVER_ERROR,
details: {
mailSentInfo: mailSentInfo,
},
Expand All @@ -432,7 +432,7 @@ export class AuthService {
if (!forgot) {
throw new HttpException(
{
error: HttpErrorMessages.UNAUTHORIZED,
error: HttpStatusMessage.UNAUTHORIZED,
details: {
error: 'hash not found',
hash,
Expand Down
4 changes: 2 additions & 2 deletions src/mail-history/mail-history.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { IMailHistoryStatusCount } from 'src/mail-history-statuses/interfaces/ma
import { InviteStatusEnum } from 'src/mail-history-statuses/mail-history-status.enum';
import { RoleEnum } from 'src/roles/roles.enum';
import { User } from 'src/users/entities/user.entity';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';
import { formatLog } from 'src/utils/logging';
import { EntityCondition } from 'src/utils/types/entity-condition.type';
import { NullableType } from 'src/utils/types/nullable.type';
Expand Down Expand Up @@ -175,7 +175,7 @@ export class MailHistoryService {
if (!invite) {
throw new HttpException(
{
error: HttpErrorMessages.NOT_FOUND,
error: HttpStatusMessage.NOT_FOUND,
},
HttpStatus.NOT_FOUND,
);
Expand Down
6 changes: 3 additions & 3 deletions src/mail-history/pipes/mail-history-validation.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
ValidationPipeOptions,
} from '@nestjs/common';
import { InviteStatusEnum } from 'src/mail-history-statuses/mail-history-status.enum';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';
import { MailHistoryService } from '../mail-history.service';

@Injectable()
Expand All @@ -31,7 +31,7 @@ export class MailHistoryValidationPipe extends ValidationPipe {
if (!inviteFound) {
throw new HttpException(
{
message: HttpErrorMessages.UNAUTHORIZED,
message: HttpStatusMessage.UNAUTHORIZED,
details: {
[fieldName]: 'invalid invite hash',
},
Expand All @@ -41,7 +41,7 @@ export class MailHistoryValidationPipe extends ValidationPipe {
} else if (inviteFound.getMailStatus() === InviteStatusEnum.used) {
throw new HttpException(
{
message: HttpErrorMessages.UNAUTHORIZED,
message: HttpStatusMessage.UNAUTHORIZED,
details: {
inviteStatus: "is already 'sent'. Cant be reused.",
},
Expand Down
10 changes: 5 additions & 5 deletions src/settings/entities/setting.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HttpException, HttpStatus } from '@nestjs/common';
import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';
import { SettingType } from 'src/setting-types/entities/setting-type.entity';
import { HttpErrorMessages } from 'src/utils/enums/http-error-messages.enum';
import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum';
import {
BaseEntity,
Column,
Expand Down Expand Up @@ -62,7 +62,7 @@ export class SettingEntity extends BaseEntity {
} catch (error) {
throw new HttpException(
{
error: HttpErrorMessages.INTERNAL_SERVER_ERROR,
error: HttpStatusMessage.INTERNAL_SERVER_ERROR,
details: {
value: `should be valid JSON, received '${this.value}' instead`,
},
Expand All @@ -79,7 +79,7 @@ export class SettingEntity extends BaseEntity {
} else {
throw new HttpException(
{
error: HttpErrorMessages.INTERNAL_SERVER_ERROR,
error: HttpStatusMessage.INTERNAL_SERVER_ERROR,
details: {
value: 'should not be null',
},
Expand Down Expand Up @@ -108,7 +108,7 @@ export class SettingEntity extends BaseEntity {
} else {
throw new HttpException(
{
error: HttpErrorMessages.INTERNAL_SERVER_ERROR,
error: HttpStatusMessage.INTERNAL_SERVER_ERROR,
details: {
value: 'should not be null',
},
Expand All @@ -122,7 +122,7 @@ export class SettingEntity extends BaseEntity {
if (!this?.value) {
throw new HttpException(
{
error: HttpErrorMessages.INTERNAL_SERVER_ERROR,
error: HttpStatusMessage.INTERNAL_SERVER_ERROR,
details: {
value: 'should not be null',
},
Expand Down
Loading

0 comments on commit 54b7418

Please sign in to comment.