Browse Source

dept

master
ma-zhongxu 10 months ago
parent
commit
49c520f08a
  1. 1
      .gitignore
  2. 63
      .idea/inspectionProfiles/Project_Default.xml
  3. 160
      server/endpoints/dept.js
  4. 2
      server/index.js
  5. 238
      server/models/dept.js
  6. 12
      server/prisma/migrations/20250222043007_init/migration.sql
  7. 10
      server/prisma/migrations/20250224030233_init_test_table/migration.sql
  8. 98
      server/prisma/schema.prisma
  9. 5
      server/utils/files/index.js

1
.gitignore

@ -1,6 +1,7 @@
v-env v-env
.env .env
!.env.example !.env.example
.idea
node_modules node_modules
__pycache__ __pycache__

63
.idea/inspectionProfiles/Project_Default.xml

@ -1,6 +1,69 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="AliAccessStaticViaInstance" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliArrayNamingShouldHaveBracket" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliControlFlowStatementWithoutBraces" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliDeprecation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliEqualsAvoidNull" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliLongLiteralsEndingWithLowercaseL" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliMissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliWrapperTypeEquality" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAbstractClassShouldStartWithAbstractNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAbstractMethodOrInterfaceMethodMustUseJavadoc" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidApacheBeanUtilsCopy" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidCallStaticSimpleDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidCommentBehindStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidComplexCondition" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidConcurrentCompetitionRandom" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidDoubleOrFloatEqualCompare" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidManuallyCreateThread" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidMissUseOfMathRandom" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidNegationOperator" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidNewDateGetTime" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidPatternCompileInMethod" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidReturnInFinally" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidStartWithDollarAndUnderLineNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidUseTimer" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaBigDecimalAvoidDoubleConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaBooleanPropertyShouldNotStartWithIs" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassCastExceptionWithSubListToArrayList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassCastExceptionWithToArray" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassMustHaveAuthor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaCollectionInitShouldAssignCapacity" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaCommentsMustBeJavadocFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaConcurrentExceptionWithModifyOriginSubList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaCountDownShouldInFinally" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaDontModifyInForeachCircle" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaExceptionClassShouldEndWithException" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaIbatisMethodQueryForList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaLockShouldWithTryFinally" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaLowerCamelCaseVariableNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaMethodReturnWrapperType" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaMethodTooLong" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPackageNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPojoMustOverrideToString" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPojoMustUsePrimitiveField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPojoNoDefaultValue" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaRemoveCommentedCode" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaServiceOrDaoClassShouldEndWithImpl" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaSneakyThrowsWithoutExceptionType" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaStringConcat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaSwitchExpression" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaSwitchStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaTestClassShouldEndWithTestNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaThreadLocalShouldRemove" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaThreadPoolCreation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaThreadShouldSetName" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaTransactionMustHaveRollback" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUndefineMagicConstant" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="true" level="WARNING" enabled_by_default="true" />
</profile> </profile>
</component> </component>

160
server/endpoints/dept.js

@ -0,0 +1,160 @@
const { Dept } = require("../models/dept");
const { validatedRequest } = require("../utils/middleware/validatedRequest");
const {
strictMultiUserRoleValid,
ROLES
} = require("../utils/middleware/multiUserProtected");
function deptEndpoints(app) {
if (!app) return;
app.get(
"/dept/list",
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])],
async (_request, response) => {
try {
const depts = await Dept.where();
response.status(200).json({ depts });
} catch (e) {
console.error(e);
response.sendStatus(500).end();
}
}
);
app.post("/dept/add",
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])],
async (request, response) => {
try {
const dept = request.body; // 获取请求体中的部门数据
// 检查部门名称是否唯一
const isUnique = await Dept.checkDeptNameUnique(dept);
if (!isUnique) {
return response.status(400).json({
success: false,
message: `新增部门 '${dept.deptName}' 失败,部门名称已存在`,
});
};
// 按照deptId查询父部门
const parentDept = await Dept.get({ deptId: dept.parentId });
dept.ancestors = parentDept.dept.ancestors + ',' + dept.parentId;
// 插入部门数据
const insertedDept = await Dept.insertDept(dept);
// 返回成功响应
response.status(200).json({
success: true,
data: insertedDept,
});
} catch (error) {
// 处理错误
console.error("添加部门失败:", error);
response.status(500).json({
success: false,
message: "添加部门失败,服务器内部错误",
});
}
});
app.post("/dept/edit",
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])],
async (request, response) => {
try {
const dept = request.body; // 获取请求体中的部门数据
// 检查部门名称是否唯一
const isUnique = await Dept.checkDeptNameUnique(dept);
if (!isUnique) {
return response.status(400).json({
success: false,
message: `修改部门 '${dept.deptName}' 失败,部门名称已存在`,
});
}
// 检查上级部门是否是自己
if (dept.parentId === dept.deptId) {
return response.status(400).json({
success: false,
message: `修改部门 '${dept.deptName}' 失败,上级部门不能是自己`,
});
}
// 检查部门是否包含未停用的子部门
if (dept.status === 1) {
const normalChildrenCount = await Dept.selectNormalChildrenDeptById(dept.deptId);
if (normalChildrenCount > 0) {
return response.status(400).json({
success: false,
message: "该部门包含未停用的子部门!",
});
}
}
// 更新部门数据
const updatedDept = await Dept.update(dept);
// 返回成功响应
response.status(200).json({
success: true,
data: updatedDept,
});
} catch (error) {
// 处理错误
console.error("修改部门失败:", error);
response.status(500).json({
success: false,
message: "修改部门失败,服务器内部错误",
});
}
});
// 删除部门的接口
app.delete("/dept/:deptId",
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])],
async (request, response) => {
try {
const deptId = parseInt(request.params.deptId); // 获取部门 ID
// 检查部门是否有子部门
const hasChild = await Dept.hasChildByDeptId(deptId);
if (hasChild) {
return response.status(400).json({
success: false,
message: "存在下级部门,不允许删除",
});
}
// 检查部门是否存在用户
const hasUser = await Dept.checkDeptExistUser(deptId);
if (hasUser) {
return response.status(400).json({
success: false,
message: "部门存在用户,不允许删除",
});
}
// // 检查部门数据权限
// const hasDataScope = await Dept.checkDeptDataScope(deptId);
// if (!hasDataScope) {
// return response.status(403).json({
// success: false,
// message: "无权限删除该部门",
// });
// }
// 删除部门
const deletedDept = await Dept.deleteDeptById(deptId);
// 返回成功响应
response.status(200).json({
success: true,
data: deletedDept,
});
} catch (error) {
// 处理错误
console.error("删除部门失败:", error);
response.status(500).json({
success: false,
message: "删除部门失败,服务器内部错误",
});
}
});
}
module.exports = { deptEndpoints };

2
server/index.js

@ -27,6 +27,7 @@ const { experimentalEndpoints } = require("./endpoints/experimental");
const { browserExtensionEndpoints } = require("./endpoints/browserExtension"); const { browserExtensionEndpoints } = require("./endpoints/browserExtension");
const { communityHubEndpoints } = require("./endpoints/communityHub"); const { communityHubEndpoints } = require("./endpoints/communityHub");
const { agentFlowEndpoints } = require("./endpoints/agentFlows"); const { agentFlowEndpoints } = require("./endpoints/agentFlows");
const { deptEndpoints } = require("./endpoints/dept");
const app = express(); const app = express();
const apiRouter = express.Router(); const apiRouter = express.Router();
const FILE_LIMIT = "3GB"; const FILE_LIMIT = "3GB";
@ -51,6 +52,7 @@ app.use("/api", apiRouter);
systemEndpoints(apiRouter); systemEndpoints(apiRouter);
extensionEndpoints(apiRouter); extensionEndpoints(apiRouter);
workspaceEndpoints(apiRouter); workspaceEndpoints(apiRouter);
deptEndpoints(apiRouter);
workspaceThreadEndpoints(apiRouter); workspaceThreadEndpoints(apiRouter);
chatEndpoints(apiRouter); chatEndpoints(apiRouter);
adminEndpoints(apiRouter); adminEndpoints(apiRouter);

238
server/models/dept.js

@ -0,0 +1,238 @@
const prisma = require("../utils/prisma");
/**
* @typedef {Object} Dept
* @property {number} deptId
* @property {number} parentId
* @property {string} ancestors
* @property {string} deptName
* @property {number} orderNum
* @property {number} status
* @property {number} delFlag
* @property {Date} createdAt
* @property {Date} lastUpdatedAt
*/
const Dept = {
writable: [
'parentId', 'ancestors', 'deptName', 'orderNum', 'status', 'delFlag'
],
validations: {
deptName: (newValue = '') => {
if (typeof newValue !== 'string' || newValue.length > 255) {
throw new Error('Dept name must be a string and cannot be longer than 255 characters');
}
return newValue;
},
orderNum: (newValue = 0) => {
const num = Number(newValue);
if (isNaN(num)) {
throw new Error('Order num must be a number');
}
return num;
},
status: (newValue = 0) => {
const status = Number(newValue);
if (isNaN(status) || status < 0 || status > 1) {
throw new Error('Status must be a number between 0 and 1');
}
return status;
},
delFlag: (newValue = 0) => {
const flag = Number(newValue);
if (isNaN(flag) || flag < 0 || flag > 1) {
throw new Error('Del flag must be a number between 0 and 1');
}
return flag;
}
},
castColumnValue: function (key, value) {
switch (key) {
case 'status':
case 'delFlag':
return Number(value);
default:
return value;
}
},
create: async function ({ parentId, ancestors, deptName, orderNum, status = 0, delFlag = 0 }) {
try {
const validatedDeptName = this.validations.deptName(deptName);
const validatedOrderNum = this.validations.orderNum(orderNum);
const validatedStatus = this.validations.status(status);
const validatedDelFlag = this.validations.delFlag(delFlag);
const dept = await prisma.dept.create({
data: {
parentId,
ancestors,
deptName: validatedDeptName,
orderNum: validatedOrderNum,
status: validatedStatus,
delFlag: validatedDelFlag,
createdAt: new Date(),
lastUpdatedAt: new Date()
}
});
return { dept, error: null };
} catch (error) {
console.error('FAILED TO CREATE DEPT.', error.message);
return { dept: null, error: error.message };
}
},
// 插入部门数据
insertDept: async function (dept) {
try {
const insertedDept = await prisma.dept.create({
data: {
deptName: dept.deptName,
parentId: dept.parentId || null,
ancestors: dept.ancestors || null,
orderNum: dept.orderNum || 0,
status: dept.status || 0,
delFlag: dept.delFlag || 0,
createdAt: new Date(),
lastUpdatedAt: new Date(),
},
});
return insertedDept;
} catch (error) {
console.error("插入部门数据失败:", error);
throw error;
}
},
update: async function (deptId, updates = {}) {
try {
if (!deptId) throw new Error('No dept id provided for update');
const currentDept = await prisma.dept.findUnique({ where: { deptId } });
if (!currentDept) throw new Error('Dept not found');
Object.entries(updates).forEach(([key, value]) => {
if (this.writable.includes(key)) {
if (Object.prototype.hasOwnProperty.call(this.validations, key)) {
updates[key] = this.validations[key](this.castColumnValue(key, value));
} else {
updates[key] = this.castColumnValue(key, value);
}
}
});
updates.lastUpdatedAt = new Date();
const updatedDept = await prisma.dept.update({ where: { deptId }, data: updates });
return { success: true, error: null, dept: updatedDept };
} catch (error) {
console.error(error.message);
return { success: false, error: error.message, dept: null };
}
},
get: async function (clause = {}) {
try {
const dept = await prisma.dept.findFirst({ where: clause, select: {
deptId: true, parentId: true, ancestors: true, deptName: true, orderNum: true, status: true, delFlag: true, createdAt: true, lastUpdatedAt: true
} });
return dept ? { dept } : null;
} catch (error) {
console.error(error.message);
return null;
}
},
delete: async function (clause = {}) {
try {
const affectedRows = await prisma.dept.deleteMany({ where: clause });
return affectedRows > 0;
} catch (error) {
console.error(error.message);
return false;
}
},
where: async function (clause = {}, limit = null) {
try {
const depts = await prisma.dept.findMany({
where: clause,
take: limit !== null ? limit : undefined,
select: {
deptId: true, parentId: true, ancestors: true, deptName: true, orderNum: true, status: true, delFlag: true, createdAt: true, lastUpdatedAt: true
}
});
return depts;
} catch (error) {
console.error(error.message);
return [];
}
},
checkDeptNameUnique: async function (dept){
try {
const existingDept = await prisma.dept.findFirst({
where: {
deptName: dept.deptName, // 根据部门名称查询
parentId: dept.parentId, // 排除父id
},
});
// 如果查询到记录,说明部门名称已存在
return !existingDept;
} catch (error) {
console.error('检查部门名称唯一性失败:', error);
throw error;
}
},
// 检查部门是否包含未停用的子部门
selectNormalChildrenDeptById: async function (deptId) {
try {
// 查询所有祖先部门中包含当前部门的未停用部门
const childrenDepts = await prisma.$queryRaw`
SELECT COUNT(*) as count
FROM sys_dept
WHERE status = 0
AND del_flag = '0'
AND FIND_IN_SET(${deptId}, ancestors)
`;
// 返回未停用的子部门数量
return childrenDepts[0].count;
} catch (error) {
console.error("查询子部门失败:", error);
throw error;
}
},
// 检查部门是否有子部门
hasChildByDeptId: async function (deptId) {
try {
const children = await prisma.dept.findMany({
where: {
parentId: deptId, // 查询当前部门的子部门
delFlag: 0,
},
});
// 如果有子部门,返回 true
return children.length > 0;
} catch (error) {
console.error("检查子部门失败:", error);
throw error;
}
},
// 检查部门是否存在用户
checkDeptExistUser: async function (deptId) {
try {
const users = await prisma.user.findMany({
where: {
deptId: deptId, // 查询当前部门的用户
},
});
// 如果存在用户,返回 true
return users.length > 0;
} catch (error) {
console.error("检查部门用户失败:", error);
throw error;
}
},
};
module.exports = { Dept };

12
server/prisma/migrations/20250222043007_init/migration.sql

@ -0,0 +1,12 @@
-- CreateTable
CREATE TABLE "dept" (
"deptId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"parentId" INTEGER,
"ancestors" TEXT,
"deptName" TEXT,
"orderNum" INTEGER,
"status" INTEGER NOT NULL DEFAULT 0,
"delFlag" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"lastUpdatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

10
server/prisma/migrations/20250224030233_init_test_table/migration.sql

@ -0,0 +1,10 @@
-- CreateTable
CREATE TABLE "dept_users" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"deptId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"createdAt" DATETIME DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "dept_users_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT "dept_users_deptId_fkey" FOREIGN KEY ("deptId") REFERENCES "dept" ("deptId") ON DELETE CASCADE ON UPDATE NO ACTION
);

98
server/prisma/schema.prisma

@ -2,14 +2,6 @@ generator client {
provider = "prisma-client-js" provider = "prisma-client-js"
} }
// Uncomment the following lines and comment out the SQLite datasource block above to use PostgreSQL
// Make sure to set the correct DATABASE_URL in your .env file
// After swapping run `yarn prisma:setup` from the root directory to migrate the database
//
// datasource db {
// provider = "postgresql"
// url = env("DATABASE_URL")
// }
datasource db { datasource db {
provider = "sqlite" provider = "sqlite"
url = "file:../storage/anythingllm.db" url = "file:../storage/anythingllm.db"
@ -30,12 +22,12 @@ model workspace_documents {
docpath String docpath String
workspaceId Int workspaceId Int
metadata String? metadata String?
pinned Boolean? @default(false)
watched Boolean? @default(false)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
workspace workspaces @relation(fields: [workspaceId], references: [id])
pinned Boolean? @default(false)
watched Boolean? @default(false)
document_sync_queues document_sync_queues? document_sync_queues document_sync_queues?
workspace workspaces @relation(fields: [workspaceId], references: [id])
} }
model invites { model invites {
@ -43,10 +35,10 @@ model invites {
code String @unique code String @unique
status String @default("pending") status String @default("pending")
claimedBy Int? claimedBy Int?
workspaceIds String?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
createdBy Int createdBy Int
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
workspaceIds String?
} }
model system_settings { model system_settings {
@ -61,24 +53,25 @@ model users {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
username String? @unique username String? @unique
password String password String
pfpFilename String?
role String @default("default") role String @default("default")
suspended Int @default(0) suspended Int @default(0)
seen_recovery_codes Boolean? @default(false)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
pfpFilename String?
seen_recovery_codes Boolean? @default(false)
dailyMessageLimit Int? dailyMessageLimit Int?
workspace_chats workspace_chats[]
workspace_users workspace_users[]
embed_configs embed_configs[]
browser_extension_api_keys browser_extension_api_keys[]
dept_users dept_users[]
embed_chats embed_chats[] embed_chats embed_chats[]
threads workspace_threads[]
recovery_codes recovery_codes[]
embed_configs embed_configs[]
password_reset_tokens password_reset_tokens[] password_reset_tokens password_reset_tokens[]
workspace_agent_invocations workspace_agent_invocations[]
recovery_codes recovery_codes[]
slash_command_presets slash_command_presets[] slash_command_presets slash_command_presets[]
browser_extension_api_keys browser_extension_api_keys[]
temporary_auth_tokens temporary_auth_tokens[] temporary_auth_tokens temporary_auth_tokens[]
workspace_agent_invocations workspace_agent_invocations[]
workspace_chats workspace_chats[]
threads workspace_threads[]
workspace_users workspace_users[]
} }
model recovery_codes { model recovery_codes {
@ -129,21 +122,21 @@ model workspaces {
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
openAiPrompt String? openAiPrompt String?
similarityThreshold Float? @default(0.25) similarityThreshold Float? @default(0.25)
chatProvider String?
chatModel String? chatModel String?
topN Int? @default(4) topN Int? @default(4)
chatMode String? @default("chat") chatMode String? @default("chat")
pfpFilename String? pfpFilename String?
agentProvider String?
chatProvider String?
agentModel String? agentModel String?
agentProvider String?
queryRefusalResponse String? queryRefusalResponse String?
vectorSearchMode String? @default("default") vectorSearchMode String? @default("default")
workspace_users workspace_users[]
embed_configs embed_configs[]
workspace_agent_invocations workspace_agent_invocations[]
documents workspace_documents[] documents workspace_documents[]
workspace_suggested_messages workspace_suggested_messages[] workspace_suggested_messages workspace_suggested_messages[]
embed_configs embed_configs[]
threads workspace_threads[] threads workspace_threads[]
workspace_agent_invocations workspace_agent_invocations[]
workspace_users workspace_users[]
} }
model workspace_threads { model workspace_threads {
@ -154,8 +147,8 @@ model workspace_threads {
user_id Int? user_id Int?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
workspace workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade)
user users? @relation(fields: [user_id], references: [id], onDelete: Cascade) user users? @relation(fields: [user_id], references: [id], onDelete: Cascade)
workspace workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade)
@@index([workspace_id]) @@index([workspace_id])
@@index([user_id]) @@index([user_id])
@ -180,26 +173,26 @@ model workspace_chats {
response String response String
include Boolean @default(true) include Boolean @default(true)
user_id Int? user_id Int?
thread_id Int? // No relation to prevent whole table migration
api_session_id String? // String identifier for only the dev API to parition chats in any mode.
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
thread_id Int?
feedbackScore Boolean? feedbackScore Boolean?
users users? @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
api_session_id String?
users users? @relation(fields: [user_id], references: [id], onDelete: Cascade)
} }
model workspace_agent_invocations { model workspace_agent_invocations {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
uuid String @unique uuid String @unique
prompt String // Contains agent invocation to parse + option additional text for seed.
prompt String
closed Boolean @default(false) closed Boolean @default(false)
user_id Int? user_id Int?
thread_id Int? // No relation to prevent whole table migration
thread_id Int?
workspace_id Int workspace_id Int
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
user users? @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
workspace workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
workspace workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade)
user users? @relation(fields: [user_id], references: [id], onDelete: Cascade)
@@index([uuid]) @@index([uuid])
} }
@ -210,8 +203,8 @@ model workspace_users {
workspace_id Int workspace_id Int
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
workspaces workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
users users @relation(fields: [user_id], references: [id], onDelete: Cascade)
workspaces workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade)
} }
model cache_data { model cache_data {
@ -240,9 +233,9 @@ model embed_configs {
createdBy Int? createdBy Int?
usersId Int? usersId Int?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
workspace workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade)
embed_chats embed_chats[] embed_chats embed_chats[]
users users? @relation(fields: [usersId], references: [id]) users users? @relation(fields: [usersId], references: [id])
workspace workspaces @relation(fields: [workspace_id], references: [id], onDelete: Cascade)
} }
model embed_chats { model embed_chats {
@ -255,8 +248,8 @@ model embed_chats {
embed_id Int embed_id Int
usersId Int? usersId Int?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
embed_config embed_configs @relation(fields: [embed_id], references: [id], onDelete: Cascade)
users users? @relation(fields: [usersId], references: [id]) users users? @relation(fields: [usersId], references: [id])
embed_config embed_configs @relation(fields: [embed_id], references: [id], onDelete: Cascade)
} }
model event_logs { model event_logs {
@ -274,7 +267,7 @@ model slash_command_presets {
command String command String
prompt String prompt String
description String description String
uid Int @default(0) // 0 is null user
uid Int @default(0)
userId Int? userId Int?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now()) lastUpdatedAt DateTime @default(now())
@ -285,13 +278,13 @@ model slash_command_presets {
model document_sync_queues { model document_sync_queues {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
staleAfterMs Int @default(604800000) // 7 days
staleAfterMs Int @default(604800000)
nextSyncAt DateTime nextSyncAt DateTime
createdAt DateTime @default(now()) createdAt DateTime @default(now())
lastSyncedAt DateTime @default(now()) lastSyncedAt DateTime @default(now())
workspaceDocId Int @unique workspaceDocId Int @unique
workspaceDoc workspace_documents? @relation(fields: [workspaceDocId], references: [id], onDelete: Cascade)
runs document_sync_executions[] runs document_sync_executions[]
workspaceDoc workspace_documents @relation(fields: [workspaceDocId], references: [id], onDelete: Cascade)
} }
model document_sync_executions { model document_sync_executions {
@ -325,3 +318,26 @@ model temporary_auth_tokens {
@@index([token]) @@index([token])
@@index([userId]) @@index([userId])
} }
model dept {
deptId Int @id @default(autoincrement())
parentId Int?
ancestors String?
deptName String?
orderNum Int?
status Int @default(0)
delFlag Int @default(0)
createdAt DateTime @default(now())
lastUpdatedAt DateTime @default(now())
dept_users dept_users[]
}
model dept_users {
id Int @id @default(autoincrement())
deptId Int
userId Int
createdAt DateTime? @default(now())
updatedAt DateTime? @default(now()) @updatedAt
user users @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
dept dept @relation(fields: [deptId], references: [deptId], onDelete: Cascade, onUpdate: NoAction)
}

5
server/utils/files/index.js

@ -32,8 +32,9 @@ async function viewLocalFiles() {
type: "folder", type: "folder",
items: [], items: [],
}; };
console.log("111111111111111111111111111111111111111111111111111111111111111111111111111111111");
for (const file of fs.readdirSync(documentsPath)) { for (const file of fs.readdirSync(documentsPath)) {
console.log("file:", file);
if (path.extname(file) === ".md") continue; if (path.extname(file) === ".md") continue;
const folderPath = path.resolve(documentsPath, file); const folderPath = path.resolve(documentsPath, file);
const isFolder = fs.lstatSync(folderPath).isDirectory(); const isFolder = fs.lstatSync(folderPath).isDirectory();
@ -45,11 +46,11 @@ async function viewLocalFiles() {
}; };
const subfiles = fs.readdirSync(folderPath); const subfiles = fs.readdirSync(folderPath);
const filenames = {}; const filenames = {};
for (const subfile of subfiles) { for (const subfile of subfiles) {
if (path.extname(subfile) !== ".json") continue; if (path.extname(subfile) !== ".json") continue;
const filePath = path.join(folderPath, subfile); const filePath = path.join(folderPath, subfile);
const rawData = fs.readFileSync(filePath, "utf8"); const rawData = fs.readFileSync(filePath, "utf8");
console.log("rawData:", rawData);
const cachefilename = `${file}/${subfile}`; const cachefilename = `${file}/${subfile}`;
const { pageContent, ...metadata } = JSON.parse(rawData); const { pageContent, ...metadata } = JSON.parse(rawData);
subdocs.items.push({ subdocs.items.push({

Loading…
Cancel
Save