feat: use buckets prefix for routes

Signed-off-by: Dominik Schwank <dominik.schwank@sda.se>
This commit is contained in:
Dominik Schwank
2022-09-01 11:12:44 +02:00
committed by Fredrik Adelöw
parent 1e12c7f5f1
commit 31a2403044
4 changed files with 71 additions and 62 deletions
@@ -52,7 +52,7 @@ describe('Persistent Storage API', () => {
beforeEach(() => {
server.use(
rest.get(`${mockBaseUrl}/`, async (_req, res, ctx) => {
rest.get(`${mockBaseUrl}/buckets/`, async (_req, res, ctx) => {
return res(ctx.json([]));
}),
);
@@ -64,9 +64,12 @@ describe('Persistent Storage API', () => {
const storage = createPersistentStorage();
server.use(
rest.get(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => {
return res(ctx.json({ value: 'a' }));
}),
rest.get(
`${mockBaseUrl}/buckets/:bucket/:key`,
async (_req, res, ctx) => {
return res(ctx.json({ value: 'a' }));
},
),
);
expect(storage.snapshot('myfakekey').value).toBeUndefined();
@@ -82,7 +85,7 @@ describe('Persistent Storage API', () => {
const dummyValue = 'a';
server.use(
rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => {
rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => {
const body = await req.json();
const data = { value: JSON.stringify(dummyValue) };
expect(body).toEqual(data);
@@ -102,7 +105,7 @@ describe('Persistent Storage API', () => {
};
server.use(
rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => {
rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => {
const body = await req.json();
const data = { value: JSON.stringify(dummyValue) };
expect(body).toEqual(data);
@@ -122,7 +125,7 @@ describe('Persistent Storage API', () => {
const mockData = { hello: 'im a great new value' };
server.use(
rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => {
rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => {
const body = await req.json();
const data = { value: JSON.stringify(mockData) };
expect(body).toEqual(data);
@@ -162,9 +165,12 @@ describe('Persistent Storage API', () => {
const selectedKeyNextHandler = jest.fn();
server.use(
rest.delete(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => {
return res(ctx.status(204));
}),
rest.delete(
`${mockBaseUrl}/buckets/:bucket/:key`,
async (_req, res, ctx) => {
return res(ctx.status(204));
},
),
);
await new Promise<void>(resolve => {
@@ -196,7 +202,7 @@ describe('Persistent Storage API', () => {
const selectedKeyNextHandler = jest.fn();
server.use(
rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => {
rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => {
const { bucket, key } = req.params;
const { value } = await req.json();
@@ -205,7 +211,7 @@ describe('Persistent Storage API', () => {
return res(ctx.json({ value }));
}),
rest.get(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => {
rest.get(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => {
const { bucket, key } = req.params;
expect(bucket).toEqual('default.profile/something');
@@ -253,7 +259,7 @@ describe('Persistent Storage API', () => {
});
server.use(
rest.get(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => {
rest.get(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => {
const { bucket, key } = req.params;
expect(bucket).toEqual('Test.Mock.Thing');
@@ -290,9 +296,12 @@ describe('Persistent Storage API', () => {
const data = { foo: 'bar', baz: [{ foo: 'bar' }] };
server.use(
rest.get(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => {
return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) })));
}),
rest.get(
`${mockBaseUrl}/buckets/:bucket/:key`,
async (_req, res, ctx) => {
return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) })));
},
),
);
await new Promise<void>(resolve => {
@@ -182,7 +182,7 @@ export class PersistentStorage implements StorageApi {
const baseUrl = await this.discoveryApi.getBaseUrl('user-settings');
const encodedNamespace = encodeURIComponent(this.namespace);
const encodedKey = encodeURIComponent(key);
return `${baseUrl}/${encodedNamespace}/${encodedKey}`;
return `${baseUrl}/buckets/${encodedNamespace}/${encodedKey}`;
}
private async notifyChanges<T>(snapshot: StorageValueSnapshot<T>) {
@@ -54,7 +54,7 @@ describe('createRouter', () => {
jest.resetAllMocks();
});
describe('GET /', () => {
describe('GET /buckets/', () => {
it('returns ok', async () => {
const settings = [
{ bucket: 'a', key: 'a', value: 'a' },
@@ -67,21 +67,21 @@ describe('createRouter', () => {
userSettingsStore.getAll.mockResolvedValue(settings);
const responses = await request(app)
.get('/')
.get('/buckets/')
.set('Authorization', 'Bearer foo');
expect(responses.status).toEqual(200);
expect(responses.body).toEqual(settings);
expect(authenticateMock).toHaveBeenCalledWith('foo');
expect(userSettingsStore.getAll).toBeCalledTimes(1);
expect(userSettingsStore.getAll).toBeCalledWith('tx', {
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('/');
const responses = await request(app).get('/buckets/');
expect(responses.status).toEqual(401);
expect(userSettingsStore.getAll).not.toHaveBeenCalled();
@@ -93,7 +93,7 @@ describe('createRouter', () => {
);
const responses = await request(app)
.get('/')
.get('/buckets/')
.set('Authorization', 'Bearer foo');
expect(responses.status).toEqual(401);
@@ -101,7 +101,7 @@ describe('createRouter', () => {
});
});
describe('DELETE /', () => {
describe('DELETE /buckets/', () => {
it('returns ok', async () => {
authenticateMock.mockResolvedValue({
identity: { userEntityRef: 'user-1' },
@@ -110,27 +110,27 @@ describe('createRouter', () => {
userSettingsStore.deleteAll.mockResolvedValue();
const responses = await request(app)
.delete('/')
.delete('/buckets/')
.set('Authorization', 'Bearer foo');
expect(responses.status).toEqual(204);
expect(authenticateMock).toHaveBeenCalledWith('foo');
expect(userSettingsStore.deleteAll).toBeCalledTimes(1);
expect(userSettingsStore.deleteAll).toBeCalledWith('tx', {
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('/');
const responses = await request(app).delete('/buckets/');
expect(responses.status).toEqual(401);
expect(userSettingsStore.getAll).not.toHaveBeenCalled();
});
});
describe('GET /:bucket', () => {
describe('GET /buckets/:bucket', () => {
it('returns ok', async () => {
const settings = [
{ bucket: 'my-bucket', key: 'a', value: 'a' },
@@ -143,29 +143,29 @@ describe('createRouter', () => {
userSettingsStore.getBucket.mockResolvedValue(settings);
const responses = await request(app)
.get('/my-bucket')
.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).toBeCalledTimes(1);
expect(userSettingsStore.getBucket).toBeCalledWith('tx', {
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('/my-bucket');
const responses = await request(app).get('/buckets/my-bucket');
expect(responses.status).toEqual(401);
expect(userSettingsStore.getBucket).not.toHaveBeenCalled();
});
});
describe('DELETE /:bucket', () => {
describe('DELETE /buckets/:bucket', () => {
it('returns ok', async () => {
authenticateMock.mockResolvedValue({
identity: { userEntityRef: 'user-1' },
@@ -174,28 +174,28 @@ describe('createRouter', () => {
userSettingsStore.deleteBucket.mockResolvedValue();
const responses = await request(app)
.delete('/my-bucket')
.delete('/buckets/my-bucket')
.set('Authorization', 'Bearer foo');
expect(responses.status).toEqual(204);
expect(authenticateMock).toHaveBeenCalledWith('foo');
expect(userSettingsStore.deleteBucket).toBeCalledTimes(1);
expect(userSettingsStore.deleteBucket).toBeCalledWith('tx', {
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('/my-bucket');
const responses = await request(app).delete('/buckets/my-bucket');
expect(responses.status).toEqual(401);
expect(userSettingsStore.deleteBucket).not.toHaveBeenCalled();
});
});
describe('GET /:bucket/:key', () => {
describe('GET /buckets/:bucket/:key', () => {
it('returns ok', async () => {
const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' };
authenticateMock.mockResolvedValue({
@@ -205,15 +205,15 @@ describe('createRouter', () => {
userSettingsStore.get.mockResolvedValue(setting);
const responses = await request(app)
.get('/my-bucket/my-key')
.get('/buckets/my-bucket/my-key')
.set('Authorization', 'Bearer foo');
expect(responses.status).toEqual(200);
expect(responses.body).toEqual(setting);
expect(authenticateMock).toHaveBeenCalledWith('foo');
expect(userSettingsStore.get).toBeCalledTimes(1);
expect(userSettingsStore.get).toBeCalledWith('tx', {
expect(userSettingsStore.get).toHaveBeenCalledTimes(1);
expect(userSettingsStore.get).toHaveBeenCalledWith('tx', {
userEntityRef: 'user-1',
bucket: 'my-bucket',
key: 'my-key',
@@ -221,14 +221,14 @@ describe('createRouter', () => {
});
it('returns an error if the Authorization header is missing', async () => {
const responses = await request(app).get('/my-bucket/my-key');
const responses = await request(app).get('/buckets/my-bucket/my-key');
expect(responses.status).toEqual(401);
expect(userSettingsStore.get).not.toHaveBeenCalled();
});
});
describe('DELETE /:bucket/:key', () => {
describe('DELETE /buckets/:bucket/:key', () => {
it('returns ok', async () => {
authenticateMock.mockResolvedValue({
identity: { userEntityRef: 'user-1' },
@@ -237,14 +237,14 @@ describe('createRouter', () => {
userSettingsStore.delete.mockResolvedValue();
const responses = await request(app)
.delete('/my-bucket/my-key')
.delete('/buckets/my-bucket/my-key')
.set('Authorization', 'Bearer foo');
expect(responses.status).toEqual(204);
expect(authenticateMock).toHaveBeenCalledWith('foo');
expect(userSettingsStore.delete).toBeCalledTimes(1);
expect(userSettingsStore.delete).toBeCalledWith('tx', {
expect(userSettingsStore.delete).toHaveBeenCalledTimes(1);
expect(userSettingsStore.delete).toHaveBeenCalledWith('tx', {
userEntityRef: 'user-1',
bucket: 'my-bucket',
key: 'my-key',
@@ -252,14 +252,14 @@ describe('createRouter', () => {
});
it('returns an error if the Authorization header is missing', async () => {
const responses = await request(app).delete('/my-bucket/my-key');
const responses = await request(app).delete('/buckets/my-bucket/my-key');
expect(responses.status).toEqual(401);
expect(userSettingsStore.delete).not.toHaveBeenCalled();
});
});
describe('PUT /:bucket/:key', () => {
describe('PUT /buckets/:bucket/:key', () => {
it('returns ok', async () => {
const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' };
authenticateMock.mockResolvedValue({
@@ -270,7 +270,7 @@ describe('createRouter', () => {
userSettingsStore.get.mockResolvedValue(setting);
const responses = await request(app)
.put('/my-bucket/my-key')
.put('/buckets/my-bucket/my-key')
.set('Authorization', 'Bearer foo')
.send({ value: 'a' });
@@ -278,15 +278,15 @@ describe('createRouter', () => {
expect(responses.body).toEqual(setting);
expect(authenticateMock).toHaveBeenCalledWith('foo');
expect(userSettingsStore.set).toBeCalledTimes(1);
expect(userSettingsStore.set).toHaveBeenCalledTimes(1);
expect(userSettingsStore.set).toHaveBeenCalledWith('tx', {
userEntityRef: 'user-1',
bucket: 'my-bucket',
key: 'my-key',
value: 'a',
});
expect(userSettingsStore.get).toBeCalledTimes(1);
expect(userSettingsStore.get).toBeCalledWith('tx', {
expect(userSettingsStore.get).toHaveBeenCalledTimes(1);
expect(userSettingsStore.get).toHaveBeenCalledWith('tx', {
userEntityRef: 'user-1',
bucket: 'my-bucket',
key: 'my-key',
@@ -299,7 +299,7 @@ describe('createRouter', () => {
});
const responses = await request(app)
.put('/my-bucket/my-key')
.put('/buckets/my-bucket/my-key')
.set('Authorization', 'Bearer foo')
.send({ value: { invalid: 'because not a string' } });
@@ -310,7 +310,7 @@ describe('createRouter', () => {
});
it('returns an error if the Authorization header is missing', async () => {
const responses = await request(app).get('/my-bucket/my-key');
const responses = await request(app).get('/buckets/my-bucket/my-key');
expect(responses.status).toEqual(401);
expect(userSettingsStore.get).not.toHaveBeenCalled();
@@ -63,7 +63,7 @@ export async function createRouter<T>(
};
// get all user related settings
router.get('/', async (req, res) => {
router.get('/buckets', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
const settings = await userSettingsStore.transaction(tx =>
@@ -74,7 +74,7 @@ export async function createRouter<T>(
});
// remove all user related settings
router.delete('/', async (req, res) => {
router.delete('/buckets', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
await userSettingsStore.transaction(tx =>
@@ -85,7 +85,7 @@ export async function createRouter<T>(
});
// get a single bucket
router.get('/:bucket', async (req, res) => {
router.get('/buckets/:bucket', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
const { bucket } = req.params;
@@ -97,7 +97,7 @@ export async function createRouter<T>(
});
// delete a whole bucket
router.delete('/:bucket', async (req, res) => {
router.delete('/buckets/:bucket', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
const { bucket } = req.params;
@@ -109,7 +109,7 @@ export async function createRouter<T>(
});
// get a single value
router.get('/:bucket/:key', async (req, res) => {
router.get('/buckets/:bucket/:key', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
const { bucket, key } = req.params;
@@ -121,7 +121,7 @@ export async function createRouter<T>(
});
// set a single value
router.put('/:bucket/:key', async (req, res) => {
router.put('/buckets/:bucket/:key', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
const { bucket, key } = req.params;
const { value } = req.body;
@@ -144,7 +144,7 @@ export async function createRouter<T>(
});
// get a single value
router.delete('/:bucket/:key', async (req, res) => {
router.delete('/buckets/:bucket/:key', async (req, res) => {
const userEntityRef = await getUserEntityRef(req);
const { bucket, key } = req.params;