Skip to content

Commit 8ab4c6a

Browse files
Add services route and schema for managing global services
1 parent f680eb6 commit 8ab4c6a

3 files changed

Lines changed: 128 additions & 0 deletions

File tree

src/database/schemas/Service.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import mongoose from "mongoose";
2+
3+
const ServiceSchema = new mongoose.Schema({
4+
key: { type: String, required: true, unique: true },
5+
name: { type: String, required: true },
6+
alwaysEnabled: { type: Boolean, default: false },
7+
enabledUsers: [{ type: String }],
8+
});
9+
10+
export const GlobalService = mongoose.model("GlobalService", ServiceSchema);

src/routes/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import responseTime from 'response-time';
33
import usersRouter from './users';
44
import vpsRouter from './vps';
55
import projectsRouter from './project'
6+
import servicesRouter from './services';
67
const router = Router();
78

89
router.use('/users', usersRouter);
910
router.use('/vps', vpsRouter);
1011
router.use('/projects', projectsRouter)
12+
router.use('/services', servicesRouter)
1113
router.use('/ping', responseTime());
1214

1315
router.get('/ping', async (req: Request, res: Response, next: NextFunction) => {

src/routes/services/index.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { Router, Request, Response } from "express";
2+
import { GlobalService } from "../../database/schemas/Service";
3+
4+
const router = Router();
5+
6+
// Add a new global service
7+
router.post("/add", async (req: Request, res: Response) => {
8+
const { key, name, alwaysEnabled = false } = req.body;
9+
10+
if (!key || !name) {
11+
return res.status(400).json({ error: "Missing 'key' or 'name'" });
12+
}
13+
14+
try {
15+
const existing = await GlobalService.findOne({ key });
16+
if (existing) {
17+
return res.status(400).json({ error: "Service with this key already exists" });
18+
}
19+
20+
const newService = new GlobalService({
21+
key,
22+
name,
23+
alwaysEnabled,
24+
enabledUsers: [] // stores user.email
25+
});
26+
27+
await newService.save();
28+
res.status(201).json({ message: "Service added", service: newService });
29+
} catch (err) {
30+
console.error(err);
31+
res.status(500).json({ error: "Internal Server Error" });
32+
}
33+
});
34+
35+
// Get all services enabled for a specific user (by email)
36+
router.get("/enabled/:email", async (req: Request, res: Response) => {
37+
const email = req.params.email;
38+
39+
try {
40+
const services = await GlobalService.find(
41+
{
42+
$or: [
43+
{ alwaysEnabled: true },
44+
{ enabledUsers: email }
45+
]
46+
},
47+
{
48+
enabledUsers: 0 // Exclude enabledUsers field from the result
49+
}
50+
);
51+
52+
res.status(200).json({ data: { services } });
53+
} catch (err) {
54+
res.status(500).json({ error: "Internal Server Error" });
55+
}
56+
});
57+
58+
// Toggle a service on/off for a user (by email)
59+
router.post("/toggle", async (req: Request, res: Response) => {
60+
const { email, key, enabled } = req.body;
61+
62+
if (!email || !key) {
63+
return res.status(400).json({ error: "Missing 'email' or 'service key'" });
64+
}
65+
66+
try {
67+
const service = await GlobalService.findOne({ key });
68+
69+
if (!service) {
70+
return res.status(404).json({ error: "Service not found" });
71+
}
72+
73+
if (service.alwaysEnabled) {
74+
return res.status(400).json({ error: "Cannot toggle an always-enabled service" });
75+
}
76+
77+
// Update based on the requested 'enabled' value instead of toggling
78+
const update = enabled
79+
? { $addToSet: { enabledUsers: email } } // Add the user if not already there
80+
: { $pull: { enabledUsers: email } }; // Remove the user
81+
82+
await GlobalService.updateOne({ key }, update);
83+
84+
res.status(200).json({
85+
message: `Service ${enabled ? 'enabled' : 'disabled'}`,
86+
changed: true
87+
});
88+
89+
} catch (err) {
90+
console.error(err);
91+
res.status(500).json({ error: "Internal Server Error" });
92+
}
93+
});
94+
95+
// Get all available services (no user filtering)
96+
router.get("/all", async (req: Request, res: Response) => {
97+
try {
98+
const services = await GlobalService.find({}, { enabledUsers: 0 }); // exclude enabledUsers field
99+
res.status(200).json({ data: { services } });
100+
} catch (err) {
101+
console.error(err);
102+
res.status(500).json({ error: "Internal Server Error" });
103+
}
104+
});
105+
106+
router.get("/alladmin", async (req: Request, res: Response) => {
107+
try {
108+
const servicesAdmin = await GlobalService.find({});
109+
res.status(200).json({ data: { servicesAdmin } });
110+
} catch (err) {
111+
console.error(err);
112+
res.status(500).json({ error: "Internal Server Error" });
113+
}
114+
});
115+
116+
export default router;

0 commit comments

Comments
 (0)