305 lines
7.5 KiB
JavaScript
305 lines
7.5 KiB
JavaScript
export function attachPortalAccountFeedbackRoutes({
|
|
app,
|
|
jsonBody,
|
|
userAuthReady = Promise.resolve(),
|
|
getUserAuth = () => null,
|
|
getLegacyAuth = () => null,
|
|
getSubscriptionService = () => null,
|
|
getFeedbackService = () => null,
|
|
userToken,
|
|
legacySessionToken,
|
|
clearUserLoginCookies,
|
|
resolveSkillRuntimeForClient = async () => null,
|
|
resolveAgentCodeRunForClient = async () => null,
|
|
logger = console,
|
|
} = {}) {
|
|
if (
|
|
!app ||
|
|
typeof jsonBody !== 'function' ||
|
|
typeof userToken !== 'function' ||
|
|
typeof legacySessionToken !== 'function' ||
|
|
typeof clearUserLoginCookies !== 'function'
|
|
) {
|
|
throw new Error(
|
|
'attachPortalAccountFeedbackRoutes requires route dependencies',
|
|
);
|
|
}
|
|
|
|
app.get('/auth/me', async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
if (!userAuth) {
|
|
return res.status(503).json({
|
|
message: '未启用用户系统',
|
|
});
|
|
}
|
|
const me = await userAuth.getMe(userToken(req));
|
|
if (!me) {
|
|
return res.status(401).json({
|
|
message: '未登录',
|
|
});
|
|
}
|
|
const subscriptionService =
|
|
getSubscriptionService();
|
|
const [
|
|
paths,
|
|
capabilityState,
|
|
subscription,
|
|
skillRuntime,
|
|
agentCodeRun,
|
|
] = await Promise.all([
|
|
userAuth.listPathGrants(me.id),
|
|
userAuth.resolveUserCapabilities(
|
|
await userAuth.getUserById(me.id),
|
|
),
|
|
subscriptionService
|
|
? subscriptionService.getActiveSubscription(
|
|
me.id,
|
|
)
|
|
: null,
|
|
resolveSkillRuntimeForClient(),
|
|
resolveAgentCodeRunForClient(me.id),
|
|
]);
|
|
return res.json({
|
|
user: {
|
|
...me,
|
|
subscription,
|
|
},
|
|
paths,
|
|
capabilities: capabilityState.capabilities,
|
|
grantedSkills:
|
|
capabilityState.grantedSkills ?? [],
|
|
unrestricted: capabilityState.unrestricted,
|
|
skillRuntime,
|
|
agentCodeRun,
|
|
});
|
|
});
|
|
|
|
app.post('/auth/logout', async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
const legacyAuth = getLegacyAuth();
|
|
if (userAuth) {
|
|
await userAuth.revoke(userToken(req));
|
|
}
|
|
if (legacyAuth) {
|
|
legacyAuth.revoke(legacySessionToken(req));
|
|
}
|
|
if (userAuth || legacyAuth) {
|
|
clearUserLoginCookies(res, req);
|
|
}
|
|
res.status(204).end();
|
|
});
|
|
|
|
app.get('/auth/usage', async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
if (!userAuth) {
|
|
return res.status(503).json({
|
|
message: '未启用用户系统',
|
|
});
|
|
}
|
|
const me = await userAuth.getMe(userToken(req));
|
|
if (!me) {
|
|
return res.status(401).json({
|
|
message: '未登录',
|
|
});
|
|
}
|
|
const records = await userAuth.listUsageRecords({
|
|
userId: me.id,
|
|
limit: 30,
|
|
});
|
|
res.json({ records });
|
|
});
|
|
|
|
app.post(
|
|
'/auth/feedback',
|
|
jsonBody,
|
|
async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
const feedbackService = getFeedbackService();
|
|
if (!userAuth || !feedbackService) {
|
|
return res.status(503).json({
|
|
message: '反馈服务未启用',
|
|
});
|
|
}
|
|
const me = await userAuth.getMe(userToken(req));
|
|
if (!me) {
|
|
return res.status(401).json({
|
|
message: '未登录',
|
|
});
|
|
}
|
|
try {
|
|
const result = await feedbackService.submit(
|
|
me.id,
|
|
{
|
|
type: req.body?.type,
|
|
title: req.body?.title,
|
|
description: req.body?.description,
|
|
contact: req.body?.contact,
|
|
images: req.body?.images,
|
|
context: req.body?.context,
|
|
},
|
|
);
|
|
res.status(201).json({
|
|
feedback: result,
|
|
});
|
|
} catch (error) {
|
|
const code =
|
|
error &&
|
|
typeof error === 'object' &&
|
|
'code' in error
|
|
? String(error.code)
|
|
: '';
|
|
if (code === 'invalid_input') {
|
|
return res.status(400).json({
|
|
message:
|
|
error instanceof Error
|
|
? error.message
|
|
: '提交内容无效',
|
|
});
|
|
}
|
|
logger.warn(
|
|
'Submit feedback failed:',
|
|
error instanceof Error
|
|
? error.message
|
|
: error,
|
|
);
|
|
return res.status(500).json({
|
|
message: '反馈提交失败,请稍后重试',
|
|
});
|
|
}
|
|
},
|
|
);
|
|
|
|
app.get('/auth/feedback', async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
const feedbackService = getFeedbackService();
|
|
if (!userAuth || !feedbackService) {
|
|
return res.status(503).json({
|
|
message: '反馈服务未启用',
|
|
});
|
|
}
|
|
const me = await userAuth.getMe(userToken(req));
|
|
if (!me) {
|
|
return res.status(401).json({
|
|
message: '未登录',
|
|
});
|
|
}
|
|
const limit = Math.min(
|
|
Math.max(Number(req.query?.limit) || 20, 1),
|
|
50,
|
|
);
|
|
const items = await feedbackService.listForUser(
|
|
me.id,
|
|
{ limit },
|
|
);
|
|
res.json({ items });
|
|
});
|
|
|
|
app.get(
|
|
'/auth/feedback/board',
|
|
async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
const feedbackService = getFeedbackService();
|
|
if (!userAuth || !feedbackService) {
|
|
return res.status(503).json({
|
|
message: '反馈服务未启用',
|
|
});
|
|
}
|
|
const me = await userAuth.getMe(userToken(req));
|
|
if (!me) {
|
|
return res.status(401).json({
|
|
message: '未登录',
|
|
});
|
|
}
|
|
const page = Math.max(
|
|
Number(req.query?.page) || 1,
|
|
1,
|
|
);
|
|
const limit = Math.min(
|
|
Math.max(
|
|
Number(req.query?.limit) || 10,
|
|
1,
|
|
),
|
|
10,
|
|
);
|
|
try {
|
|
const result =
|
|
await feedbackService.listAll({
|
|
page,
|
|
limit,
|
|
});
|
|
res.json(result);
|
|
} catch (error) {
|
|
logger.warn(
|
|
'List feedback board failed:',
|
|
error instanceof Error
|
|
? error.message
|
|
: error,
|
|
);
|
|
return res.status(500).json({
|
|
message: '反馈列表加载失败',
|
|
});
|
|
}
|
|
},
|
|
);
|
|
|
|
app.get(
|
|
'/auth/feedback/:feedbackId',
|
|
async (req, res) => {
|
|
await userAuthReady;
|
|
const userAuth = getUserAuth();
|
|
const feedbackService = getFeedbackService();
|
|
if (!userAuth || !feedbackService) {
|
|
return res.status(503).json({
|
|
message: '反馈服务未启用',
|
|
});
|
|
}
|
|
const me = await userAuth.getMe(userToken(req));
|
|
if (!me) {
|
|
return res.status(401).json({
|
|
message: '未登录',
|
|
});
|
|
}
|
|
try {
|
|
const item = await feedbackService.getById(
|
|
req.params.feedbackId,
|
|
me.id,
|
|
);
|
|
res.json({
|
|
item,
|
|
isMine: item.userId === me.id,
|
|
});
|
|
} catch (error) {
|
|
const code =
|
|
error &&
|
|
typeof error === 'object' &&
|
|
'code' in error
|
|
? String(error.code)
|
|
: '';
|
|
if (code === 'feedback_not_found') {
|
|
return res.status(404).json({
|
|
message:
|
|
error instanceof Error
|
|
? error.message
|
|
: '反馈不存在',
|
|
});
|
|
}
|
|
logger.warn(
|
|
'Get feedback detail failed:',
|
|
error instanceof Error
|
|
? error.message
|
|
: error,
|
|
);
|
|
return res.status(500).json({
|
|
message: '反馈详情加载失败',
|
|
});
|
|
}
|
|
},
|
|
);
|
|
}
|