Skip to content

Commit d0f1eb2

Browse files
[Human App] Implemented register worker (#2315)
* Implemeted register worker * Removed .env file * Implemented registration_needed flag * Lint human app * Updated authorization headers * Resolved comments * Lint human app * Updated unit tests * Revert reputation oracle changes * Removed the registration required check * update endpoint summary --------- Co-authored-by: portuu3 <adrian.portugues.mas@gmail.com>
1 parent 207fdf5 commit d0f1eb2

29 files changed

+390
-43
lines changed

packages/apps/human-app/server/.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,7 @@ lerna-debug.log*
3535
!.vscode/extensions.json
3636

3737
# Redis Data
38-
./redis_data
38+
./redis_data
39+
40+
.env.development
41+
.env.production

packages/apps/human-app/server/src/common/config/environment-config.service.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const DEFAULT_CORS_ALLOWED_ORIGIN = 'http://localhost:5173';
99
const DEFAULT_CORS_ALLOWED_HEADERS =
1010
'Content-Type,Authorization,X-Requested-With,Accept,Origin';
1111
const DEFAULT_CACHE_TTL_EXCHANGE_ORACLE_URL = 24 * 60 * 60;
12+
const DEFAULT_CACHE_TTL_EXCHANGE_ORACLE_REGISTRATION_NEEDED = 24 * 60 * 60;
1213

1314
@Injectable()
1415
export class EnvironmentConfigService {
@@ -94,6 +95,12 @@ export class EnvironmentConfigService {
9495
DEFAULT_CACHE_TTL_EXCHANGE_ORACLE_URL,
9596
);
9697
}
98+
get cacheTtlExchangeOracleRegistrationNeeded(): number {
99+
return this.configService.get<number>(
100+
'CACHE_TTL_EXCHANGE_ORACLE_REGISTRATION_NEEDED',
101+
DEFAULT_CACHE_TTL_EXCHANGE_ORACLE_REGISTRATION_NEEDED,
102+
);
103+
}
97104
get hcaptchaLabelingStatsApiUrl(): string {
98105
return this.configService.getOrThrow<string>(
99106
'HCAPTCHA_LABELING_STATS_API_URL',

packages/apps/human-app/server/src/common/config/gateway-config.service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ export class GatewayConfigService {
4141
method: HttpMethod.POST,
4242
headers: this.JSON_HEADER,
4343
},
44+
[ReputationOracleEndpoints.WORKER_REGISTRATION]: {
45+
endpoint: '/user/registration',
46+
method: HttpMethod.POST,
47+
headers: this.JSON_HEADER,
48+
},
4449
[ReputationOracleEndpoints.EMAIL_VERIFICATION]: {
4550
endpoint: '/auth/email-verification',
4651
method: HttpMethod.POST,

packages/apps/human-app/server/src/common/config/spec/gateway-config-service.mock.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export const gatewayConfigServiceMock = {
1717
method: 'POST',
1818
headers: { 'Content-Type': 'application/json' },
1919
},
20+
WORKER_REGISTRATION: {
21+
endpoint: '/user/registration',
22+
method: 'POST',
23+
headers: { 'Content-Type': 'application/json' },
24+
},
2025
EMAIL_VERIFICATION: {
2126
endpoint: '/auth/email-verification',
2227
method: 'POST',
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export const JOB_DISCOVERY_CACHE_KEY = 'jobs:avialable';
22
export const JOB_ASSIGNMENT_CACHE_KEY = 'jobs:assigned';
3-
export const KV_STORE_CACHE_KEY = 'kvstore';
3+
export const ORACLE_URL_CACHE_KEY = 'oracle:url';
44
export const DAILY_HMT_SPENT_CACHE_KEY = 'daily:hmt-spent';
55
export const ORACLE_STATISTICS_CACHE_KEY = 'statistics:oracle';
66
export const WORKER_STATISTICS_CACHE_KEY = 'statistics:worker';

packages/apps/human-app/server/src/common/enums/reputation-oracle-endpoints.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export enum ReputationOracleEndpoints {
22
WORKER_SIGNUP = 'WORKER_SIGNUP',
33
WORKER_SIGNIN = 'WORKER_SIGNIN',
4+
WORKER_REGISTRATION = 'WORKER_REGISTRATION',
45
OPERATOR_SIGNUP = 'OPERATOR_SIGNUP',
56
OPERATOR_SIGNIN = 'OPERATOR_SIGNIN',
67
EMAIL_VERIFICATION = 'EMAIL_VERIFICATION',

packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Injectable } from '@nestjs/common';
1+
import { HttpException, Injectable } from '@nestjs/common';
22
import { AxiosRequestConfig } from 'axios';
33
import { lastValueFrom } from 'rxjs';
44
import {
@@ -34,6 +34,10 @@ import { HttpMethod } from '../../common/enums/http-method';
3434
import { toCleanObjParams } from '../../common/utils/gateway-common.utils';
3535
import { KvStoreGateway } from '../kv-store/kv-store.gateway';
3636
import { EscrowUtilsGateway } from '../escrow/escrow-utils-gateway.service';
37+
import {
38+
RegisterWorkerCommand,
39+
RegisterWorkerData,
40+
} from '../../modules/user-worker/model/worker-registration.model';
3741

3842
@Injectable()
3943
export class ExchangeOracleGateway {
@@ -171,4 +175,25 @@ export class ExchangeOracleGateway {
171175
};
172176
return this.callExternalHttpUtilRequest<JobsDiscoveryResponse>(options);
173177
}
178+
179+
async registerWorker(command: RegisterWorkerCommand) {
180+
const data = this.mapper.map(
181+
command,
182+
RegisterWorkerCommand,
183+
RegisterWorkerData,
184+
);
185+
186+
const options: AxiosRequestConfig = {
187+
method: HttpMethod.POST,
188+
url: `${await this.kvStoreGateway.getExchangeOracleUrlByAddress(
189+
command.oracleAddress,
190+
)}/register`,
191+
data: data,
192+
headers: {
193+
Authorization: command.token,
194+
Accept: 'application/json',
195+
},
196+
};
197+
return this.callExternalHttpUtilRequest(options);
198+
}
174199
}

packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.mapper.profile.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import {
2121
JobsDiscoveryParams,
2222
JobsDiscoveryParamsData,
2323
} from '../../modules/jobs-discovery/model/jobs-discovery.model';
24+
import {
25+
RegisterWorkerCommand,
26+
RegisterWorkerData,
27+
} from '../../modules/user-worker/model/worker-registration.model';
2428

2529
@Injectable()
2630
export class ExchangeOracleProfile extends AutomapperProfile {
@@ -88,6 +92,15 @@ export class ExchangeOracleProfile extends AutomapperProfile {
8892
destination: new SnakeCaseNamingConvention(),
8993
}),
9094
);
95+
createMap(
96+
mapper,
97+
RegisterWorkerCommand,
98+
RegisterWorkerData,
99+
namingConventions({
100+
source: new CamelCaseNamingConvention(),
101+
destination: new SnakeCaseNamingConvention(),
102+
}),
103+
);
91104
};
92105
}
93106
}

packages/apps/human-app/server/src/integrations/exchange-oracle/spec/exchange-oracle.gateway.mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export const exchangeOracleGatewayMock = {
44
fetchAssignedJobs: jest.fn(),
55
postNewJobAssignment: jest.fn(),
66
fetchDiscoveredJobs: jest.fn(),
7+
registerWorker: jest.fn(),
78
};

packages/apps/human-app/server/src/integrations/exchange-oracle/spec/exchange-oracle.gateway.spec.ts

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
jobResignAssignedCommandFixture,
1818
jobsFetchParamsCommandFixture,
1919
jobsFetchParamsDataFixtureAsString,
20+
workerRegisterUrl,
2021
} from '../../../modules/job-assignment/spec/job-assignment.fixtures';
2122
import { ExchangeOracleProfile } from '../exchange-oracle.mapper.profile';
2223
import {
@@ -32,12 +33,20 @@ import { EscrowUtilsGateway } from '../../escrow/escrow-utils-gateway.service';
3233
import { ResignJobData } from '../../../modules/job-assignment/model/job-assignment.model';
3334
import { JobsDiscoveryParamsData } from '../../../modules/jobs-discovery/model/jobs-discovery.model';
3435
import { AxiosResponse } from 'axios';
36+
import { RegisterWorkerData } from '../../../modules/user-worker/model/worker-registration.model';
37+
import {
38+
registerWorkerCommandFixture,
39+
registerWorkerDataFixture,
40+
responseWorkerFixture,
41+
} from '../../../modules/user-worker/spec/worker.fixtures';
3542

3643
describe('ExchangeOracleApiGateway', () => {
3744
let gateway: ExchangeOracleGateway;
3845
let httpService: HttpService;
3946
let escrowGateway: EscrowUtilsGateway;
40-
const EXCHANGE_ORACLE_ADR = 'mocked:exchange_oracle:address';
47+
const EXCHANGE_ORACLE_REGISTRATION_NEEDED =
48+
'mocked:exchange_oracle:registration_needed';
49+
const EXCHANGE_ORACLE_URL = 'mocked:exchange_oracle:url';
4150
beforeEach(async () => {
4251
const module: TestingModule = await Test.createTestingModule({
4352
imports: [
@@ -49,9 +58,12 @@ describe('ExchangeOracleApiGateway', () => {
4958
{
5059
provide: KvStoreGateway,
5160
useValue: {
61+
getExchangeOracleRegistrationNeeded: jest
62+
.fn()
63+
.mockReturnValue(EXCHANGE_ORACLE_REGISTRATION_NEEDED),
5264
getExchangeOracleUrlByAddress: jest
5365
.fn()
54-
.mockReturnValue(EXCHANGE_ORACLE_ADR),
66+
.mockReturnValue(EXCHANGE_ORACLE_URL),
5567
},
5668
},
5769
{
@@ -90,7 +102,7 @@ describe('ExchangeOracleApiGateway', () => {
90102
await gateway.fetchUserStatistics(command);
91103
expect(httpService.request).toHaveBeenCalledWith(
92104
expect.objectContaining({
93-
url: EXCHANGE_ORACLE_ADR + '/stats/assignment',
105+
url: EXCHANGE_ORACLE_URL + '/stats/assignment',
94106
method: HttpMethod.GET,
95107
}),
96108
);
@@ -115,7 +127,7 @@ describe('ExchangeOracleApiGateway', () => {
115127
await gateway.fetchOracleStatistics(command);
116128
expect(httpService.request).toHaveBeenCalledWith(
117129
expect.objectContaining({
118-
url: EXCHANGE_ORACLE_ADR + '/stats',
130+
url: EXCHANGE_ORACLE_URL + '/stats',
119131
method: HttpMethod.GET,
120132
}),
121133
);
@@ -151,7 +163,7 @@ describe('ExchangeOracleApiGateway', () => {
151163
await gateway.fetchAssignedJobs(command);
152164
expect(httpService.request).toHaveBeenCalledWith(
153165
expect.objectContaining({
154-
url: EXCHANGE_ORACLE_ADR + '/assignment',
166+
url: EXCHANGE_ORACLE_URL + '/assignment',
155167
method: HttpMethod.GET,
156168
params: expectedMappedData,
157169
headers: {
@@ -168,7 +180,7 @@ describe('ExchangeOracleApiGateway', () => {
168180
const data = jobAssignmentDataFixture;
169181
jest
170182
.spyOn(escrowGateway, 'getExchangeOracleAddressByEscrowAddress')
171-
.mockResolvedValue(EXCHANGE_ORACLE_ADR);
183+
.mockResolvedValue(EXCHANGE_ORACLE_URL);
172184
const matcher: RequestBodyMatcher = {
173185
escrowAddress: data.escrow_address,
174186
chainId: data.chain_id,
@@ -180,7 +192,7 @@ describe('ExchangeOracleApiGateway', () => {
180192
).toHaveBeenCalledWith(command.data.chainId, command.data.escrowAddress);
181193
expect(httpService.request).toHaveBeenCalledWith(
182194
expect.objectContaining({
183-
url: EXCHANGE_ORACLE_ADR + '/assignment',
195+
url: EXCHANGE_ORACLE_URL + '/assignment',
184196
method: HttpMethod.POST,
185197
}),
186198
);
@@ -197,7 +209,7 @@ describe('ExchangeOracleApiGateway', () => {
197209
await gateway.resignAssignedJob(command);
198210
expect(httpService.request).toHaveBeenCalledWith(
199211
expect.objectContaining({
200-
url: EXCHANGE_ORACLE_ADR + '/assignment/resign',
212+
url: EXCHANGE_ORACLE_URL + '/assignment/resign',
201213
method: HttpMethod.POST,
202214
data: expectedMappedData,
203215
headers: {
@@ -228,7 +240,7 @@ describe('ExchangeOracleApiGateway', () => {
228240
await gateway.fetchJobs(command);
229241
expect(httpService.request).toHaveBeenCalledWith(
230242
expect.objectContaining({
231-
url: EXCHANGE_ORACLE_ADR + '/job',
243+
url: EXCHANGE_ORACLE_URL + '/job',
232244
method: HttpMethod.GET,
233245
params: expectedMappedData,
234246
headers: {
@@ -240,6 +252,37 @@ describe('ExchangeOracleApiGateway', () => {
240252
});
241253
});
242254

255+
describe('registerWorker', () => {
256+
it('should successfully call register worker', async () => {
257+
jest.spyOn(httpService, 'request').mockReturnValue(
258+
of({
259+
data: responseWorkerFixture,
260+
status: 200,
261+
statusText: 'OK',
262+
headers: {},
263+
config: {},
264+
} as AxiosResponse),
265+
);
266+
const command = registerWorkerCommandFixture;
267+
const expectedMappedData: RegisterWorkerData = registerWorkerDataFixture;
268+
nock(workerRegisterUrl)
269+
.post(`/register`)
270+
.reply(200, responseWorkerFixture);
271+
await gateway.registerWorker(command);
272+
expect(httpService.request).toHaveBeenCalledWith(
273+
expect.objectContaining({
274+
url: EXCHANGE_ORACLE_URL + '/register',
275+
method: HttpMethod.POST,
276+
data: expectedMappedData,
277+
headers: {
278+
Authorization: command.token,
279+
Accept: 'application/json',
280+
},
281+
}),
282+
);
283+
});
284+
});
285+
243286
afterEach(() => {
244287
nock.cleanAll();
245288
});

packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ethers } from 'ethers';
44
import { ChainId, KVStoreKeys, KVStoreUtils } from '@human-protocol/sdk';
55
import { CACHE_MANAGER } from '@nestjs/cache-manager';
66
import { Cache } from 'cache-manager';
7-
import { KV_STORE_CACHE_KEY } from '../../common/constants/cache';
7+
import { ORACLE_URL_CACHE_KEY } from '../../common/constants/cache';
88

99
@Injectable()
1010
export class KvStoreGateway {
@@ -13,18 +13,18 @@ export class KvStoreGateway {
1313
@Inject(CACHE_MANAGER) private cacheManager: Cache,
1414
) {}
1515
async getExchangeOracleUrlByAddress(address: string): Promise<string | void> {
16-
const key = `${KV_STORE_CACHE_KEY}:${address}`;
17-
const cachedUrl: string | undefined = await this.cacheManager.get(key);
18-
if (cachedUrl) {
19-
return cachedUrl;
16+
const key = `${ORACLE_URL_CACHE_KEY}:${address}`;
17+
const cachedData: string | undefined = await this.cacheManager.get(key);
18+
if (cachedData) {
19+
return cachedData;
2020
}
21-
let fetchedUrl: string;
21+
let fetchedData: string;
2222
try {
2323
const runner = new ethers.JsonRpcProvider(this.configService.rpcUrl);
2424
const network = await runner.provider?.getNetwork();
2525
const chainId: ChainId = Number(network?.chainId);
2626

27-
fetchedUrl = await KVStoreUtils.get(chainId, address, KVStoreKeys.url);
27+
fetchedData = await KVStoreUtils.get(chainId, address, KVStoreKeys.url);
2828
} catch (e) {
2929
if (e.toString().includes('Error: Invalid address')) {
3030
throw new HttpException(
@@ -37,16 +37,16 @@ export class KvStoreGateway {
3737
);
3838
}
3939
}
40-
if (!fetchedUrl || fetchedUrl === '') {
40+
if (!fetchedData || fetchedData === '') {
4141
throw new HttpException(
4242
`Unable to retrieve URL from address: ${address}`,
4343
400,
4444
);
4545
} else {
46-
await this.cacheManager.set(key, fetchedUrl, {
46+
await this.cacheManager.set(key, fetchedData, {
4747
ttl: this.configService.cacheTtlExchangeOracleUrl,
4848
} as any);
49-
return fetchedUrl;
49+
return fetchedData;
5050
}
5151
}
5252
}

packages/apps/human-app/server/src/integrations/kv-store/spec/kv-store.gateway.spec.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ChainId, KVStoreKeys, KVStoreUtils } from '@human-protocol/sdk';
44
import { EnvironmentConfigService } from '../../../common/config/environment-config.service';
55
import { CACHE_MANAGER } from '@nestjs/cache-manager';
66
import { Cache } from 'cache-manager';
7-
import { KV_STORE_CACHE_KEY } from '../../../common/constants/cache';
7+
import { ORACLE_URL_CACHE_KEY } from '../../../common/constants/cache';
88

99
const EXPECTED_URL = 'https://example.com';
1010
jest.mock('@human-protocol/sdk', () => {
@@ -86,9 +86,9 @@ describe('KvStoreGateway', () => {
8686
describe('getExchangeOracleUrlByAddress', () => {
8787
it('should get data from kvStoreUtils, if not cached', async () => {
8888
const testAddress = 'testAddress';
89-
const cacheKey = `${KV_STORE_CACHE_KEY}:${testAddress}`;
90-
const expectedUrl = EXPECTED_URL;
91-
mockKVStoreUtils.get.mockResolvedValue(expectedUrl);
89+
const cacheKey = `${ORACLE_URL_CACHE_KEY}:${testAddress}`;
90+
const expectedData = EXPECTED_URL;
91+
mockKVStoreUtils.get.mockResolvedValue(expectedData);
9292
cacheManager.get.mockResolvedValue(undefined);
9393
const result = await service.getExchangeOracleUrlByAddress(testAddress);
9494
expect(KVStoreUtils.get).toHaveBeenCalledWith(
@@ -97,22 +97,22 @@ describe('KvStoreGateway', () => {
9797
KVStoreKeys.url,
9898
);
9999

100-
expect(cacheManager.set).toHaveBeenCalledWith(cacheKey, expectedUrl, {
100+
expect(cacheManager.set).toHaveBeenCalledWith(cacheKey, expectedData, {
101101
ttl: configService.cacheTtlExchangeOracleUrl,
102102
});
103103
expect(cacheManager.get).toHaveBeenCalledWith(cacheKey);
104-
expect(result).toBe(expectedUrl);
104+
expect(result).toBe(expectedData);
105105
});
106106
it('should get data from cache, if available', async () => {
107107
const testAddress = 'testAddress';
108-
const cacheKey = `${KV_STORE_CACHE_KEY}:${testAddress}`;
109-
const expectedUrl = EXPECTED_URL;
110-
cacheManager.get.mockResolvedValue(expectedUrl);
108+
const cacheKey = `${ORACLE_URL_CACHE_KEY}:${testAddress}`;
109+
const expectedData = EXPECTED_URL;
110+
cacheManager.get.mockResolvedValue(expectedData);
111111
const result = await service.getExchangeOracleUrlByAddress(testAddress);
112112

113113
expect(KVStoreUtils.get).not.toHaveBeenCalled();
114114
expect(cacheManager.get).toHaveBeenCalledWith(cacheKey);
115-
expect(result).toBe(expectedUrl);
115+
expect(result).toBe(expectedData);
116116
});
117117
});
118118
});

0 commit comments

Comments
 (0)