Skip to content

Commit

Permalink
feat: user profile edit/deletion (#37)
Browse files Browse the repository at this point in the history
* feat: add migration to edit and delete

* feat: add delete user hook

* test: add user deletion hook tests

* feat: add accountability check

* feat: allow to adopt probe even if gp api request failed (#38)

* feat: allow to adopt probe if gp api requests timed out

* test: add tests
  • Loading branch information
alexey-yarmosh committed Mar 16, 2024
1 parent b291e1d commit d6dce68
Show file tree
Hide file tree
Showing 18 changed files with 6,616 additions and 36 deletions.
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ RUN npm ci
COPY ./src/extensions/hooks/gp-tokens .
RUN npm run build

# Build hooks/gp-tokens
FROM node:18-alpine AS builder-18
WORKDIR /builder/src/extensions/hooks/directus-users
ADD ./src/extensions/hooks/directus-users/package.json ./src/extensions/hooks/directus-users/package-lock.json ./
RUN npm ci
COPY ./src/extensions/hooks/directus-users .
RUN npm run build

FROM directus/directus:10.9.0

COPY --from=builder-01 /builder/src/extensions/hooks/jsd-purge-tokens/dist/* /directus/extensions/hooks/jsd-purge-tokens/
Expand All @@ -154,3 +162,4 @@ COPY --from=builder-14 /builder/src/extensions/operations/adopted-probes-credits
COPY --from=builder-15 /builder/src/extensions/interfaces/gp-tags/dist/* /directus/extensions/interfaces/gp-tags/
COPY --from=builder-16 /builder/src/extensions/operations/remove-banned-users-cron-handler/dist/* /directus/extensions/operations/remove-banned-users-cron-handler/
COPY --from=builder-17 /builder/src/extensions/hooks/gp-tokens/dist/* /directus/extensions/hooks/gp-tokens/
COPY --from=builder-18 /builder/src/extensions/hooks/directus-users/dist/* /directus/extensions/hooks/directus-users/
20 changes: 10 additions & 10 deletions snapshots/collections-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ fields:
note: null
options: null
readonly: false
required: true
required: false
sort: 20
special: null
translations: null
Expand All @@ -382,7 +382,7 @@ fields:
max_length: null
numeric_precision: 10
numeric_scale: 0
is_nullable: false
is_nullable: true
is_unique: false
is_primary_key: false
is_generated: false
Expand Down Expand Up @@ -450,7 +450,7 @@ fields:
a message here: https://github.com/jsdelivr/globalping/issues/268
options: null
readonly: false
required: true
required: false
sort: 8
special: null
translations: null
Expand All @@ -465,7 +465,7 @@ fields:
max_length: 255
numeric_precision: null
numeric_scale: null
is_nullable: false
is_nullable: true
is_unique: false
is_primary_key: false
is_generated: false
Expand Down Expand Up @@ -699,7 +699,7 @@ fields:
max_length: null
numeric_precision: 3
numeric_scale: 0
is_nullable: true
is_nullable: false
is_unique: false
is_primary_key: false
is_generated: false
Expand Down Expand Up @@ -878,7 +878,7 @@ fields:
note: null
options: null
readonly: false
required: true
required: false
sort: 21
special: null
translations: null
Expand All @@ -893,7 +893,7 @@ fields:
max_length: 255
numeric_precision: null
numeric_scale: null
is_nullable: false
is_nullable: true
is_unique: false
is_primary_key: false
is_generated: false
Expand Down Expand Up @@ -1114,7 +1114,7 @@ fields:
note: null
options: null
readonly: false
required: true
required: false
sort: 13
special: null
translations: null
Expand Down Expand Up @@ -1152,7 +1152,7 @@ fields:
note: null
options: null
readonly: false
required: true
required: false
sort: 14
special: null
translations: null
Expand All @@ -1167,7 +1167,7 @@ fields:
max_length: 255
numeric_precision: null
numeric_scale: null
is_nullable: false
is_nullable: true
is_unique: false
is_primary_key: false
is_generated: false
Expand Down
37 changes: 32 additions & 5 deletions src/extensions/endpoints/adoption-code/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,26 @@ type SendCodeResponse = {
network: string;
}

type AdoptedProbe = Omit<SendCodeResponse, 'ip' | 'code' | 'state'> & {
ip: string,
code: string,
state: string | null
type AdoptedProbe = {
ip: string;
code: string;
uuid: string | null;
version: string | null;
hardwareDevice: string | null;
status: string;
city: string | null;
state: string | null;
country: string | null;
latitude: number | null;
longitude: number | null;
asn: number | null;
network: string | null;
}

const InvalidCodeError = createError('INVALID_PAYLOAD_ERROR', 'Code is not valid', 400);
const TooManyRequestsError = createError('TOO_MANY_REQUESTS', 'Too many requests', 429);


const rateLimiter = new RateLimiterMemory({
points: 20,
duration: 30 * 60,
Expand Down Expand Up @@ -74,6 +85,22 @@ export default defineEndpoint((router, { env, logger, services }) => {

const code = generateRandomCode();

probesToAdopt.set(userId, {
ip,
code,
uuid: null,
version: null,
hardwareDevice: null,
status: 'offline',
city: null,
state: null,
country: null,
latitude: null,
longitude: null,
asn: null,
network: null,
});

const response = await axios.post<SendCodeResponse>(`${env.GLOBALPING_URL}/adoption-code?systemkey=${env.GP_SYSTEM_KEY}`, {
ip,
code,
Expand Down Expand Up @@ -104,7 +131,7 @@ export default defineEndpoint((router, { env, logger, services }) => {
if (isDirectusError(error)) {
res.status(error.status).send(error.message);
} else if (axios.isAxiosError(error)) {
res.status(400).send(error.response?.data?.error?.message);
res.status(400).send(error.message);
} else {
res.status(500).send('Internal Server Error');
}
Expand Down
52 changes: 52 additions & 0 deletions src/extensions/endpoints/adoption-code/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,58 @@ describe('adoption code endpoints', () => {
});
});

it('should accept valid verification code even if request to GP api failed', async () => {
endpoint(router, endpointContext);
let code = '';
nock('https://api.globalping.io').post('/v1/adoption-code?systemkey=system', (body) => {
expect(body.ip).to.equal('1.1.1.1');
expect(body.code.length).to.equal(6);
code = body.code;
return true;
}).reply(504);

await request('/send-code', {
accountability: {
user: 'f3115997-31d1-4cf5-8b41-0617a99c5706',
},
body: {
ip: '1.1.1.1',
},
}, res);

await request('/verify-code', {
accountability: {
user: 'f3115997-31d1-4cf5-8b41-0617a99c5706',
},
body: {
code,
},
}, res);

expect(nock.isDone()).to.equal(true);
expect(resSend.callCount).to.equal(2);
expect(resSend.args[0]).to.deep.equal([ 'Request failed with status code 504' ]);
expect(resSend.args[1]).to.deep.equal([ 'Code successfully validated. Probe was assigned to you.' ]);
expect(createOne.callCount).to.equal(1);

expect(createOne.args[0][0]).to.deep.equal({
ip: '1.1.1.1',
uuid: null,
version: null,
hardwareDevice: null,
status: 'offline',
city: null,
state: null,
country: null,
latitude: null,
longitude: null,
asn: null,
network: null,
userId: 'f3115997-31d1-4cf5-8b41-0617a99c5706',
lastSyncDate: new Date(),
});
});

it('should accept valid verification code with spaces', async () => {
endpoint(router, endpointContext);
let code = '';
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/endpoints/sync-github-data/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default defineEndpoint((router, context: EndpointExtensionContext) => {
if (isDirectusError(error)) {
res.status(error.status).send(error.message);
} else if (axios.isAxiosError(error)) {
res.status(400).send(error.response?.data?.error?.message);
res.status(400).send(error.message);
} else {
res.status(500).send('Internal Server Error');
}
Expand Down
3 changes: 3 additions & 0 deletions src/extensions/hooks/directus-users/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DS_Store
node_modules
dist
11 changes: 11 additions & 0 deletions src/extensions/hooks/directus-users/.mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extension": [
"ts"
],
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm",
"no-experimental-fetch"
],
"spec": "test/**/*.ts"
}
Loading

0 comments on commit d6dce68

Please sign in to comment.