Skip to content

Commit

Permalink
fix: resolve PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Dzeranov committed Jan 29, 2025
1 parent e83c8ae commit 2fe5cec
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
import { SignatureAuthGuard } from './signature.auth';
import { verifySignature } from '../utils/signature';
import { signMessage } from '../utils/signature';
import { ChainId, EscrowUtils } from '@human-protocol/sdk';
import { MOCK_ADDRESS } from '../../../test/constants';
import { MOCK_ADDRESS, MOCK_PRIVATE_KEY } from '../../../test/constants';
import { AuthSignatureRole } from '../enums/role';

jest.mock('../../common/utils/signature');

jest.mock('@human-protocol/sdk', () => ({
...jest.requireActual('@human-protocol/sdk'),
EscrowUtils: {
getEscrow: jest.fn().mockResolvedValue({
launcher: '0x1234567890123456789012345678901234567890',
exchangeOracle: '0x1234567890123456789012345678901234567891',
reputationOracle: '0x1234567890123456789012345678901234567892',
}),
getEscrow: jest.fn(),
},
}));

Expand All @@ -37,6 +31,11 @@ describe('SignatureAuthGuard', () => {
}).compile();

guard = module.get<SignatureAuthGuard>(SignatureAuthGuard);
EscrowUtils.getEscrow = jest.fn().mockResolvedValueOnce({
launcher: MOCK_ADDRESS,
exchangeOracle: MOCK_ADDRESS,
reputationOracle: MOCK_ADDRESS,
});
});

it('should be defined', () => {
Expand All @@ -62,13 +61,13 @@ describe('SignatureAuthGuard', () => {
});

it('should return true if signature is verified', async () => {
mockRequest.headers['header-signature-key'] = 'validSignature';
mockRequest.body = {
const body = {
escrow_address: MOCK_ADDRESS,
chain_id: ChainId.LOCALHOST,
};
(verifySignature as jest.Mock).mockReturnValue(true);

const signature = await signMessage(body, MOCK_PRIVATE_KEY);
mockRequest.headers['human-signature'] = signature;
mockRequest.body = body;
const result = await guard.canActivate(context as any);
expect(result).toBeTruthy();
expect(EscrowUtils.getEscrow).toHaveBeenCalledWith(
Expand All @@ -78,34 +77,36 @@ describe('SignatureAuthGuard', () => {
});

it('should throw unauthorized exception if signature is not verified', async () => {
(verifySignature as jest.Mock).mockReturnValueOnce(false);

let catchedError;
try {
await guard.canActivate(context as any);
} catch (error) {
expect(error).toBeInstanceOf(HttpException);
expect(error.response).toHaveProperty(
'message',
'Invalid web3 signature',
);
expect(error.response).toHaveProperty('timestamp');
expect(error).toHaveProperty('status', HttpStatus.UNAUTHORIZED);
catchedError = error;
}
expect(catchedError).toBeInstanceOf(HttpException);
expect(catchedError.response).toHaveProperty(
'message',
'Invalid web3 signature',
);
expect(catchedError.response).toHaveProperty('timestamp');
expect(catchedError).toHaveProperty('status', HttpStatus.UNAUTHORIZED);
});

it('should throw unauthorized exception for unrecognized oracle type', async () => {
mockRequest.originalUrl = '/some/random/path';
let catchedError;
try {
await guard.canActivate(context as any);
} catch (error) {
expect(error).toBeInstanceOf(HttpException);
expect(error.response).toHaveProperty(
'message',
'Invalid web3 signature',
);
expect(error.response).toHaveProperty('timestamp');
expect(error).toHaveProperty('status', HttpStatus.UNAUTHORIZED);
catchedError = error;
}
expect(catchedError).toBeInstanceOf(HttpException);
expect(catchedError.response).toHaveProperty(
'message',
'Invalid web3 signature',
);
expect(catchedError.response).toHaveProperty('timestamp');
expect(catchedError).toHaveProperty('status', HttpStatus.UNAUTHORIZED);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,23 @@ import { Request, Response } from 'express';

import {
AuthError,
DuplicatedUserAddressError,
DuplicatedUserEmailError,
InvalidOperatorSignupDataError,
} from './auth.error';

type AuthControllerError =
| AuthError
| DuplicatedUserEmailError
| InvalidOperatorSignupDataError;
| InvalidOperatorSignupDataError
| DuplicatedUserAddressError;

@Catch(AuthError, DuplicatedUserEmailError, InvalidOperatorSignupDataError)
@Catch(
AuthError,
DuplicatedUserEmailError,
DuplicatedUserAddressError,
InvalidOperatorSignupDataError,
)
export class AuthControllerErrorsFilter implements ExceptionFilter {
private logger = new Logger(AuthControllerErrorsFilter.name);
catch(exception: AuthControllerError, host: ArgumentsHost) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ export class UserErrorFilter implements ExceptionFilter {

if (exception instanceof DuplicatedWalletAddressError) {
status = HttpStatus.CONFLICT;
} else if (exception instanceof InvalidWeb3SignatureError) {
status = HttpStatus.CONFLICT;
}

this.logger.error(exception.message, exception.stack, exception.userId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export class UserService {
user: UserEntity,
data: RegisterAddressRequestDto,
): Promise<KycSignedAddressDto> {
data.address = data.address.toLowerCase();
const lowercasedAddress = data.address.toLocaleLowerCase();

if (user.evmAddress) {
throw new UserError(UserErrorMessage.ADDRESS_EXISTS, user.id);
Expand All @@ -158,31 +158,32 @@ export class UserService {
throw new UserError(UserErrorMessage.KYC_NOT_APPROVED, user.id);
}

const dbUser = await this.userRepository.findOneByAddress(data.address);
const dbUser =
await this.userRepository.findOneByAddress(lowercasedAddress);
if (dbUser) {
throw new DuplicatedWalletAddressError(user.id, data.address);
throw new DuplicatedWalletAddressError(user.id, lowercasedAddress);
}

// Prepare signed data and verify the signature
const signedData = prepareSignatureBody({
from: data.address,
from: lowercasedAddress,
to: this.web3Service.getOperatorAddress(),
contents: SignatureType.REGISTER_ADDRESS,
});
const verified = verifySignature(signedData, data.signature, [
data.address,
lowercasedAddress,
]);

if (!verified) {
throw new InvalidWeb3SignatureError(user.id, data.address);
throw new InvalidWeb3SignatureError(user.id, lowercasedAddress);
}

user.evmAddress = data.address.toLowerCase();
user.evmAddress = lowercasedAddress;
await this.userRepository.updateOne(user);

const signature = await this.web3Service
.getSigner(this.networkConfigService.networks[0].chainId)
.signMessage(data.address);
.signMessage(lowercasedAddress);

return {
key: `KYC-${this.web3Service.getOperatorAddress()}`,
Expand Down

0 comments on commit 2fe5cec

Please sign in to comment.