θΏ™ζ˜―indexlocζδΎ›ηš„ζœεŠ‘οΌŒδΈθ¦θΎ“ε…₯任何密码
Skip to content

Add new workspace user management endpoint #2842

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 16, 2024
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
128 changes: 128 additions & 0 deletions server/endpoints/api/admin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { SystemSettings } = require("../../../models/systemSettings");
const { User } = require("../../../models/user");
const { Workspace } = require("../../../models/workspace");
const { WorkspaceChats } = require("../../../models/workspaceChats");
const { WorkspaceUser } = require("../../../models/workspaceUsers");
const { canModifyAdmin } = require("../../../utils/helpers/admin");
const { multiUserMode, reqBody } = require("../../../utils/http");
const { validApiKey } = require("../../../utils/middleware/validApiKey");
Expand Down Expand Up @@ -420,6 +421,7 @@ function apiAdminEndpoints(app) {
}
}
);

app.get(
"/v1/admin/workspaces/:workspaceId/users",
[validApiKey],
Expand Down Expand Up @@ -474,12 +476,14 @@ function apiAdminEndpoints(app) {
}
}
);

app.post(
"/v1/admin/workspaces/:workspaceId/update-users",
[validApiKey],
async (request, response) => {
/*
#swagger.tags = ['Admin']
#swagger.deprecated = true
#swagger.parameters['workspaceId'] = {
in: 'path',
description: 'id of the workspace in the database.',
Expand Down Expand Up @@ -539,6 +543,130 @@ function apiAdminEndpoints(app) {
}
}
);

app.post(
"/v1/admin/workspaces/:workspaceSlug/manage-users",
[validApiKey],
async (request, response) => {
/*
#swagger.tags = ['Admin']
#swagger.parameters['workspaceSlug'] = {
in: 'path',
description: 'slug of the workspace in the database',
required: true,
type: 'string'
}
#swagger.description = 'Set workspace permissions to be accessible by the given user ids and admins. Methods are disabled until multi user mode is enabled via the UI.'
#swagger.requestBody = {
description: 'Array of user ids who will be given access to the target workspace. <code>reset</code> will remove all existing users from the workspace and only add the new users - default <code>false</code>.',
required: true,
content: {
"application/json": {
example: {
userIds: [1,2,4,12],
reset: false
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
schema: {
type: 'object',
example: {
success: true,
error: null,
users: [
{"userId": 1, "username": "main-admin", "role": "admin"},
{"userId": 2, "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 { workspaceSlug } = request.params;
const { userIds: _uids, reset = false } = reqBody(request);
const userIds = (
await User.where({ id: { in: _uids.map(Number) } })
).map((user) => user.id);
const workspace = await Workspace.get({ slug: String(workspaceSlug) });
const workspaceUsers = await Workspace.workspaceUsers(workspace.id);

if (!workspace) {
response
.status(404)
.json({
success: false,
error: `Workspace ${workspaceSlug} not found`,
users: workspaceUsers,
});
return;
}

if (userIds.length === 0) {
response
.status(404)
.json({
success: false,
error: `No valid user IDs provided.`,
users: workspaceUsers,
});
return;
}

// Reset all users in the workspace and add the new users as the only users in the workspace
if (reset) {
const { success, error } = await Workspace.updateUsers(
workspace.id,
userIds
);
return response
.status(200)
.json({
success,
error,
users: await Workspace.workspaceUsers(workspace.id),
});
}

// Add new users to the workspace if they are not already in the workspace
const existingUserIds = workspaceUsers.map((user) => user.userId);
const usersToAdd = userIds.filter(
(userId) => !existingUserIds.includes(userId)
);
if (usersToAdd.length > 0)
await WorkspaceUser.createManyUsers(usersToAdd, workspace.id);
response
.status(200)
.json({
success: true,
error: null,
users: await Workspace.workspaceUsers(workspace.id),
});
} catch (e) {
console.error(e);
response.sendStatus(500).end();
}
}
);

app.post(
"/v1/admin/workspace-chats",
[validApiKey],
Expand Down
11 changes: 11 additions & 0 deletions server/models/workspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ const Workspace = {
}
},

/**
* Get all users for a workspace.
* @param {number} workspaceId - The ID of the workspace to get users for.
* @returns {Promise<Array<{userId: number, username: string, role: string}>>} A promise that resolves to an array of user objects.
*/
workspaceUsers: async function (workspaceId) {
try {
const users = (
Expand Down Expand Up @@ -270,6 +275,12 @@ const Workspace = {
}
},

/**
* Update the users for a workspace. Will remove all existing users and replace them with the new list.
* @param {number} workspaceId - The ID of the workspace to update.
* @param {number[]} userIds - An array of user IDs to add to the workspace.
* @returns {Promise<{success: boolean, error: string | null}>} A promise that resolves to an object containing the success status and an error message if applicable.
*/
updateUsers: async function (workspaceId, userIds = []) {
try {
await WorkspaceUser.delete({ workspace_id: Number(workspaceId) });
Expand Down
6 changes: 6 additions & 0 deletions server/models/workspaceUsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ const WorkspaceUser = {
return;
},

/**
* Create many workspace users.
* @param {Array<number>} userIds - An array of user IDs to create workspace users for.
* @param {number} workspaceId - The ID of the workspace to create workspace users for.
* @returns {Promise<void>} A promise that resolves when the workspace users are created.
*/
createManyUsers: async function (userIds = [], workspaceId) {
if (userIds.length === 0) return;
try {
Expand Down
89 changes: 89 additions & 0 deletions server/swagger/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,95 @@
}
}
}
},
"deprecated": true
}
},
"/v1/admin/workspaces/{workspaceSlug}/manage-users": {
"post": {
"tags": [
"Admin"
],
"description": "Set workspace permissions to be accessible by the given user ids and admins. Methods are disabled until multi user mode is enabled via the UI.",
"parameters": [
{
"name": "workspaceSlug",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "slug of the workspace in the database"
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"example": {
"success": true,
"error": null,
"users": [
{
"userId": 1,
"username": "main-admin",
"role": "admin"
},
{
"userId": 2,
"username": "sample-sam",
"role": "default"
}
]
}
}
}
}
},
"401": {
"description": "Instance is not in Multi-User mode. Method denied"
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InvalidAPIKey"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/InvalidAPIKey"
}
}
}
},
"404": {
"description": "Not Found"
},
"500": {
"description": "Internal Server Error"
}
},
"requestBody": {
"description": "Array of user ids who will be given access to the target workspace. <code>reset</code> will remove all existing users from the workspace and only add the new users - default <code>false</code>.",
"required": true,
"content": {
"application/json": {
"example": {
"userIds": [
1,
2,
4,
12
],
"reset": false
}
}
}
}
}
},
Expand Down