Skip to content

Commit

Permalink
feat: added rooms back-end #78
Browse files Browse the repository at this point in the history
  • Loading branch information
rbento1096 committed Feb 17, 2024
1 parent 5727372 commit 836c263
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 1 deletion.
6 changes: 5 additions & 1 deletion back-end/deploy/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const apiResources: ResourceController[] = [
{ name: 'usefulLinks', paths: ['/useful-links', '/useful-links/{linkId}'] },
{ name: 'venues', paths: ['/venues', '/venues/{venueId}'] },
{ name: 'communications', paths: ['/communications', '/communications/{communicationId}'] },
{ name: 'organizations', paths: ['/organizations', '/organizations/{organizationId}'] }
{ name: 'organizations', paths: ['/organizations', '/organizations/{organizationId}'] },
{ name: 'rooms', paths: ['/rooms', '/rooms/{roomId}'] }
];

const tables: { [tableName: string]: DDBTable } = {
Expand Down Expand Up @@ -58,6 +59,9 @@ const tables: { [tableName: string]: DDBTable } = {
},
organizations: {
PK: { name: 'organizationId', type: DDB.AttributeType.STRING }
},
rooms: {
PK: { name: 'roomId', type: DDB.AttributeType.STRING }
}
};

Expand Down
120 changes: 120 additions & 0 deletions back-end/src/handlers/rooms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
///
/// IMPORTS
///

import { DynamoDB, RCError, ResourceController } from 'idea-aws';

import { Room } from '../models/room.model';
import { VenueLinked } from '../models/venue.model';
import { User } from '../models/user.model';

///
/// CONSTANTS, ENVIRONMENT VARIABLES, HANDLER
///

const PROJECT = process.env.PROJECT;

const DDB_TABLES = {
users: process.env.DDB_TABLE_users,
rooms: process.env.DDB_TABLE_rooms,
venues: process.env.DDB_TABLE_venues
};

const ddb = new DynamoDB();

export const handler = (ev: any, _: any, cb: any) => new Rooms(ev, cb).handleRequest();

///
/// RESOURCE CONTROLLER
///

class Rooms extends ResourceController {
user: User;
room: Room;

constructor(event: any, callback: any) {
super(event, callback, { resourceId: 'roomId' });
}

protected async checkAuthBeforeRequest(): Promise<void> {
try {
this.user = new User(await ddb.get({ TableName: DDB_TABLES.users, Key: { userId: this.principalId } }));
} catch (err) {
throw new RCError('User not found');
}

if (!this.resourceId) return;

try {
this.room = new Room(await ddb.get({ TableName: DDB_TABLES.rooms, Key: { roomId: this.resourceId } }));
} catch (err) {
throw new RCError('Room not found');
}
}

protected async getResource(): Promise<Room> {
return this.room;
}

protected async putResource(): Promise<Room> {
if (!this.user.permissions.canManageContents) throw new RCError('Unauthorized');

const oldResource = new Room(this.room);
this.room.safeLoad(this.body, oldResource);

return await this.putSafeResource();
}
private async putSafeResource(opts: { noOverwrite?: boolean } = {}): Promise<Room> {
const errors = this.room.validate();
if (errors.length) throw new RCError(`Invalid fields: ${errors.join(', ')}`);

this.room.venue = new VenueLinked(
await ddb.get({ TableName: DDB_TABLES.venues, Key: { venueId: this.room.venue.venueId } })
);

try {
const putParams: any = { TableName: DDB_TABLES.rooms, Item: this.room };
if (opts.noOverwrite) putParams.ConditionExpression = 'attribute_not_exists(roomId)';
await ddb.put(putParams);

return this.room;
} catch (err) {
throw new RCError('Operation failed');
}
}

protected async deleteResource(): Promise<void> {
if (!this.user.permissions.canManageContents) throw new RCError('Unauthorized');

try {
await ddb.delete({ TableName: DDB_TABLES.rooms, Key: { roomId: this.resourceId } });
} catch (err) {
throw new RCError('Delete failed');
}
}

protected async postResources(): Promise<Room> {
if (!this.user.permissions.canManageContents) throw new RCError('Unauthorized');

this.room = new Room(this.body);
this.room.roomId = await ddb.IUNID(PROJECT);

return await this.putSafeResource({ noOverwrite: true });
}

protected async getResources(): Promise<Room[]> {
try {
const rooms = (await ddb.scan({ TableName: DDB_TABLES.rooms })).map((x: Room) => new Room(x));

const filteredRooms = this.queryParams.venue
? rooms.filter(x => x.venue.venueId === this.queryParams.venue)
: rooms;

const sortedRooms = filteredRooms.sort((a, b) => a.name.localeCompare(b.name));

return sortedRooms;
} catch (err) {
throw new RCError('Operation failed');
}
}
}
68 changes: 68 additions & 0 deletions back-end/src/models/room.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { isEmpty, Resource } from 'idea-toolbox';

import { VenueLinked } from './venue.model';

export class Room extends Resource {
/**
* The room ID.
*/
roomId: string;
/**
* The name of the room.
*/
name: string;
/**
* The venue where this room is located
*/
venue: VenueLinked;
/**
* The room's internal location.
*/
internalLocation: string;
/**
* A description for the room.
*/
description: string;
/**
* An URI for an image of the room.
*/
imageURI: string;
/**
* An URI for a plan of the room.
*/
planImageURI: string;

load(x: any): void {
super.load(x);
this.roomId = this.clean(x.roomId, String);
this.name = this.clean(x.name, String);
this.venue = typeof x.venue === 'string' ? new VenueLinked({ venueId: x.venue }) : new VenueLinked(x.venue);
this.internalLocation = this.clean(x.internalLocation, String);
this.description = this.clean(x.description, String);
this.imageURI = this.clean(x.imageURI, String);
this.planImageURI = this.clean(x.planImageURI, String);
}
safeLoad(newData: any, safeData: any): void {
super.safeLoad(newData, safeData);
this.roomId = safeData.roomId;
}
validate(): string[] {
const e = super.validate();
if (isEmpty(this.name)) e.push('name');
if (!this.venue.venueId) e.push('venue');
return e;
}
}

export class RoomLinked extends Resource {
roomId: string;
name: string;
venue: VenueLinked;

load(x: any): void {
super.load(x);
this.roomId = this.clean(x.roomId, String);
this.name = this.clean(x.name, String);
this.venue = new VenueLinked(x.venue);
}
}
109 changes: 109 additions & 0 deletions back-end/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ tags:
description: The event's communications and announcements.
- name: Organizations
description: The organizations of the event
- name: Rooms
description: The rooms of the event

paths:
/status:
Expand Down Expand Up @@ -760,6 +762,94 @@ paths:
$ref: '#/components/responses/OperationCompleted'
400:
$ref: '#/components/responses/BadParameters'
/rooms:
get:
summary: Get the rooms
tags: [Rooms]
security:
- AuthFunction: []
parameters:
- name: venue
in: query
schema:
type: string
responses:
200:
$ref: '#/components/responses/Rooms'
post:
summary: Insert a new room
description: Requires to be content manager
tags: [Rooms]
security:
- AuthFunction: []
requestBody:
required: true
description: Room
content:
application/json:
schema:
type: object
responses:
200:
$ref: '#/components/responses/Room'
400:
$ref: '#/components/responses/BadParameters'
/rooms/{roomId}:
get:
summary: Get a room
tags: [Rooms]
security:
- AuthFunction: []
parameters:
- name: roomId
in: path
required: true
schema:
type: string
responses:
200:
$ref: '#/components/responses/Room'
put:
summary: Edit a room
description: Requires to be content manager
tags: [Rooms]
security:
- AuthFunction: []
parameters:
- name: roomId
in: path
required: true
schema:
type: string
requestBody:
required: true
description: Room
content:
application/json:
schema:
type: object
responses:
200:
$ref: '#/components/responses/Room'
400:
$ref: '#/components/responses/BadParameters'
delete:
summary: Delete a room
description: Requires to be content manager
tags: [Rooms]
security:
- AuthFunction: []
parameters:
- name: roomId
in: path
required: true
schema:
type: string
responses:
200:
$ref: '#/components/responses/Room'
400:
$ref: '#/components/responses/BadParameters'

components:
schemas:
Expand Down Expand Up @@ -787,6 +877,9 @@ components:
Organization:
type: object
additionalProperties: {}
Room:
type: object
additionalProperties: {}

responses:
AppStatus:
Expand Down Expand Up @@ -895,6 +988,22 @@ components:
type: array
items:
$ref: '#/components/schemas/Organization'
Room:
description: Room
content:
application/json:
schema:
type: object
items:
$ref: '#/components/schemas/Room'
Rooms:
description: Room[]
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Room'
BadParameters:
description: Bad input parameters
content:
Expand Down

0 comments on commit 836c263

Please sign in to comment.