Skip to content

Commit

Permalink
Merge branch 'main' into dev/alex/s3-service
Browse files Browse the repository at this point in the history
  • Loading branch information
aletya committed Apr 23, 2024
2 parents 357eb12 + 61af94e commit 14059ed
Show file tree
Hide file tree
Showing 12 changed files with 281 additions and 3 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "18.x"
cache: 'yarn'
- name: Install dependencies
run: yarn
- name: Build
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "18.x"
cache: 'yarn'
- name: Install dependencies
run: yarn
- name: Run ESLint
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/prettier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "18.x"
cache: 'yarn'
- name: Install dependencies
run: yarn
- name: Run Prettier
Expand Down
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import morgan from "morgan";
import bodyParser from "body-parser";
import errorHandler from "./middleware/error-handler";

import attendeeRouter from "./services/attendees/attendee-router";

Check failure on line 11 in src/app.ts

View workflow job for this annotation

GitHub Actions / lint

'attendeeRouter' is defined but never used

Check failure on line 11 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'attendeeRouter' is declared but its value is never read.
import authRouter from "./services/auth/auth-router";
import eventRouter from "./services/events/events-router";
import registrationRouter from "./services/registration/registration-router";

Check failure on line 14 in src/app.ts

View workflow job for this annotation

GitHub Actions / lint

'registrationRouter' is defined but never used

Check failure on line 14 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'registrationRouter' is declared but its value is never read.
import s3Router from "./services/s3/s3-router";
import subscriptionRouter from "./services/subscription/subscription-router";

Expand Down
7 changes: 4 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ export const Config = {
CLIENT_ID: getEnv("OAUTH_GOOGLE_CLIENT_ID"),
CLIENT_SECRET: getEnv("OAUTH_GOOGLE_CLIENT_SECRET"),

AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/",
// AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback/",
// AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/",
AUTH_CALLBACK_URI_BASE:
"https://api.reflectionsprojections.org/auth/callback/",

JWT_SIGNING_SECRET: getEnv("JWT_SIGNING_SECRET"),
JWT_EXPIRATION_TIME: "1 day",
Expand All @@ -35,5 +36,5 @@ export const Config = {

export const DeviceRedirects: Record<string, string> = {
web: "https://www.google.com/",
dev: "http://127.0.0.1:3000/auth/dev/",
dev: "https://api.reflectionsprojections.org/auth/dev/",
};
14 changes: 14 additions & 0 deletions src/database.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import mongoose, { Schema } from "mongoose";
import {
AttendeeSchema,
AttendeeValidator,
} from "./services/attendees/attendee-schema";
import { RoleValidator, RoleSchema } from "./services/auth/auth-schema";
import { EventSchema, EventValidator } from "./services/events/events-schema";
import {
RegistrationSchema,
RegistrationValidator,
} from "./services/registration/registration-schema";
import {
SubscriptionSchemaValidator,
SubscriptionSchema,
Expand Down Expand Up @@ -43,4 +51,10 @@ export const Database = {
SubscriptionSchema,
SubscriptionSchemaValidator
),
ATTENDEES: initializeModel("attendees", AttendeeSchema, AttendeeValidator),
REGISTRATION: initializeModel(
"registration",
RegistrationSchema,
RegistrationValidator
),
};
43 changes: 43 additions & 0 deletions src/services/attendees/attendee-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Router } from "express";
import { StatusCodes } from "http-status-codes";
import { AttendeeValidator } from "./attendee-schema";
import { Database } from "../../database";

const attendeeRouter = Router();

// Create a new attendee
attendeeRouter.post("/", async (req, res, next) => {
try {
const attendeeData = AttendeeValidator.parse(req.body);
const attendee = new Database.ATTENDEES(attendeeData);
await attendee.save();

return res.status(StatusCodes.CREATED).json(attendeeData);
} catch (error) {
next(error);
}
});

// Check if a user email exists
attendeeRouter.get("/:email", async (req, res, next) => {
try {
const { email } = req.params;

// Check if the user exists in the database
const userExists = await Database.ATTENDEES.exists({ email });

if (!userExists) {
return { error: "DoesNotExist" };
}

const user = await Database.ATTENDEES.findOne({
email,
});

return res.status(StatusCodes.OK).json(user);
} catch (error) {
next(error);
}
});

export default attendeeRouter;
26 changes: 26 additions & 0 deletions src/services/attendees/attendee-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import mongoose from "mongoose";
import { z } from "zod";

// Zod schema for attendee
const AttendeeValidator = z.object({
userId: z.string(),
name: z.string(),
email: z.string().email(),
events: z.array(z.string()),
dietary_restrictions: z.string(),
priority_expiry: z.date().nullable().optional(),
points: z.number().min(0).default(0),
});

// Mongoose schema for attendee
const AttendeeSchema = new mongoose.Schema({
userId: { type: String, required: true, unique: true },
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }],
dietary_restrictions: { type: String, required: true },
priority_expiry: { type: Date, default: null },
points: { type: Number, default: 0 },
});

export { AttendeeSchema, AttendeeValidator };
82 changes: 82 additions & 0 deletions src/services/events/event-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Router } from "express";
import { StatusCodes } from "http-status-codes";
import { EventValidator } from "./event-schema";
import { Database } from "../../database";

const eventRouter = Router();

// Create a new event
eventRouter.post("/", async (req, res, next) => {
try {
const eventData = EventValidator.parse(req.body);
const event = new Database.EVENTS(eventData);
await event.save();
return res.status(StatusCodes.CREATED).json(event);
} catch (error) {
next(error);
}
});

// Get all events
eventRouter.get("/", async (req, res, next) => {
try {
const events = await Database.EVENTS.find();
return res.status(StatusCodes.OK).json(events);
} catch (error) {
next(error);
}
});

// Get event by ID
eventRouter.get("/:id", async (req, res, next) => {
try {
const event = await Database.EVENTS.findOneAndUpdate(
{ _id: req.params.id },
{ new: true }
);

if (!event) {
return { error: "DoesNotExist" };
}

return res.status(StatusCodes.OK).json(event);
} catch (error) {
next(error);
}
});

// Update event
eventRouter.patch("/:id", async (req, res, next) => {
try {
const event = await Database.EVENTS.findOneAndUpdate(
{ _id: req.params.id },
req.body,
{ new: true }
);

if (!event) {
return { error: "DoesNotExist" };
}

return res.status(StatusCodes.OK).json(event);
} catch (error) {
next(error);
}
});

// Delete event
eventRouter.delete("/:id", async (req, res, next) => {
try {
const event = await Database.EVENTS.findByIdAndDelete(req.params.id);

if (!event) {
return { error: "DoesNotExist" };
}

return res.status(StatusCodes.OK).json(event);
} catch (error) {
next(error);
}
});

export default eventRouter;
47 changes: 47 additions & 0 deletions src/services/events/event-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import mongoose from "mongoose";
import { z } from "zod";

// Zod schema for event
const EventValidator = z.object({
name: z.string(),
description: z.string(),
start_time: z.date(),
end_time: z.date(),
attendees: z.array(z.string()),
location: z.array(
z.object({
description: z.string(),
tags: z.array(z.string()),
latitude: z.number(),
longitude: z.number(),
})
),
virtual: z.boolean(),
points: z.number().min(0).default(0),
imageUrl: z.string().nullable().optional(),
visible: z.boolean().default(false),
});

// Mongoose schema for location
const LocationSchema = new mongoose.Schema({
description: { type: String, required: true },
tags: [{ type: String }],
latitude: { type: Number, required: true },
longitude: { type: Number, required: true },
});

// Mongoose schema for event
const EventSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: true },
start_time: { type: Date, required: true },
end_time: { type: Date, required: true },
attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: "Attendee" }],
location: [LocationSchema],
virtual: { type: Boolean, required: true },
points: { type: Number, default: 0 },
imageUrl: { type: String, default: null },
visible: { type: Boolean, default: false },
});

export { EventSchema, EventValidator, LocationSchema };
10 changes: 10 additions & 0 deletions src/services/registration/registration-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Router } from "express";
// import { StatusCodes } from "http-status-codes";
// import { RegistrationValidator } from "./registration-schema";
// import { Database } from "../../database";

const registrationRouter = Router();

// TODO: registration routes

export default registrationRouter;
50 changes: 50 additions & 0 deletions src/services/registration/registration-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import mongoose from "mongoose";
import { z } from "zod";

// Zod schema for registration
const RegistrationValidator = z.object({
userId: z.string(),
name: z.string(),
email: z.string().email(),
studentInfo: z.object({
university: z.string().nonempty(),
graduation: z.string().nullable().optional(),
major: z.string().nullable().optional(),
}),
dietary_restrictions: z.string(),
age: z.number().nullable().optional(),
gender: z.string().nullable().optional(),
race: z.array(z.string()).nullable().optional(),
ethnicity: z.array(z.string()).nullable().optional(),
first_gen: z.string().nullable().optional(),
hear_about_rp: z.array(z.string()).nullable().optional(),
portfolio: z.string().nullable().optional(),
job_interest: z.array(z.string()).nullable().optional(),
interest_mech_puzzle: z.array(z.string()).nullable().optional(),
has_resume: z.boolean(),
});

// Mongoose schema for registration
const RegistrationSchema = new mongoose.Schema({
userId: { type: String, required: true, unique: true },
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
studentInfo: {
university: { type: String, required: true },
graduation: { type: String, default: null },
major: { type: String, default: null },
},
dietary_restrictions: { type: String, required: true },
age: { type: Number, default: null },
gender: { type: String, default: null },
race: [{ type: String }],
ethnicity: [{ type: String }],
first_gen: { type: String, default: null },
hear_about_rp: [{ type: String }],
portfolio: { type: String, default: null },
job_interest: [{ type: String }],
interest_mech_puzzle: [{ type: String }],
has_resume: { type: Boolean, default: false },
});

export { RegistrationSchema, RegistrationValidator };

0 comments on commit 14059ed

Please sign in to comment.