diff --git a/apps/api/app/routes/enrolment.ts b/apps/api/app/routes/enrolment.ts index 1391e62d..e7eff5e2 100644 --- a/apps/api/app/routes/enrolment.ts +++ b/apps/api/app/routes/enrolment.ts @@ -1,7 +1,5 @@ import { Actor } from '@nestri/core/actor'; -import { Env } from '@nestri/core/env'; import { ErrorCodes, VisibleError } from '@nestri/core/error'; -import { Machine } from '@nestri/core/machine/index'; import { Enrolment } from '@nestri/core/steam/enrolment'; import { Identity } from '@nestri/core/user/identity'; import { Hono } from 'hono'; @@ -31,32 +29,23 @@ import { ErrorResponses, machineOnly, Result, validator } from '../utils'; */ export namespace EnrolmentApi { /** - * A sign-in on one of Nestri's own machines is also proof of the Steam - * account, so it links it: the person scanned a QR code on hardware we - * run, the Steam id is the subject of the token Valve issued there, and - * who they are came from the edge. Asking them to sign in to Steam a - * second time, in a browser, would prove nothing new. - * - * **Only the fleet.** On a host somebody brought, the report is that - * person's machine vouching for itself, and a machine can say anything. - * Linking from it would let any host operator attach any Steam account to - * any user enrolled on it. + * A Steam sign-in on a host is also proof of the Steam account, so it + * links it: the person scanned a QR code with the Steam app, the Steam id + * is the subject of the token Valve issued there, and who they are came + * from the edge. Asking them to sign in to Steam a second time, in a + * browser, would prove nothing new. * * Never a reason to refuse the report. The sign-in happened and the * enrolment is recorded either way; a Steam account already linked to * somebody else stays theirs, and is left for the person to sort out on * the website. */ - async function linkIfFleet(machineId: string, userId: string, steamId: string) { - const fleet = Env.get().FLEET_ORGANISATION_ID; - if (!fleet) return; - const machine = await Machine.fromID(machineId); - if (machine?.organisationId !== fleet) return; + async function link(machineId: string, userId: string, steamId: string) { try { await Identity.linkSteam({ userId, steamId }); } catch (err) { if (err instanceof VisibleError) { - console.warn('a fleet sign-in was not linked', { machineId, userId, reason: err.message }); + console.warn('a sign-in was not linked', { machineId, userId, reason: err.message }); return; } throw err; @@ -102,7 +91,7 @@ export namespace EnrolmentApi { userId: body.userId, steamId: body.steamId }); - await linkIfFleet(Actor.machineID, body.userId, body.steamId); + await link(Actor.machineID, body.userId, body.steamId); return c.json({ data: enrolment }); } ) diff --git a/apps/api/install/desktop-version.ts b/apps/api/install/desktop-version.ts index ed4cfd70..62522fa2 100644 --- a/apps/api/install/desktop-version.ts +++ b/apps/api/install/desktop-version.ts @@ -3,4 +3,4 @@ * release of that version is published, the same way the host installer's * default is, so what a person downloads changes only through review. */ -export const DESKTOP_VERSION = '0.1.0'; +export const DESKTOP_VERSION = '0.1.1'; diff --git a/apps/api/install/install.sh b/apps/api/install/install.sh index ce9ca2d1..47e147a2 100755 --- a/apps/api/install/install.sh +++ b/apps/api/install/install.sh @@ -24,7 +24,7 @@ set -eu API="${NESTRI_API:-https://api.nestri.io}" # Pinned, not "latest", so the script and the binary it installs are a pair # somebody chose. Bump when cutting a release; NESTRI_HOST_VERSION overrides it. -DEFAULT_VERSION="0.2.13" +DEFAULT_VERSION="0.2.14" VERSION="${NESTRI_HOST_VERSION:-$DEFAULT_VERSION}" BIN_DIR="${NESTRI_BIN_DIR:-/usr/local/bin}" STATE_DIR=/var/lib/nestri diff --git a/apps/api/test/enrolment.test.ts b/apps/api/test/enrolment.test.ts index 9331c35f..9e56106d 100644 --- a/apps/api/test/enrolment.test.ts +++ b/apps/api/test/enrolment.test.ts @@ -393,7 +393,7 @@ describe('The enrolment surface refuses a token', () => { }); }); -describe('A sign-in on the fleet links the Steam account', () => { +describe('A sign-in on a host links the Steam account', () => { /** A fleet host the API knows is the fleet, and a person to enrol on it. */ async function fleetHost(label: string) { const operator = await Fixtures.owner(`${label}-operator`); @@ -436,11 +436,11 @@ describe('A sign-in on the fleet links the Steam account', () => { expect(await linked(steamId(9001))).toHaveLength(1); }); - test('a host somebody brought cannot link anything', async () => { + test('a host somebody brought links it too', async () => { const host = await registeredHost('own-host-link'); const res = await enrol(host, { userId: host.userId, steamId: steamId(9002) }); expect(res.status).toBe(200); - expect(await linked(steamId(9002))).toHaveLength(0); + expect((await linked(steamId(9002))).map((r) => r.user_id)).toEqual([host.userId]); }); test('an account already linked elsewhere stays there, and the report still lands', async () => {