Skip to content

Commit

Permalink
Merge pull request #80 from cthit/clean-up
Browse files Browse the repository at this point in the history
Made the backend code easier to read and more maintainable
  • Loading branch information
x183 authored Apr 24, 2023
2 parents 9a13852 + 779f13d commit 46a3e3c
Show file tree
Hide file tree
Showing 13 changed files with 771 additions and 1,311 deletions.
1,438 changes: 403 additions & 1,035 deletions backend/package-lock.json

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
"express-session": "^1.17.2",
"graphql": "^15.5.1",
"js-base64": "^3.6.1",
"passport": "^0.4.1",
"passport-gamma": "^0.0.6",
"passport": "^0.6.0",
"qs": "^6.10.1",
"redis": "^3.1.2",
"ts-node": "^10.2.0"
Expand Down Expand Up @@ -54,4 +53,4 @@
"ts-node-dev": "^1.1.8",
"typescript": "^4.3.5"
}
}
}
9 changes: 7 additions & 2 deletions backend/src/authentication/gamma.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ const isAdmin = (authorities: Authority[], groups: String[]): boolean => {
if (process.env.MOCK && groups.includes("superadmin")) {
return true;
}

if (groups.includes("prit")) {
return true;
}

for (const i in authorities) {
if (authorities[i].authority == process.env.ADMIN_AUTHORITY || groups.includes("prit")) {
if (authorities[i].authority == process.env.ADMIN_AUTHORITY) {
return true;
}
}
Expand All @@ -38,7 +43,7 @@ export const init = (pass: passport.PassportStatic) => {
const groups = profile.groups
.filter(g => g.superGroup.type != "ALUMNI")
.map(g => g.superGroup.name);
groups.push(profile.cid);
groups.push(profile.cid);
cb(
null,
{
Expand Down
4 changes: 2 additions & 2 deletions backend/src/models/event.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Room } from "./room";
import { room } from "@prisma/client";

export interface Event {
id: string | null;
Expand All @@ -8,7 +8,7 @@ export interface Event {
title: string;
created_at: string;
updated_at: string;
room: Room[];
room: room[];
phone: string;
booked_by: string;
booked_as: string;
Expand Down
3 changes: 1 addition & 2 deletions backend/src/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Event } from "./event";
import { Room } from "./room";
import { Rule } from "./rule";
import { User } from "./user";
import { Error } from "./error";

export { Event, Room, Rule, User, Error };
export { Event, Rule, User, Error };
1 change: 0 additions & 1 deletion backend/src/models/room.ts

This file was deleted.

6 changes: 3 additions & 3 deletions backend/src/models/rule.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Room } from "./room";
import { room } from "@prisma/client";

export interface Rule {
id: string;
Expand All @@ -13,7 +13,7 @@ export interface Rule {
title: string;
created_at: string;
updated_at: string;
room: Room[];
room: room[];
}
export interface dbRule {
id: string;
Expand All @@ -28,5 +28,5 @@ export interface dbRule {
title: string;
created_at: Date;
updated_at: Date;
room: Room[];
room: room[];
}
8 changes: 5 additions & 3 deletions backend/src/resolvers/illegal_slots.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Tools } from "../utils/commonTypes";
import {
mergeRules,
toMiniRules,
toExplicitRules,
getRulesBetween,
} from "../services/rule.service";

Expand All @@ -10,8 +10,10 @@ export const getIllegalSlotsQResolvers = ({ prisma }: Tools) => ({
const from = new Date(ft.from);
const to = new Date(ft.to);

const rules = await (await getRulesBetween(prisma, from, to))
const rules = await await getRulesBetween(prisma, from, to);

return mergeRules(toMiniRules(rules, from, to)).filter(rule => !rule.allow);
return mergeRules(toExplicitRules(rules, from, to)).filter(
rule => !rule.allow,
);
},
});
142 changes: 106 additions & 36 deletions backend/src/services/event.service.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,159 @@
import { Event } from "../models/event";
import { checkRules } from "./rule.service";
import { User, Error } from "../models";
import { PrismaClient, event } from "@prisma/client";
import { PrismaClient, event, room } from "@prisma/client";

/*
* Events must end after they start
*/
const endIsAfterStart = (event: Event) => {
return new Date(event.start) < new Date(event.end);
};

/**
* Users cannot book events more than 9 weeks in advance
* Admins are exempt from this rule
*/
const isWithin9Weeks = (event: Event, is_admin: boolean) => {
return new Date(event.start) <= new Date(Date.now() + 5443200000) || is_admin;
};

/*
* Users must be in a booking group to book a room
* Admins are exempt from this rule
*/
const userIsInBookingGroup = (event: Event | event, user: User) => {
return user.groups.includes(event.booked_as) || user.is_admin;
};

/**
* The person booking the event must be specified
*/
const bookedByIsSpecified = (event: Event) => {
return event.booked_by && event.booked_by != "";
};

/**
* Big hub cannot be booked for a private event
*/
const bookingBigHubAsPrivate = (event: Event) => {
return (
event.booked_as == event.booked_by && event.room.includes(room.BIG_HUB)
);
};

const roomSpecified = (event: Event) => {
return event.room.length > 0;
};

/**
* The new event may not overlap with any existing events
*/
const overlappingEvent = async (
prisma: PrismaClient,
event: Event,
user: User,
): Promise<Boolean> => {
let query: any = {
where: {
end: { gt: new Date(event.start) },
start: { lte: new Date(event.end) },
room: { hasSome: event.room.map(e => e.toString()) },
},
};

if (event.id) {
query.where.id = { not: event.id };
}

let overlap_count = await prisma.event.count(query);
return overlap_count > 0;
};

/**
* Booking terms and conditions must be accepted
*/
const bookingTermsAccepted = (event: Event) => {
return event.booking_terms;
};

const validPhoneNumber = (phoneNumber: string) => {
return /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,5}$/im.test(
phoneNumber,
);
};

const validEvent = async (
prisma: PrismaClient,
event: Event,

{ groups, is_admin }: User,
user: User,
) => {
if (new Date(event.start) >= new Date(event.end)) {
if (!endIsAfterStart(event)) {
return {
sv: "Starttid är efter sluttid",
en: "Start date is later than end date",
};
}

if (new Date(event.start) > new Date(Date.now() + 5443200000) && !is_admin) {
if (!isWithin9Weeks(event, user.is_admin)) {
// 5443200000 = 63 days or 9 weeks
return {
sv: "Den angivna starttiden är för långt fram i tiden",
en: "Start date is too far in the future",
};
}

if (!groups.includes(event.booked_as) && !is_admin) {
if (!userIsInBookingGroup(event, user)) {
return {
sv: "Bokande grupp ej specificerad",
en: "Booking group not specified",
};
}

if (!event.booked_by || event.booked_by == "") {
if (!bookedByIsSpecified(event)) {
return {
sv: "Bokande användare ej specificerad",
en: "Booking user not specified",
};
}

if (event.booked_as == event.booked_by && event.room.includes("BIG_HUB")) {
if (bookingBigHubAsPrivate(event)) {
return {
sv: "Storhubben får inte bokas som privatperson",
en: "The big hub cannot be booked as a private person",
};
}
if (event.room.length <= 0) {
if (!roomSpecified(event)) {
return {
sv: "Inget rum specificerat",
en: "No room specified",
};
}

let query: any = {
where: {
end: { gt: new Date(event.start) },
start: { lte: new Date(event.end) },
room: { hasSome: event.room.map(e => e.toString()) },
},
};

if (event.id) {
query.where.id = { not: event.id };
}

let overlap_count = await prisma.event.count(query);

if (overlap_count > 0) {
try {
if (await overlappingEvent(prisma, event, user)) {
return {
sv: "Den angivna tiden är upptagen",
en: "The time slot is already taken",
};
}
} catch (e) {
console.log(e);
return {
sv: "Den angivna tiden är upptagen",
en: "The time slot is already taken",
sv: "Kunde inte kontrollera överlappande bokningar",
en: "Failed to check for overlapping events",
};
}

if (!event.booking_terms) {
if (!bookingTermsAccepted(event)) {
return {
sv: "Du måste godkänna bokningsvillkoren",
en: "You must accept the booking terms and conditions",
};
}

if (
!/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,5}$/im.test(
event.phone,
)
) {
if (!validPhoneNumber(event.phone)) {
return {
sv: "Ogiltigt telefonnummer",
en: "Provided phone number is faulty",
Expand Down Expand Up @@ -112,8 +182,8 @@ export const editEvent = async (
// Sanity checks
if (event.id == null) {
return {
sv: "Inget boknings id",
en: "No event id",
sv: "Inget boknings id angivet",
en: "No event id specified",
};
}

Expand All @@ -137,7 +207,7 @@ export const editEvent = async (
};
}

if (!(user.groups.includes(old_event.booked_as) || user.is_admin)) {
if (!userIsInBookingGroup(old_event, user)) {
return {
sv: "Du har inte behörighet att redigera denna bokning",
en: "You do not have permission to edit this event",
Expand Down Expand Up @@ -193,7 +263,7 @@ export const createEvent = async (
export const deleteEvent = async (
prisma: PrismaClient,
id: string,
{ groups, is_admin }: User,
user: User,
) => {
const event: event | null = await prisma.event.findUnique({
where: {
Expand All @@ -207,7 +277,7 @@ export const deleteEvent = async (
};
}

if (!groups.includes(event.booked_as) && !is_admin) {
if (!userIsInBookingGroup(event, user)) {
return {
sv: "Du får ej radera denna bokning",
en: "You may not delete this event",
Expand Down
Loading

0 comments on commit 46a3e3c

Please sign in to comment.