import express from 'express'; | |
import axios from 'axios'; | |
import { authenticateApiKey, apiLimiter } from '../middleware/midware.js'; | |
import { Federation } from '../models.js'; | |
const FedsRoutes = express.Router(); | |
/** | |
* @swagger | |
* /api/v2/federation/newfed: | |
* post: | |
* summary: Create a new federation | |
* tags: [Federation] | |
* description: Creates a new federation with a unique name and owner. | |
* security: | |
* - apiKeyAuth: [] | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* name: | |
* type: string | |
* description: The unique name of the federation. | |
* owner: | |
* type: integer | |
* description: The user ID of the federation owner. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Federation created successfully. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* message: | |
* type: string | |
* example: Federation created successfully | |
* federation: | |
* type: object | |
* properties: | |
* name: | |
* type: string | |
* owner: | |
* type: integer | |
* banned_users: | |
* type: array | |
* items: | |
* type: integer | |
* sub_federations: | |
* type: array | |
* items: | |
* type: string | |
* 400: | |
* description: Federation already exists or missing parameters. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post("/api/v2/federation/newfed", authenticateApiKey, apiLimiter, async (req, res) => { | |
try { | |
const { name, owner } = req.body; | |
const existing = await Federation.findOne({ name }); | |
if (existing) return res.status(200).json({ error: "Federation already exists" }); | |
const federation = new Federation({ name, owner, banned_users: [], sub_federations: [] }); | |
await federation.save(); | |
res.json({ message: "Federation created successfully", federation }); | |
} catch (err) { | |
console.log(err.message); | |
res.status(500).json({ error: err.message }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/subfed: | |
* post: | |
* summary: Add a sub-federation | |
* tags: [Federation] | |
* description: Adds a federation as a sub-federation under a parent federation. | |
* security: | |
* - apiKeyAuth: [] | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* parent_uuid: | |
* type: string | |
* description: UUID of the parent federation. | |
* child_uuid: | |
* type: string | |
* description: UUID of the child federation to be added as a sub-federation. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Sub-federation added successfully. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* message: | |
* type: string | |
* example: "Federation ChildName is now a sub-federation of ParentName" | |
* 404: | |
* description: Parent or child federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post("/api/v2/federation/subfed", authenticateApiKey, apiLimiter, async (req, res) => { | |
try { | |
const { parent_uuid, child_uuid } = req.body; | |
const parent = await Federation.findOne({ uuid: parent_uuid }); | |
const child = await Federation.findOne({ uuid: child_uuid }); | |
if (!parent || !child) return res.status(404).json({ error: "Federation not found" }); | |
if (!parent.sub_federations.includes(child.uuid)) { | |
parent.sub_federations.push(child.uuid); | |
await parent.save(); | |
} | |
res.json({ message: `Federation ${child.name} is now a sub-federation of ${parent.name}` }); | |
} catch (err) { | |
res.status(500).json({ error: err.message }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/getfed/{uuid}: | |
* get: | |
* summary: Check Federation Info | |
* tags: [Federation] | |
* parameters: | |
* - in: path | |
* name: uuid | |
* required: true | |
* description: Check uuid to info | |
* schema: | |
* type: string | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Returns | |
*/ | |
FedsRoutes.get("/api/v2/federation/getfed/:uuid", authenticateApiKey, apiLimiter, async (req, res) => { | |
try { | |
const federation = await Federation.findOne({ uuid: req.params.uuid }); | |
if (!federation) return res.status(404).json({ error: "Federation not found" }); | |
const subFeds = await Federation.find({ uuid: { $in: federation.sub_federations } }); | |
res.json({ federation, sub_federations: subFeds }); | |
} catch (err) { | |
res.status(500).json({ error: err.message }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/unban: | |
* post: | |
* summary: Unban a user in a federation | |
* tags: [Federation] | |
* description: Removes a user from the banned list of a specified federation. | |
* security: | |
* - apiKeyAuth: [] | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* name: | |
* type: string | |
* description: Name of the federation where the user will be unbanned. | |
* user_id: | |
* type: integer | |
* description: User ID to be unbanned. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: User unbanned successfully. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* success: | |
* type: boolean | |
* example: true | |
* message: | |
* type: string | |
* example: "User 12345 unbanned from federation FederationName." | |
* 400: | |
* description: Missing federation name or user ID. | |
* 404: | |
* description: Federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post('/api/v2/federation/unban', authenticateApiKey, async (req, res) => { | |
try { | |
const { name, user_id } = req.body; | |
if (!name || !user_id || isNaN(user_id)) { | |
return res.status(400).json({ error: "Federation name and valid user ID required" }); | |
} | |
const federation = await Federation.findOne({ name }); | |
if (!federation) { | |
return res.status(404).json({ error: "Federation not found." }); | |
} | |
federation.banned_users = federation.banned_users.filter(id => Number(id) !== Number(user_id)); | |
await federation.save(); | |
await Federation.updateMany( | |
{ uuid: { $in: federation.sub_federations } }, | |
{ $pull: { banned_users: Number(user_id) } } | |
); | |
res.json({ success: true, message: `User ${user_id} unbanned from ${name} and its sub-federations.` }); | |
} catch (error) { | |
res.status(500).json({ error: `Failed to unban user: ${error.message}` }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/ban: | |
* post: | |
* summary: Ban a user in a federation | |
* tags: [Federation] | |
* description: Bans a user in the specified federation and all its sub-federations. | |
* security: | |
* - apiKeyAuth: [] | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* federation_uuid: | |
* type: string | |
* description: UUID of the federation where the user will be banned. | |
* user_id: | |
* type: integer | |
* description: User ID to be banned. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: User banned successfully. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* message: | |
* type: string | |
* example: "User 12345 banned in FederationName and all its sub-federations" | |
* 404: | |
* description: Federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post("/api/v2/federation/ban", authenticateApiKey, apiLimiter, async (req, res) => { | |
try { | |
const { federation_uuid, user_id } = req.body; | |
if (!federation_uuid || !user_id || isNaN(user_id)) { | |
return res.status(400).json({ error: "Federation UUID and valid user ID required" }); | |
} | |
const federation = await Federation.findOne({ uuid: federation_uuid }); | |
if (!federation) return res.status(404).json({ error: "Federation not found" }); | |
if (!federation.banned_users.includes(Number(user_id))) { | |
federation.banned_users.push(Number(user_id)); | |
await federation.save(); | |
} | |
await Federation.updateMany( | |
{ uuid: { $in: federation.sub_federations } }, | |
{ $addToSet: { banned_users: Number(user_id) } } | |
); | |
res.json({ message: `User ${user_id} banned in ${federation.name} and all its sub-federations.` }); | |
console.log(user_id); | |
} catch (err) { | |
res.status(500).json({ error: err.message }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/ban-check: | |
* post: | |
* summary: Check if a user is banned in a federation | |
* tags: [Federation] | |
* description: Checks whether a user is banned in a specific federation using UUID and user ID. | |
* security: | |
* - apiKeyAuth: [] | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* federation_uuid: | |
* type: string | |
* description: UUID of the federation. | |
* user_id: | |
* type: integer | |
* description: User ID to check. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Ban status of the user in the federation. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* federation: | |
* type: string | |
* example: "AkenoX Federation" | |
* user_id: | |
* type: integer | |
* example: 12345 | |
* is_banned: | |
* type: boolean | |
* example: true | |
* 400: | |
* description: Missing federation UUID or invalid user ID. | |
* 404: | |
* description: Federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post("/api/v2/federation/ban-check", authenticateApiKey, async (req, res) => { | |
try { | |
const { federation_uuid, user_id } = req.body; | |
if (!federation_uuid || !user_id || isNaN(user_id)) { | |
return res.status(400).json({ error: "Federation UUID and valid user ID required." }); | |
} | |
const federation = await Federation.findOne({ uuid: federation_uuid }); | |
if (!federation) { | |
return res.status(404).json({ error: "Federation not found." }); | |
} | |
const isBanned = federation.banned_users.includes(user_id); | |
res.json({ | |
federation: federation.name, | |
user_id, | |
is_banned: isBanned | |
}); | |
} catch (error) { | |
res.status(500).json({ error: `Failed to check ban status: ${error.message}` }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/fedstats: | |
* get: | |
* summary: Get Federation Statistics | |
* tags: [Federation] | |
* description: Retrieve the statistics of a federation, including total banned users and sub-federations. | |
* parameters: | |
* - in: query | |
* name: uuid | |
* required: true | |
* description: UUID of the federation to check stats for. | |
* schema: | |
* type: string | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Federation statistics retrieved successfully. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* success: | |
* type: boolean | |
* example: true | |
* stats: | |
* type: object | |
* properties: | |
* federation_name: | |
* type: string | |
* example: "Example Federation" | |
* total_banned_users: | |
* type: integer | |
* example: 10 | |
* total_sub_federations: | |
* type: integer | |
* example: 3 | |
* owner: | |
* type: number | |
* example: 123456789 | |
* 400: | |
* description: Missing or invalid federation UUID. | |
* 404: | |
* description: Federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.get("/api/v2/federation/fedstats", authenticateApiKey, async (req, res) => { | |
try { | |
const { uuid } = req.query; | |
if (!uuid) { | |
return res.status(400).json({ error: "Federation UUID is required" }); | |
} | |
const federation = await Federation.findOne({ uuid }); | |
if (!federation) { | |
return res.status(404).json({ error: "Federation not found" }); | |
} | |
const stats = { | |
federation_name: federation.name, | |
total_banned_users: federation.banned_users.length, | |
total_sub_federations: federation.sub_federations.length, | |
owner: federation.owner, | |
}; | |
res.json({ success: true, stats }); | |
} catch (error) { | |
res.status(500).json({ error: `Failed to fetch federation stats: ${error.message}` }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/unsubfed: | |
* post: | |
* summary: Unsubscribe a Sub-Federation | |
* tags: [Federation] | |
* description: Remove a sub-federation from a parent federation. | |
* security: | |
* - apiKeyAuth: [] | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* parent_uuid: | |
* type: string | |
* description: UUID of the parent federation. | |
* child_uuid: | |
* type: string | |
* description: UUID of the sub-federation to be removed. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Sub-federation successfully removed. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* message: | |
* type: string | |
* example: "Federation SubFed has been unsubscribed from ParentFed." | |
* 400: | |
* description: Missing or invalid federation UUIDs. | |
* 404: | |
* description: Federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post("/api/v2/federation/unsubfed", authenticateApiKey, apiLimiter, async (req, res) => { | |
try { | |
const { parent_uuid, child_uuid } = req.body; | |
if (!parent_uuid || !child_uuid) { | |
return res.status(400).json({ error: "Both parent and child federation UUIDs are required." }); | |
} | |
const parent = await Federation.findOne({ uuid: parent_uuid }); | |
const child = await Federation.findOne({ uuid: child_uuid }); | |
if (!parent || !child) { | |
return res.status(404).json({ error: "Federation not found." }); | |
} | |
parent.sub_federations = parent.sub_federations.filter(uuid => uuid !== child_uuid); | |
await parent.save(); | |
res.json({ message: `Federation ${child.name} has been unsubscribed from ${parent.name}` }); | |
} catch (error) { | |
res.status(500).json({ error: `Failed to unsubscribe sub-federation: ${error.message}` }); | |
} | |
}); | |
/** | |
* @swagger | |
* /api/v2/federation/renamefed: | |
* post: | |
* summary: Rename a Federation | |
* tags: [Federation] | |
* description: Change the name of an existing federation. | |
* requestBody: | |
* required: true | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* federation_uuid: | |
* type: string | |
* description: UUID of the federation to be renamed. | |
* new_name: | |
* type: string | |
* description: The new name for the federation. | |
* parameters: | |
* - in: header | |
* name: x-api-key | |
* required: true | |
* description: API key for authentication. | |
* schema: | |
* type: string | |
* responses: | |
* 200: | |
* description: Federation successfully renamed. | |
* content: | |
* application/json: | |
* schema: | |
* type: object | |
* properties: | |
* message: | |
* type: string | |
* example: "Federation renamed to NewFedName successfully." | |
* 400: | |
* description: Missing parameters or federation name already exists. | |
* 404: | |
* description: Federation not found. | |
* 500: | |
* description: Internal server error. | |
*/ | |
FedsRoutes.post("/api/v2/federation/renamefed", authenticateApiKey, apiLimiter, async (req, res) => { | |
try { | |
const { federation_uuid, new_name } = req.body; | |
if (!federation_uuid || !new_name) { | |
return res.status(400).json({ error: "Federation UUID and new name are required." }); | |
} | |
const federation = await Federation.findOne({ uuid: federation_uuid }); | |
if (!federation) { | |
return res.status(404).json({ error: "Federation not found." }); | |
} | |
const existingFederation = await Federation.findOne({ name: new_name }); | |
if (existingFederation) { | |
return res.status(400).json({ error: "Federation name already exists." }); | |
} | |
federation.name = new_name; | |
await federation.save(); | |
res.json({ message: `Federation renamed to ${new_name} successfully.` }); | |
} catch (error) { | |
res.status(500).json({ error: `Failed to rename federation: ${error.message}` }); | |
} | |
}); | |
export { FedsRoutes }; |