Skip to content

Commit faae097

Browse files
committed
added page routes, middlewares, modals and bumped version
1 parent ee9815c commit faae097

File tree

5 files changed

+471
-2
lines changed

5 files changed

+471
-2
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import System from '../../../models/schemas/System.js';
2+
3+
/**
4+
* Fetches the status of a specific page (availability & maintenance status).
5+
*/
6+
export const getPageStatus = async (req, res) => {
7+
try {
8+
const { id } = req.params;
9+
const key = req.headers.key;
10+
11+
// Check for valid access key in headers
12+
if (!key || key !== process.env.ACCESS_KEY) {
13+
return res.status(401).json({
14+
message: 'Unauthorized',
15+
});
16+
}
17+
18+
const system = await System.findOne({ 'pages._id': id }, { 'pages.$': 1 });
19+
20+
if (!system || !system.pages.length) {
21+
return res.status(404).json({ message: 'Page not found' });
22+
}
23+
24+
const page = system.pages[0];
25+
26+
return res.status(200).json({
27+
_id: page._id,
28+
available: page.available,
29+
maintenance: page.maintenance,
30+
});
31+
} catch (error) {
32+
console.error('Error fetching page status:', error);
33+
return res.status(500).json({ message: 'Internal Server Error' });
34+
}
35+
};
36+
37+
/**
38+
* Retrieves metadata, including permissions and maintenance info.
39+
*/
40+
export const getPageMeta = async (req, res) => {
41+
try {
42+
const { id } = req.params;
43+
const key = req.headers.key;
44+
45+
// Check for valid access key in headers
46+
if (!key || key !== process.env.ACCESS_KEY) {
47+
return res.status(401).json({
48+
message: 'Unauthorized',
49+
});
50+
}
51+
52+
const system = await System.findOne({ 'pages._id': id }, { 'pages.$': 1 });
53+
54+
if (!system || !system.pages.length) {
55+
return res.status(404).json({ message: 'Page not found' });
56+
}
57+
58+
const page = system.pages[0];
59+
60+
return res.status(200).json({
61+
_id: page._id,
62+
type: page.type,
63+
maintenance: page.maintenance,
64+
permission: page.permission,
65+
});
66+
} catch (error) {
67+
console.error('Error fetching page metadata:', error);
68+
return res.status(500).json({ message: 'Internal Server Error' });
69+
}
70+
};
71+
72+
/**
73+
* Checks if the user has permission to access the page.
74+
*/
75+
export const checkPageAccess = async (req, res) => {
76+
try {
77+
const { id } = req.params;
78+
const { role } = req.query; // User role should be passed as a query param
79+
const key = req.headers.key;
80+
81+
// Check for valid access key in headers
82+
if (!key || key !== process.env.ACCESS_KEY) {
83+
return res.status(401).json({
84+
message: 'Unauthorized',
85+
});
86+
}
87+
88+
const system = await System.findOne({ 'pages._id': id }, { 'pages.$': 1 });
89+
90+
if (!system || !system.pages.length) {
91+
return res.status(404).json({ message: 'Page not found' });
92+
}
93+
94+
const page = system.pages[0];
95+
96+
if (!role) {
97+
return res.status(200).json({ _id: page._id, permissions: page.permission });
98+
}
99+
100+
const hasAccess = page.permission.roles.includes('guest') || page.permission.roles.includes(role);
101+
102+
return res.status(200).json({ _id: page._id, access: hasAccess });
103+
} catch (error) {
104+
console.error('Error checking page access:', error);
105+
return res.status(500).json({ message: 'Internal Server Error' });
106+
}
107+
};
108+
109+
/**
110+
* Returns general page details, including type, status, and permissions.
111+
*/
112+
export const getPageInfo = async (req, res) => {
113+
try {
114+
const { id } = req.params;
115+
const key = req.headers.key;
116+
117+
// Check for valid access key in headers
118+
if (!key || key !== process.env.ACCESS_KEY) {
119+
return res.status(401).json({
120+
message: 'Unauthorized',
121+
});
122+
}
123+
124+
const system = await System.findOne({ 'pages._id': id }, { 'pages.$': 1 });
125+
126+
if (!system || !system.pages.length) {
127+
return res.status(404).json({ message: 'Page not found' });
128+
}
129+
130+
const page = system.pages[0];
131+
132+
return res.status(200).json(page);
133+
} catch (error) {
134+
console.error('Error fetching page info:', error);
135+
return res.status(500).json({ message: 'Internal Server Error' });
136+
}
137+
};
138+
139+
/**
140+
* Updates page details (availability, type, maintenance, or permissions).
141+
*/
142+
export const updatePage = async (req, res) => {
143+
try {
144+
const { id } = req.params;
145+
const { available, type, maintenance, permission } = req.body;
146+
const key = req.headers.key;
147+
148+
// Check for valid access key in headers
149+
if (!key || key !== process.env.ACCESS_KEY) {
150+
return res.status(401).json({ message: 'Unauthorized' });
151+
}
152+
153+
// Validate input
154+
if (type && !['production', 'alpha', 'beta'].includes(type)) {
155+
return res.status(400).json({ message: 'Invalid page type' });
156+
}
157+
158+
const updateFields = {};
159+
if (available !== undefined) updateFields['pages.$.available'] = available;
160+
if (type) updateFields['pages.$.type'] = type;
161+
162+
// Merge `maintenance` fields instead of replacing
163+
if (maintenance) {
164+
Object.keys(maintenance).forEach(key => {
165+
updateFields[`pages.$.maintenance.${key}`] = maintenance[key];
166+
});
167+
}
168+
169+
// Merge `permission` fields instead of replacing
170+
if (permission) {
171+
Object.keys(permission).forEach(key => {
172+
updateFields[`pages.$.permission.${key}`] = permission[key];
173+
});
174+
}
175+
176+
if (Object.keys(updateFields).length === 0) {
177+
return res.status(400).json({ message: 'No valid fields to update' });
178+
}
179+
180+
// Update the document without projection to avoid MongoDB error
181+
await System.findOneAndUpdate({ 'pages._id': id }, { $set: updateFields });
182+
183+
// Fetch the updated page separately
184+
const updatedSystem = await System.findOne({ 'pages._id': id }, { pages: { $elemMatch: { _id: id } } });
185+
186+
if (!updatedSystem || !updatedSystem.pages.length) {
187+
return res.status(404).json({ message: 'Page not found' });
188+
}
189+
190+
return res.status(200).json({
191+
message: 'Page updated successfully',
192+
page: updatedSystem.pages[0],
193+
});
194+
} catch (error) {
195+
console.error('Error updating page:', error);
196+
return res.status(500).json({ message: 'Internal Server Error' });
197+
}
198+
};
199+
200+
/**
201+
* Middleware to add page details
202+
*/
203+
export const addPage = async (req, res, next) => {
204+
try {
205+
const { name, available, type, maintenance, permission } = req.body;
206+
const key = req.headers.key;
207+
208+
// Check for valid access key in headers
209+
if (!key || key !== process.env.ACCESS_KEY) {
210+
return res.status(401).json({ message: 'Unauthorized' });
211+
}
212+
213+
// Validate input
214+
if (!name) {
215+
return res.status(400).json({ message: 'Page name is required' });
216+
}
217+
218+
if (type && !['production', 'alpha', 'beta'].includes(type)) {
219+
return res.status(400).json({ message: 'Invalid page type' });
220+
}
221+
222+
const newPage = {
223+
_id: name,
224+
available: available ?? true, // Default to true if not provided
225+
type: type || 'production',
226+
maintenance: maintenance || {},
227+
permission: permission || {},
228+
};
229+
230+
const updatedSystem = await System.findOneAndUpdate(
231+
{},
232+
{ $push: { pages: newPage } },
233+
{ new: true, projection: { pages: 1 } },
234+
);
235+
236+
if (!updatedSystem) {
237+
return res.status(500).json({ message: 'Failed to add page' });
238+
}
239+
240+
return res.status(201).json({
241+
message: 'Page added successfully',
242+
page: newPage,
243+
});
244+
} catch (error) {
245+
console.error('Error adding page:', error);
246+
return res.status(500).json({ message: 'Internal Server Error' });
247+
}
248+
};

src/models/schemas/System.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
import mongoose from 'mongoose';
22
const { Schema, model } = mongoose;
33

4+
const roles = [
5+
'developer',
6+
'super_admin',
7+
'admin',
8+
'database_moderator',
9+
'discord_moderator',
10+
'moderator',
11+
'community_manager',
12+
'support',
13+
'contributor',
14+
'tester',
15+
'beta_tester',
16+
'alpha_tester',
17+
'translator',
18+
'sponsor',
19+
'member',
20+
'user',
21+
'guest',
22+
];
23+
424
const SystemSchema = new Schema({
525
_id: String,
626
membership: {
@@ -22,6 +42,27 @@ const SystemSchema = new Schema({
2242
},
2343
],
2444
},
45+
pages: [
46+
{
47+
_id: { type: String, required: true, unique: true },
48+
available: { type: Boolean, default: true },
49+
type: { type: String, enum: ['production', 'alpha', 'beta'], required: true },
50+
maintenance: {
51+
status: { type: Boolean, default: false },
52+
message: { type: String, default: 'Page is under maintenance. Please try again later.' },
53+
},
54+
permission: {
55+
roles: [
56+
{
57+
type: String,
58+
enum: roles,
59+
required: true,
60+
default: ['user'],
61+
},
62+
],
63+
},
64+
},
65+
],
2566
});
2667

2768
export default model('System', SystemSchema);

src/routes/v4/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,38 @@ import membershipRoutes from './internal/membership.js';
12241224
*/
12251225
router.use('/membership', membershipRoutes);
12261226

1227+
import notificationRoutes from './internal/notifications.js';
1228+
1229+
/**
1230+
* @api {use} Mount Membership Routes
1231+
* @apiDescription Mount the membership-related routes for handling interactions.
1232+
* @apiName UseMembershipRoutes
1233+
* @apiGroup Routes
1234+
*
1235+
* @apiSuccess {Object} routes Membership-related routes mounted on the parent router.
1236+
*
1237+
* @function createMembershipRoutes
1238+
* @description Creates and returns a set of routes for handling interactions related to Membership.
1239+
* @returns {Object} Membership-related routes.
1240+
*/
1241+
router.use('/notifications', notificationRoutes);
1242+
1243+
import pageRoutes from './internal/pages.js';
1244+
1245+
/**
1246+
* @api {use} Mount Pages Routes
1247+
* @apiDescription Mount the pages-related routes for handling page interactions.
1248+
* @apiName UsePagesRoutes
1249+
* @apiGroup Routes
1250+
*
1251+
* @apiSuccess {Object} routes Pages-related routes mounted on the parent router.
1252+
*
1253+
* @function createPagesRoutes
1254+
* @description Creates and returns a set of routes for handling interactions related to pages.
1255+
* @returns {Object} Pages-related routes.
1256+
*/
1257+
router.use('/pages', pageRoutes);
1258+
12271259
/**
12281260
* Exporting the router for use in other parts of the application.
12291261
* @exports {Router} router - Express Router instance with mounted routes.

0 commit comments

Comments
 (0)