const { escape } = require("sqlstring-sqlite"); const { Invite } = require("../../../models/invite"); const { SystemSettings } = require("../../../models/systemSettings"); const { User } = require("../../../models/user"); const { Workspace } = require("../../../models/workspace"); const { WorkspaceChats } = require("../../../models/workspaceChats"); const { multiUserMode, reqBody } = require("../../../utils/http"); const { validApiKey } = require("../../../utils/middleware/validApiKey"); function apiAdminEndpoints(app) { if (!app) return; app.get("/v1/admin/is-multi-user-mode", [validApiKey], (_, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Check to see if the instance is in multi-user-mode first. Methods are disabled until multi user mode is enabled via the UI.' #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { "isMultiUser": true } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } */ const isMultiUser = multiUserMode(response); response.status(200).json({ isMultiUser }); }); app.get("/v1/admin/users", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Check to see if the instance is in multi-user-mode first. Methods are disabled until multi user mode is enabled via the UI.' #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { "users": [ { username: "sample-sam", role: 'default', } ] } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const users = (await User.where()).map((user) => { const { password, ...rest } = user; return rest; }); response.status(200).json({ users }); } catch (e) { console.error(e); response.sendStatus(500).end(); } }); app.post("/v1/admin/users/new", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Create a new user with username and password. Methods are disabled until multi user mode is enabled via the UI.' #swagger.requestBody = { description: 'Key pair object that will define the new user to add to the system.', required: true, type: 'object', content: { "application/json": { example: { username: "sample-sam", password: 'hunter2', role: 'default | admin' } } } } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { user: { id: 1, username: 'sample-sam', role: 'default', }, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const newUserParams = reqBody(request); const { user: newUser, error } = await User.create(newUserParams); response.status(200).json({ user: newUser, error }); } catch (e) { console.error(e); response.sendStatus(500).end(); } }); app.post("/v1/admin/users/:id", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.path = '/v1/admin/users/{id}' #swagger.parameters['id'] = { in: 'path', description: 'id of the user in the database.', required: true, type: 'string' } #swagger.description = 'Update existing user settings. Methods are disabled until multi user mode is enabled via the UI.' #swagger.requestBody = { description: 'Key pair object that will update the found user. All fields are optional and will not update unless specified.', required: true, type: 'object', content: { "application/json": { example: { username: "sample-sam", password: 'hunter2', role: 'default | admin', suspended: 0, } } } } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { success: true, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const { id } = request.params; const updates = reqBody(request); const { success, error } = await User.update(id, updates); response.status(200).json({ success, error }); } catch (e) { console.error(e); response.sendStatus(500).end(); } }); app.delete( "/v1/admin/users/:id", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Delete existing user by id. Methods are disabled until multi user mode is enabled via the UI.' #swagger.path = '/v1/admin/users/{id}' #swagger.parameters['id'] = { in: 'path', description: 'id of the user in the database.', required: true, type: 'string' } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { success: true, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const { id } = request.params; await User.delete(`id = ${id}`); response.status(200).json({ success: true, error: null }); } catch (e) { console.error(e); response.sendStatus(500).end(); } } ); app.get("/v1/admin/invites", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'List all existing invitations to instance regardless of status. Methods are disabled until multi user mode is enabled via the UI.' #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { "invites": [ { id: 1, status: "pending", code: 'abc-123', claimedBy: null } ] } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const invites = await Invite.whereWithUsers(); response.status(200).json({ invites }); } catch (e) { console.error(e); response.sendStatus(500).end(); } }); app.post("/v1/admin/invite/new", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Create a new invite code for someone to use to register with instance. Methods are disabled until multi user mode is enabled via the UI.' #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { invite: { id: 1, status: "pending", code: 'abc-123', }, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const { invite, error } = await Invite.create(); response.status(200).json({ invite, error }); } catch (e) { console.error(e); response.sendStatus(500).end(); } }); app.delete( "/v1/admin/invite/:id", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Deactivates (soft-delete) invite by id. Methods are disabled until multi user mode is enabled via the UI.' #swagger.path = '/v1/admin/invite/{id}' #swagger.parameters['id'] = { in: 'path', description: 'id of the invite in the database.', required: true, type: 'string' } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { success: true, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const { id } = request.params; const { success, error } = await Invite.deactivate(id); response.status(200).json({ success, error }); } catch (e) { console.error(e); response.sendStatus(500).end(); } } ); app.post( "/v1/admin/workspaces/:workspaceId/update-users", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.path = '/v1/admin/workspaces/{workspaceId}/update-users' #swagger.parameters['workspaceId'] = { in: 'path', description: 'id of the workspace in the database.', required: true, type: 'string' } #swagger.description = 'Overwrite workspace permissions to only be accessible by the given user ids and admins. Methods are disabled until multi user mode is enabled via the UI.' #swagger.requestBody = { description: 'Entire array of user ids who can access the workspace. All fields are optional and will not update unless specified.', required: true, type: 'object', content: { "application/json": { example: { userIds: [1,2,4,12], } } } } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { success: true, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const { workspaceId } = request.params; const { userIds } = reqBody(request); const { success, error } = await Workspace.updateUsers( escape(workspaceId), userIds ); response.status(200).json({ success, error }); } catch (e) { console.error(e); response.sendStatus(500).end(); } } ); app.post( "/v1/admin/workspace-chats", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'All chats in the system ordered by most recent. Methods are disabled until multi user mode is enabled via the UI.' #swagger.requestBody = { description: 'Page offset to show of workspace chats. All fields are optional and will not update unless specified.', required: false, type: 'integer', content: { "application/json": { example: { offset: 2, } } } } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { success: true, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const { offset = 0 } = reqBody(request); const chats = await WorkspaceChats.whereWithData( `id >= ${escape(offset)}`, 20 ); const hasPages = (await WorkspaceChats.count()) > 20; response.status(200).json({ chats: chats.reverse(), hasPages }); } catch (e) { console.error(e); response.sendStatus(500).end(); } } ); app.get("/v1/admin/preferences", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Show all multi-user preferences for instance. Methods are disabled until multi user mode is enabled via the UI.' #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { settings: { users_can_delete_workspaces: true, limit_user_messages: false, message_limit: 10, } } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const settings = { users_can_delete_workspaces: (await SystemSettings.get(`label = 'users_can_delete_workspaces'`)) ?.value === "true", limit_user_messages: (await SystemSettings.get(`label = 'limit_user_messages'`))?.value === "true", message_limit: Number( (await SystemSettings.get(`label = 'message_limit'`))?.value ) || 10, }; response.status(200).json({ settings }); } catch (e) { console.error(e); response.sendStatus(500).end(); } }); app.post( "/v1/admin/preferences", [validApiKey], async (request, response) => { /* #swagger.tags = ['Admin'] #swagger.description = 'Update multi-user preferences for instance. Methods are disabled until multi user mode is enabled via the UI.' #swagger.requestBody = { description: 'Object with setting key and new value to set. All keys are optional and will not update unless specified.', required: true, type: 'object', content: { "application/json": { example: { users_can_delete_workspaces: false, limit_user_messages: true, message_limit: 5, } } } } #swagger.responses[200] = { content: { "application/json": { schema: { type: 'object', example: { success: true, error: null, } } } } } #swagger.responses[403] = { schema: { "$ref": "#/definitions/InvalidAPIKey" } } #swagger.responses[401] = { description: "Instance is not in Multi-User mode. Method denied", } */ try { if (!multiUserMode(response)) { response.sendStatus(401).end(); return; } const updates = reqBody(request); await SystemSettings.updateSettings(updates); response.status(200).json({ success: true, error: null }); } catch (e) { console.error(e); response.sendStatus(500).end(); } } ); } module.exports = { apiAdminEndpoints };