Skip to content

Commit

Permalink
step 2: copy data + add new constraint + update extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
alexey-yarmosh committed Feb 17, 2025
1 parent f21eb0e commit d6ee3ab
Show file tree
Hide file tree
Showing 27 changed files with 144 additions and 68 deletions.
4 changes: 2 additions & 2 deletions .env.development.example
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ ADOPTED_PROBES_CHECK_TIME_MAX_DEVIATION_MINS=5
# To trigger credits assignment probe need to be online >20 hours during the day. Current "Adopted probes status CRON" is "*/10 * * * *", which is 6 times an hour
# So required value is 20 * 6 = 120
ADOPTED_PROBES_REQUIRED_ONLINE_TIMES=120
TARGET_NODE_VERSION=v20.13.0 # Same format as in gp_adopted_probes.nodeVersion
TARGET_HW_DEVICE_FIRMWARE=v2.0 # Same format as in gp_adopted_probes.hardwareDeviceFirmware
TARGET_NODE_VERSION=v20.13.0 # Same format as in gp_probes.nodeVersion
TARGET_HW_DEVICE_FIRMWARE=v2.0 # Same format as in gp_probes.hardwareDeviceFirmware

# Are updated during `pnpm run init`
AUTH_GITHUB_DEFAULT_ROLE_ID=
Expand Down
4 changes: 2 additions & 2 deletions .env.e2e.example
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ ADOPTED_PROBES_CHECK_TIME_MAX_DEVIATION_MINS=5
# To trigger credits assignment probe need to be online >20 hours during the day. Current "Adopted probes status CRON" is "*/10 * * * *", which is 6 times an hour
# So required value is 20 * 6 = 120
ADOPTED_PROBES_REQUIRED_ONLINE_TIMES=120
TARGET_NODE_VERSION=v20.13.0 # Same format as in gp_adopted_probes.nodeVersion
TARGET_HW_DEVICE_FIRMWARE=v2.0 # Same format as in gp_adopted_probes.hardwareDeviceFirmware
TARGET_NODE_VERSION=v20.13.0 # Same format as in gp_probes.nodeVersion
TARGET_HW_DEVICE_FIRMWARE=v2.0 # Same format as in gp_probes.hardwareDeviceFirmware

# Are updated during `pnpm run init`
AUTH_GITHUB_DEFAULT_ROLE_ID=
Expand Down
4 changes: 2 additions & 2 deletions .env.production.example
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ ADOPTED_PROBES_CHECK_TIME_MAX_DEVIATION_MINS=5
# To trigger credits assignment probe need to be online >20 hours during the day. Current "Adopted probes status CRON" is "*/10 * * * *", which is 6 times an hour
# So required value is 20 * 6 = 120
ADOPTED_PROBES_REQUIRED_ONLINE_TIMES=120
TARGET_NODE_VERSION=v20.13.0 # Same format as in gp_adopted_probes.nodeVersion
TARGET_HW_DEVICE_FIRMWARE=v2.0 # Same format as in gp_adopted_probes.hardwareDeviceFirmware
TARGET_NODE_VERSION=v20.13.0 # Same format as in gp_probes.nodeVersion
TARGET_HW_DEVICE_FIRMWARE=v2.0 # Same format as in gp_probes.hardwareDeviceFirmware

# Are updated during `pnpm run init`
AUTH_GITHUB_DEFAULT_ROLE_ID=
Expand Down
2 changes: 1 addition & 1 deletion seeds/development/admin-layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const seed = async (knex) => {

await knex('directus_presets').insert([{
user: admin.id,
collection: 'gp_adopted_probes',
collection: 'gp_probes',
layout_query: { tabular: { fields: [ 'id', 'userId.first_name', 'ip', 'city', 'country', 'name', 'status', 'onlineTimesToday' ] } },
icon: 'bookmark',
},
Expand Down
4 changes: 2 additions & 2 deletions seeds/development/user-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const seed = async (knex) => {
await Promise.all([
knex('gp_apps').delete(),
knex('gp_tokens').delete(),
knex('gp_adopted_probes').delete(),
knex('gp_probes').delete(),
knex('sponsors').delete(),
knex('gp_credits_additions').delete(),
knex('gp_credits_deductions').delete(),
Expand Down Expand Up @@ -168,7 +168,7 @@ export const seed = async (knex) => {
]);

const probeId = randomUUID();
await knex('gp_adopted_probes').insert([{
await knex('gp_probes').insert([{
id: probeId,
asn: 3302,
city: 'Naples',
Expand Down
2 changes: 1 addition & 1 deletion seeds/development/user-layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const seed = async (knex) => {

await knex('directus_presets').insert([{
user: user.id,
collection: 'gp_adopted_probes',
collection: 'gp_probes',
layout_query: { tabular: { fields: [ 'id', 'userId.first_name', 'ip', 'city', 'country', 'name', 'status' ] } },
icon: 'bookmark',
},
Expand Down
25 changes: 23 additions & 2 deletions snapshots/collections-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2768,8 +2768,8 @@ fields:
is_generated: false
generation_expression: null
has_auto_increment: false
foreign_key_table: null
foreign_key_column: null
foreign_key_table: gp_probes
foreign_key_column: id
- collection: gp_credits_deductions
field: amount
type: integer
Expand Down Expand Up @@ -5502,6 +5502,27 @@ relations:
constraint_name: gp_credits_additions_user_updated_foreign
on_update: RESTRICT
on_delete: RESTRICT
- collection: gp_credits_additions
field: adopted_probe
related_collection: gp_probes
meta:
junction_field: null
many_collection: gp_credits_additions
many_field: adopted_probe
one_allowed_collections: null
one_collection: gp_probes
one_collection_field: null
one_deselect_action: nullify
one_field: null
sort_field: null
schema:
table: gp_credits_additions
column: adopted_probe
foreign_key_table: gp_probes
foreign_key_column: id
constraint_name: gp_credits_additions_adopted_probe_foreign
on_update: RESTRICT
on_delete: SET NULL
- collection: gp_credits_deductions
field: user_id
related_collection: directus_users
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { AdoptedProbe, Request } from '../index.js';

export const createAdoptedProbe = async (req: Request, probe: AdoptedProbe, context: EndpointExtensionContext) => {
const { services } = context;
const itemsService = new services.ItemsService('gp_adopted_probes', {
const itemsService = new services.ItemsService('gp_probes', {
schema: req.schema,
});

Expand Down Expand Up @@ -34,7 +34,7 @@ export const createAdoptedProbe = async (req: Request, probe: AdoptedProbe, cont
};

export const findAdoptedProbes = async (filter: Record<string, unknown>, { services, getSchema, database }: EndpointExtensionContext) => {
const itemsService = new services.ItemsService('gp_adopted_probes', {
const itemsService = new services.ItemsService('gp_probes', {
schema: await getSchema({ database }),
knex: database,
});
Expand Down Expand Up @@ -63,7 +63,7 @@ const getDefaultProbeName = async (req: Request, probe: AdoptedProbe, context: E
};

export const findAdoptedProbesByIp = async (ip: string, { database }: EndpointExtensionContext) => {
const probes = await database('gp_adopted_probes')
const probes = await database('gp_probes')
.whereRaw('JSON_CONTAINS(altIps, ?)', [ `"${ip}"` ])
.orWhere('ip', ip);

Expand Down
2 changes: 1 addition & 1 deletion src/extensions/endpoints/adoption-code/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ describe('adoption code endpoints', () => {
expect(notificationCreateOne.args[0]?.[0]).to.deep.include({
recipient: 'f3115997-31d1-4cf5-8b41-0617a99c5706',
item: 'generatedId',
collection: 'gp_adopted_probes',
collection: 'gp_probes',
});
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/hooks/adopted-probe/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type Fields = Partial<AdoptedProbe>;
export const UserNotFoundError = createError('UNAUTHORIZED', 'User not found.', 401);

export default defineHook(({ filter, action }, context) => {
filter('gp_adopted_probes.items.update', async (payload, { keys }, { accountability }) => {
filter('gp_probes.items.update', async (payload, { keys }, { accountability }) => {
const fields = payload as Fields;

if (!accountability) {
Expand All @@ -36,7 +36,7 @@ export default defineHook(({ filter, action }, context) => {
});

// State, latitude and longitude are updated in a separate hook, because user operation doesn't have permission to edit them.
action('gp_adopted_probes.items.update', async ({ keys, payload }) => {
action('gp_probes.items.update', async ({ keys, payload }) => {
const fields = payload as Fields;

if (fields.city) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type User = {
export const getProbes = async (keys: string[], { services, database, getSchema }: HookExtensionContext, accountability: EventContext['accountability'] = null) => {
const { ItemsService } = services;

const adoptedProbesService = new ItemsService('gp_adopted_probes', {
const adoptedProbesService = new ItemsService('gp_probes', {
database,
schema: await getSchema(),
accountability,
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/hooks/adopted-probe/src/update-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { Fields } from './index.js';
export const resetMetadata = async (_fields: Fields, keys: string[], { services, database, getSchema }: HookExtensionContext) => {
const { ItemsService } = services;

const adoptedProbesService = new ItemsService('gp_adopted_probes', {
const adoptedProbesService = new ItemsService('gp_probes', {
database,
schema: await getSchema(),
});
Expand All @@ -24,7 +24,7 @@ export const resetMetadata = async (_fields: Fields, keys: string[], { services,
export const updateMetadata = async (_fields: Fields, keys: string[], { services, database, getSchema }: HookExtensionContext) => {
const { ItemsService } = services;

const adoptedProbesService = new ItemsService('gp_adopted_probes', {
const adoptedProbesService = new ItemsService('gp_probes', {
database,
schema: await getSchema(),
});
Expand Down
38 changes: 19 additions & 19 deletions src/extensions/hooks/adopted-probe/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('adopted-probe hook', () => {
ItemsService: sinon.stub().callsFake((collection) => {
if (collection === 'directus_users') {
return users;
} else if (collection === 'gp_adopted_probes') {
} else if (collection === 'gp_probes') {
return adoptedProbes;
}

Expand Down Expand Up @@ -107,14 +107,14 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { city: 'marsel' };
await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context);
await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context);

expect(adoptedProbes.readMany.callCount).to.equal(1);
expect(adoptedProbes.readMany.args[0]).to.deep.equal([ [ '1' ] ]);
expect(nock.isDone()).to.equal(true);
expect(payload.city).to.equal('Marseille');

await callbacks.action['gp_adopted_probes.items.update']?.({ payload, keys: [ '1' ] }, context);
await callbacks.action['gp_probes.items.update']?.({ payload, keys: [ '1' ] }, context);

expect(adoptedProbes.updateMany.callCount).to.equal(1);

Expand Down Expand Up @@ -165,14 +165,14 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { city: 'miami' };
await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context);
await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context);

expect(adoptedProbes.readMany.callCount).to.equal(1);
expect(adoptedProbes.readMany.args[0]).to.deep.equal([ [ '1' ] ]);
expect(nock.isDone()).to.equal(true);
expect(payload.city).to.equal('Miami');

await callbacks.action['gp_adopted_probes.items.update']?.({ payload, keys: [ '1' ] }, context);
await callbacks.action['gp_probes.items.update']?.({ payload, keys: [ '1' ] }, context);

expect(adoptedProbes.updateMany.callCount).to.equal(1);

Expand All @@ -197,8 +197,8 @@ describe('adopted-probe hook', () => {
hook(events, context);
const payload = { city: null };

await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context);
await callbacks.action['gp_adopted_probes.items.update']?.({ payload, keys: [ '1' ] }, context);
await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context);
await callbacks.action['gp_probes.items.update']?.({ payload, keys: [ '1' ] }, context);

expect(adoptedProbes.updateMany.callCount).to.equal(1);

Expand All @@ -224,7 +224,7 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { name: 'My Probe', tags: [{ prefix: 'jimaek', value: 'mytag' }, { prefix: 'jsdelivr', value: 'mytag2' }] };
await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context);
await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context);

expect(adoptedProbes.readMany.callCount).to.equal(1);
expect(nock.isDone()).to.equal(true);
Expand All @@ -237,7 +237,7 @@ describe('adopted-probe hook', () => {
],
});

await callbacks.action['gp_adopted_probes.items.update']?.({ payload, keys: [ '1' ] }, context);
await callbacks.action['gp_probes.items.update']?.({ payload, keys: [ '1' ] }, context);

expect(adoptedProbes.updateMany.callCount).to.equal(0);
});
Expand All @@ -247,7 +247,7 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { city: 'marsel' };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err).to.deep.equal(payloadError('Adopted probes not found.'));
});
Expand All @@ -265,7 +265,7 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { city: 'marsel' };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.status).to.equal(400);
expect(adoptedProbes.updateMany.callCount).to.equal(0);
Expand All @@ -290,7 +290,7 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { city: 'marsel' };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.status).to.equal(400);
});
Expand All @@ -314,7 +314,7 @@ describe('adopted-probe hook', () => {

hook(events, context);
const payload = { city: 'invalidcity' };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(nock.isDone()).to.equal(true);
expect(err.status).to.equal(400);
Expand All @@ -337,7 +337,7 @@ describe('adopted-probe hook', () => {
it('should send valid error if prefix is wrong', async () => {
hook(events, context);
const payload = { tags: [{ prefix: 'wrong_organization', value: 'a' }] };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.message).to.equal('"[0].prefix" must be one of [jimaek, jsdelivr]');
});
Expand All @@ -358,7 +358,7 @@ describe('adopted-probe hook', () => {

const payload = { tags: [{ prefix: 'oldprefix', value: 'a' }] };

await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context);
await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context);


expect(payload).to.deep.equal({ tags: [{ prefix: 'oldprefix', value: 'a' }] });
Expand All @@ -380,7 +380,7 @@ describe('adopted-probe hook', () => {

const payload = { tags: [{ prefix: 'oldprefix', value: 'a' }, { prefix: 'oldprefix', value: 'b' }] };

const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.message).to.equal('"[0].prefix" must be one of [jimaek, jsdelivr]');
});
Expand All @@ -395,15 +395,15 @@ describe('adopted-probe hook', () => {
{ prefix: 'jimaek', value: 'e' },
{ prefix: 'jimaek', value: 'f' },
] };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.message).to.equal('"value" must contain less than or equal to 5 items');
});

it('should send valid error if the tag is too big', async () => {
hook(events, context);
const payload = { tags: [{ prefix: 'jimaek', value: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }] };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.message).to.equal('"[0].value" length must be less than or equal to 32 characters long');
expect(adoptedProbes.updateMany.callCount).to.equal(0);
Expand All @@ -412,7 +412,7 @@ describe('adopted-probe hook', () => {
it('should send valid error if the tag has invalid characters', async () => {
hook(events, context);
const payload = { tags: [{ prefix: 'jimaek', value: '@mytag' }] };
const err = await callbacks.filter['gp_adopted_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);
const err = await callbacks.filter['gp_probes.items.update']?.(payload, { keys: [ '1' ] }, context).catch(err => err);

expect(err.message).to.equal('"[0].value" with value "@mytag" fails to match the required pattern: /^[a-zA-Z0-9-]+$/');
});
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/lib/src/check-firmware-versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const sendNotification = async (probe: ProbeInfo, userId: string, { services, ge
await notificationsService.createOne({
recipient: userId,
item: probe.id,
collection: 'gp_adopted_probes',
collection: 'gp_probes',
type: OUTDATED_FIRMWARE_NOTIFICATION_TYPE,
secondary_type: `${env.TARGET_HW_DEVICE_FIRMWARE}_${env.TARGET_NODE_VERSION}`,
subject: 'Your probe is running an outdated firmware',
Expand Down
Loading

0 comments on commit d6ee3ab

Please sign in to comment.