From 54a99460ceaa14dc42cd9539fcad280858f7533c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Fri, 1 Oct 2021 10:59:43 +0200 Subject: [PATCH] fix: add projects api for oss as well --- src/lib/db/project-store.ts | 4 ++- src/lib/routes/admin-api/project/index.ts | 13 ++++++++ src/lib/services/project-service.ts | 6 ++-- src/lib/types/stores/project-store.ts | 5 +++ .../api/admin/project/projects.e2e.test.ts | 32 +++++++++++++++++++ 5 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 src/test/e2e/api/admin/project/projects.e2e.test.ts diff --git a/src/lib/db/project-store.ts b/src/lib/db/project-store.ts index adba0644c5..8d6efc3b43 100644 --- a/src/lib/db/project-store.ts +++ b/src/lib/db/project-store.ts @@ -6,6 +6,7 @@ import { IProject } from '../types/model'; import { IProjectHealthUpdate, IProjectInsert, + IProjectQuery, IProjectStore, } from '../types/stores/project-store'; import { DEFAULT_ENV } from '../util/constants'; @@ -43,10 +44,11 @@ class ProjectStore implements IProjectStore { return present; } - async getAll(): Promise { + async getAll(query: IProjectQuery = {}): Promise { const rows = await this.db .select(COLUMNS) .from(TABLE) + .where(query) .orderBy('name', 'asc'); return rows.map(this.mapRow); diff --git a/src/lib/routes/admin-api/project/index.ts b/src/lib/routes/admin-api/project/index.ts index e55ec72cc3..22f982fbe7 100644 --- a/src/lib/routes/admin-api/project/index.ts +++ b/src/lib/routes/admin-api/project/index.ts @@ -1,15 +1,28 @@ +import { Request, Response } from 'express'; import Controller from '../../controller'; import { IUnleashConfig } from '../../../types/option'; import { IUnleashServices } from '../../../types/services'; import ProjectFeaturesController from './features'; import EnvironmentsController from './environments'; import ProjectHealthReport from './health-report'; +import ProjectService from '../../../services/project-service'; export default class ProjectApi extends Controller { + private projectService: ProjectService; + constructor(config: IUnleashConfig, services: IUnleashServices) { super(config); + this.projectService = services.projectService; + this.get('/', this.getProjects); this.use('/', new ProjectFeaturesController(config, services).router); this.use('/', new EnvironmentsController(config, services).router); this.use('/', new ProjectHealthReport(config, services).router); } + + async getProjects(req: Request, res: Response): Promise { + const projects = await this.projectService.getProjects({ + id: 'default', + }); + res.json({ version: 1, projects }).end(); + } } diff --git a/src/lib/services/project-service.ts b/src/lib/services/project-service.ts index 1f324bba61..0141ce407d 100644 --- a/src/lib/services/project-service.ts +++ b/src/lib/services/project-service.ts @@ -24,7 +24,7 @@ import { IEnvironmentStore } from '../types/stores/environment-store'; import { IFeatureTypeStore } from '../types/stores/feature-type-store'; import { IFeatureToggleStore } from '../types/stores/feature-toggle-store'; import { IFeatureEnvironmentStore } from '../types/stores/feature-environment-store'; -import { IProjectStore } from '../types/stores/project-store'; +import { IProjectQuery, IProjectStore } from '../types/stores/project-store'; import { IRole } from '../types/stores/access-store'; import { IEventStore } from '../types/stores/event-store'; import FeatureToggleServiceV2 from './feature-toggle-service-v2'; @@ -91,8 +91,8 @@ export default class ProjectService { this.logger = config.getLogger('services/project-service.js'); } - async getProjects(): Promise { - const projects = await this.store.getAll(); + async getProjects(query?: IProjectQuery): Promise { + const projects = await this.store.getAll(query); const projectsWithCount = await Promise.all( projects.map(async (p) => { let featureCount = 0; diff --git a/src/lib/types/stores/project-store.ts b/src/lib/types/stores/project-store.ts index 81427a8e9b..adcff6168e 100644 --- a/src/lib/types/stores/project-store.ts +++ b/src/lib/types/stores/project-store.ts @@ -17,6 +17,10 @@ export interface IProjectHealthUpdate { health: number; } +export interface IProjectQuery { + id?: string; +} + export interface IProjectStore extends Store { hasProject(id: string): Promise; updateHealth(healthUpdate: IProjectHealthUpdate): Promise; @@ -28,4 +32,5 @@ export interface IProjectStore extends Store { getEnvironmentsForProject(id: string): Promise; getMembers(projectId: string): Promise; count(): Promise; + getAll(query?: IProjectQuery): Promise; } diff --git a/src/test/e2e/api/admin/project/projects.e2e.test.ts b/src/test/e2e/api/admin/project/projects.e2e.test.ts new file mode 100644 index 0000000000..9bbae4ccff --- /dev/null +++ b/src/test/e2e/api/admin/project/projects.e2e.test.ts @@ -0,0 +1,32 @@ +import dbInit from '../../../helpers/database-init'; +import { setupApp } from '../../../helpers/test-helper'; +import getLogger from '../../../../fixtures/no-logger'; +import ProjectStore from '../../../../../lib/db/project-store'; + +let app; +let db; + +let projectStore: ProjectStore; + +beforeAll(async () => { + db = await dbInit('projects_api_serial', getLogger); + app = await setupApp(db.stores); + projectStore = db.stores.projectStore; +}); + +afterAll(async () => { + await app.destroy(); + await db.destroy(); +}); + +test('Should ONLY return default project', async () => { + projectStore.create({ id: 'test2', name: 'test', description: '' }); + + const { body } = await app.request + .get('/api/admin/projects') + .expect(200) + .expect('Content-Type', /json/); + + expect(body.projects).toHaveLength(1); + expect(body.projects[0].id).toBe('default'); +});