Browse Source

用户新增接口

master
ma-zhongxu 10 months ago
parent
commit
6923af70ad
  1. 2
      frontend/src/components/Sidebar/index.jsx
  2. 12
      frontend/src/pages/WorkspaceSettings/Members/AddMemberModal/index.jsx
  3. 8
      frontend/src/pages/WorkspaceSettings/Members/index.jsx
  4. 4
      frontend/src/utils/constants.js
  5. 43
      server/endpoints/admin.js
  6. 1
      server/models/deptUsers.js
  7. 2
      server/models/user.js
  8. 3
      server/models/workspace.js

2
frontend/src/components/Sidebar/index.jsx

@ -62,7 +62,7 @@ export default function Sidebar() {
<div className="relative h-[calc(100%-60px)] flex flex-col w-full justify-between pt-[10px] overflow-y-scroll no-scroll"> <div className="relative h-[calc(100%-60px)] flex flex-col w-full justify-between pt-[10px] overflow-y-scroll no-scroll">
<div className="flex flex-col gap-y-2 pb-[60px] overflow-y-scroll no-scroll"> <div className="flex flex-col gap-y-2 pb-[60px] overflow-y-scroll no-scroll">
<div className="flex gap-x-2 items-center justify-between"> <div className="flex gap-x-2 items-center justify-between">
{(!user || user?.role !== "default") && (
{(!user || user?.role == "admin") && (
<button <button
onClick={showNewWsModal} onClick={showNewWsModal}
className="light:bg-[#C2E7FE] light:hover:bg-[#7CD4FD] flex flex-grow w-[75%] h-[44px] gap-x-2 py-[5px] px-2.5 mb-2 bg-white rounded-[8px] text-sidebar justify-center items-center hover:bg-opacity-80 transition-all duration-300" className="light:bg-[#C2E7FE] light:hover:bg-[#7CD4FD] flex flex-grow w-[75%] h-[44px] gap-x-2 py-[5px] px-2.5 mb-2 bg-white rounded-[8px] text-sidebar justify-center items-center hover:bg-opacity-80 transition-all duration-300"

12
frontend/src/pages/WorkspaceSettings/Members/AddMemberModal/index.jsx

@ -64,12 +64,12 @@ export default function AddMemberModal({ closeModal, workspace, users }) {
<div className="w-full max-w-2xl bg-theme-bg-secondary rounded-lg shadow border-2 border-theme-modal-border overflow-hidden"> <div className="w-full max-w-2xl bg-theme-bg-secondary rounded-lg shadow border-2 border-theme-modal-border overflow-hidden">
<div className="flex items-center justify-between p-6 border-b rounded-t border-theme-modal-border"> <div className="flex items-center justify-between p-6 border-b rounded-t border-theme-modal-border">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
<h3 className="text-base font-semibold text-white">Users</h3>
<h3 className="text-base font-semibold text-white">用户</h3>
<div className="relative"> <div className="relative">
<input <input
onChange={handleSearch} onChange={handleSearch}
className="w-[400px] h-[34px] bg-theme-bg-primary rounded-[100px] text-white placeholder:text-theme-text-secondary text-sm px-10 pl-10" className="w-[400px] h-[34px] bg-theme-bg-primary rounded-[100px] text-white placeholder:text-theme-text-secondary text-sm px-10 pl-10"
placeholder="Search for a user"
placeholder="搜索用户"
/> />
<MagnifyingGlass <MagnifyingGlass
size={16} size={16}
@ -113,7 +113,7 @@ export default function AddMemberModal({ closeModal, workspace, users }) {
)) ))
) : ( ) : (
<p className="text-theme-text-secondary text-sm font-medium "> <p className="text-theme-text-secondary text-sm font-medium ">
No users found
未找到用户
</p> </p>
)} )}
</table> </table>
@ -135,7 +135,7 @@ export default function AddMemberModal({ closeModal, workspace, users }) {
<div className="w-2 h-2 bg-white rounded-[2px]" /> <div className="w-2 h-2 bg-white rounded-[2px]" />
)} )}
</div> </div>
<p className="text-white text-sm font-medium">Select All</p>
<p className="text-white text-sm font-medium">全选</p>
</button> </button>
{selectedUsers.length > 0 && ( {selectedUsers.length > 0 && (
<button <button
@ -144,7 +144,7 @@ export default function AddMemberModal({ closeModal, workspace, users }) {
className="flex items-center gap-x-2 ml-2" className="flex items-center gap-x-2 ml-2"
> >
<p className="text-theme-text-secondary text-sm font-medium hover:text-theme-text-primary"> <p className="text-theme-text-secondary text-sm font-medium hover:text-theme-text-primary">
Unselect
反选
</p> </p>
</button> </button>
)} )}
@ -153,7 +153,7 @@ export default function AddMemberModal({ closeModal, workspace, users }) {
type="submit" type="submit"
className="transition-all duration-300 text-xs px-2 py-1 font-semibold rounded-lg bg-primary-button hover:bg-secondary border-2 border-transparent hover:border-primary-button hover:text-white h-[32px] w-[68px] -mr-8 whitespace-nowrap shadow-[0_4px_14px_rgba(0,0,0,0.25)]" className="transition-all duration-300 text-xs px-2 py-1 font-semibold rounded-lg bg-primary-button hover:bg-secondary border-2 border-transparent hover:border-primary-button hover:text-white h-[32px] w-[68px] -mr-8 whitespace-nowrap shadow-[0_4px_14px_rgba(0,0,0,0.25)]"
> >
Save
保存
</button> </button>
</div> </div>
</form> </form>

8
frontend/src/pages/WorkspaceSettings/Members/index.jsx

@ -51,13 +51,13 @@ export default function Members({ workspace }) {
<thead className="text-white text-opacity-80 text-xs leading-[18px] font-bold uppercase border-white/10 border-b border-opacity-60"> <thead className="text-white text-opacity-80 text-xs leading-[18px] font-bold uppercase border-white/10 border-b border-opacity-60">
<tr> <tr>
<th scope="col" className="px-6 py-3 rounded-tl-lg"> <th scope="col" className="px-6 py-3 rounded-tl-lg">
Username
用户名
</th> </th>
<th scope="col" className="px-6 py-3"> <th scope="col" className="px-6 py-3">
Role
角色
</th> </th>
<th scope="col" className="px-6 py-3"> <th scope="col" className="px-6 py-3">
Date Added
添加时间
</th> </th>
<th scope="col" className="px-6 py-3 rounded-tr-lg"> <th scope="col" className="px-6 py-3 rounded-tr-lg">
{" "} {" "}
@ -78,7 +78,7 @@ export default function Members({ workspace }) {
)} )}
</tbody> </tbody>
</table> </table>
<CTAButton onClick={openModal}>Manage Users</CTAButton>
<CTAButton onClick={openModal}>用户管理</CTAButton>
<ModalWrapper isOpen={isOpen}> <ModalWrapper isOpen={isOpen}>
<AddMemberModal <AddMemberModal
closeModal={closeModal} closeModal={closeModal}

4
frontend/src/utils/constants.js

@ -1,5 +1,5 @@
// export const API_BASE = import.meta.env.VITE_API_BASE || "/api";
export const API_BASE = 'http://172.16.2.31:3001/api'
export const API_BASE = import.meta.env.VITE_API_BASE || "/api";
// export const API_BASE = 'http://172.16.2.31:3001/api'
export const ONBOARDING_SURVEY_URL = "https://onboarding.anythingllm.com"; export const ONBOARDING_SURVEY_URL = "https://onboarding.anythingllm.com";
export const AUTH_USER = "anythingllm_user"; export const AUTH_USER = "anythingllm_user";

43
server/endpoints/admin.js

@ -5,9 +5,11 @@ const { Invite } = require("../models/invite");
const { SystemSettings } = require("../models/systemSettings"); const { SystemSettings } = require("../models/systemSettings");
const { Telemetry } = require("../models/telemetry"); const { Telemetry } = require("../models/telemetry");
const { User } = require("../models/user"); const { User } = require("../models/user");
const { DeptUsers } = require("../models/deptUsers");
const { DocumentVectors } = require("../models/vectors"); const { DocumentVectors } = require("../models/vectors");
const { Workspace } = require("../models/workspace"); const { Workspace } = require("../models/workspace");
const { WorkspaceChats } = require("../models/workspaceChats"); const { WorkspaceChats } = require("../models/workspaceChats");
const prisma = require("../utils/prisma");
const { const {
getVectorDbClass, getVectorDbClass,
getEmbeddingEngineSelection, getEmbeddingEngineSelection,
@ -80,6 +82,47 @@ function adminEndpoints(app) {
} }
); );
app.post(
"/admin/users/add/:deptId",
[validatedRequest, strictMultiUserRoleValid([ROLES.admin, ROLES.manager])],
async (request, response) => {
try {
const currUser = await userFromSession(request, response);
const { deptId } = request.params;
const newUserParams = reqBody(request);
const roleValidation = validRoleSelection(currUser, newUserParams);
if (!roleValidation.valid) {
return response.status(400).json({ error: roleValidation.error });
}
await prisma.$transaction(async () => {
try {
const { user: newUser, error } = await User.create(newUserParams);
console.log("newUser", newUser);
const deptUser = await DeptUsers.create({
data: { userId: newUser.id, deptId: deptId },
});
await EventLogs.logEvent(
"user_created",
{ userName: newUser.username, createdBy: currUser.username },
currUser.id
);
response.status(200).json({ user: newUser, error });
} catch (error) {
throw new Error(`Transaction failed: ${error.message}`);
}
});
} catch (e) {
console.error("Error creating user and dept user association:", e);
response.status(500).json({ error: "Internal Server Error" });
}
}
);
// app.post( // app.post(
// "/admin/users/new", // "/admin/users/new",
// [validatedRequest, strictMultiUserRoleValid([ROLES.admin, ROLES.manager])], // [validatedRequest, strictMultiUserRoleValid([ROLES.admin, ROLES.manager])],

1
server/models/deptUsers.js

@ -43,6 +43,7 @@ const DeptUsers = {
* @returns {Promise<{ deptUser: DeptUser | null, error: string | null }>} * @returns {Promise<{ deptUser: DeptUser | null, error: string | null }>}
*/ */
create: async function (data) { create: async function (data) {
console.log("55555555555555555", data);
try { try {
const validatedData = {}; const validatedData = {};
for (const key of this.writable) { for (const key of this.writable) {

2
server/models/user.js

@ -101,6 +101,8 @@ const User = {
this.validations.dailyMessageLimit(dailyMessageLimit), this.validations.dailyMessageLimit(dailyMessageLimit),
}, },
}); });
// const vue = this.filterFields(user);
console.log("6666666666",user);
return { user: this.filterFields(user), error: null }; return { user: this.filterFields(user), error: null };
} catch (error) { } catch (error) {
console.error("FAILED TO CREATE USER.", error.message); console.error("FAILED TO CREATE USER.", error.message);

3
server/models/workspace.js

@ -318,7 +318,8 @@ const Workspace = {
limit = null, limit = null,
orderBy = null orderBy = null
) { ) {
if ([ROLES.admin, ROLES.manager].includes(user.role))
// if ([ROLES.admin, ROLES.manager].includes(user.role))
if ([ROLES.admin].includes(user.role))
return await this.where(clause, limit, orderBy); return await this.where(clause, limit, orderBy);
try { try {

Loading…
Cancel
Save