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: '反馈详情加载失败', }); } }, ); }