Skip to content

Commit 8ffb801

Browse files
authored
feat: fixes and validation (#35)
* fix: make err handling resilient, and fix bugs (#32) * fix: infinite looping cronjob * feat: rewrite service unit tests * feat: add global err handlers * feat: add 404 * feat: update api client * refactor: use common page skeleton on loading * fix: fix code smells * feat: add ci badge * feat: add ratelimit handling * fix: fix proxy security warn * fix: typo * refactor: auto detect rsc on xhr request * feat: rewrite auth tests * chore: bump deps, fix text * feat: start on announcementmodel unit tests * fix: add cleanup func * feat: replace working name * fix: rename completed to read * Feat/api type validation (#36) * feat: write middleware for checking * feat: overhaul file structure * feat: upgrade auth endpoints * feat: add typecheck for /user/* * fix: provide full list of missing env * feat: announcement api validation * feat: upgrade service endpoints * feat: fix up announcementmodel tests * chore: Update to use "CCA Hours" instead of "Service Hours". * fix: api regression * fix: code smells * Feat/requested changes (#38) * feat: migrate db * feat: update models and endpoints * fix: update tests * feat: update scheduler * refactor: deletion logic efficiency * fix: debounce state for xhr req * feat: update FE service sessions and varifyattendance * feat: add support for service * feat: improved validation errors * chore: rename service hours to cca hours * fix: fix smells * fix: misc bugfixes * feat: initial commit of empty suites * chore: bump deps * fix: remove unused import * fix: permissions issue * chore: update meta * feat: start on usermodel tests * chore: continue tests * feat: more tests * feat: complete usermodel tests * feat: add db snapshotting * fix: scheduling of service sessions * fix: smells * fix: test volume type * test: volume test again * chore: bump versions * chore: remove console log
1 parent 524c096 commit 8ffb801

106 files changed

Lines changed: 5022 additions & 1910 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/pipeline.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Setup bun
2424
uses: oven-sh/setup-bun@v1
2525
with:
26-
bun-version: 1.0.24
26+
bun-version: 1.0.29
2727

2828
- name: Install dependencies
2929
run: cd interapp-backend && bun install

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,5 @@ dist
175175
.DS_Store
176176

177177
pgdata/
178-
minio_data/
178+
minio_data/
179+
dump/

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=raffles-interact_interapp&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=raffles-interact_interapp)
55
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=raffles-interact_interapp&metric=bugs)](https://sonarcloud.io/summary/new_code?id=raffles-interact_interapp)
66
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=raffles-interact_interapp&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=raffles-interact_interapp)
7+
[![CI](https://github.com/raffles-interact/interapp/actions/workflows/pipeline.yml/badge.svg)](https://github.com/raffles-interact/interapp/actions/workflows/pipeline.yml)
78

89
A monorepo for Raffles Interact's administrative application. Built with Next.js and Express along with the Bun runtime.
910

docker-compose.dev.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: "3"
33
services:
44
postgres:
55
container_name: interapp-postgres
6-
image: postgres:alpine
6+
image: postgres:16-alpine
77
restart: on-failure
88
ports:
99
- 5432:5432
@@ -62,6 +62,10 @@ services:
6262
condition: service_healthy
6363
redis:
6464
condition: service_healthy
65+
volumes:
66+
- type: bind
67+
source: ./dump
68+
target: /tmp/dump
6569

6670
minio:
6771
container_name: interapp-minio

docker-compose.prod.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: "3"
33
services:
44
postgres:
55
container_name: interapp-postgres
6-
image: postgres:alpine
6+
image: postgres:16-alpine
77
restart: always
88
ports:
99
- 5432:5432
@@ -52,6 +52,8 @@ services:
5252
condition: service_healthy
5353
redis:
5454
condition: service_healthy
55+
volumes:
56+
- ./:/tmp/dump
5557

5658
minio:
5759
container_name: interapp-minio

docker-compose.test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: "3"
33
services:
44
postgres:
55
container_name: interapp-postgres-test
6-
image: postgres:alpine
6+
image: postgres:16-alpine
77
restart: on-failure
88
ports:
99
- 2345:2345

interapp-backend/api/email_handler/templates/reset_password.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
</head>
3232
<body>
3333
<div>
34-
<h1 class="title">Reset your password on Interapp!</h1>
34+
<h1 class="title">Reset your password on OneInteract!</h1>
3535
<p class="content">Hi {{ username }},</p>
3636
<p class="content">Click the link below to reset your password:</p>
3737
<button class="content button"><a href="{{ url }}">Reset</a></button>
@@ -40,7 +40,7 @@ <h1 class="title">Reset your password on Interapp!</h1>
4040
contact the administrator immediately.
4141
</p>
4242
<p class="content">Thanks,</p>
43-
<p class="content">Interapp Team</p>
43+
<p class="content">OneInteract Team</p>
4444
<hr />
4545
<p class="content">
4646
If you're having trouble clicking the "Reset" button, copy and paste the URL below into your

interapp-backend/api/email_handler/templates/verify_email.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
</head>
3232
<body>
3333
<div>
34-
<h1 class="title">Verify your email with Interapp!</h1>
34+
<h1 class="title">Verify your email with OneInteract!</h1>
3535
<p class="content">Hi {{ username }},</p>
3636
<p class="content">Click the link below to verify your email:</p>
3737
<button class="content button"><a href="{{ url }}">Verify Now!</a></button>
3838
<p class="content">If you did not request this, please ignore this email.</p>
3939
<p class="content">Thanks,</p>
40-
<p class="content">Interapp Team</p>
40+
<p class="content">OneInteract Team</p>
4141
<hr />
4242
<p class="content">
4343
If you're having trouble clicking the "Verify Now" button, copy and paste the URL below into
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from './announcement';
2+
export * from './auth';
3+
export * from './hello';
4+
export * from './user';
5+
export * from './service';

interapp-backend/api/models/service.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export class ServiceModel {
1616
newService.contact_email = service.contact_email;
1717
newService.contact_number = service.contact_number;
1818
newService.website = service.website;
19+
newService.enable_scheduled = service.enable_scheduled;
20+
newService.service_hours = service.service_hours;
1921

2022
if (!service.promotional_image) newService.promotional_image = null;
2123
else {
@@ -136,9 +138,18 @@ export class ServiceModel {
136138
) {
137139
const session = new ServiceSession();
138140
session.service_id = service_session.service_id;
141+
const validTime = new Date(service_session.start_time) > new Date(service_session.end_time);
142+
if (validTime) {
143+
throw new HTTPError(
144+
'Invalid time',
145+
'Start time must be before end time',
146+
HTTPErrorCode.BAD_REQUEST_ERROR,
147+
);
148+
}
139149
session.start_time = service_session.start_time;
140150
session.end_time = service_session.end_time;
141151
session.ad_hoc_enabled = service_session.ad_hoc_enabled;
152+
session.service_hours = service_session.service_hours;
142153
session.service = await this.getService(service_session.service_id);
143154
try {
144155
await appDataSource.manager.insert(ServiceSession, session);
@@ -163,8 +174,19 @@ export class ServiceModel {
163174
}
164175
return res;
165176
}
166-
public static async updateServiceSession(service_session: ServiceSession) {
177+
public static async updateServiceSession(
178+
service_session: Omit<ServiceSession, 'service_session_users' | 'service'>,
179+
) {
167180
const service = await this.getService(service_session.service_id); // check if service exists
181+
182+
const validTime = new Date(service_session.start_time) > new Date(service_session.end_time);
183+
if (validTime) {
184+
throw new HTTPError(
185+
'Invalid time',
186+
'Start time must be before end time',
187+
HTTPErrorCode.BAD_REQUEST_ERROR,
188+
);
189+
}
168190
try {
169191
await appDataSource.manager.update(
170192
ServiceSession,

0 commit comments

Comments
 (0)