@drodil/backstage-plugin-qeta-backend 3.54.0 → 3.55.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/database/DatabaseQetaStore.cjs.js +1 -0
- package/dist/database/DatabaseQetaStore.cjs.js.map +1 -1
- package/dist/database/stores/CollectionsStore.cjs.js +262 -23
- package/dist/database/stores/CollectionsStore.cjs.js.map +1 -1
- package/dist/database/stores/PostsStore.cjs.js +6 -0
- package/dist/database/stores/PostsStore.cjs.js.map +1 -1
- package/dist/service/routes/collections.cjs.js +6 -0
- package/dist/service/routes/collections.cjs.js.map +1 -1
- package/dist/service/routes/helpers.cjs.js +35 -4
- package/dist/service/routes/helpers.cjs.js.map +1 -1
- package/dist/service/routes/posts.cjs.js +23 -13
- package/dist/service/routes/posts.cjs.js.map +1 -1
- package/dist/service/routes/routeUtil.cjs.js +33 -0
- package/dist/service/routes/routeUtil.cjs.js.map +1 -1
- package/dist/service/routes/statistics.cjs.js +109 -71
- package/dist/service/routes/statistics.cjs.js.map +1 -1
- package/dist/service/routes/suggestions.cjs.js +34 -20
- package/dist/service/routes/suggestions.cjs.js.map +1 -1
- package/dist/service/types.cjs.js +4 -1
- package/dist/service/types.cjs.js.map +1 -1
- package/dist/service/util.cjs.js +74 -18
- package/dist/service/util.cjs.js.map +1 -1
- package/migrations/20260109_automatic_collections.js +59 -0
- package/migrations/20260110_optimize_indexes.js +43 -0
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statistics.cjs.js","sources":["../../../src/service/routes/statistics.ts"],"sourcesContent":["import { Router } from 'express';\nimport { stringDateTime } from '../util';\nimport {\n Statistic,\n StatisticResponse,\n StatisticsOptions,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { RouteOptions } from '../types';\n\nexport const statisticRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr } = options;\n\n const getSummary = async (user_ref?: string) => {\n const results = await Promise.all([\n database.getCount('posts', { author: user_ref, type: 'question' }),\n database.getCount('answers', { author: user_ref }),\n user_ref\n ? database.getTotalViews(user_ref)\n : database.getCount('post_views'),\n database.getCount('comments', { author: user_ref }),\n database.getCount('post_votes', { author: user_ref }),\n database.getCount('answer_votes', { author: user_ref }),\n database.getCount('posts', { author: user_ref, type: 'article' }),\n !user_ref ? database.getUsersCount() : undefined,\n !user_ref ? database.getCount('tags') : undefined,\n database.getCount('posts', { author: user_ref, type: 'link' }),\n ]);\n return {\n totalQuestions: results[0],\n totalAnswers: results[1],\n totalViews: results[2],\n totalComments: results[3],\n totalVotes: results[4] + results[5],\n totalArticles: results[6],\n totalUsers: results[7],\n totalTags: results[8],\n totalLinks: results[9],\n };\n };\n\n router.get('/statistics/user/impact', async (request, response) => {\n const userRef = await permissionMgr.getUsername(request);\n const userImpact = await database.getTotalViews(userRef, undefined, true);\n const userImpactWeek = await database.getTotalViews(userRef, 7, true);\n return response\n .status(200)\n .json({ impact: userImpact, lastWeekImpact: userImpactWeek });\n });\n\n router.get('/statistics/global', async (_req, response) => {\n const globalStats = await database.getGlobalStats();\n let summary = await getSummary();\n if (!summary) {\n summary = {\n totalAnswers: 0,\n totalArticles: 0,\n totalLinks: 0,\n totalComments: 0,\n totalQuestions: 0,\n totalViews: 0,\n totalVotes: 0,\n totalTags: 0,\n totalUsers: 0,\n };\n }\n let todayStatsAdded = false;\n const statistics = globalStats.map(g => {\n const d = new Date(g.date);\n if (d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary,\n };\n });\n\n if (!todayStatsAdded) {\n statistics.push({ date: new Date(), ...summary });\n }\n\n return response.status(200).json({ statistics, summary });\n });\n\n router.get('/statistics/user/:userRef(*)', async (req, response) => {\n const userRef = req.params.userRef;\n const userStats = await database.getUserStats(userRef);\n let summary = await database.getUser(userRef);\n let todayStatsAdded = false;\n const statistics = userStats.map(g => {\n const d = new Date(g.date);\n if (!summary || d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary,\n };\n });\n\n if (!todayStatsAdded) {\n if (!summary) {\n summary = {\n userRef: userRef,\n totalViews: 0,\n totalQuestions: 0,\n totalAnswers: 0,\n totalComments: 0,\n totalVotes: 0,\n totalArticles: 0,\n totalFollowers: 0,\n totalLinks: 0,\n reputation: 0,\n answerScore: 0,\n postScore: 0,\n correctAnswers: 0,\n };\n }\n\n if (userStats.length === 0) {\n statistics.push({ date: new Date(), ...summary });\n }\n }\n\n return response.status(200).json({ statistics, summary });\n });\n\n // GET /statistics/posts/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/posts/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostUpvotedQuestions: Statistic[] =\n await database.getMostUpvotedPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedQuestions = await database.getMostUpvotedPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedQuestions.length === 1\n ? 0\n : mostUpvotedQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedAnswers: Statistic[] =\n await database.getMostUpvotedAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedAnswers = await database.getMostUpvotedAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedAnswers.length === 1 ? 0 : mostUpvotedAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-correct-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-correct-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedCorrectAnswers: Statistic[] =\n await database.getMostUpvotedCorrectAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedCorrectAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedCorrectAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedCorrectAnswers =\n await database.getMostUpvotedCorrectAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedCorrectAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedCorrectAnswers.length === 1\n ? 0\n : mostUpvotedCorrectAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/posts/most-questions?period=x&limit=x\n router.get('/statistics/posts/most-questions', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostQuestions: Statistic[] = await database.getTotalPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostQuestions.length === 1 ? 0 : mostQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n\n // GET /statistics/answers/most-answers?period=x&limit=x\n router.get('/statistics/answers/most-answers', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostAnswers: Statistic[] = await database.getTotalAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostAnswers.length === 1 ? 0 : mostAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n};\n"],"names":["stringDateTime"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"statistics.cjs.js","sources":["../../../src/service/routes/statistics.ts"],"sourcesContent":["import { Router } from 'express';\nimport { stringDateTime } from '../util';\nimport { getCachedData } from './routeUtil';\nimport {\n Statistic,\n StatisticResponse,\n StatisticsOptions,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { RouteOptions } from '../types';\n\nexport const statisticRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr } = options;\n\n const getSummary = async (user_ref?: string) => {\n const results = await Promise.all([\n database.getCount('posts', { author: user_ref, type: 'question' }),\n database.getCount('answers', { author: user_ref }),\n user_ref\n ? database.getTotalViews(user_ref)\n : database.getCount('post_views'),\n database.getCount('comments', { author: user_ref }),\n database.getCount('post_votes', { author: user_ref }),\n database.getCount('answer_votes', { author: user_ref }),\n database.getCount('posts', { author: user_ref, type: 'article' }),\n !user_ref ? database.getUsersCount() : undefined,\n !user_ref ? database.getCount('tags') : undefined,\n database.getCount('posts', { author: user_ref, type: 'link' }),\n ]);\n return {\n totalQuestions: results[0],\n totalAnswers: results[1],\n totalViews: results[2],\n totalComments: results[3],\n totalVotes: results[4] + results[5],\n totalArticles: results[6],\n totalUsers: results[7],\n totalTags: results[8],\n totalLinks: results[9],\n };\n };\n\n router.get('/statistics/user/impact', async (request, response) => {\n const userRef = await permissionMgr.getUsername(request);\n const key = `qeta:statistics:impact:${userRef}`;\n const ttl = 300 * 1000;\n\n const impact = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n const userImpact = await database.getTotalViews(\n userRef,\n undefined,\n true,\n );\n const userImpactWeek = await database.getTotalViews(userRef, 7, true);\n return { impact: userImpact, lastWeekImpact: userImpactWeek };\n },\n options.logger,\n );\n\n return response.status(200).json(impact);\n });\n\n router.get('/statistics/global', async (_req, response) => {\n const key = 'qeta:statistics:global';\n const ttl = 3600 * 1000;\n\n const data = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n const globalStats = await database.getGlobalStats();\n let summary = await getSummary();\n if (!summary) {\n summary = {\n totalAnswers: 0,\n totalArticles: 0,\n totalLinks: 0,\n totalComments: 0,\n totalQuestions: 0,\n totalViews: 0,\n totalVotes: 0,\n totalTags: 0,\n totalUsers: 0,\n };\n }\n let todayStatsAdded = false;\n const statistics = globalStats.map(g => {\n const d = new Date(g.date);\n if (d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary!,\n };\n });\n\n if (!todayStatsAdded) {\n statistics.push({ date: new Date(), ...summary! });\n }\n return { statistics, summary };\n },\n options.logger,\n );\n return response.json(data);\n });\n\n router.get('/statistics/user/:userRef(*)', async (req, response) => {\n const userRef = req.params.userRef;\n const key = `qeta:statistics:user:${userRef}`;\n const ttl = 3600 * 1000;\n\n const data = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n const userStats = await database.getUserStats(userRef);\n let summary = await database.getUser(userRef);\n let todayStatsAdded = false;\n const statistics = userStats.map(g => {\n const d = new Date(g.date);\n if (!summary || d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary,\n };\n });\n\n if (!todayStatsAdded) {\n if (!summary) {\n summary = {\n userRef: userRef,\n totalViews: 0,\n totalQuestions: 0,\n totalAnswers: 0,\n totalComments: 0,\n totalVotes: 0,\n totalArticles: 0,\n totalFollowers: 0,\n totalLinks: 0,\n reputation: 0,\n answerScore: 0,\n postScore: 0,\n correctAnswers: 0,\n };\n }\n\n if (userStats.length === 0) {\n statistics.push({ date: new Date(), ...summary });\n }\n }\n return { statistics, summary };\n },\n options.logger,\n );\n\n return response.status(200).json(data);\n });\n\n // GET /statistics/posts/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/posts/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostUpvotedQuestions: Statistic[] =\n await database.getMostUpvotedPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedQuestions = await database.getMostUpvotedPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedQuestions.length === 1\n ? 0\n : mostUpvotedQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedAnswers: Statistic[] =\n await database.getMostUpvotedAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedAnswers = await database.getMostUpvotedAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedAnswers.length === 1 ? 0 : mostUpvotedAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-correct-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-correct-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedCorrectAnswers: Statistic[] =\n await database.getMostUpvotedCorrectAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedCorrectAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedCorrectAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedCorrectAnswers =\n await database.getMostUpvotedCorrectAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedCorrectAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedCorrectAnswers.length === 1\n ? 0\n : mostUpvotedCorrectAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/posts/most-questions?period=x&limit=x\n router.get('/statistics/posts/most-questions', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostQuestions: Statistic[] = await database.getTotalPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostQuestions.length === 1 ? 0 : mostQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n\n // GET /statistics/answers/most-answers?period=x&limit=x\n router.get('/statistics/answers/most-answers', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostAnswers: Statistic[] = await database.getTotalAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostAnswers.length === 1 ? 0 : mostAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n};\n"],"names":["getCachedData","stringDateTime"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var types$1 = require('../types.cjs.js');
|
|
4
|
+
var routeUtil = require('./routeUtil.cjs.js');
|
|
4
5
|
var backstagePluginQetaCommon = require('@drodil/backstage-plugin-qeta-common');
|
|
5
6
|
var Ajv = require('ajv');
|
|
6
7
|
var addFormats = require('ajv-formats');
|
|
@@ -295,25 +296,7 @@ const suggestionRoutes = (router, options) => {
|
|
|
295
296
|
post
|
|
296
297
|
}));
|
|
297
298
|
};
|
|
298
|
-
|
|
299
|
-
const validateQuery = ajv.compile(types$1.SuggestionsQuerySchema);
|
|
300
|
-
if (!validateQuery(request.query)) {
|
|
301
|
-
response.status(400).send({ errors: validateQuery.errors, type: "query" });
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
const username = await permissionMgr.getUsername(request, false);
|
|
305
|
-
let limit = Number(request.query.limit);
|
|
306
|
-
if (isNaN(limit)) {
|
|
307
|
-
limit = 5;
|
|
308
|
-
}
|
|
309
|
-
const filter = await permissionMgr.getAuthorizeConditions(
|
|
310
|
-
request,
|
|
311
|
-
backstagePluginQetaCommon.qetaReadPostPermission
|
|
312
|
-
);
|
|
313
|
-
const canReviewResults = await permissionMgr.authorizeBoolean(request, [
|
|
314
|
-
{ permission: backstagePluginQetaCommon.qetaCreatePostReviewPermission }
|
|
315
|
-
]);
|
|
316
|
-
const canReview = canReviewResults[0] ?? false;
|
|
299
|
+
const getSuggestions = async (username, limit, filter, canReview) => {
|
|
317
300
|
const promises = [
|
|
318
301
|
getNotCorrectQuestions(username, filter),
|
|
319
302
|
getNewTagQuestions(username, filter),
|
|
@@ -338,7 +321,38 @@ const suggestionRoutes = (router, options) => {
|
|
|
338
321
|
if (suggestionsRaw.length < limit) {
|
|
339
322
|
suggestionsRaw.push(...await getRandomPosts(username, limit, filter));
|
|
340
323
|
}
|
|
341
|
-
|
|
324
|
+
return suggestionsRaw.sort(() => 0.5 - Math.random()).slice(0, limit);
|
|
325
|
+
};
|
|
326
|
+
router.get("/suggestions", async (request, response) => {
|
|
327
|
+
const validateQuery = ajv.compile(types$1.SuggestionsQuerySchema);
|
|
328
|
+
if (!validateQuery(request.query)) {
|
|
329
|
+
response.status(400).send({ errors: validateQuery.errors, type: "query" });
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const username = await permissionMgr.getUsername(request, false);
|
|
333
|
+
let limit = Number(request.query.limit);
|
|
334
|
+
if (isNaN(limit)) {
|
|
335
|
+
limit = 5;
|
|
336
|
+
}
|
|
337
|
+
const filter = await permissionMgr.getAuthorizeConditions(
|
|
338
|
+
request,
|
|
339
|
+
backstagePluginQetaCommon.qetaReadPostPermission
|
|
340
|
+
);
|
|
341
|
+
const canReviewResults = await permissionMgr.authorizeBoolean(request, [
|
|
342
|
+
{ permission: backstagePluginQetaCommon.qetaCreatePostReviewPermission }
|
|
343
|
+
]);
|
|
344
|
+
const canReview = canReviewResults[0] ?? false;
|
|
345
|
+
const key = `qeta:suggestions:${username}:${limit}`;
|
|
346
|
+
const ttl = 3600 * 1e3;
|
|
347
|
+
const suggestions = await routeUtil.getCachedData(
|
|
348
|
+
options.cache,
|
|
349
|
+
key,
|
|
350
|
+
ttl,
|
|
351
|
+
async () => {
|
|
352
|
+
return await getSuggestions(username, limit, filter, canReview);
|
|
353
|
+
},
|
|
354
|
+
options.logger
|
|
355
|
+
);
|
|
342
356
|
response.json({ suggestions });
|
|
343
357
|
});
|
|
344
358
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggestions.cjs.js","sources":["../../../src/service/routes/suggestions.ts"],"sourcesContent":["import { Router } from 'express';\nimport { RouteOptions, SuggestionsQuerySchema } from '../types';\nimport { QetaFilters } from '../util';\nimport {\n Article,\n DraftPostSuggestion,\n Link,\n NeedsReviewSuggestion,\n NewArticleSuggestion,\n NewLinkSuggestion,\n NewQuestionSuggestion,\n NoCorrectAnswerSuggestion,\n qetaCreatePostReviewPermission,\n qetaReadPostPermission,\n Question,\n RandomPostSuggestion,\n Suggestion,\n} from '@drodil/backstage-plugin-qeta-common';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { PostOptions } from '../../database/QetaStore';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const suggestionRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr, config } = options;\n\n const postsOlderThan = config.getOptional<HumanDuration>(\n 'qeta.contentHealth.postsOlderThan',\n ) ?? { months: 6 };\n const reviewThresholdMs = durationToMilliseconds(postsOlderThan);\n\n const includeNothingOptions: PostOptions = {\n includeVotes: false,\n includeTags: false,\n includeComments: false,\n includeEntities: false,\n includeAnswers: false,\n includeAttachments: false,\n };\n\n const getFromDate = (days: number = 7) => {\n const date = new Date(Date.now() - 1000 * 60 * 60 * 24 * days);\n return date.toISOString().split('T')[0];\n };\n\n const getNotCorrectQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NoCorrectAnswerSuggestion[]> => {\n const questions = await database.getPosts(\n username,\n {\n author: username,\n hasAnswers: true,\n noCorrectAnswer: true,\n type: 'question',\n },\n filter,\n includeNothingOptions,\n );\n\n return questions.posts.map(question => ({\n id: `noq_${question.id}`,\n type: 'noCorrectAnswer',\n question: question as Question,\n }));\n };\n\n const getNewTagQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewEntityQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewTagArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewEntityArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewUserQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getUsersDraftPosts = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<DraftPostSuggestion[]> => {\n const draftPosts = await database.getPosts(\n username,\n {\n status: 'draft',\n author: username,\n },\n filter,\n includeNothingOptions,\n );\n\n return draftPosts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'draftPost',\n post,\n }));\n };\n\n const getNewUserArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewTagLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `q_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewEntityLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewUserLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getPostsNeedingReview = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NeedsReviewSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { reviewNeeded: true, includeHealth: true, limit: 5 },\n filter,\n { ...includeNothingOptions, reviewThresholdMs },\n );\n return posts.posts.map(post => ({\n id: `r_${post.id}`,\n type: 'needsReview',\n post,\n }));\n };\n\n const getRandomPosts = async (\n username: string,\n limit: number,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<RandomPostSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { random: true, limit },\n filter,\n includeNothingOptions,\n );\n return posts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'randomPost',\n post,\n }));\n };\n\n router.get('/suggestions', async (request, response) => {\n const validateQuery = ajv.compile(SuggestionsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n const username = await permissionMgr.getUsername(request, false);\n let limit = Number(request.query.limit);\n if (isNaN(limit)) {\n limit = 5;\n }\n\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadPostPermission,\n );\n\n // Check if user has review permissions\n const canReviewResults = await permissionMgr.authorizeBoolean(request, [\n { permission: qetaCreatePostReviewPermission },\n ]);\n const canReview = canReviewResults[0] ?? false;\n\n const promises: Promise<Suggestion[]>[] = [\n getNotCorrectQuestions(username, filter),\n getNewTagQuestions(username, filter),\n getNewTagArticles(username, filter),\n getNewTagLinks(username, filter),\n getNewEntityQuestions(username, filter),\n getNewEntityArticles(username, filter),\n getNewEntityLinks(username, filter),\n getNewUserQuestions(username, filter),\n getNewUserArticles(username, filter),\n getNewUserLinks(username, filter),\n getUsersDraftPosts(username, filter),\n canReview ? getPostsNeedingReview(username, filter) : Promise.resolve([]),\n ];\n\n const raw = await Promise.all(promises);\n\n const suggestionsRaw = raw\n .flat()\n .reduce((acc: Suggestion[], cur: Suggestion) => {\n if (!acc.some(s => s.id === cur.id)) {\n acc.push(cur);\n }\n return acc;\n }, []);\n\n if (suggestionsRaw.length < limit) {\n suggestionsRaw.push(...(await getRandomPosts(username, limit, filter)));\n }\n\n const suggestions = suggestionsRaw\n .sort(() => 0.5 - Math.random())\n .slice(0, limit);\n response.json({ suggestions });\n });\n};\n"],"names":["Ajv","addFormats","durationToMilliseconds","SuggestionsQuerySchema","qetaReadPostPermission","qetaCreatePostReviewPermission"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"suggestions.cjs.js","sources":["../../../src/service/routes/suggestions.ts"],"sourcesContent":["import { Router } from 'express';\nimport { RouteOptions, SuggestionsQuerySchema } from '../types';\nimport { QetaFilters } from '../util';\nimport { getCachedData } from './routeUtil';\nimport {\n Article,\n DraftPostSuggestion,\n Link,\n NeedsReviewSuggestion,\n NewArticleSuggestion,\n NewLinkSuggestion,\n NewQuestionSuggestion,\n NoCorrectAnswerSuggestion,\n qetaCreatePostReviewPermission,\n qetaReadPostPermission,\n Question,\n RandomPostSuggestion,\n Suggestion,\n} from '@drodil/backstage-plugin-qeta-common';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { PostOptions } from '../../database/QetaStore';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const suggestionRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr, config } = options;\n\n const postsOlderThan = config.getOptional<HumanDuration>(\n 'qeta.contentHealth.postsOlderThan',\n ) ?? { months: 6 };\n const reviewThresholdMs = durationToMilliseconds(postsOlderThan);\n\n const includeNothingOptions: PostOptions = {\n includeVotes: false,\n includeTags: false,\n includeComments: false,\n includeEntities: false,\n includeAnswers: false,\n includeAttachments: false,\n };\n\n const getFromDate = (days: number = 7) => {\n const date = new Date(Date.now() - 1000 * 60 * 60 * 24 * days);\n return date.toISOString().split('T')[0];\n };\n\n const getNotCorrectQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NoCorrectAnswerSuggestion[]> => {\n const questions = await database.getPosts(\n username,\n {\n author: username,\n hasAnswers: true,\n noCorrectAnswer: true,\n type: 'question',\n },\n filter,\n includeNothingOptions,\n );\n\n return questions.posts.map(question => ({\n id: `noq_${question.id}`,\n type: 'noCorrectAnswer',\n question: question as Question,\n }));\n };\n\n const getNewTagQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewEntityQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewTagArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewEntityArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewUserQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getUsersDraftPosts = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<DraftPostSuggestion[]> => {\n const draftPosts = await database.getPosts(\n username,\n {\n status: 'draft',\n author: username,\n },\n filter,\n includeNothingOptions,\n );\n\n return draftPosts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'draftPost',\n post,\n }));\n };\n\n const getNewUserArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewTagLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `q_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewEntityLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewUserLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getPostsNeedingReview = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NeedsReviewSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { reviewNeeded: true, includeHealth: true, limit: 5 },\n filter,\n { ...includeNothingOptions, reviewThresholdMs },\n );\n return posts.posts.map(post => ({\n id: `r_${post.id}`,\n type: 'needsReview',\n post,\n }));\n };\n\n const getRandomPosts = async (\n username: string,\n limit: number,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<RandomPostSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { random: true, limit },\n filter,\n includeNothingOptions,\n );\n return posts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'randomPost',\n post,\n }));\n };\n\n const getSuggestions = async (\n username: string,\n limit: number,\n filter?: PermissionCriteria<QetaFilters>,\n canReview?: boolean,\n ): Promise<Suggestion[]> => {\n const promises: Promise<Suggestion[]>[] = [\n getNotCorrectQuestions(username, filter),\n getNewTagQuestions(username, filter),\n getNewTagArticles(username, filter),\n getNewTagLinks(username, filter),\n getNewEntityQuestions(username, filter),\n getNewEntityArticles(username, filter),\n getNewEntityLinks(username, filter),\n getNewUserQuestions(username, filter),\n getNewUserArticles(username, filter),\n getNewUserLinks(username, filter),\n getUsersDraftPosts(username, filter),\n canReview ? getPostsNeedingReview(username, filter) : Promise.resolve([]),\n ];\n\n const raw = await Promise.all(promises);\n\n const suggestionsRaw = raw\n .flat()\n .reduce((acc: Suggestion[], cur: Suggestion) => {\n if (!acc.some(s => s.id === cur.id)) {\n acc.push(cur);\n }\n return acc;\n }, []);\n\n if (suggestionsRaw.length < limit) {\n suggestionsRaw.push(...(await getRandomPosts(username, limit, filter)));\n }\n\n return suggestionsRaw.sort(() => 0.5 - Math.random()).slice(0, limit);\n };\n\n router.get('/suggestions', async (request, response) => {\n const validateQuery = ajv.compile(SuggestionsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n const username = await permissionMgr.getUsername(request, false);\n let limit = Number(request.query.limit);\n if (isNaN(limit)) {\n limit = 5;\n }\n\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadPostPermission,\n );\n\n const canReviewResults = await permissionMgr.authorizeBoolean(request, [\n { permission: qetaCreatePostReviewPermission },\n ]);\n const canReview = canReviewResults[0] ?? false;\n\n const key = `qeta:suggestions:${username}:${limit}`;\n const ttl = 3600 * 1000;\n\n const suggestions = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n return await getSuggestions(username, limit, filter, canReview);\n },\n options.logger,\n );\n\n response.json({ suggestions });\n });\n};\n"],"names":["Ajv","addFormats","durationToMilliseconds","SuggestionsQuerySchema","qetaReadPostPermission","qetaCreatePostReviewPermission","getCachedData"],"mappings":"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"}
|
|
@@ -259,7 +259,10 @@ const CollectionSchema = {
|
|
|
259
259
|
description: { type: "string", nullable: true },
|
|
260
260
|
headerImage: { type: "string", nullable: true },
|
|
261
261
|
images: { type: "array", items: { type: "integer" }, nullable: true },
|
|
262
|
-
created: { type: "string", minLength: 1, nullable: true }
|
|
262
|
+
created: { type: "string", minLength: 1, nullable: true },
|
|
263
|
+
tags: { type: "array", items: { type: "string" }, nullable: true },
|
|
264
|
+
entities: { type: "array", items: { type: "string" }, nullable: true },
|
|
265
|
+
users: { type: "array", items: { type: "string" }, nullable: true }
|
|
263
266
|
},
|
|
264
267
|
required: ["title"],
|
|
265
268
|
additionalProperties: false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs.js","sources":["../../src/service/types.ts"],"sourcesContent":["import { JSONSchemaType } from 'ajv';\nimport { QetaStore } from '../database/QetaStore';\nimport {\n AuditorService,\n AuthService,\n CacheService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport { NotificationService } from '@backstage/plugin-notifications-node';\nimport { NotificationManager } from './NotificationManager';\nimport {\n AIQuery,\n AnswersQuery,\n CollectionsQuery,\n EntitiesQuery,\n PostQuery,\n PostsQuery,\n PostStatus,\n PostType,\n SuggestionsQuery,\n TagsQuery,\n URLMetadataQuery,\n UsersQuery,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { AIHandler } from '@drodil/backstage-plugin-qeta-node';\nimport { PermissionManager } from './PermissionManager.ts';\n\nexport interface RouterOptions {\n database: QetaStore;\n logger: LoggerService;\n config: Config;\n discovery: DiscoveryService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n catalog: CatalogApi;\n auth: AuthService;\n cache?: CacheService;\n permissions?: PermissionsService;\n events?: EventsService;\n signals?: SignalsService;\n notifications?: NotificationService;\n aiHandler?: AIHandler;\n permissionsRegistry?: PermissionsRegistryService;\n auditor?: AuditorService;\n notificationMgr: NotificationManager;\n}\n\nexport interface RouteOptions extends RouterOptions {\n notificationMgr: NotificationManager;\n permissionMgr: PermissionManager;\n}\n\nexport interface PostContent {\n title: string;\n content: string;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n user?: string;\n created?: string;\n headerImage?: string;\n url?: string;\n anonymous?: boolean;\n type: PostType;\n status?: PostStatus;\n}\n\nexport interface TemplateContent {\n title: string;\n description: string;\n questionTitle?: string;\n questionContent?: string;\n tags?: string[];\n entities?: string[];\n}\n\nexport interface CollectionContent {\n title: string;\n description?: string;\n headerImage?: string;\n images?: number[];\n created?: string;\n}\n\nexport interface CollectionPostContent {\n postId: number;\n}\n\nexport interface CollectionRankContent {\n postId: number;\n rank: 'top' | 'bottom' | 'up' | 'down';\n}\n\nexport const CollectionsQuerySchema: JSONSchemaType<CollectionsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n searchQuery: { type: 'string', nullable: true },\n owner: { type: 'string', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'created',\n 'title',\n 'postsCount',\n 'questionsCount',\n 'articlesCount',\n 'linksCount',\n 'followerCount',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n entitiesRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n includePosts: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n tagsRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n fromDate: { type: 'string', nullable: true, format: 'date' },\n toDate: { type: 'string', nullable: true, format: 'date' },\n ids: { type: 'array', items: { type: 'integer' }, nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const PostsQuerySchema: JSONSchemaType<PostsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n author: { type: 'string', nullable: true },\n excludeAuthors: {\n type: 'array',\n items: { type: 'string' },\n nullable: true,\n },\n orderBy: {\n type: 'string',\n enum: [\n 'rank',\n 'views',\n 'title',\n 'trend',\n 'score',\n 'answersCount',\n 'created',\n 'updated',\n ],\n nullable: true,\n },\n collectionId: { type: 'number', nullable: true },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n noCorrectAnswer: { type: 'boolean', nullable: true },\n noAnswers: { type: 'boolean', nullable: true },\n hasAnswers: { type: 'boolean', nullable: true },\n favorite: { type: 'boolean', nullable: true },\n noVotes: { type: 'boolean', nullable: true },\n status: {\n type: 'string',\n enum: ['active', 'draft', 'deleted'],\n nullable: true,\n },\n random: { type: 'boolean', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n entitiesRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n tagsRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n includeAnswers: { type: 'boolean', nullable: true },\n includeVotes: { type: 'boolean', nullable: true },\n includeAttachments: { type: 'boolean', nullable: true },\n includeHealth: { type: 'boolean', nullable: true },\n reviewNeeded: { type: 'boolean', nullable: true },\n obsolete: { type: 'boolean', nullable: true },\n includeTags: { type: 'boolean', nullable: true },\n includeEntities: { type: 'boolean', nullable: true },\n includeTrend: { type: 'boolean', nullable: true },\n includeComments: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n searchQuery: { type: 'string', nullable: true },\n fromDate: { type: 'string', nullable: true, format: 'date' },\n toDate: { type: 'string', nullable: true, format: 'date' },\n type: {\n type: 'string',\n enum: ['question', 'article', 'link'],\n nullable: true,\n },\n ids: { type: 'array', items: { type: 'integer' }, nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const PostQuerySchema: JSONSchemaType<PostQuery> = {\n type: 'object',\n properties: {\n anonymous: { type: 'boolean', nullable: true },\n },\n};\n\nexport const TagsQuerySchema: JSONSchemaType<TagsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'tag',\n 'postsCount',\n 'questionsCount',\n 'articlesCount',\n 'linksCount',\n 'followerCount',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n searchQuery: { type: 'string', nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const UsersQuerySchema: JSONSchemaType<UsersQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'userRef',\n 'totalPosts',\n 'totalQuestions',\n 'totalAnswers',\n 'totalArticles',\n 'totalLinks',\n 'totalViews',\n 'totalVotes',\n 'followerCount',\n 'reputation',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n searchQuery: { type: 'string', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const EntitiesQuerySchema: JSONSchemaType<EntitiesQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'entityRef',\n 'postsCount',\n 'questionsCount',\n 'articlesCount',\n 'linksCount',\n 'followerCount',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n searchQuery: { type: 'string', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const AnswersQuerySchema: JSONSchemaType<AnswersQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n author: { type: 'string', nullable: true },\n orderBy: {\n type: 'string',\n enum: ['score', 'created', 'updated'],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n noCorrectAnswer: { type: 'boolean', nullable: true },\n noVotes: { type: 'boolean', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n entitiesRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n tagsRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n includeVotes: { type: 'boolean', nullable: true },\n includeEntities: { type: 'boolean', nullable: true },\n includeComments: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n searchQuery: { type: 'string', nullable: true },\n fromDate: { type: 'string', nullable: true, format: 'date' },\n toDate: { type: 'string', nullable: true, format: 'date' },\n ids: { type: 'array', items: { type: 'integer' }, nullable: true },\n questionId: { type: 'integer', nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const PostSchema: JSONSchemaType<PostContent> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n content: { type: 'string', minLength: 0 },\n author: { type: 'string', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n images: { type: 'array', items: { type: 'integer' }, nullable: true },\n user: { type: 'string', minLength: 1, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n anonymous: { type: 'boolean', nullable: true },\n headerImage: { type: 'string', nullable: true },\n url: { type: 'string', nullable: true },\n type: { type: 'string', enum: ['question', 'article', 'link'] },\n status: {\n type: 'string',\n enum: ['active', 'draft', 'deleted'],\n nullable: true,\n },\n },\n required: ['title', 'content'],\n additionalProperties: false,\n};\n\nexport const TemplateSchema: JSONSchemaType<TemplateContent> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n description: { type: 'string', minLength: 1 },\n questionTitle: { type: 'string', nullable: true },\n questionContent: { type: 'string', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n },\n required: ['title', 'description'],\n additionalProperties: false,\n};\n\nexport const CollectionSchema: JSONSchemaType<CollectionContent> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n description: { type: 'string', nullable: true },\n headerImage: { type: 'string', nullable: true },\n images: { type: 'array', items: { type: 'integer' }, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n },\n required: ['title'],\n additionalProperties: false,\n};\n\nexport const CollectionPostSchema: JSONSchemaType<CollectionPostContent> = {\n type: 'object',\n properties: {\n postId: { type: 'integer' },\n },\n required: ['postId'],\n additionalProperties: false,\n};\n\nexport const CollectionRankPostSchema: JSONSchemaType<CollectionRankContent> = {\n type: 'object',\n properties: {\n postId: { type: 'integer' },\n rank: { type: 'string', enum: ['top', 'bottom', 'up', 'down'] },\n },\n required: ['postId', 'rank'],\n additionalProperties: false,\n};\n\nexport interface AnswerQuestion {\n answer: string;\n images?: number[];\n user?: string;\n author?: string;\n created?: string;\n anonymous?: boolean;\n}\n\nexport const PostAnswerSchema: JSONSchemaType<AnswerQuestion> = {\n type: 'object',\n properties: {\n answer: { type: 'string', minLength: 1 },\n images: { type: 'array', items: { type: 'integer' }, nullable: true },\n user: { type: 'string', minLength: 1, nullable: true },\n author: { type: 'string', minLength: 1, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n anonymous: { type: 'boolean', nullable: true },\n },\n required: ['answer'],\n additionalProperties: false,\n};\n\nexport interface DeleteMetadata {\n reason?: string;\n permanent?: boolean;\n}\n\nexport const DeleteMetadataSchema: JSONSchemaType<DeleteMetadata> = {\n type: 'object',\n properties: {\n reason: { type: 'string', minLength: 1, nullable: true },\n permanent: { type: 'boolean', nullable: true },\n },\n additionalProperties: false,\n};\n\nexport interface Comment {\n content: string;\n user?: string;\n created?: string;\n}\n\nexport const CommentSchema: JSONSchemaType<Comment> = {\n type: 'object',\n properties: {\n content: { type: 'string', minLength: 1 },\n user: { type: 'string', minLength: 1, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n },\n required: ['content'],\n additionalProperties: false,\n};\n\nexport interface DraftQuestion {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n}\n\nexport const DraftQuestionSchema: JSONSchemaType<DraftQuestion> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n content: { type: 'string', minLength: 1 },\n tags: {\n type: 'array',\n items: { type: 'string' },\n nullable: true,\n },\n entities: {\n type: 'array',\n items: { type: 'string' },\n nullable: true,\n },\n },\n required: ['title', 'content'],\n additionalProperties: false,\n};\n\nexport const AIQuerySchema: JSONSchemaType<AIQuery> = {\n type: 'object',\n properties: {\n regenerate: { type: 'boolean', default: false, nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const SuggestionsQuerySchema: JSONSchemaType<SuggestionsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', minimum: 1, nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport interface File {\n name: string;\n path: string;\n buffer: Buffer;\n mimeType: string;\n ext: string;\n size: number;\n}\n\nexport const URLMetadataSchema: JSONSchemaType<URLMetadataQuery> = {\n type: 'object',\n properties: {\n url: { type: 'string', minLength: 7 }, // http://\n },\n required: ['url'],\n additionalProperties: false,\n};\n\nexport interface PostReviewBody {\n status: 'valid' | 'obsolete';\n comment?: string;\n}\n\nexport const PostReviewBodySchema: JSONSchemaType<PostReviewBody> = {\n type: 'object',\n properties: {\n status: { type: 'string', enum: ['valid', 'obsolete'] },\n comment: { type: 'string', nullable: true },\n },\n required: ['status'],\n additionalProperties: false,\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.cjs.js","sources":["../../src/service/types.ts"],"sourcesContent":["import { JSONSchemaType } from 'ajv';\nimport { QetaStore } from '../database/QetaStore';\nimport {\n AuditorService,\n AuthService,\n CacheService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport { NotificationService } from '@backstage/plugin-notifications-node';\nimport { NotificationManager } from './NotificationManager';\nimport {\n AIQuery,\n AnswersQuery,\n CollectionsQuery,\n EntitiesQuery,\n PostQuery,\n PostsQuery,\n PostStatus,\n PostType,\n SuggestionsQuery,\n TagsQuery,\n URLMetadataQuery,\n UsersQuery,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { AIHandler } from '@drodil/backstage-plugin-qeta-node';\nimport { PermissionManager } from './PermissionManager.ts';\n\nexport interface RouterOptions {\n database: QetaStore;\n logger: LoggerService;\n config: Config;\n discovery: DiscoveryService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n catalog: CatalogApi;\n auth: AuthService;\n cache?: CacheService;\n permissions?: PermissionsService;\n events?: EventsService;\n signals?: SignalsService;\n notifications?: NotificationService;\n aiHandler?: AIHandler;\n permissionsRegistry?: PermissionsRegistryService;\n auditor?: AuditorService;\n notificationMgr: NotificationManager;\n}\n\nexport interface RouteOptions extends RouterOptions {\n notificationMgr: NotificationManager;\n permissionMgr: PermissionManager;\n}\n\nexport interface PostContent {\n title: string;\n content: string;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n user?: string;\n created?: string;\n headerImage?: string;\n url?: string;\n anonymous?: boolean;\n type: PostType;\n status?: PostStatus;\n}\n\nexport interface TemplateContent {\n title: string;\n description: string;\n questionTitle?: string;\n questionContent?: string;\n tags?: string[];\n entities?: string[];\n}\n\nexport interface CollectionContent {\n title: string;\n description?: string;\n headerImage?: string;\n images?: number[];\n created?: string;\n tags?: string[];\n entities?: string[];\n users?: string[];\n}\n\nexport interface CollectionPostContent {\n postId: number;\n}\n\nexport interface CollectionRankContent {\n postId: number;\n rank: 'top' | 'bottom' | 'up' | 'down';\n}\n\nexport const CollectionsQuerySchema: JSONSchemaType<CollectionsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n searchQuery: { type: 'string', nullable: true },\n owner: { type: 'string', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'created',\n 'title',\n 'postsCount',\n 'questionsCount',\n 'articlesCount',\n 'linksCount',\n 'followerCount',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n entitiesRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n includePosts: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n tagsRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n fromDate: { type: 'string', nullable: true, format: 'date' },\n toDate: { type: 'string', nullable: true, format: 'date' },\n ids: { type: 'array', items: { type: 'integer' }, nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const PostsQuerySchema: JSONSchemaType<PostsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n author: { type: 'string', nullable: true },\n excludeAuthors: {\n type: 'array',\n items: { type: 'string' },\n nullable: true,\n },\n orderBy: {\n type: 'string',\n enum: [\n 'rank',\n 'views',\n 'title',\n 'trend',\n 'score',\n 'answersCount',\n 'created',\n 'updated',\n ],\n nullable: true,\n },\n collectionId: { type: 'number', nullable: true },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n noCorrectAnswer: { type: 'boolean', nullable: true },\n noAnswers: { type: 'boolean', nullable: true },\n hasAnswers: { type: 'boolean', nullable: true },\n favorite: { type: 'boolean', nullable: true },\n noVotes: { type: 'boolean', nullable: true },\n status: {\n type: 'string',\n enum: ['active', 'draft', 'deleted'],\n nullable: true,\n },\n random: { type: 'boolean', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n entitiesRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n tagsRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n includeAnswers: { type: 'boolean', nullable: true },\n includeVotes: { type: 'boolean', nullable: true },\n includeAttachments: { type: 'boolean', nullable: true },\n includeHealth: { type: 'boolean', nullable: true },\n reviewNeeded: { type: 'boolean', nullable: true },\n obsolete: { type: 'boolean', nullable: true },\n includeTags: { type: 'boolean', nullable: true },\n includeEntities: { type: 'boolean', nullable: true },\n includeTrend: { type: 'boolean', nullable: true },\n includeComments: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n searchQuery: { type: 'string', nullable: true },\n fromDate: { type: 'string', nullable: true, format: 'date' },\n toDate: { type: 'string', nullable: true, format: 'date' },\n type: {\n type: 'string',\n enum: ['question', 'article', 'link'],\n nullable: true,\n },\n ids: { type: 'array', items: { type: 'integer' }, nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const PostQuerySchema: JSONSchemaType<PostQuery> = {\n type: 'object',\n properties: {\n anonymous: { type: 'boolean', nullable: true },\n },\n};\n\nexport const TagsQuerySchema: JSONSchemaType<TagsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'tag',\n 'postsCount',\n 'questionsCount',\n 'articlesCount',\n 'linksCount',\n 'followerCount',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n searchQuery: { type: 'string', nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const UsersQuerySchema: JSONSchemaType<UsersQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'userRef',\n 'totalPosts',\n 'totalQuestions',\n 'totalAnswers',\n 'totalArticles',\n 'totalLinks',\n 'totalViews',\n 'totalVotes',\n 'followerCount',\n 'reputation',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n searchQuery: { type: 'string', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const EntitiesQuerySchema: JSONSchemaType<EntitiesQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n orderBy: {\n type: 'string',\n enum: [\n 'entityRef',\n 'postsCount',\n 'questionsCount',\n 'articlesCount',\n 'linksCount',\n 'followerCount',\n ],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n searchQuery: { type: 'string', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const AnswersQuerySchema: JSONSchemaType<AnswersQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', nullable: true },\n offset: { type: 'integer', nullable: true },\n author: { type: 'string', nullable: true },\n orderBy: {\n type: 'string',\n enum: ['score', 'created', 'updated'],\n nullable: true,\n },\n order: { type: 'string', enum: ['desc', 'asc'], nullable: true },\n noCorrectAnswer: { type: 'boolean', nullable: true },\n noVotes: { type: 'boolean', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n entitiesRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n tagsRelation: { type: 'string', enum: ['and', 'or'], nullable: true },\n includeVotes: { type: 'boolean', nullable: true },\n includeEntities: { type: 'boolean', nullable: true },\n includeComments: { type: 'boolean', nullable: true },\n includeExperts: { type: 'boolean', nullable: true },\n searchQuery: { type: 'string', nullable: true },\n fromDate: { type: 'string', nullable: true, format: 'date' },\n toDate: { type: 'string', nullable: true, format: 'date' },\n ids: { type: 'array', items: { type: 'integer' }, nullable: true },\n questionId: { type: 'integer', nullable: true },\n checkAccess: { type: 'boolean', nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const PostSchema: JSONSchemaType<PostContent> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n content: { type: 'string', minLength: 0 },\n author: { type: 'string', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n images: { type: 'array', items: { type: 'integer' }, nullable: true },\n user: { type: 'string', minLength: 1, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n anonymous: { type: 'boolean', nullable: true },\n headerImage: { type: 'string', nullable: true },\n url: { type: 'string', nullable: true },\n type: { type: 'string', enum: ['question', 'article', 'link'] },\n status: {\n type: 'string',\n enum: ['active', 'draft', 'deleted'],\n nullable: true,\n },\n },\n required: ['title', 'content'],\n additionalProperties: false,\n};\n\nexport const TemplateSchema: JSONSchemaType<TemplateContent> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n description: { type: 'string', minLength: 1 },\n questionTitle: { type: 'string', nullable: true },\n questionContent: { type: 'string', nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n },\n required: ['title', 'description'],\n additionalProperties: false,\n};\n\nexport const CollectionSchema: JSONSchemaType<CollectionContent> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n description: { type: 'string', nullable: true },\n headerImage: { type: 'string', nullable: true },\n images: { type: 'array', items: { type: 'integer' }, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n tags: { type: 'array', items: { type: 'string' }, nullable: true },\n entities: { type: 'array', items: { type: 'string' }, nullable: true },\n users: { type: 'array', items: { type: 'string' }, nullable: true },\n },\n required: ['title'],\n additionalProperties: false,\n};\n\nexport const CollectionPostSchema: JSONSchemaType<CollectionPostContent> = {\n type: 'object',\n properties: {\n postId: { type: 'integer' },\n },\n required: ['postId'],\n additionalProperties: false,\n};\n\nexport const CollectionRankPostSchema: JSONSchemaType<CollectionRankContent> = {\n type: 'object',\n properties: {\n postId: { type: 'integer' },\n rank: { type: 'string', enum: ['top', 'bottom', 'up', 'down'] },\n },\n required: ['postId', 'rank'],\n additionalProperties: false,\n};\n\nexport interface AnswerQuestion {\n answer: string;\n images?: number[];\n user?: string;\n author?: string;\n created?: string;\n anonymous?: boolean;\n}\n\nexport const PostAnswerSchema: JSONSchemaType<AnswerQuestion> = {\n type: 'object',\n properties: {\n answer: { type: 'string', minLength: 1 },\n images: { type: 'array', items: { type: 'integer' }, nullable: true },\n user: { type: 'string', minLength: 1, nullable: true },\n author: { type: 'string', minLength: 1, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n anonymous: { type: 'boolean', nullable: true },\n },\n required: ['answer'],\n additionalProperties: false,\n};\n\nexport interface DeleteMetadata {\n reason?: string;\n permanent?: boolean;\n}\n\nexport const DeleteMetadataSchema: JSONSchemaType<DeleteMetadata> = {\n type: 'object',\n properties: {\n reason: { type: 'string', minLength: 1, nullable: true },\n permanent: { type: 'boolean', nullable: true },\n },\n additionalProperties: false,\n};\n\nexport interface Comment {\n content: string;\n user?: string;\n created?: string;\n}\n\nexport const CommentSchema: JSONSchemaType<Comment> = {\n type: 'object',\n properties: {\n content: { type: 'string', minLength: 1 },\n user: { type: 'string', minLength: 1, nullable: true },\n created: { type: 'string', minLength: 1, nullable: true },\n },\n required: ['content'],\n additionalProperties: false,\n};\n\nexport interface DraftQuestion {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n}\n\nexport const DraftQuestionSchema: JSONSchemaType<DraftQuestion> = {\n type: 'object',\n properties: {\n title: { type: 'string', minLength: 1 },\n content: { type: 'string', minLength: 1 },\n tags: {\n type: 'array',\n items: { type: 'string' },\n nullable: true,\n },\n entities: {\n type: 'array',\n items: { type: 'string' },\n nullable: true,\n },\n },\n required: ['title', 'content'],\n additionalProperties: false,\n};\n\nexport const AIQuerySchema: JSONSchemaType<AIQuery> = {\n type: 'object',\n properties: {\n regenerate: { type: 'boolean', default: false, nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport const SuggestionsQuerySchema: JSONSchemaType<SuggestionsQuery> = {\n type: 'object',\n properties: {\n limit: { type: 'integer', minimum: 1, nullable: true },\n },\n required: [],\n additionalProperties: false,\n};\n\nexport interface File {\n name: string;\n path: string;\n buffer: Buffer;\n mimeType: string;\n ext: string;\n size: number;\n}\n\nexport const URLMetadataSchema: JSONSchemaType<URLMetadataQuery> = {\n type: 'object',\n properties: {\n url: { type: 'string', minLength: 7 }, // http://\n },\n required: ['url'],\n additionalProperties: false,\n};\n\nexport interface PostReviewBody {\n status: 'valid' | 'obsolete';\n comment?: string;\n}\n\nexport const PostReviewBodySchema: JSONSchemaType<PostReviewBody> = {\n type: 'object',\n properties: {\n status: { type: 'string', enum: ['valid', 'obsolete'] },\n comment: { type: 'string', nullable: true },\n },\n required: ['status'],\n additionalProperties: false,\n};\n"],"names":[],"mappings":"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"}
|
package/dist/service/util.cjs.js
CHANGED
|
@@ -42,15 +42,63 @@ const filterEntitiesByPermissions = async (entityRefs, routeOpts, credentials) =
|
|
|
42
42
|
return entityRefs;
|
|
43
43
|
}
|
|
44
44
|
try {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
let userKey = void 0;
|
|
46
|
+
if (routeOpts.auth.isPrincipal(credentials, "user")) {
|
|
47
|
+
userKey = credentials.principal.userEntityRef;
|
|
48
|
+
} else if (routeOpts.auth.isPrincipal(credentials, "service")) {
|
|
49
|
+
userKey = credentials.principal.subject;
|
|
50
|
+
} else {
|
|
51
|
+
routeOpts.logger.warn(
|
|
52
|
+
`Could not determine principal for permission check. Credentials: ${JSON.stringify(
|
|
53
|
+
credentials
|
|
54
|
+
)}`
|
|
55
|
+
);
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const cacheKey = `qeta:entity-permissions:${userKey}`;
|
|
59
|
+
const cache = routeOpts.cache;
|
|
60
|
+
let cachedPermissions = {};
|
|
61
|
+
if (cache) {
|
|
62
|
+
const cached = await cache.get(cacheKey);
|
|
63
|
+
if (cached) {
|
|
64
|
+
cachedPermissions = cached;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const refsToCheck = [];
|
|
68
|
+
const allowedRefs = [];
|
|
69
|
+
for (const ref of entityRefs) {
|
|
70
|
+
if (ref in cachedPermissions) {
|
|
71
|
+
if (cachedPermissions[ref]) {
|
|
72
|
+
allowedRefs.push(ref);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
refsToCheck.push(ref);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (refsToCheck.length > 0) {
|
|
79
|
+
const { token } = await routeOpts.auth.getPluginRequestToken({
|
|
80
|
+
onBehalfOf: credentials,
|
|
81
|
+
targetPluginId: "catalog"
|
|
82
|
+
});
|
|
83
|
+
const entities = await routeOpts.catalog.getEntitiesByRefs(
|
|
84
|
+
{ entityRefs: refsToCheck },
|
|
85
|
+
{ token }
|
|
86
|
+
);
|
|
87
|
+
const fetchedRefs = new Set(
|
|
88
|
+
entities.items.filter((entity) => entity !== void 0).map(catalogModel.stringifyEntityRef)
|
|
89
|
+
);
|
|
90
|
+
refsToCheck.forEach((ref) => {
|
|
91
|
+
const isAllowed = fetchedRefs.has(ref);
|
|
92
|
+
cachedPermissions[ref] = isAllowed;
|
|
93
|
+
if (isAllowed) {
|
|
94
|
+
allowedRefs.push(ref);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (cache) {
|
|
98
|
+
await cache.set(cacheKey, cachedPermissions, { ttl: 3e5 });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return allowedRefs;
|
|
54
102
|
} catch (error) {
|
|
55
103
|
routeOpts.logger.warn("Error filtering entities by permissions", error);
|
|
56
104
|
return [];
|
|
@@ -109,15 +157,23 @@ const mapCollectionAdditionalFields = async (request, resource, permissionMgr, c
|
|
|
109
157
|
resource.canDelete = canDelete;
|
|
110
158
|
resource.entities = filteredEntities;
|
|
111
159
|
if (resource.posts && routeOpts) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
160
|
+
const allEntityRefs = /* @__PURE__ */ new Set();
|
|
161
|
+
resource.posts.forEach((post) => {
|
|
162
|
+
post.entities?.forEach((ref) => allEntityRefs.add(ref));
|
|
163
|
+
});
|
|
164
|
+
if (allEntityRefs.size > 0) {
|
|
165
|
+
const allowedRefs = await filterEntitiesByPermissions(
|
|
166
|
+
Array.from(allEntityRefs),
|
|
167
|
+
routeOpts,
|
|
168
|
+
credentials
|
|
169
|
+
);
|
|
170
|
+
if (allowedRefs) {
|
|
171
|
+
const allowedSet = new Set(allowedRefs);
|
|
172
|
+
resource.posts.forEach((post) => {
|
|
173
|
+
post.entities = post.entities?.filter((ref) => allowedSet.has(ref));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
121
177
|
}
|
|
122
178
|
return resource;
|
|
123
179
|
};
|