Skip to content

Commit 01151a2

Browse files
committed
chore: add cerberus
1 parent f34f161 commit 01151a2

File tree

25 files changed

+2040
-74
lines changed

25 files changed

+2040
-74
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@
2626
"esbuild"
2727
]
2828
}
29-
}
29+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { Request, Response } from "express";
2+
import { v4 as uuidv4 } from "uuid";
3+
import { UserService } from "../services/UserService";
4+
import { EventEmitter } from "events";
5+
6+
export class AuthController {
7+
private userService: UserService;
8+
private eventEmitter: EventEmitter;
9+
10+
constructor() {
11+
this.userService = new UserService();
12+
this.eventEmitter = new EventEmitter();
13+
}
14+
15+
sseStream = async (req: Request, res: Response) => {
16+
const { id } = req.params;
17+
18+
// Set headers for SSE
19+
res.writeHead(200, {
20+
"Content-Type": "text/event-stream",
21+
"Cache-Control": "no-cache",
22+
Connection: "keep-alive",
23+
"Access-Control-Allow-Origin": "*",
24+
});
25+
26+
const handler = (data: any) => {
27+
res.write(`data: ${JSON.stringify(data)}\n\n`);
28+
};
29+
30+
this.eventEmitter.on(id, handler);
31+
32+
// Handle client disconnect
33+
req.on("close", () => {
34+
this.eventEmitter.off(id, handler);
35+
res.end();
36+
});
37+
38+
req.on("error", (error) => {
39+
console.error("SSE Error:", error);
40+
this.eventEmitter.off(id, handler);
41+
res.end();
42+
});
43+
};
44+
45+
getOffer = async (req: Request, res: Response) => {
46+
const url = new URL(
47+
"/api/auth",
48+
process.env.PUBLIC_CERBERUS_BASE_URL,
49+
).toString();
50+
const session = uuidv4();
51+
const offer = `w3ds://auth?redirect=${url}&session=${session}&platform=Cerberus`;
52+
res.json({ uri: offer });
53+
};
54+
55+
login = async (req: Request, res: Response) => {
56+
try {
57+
const { ename, session } = req.body;
58+
59+
if (!ename) {
60+
return res.status(400).json({ error: "ename is required" });
61+
}
62+
63+
const { user, token } =
64+
await this.userService.findOrCreateUser(ename);
65+
66+
const data = {
67+
user: {
68+
id: user.id,
69+
ename: user.ename,
70+
isVerified: user.isVerified,
71+
isPrivate: user.isPrivate,
72+
},
73+
token,
74+
};
75+
this.eventEmitter.emit(session, data);
76+
res.status(200).send();
77+
} catch (error) {
78+
console.error("Error during login:", error);
79+
res.status(500).json({ error: "Internal server error" });
80+
}
81+
};
82+
}
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import { Request, Response } from "express";
2+
import { GroupService } from "../services/GroupService";
3+
4+
export class GroupController {
5+
private groupService = new GroupService();
6+
7+
async createGroup(req: Request, res: Response) {
8+
try {
9+
const userId = (req as any).user?.id;
10+
if (!userId) {
11+
return res.status(401).json({ error: "Unauthorized" });
12+
}
13+
14+
const { name, description, participants } = req.body;
15+
16+
const group = await this.groupService.createGroup({
17+
name,
18+
description,
19+
owner: userId,
20+
admins: [userId],
21+
participants: []
22+
});
23+
24+
// Add participants including the creator
25+
const allParticipants = [...new Set([userId, ...participants])];
26+
for (const participantId of allParticipants) {
27+
await this.groupService.addParticipantToGroup(group.id, participantId);
28+
}
29+
30+
const fullGroup = await this.groupService.getGroupById(group.id);
31+
res.status(201).json(fullGroup);
32+
} catch (error) {
33+
console.error("Error creating group:", error);
34+
res.status(500).json({ error: "Internal server error" });
35+
}
36+
}
37+
38+
async getGroupById(req: Request, res: Response) {
39+
try {
40+
const { id } = req.params;
41+
const group = await this.groupService.getGroupById(id);
42+
43+
if (!group) {
44+
return res.status(404).json({ error: "Group not found" });
45+
}
46+
47+
res.json(group);
48+
} catch (error) {
49+
console.error("Error getting group by id:", error);
50+
res.status(500).json({ error: "Internal server error" });
51+
}
52+
}
53+
54+
async updateGroup(req: Request, res: Response) {
55+
try {
56+
const { id } = req.params;
57+
const userId = (req as any).user?.id;
58+
59+
if (!userId) {
60+
return res.status(401).json({ error: "Unauthorized" });
61+
}
62+
63+
const group = await this.groupService.getGroupById(id);
64+
if (!group) {
65+
return res.status(404).json({ error: "Group not found" });
66+
}
67+
68+
// Check if user is owner or admin
69+
const isOwner = group.owner === userId;
70+
const isAdmin = group.admins?.includes(userId);
71+
72+
if (!isOwner && !isAdmin) {
73+
return res.status(403).json({ error: "Access denied" });
74+
}
75+
76+
const groupData = req.body;
77+
const updatedGroup = await this.groupService.updateGroup(id, groupData);
78+
if (!updatedGroup) {
79+
return res.status(404).json({ error: "Group not found" });
80+
}
81+
82+
res.json(updatedGroup);
83+
} catch (error) {
84+
console.error("Error updating group:", error);
85+
res.status(500).json({ error: "Internal server error" });
86+
}
87+
}
88+
89+
async updateCharter(req: Request, res: Response) {
90+
try {
91+
const { id } = req.params;
92+
const userId = (req as any).user?.id;
93+
94+
if (!userId) {
95+
return res.status(401).json({ error: "Unauthorized" });
96+
}
97+
98+
const group = await this.groupService.getGroupById(id);
99+
if (!group) {
100+
return res.status(404).json({ error: "Group not found" });
101+
}
102+
103+
// Check if user is a participant in the group
104+
const isParticipant = group.participants?.some(p => p.id === userId);
105+
if (!isParticipant) {
106+
return res.status(403).json({ error: "Access denied - you must be a participant in this group" });
107+
}
108+
109+
const { charter } = req.body;
110+
const updatedGroup = await this.groupService.updateGroup(id, { charter });
111+
112+
if (!updatedGroup) {
113+
return res.status(404).json({ error: "Group not found" });
114+
}
115+
116+
res.json(updatedGroup);
117+
} catch (error) {
118+
console.error("Error updating charter:", error);
119+
res.status(500).json({ error: "Internal server error" });
120+
}
121+
}
122+
123+
async deleteGroup(req: Request, res: Response) {
124+
try {
125+
const { id } = req.params;
126+
const success = await this.groupService.deleteGroup(id);
127+
128+
if (!success) {
129+
return res.status(404).json({ error: "Group not found" });
130+
}
131+
132+
res.json({ message: "Group deleted successfully" });
133+
} catch (error) {
134+
console.error("Error deleting group:", error);
135+
res.status(500).json({ error: "Internal server error" });
136+
}
137+
}
138+
139+
async getAllGroups(req: Request, res: Response) {
140+
try {
141+
const groups = await this.groupService.getAllGroups();
142+
res.json(groups);
143+
} catch (error) {
144+
console.error("Error getting all groups:", error);
145+
res.status(500).json({ error: "Internal server error" });
146+
}
147+
}
148+
149+
async getUserGroups(req: Request, res: Response) {
150+
try {
151+
const userId = (req as any).user?.id;
152+
if (!userId) {
153+
return res.status(401).json({ error: "Unauthorized" });
154+
}
155+
156+
const groups = await this.groupService.getUserGroups(userId);
157+
res.json(groups);
158+
} catch (error) {
159+
console.error("Error getting user groups:", error);
160+
res.status(500).json({ error: "Internal server error" });
161+
}
162+
}
163+
164+
async getGroup(req: Request, res: Response) {
165+
try {
166+
const { groupId } = req.params;
167+
const userId = (req as any).user?.id;
168+
169+
if (!userId) {
170+
return res.status(401).json({ error: "Unauthorized" });
171+
}
172+
173+
const group = await this.groupService.getGroupById(groupId);
174+
if (!group) {
175+
return res.status(404).json({ error: "Group not found" });
176+
}
177+
178+
// Check if user is a participant
179+
const isParticipant = group.participants.some(p => p.id === userId);
180+
if (!isParticipant) {
181+
return res.status(403).json({ error: "Access denied" });
182+
}
183+
184+
res.json(group);
185+
} catch (error) {
186+
console.error("Error getting group:", error);
187+
res.status(500).json({ error: "Internal server error" });
188+
}
189+
}
190+
191+
async addParticipants(req: Request, res: Response) {
192+
try {
193+
const { groupId } = req.params;
194+
const { participants } = req.body;
195+
const userId = (req as any).user?.id;
196+
197+
if (!userId) {
198+
return res.status(401).json({ error: "Unauthorized" });
199+
}
200+
201+
const group = await this.groupService.getGroupById(groupId);
202+
if (!group) {
203+
return res.status(404).json({ error: "Group not found" });
204+
}
205+
206+
// Check if user is admin or owner
207+
const isAdmin = group.admins?.includes(userId) || group.owner === userId;
208+
if (!isAdmin) {
209+
return res.status(403).json({ error: "Access denied" });
210+
}
211+
212+
for (const participantId of participants) {
213+
await this.groupService.addParticipantToGroup(groupId, participantId);
214+
}
215+
216+
const updatedGroup = await this.groupService.getGroupById(groupId);
217+
res.json(updatedGroup);
218+
} catch (error) {
219+
console.error("Error adding participants:", error);
220+
res.status(500).json({ error: "Internal server error" });
221+
}
222+
}
223+
224+
async removeParticipant(req: Request, res: Response) {
225+
try {
226+
const { groupId, userId: participantId } = req.params;
227+
const userId = (req as any).user?.id;
228+
229+
if (!userId) {
230+
return res.status(401).json({ error: "Unauthorized" });
231+
}
232+
233+
const group = await this.groupService.getGroupById(groupId);
234+
if (!group) {
235+
return res.status(404).json({ error: "Group not found" });
236+
}
237+
238+
// Check if user is admin or owner
239+
const isAdmin = group.admins?.includes(userId) || group.owner === userId;
240+
if (!isAdmin) {
241+
return res.status(403).json({ error: "Access denied" });
242+
}
243+
244+
await this.groupService.removeParticipantFromGroup(groupId, participantId);
245+
246+
const updatedGroup = await this.groupService.getGroupById(groupId);
247+
res.json(updatedGroup);
248+
} catch (error) {
249+
console.error("Error removing participant:", error);
250+
res.status(500).json({ error: "Internal server error" });
251+
}
252+
}
253+
}

0 commit comments

Comments
 (0)