Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions functions/src/controllers/auth_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import axios from "axios";
import validator from "validator";
import { FieldValue } from "firebase-admin/firestore";
import { convertResponseToSnakeCase } from "../utils/camel_case";
import { User, formatUser } from "../models/user";

const validateEmailAndPassword = (
email: string,
Expand Down Expand Up @@ -96,24 +97,20 @@ export const register = async (req: Request, res: Response): Promise<void> => {
await axios.post(url, { token: customToken, returnSecureToken: true })
).data;

await db.collection("users").doc(user.uid).set({
email: user.email,
first_name: user.displayName,
last_name: null,
date_of_birth: null,
education: null,
school: null,
grade: null,
year: null,
gender_identity: null,
const userData: User = formatUser({
email: user.email ?? "",
firstName: user.displayName ?? "",
status: "not applicable",
portfolio: null,
github: null,
linkedin: null,
admin: false,
created_at: FieldValue.serverTimestamp(),
});

await db
.collection("users")
.doc(user.uid)
.set({
...userData,
createdAt: FieldValue.serverTimestamp(),
});

res.status(201).json(
convertResponseToSnakeCase({
message: "Registration successful",
Expand Down
126 changes: 126 additions & 0 deletions functions/src/controllers/ticket_controllers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Request, Response } from "express";
import { db } from "../config/firebase";
import { Ticket, formatTicket } from "../models/ticket";

/**
* Create a new ticket
*/
export const createTicket = async (
req: Request,
res: Response
): Promise<void> => {
try {
const data = req.body as Partial<Ticket>;

if (!req.user || !req.user.uid) {
res.status(401).json({ error: "Unauthorized" });
return;
}

const ticketRef = await db.collection("tickets").add({
topic: data.topic || "",
description: data.description || "",
location: data.location || "",
requestorId: req.user.uid,
tags: Array.isArray(data.tags) ? data.tags : [],
taken: false,
resolved: false,
});

res.status(201).json({ success: true, id: ticketRef.id });
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};

/**
* Get all tickets
*/
export const getTickets = async (
_req: Request,
res: Response
): Promise<void> => {
try {
const snapshot = await db
.collection("tickets")
.where("resolved", "==", false)
.get();
const tickets = snapshot.docs.map((doc) =>
formatTicket({ id: doc.id, ...doc.data() })
);
res.status(200).json(tickets);
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};

/**
* Get a ticket by ID
*/
export const getTicketById = async (
req: Request,
res: Response
): Promise<void> => {
try {
const { id } = req.params;
const doc = await db.collection("tickets").doc(id).get();

if (!doc.exists) {
res.status(404).json({ error: "Ticket not found" });
return;
}

res.status(200).json(formatTicket({ id: doc.id, ...doc.data() }));
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};

/**
* Update a ticket
*/
export const updateTicket = async (
req: Request,
res: Response
): Promise<void> => {
try {
const { id } = req.params;
const data = req.body as Partial<Ticket>;

const ticketDoc = db.collection("tickets").doc(id);
const ticketSnap = await ticketDoc.get();
if (!ticketSnap.exists) {
res.status(404).json({ error: "Ticket not found" });
return;
}
await ticketDoc.update(data);

res.status(200).json({ success: true, message: "Ticket updated" });
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};

/**
* Delete a ticket
*/
export const deleteTicket = async (
req: Request,
res: Response
): Promise<void> => {
try {
const { id } = req.params;

const ticketDoc = db.collection("tickets").doc(id);
const ticketSnap = await ticketDoc.get();
if (!ticketSnap.exists) {
res.status(404).json({ error: "Ticket not found" });
return;
}
await ticketDoc.delete();

res.status(200).json({ success: true, message: "Ticket deleted" });
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};
41 changes: 41 additions & 0 deletions functions/src/controllers/user_controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Request, Response } from "express";
import { db } from "../config/firebase";

/**
* Fetch all users
*/
export const getUsers = async (req: Request, res: Response): Promise<void> => {
try {
const snapshot = await db.collection("users").get();
const users = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
res.json(users);
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};

export const getCurrentUser = async (
req: Request,
res: Response
): Promise<void> => {
try {
const userId = req.user?.uid;
if (!userId) {
res.status(401).json({ error: "Unauthorized" });
return;
}

const userDoc = await db.collection("users").doc(userId).get();
if (!userDoc.exists) {
res.status(404).json({ error: "User not found" });
return;
}

res.json({ id: userDoc.id, ...userDoc.data() });
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
};
101 changes: 0 additions & 101 deletions functions/src/controllers/users_controller.ts

This file was deleted.

21 changes: 21 additions & 0 deletions functions/src/models/ticket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface Ticket {
id: string;
topic: string;
description: string;
location: string;
requestorId: string;
tags: string[];
taken: boolean;
resolved: boolean;
}

export const formatTicket = (data: Partial<Ticket>): Ticket => ({
id: data.id || "",
topic: data.topic || "",
description: data.description || "",
location: data.location || "",
requestorId: data.requestorId || "",
tags: Array.isArray(data.tags) ? data.tags : [],
taken: data.taken ?? false,
resolved: data.resolved ?? false,
});
31 changes: 31 additions & 0 deletions functions/src/models/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export interface User {
firstName: string;
lastName: string;
email: string;
dateOfBirth?: string;
school?: string;
grade?: number | null;
year?: number | null;
genderIdentity?: string;
status?: string;
portfolio?: string;
github?: string;
linkedin?: string;
admin?: boolean;
}

export const formatUser = (data: Partial<User>): User => ({
firstName: data.firstName || "",
lastName: data.lastName || "",
email: data.email || "",
dateOfBirth: data.dateOfBirth || "",
school: data.school || "",
grade: data.grade || null,
year: data.year || null,
genderIdentity: data.genderIdentity || "",
status: data.status || "not applicable",
portfolio: data.portfolio || "",
github: data.github || "",
linkedin: data.linkedin || "",
admin: data.admin || false,
});
4 changes: 3 additions & 1 deletion functions/src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import express, { Router } from "express";
import authRoutes from "./auth";
import userRoutes from "./users";
import userRoutes from "./user";
import ticketRoutes from "./ticket";

const router: Router = express.Router();

router.use("/auth", authRoutes);
router.use("/users", userRoutes);
router.use("/tickets", ticketRoutes);

export default router;
Loading