diff --git a/src/compose/commit.ts b/src/compose/commit.ts index 17705f82..5a0b0733 100644 --- a/src/compose/commit.ts +++ b/src/compose/commit.ts @@ -5,6 +5,10 @@ const cache: { [appId: number]: string } = {}; export async function getCommitForApp( appId: number, ): Promise { + if (isNaN(appId)) { + return; + } + if (cache[appId] != null) { return cache[appId]; } diff --git a/src/lib/api-keys.ts b/src/lib/api-keys.ts index e8ab161a..e2e1a1c5 100644 --- a/src/lib/api-keys.ts +++ b/src/lib/api-keys.ts @@ -134,6 +134,7 @@ export const authMiddleware: AuthorizedRequestHandler = async ( // no need to authenticate, shortcut if (!needsAuth) { + req.auth.isScoped = () => true; return next(); } diff --git a/test/21-supervisor-api.spec.ts b/test/21-supervisor-api.spec.ts index b367736e..9c2b5915 100644 --- a/test/21-supervisor-api.spec.ts +++ b/test/21-supervisor-api.spec.ts @@ -12,8 +12,12 @@ import mockedAPI = require('./lib/mocked-device-api'); import * as applicationManager from '../src/compose/application-manager'; import { InstancedAppState } from '../src/types/state'; +import * as serviceManager from '../src/compose/service-manager'; + import * as apiKeys from '../src/lib/api-keys'; import * as db from '../src/db'; +import * as config from '../src/config'; +import { Service } from '../src/compose/service'; const mockedOptions = { listenPort: 54321, @@ -354,6 +358,67 @@ describe('SupervisorAPI', () => { }); }); + describe('GET /v2/state/status', () => { + let serviceManagerMock: SinonStub; + + const mockService = ( + appId: number, + serviceId: number, + serviceName: string, + ) => { + return { + appId, + status: 'Running', + serviceName, + imageId: appId, + serviceId, + containerId: Math.random() + .toString(36) + .replace(/[^a-z]+/g, '') + .substr(0, 16), + createdAt: new Date(), + } as Service; + }; + + before(async () => { + await config.set({ localMode: true }); + serviceManagerMock = stub(serviceManager, 'getAll').resolves([]); + }); + + after(async () => { + await config.set({ localMode: false }); + serviceManagerMock.restore(); + }); + + it('should succeed in LocalMode with a single application', async () => { + serviceManagerMock.resolves([mockService(1, 1, 'main')]); + + const { body } = await request + .get('/v2/state/status') + .set('Accept', 'application/json') + .expect(200); + + expect(body).to.have.property('status').which.equals('success'); + expect(body).to.have.property('appState').which.equals('applied'); + expect(body) + .to.have.property('containers') + .which.is.an('array') + .with.lengthOf(1); + }); + + it('should error in LocalMode with multiple applications', async () => { + serviceManagerMock.resolves([ + mockService(1, 1, 'main'), + mockService(2, 2, 'extra'), + ]); + + await request + .get('/v2/state/status') + .set('Accept', 'application/json') + .expect(405); + }); + }); + // TODO: add tests for rest of V2 endpoints });