θΏ™ζ˜―indexlocζδΎ›ηš„ζœεŠ‘οΌŒδΈθ¦θΎ“ε…₯任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions server/endpoints/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { apiAuthEndpoints } = require("./auth");
const { apiDocumentEndpoints } = require("./document");
const { apiSystemEndpoints } = require("./system");
const { apiWorkspaceEndpoints } = require("./workspace");
const { apiUserManagementEndpoints } = require("./userManagement");

// All endpoints must be documented and pass through the validApiKey Middleware.
// How to JSDoc an endpoint
Expand All @@ -16,6 +17,7 @@ function developerEndpoints(app, router) {
apiSystemEndpoints(router);
apiWorkspaceEndpoints(router);
apiDocumentEndpoints(router);
apiUserManagementEndpoints(router);
}

module.exports = { developerEndpoints };
64 changes: 64 additions & 0 deletions server/endpoints/api/userManagement/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const { User } = require("../../../models/user");
const { multiUserMode } = require("../../../utils/http");
const { validApiKey } = require("../../../utils/middleware/validApiKey");

function apiUserManagementEndpoints(app) {
if (!app) return;

app.get("/v1/users", [validApiKey], async (request, response) => {
/*
#swagger.tags = ['User Management']
#swagger.description = 'List all users'
#swagger.responses[200] = {
content: {
"application/json": {
schema: {
type: 'object',
example: {
users: [
{
"id": 1,
"username": "john_doe",
"role": "admin"
},
{
"id": 2,
"username": "jane_smith",
"role": "default"
}
]
}
}
}
}
}
#swagger.responses[403] = {
schema: {
"$ref": "#/definitions/InvalidAPIKey"
}
}
#swagger.responses[401] = {
description: "Instance is not in Multi-User mode. Permission denied.",
}
*/
try {
if (!multiUserMode(response))
return response
.status(401)
.send("Instance is not in Multi-User mode. Permission denied.");

const users = await User.where();
const filteredUsers = users.map((user) => ({
id: user.id,
username: user.username,
role: user.role,
}));
response.status(200).json({ users: filteredUsers });
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
});
}

module.exports = { apiUserManagementEndpoints };
107 changes: 55 additions & 52 deletions server/swagger/init.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,76 @@
const swaggerAutogen = require('swagger-autogen')({ openapi: '3.0.0' });
const fs = require('fs')
const path = require('path')
const swaggerAutogen = require("swagger-autogen")({ openapi: "3.0.0" });
const fs = require("fs");
const path = require("path");

const doc = {
info: {
version: '1.0.0',
title: 'AnythingLLM Developer API',
description: 'API endpoints that enable programmatic reading, writing, and updating of your AnythingLLM instance. UI supplied by Swagger.io.',
version: "1.0.0",
title: "AnythingLLM Developer API",
description:
"API endpoints that enable programmatic reading, writing, and updating of your AnythingLLM instance. UI supplied by Swagger.io.",
},
// Swagger-autogen does not allow us to use relative paths as these will resolve to
// http:///api in the openapi.json file, so we need to monkey-patch this post-generation.
host: '/api',
schemes: ['http'],
host: "/api",
schemes: ["http"],
securityDefinitions: {
BearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
}
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
},
},
security: [
{ BearerAuth: [] }
],
security: [{ BearerAuth: [] }],
definitions: {
InvalidAPIKey: {
message: 'Invalid API Key',
message: "Invalid API Key",
},
}
},
};

const outputFile = path.resolve(__dirname, './openapi.json');
const outputFile = path.resolve(__dirname, "./openapi.json");
const endpointsFiles = [
'../endpoints/api/auth/index.js',
'../endpoints/api/admin/index.js',
'../endpoints/api/document/index.js',
'../endpoints/api/workspace/index.js',
'../endpoints/api/system/index.js',
"../endpoints/api/auth/index.js",
"../endpoints/api/admin/index.js",
"../endpoints/api/document/index.js",
"../endpoints/api/workspace/index.js",
"../endpoints/api/system/index.js",
"../endpoints/api/userManagement/index.js",
];

swaggerAutogen(outputFile, endpointsFiles, doc)
.then(({ data }) => {

// Remove Authorization parameters from arguments.
for (const path of Object.keys(data.paths)) {
if (data.paths[path].hasOwnProperty('get')) {
let parameters = data.paths[path].get?.parameters || [];
parameters = parameters.filter((arg) => arg.name !== 'Authorization');
data.paths[path].get.parameters = parameters;
}

if (data.paths[path].hasOwnProperty('post')) {
let parameters = data.paths[path].post?.parameters || [];
parameters = parameters.filter((arg) => arg.name !== 'Authorization');
data.paths[path].post.parameters = parameters;
}
swaggerAutogen(outputFile, endpointsFiles, doc).then(({ data }) => {
// Remove Authorization parameters from arguments.
for (const path of Object.keys(data.paths)) {
if (data.paths[path].hasOwnProperty("get")) {
let parameters = data.paths[path].get?.parameters || [];
parameters = parameters.filter((arg) => arg.name !== "Authorization");
data.paths[path].get.parameters = parameters;
}

if (data.paths[path].hasOwnProperty('delete')) {
let parameters = data.paths[path].delete?.parameters || [];
parameters = parameters.filter((arg) => arg.name !== 'Authorization');
data.paths[path].delete.parameters = parameters;
}
if (data.paths[path].hasOwnProperty("post")) {
let parameters = data.paths[path].post?.parameters || [];
parameters = parameters.filter((arg) => arg.name !== "Authorization");
data.paths[path].post.parameters = parameters;
}

const openApiSpec = {
...data,
servers: [{
url: "/api"
}]
if (data.paths[path].hasOwnProperty("delete")) {
let parameters = data.paths[path].delete?.parameters || [];
parameters = parameters.filter((arg) => arg.name !== "Authorization");
data.paths[path].delete.parameters = parameters;
}
fs.writeFileSync(outputFile, JSON.stringify(openApiSpec, null, 2), { encoding: 'utf-8', flag: 'w' });
console.log(`Swagger-autogen: \x1b[32mPatched servers.url βœ”\x1b[0m`)
})
}

const openApiSpec = {
...data,
servers: [
{
url: "/api",
},
],
};
fs.writeFileSync(outputFile, JSON.stringify(openApiSpec, null, 2), {
encoding: "utf-8",
flag: "w",
});
console.log(`Swagger-autogen: \x1b[32mPatched servers.url βœ”\x1b[0m`);
});
56 changes: 56 additions & 0 deletions server/swagger/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2370,6 +2370,62 @@
}
}
}
},
"/v1/users": {
"get": {
"tags": [
"User Management"
],
"description": "List all users",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"example": {
"users": [
{
"id": 1,
"username": "john_doe",
"role": "admin"
},
{
"id": 2,
"username": "jane_smith",
"role": "default"
}
]
}
}
}
}
},
"401": {
"description": "Instance is not in Multi-User mode. Permission denied."
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InvalidAPIKey"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/InvalidAPIKey"
}
}
}
},
"500": {
"description": "Internal Server Error"
}
}
}
}
},
"components": {
Expand Down