Skip to content

Commit

Permalink
refactor: registrations and sessions RCs
Browse files Browse the repository at this point in the history
  • Loading branch information
uatisdeproblem committed Mar 23, 2024
1 parent 5963963 commit 0bd8bf1
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 112 deletions.
158 changes: 71 additions & 87 deletions back-end/src/handlers/registrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ const DDB_TABLES = {

const ddb = new DynamoDB();

export const handler = (ev: any, _: any, cb: any) => new SessionRegistrations(ev, cb).handleRequest();
export const handler = (ev: any, _: any, cb: any): Promise<void> => new SessionRegistrationsRC(ev, cb).handleRequest();

///
/// RESOURCE CONTROLLER
///

class SessionRegistrations extends ResourceController {
class SessionRegistrationsRC extends ResourceController {
user: User;
configurations: Configurations;
registration: SessionRegistration;
Expand All @@ -39,10 +39,11 @@ class SessionRegistrations extends ResourceController {
}

protected async checkAuthBeforeRequest(): Promise<void> {

const sessionId = this.resourceId;
const userId = this.principalId;

try {
this.user = new User(await ddb.get({ TableName: DDB_TABLES.users, Key: { userId: this.principalId } }));
this.user = new User(await ddb.get({ TableName: DDB_TABLES.users, Key: { userId } }));
} catch (err) {
throw new HandledError('User not found');
}
Expand All @@ -55,39 +56,24 @@ class SessionRegistrations extends ResourceController {
throw new HandledError('Configuration not found');
}

if (!this.resourceId || this.httpMethod === 'POST') return;
if (!sessionId || this.httpMethod === 'POST') return;

try {
this.registration = new SessionRegistration(
await ddb.get({
TableName: DDB_TABLES.registrations,
Key: { sessionId: this.resourceId, userId: this.principalId }
})
await ddb.get({ TableName: DDB_TABLES.registrations, Key: { sessionId, userId } })
);
} catch (err) {
throw new HandledError('Registration not found');
}
}

protected async getResources(): Promise<SessionRegistration[]> {
if (this.queryParams.sessionId) {
try {
const registrationsOfSession = await ddb.query({
TableName: DDB_TABLES.registrations,
KeyConditionExpression: 'sessionId = :sessionId',
ExpressionAttributeValues: { ':sessionId': this.queryParams.sessionId }
});
return registrationsOfSession.map(s => new SessionRegistration(s));
} catch (error) {
throw new HandledError('Could not load registrations for this session');
}
} else {
return await this.getUsersRegistrations(this.principalId);
}
if (this.queryParams.sessionId) return this.getSessionRegistrations(this.queryParams.sessionId);
else return await this.getUsersRegistrations(this.principalId);
}

protected async postResource(): Promise<any> {
if (!this.configurations.areSessionRegistrationsOpen) throw new HandledError('Registrations are closed!')
if (!this.configurations.areSessionRegistrationsOpen) throw new HandledError('Registrations are closed!');

this.registration = new SessionRegistration({
sessionId: this.resourceId,
Expand All @@ -105,84 +91,70 @@ class SessionRegistrations extends ResourceController {
}

protected async deleteResource(): Promise<void> {
if (!this.configurations.areSessionRegistrationsOpen) throw new HandledError('Registrations are closed!')
if (!this.configurations.areSessionRegistrationsOpen) throw new HandledError('Registrations are closed!');

try {
const { sessionId, userId } = this.registration;

const deleteSessionRegistration = { TableName: DDB_TABLES.registrations, Key: { sessionId, userId } };

const updateSessionCount = {
TableName: DDB_TABLES.sessions,
Key: { sessionId },
UpdateExpression: 'ADD numberOfParticipants :minusOne',
ExpressionAttributeValues: {
':minusOne': -1
}
};

const removeFromFavorites = {
TableName: DDB_TABLES.usersFavoriteSessions,
Key: { userId: this.principalId, sessionId }
};

await ddb.transactWrites([
{ Delete: deleteSessionRegistration },
{ Delete: removeFromFavorites },
{ Update: updateSessionCount }
]);
} catch (err) {
throw new HandledError('Delete failed');
}
const { sessionId, userId } = this.registration;

const deleteSessionRegistration = { TableName: DDB_TABLES.registrations, Key: { sessionId, userId } };

const updateSessionCount = {
TableName: DDB_TABLES.sessions,
Key: { sessionId },
UpdateExpression: 'ADD numberOfParticipants :minusOne',
ExpressionAttributeValues: { ':minusOne': -1 }
};

const removeFromFavorites = {
TableName: DDB_TABLES.usersFavoriteSessions,
Key: { userId: this.principalId, sessionId }
};

await ddb.transactWrites([
{ Delete: deleteSessionRegistration },
{ Delete: removeFromFavorites },
{ Update: updateSessionCount }
]);
}

private async putSafeResource(): Promise<SessionRegistration> {
const { sessionId, userId } = this.registration;
const session: Session = new Session(await ddb.get({ TableName: DDB_TABLES.sessions, Key: { sessionId } }));
const session = new Session(await ddb.get({ TableName: DDB_TABLES.sessions, Key: { sessionId } }));
const isValid = await this.validateRegistration(session, userId);

if (!isValid) throw new HandledError("User can't sign up for this session!");

try {
const putSessionRegistration = { TableName: DDB_TABLES.registrations, Item: this.registration };

const updateSessionCount = {
TableName: DDB_TABLES.sessions,
Key: { sessionId },
UpdateExpression: 'ADD numberOfParticipants :one',
ConditionExpression: 'numberOfParticipants < :limit',
ExpressionAttributeValues: {
':one': 1,
":limit": session.limitOfParticipants
}
};

const addToFavorites = {
TableName: DDB_TABLES.usersFavoriteSessions,
Item: { userId: this.principalId, sessionId: this.resourceId }
}

await ddb.transactWrites([
{ Put: putSessionRegistration },
{ Put: addToFavorites },
{ Update: updateSessionCount }
]);

return this.registration;
} catch (err) {
throw new HandledError('Operation failed');
}
const putSessionRegistration = { TableName: DDB_TABLES.registrations, Item: this.registration };

const updateSessionCount = {
TableName: DDB_TABLES.sessions,
Key: { sessionId },
UpdateExpression: 'ADD numberOfParticipants :one',
ConditionExpression: 'numberOfParticipants < :limit',
ExpressionAttributeValues: { ':one': 1, ':limit': session.limitOfParticipants }
};

const addToFavorites = {
TableName: DDB_TABLES.usersFavoriteSessions,
Item: { userId: this.principalId, sessionId: this.resourceId }
};

await ddb.transactWrites([
{ Put: putSessionRegistration },
{ Put: addToFavorites },
{ Update: updateSessionCount }
]);

return this.registration;
}

private async validateRegistration(session: Session, userId: string) {
private async validateRegistration(session: Session, userId: string): Promise<boolean> {
if (!session.requiresRegistration) throw new HandledError("User can't sign up for this session!");
if (session.isFull()) throw new HandledError('Session is full! Refresh your page.');

const userRegistrations: SessionRegistration[] = await this.getUsersRegistrations(userId);

const userRegistrations = await this.getUsersRegistrations(userId);
if (!userRegistrations.length) return true;

const sessions: Session[] = (
const sessions = (
await ddb.batchGet(
DDB_TABLES.sessions,
userRegistrations.map(ur => ({ sessionId: ur.sessionId }))
Expand Down Expand Up @@ -215,7 +187,7 @@ class SessionRegistrations extends ResourceController {

private async getUsersRegistrations(userId: string): Promise<SessionRegistration[]> {
try {
const registrationsOfUser = await ddb.query({
const registrationsOfUser: SessionRegistration[] = await ddb.query({
TableName: DDB_TABLES.registrations,
IndexName: 'userId-sessionId-index',
KeyConditionExpression: 'userId = :userId',
Expand All @@ -226,4 +198,16 @@ class SessionRegistrations extends ResourceController {
throw new HandledError('Could not load registrations for this user');
}
}
private async getSessionRegistrations(sessionId: string): Promise<SessionRegistration[]> {
try {
const registrationsOfSession: SessionRegistration[] = await ddb.query({
TableName: DDB_TABLES.registrations,
KeyConditionExpression: 'sessionId = :sessionId',
ExpressionAttributeValues: { ':sessionId': sessionId }
});
return registrationsOfSession.map(s => new SessionRegistration(s));
} catch (error) {
throw new HandledError('Could not load registrations for this session');
}
}
}
37 changes: 12 additions & 25 deletions back-end/src/handlers/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,21 @@ import { User } from '../models/user.model';
///

const PROJECT = process.env.PROJECT;

const DDB_TABLES = {
users: process.env.DDB_TABLE_users,
sessions: process.env.DDB_TABLE_sessions,
rooms: process.env.DDB_TABLE_rooms,
speakers: process.env.DDB_TABLE_speakers
};

const ddb = new DynamoDB();

export const handler = (ev: any, _: any, cb: any) => new Sessions(ev, cb).handleRequest();
export const handler = (ev: any, _: any, cb: any): Promise<void> => new SessionsRC(ev, cb).handleRequest();

///
/// RESOURCE CONTROLLER
///

class Sessions extends ResourceController {
class SessionsRC extends ResourceController {
user: User;
session: Session;

Expand Down Expand Up @@ -73,12 +71,11 @@ class Sessions extends ResourceController {
await ddb.get({ TableName: DDB_TABLES.rooms, Key: { roomId: this.session.room.roomId } })
);

const getSpeakers = await ddb.batchGet(
const getSpeakers: SpeakerLinked[] = await ddb.batchGet(
DDB_TABLES.speakers,
this.session.speakers?.map(s => ({ speakerId: s.speakerId })),
true
)

);
this.session.speakers = getSpeakers.map(s => new SpeakerLinked(s));

const errors = this.session.validate();
Expand All @@ -98,11 +95,7 @@ class Sessions extends ResourceController {
protected async deleteResource(): Promise<void> {
if (!this.user.permissions.canManageContents) throw new HandledError('Unauthorized');

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

protected async postResources(): Promise<Session> {
Expand All @@ -115,20 +108,14 @@ class Sessions extends ResourceController {
}

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

const filtertedSessions = sessions.filter(
x =>
(!this.queryParams.speaker || x.speakers.some(speaker => speaker.speakerId === this.queryParams.speaker)) &&
(!this.queryParams.room || x.room.roomId === this.queryParams.room)
);
const sessions = (await ddb.scan({ TableName: DDB_TABLES.sessions })).map(x => new Session(x));

const sortedSessions = filtertedSessions.sort((a, b) => a.startsAt.localeCompare(b.startsAt));
const filtertedSessions = sessions.filter(
x =>
(!this.queryParams.speaker || x.speakers.some(speaker => speaker.speakerId === this.queryParams.speaker)) &&
(!this.queryParams.room || x.room.roomId === this.queryParams.room)
);

return sortedSessions;
} catch (err) {
throw new HandledError('Operation failed');
}
return filtertedSessions.sort((a, b): number => a.startsAt.localeCompare(b.startsAt));
}
}

0 comments on commit 0bd8bf1

Please sign in to comment.