Skip to content

Commit

Permalink
refactor: use application object for awards backend (#30)
Browse files Browse the repository at this point in the history
* set up Awards app class, port put to use that

* fix put

* move delete into Awards class

* create shared "get award by uid" func

* move get to class

* move create to class

* add copyright headers

* fix tsc

* run prettier
  • Loading branch information
zhammer committed Feb 23, 2024
1 parent b1ff820 commit 197dae3
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 53 deletions.
76 changes: 76 additions & 0 deletions plugins/awards-backend/src/awards.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright SeatGeek
* Licensed under the terms of the Apache-2.0 license. See LICENSE file in project root for terms.
*/
import { NotFoundError } from '@backstage/errors';
import { Award, AwardInput } from '@seatgeek/backstage-plugin-awards-common';
import { Logger } from 'winston';
import { AwardsStore } from './database/awards';

export class Awards {
private readonly db: AwardsStore;
private readonly logger: Logger;

constructor(db: AwardsStore, logger: Logger) {
this.db = db;
this.logger = logger.child({ class: 'Awards' });
this.logger.debug('Constructed');
}

async get(uid: string): Promise<Award> {
return await this.getAwardByUid(uid);
}

async create(input: AwardInput): Promise<Award> {
return await this.db.add(
input.name,
input.description,
input.image,
input.owners,
input.recipients,
);
}

async update(
identityRef: string,
uid: string,
input: AwardInput,
): Promise<Award> {
const award = await this.getAwardByUid(uid);

if (!award.owners.includes(identityRef)) {
throw new Error('Unauthorized to update award');
}

const updated = await this.db.update(
uid,
input.name,
input.description,
input.image,
input.owners,
input.recipients,
);

return updated;
}

async delete(identityRef: string, uid: string): Promise<boolean> {
const award = await this.getAwardByUid(uid);

if (!award.owners.includes(identityRef)) {
throw new Error('Unauthorized to delete award');
}

return await this.db.delete(uid);
}

private async getAwardByUid(uid: string): Promise<Award> {
const res = await this.db.search(uid, '', [], []);

if (!res || res.length === 0) {
throw new NotFoundError(uid);
}

return res[0];
}
}
64 changes: 11 additions & 53 deletions plugins/awards-backend/src/service/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
* Licensed under the terms of the Apache-2.0 license. See LICENSE file in project root for terms.
*/
import { PluginDatabaseManager, errorHandler } from '@backstage/backend-common';
import { AuthenticationError, NotFoundError } from '@backstage/errors';
import { AuthenticationError } from '@backstage/errors';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { Award } from '@seatgeek/backstage-plugin-awards-common';
import express from 'express';
import Router from 'express-promise-router';
import { Logger } from 'winston';
import { Awards } from '../awards';
import { DatabaseAwardsStore } from '../database/awards';

export interface RouterOptions {
Expand All @@ -23,6 +23,7 @@ export async function createRouter(
const { database, identity, logger } = options;

const dbStore = await DatabaseAwardsStore.create({ database: database });
const awardsApp = new Awards(dbStore, logger);

const router = Router();
router.use(express.json());
Expand Down Expand Up @@ -76,44 +77,19 @@ export async function createRouter(

const uid = request.params.uid;
// TODO: validate uuid parameter
const resp = await dbStore.search(uid, '', [], []);

if (!resp) {
throw new NotFoundError(uid);
}

response.json(resp);
const award = await awardsApp.get(uid);
response.json(award);
});

router.put('/:uid', async (request, response) => {
const userRef = await getUserRef(identity, request);

const uid = request.params.uid;
// TODO: validate uuid parameter
// TODO: validate request.body

const res = await dbStore.search(uid, '', [], []);

if (!res || res.length === 0) {
throw new NotFoundError(uid);
}

const award: Award = res[0];

if (!award.owners.includes(userRef)) {
throw new Error('Unauthorized to update award');
}

logger.debug(request.body);
const { name, description, image, owners, recipients } = request.body;

const upd = await dbStore.update(
uid,
name,
description,
image,
owners,
recipients,
);
const upd = await awardsApp.update(userRef, uid, request.body);

response.json(upd);
});
Expand All @@ -124,36 +100,18 @@ export async function createRouter(
const uid = request.params.uid;
// TODO: validate uuid parameter

const res = await dbStore.search(uid, '', [], []);

if (!res || res.length === 0) {
throw new NotFoundError(uid);
}
const result = await awardsApp.delete(userRef, uid);

const award: Award = res[0];

if (!award.owners.includes(userRef)) {
throw new Error('Unauthorized to delete award');
}

response.json(dbStore.delete(uid));
response.json(result);
});

router.post('/', async (request, response) => {
// Just to protect the request
await getUserRef(identity, request);

const { name, description, image, owners, recipients } = request.body;

const resp = await dbStore.add(
name,
description,
image,
owners,
recipients,
);
const award = await awardsApp.create(request.body);

response.json(resp);
response.json(award);
});

router.use(errorHandler());
Expand Down
2 changes: 2 additions & 0 deletions plugins/awards-common/src/types/award.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export interface Award {
owners: string[];
recipients: string[];
}

export type AwardInput = Omit<Award, 'uid'>;

0 comments on commit 197dae3

Please sign in to comment.