Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ham 8 backend implementation #192

Merged
merged 8 commits into from
Jul 5, 2024
3 changes: 2 additions & 1 deletion packages/apps/human-app/server/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ HCAPTCHA_LABELING_STATS_API_URL= # string
HCAPTCHA_LABELING_VERIFY_API_URL= # string
HCAPTCHA_LABELING_API_KEY= # string
IS_AXIOS_REQUEST_LOGGING_ENABLED= #string, true if enabled, disabled otherwise
# CACHE TTL VALUES
# CACHE TTL VALUES - in seconds
CACHE_TTL_ORACLE_DISCOVERY= # number, example: 43200
CACHE_TTL_ORACLE_STATS= # number, example: 900
CACHE_TTL_USER_STATS= # number, example: 86400
Expand All @@ -27,3 +27,4 @@ E2E_TESTING_ESCROW_CHAIN_ID= # number
CORS_ALLOWED_ORIGIN= # string example: http://localhost:5173
CORS_ALLOWED_HEADERS= # string, example: 'Content-Type,Authorization,X-Requested-With,Accept,Origin'
CORS_ENABLED= # boolean, example: true
IS_CACHE_TO_RESTART= # boolean, example: false
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class EnvironmentConfigService {
return this.configService.getOrThrow<string>('RPC_URL');
}
get isCorsEnabled(): boolean {
return this.configService.get<boolean>('CORS_ENABLED', false);
return this.configService.get<string>('CORS_ENABLED') === 'true';
}
get corsEnabledOrigin(): string {
return this.configService.get<string>(
Expand Down Expand Up @@ -107,4 +107,7 @@ export class EnvironmentConfigService {
const chainIds = this.configService.getOrThrow<string>('CHAIN_IDS_ENABLED');
return chainIds.split(',').map((id) => id.trim());
}
get isCacheToRestart(): boolean {
return this.configService.get('IS_CACHE_TO_RESTART') === 'true';
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { createParamDecorator, ExecutionContext, HttpException, UnauthorizedException } from '@nestjs/common';
import {
BadRequestException,
createParamDecorator,
ExecutionContext,
UnauthorizedException,
} from '@nestjs/common';
import { jwtDecode } from 'jwt-decode';
import { JwtUserData } from '../utils/jwt-token.model';

Expand All @@ -24,7 +29,7 @@ export const JwtPayload = createParamDecorator(
return decoded as JwtUserData;
} catch (error) {
console.error('Error in decoding token: ', error);
return null;
throw new BadRequestException();
}
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export class JwtUserData {
@AutoMap()
userId: string;
@AutoMap()
address: string;
wallet_address: string;
@AutoMap()
email: string;
@AutoMap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,9 @@ export class KvStoreGateway {
400,
);
} else {
await this.cacheManager.set(
this.cachePrefix + address,
fetchedUrl,
this.configService.cacheTtlExchangeOracleUrl,
);
await this.cacheManager.set(this.cachePrefix + address, fetchedUrl, {
ttl: this.configService.cacheTtlExchangeOracleUrl,
} as any);
return fetchedUrl;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('KvStoreGateway', () => {
expect(cacheManager.set).toHaveBeenCalledWith(
service.cachePrefix + testAddress,
expectedUrl,
configService.cacheTtlExchangeOracleUrl,
{ ttl: configService.cacheTtlExchangeOracleUrl },
);
expect(cacheManager.get).toHaveBeenCalledWith(service.cachePrefix + testAddress);
expect(result).toBe(expectedUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,23 @@ export class ReputationOracleProfile extends AutomapperProfile {
createMap(mapper, PrepareSignatureCommand, PrepareSignatureData);
createMap(mapper, SigninOperatorCommand, SigninOperatorData);
createMap(mapper, DisableOperatorParams, DisableOperatorData);
createMap(mapper, ForgotPasswordCommand, ForgotPasswordData);
createMap(
mapper,
ForgotPasswordCommand,
ForgotPasswordData,
namingConventions({
source: new CamelCaseNamingConvention(),
destination: new SnakeCaseNamingConvention(),
}),
);
createMap(
mapper,
ResendEmailVerificationParams,
ResendEmailVerificationData,
namingConventions({
source: new CamelCaseNamingConvention(),
destination: new SnakeCaseNamingConvention(),
}),
);
createMap(mapper, EmailVerificationCommand, EmailVerificationData);
createMap(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import {
emailVerificationCommandFixture,
emailVerificationDataFixture,
resendEmailVerificationCommandFixture,
resendEmailVerificationCommandFixture, resendEmailVerificationDataFixture,
} from '../../../modules/email-confirmation/spec/email-verification.fixtures';
import {
ResendEmailVerificationCommand,
Expand Down Expand Up @@ -358,9 +358,8 @@ describe('ReputationOracleGateway', () => {
it('should successfully call the reputation oracle endpoint', async () => {
const command: ResendEmailVerificationCommand =
resendEmailVerificationCommandFixture;
const data: ResendEmailVerificationData = {
...command.data,
};
const data: ResendEmailVerificationData =
resendEmailVerificationDataFixture;
nock('https://example.com')
.post('/auth/resend-email-verification', {
...data,
Expand Down
7 changes: 6 additions & 1 deletion packages/apps/human-app/server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { ConfigService } from '@nestjs/config';
import { Logger, ValidationPipe } from '@nestjs/common';
import { EnvironmentConfigService } from './common/config/environment-config.service';
import { GlobalExceptionsFilter } from './common/filter/global-exceptions.filter';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

async function bootstrap() {
const logger = new Logger('bootstrap');
Expand All @@ -30,7 +32,10 @@ async function bootstrap() {

const host = envConfigService.host;
const port = envConfigService.port;

if (envConfigService.isCacheToRestart) {
const cacheManager: Cache = app.get<Cache>(CACHE_MANAGER);
await cacheManager.reset();
}
app.useGlobalFilters(new GlobalExceptionsFilter());
app.useGlobalPipes(new ValidationPipe({ transform: true }));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { Injectable } from '@nestjs/common';
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
import { createMap, forMember, Mapper, mapWith } from '@automapper/core';
import {
CamelCaseNamingConvention,
createMap,
forMember,
Mapper,
mapWith,
namingConventions,
SnakeCaseNamingConvention,
} from '@automapper/core';
import {
EmailVerificationCommand,
EmailVerificationData,
Expand Down Expand Up @@ -41,6 +49,10 @@ export class EmailConfirmationProfile extends AutomapperProfile {
mapper,
ResendEmailVerificationDto,
ResendEmailVerificationParams,
namingConventions({
destination: new CamelCaseNamingConvention(),
source: new SnakeCaseNamingConvention(),
}),
);
createMap(
mapper,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import { AutoMap } from '@automapper/classes';
import { IsEmail } from 'class-validator';
import { IsEmail, IsString } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class ResendEmailVerificationDto {
@AutoMap()
@IsEmail()
@ApiProperty({ example: 'string' })
email: string;
@AutoMap()
@IsString()
@ApiProperty({ example: 'string' })
h_captcha_token: string;
}

export class ResendEmailVerificationParams {
@AutoMap()
email: string;
@AutoMap()
hCaptchaToken: string;
}
export class ResendEmailVerificationCommand {
@AutoMap()
Expand All @@ -22,4 +28,6 @@ export class ResendEmailVerificationCommand {
export class ResendEmailVerificationData {
@AutoMap()
email: string;
@AutoMap()
h_captcha_token: string;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
ResendEmailVerificationCommand,
ResendEmailVerificationCommand, ResendEmailVerificationData,
ResendEmailVerificationDto,
ResendEmailVerificationParams,
} from '../model/resend-email-verification.model';
Expand All @@ -25,13 +25,19 @@ export const emailVerificationDataFixture: EmailVerificationData = {
export const emailVerificationToken = TOKEN;
export const resendEmailVerificationDtoFixture: ResendEmailVerificationDto = {
email: EMAIL,
h_captcha_token: TOKEN,
};
export const resendEmailVerificationParamsFixture: ResendEmailVerificationParams =
{
email: EMAIL,
hCaptchaToken: TOKEN,
};
export const resendEmailVerificationCommandFixture: ResendEmailVerificationCommand =
{
data: resendEmailVerificationParamsFixture,
token: TOKEN,
};
export const resendEmailVerificationDataFixture: ResendEmailVerificationData = {
email: EMAIL,
h_captcha_token: TOKEN,
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class HCaptchaMapperProfile extends AutomapperProfile {
),
forMember(
(destination) => destination.secret,
mapFrom((source) => source.address),
mapFrom((source) => source.wallet_address),
),
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ export class HCaptchaService {
): Promise<DailyHmtSpentResponse> {
this.checkIfHcaptchaSitekeyPresent(command.siteKey);
let dailyHmtSpent = await this.cacheManager.get<DailyHmtSpentResponse>(
this.dailyHmtSpentCacheKey
this.dailyHmtSpentCacheKey,
);
if (!dailyHmtSpent) {
dailyHmtSpent = await this.hCaptchaLabelingGateway.fetchDailyHmtSpent();
await this.cacheManager.set(
this.dailyHmtSpentCacheKey,
dailyHmtSpent,
this.configService.cacheTtlDailyHmtSpent,
);
{
ttl: this.configService.cacheTtlDailyHmtSpent,
} as any);
}
return dailyHmtSpent;
}
Expand All @@ -97,7 +98,9 @@ export class HCaptchaService {
await this.cacheManager.set(
command.email,
stats,
this.configService.cacheTtlHCaptchaUserStats,
{
ttl: this.configService.cacheTtlHCaptchaUserStats
} as any,
);
return stats;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const EARNINGS_DATA_2 = { date: '2021-01-22', value: 209 } as DateValue;
const SUCCESSFULLY_ENABLED = 'Enabled labeling for this account successfully';
export const jwtUserDataFixture: JwtUserData = {
userId: ID,
address: POLYGON_WALLET_ADDR,
wallet_address: POLYGON_WALLET_ADDR,
email: EMAIL,
kyc_status: 'APPROVED',
site_key: H_CAPTCHA_SITE_KEY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ describe('HCaptchaService', () => {
expect(cacheManager.set).toHaveBeenCalledWith(
service.dailyHmtSpentCacheKey,
dailyHmtSpentResponseFixture,
configService.cacheTtlDailyHmtSpent,
{ ttl: configService.cacheTtlDailyHmtSpent },
);
});
});
Expand Down Expand Up @@ -224,7 +224,7 @@ describe('HCaptchaService', () => {
expect(cacheManager.set).toHaveBeenCalledWith(
command.email,
userStatsResponseFixture,
configService.cacheTtlHCaptchaUserStats,
{ ttl: configService.cacheTtlHCaptchaUserStats },
);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ export class OracleDiscoveryService {
await this.cacheManager.set(
chainId,
filteredOracles,
this.configService.cacheTtlOracleDiscovery,
{
ttl: this.configService.cacheTtlOracleDiscovery
} as any,
);
return filteredOracles;
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import { Cache } from 'cache-manager';
import { OracleDiscoveryService } from '../oracle-discovery.service';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { OperatorUtils } from '@human-protocol/sdk';
import { OracleDiscoveryCommand, OracleDiscoveryResponse } from '../model/oracle-discovery.model';
import {
OracleDiscoveryCommand,
OracleDiscoveryResponse,
} from '../model/oracle-discovery.model';
import { EnvironmentConfigService } from '../../../common/config/environment-config.service';
import { CommonConfigModule } from '../../../common/config/common-config.module';
import { ConfigModule } from '@nestjs/config';
import {
emptyCommandFixture, filledCommandFixture,
emptyCommandFixture,
filledCommandFixture,
generateOracleDiscoveryResponseBody,
notSetCommandFixture,
} from './oracle-discovery.fixture';
Expand Down Expand Up @@ -101,11 +105,9 @@ describe('OracleDiscoveryService', () => {
expect(result).toEqual([mockData[0]]);
EXPECTED_CHAIN_IDS.forEach((chainId) => {
expect(cacheManager.get).toHaveBeenCalledWith(chainId);
expect(cacheManager.set).toHaveBeenCalledWith(
chainId,
[mockData[0]],
TTL,
);
expect(cacheManager.set).toHaveBeenCalledWith(chainId, [mockData[0]], {
ttl: TTL,
});
expect(OperatorUtils.getReputationNetworkOperators).toHaveBeenCalledWith(
Number(chainId),
REPUTATION_ORACLE_ADDRESS,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { AutoMap } from '@automapper/classes';
import { IsEmail } from 'class-validator';
import { IsEmail, IsString } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class ForgotPasswordDto {
@AutoMap()
@IsEmail()
@ApiProperty({ example: 'string' })
email: string;
@AutoMap()
@IsString()
@ApiProperty({ example: 'string' })
h_captcha_token: string;
}

export class ForgotPasswordCommand {
@AutoMap()
email: string;
@AutoMap()
hCaptchaToken: string;
}

export class ForgotPasswordData {
@AutoMap()
email: string;
@AutoMap()
h_captcha_token: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ export class RestorePasswordData {
@AutoMap()
token: string;
@AutoMap()
h_captcha_token: string;
hCaptchaToken: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ export class PasswordResetController {
summary: 'Endpoint to restore the user password after reset',
})
@UsePipes(new ValidationPipe())
public async restorePassword(
@Body() dto: RestorePasswordDto,
): Promise<void> {
public async restorePassword(@Body() dto: RestorePasswordDto): Promise<void> {
const command = this.mapper.map(
dto,
RestorePasswordDto,
Expand Down
Loading
Loading