feat: 负责人下钻视图+项目负责人编辑管理+企微授权自助绑定
- 任务/项目负责人 union scope:任务中心分组视图、工作台项目进度卡、收录验证列 - 项目负责人可管理自己项目:编辑/删除项目、编辑任务、分配负责人、推送、项目内建任务;堵死转移归属/越权新建/任务迁移 - 只读依赖放开给已登录:inspect_feishu、wecom_list_internal_contacts - 企微 OAuth 自助绑定:/api/wecom-bind(state 签名校验+登录态一致性+归属冲突检查),未绑定 banner 增加入口 - 工作台项目进度卡与未绑定 banner 排版修复 - 修 user-auth 判空分支被 Turbopack dev 折叠删除导致匿名请求 500
This commit is contained in:
@@ -26,12 +26,21 @@ export async function isTaskOwner(
|
||||
db: DatabaseClient,
|
||||
taskId: string,
|
||||
wecomUserId: string,
|
||||
options?: { strict?: boolean },
|
||||
) {
|
||||
const id = String(taskId ?? "").trim();
|
||||
if (!id || !wecomUserId) return false;
|
||||
const row = await db
|
||||
.prepare("SELECT id FROM tasks WHERE id = ? AND owner_userid = ? LIMIT 1")
|
||||
.bind(id, wecomUserId)
|
||||
.prepare(
|
||||
options?.strict
|
||||
? "SELECT id FROM tasks WHERE id = ? AND owner_userid = ? LIMIT 1"
|
||||
: `SELECT t.id
|
||||
FROM tasks t
|
||||
LEFT JOIN projects p ON p.id = t.project_id
|
||||
WHERE t.id = ? AND (t.owner_userid = ? OR p.owner_userid = ?)
|
||||
LIMIT 1`,
|
||||
)
|
||||
.bind(...(options?.strict ? [id, wecomUserId] : [id, wecomUserId, wecomUserId]))
|
||||
.first<{ id: string }>();
|
||||
return Boolean(row);
|
||||
}
|
||||
@@ -48,7 +57,42 @@ export async function isDistributionOwner(
|
||||
`SELECT d.id
|
||||
FROM distributions d
|
||||
JOIN tasks t ON t.id = d.task_id
|
||||
WHERE d.id = ? AND t.owner_userid = ?
|
||||
LEFT JOIN projects p ON p.id = t.project_id
|
||||
WHERE d.id = ? AND (t.owner_userid = ? OR p.owner_userid = ?)
|
||||
LIMIT 1`,
|
||||
)
|
||||
.bind(id, wecomUserId, wecomUserId)
|
||||
.first<{ id: string }>();
|
||||
return Boolean(row);
|
||||
}
|
||||
|
||||
export async function isProjectOwner(
|
||||
db: DatabaseClient,
|
||||
projectId: string,
|
||||
wecomUserId: string,
|
||||
) {
|
||||
const id = String(projectId ?? "").trim();
|
||||
if (!id || !wecomUserId) return false;
|
||||
const row = await db
|
||||
.prepare("SELECT id FROM projects WHERE id = ? AND owner_userid = ? LIMIT 1")
|
||||
.bind(id, wecomUserId)
|
||||
.first<{ id: string }>();
|
||||
return Boolean(row);
|
||||
}
|
||||
|
||||
export async function isTaskProjectOwner(
|
||||
db: DatabaseClient,
|
||||
taskId: string,
|
||||
wecomUserId: string,
|
||||
) {
|
||||
const id = String(taskId ?? "").trim();
|
||||
if (!id || !wecomUserId) return false;
|
||||
const row = await db
|
||||
.prepare(
|
||||
`SELECT t.id
|
||||
FROM tasks t
|
||||
JOIN projects p ON p.id = t.project_id
|
||||
WHERE t.id = ? AND p.owner_userid = ?
|
||||
LIMIT 1`,
|
||||
)
|
||||
.bind(id, wecomUserId)
|
||||
@@ -59,3 +103,7 @@ export async function isDistributionOwner(
|
||||
export function ownerForbidden() {
|
||||
return Response.json({ error: "该任务未分配给您,无权操作" }, { status: 403 });
|
||||
}
|
||||
|
||||
export function projectForbidden() {
|
||||
return Response.json({ error: "您不是该项目负责人,无权操作" }, { status: 403 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user