diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index 47e59637d6..15e8b5eb5b 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-backend/api-report.md @@ -5,169 +5,17 @@ ```ts import express from 'express'; import { IdentityClient } from '@backstage/plugin-auth-node'; -import { Knex } from 'knex'; import { PluginDatabaseManager } from '@backstage/backend-common'; // @public -export function createRouter( - options: RouterOptions, -): Promise; - -// @public -export class DatabaseUserSettingsStore - implements UserSettingsStore -{ - // (undocumented) - static create(options: { - database: PluginDatabaseManager; - }): Promise; - // (undocumented) - delete( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - deleteAll( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - }, - ): Promise; - // (undocumented) - deleteBucket( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - get( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - getAll( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - }, - ): Promise[]>; - // (undocumented) - getBucket( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - set( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - value: string; - }, - ): Promise; - // (undocumented) - transaction(fn: (tx: Knex.Transaction) => Promise): Promise; -} +export function createRouter(options: RouterOptions): Promise; // @public (undocumented) -export type RawDbUserSettingsRow = { - user_entity_ref: string; - bucket: string; - key: string; - value: string; -}; - -// @public (undocumented) -export interface RouterOptions { +export interface RouterOptions { + // (undocumented) + database: PluginDatabaseManager; // (undocumented) identity: IdentityClient; - // (undocumented) - userSettingsStore: UserSettingsStore; -} - -// @public (undocumented) -export type UserSetting = { - bucket: string; - key: string; - value: string; -}; - -// @public -export interface UserSettingsStore { - // (undocumented) - delete( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - deleteAll( - tx: Transaction, - opts: { - userEntityRef: string; - }, - ): Promise; - // (undocumented) - deleteBucket( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - get( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - getAll( - tx: Transaction, - opts: { - userEntityRef: string; - }, - ): Promise; - // (undocumented) - getBucket( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - set( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - value: string; - }, - ): Promise; - // (undocumented) - transaction(fn: (tx: Transaction) => Promise): Promise; } // (No @packageDocumentation comment for this package) diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts index ed69bdcb59..e98ee0010e 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts @@ -67,189 +67,14 @@ describe.each(databases.eachSupportedId())( .orderBy('user_entity_ref') .select(); - describe('getAll', () => { - it('should return empty user settings', async () => { - expect( - await storage.transaction(tx => - storage.getAll(tx, { userEntityRef: 'user-1' }), - ), - ).toEqual([]); - }); - - it('should return all user settings', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-b', - value: 'value-b', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - expect( - await storage.transaction(tx => - storage.getAll(tx, { userEntityRef: 'user-1' }), - ), - ).toEqual([ - { bucket: 'bucket-a', key: 'key-a', value: 'value-a' }, - { bucket: 'bucket-a', key: 'key-b', value: 'value-b' }, - { bucket: 'bucket-c', key: 'key-c', value: 'value-c' }, - ]); - }); - }); - - describe('deleteAll', () => { - it('should delete all user settings', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - await storage.transaction(tx => - storage.deleteAll(tx, { userEntityRef: 'user-1' }), - ); - - expect(await query()).toEqual([ - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - }); - }); - - describe('getBucket', () => { - it('should return an empty bucket', async () => { - expect( - await storage.transaction(tx => - storage.getBucket(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-c', - }), - ), - ).toEqual([]); - }); - - it('should return the settings of the bucket', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - expect( - await storage.transaction(tx => - storage.getBucket(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - }), - ), - ).toEqual([{ bucket: 'bucket-a', key: 'key-a', value: 'value-a' }]); - }); - }); - - describe('deleteBucket', () => { - it('should delete a bucket', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - await storage.transaction(tx => - storage.deleteBucket(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - }), - ); - - expect(await query()).toEqual([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - }); - }); - describe('get', () => { it('should throw an error', async () => { await expect(() => - storage.transaction(tx => - storage.get(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - }), - ), + storage.get({ + userEntityRef: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + }), ).rejects.toThrow(`Unable to find 'key-c' in bucket 'bucket-c'`); }); @@ -269,30 +94,30 @@ describe.each(databases.eachSupportedId())( }, ]); - expect( - await storage.transaction(tx => - storage.get(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - }), - ), - ).toEqual({ bucket: 'bucket-a', key: 'key-a', value: 'value-a' }); + await expect( + storage.get({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + }), + ).resolves.toEqual({ + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }); }); }); describe('set', () => { it('should insert a new setting', async () => { - await storage.transaction(tx => - storage.set(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }), - ); + await storage.set({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }); - expect(await query()).toEqual([ + await expect(query()).resolves.toEqual([ { user_entity_ref: 'user-1', bucket: 'bucket-a', @@ -303,25 +128,21 @@ describe.each(databases.eachSupportedId())( }); it('should overwrite an existing setting', async () => { - await storage.transaction(tx => - storage.set(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }), - ); + await storage.set({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }); - await storage.transaction(tx => - storage.set(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-b', - }), - ); + await storage.set({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-b', + }); - expect(await query()).toEqual([ + await expect(query()).resolves.toEqual([ { user_entity_ref: 'user-1', bucket: 'bucket-a', @@ -334,15 +155,13 @@ describe.each(databases.eachSupportedId())( describe('delete', () => { it('should not throw an error if the entry does not exist', async () => { - await expect(() => - storage.transaction(tx => - storage.delete(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - }), - ), - ).not.toThrow(); + await expect( + storage.delete({ + userEntityRef: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + }), + ).resolves.toBeUndefined(); }); it('should return the setting', async () => { @@ -361,14 +180,12 @@ describe.each(databases.eachSupportedId())( }, ]); - await storage.transaction(tx => - storage.delete(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - }), - ); - expect(await query()).toEqual([ + await storage.delete({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + }); + await expect(query()).resolves.toEqual([ { user_entity_ref: 'user-2', bucket: 'bucket-c', diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts index 961149c9ea..4b46b6383f 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts @@ -42,9 +42,7 @@ export type RawDbUserSettingsRow = { * * @public */ -export class DatabaseUserSettingsStore - implements UserSettingsStore -{ +export class DatabaseUserSettingsStore implements UserSettingsStore { static async create(options: { database: PluginDatabaseManager; }): Promise { @@ -62,93 +60,56 @@ export class DatabaseUserSettingsStore private constructor(private readonly db: Knex) {} - async getAll(tx: Knex.Transaction, opts: { userEntityRef: string }) { - const settings = await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef }) - .select('bucket', 'key', 'value'); - - return settings; - } - - async deleteAll( - tx: Knex.Transaction, - opts: { userEntityRef: string }, - ): Promise { - await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef }) - .delete(); - } - - async getBucket( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise { - const settings = await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef, bucket: opts.bucket }) - .select(['bucket', 'key', 'value']); - - return settings; - } - - async deleteBucket( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise { - await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef, bucket: opts.bucket }) - .delete(); - } - - async get( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise { - const setting = await tx('user_settings') + async get(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise { + const rows = await this.db('user_settings') .where({ - user_entity_ref: opts.userEntityRef, - bucket: opts.bucket, - key: opts.key, + user_entity_ref: options.userEntityRef, + bucket: options.bucket, + key: options.key, }) .select(['bucket', 'key', 'value']); - if (!setting.length) { + if (!rows.length) { throw new NotFoundError( - `Unable to find '${opts.key}' in bucket '${opts.bucket}'`, + `Unable to find '${options.key}' in bucket '${options.bucket}'`, ); } - return setting[0]; + return rows[0]; } - async set( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string; key: string; value: string }, - ): Promise { - await tx('user_settings') + async set(options: { + userEntityRef: string; + bucket: string; + key: string; + value: string; + }): Promise { + await this.db('user_settings') .insert({ - user_entity_ref: opts.userEntityRef, - bucket: opts.bucket, - key: opts.key, - value: opts.value, + user_entity_ref: options.userEntityRef, + bucket: options.bucket, + key: options.key, + value: options.value, }) .onConflict(['user_entity_ref', 'bucket', 'key']) - .merge({ value: opts.value }); + .merge(['value']); } - async delete( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise { - await tx('user_settings') + async delete(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise { + await this.db('user_settings') .where({ - user_entity_ref: opts.userEntityRef, - bucket: opts.bucket, - key: opts.key, + user_entity_ref: options.userEntityRef, + bucket: options.bucket, + key: options.key, }) .delete(); } - - async transaction(fn: (tx: Knex.Transaction) => Promise) { - return await this.db.transaction(fn); - } } diff --git a/plugins/user-settings-backend/src/database/UserSettingsStore.ts b/plugins/user-settings-backend/src/database/UserSettingsStore.ts index b86673270f..d14af091ef 100644 --- a/plugins/user-settings-backend/src/database/UserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/UserSettingsStore.ts @@ -15,7 +15,7 @@ */ /** - * @public + * A single setting in a bucket */ export type UserSetting = { bucket: string; @@ -25,41 +25,24 @@ export type UserSetting = { /** * Store definition for the user settings. - * - * @public */ -export interface UserSettingsStore { - transaction(fn: (tx: Transaction) => Promise): Promise; +export interface UserSettingsStore { + get(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise; - get( - tx: Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise; + set(options: { + userEntityRef: string; + bucket: string; + key: string; + value: string; + }): Promise; - set( - tx: Transaction, - opts: { userEntityRef: string; bucket: string; key: string; value: string }, - ): Promise; - - delete( - tx: Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise; - - getBucket( - tx: Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise; - - deleteBucket( - tx: Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise; - - getAll( - tx: Transaction, - opts: { userEntityRef: string }, - ): Promise; - - deleteAll(tx: Transaction, opts: { userEntityRef: string }): Promise; + delete(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise; } diff --git a/plugins/user-settings-backend/src/database/index.ts b/plugins/user-settings-backend/src/database/index.ts index 2552b7db13..813cdeaae3 100644 --- a/plugins/user-settings-backend/src/database/index.ts +++ b/plugins/user-settings-backend/src/database/index.ts @@ -14,8 +14,4 @@ * limitations under the License. */ -export { - DatabaseUserSettingsStore, - type RawDbUserSettingsRow, -} from './DatabaseUserSettingsStore'; -export type { UserSettingsStore, UserSetting } from './UserSettingsStore'; +export {}; diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index c1feb284a0..7640714477 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -14,20 +14,14 @@ * limitations under the License. */ -import { AuthenticationError } from '@backstage/errors'; import { IdentityClient } from '@backstage/plugin-auth-node'; import express from 'express'; import request from 'supertest'; -import { UserSettingsStore } from '../database'; -import { createRouter } from './router'; +import { UserSettingsStore } from '../database/UserSettingsStore'; +import { createRouterInternal } from './router'; describe('createRouter', () => { - const userSettingsStore: jest.Mocked> = { - transaction: jest.fn(), - deleteAll: jest.fn(), - getAll: jest.fn(), - getBucket: jest.fn(), - deleteBucket: jest.fn(), + const userSettingsStore: jest.Mocked = { get: jest.fn(), set: jest.fn(), delete: jest.fn(), @@ -40,9 +34,7 @@ describe('createRouter', () => { let app: express.Express; beforeEach(async () => { - userSettingsStore.transaction.mockImplementation(fn => fn('tx')); - - const router = await createRouter({ + const router = await createRouterInternal({ userSettingsStore, identity: identityClient as IdentityClient, }); @@ -54,147 +46,6 @@ describe('createRouter', () => { jest.resetAllMocks(); }); - describe('GET /buckets/', () => { - it('returns ok', async () => { - const settings = [ - { bucket: 'a', key: 'a', value: 'a' }, - { bucket: 'b', key: 'b', value: 'b' }, - ]; - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.getAll.mockResolvedValue(settings); - - const responses = await request(app) - .get('/buckets/') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(200); - expect(responses.body).toEqual(settings); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.getAll).toHaveBeenCalledTimes(1); - expect(userSettingsStore.getAll).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/buckets/'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getAll).not.toHaveBeenCalled(); - }); - - it('returns an error if the token is not valid', async () => { - authenticateMock.mockRejectedValue( - new AuthenticationError('Invalid token'), - ); - - const responses = await request(app) - .get('/buckets/') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getAll).not.toHaveBeenCalled(); - }); - }); - - describe('DELETE /buckets/', () => { - it('returns ok', async () => { - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.deleteAll.mockResolvedValue(); - - const responses = await request(app) - .delete('/buckets/') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(204); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.deleteAll).toHaveBeenCalledTimes(1); - expect(userSettingsStore.deleteAll).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/buckets/'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getAll).not.toHaveBeenCalled(); - }); - }); - - describe('GET /buckets/:bucket', () => { - it('returns ok', async () => { - const settings = [ - { bucket: 'my-bucket', key: 'a', value: 'a' }, - { bucket: 'my-bucket', key: 'b', value: 'b' }, - ]; - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.getBucket.mockResolvedValue(settings); - - const responses = await request(app) - .get('/buckets/my-bucket') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(200); - expect(responses.body).toEqual(settings); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.getBucket).toHaveBeenCalledTimes(1); - expect(userSettingsStore.getBucket).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - bucket: 'my-bucket', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/buckets/my-bucket'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getBucket).not.toHaveBeenCalled(); - }); - }); - - describe('DELETE /buckets/:bucket', () => { - it('returns ok', async () => { - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.deleteBucket.mockResolvedValue(); - - const responses = await request(app) - .delete('/buckets/my-bucket') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(204); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.deleteBucket).toHaveBeenCalledTimes(1); - expect(userSettingsStore.deleteBucket).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - bucket: 'my-bucket', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/buckets/my-bucket'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.deleteBucket).not.toHaveBeenCalled(); - }); - }); - describe('GET /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; @@ -213,7 +64,7 @@ describe('createRouter', () => { expect(authenticateMock).toHaveBeenCalledWith('foo'); expect(userSettingsStore.get).toHaveBeenCalledTimes(1); - expect(userSettingsStore.get).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.get).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -246,7 +97,7 @@ describe('createRouter', () => { expect(authenticateMock).toHaveBeenCalledWith('foo'); expect(userSettingsStore.delete).toHaveBeenCalledTimes(1); - expect(userSettingsStore.delete).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.delete).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -283,14 +134,14 @@ describe('createRouter', () => { expect(authenticateMock).toHaveBeenCalledWith('foo'); expect(userSettingsStore.set).toHaveBeenCalledTimes(1); - expect(userSettingsStore.set).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.set).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', value: 'a', }); expect(userSettingsStore.get).toHaveBeenCalledTimes(1); - expect(userSettingsStore.get).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.get).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index 58580eddda..d677ee4bfb 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { errorHandler } from '@backstage/backend-common'; +import { errorHandler, PluginDatabaseManager } from '@backstage/backend-common'; import { AuthenticationError, InputError } from '@backstage/errors'; import { getBearerTokenFromAuthorizationHeader, @@ -22,13 +22,14 @@ import { } from '@backstage/plugin-auth-node'; import express, { Request } from 'express'; import Router from 'express-promise-router'; -import { UserSettingsStore } from '../database'; +import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; +import { UserSettingsStore } from '../database/UserSettingsStore'; /** * @public */ -export interface RouterOptions { - userSettingsStore: UserSettingsStore; +export interface RouterOptions { + database: PluginDatabaseManager; identity: IdentityClient; } @@ -37,10 +38,23 @@ export interface RouterOptions { * * @public */ -export async function createRouter( - options: RouterOptions, +export async function createRouter( + options: RouterOptions, ): Promise { - const { userSettingsStore, identity } = options; + const userSettingsStore = await DatabaseUserSettingsStore.create({ + database: options.database, + }); + + return await createRouterInternal({ + userSettingsStore, + identity: options.identity, + }); +} + +export async function createRouterInternal(options: { + identity: IdentityClient; + userSettingsStore: UserSettingsStore; +}): Promise { const router = Router(); router.use(express.json()); @@ -57,65 +71,21 @@ export async function createRouter( } // throws an AuthenticationError in case the token is invalid - const user = await identity.authenticate(token); + const user = await options.identity.authenticate(token); return user.identity.userEntityRef; }; - // get all user related settings - router.get('/buckets', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - - const settings = await userSettingsStore.transaction(tx => - userSettingsStore.getAll(tx, { userEntityRef }), - ); - - res.json(settings); - }); - - // remove all user related settings - router.delete('/buckets', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - - await userSettingsStore.transaction(tx => - userSettingsStore.deleteAll(tx, { userEntityRef }), - ); - - res.send(204).end(); - }); - - // get a single bucket - router.get('/buckets/:bucket', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - const { bucket } = req.params; - - const settings = await userSettingsStore.transaction(tx => - userSettingsStore.getBucket(tx, { userEntityRef, bucket }), - ); - - res.json(settings); - }); - - // delete a whole bucket - router.delete('/buckets/:bucket', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - const { bucket } = req.params; - - await userSettingsStore.transaction(tx => - userSettingsStore.deleteBucket(tx, { userEntityRef, bucket }), - ); - - res.status(204).end(); - }); - // get a single value router.get('/buckets/:bucket/keys/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; - const setting = await userSettingsStore.transaction(tx => - userSettingsStore.get(tx, { userEntityRef, bucket, key }), - ); + const setting = await options.userSettingsStore.get({ + userEntityRef, + bucket, + key, + }); res.json(setting); }); @@ -130,14 +100,16 @@ export async function createRouter( throw new InputError('Value must be a string'); } - const setting = await userSettingsStore.transaction(async tx => { - await userSettingsStore.set(tx, { - userEntityRef, - bucket, - key, - value, - }); - return userSettingsStore.get(tx, { userEntityRef, bucket, key }); + await options.userSettingsStore.set({ + userEntityRef, + bucket, + key, + value, + }); + const setting = await options.userSettingsStore.get({ + userEntityRef, + bucket, + key, }); res.json(setting); @@ -148,9 +120,7 @@ export async function createRouter( const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; - await userSettingsStore.transaction(tx => - userSettingsStore.delete(tx, { userEntityRef, bucket, key }), - ); + await options.userSettingsStore.delete({ userEntityRef, bucket, key }); res.send(204).end(); }); diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 3cd3704ca8..28af3a163f 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -20,8 +20,8 @@ import { Router } from 'express'; import { Server } from 'http'; import Knex from 'knex'; import { Logger } from 'winston'; -import { DatabaseUserSettingsStore } from '../database'; -import { createRouter } from './router'; +import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; +import { createRouterInternal } from './router'; export interface ServerOptions { port: number; @@ -50,7 +50,7 @@ export async function startStandaloneServer( }), } as IdentityClient; - const router = await createRouter({ + const router = await createRouterInternal({ userSettingsStore: await DatabaseUserSettingsStore.create({ database: { getClient: async () => database }, }),