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

Check user access to the device type provided to /config/vars #1439

Merged
merged 1 commit into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions src/features/vars-schema/schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { RequestHandler } from 'express';
import type { JSONSchema6 } from 'json-schema';

import { sbvrUtils } from '@balena/pinejs';
import {
BLOCKED_NAMES,
DEVICE_TYPE_SPECIFIC_CONFIG_VAR_PROPERTIES,
Expand All @@ -13,19 +13,54 @@ import {
ALLOWED_NAMESPACES,
} from './env-vars';

const { api } = sbvrUtils;

// Return config variable constants for use by external components.
// A query string parameter of 'deviceType' is accepted, which should
// be a device type slug.
export const schema: RequestHandler = (req, res) => {
export const schema: RequestHandler = async (req, res) => {
const deviceTypeSlug = await (async () => {
if (typeof req.query.deviceType !== 'string') {
return;
}

const resinApi = api.resin.clone({ passthrough: { req } });
// Ensure that the user has access to the provided device type.
const [dt] = (await resinApi.get({
resource: 'device_type',
options: {
$top: 1,
$select: 'slug',
$filter: {
device_type_alias: {
$any: {
$alias: 'dta',
$expr: {
dta: {
is_referenced_by__alias: req.query.deviceType,
},
},
},
},
},
},
})) as Array<{ slug: string }>;

// We do not throw when the DT is not found for backwards compatibility reasons.
return dt?.slug;
})();

const configVarSchema: JSONSchema6 = {
type: 'object',
$schema: 'http://json-schema.org/draft-06/schema#',
properties: Object.assign(
{},
SUPERVISOR_CONFIG_VAR_PROPERTIES,
...DEVICE_TYPE_SPECIFIC_CONFIG_VAR_PROPERTIES.filter((config) =>
config.capableDeviceTypes.includes(req.query.deviceType as string),
).map((config) => config.properties),
...(deviceTypeSlug != null
? DEVICE_TYPE_SPECIFIC_CONFIG_VAR_PROPERTIES.filter((config) =>
config.capableDeviceTypes.includes(deviceTypeSlug),
).map((config) => config.properties)
: []),
),
};

Expand Down
8 changes: 8 additions & 0 deletions test/01_basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ describe('Basic', () => {
checkBaseVarsResult(vars);
});

it(`should return the base vars when device type is not found`, async () => {
const { body: vars } = await supertest()
.get(`/config/vars?deviceType=wrong-device-type`)
.expect(200);

checkBaseVarsResult(vars);
});

[
{ deviceType: 'beaglebone-black' },
{
Expand Down
4 changes: 2 additions & 2 deletions test/02_device-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('device type resource', () => {
expect(deviceType).to.have.property('name').that.is.a('string');
});

expect(res.body.d).to.have.property('length', 14);
expect(res.body.d).to.have.property('length', 16);
});
});

Expand Down Expand Up @@ -217,7 +217,7 @@ describe('device type endpoints', () => {
it('should return a proper result', async () => {
const res = await supertest().get('/device-types/v1').expect(200);
expect(res.body).to.be.an('array');
expect(res.body).to.have.property('length', 15);
expect(res.body).to.have.property('length', 17);
const rpi3config = _.find(res.body, { slug: 'raspberrypi3' });
expect(rpi3config).to.be.an('object');
expect(rpi3config).to.have.property('buildId', '2.19.0+rev1.prod');
Expand Down
8 changes: 4 additions & 4 deletions test/09_contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('contracts', () => {
await fetchContractsLocally([contractRepository]);
const contracts = await getContracts('hw.device-type');

expect(contracts).to.have.length(14);
expect(contracts).to.have.length(16);
expect(contracts.find((contract) => contract.slug === 'raspberrypi3')).to
.not.be.undefined;
});
Expand All @@ -96,7 +96,7 @@ describe('contracts', () => {
]);
const contracts = await getContracts('hw.device-type');

expect(contracts).to.have.length(15);
expect(contracts).to.have.length(17);
expect(
contracts.find((contract) => contract.slug === 'other-contract-dt'),
).to.not.be.undefined;
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('contracts', () => {
(dbDeviceType) => dbDeviceType.slug === 'fincm3',
);

expect(contracts).to.have.length(15);
expect(contracts).to.have.length(17);
expect(newDt).to.not.be.undefined;
expect(finDt).to.have.property('name', 'Fin');
});
Expand Down Expand Up @@ -232,7 +232,7 @@ describe('contracts', () => {
(dbDeviceType) => dbDeviceType.slug === 'raspberry-pi',
);

expect(dbDeviceTypes).to.have.length(15);
expect(dbDeviceTypes).to.have.length(17);
expect(newDt).to.not.be.undefined;
expect(finDt).to.have.property('name', 'Fin');
expect(finDt).to.have.deep.property(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"slug": "jetson-tx2",
"version": "1",
"type": "hw.device-type",
"aliases": [],
"name": "Nvidia Jetson TX2",
"assets": {
"logo": {
"url": "./jetson-tx2.svg",
"name": "logo"
}
},
"data": {
"arch": "aarch64",
"hdmi": true,
"led": false,
"connectivity": {
"bluetooth": true,
"wifi": true
},
"storage": {
"internal": true
},
"media": {
"defaultBoot": "internal",
"altBoot": ["sdcard"]
},
"is_private": false
},
"partials": {
"bootDeviceExternal": [
"Connect power to the {{name}} and press and hold the POWER push button for 1 second"
],
"flashIndicator": ["all LEDs are off"],
"bootDevice": ["Remove and re-connect power to the {{name}}"]
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"slug": "up-board",
"version": "1",
"type": "hw.device-type",
"aliases": [],
"name": "UP Board",
"assets": {
"logo": {
"url": "./up-board.svg",
"name": "logo"
}
},
"data": {
"arch": "amd64",
"family": "family-upboard",
"hdmi": true,
"led": true,
"connectivity": {
"bluetooth": false,
"wifi": false
},
"storage": {
"internal": true
},
"media": {
"defaultBoot": "internal",
"altBoot": ["usb_mass_storage"]
},
"is_private": false
},
"partials": {
"bootDeviceExternal": [
"Power on the {{name}} with a keyboard connected.",
"Press the F7 key while BIOS is loading to enter the boot menu.",
"Select the \"UEFI:\" option from the boot menu."
],
"flashIndicator": ["all LEDs are off"],
"bootDevice": ["Power up the {{name}}"]
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading