@drodil/backstage-plugin-qeta-backend 3.53.0 → 3.53.2
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/stores/AnswersStore.cjs.js +7 -4
- package/dist/database/stores/AnswersStore.cjs.js.map +1 -1
- package/dist/service/routes/answers.cjs.js +21 -1
- package/dist/service/routes/answers.cjs.js.map +1 -1
- package/dist/service/routes/posts.cjs.js +20 -2
- package/dist/service/routes/posts.cjs.js.map +1 -1
- package/dist/service/util.cjs.js +1 -1
- package/dist/service/util.cjs.js.map +1 -1
- package/package.json +6 -6
|
@@ -27,6 +27,9 @@ class AnswersStore extends BaseStore.BaseStore {
|
|
|
27
27
|
if (options.noVotes) {
|
|
28
28
|
query.whereNull("answer_votes.answerId");
|
|
29
29
|
}
|
|
30
|
+
if (opts?.correct !== void 0) {
|
|
31
|
+
query.where("answers.correct", "=", opts.correct);
|
|
32
|
+
}
|
|
30
33
|
const totalQuery = query.clone();
|
|
31
34
|
if (options.orderBy) {
|
|
32
35
|
query.orderBy(options.orderBy, options.order ? options.order : "desc");
|
|
@@ -53,6 +56,9 @@ class AnswersStore extends BaseStore.BaseStore {
|
|
|
53
56
|
if (options?.filter) {
|
|
54
57
|
this.parseFilter(options.filter, query, this.db, "answer");
|
|
55
58
|
}
|
|
59
|
+
if (options?.correct !== void 0) {
|
|
60
|
+
query.where("answers.correct", "=", options.correct);
|
|
61
|
+
}
|
|
56
62
|
const rows = await query.select();
|
|
57
63
|
if (rows.length === 0) {
|
|
58
64
|
return null;
|
|
@@ -158,10 +164,7 @@ class AnswersStore extends BaseStore.BaseStore {
|
|
|
158
164
|
}
|
|
159
165
|
async markAnswer(postId, answerId, correct) {
|
|
160
166
|
if (correct) {
|
|
161
|
-
|
|
162
|
-
if (exists && exists.length > 0) {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
167
|
+
await this.db("answers").where("correct", "=", true).where("postId", "=", postId).update({ correct: false });
|
|
165
168
|
}
|
|
166
169
|
const ret = await this.db("answers").where("answers.id", "=", answerId).where("postId", "=", postId).update({ correct }, ["id"]);
|
|
167
170
|
if (ret !== void 0 && ret?.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnswersStore.cjs.js","sources":["../../../src/database/stores/AnswersStore.ts"],"sourcesContent":["import {\n Answer,\n AnswersQuery,\n AnswerCommentStatus,\n Comment as QetaComment,\n PostsQuery,\n} from '@drodil/backstage-plugin-qeta-common';\nimport {\n AnswerOptions,\n Answers,\n MaybeAnswer,\n MaybePost,\n Posts,\n} from '../QetaStore';\nimport { Knex } from 'knex';\nimport { CommentsStore } from './CommentsStore';\nimport { AttachmentsStore } from './AttachmentsStore';\nimport { QetaFilters } from '../../service/util';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { BaseStore } from './BaseStore';\n\nexport interface RawAnswerEntity {\n id: number;\n postId: number;\n author: string;\n content: string;\n correct: boolean;\n score: number | string;\n created: Date;\n updated: Date;\n updatedBy: string;\n anonymous: boolean;\n status: string;\n}\n\nexport interface RawAnswerVoteEntity {\n answerId: number;\n author: string;\n score: number;\n timestamp: Date;\n}\n\nexport class AnswersStore extends BaseStore {\n constructor(\n protected readonly db: Knex,\n private readonly commentsStore: CommentsStore,\n private readonly postsStore: {\n getPost(\n user_ref: string,\n id: number,\n recordView?: boolean,\n ): Promise<MaybePost>;\n getPosts(user_ref: string, options: PostsQuery): Promise<Posts>;\n },\n private readonly attachmentsStore: AttachmentsStore,\n ) {\n super(db);\n }\n\n async getAnswers(\n user_ref: string,\n options: AnswersQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: AnswerOptions,\n ): Promise<Answers> {\n const query = this.getAnswerBaseQuery();\n\n if (options.author) {\n query.where('answers.author', '=', options.author);\n }\n\n if (filters) {\n this.parseFilter(filters, query, this.db, 'answer');\n }\n\n if (options.searchQuery) {\n this.applySearchQuery(query, ['answers.content'], options.searchQuery);\n }\n\n if (options.questionId) {\n query.where('answers.postId', '=', options.questionId);\n }\n\n if (options.noVotes) {\n query.whereNull('answer_votes.answerId');\n }\n\n const totalQuery = query.clone();\n\n if (options.orderBy) {\n query.orderBy(options.orderBy, options.order ? options.order : 'desc');\n }\n\n if (options.limit) {\n query.limit(options.limit);\n }\n\n if (options.offset) {\n query.offset(options.offset);\n }\n\n const results = await Promise.all([\n query,\n this.db(totalQuery.as('totalQuery')).count('* as CNT').first(),\n ]);\n\n const rows = results[0] as RawAnswerEntity[];\n const total = this.mapToInteger((results[1] as any)?.CNT);\n\n return {\n answers: await this.mapAnswerEntities(rows, user_ref, opts),\n total,\n };\n }\n\n async getAnswer(\n answerId: number,\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n const query = this.getAnswerBaseQuery().where('answers.id', '=', answerId);\n if (options?.filter) {\n this.parseFilter(options.filter, query, this.db, 'answer');\n }\n\n const rows = await query.select();\n if (rows.length === 0) {\n return null;\n }\n return (\n await this.mapAnswerEntities(\n [rows[0] as unknown as RawAnswerEntity],\n user_ref,\n options,\n )\n )[0];\n }\n\n async getPostAnswers(\n postId: number | number[],\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<Answer[]> {\n const { includeStatusFilter = true } = options ?? {};\n const query = this.getAnswerBaseQuery()\n .orderBy('answers.correct', 'desc')\n .orderBy('answers.created');\n\n if (Array.isArray(postId)) {\n query.whereIn('postId', postId);\n } else {\n query.where('postId', '=', postId);\n }\n\n if (includeStatusFilter) {\n query.where('answers.status', '=', 'active');\n }\n\n if (options?.filter) {\n this.parseFilter(options.filter, query, this.db, 'answer');\n }\n\n const rows = await query.select();\n return this.mapAnswerEntities(rows, user_ref, options);\n }\n\n async answerPost(\n user_ref: string,\n questionId: number,\n answer: string,\n created: Date,\n images?: number[],\n anonymous?: boolean,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n const answers = await this.db\n .insert(\n {\n postId: questionId,\n author: user_ref,\n content: answer,\n created,\n correct: false,\n anonymous: anonymous ?? false,\n },\n ['id'],\n )\n .into('answers')\n .returning('id');\n\n await this.db('posts').where('id', questionId).increment('answersCount', 1);\n\n if (images && images.length > 0) {\n await this.updateAttachments('answerId', answer, images, answers[0].id);\n }\n\n return this.getAnswer(answers[0].id, user_ref, options);\n }\n\n async updateAnswer(\n user_ref: string,\n questionId: number,\n answerId: number,\n answer: string,\n author?: string,\n images?: number[],\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n const query = this.db('answers')\n .where('id', '=', answerId)\n .where('postId', '=', questionId);\n\n await query.update({\n content: answer,\n updatedBy: user_ref,\n updated: new Date(),\n author: author,\n });\n\n if (images) {\n await this.updateAttachments('answerId', answer, images, answerId);\n }\n\n return this.getAnswer(answerId, user_ref, options);\n }\n\n async deleteAnswer(id: number, permanently?: boolean): Promise<boolean> {\n const answer = await this.db('answers')\n .select('postId')\n .where('id', id)\n .first();\n\n if (permanently) {\n const rows = await this.db('answers').where('id', '=', id).delete();\n if (answer && rows > 0) {\n await this.db('posts')\n .where('id', answer.postId)\n .decrement('answersCount', 1);\n }\n return rows > 0;\n }\n const rows = await this.db('answers').where('id', '=', id).update({\n status: 'deleted',\n });\n if (answer && rows > 0) {\n await this.db('posts')\n .where('id', answer.postId)\n .decrement('answersCount', 1);\n }\n return rows > 0;\n }\n\n async voteAnswer(\n user_ref: string,\n answerId: number,\n score: number,\n ): Promise<boolean> {\n await this.db('answer_votes')\n .where('author', '=', user_ref)\n .where('answerId', '=', answerId)\n .delete();\n\n await this.db\n .insert({\n author: user_ref,\n answerId,\n score,\n timestamp: new Date(),\n })\n .into('answer_votes');\n\n await this.db('answers')\n .where('id', '=', answerId)\n .update({\n score: this.db('answer_votes')\n .where('answerId', '=', answerId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n return true;\n }\n\n async deleteAnswerVote(user_ref: string, answerId: number): Promise<boolean> {\n const rows = await this.db('answer_votes')\n .where('author', '=', user_ref)\n .where('answerId', '=', answerId)\n .delete();\n\n if (rows > 0) {\n await this.db('answers')\n .where('id', '=', answerId)\n .update({\n score: this.db('answer_votes')\n .where('answerId', '=', answerId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n }\n return rows > 0;\n }\n\n async markAnswerCorrect(postId: number, answerId: number): Promise<boolean> {\n return this.markAnswer(postId, answerId, true);\n }\n\n async markAnswerIncorrect(\n postId: number,\n answerId: number,\n ): Promise<boolean> {\n return this.markAnswer(postId, answerId, false);\n }\n\n private async markAnswer(\n postId: number,\n answerId: number,\n correct: boolean,\n ): Promise<boolean> {\n if (correct) {\n const exists = await this.db('answers')\n .select('id')\n .where('correct', '=', true)\n .where('postId', '=', postId);\n if (exists && exists.length > 0) {\n return false;\n }\n }\n\n const ret = await this.db('answers')\n .where('answers.id', '=', answerId)\n .where('postId', '=', postId)\n .update({ correct }, ['id']);\n\n if (ret !== undefined && ret?.length > 0) {\n if (correct) {\n await this.db('posts')\n .where('id', '=', postId)\n .increment('correctAnswers', 1);\n } else {\n await this.db('posts')\n .where('id', '=', postId)\n .decrement('correctAnswers', 1);\n }\n }\n\n return ret !== undefined && ret?.length > 0;\n }\n\n private getAnswerBaseQuery() {\n return this.db<RawAnswerEntity>('answers').select('*');\n }\n\n private async mapAnswerEntities(\n rows: RawAnswerEntity[],\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<Answer[]> {\n if (rows.length === 0) {\n return [];\n }\n const answerIds = rows.map(r => r.id);\n const {\n includeVotes = true,\n includeComments = true,\n includePost = true,\n includeExperts = true,\n } = options ?? {};\n const [votes, comments, posts, attachments, experts] = await Promise.all([\n includeVotes\n ? this.db<RawAnswerVoteEntity>('answer_votes')\n .whereIn('answerId', answerIds)\n .select()\n : undefined,\n includeComments\n ? (this.commentsStore.getAnswerComments(\n answerIds as any,\n options?.commentsFilter,\n ) as unknown as Promise<(QetaComment & { answerId: number })[]>)\n : undefined,\n includePost && this.postsStore\n ? this.postsStore\n .getPosts(user_ref, {\n ids: [...new Set(rows.map((r: RawAnswerEntity) => r.postId))],\n limit: rows.length,\n })\n .then(p => p.posts)\n : undefined,\n this.attachmentsStore.getAttachments(answerIds, 'answerId'),\n includeExperts\n ? this.db('tag_experts')\n .leftJoin('tags', 'tag_experts.tagId', 'tags.id')\n .leftJoin('post_tags', 'post_tags.tagId', 'tags.id')\n .leftJoin('answers', 'answers.postId', 'post_tags.postId')\n .whereIn('answers.id', answerIds)\n .select('answers.id as answerId', 'tag_experts.entityRef')\n : undefined,\n ]);\n\n const votesMap = new Map<number, RawAnswerVoteEntity[]>();\n votes?.forEach((v: RawAnswerVoteEntity) => {\n const ps = votesMap.get(v.answerId) || [];\n ps.push(v);\n votesMap.set(v.answerId, ps);\n });\n\n const commentsMap = new Map<number, QetaComment[]>();\n comments?.forEach(c => {\n const ps = commentsMap.get(c.answerId) || [];\n ps.push(c);\n commentsMap.set(c.answerId, ps);\n });\n\n const attachmentsMap = attachments ?? new Map<number, number[]>();\n\n const expertsMap = new Map<number, string[]>();\n experts?.forEach((e: any) => {\n const ps = expertsMap.get(e.answerId) || [];\n ps.push(e.entityRef);\n expertsMap.set(e.answerId, ps);\n });\n\n return rows.map(val => {\n const answerVotes = votesMap.get(val.id) || [];\n return {\n id: val.id,\n postId: val.postId,\n own: val.author === user_ref,\n author:\n val.anonymous && val.author !== user_ref ? 'anonymous' : val.author,\n content: val.content,\n correct: val.correct,\n created: val.created,\n updated: val.updated,\n updatedBy: val.updatedBy,\n status: val.status as AnswerCommentStatus,\n score: this.mapToInteger(val.score),\n votes: answerVotes.map((v: RawAnswerVoteEntity) => ({\n author: v.author,\n score: v.score,\n timestamp: v.timestamp,\n })),\n comments: commentsMap.get(val.id),\n anonymous: val.anonymous,\n post: posts?.find(p => p?.id === val.postId) ?? undefined,\n images: attachmentsMap.get(val.id) || [],\n experts: expertsMap.get(val.id),\n };\n });\n }\n}\n"],"names":["BaseStore","rows"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnswersStore.cjs.js","sources":["../../../src/database/stores/AnswersStore.ts"],"sourcesContent":["import {\n Answer,\n AnswersQuery,\n AnswerCommentStatus,\n Comment as QetaComment,\n PostsQuery,\n} from '@drodil/backstage-plugin-qeta-common';\nimport {\n AnswerOptions,\n Answers,\n MaybeAnswer,\n MaybePost,\n Posts,\n} from '../QetaStore';\nimport { Knex } from 'knex';\nimport { CommentsStore } from './CommentsStore';\nimport { AttachmentsStore } from './AttachmentsStore';\nimport { QetaFilters } from '../../service/util';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { BaseStore } from './BaseStore';\n\nexport interface RawAnswerEntity {\n id: number;\n postId: number;\n author: string;\n content: string;\n correct: boolean;\n score: number | string;\n created: Date;\n updated: Date;\n updatedBy: string;\n anonymous: boolean;\n status: string;\n}\n\nexport interface RawAnswerVoteEntity {\n answerId: number;\n author: string;\n score: number;\n timestamp: Date;\n}\n\nexport class AnswersStore extends BaseStore {\n constructor(\n protected readonly db: Knex,\n private readonly commentsStore: CommentsStore,\n private readonly postsStore: {\n getPost(\n user_ref: string,\n id: number,\n recordView?: boolean,\n ): Promise<MaybePost>;\n getPosts(user_ref: string, options: PostsQuery): Promise<Posts>;\n },\n private readonly attachmentsStore: AttachmentsStore,\n ) {\n super(db);\n }\n\n async getAnswers(\n user_ref: string,\n options: AnswersQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: AnswerOptions,\n ): Promise<Answers> {\n const query = this.getAnswerBaseQuery();\n\n if (options.author) {\n query.where('answers.author', '=', options.author);\n }\n\n if (filters) {\n this.parseFilter(filters, query, this.db, 'answer');\n }\n\n if (options.searchQuery) {\n this.applySearchQuery(query, ['answers.content'], options.searchQuery);\n }\n\n if (options.questionId) {\n query.where('answers.postId', '=', options.questionId);\n }\n\n if (options.noVotes) {\n query.whereNull('answer_votes.answerId');\n }\n\n if (opts?.correct !== undefined) {\n query.where('answers.correct', '=', opts.correct);\n }\n\n const totalQuery = query.clone();\n\n if (options.orderBy) {\n query.orderBy(options.orderBy, options.order ? options.order : 'desc');\n }\n\n if (options.limit) {\n query.limit(options.limit);\n }\n\n if (options.offset) {\n query.offset(options.offset);\n }\n\n const results = await Promise.all([\n query,\n this.db(totalQuery.as('totalQuery')).count('* as CNT').first(),\n ]);\n\n const rows = results[0] as RawAnswerEntity[];\n const total = this.mapToInteger((results[1] as any)?.CNT);\n\n return {\n answers: await this.mapAnswerEntities(rows, user_ref, opts),\n total,\n };\n }\n\n async getAnswer(\n answerId: number,\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n const query = this.getAnswerBaseQuery().where('answers.id', '=', answerId);\n if (options?.filter) {\n this.parseFilter(options.filter, query, this.db, 'answer');\n }\n\n if (options?.correct !== undefined) {\n query.where('answers.correct', '=', options.correct);\n }\n\n const rows = await query.select();\n if (rows.length === 0) {\n return null;\n }\n return (\n await this.mapAnswerEntities(\n [rows[0] as unknown as RawAnswerEntity],\n user_ref,\n options,\n )\n )[0];\n }\n\n async getPostAnswers(\n postId: number | number[],\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<Answer[]> {\n const { includeStatusFilter = true } = options ?? {};\n const query = this.getAnswerBaseQuery()\n .orderBy('answers.correct', 'desc')\n .orderBy('answers.created');\n\n if (Array.isArray(postId)) {\n query.whereIn('postId', postId);\n } else {\n query.where('postId', '=', postId);\n }\n\n if (includeStatusFilter) {\n query.where('answers.status', '=', 'active');\n }\n\n if (options?.filter) {\n this.parseFilter(options.filter, query, this.db, 'answer');\n }\n\n const rows = await query.select();\n return this.mapAnswerEntities(rows, user_ref, options);\n }\n\n async answerPost(\n user_ref: string,\n questionId: number,\n answer: string,\n created: Date,\n images?: number[],\n anonymous?: boolean,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n const answers = await this.db\n .insert(\n {\n postId: questionId,\n author: user_ref,\n content: answer,\n created,\n correct: false,\n anonymous: anonymous ?? false,\n },\n ['id'],\n )\n .into('answers')\n .returning('id');\n\n await this.db('posts').where('id', questionId).increment('answersCount', 1);\n\n if (images && images.length > 0) {\n await this.updateAttachments('answerId', answer, images, answers[0].id);\n }\n\n return this.getAnswer(answers[0].id, user_ref, options);\n }\n\n async updateAnswer(\n user_ref: string,\n questionId: number,\n answerId: number,\n answer: string,\n author?: string,\n images?: number[],\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n const query = this.db('answers')\n .where('id', '=', answerId)\n .where('postId', '=', questionId);\n\n await query.update({\n content: answer,\n updatedBy: user_ref,\n updated: new Date(),\n author: author,\n });\n\n if (images) {\n await this.updateAttachments('answerId', answer, images, answerId);\n }\n\n return this.getAnswer(answerId, user_ref, options);\n }\n\n async deleteAnswer(id: number, permanently?: boolean): Promise<boolean> {\n const answer = await this.db('answers')\n .select('postId')\n .where('id', id)\n .first();\n\n if (permanently) {\n const rows = await this.db('answers').where('id', '=', id).delete();\n if (answer && rows > 0) {\n await this.db('posts')\n .where('id', answer.postId)\n .decrement('answersCount', 1);\n }\n return rows > 0;\n }\n const rows = await this.db('answers').where('id', '=', id).update({\n status: 'deleted',\n });\n if (answer && rows > 0) {\n await this.db('posts')\n .where('id', answer.postId)\n .decrement('answersCount', 1);\n }\n return rows > 0;\n }\n\n async voteAnswer(\n user_ref: string,\n answerId: number,\n score: number,\n ): Promise<boolean> {\n await this.db('answer_votes')\n .where('author', '=', user_ref)\n .where('answerId', '=', answerId)\n .delete();\n\n await this.db\n .insert({\n author: user_ref,\n answerId,\n score,\n timestamp: new Date(),\n })\n .into('answer_votes');\n\n await this.db('answers')\n .where('id', '=', answerId)\n .update({\n score: this.db('answer_votes')\n .where('answerId', '=', answerId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n return true;\n }\n\n async deleteAnswerVote(user_ref: string, answerId: number): Promise<boolean> {\n const rows = await this.db('answer_votes')\n .where('author', '=', user_ref)\n .where('answerId', '=', answerId)\n .delete();\n\n if (rows > 0) {\n await this.db('answers')\n .where('id', '=', answerId)\n .update({\n score: this.db('answer_votes')\n .where('answerId', '=', answerId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n }\n return rows > 0;\n }\n\n async markAnswerCorrect(postId: number, answerId: number): Promise<boolean> {\n return this.markAnswer(postId, answerId, true);\n }\n\n async markAnswerIncorrect(\n postId: number,\n answerId: number,\n ): Promise<boolean> {\n return this.markAnswer(postId, answerId, false);\n }\n\n private async markAnswer(\n postId: number,\n answerId: number,\n correct: boolean,\n ): Promise<boolean> {\n if (correct) {\n await this.db('answers')\n .where('correct', '=', true)\n .where('postId', '=', postId)\n .update({ correct: false });\n }\n\n const ret = await this.db('answers')\n .where('answers.id', '=', answerId)\n .where('postId', '=', postId)\n .update({ correct }, ['id']);\n\n if (ret !== undefined && ret?.length > 0) {\n if (correct) {\n await this.db('posts')\n .where('id', '=', postId)\n .increment('correctAnswers', 1);\n } else {\n await this.db('posts')\n .where('id', '=', postId)\n .decrement('correctAnswers', 1);\n }\n }\n\n return ret !== undefined && ret?.length > 0;\n }\n\n private getAnswerBaseQuery() {\n return this.db<RawAnswerEntity>('answers').select('*');\n }\n\n private async mapAnswerEntities(\n rows: RawAnswerEntity[],\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<Answer[]> {\n if (rows.length === 0) {\n return [];\n }\n const answerIds = rows.map(r => r.id);\n const {\n includeVotes = true,\n includeComments = true,\n includePost = true,\n includeExperts = true,\n } = options ?? {};\n const [votes, comments, posts, attachments, experts] = await Promise.all([\n includeVotes\n ? this.db<RawAnswerVoteEntity>('answer_votes')\n .whereIn('answerId', answerIds)\n .select()\n : undefined,\n includeComments\n ? (this.commentsStore.getAnswerComments(\n answerIds as any,\n options?.commentsFilter,\n ) as unknown as Promise<(QetaComment & { answerId: number })[]>)\n : undefined,\n includePost && this.postsStore\n ? this.postsStore\n .getPosts(user_ref, {\n ids: [...new Set(rows.map((r: RawAnswerEntity) => r.postId))],\n limit: rows.length,\n })\n .then(p => p.posts)\n : undefined,\n this.attachmentsStore.getAttachments(answerIds, 'answerId'),\n includeExperts\n ? this.db('tag_experts')\n .leftJoin('tags', 'tag_experts.tagId', 'tags.id')\n .leftJoin('post_tags', 'post_tags.tagId', 'tags.id')\n .leftJoin('answers', 'answers.postId', 'post_tags.postId')\n .whereIn('answers.id', answerIds)\n .select('answers.id as answerId', 'tag_experts.entityRef')\n : undefined,\n ]);\n\n const votesMap = new Map<number, RawAnswerVoteEntity[]>();\n votes?.forEach((v: RawAnswerVoteEntity) => {\n const ps = votesMap.get(v.answerId) || [];\n ps.push(v);\n votesMap.set(v.answerId, ps);\n });\n\n const commentsMap = new Map<number, QetaComment[]>();\n comments?.forEach(c => {\n const ps = commentsMap.get(c.answerId) || [];\n ps.push(c);\n commentsMap.set(c.answerId, ps);\n });\n\n const attachmentsMap = attachments ?? new Map<number, number[]>();\n\n const expertsMap = new Map<number, string[]>();\n experts?.forEach((e: any) => {\n const ps = expertsMap.get(e.answerId) || [];\n ps.push(e.entityRef);\n expertsMap.set(e.answerId, ps);\n });\n\n return rows.map(val => {\n const answerVotes = votesMap.get(val.id) || [];\n return {\n id: val.id,\n postId: val.postId,\n own: val.author === user_ref,\n author:\n val.anonymous && val.author !== user_ref ? 'anonymous' : val.author,\n content: val.content,\n correct: val.correct,\n created: val.created,\n updated: val.updated,\n updatedBy: val.updatedBy,\n status: val.status as AnswerCommentStatus,\n score: this.mapToInteger(val.score),\n votes: answerVotes.map((v: RawAnswerVoteEntity) => ({\n author: v.author,\n score: v.score,\n timestamp: v.timestamp,\n })),\n comments: commentsMap.get(val.id),\n anonymous: val.anonymous,\n post: posts?.find(p => p?.id === val.postId) ?? undefined,\n images: attachmentsMap.get(val.id) || [],\n experts: expertsMap.get(val.id),\n };\n });\n }\n}\n"],"names":["BaseStore","rows"],"mappings":";;;;AA0CO,MAAM,qBAAqBA,mBAAU,CAAA;AAAA,EAC1C,WACqB,CAAA,EAAA,EACF,aACA,EAAA,UAAA,EAQA,gBACjB,EAAA;AACA,IAAA,KAAA,CAAM,EAAE,CAAA;AAZW,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AACF,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAQA,IAAA,IAAA,CAAA,gBAAA,GAAA,gBAAA;AAAA;AAGnB,EAEA,MAAM,UAAA,CACJ,QACA,EAAA,OAAA,EACA,SACA,IACkB,EAAA;AAClB,IAAM,MAAA,KAAA,GAAQ,KAAK,kBAAmB,EAAA;AAEtC,IAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,MAAA,KAAA,CAAM,KAAM,CAAA,gBAAA,EAAkB,GAAK,EAAA,OAAA,CAAQ,MAAM,CAAA;AAAA;AAGnD,IAAA,IAAI,OAAS,EAAA;AACX,MAAA,IAAA,CAAK,WAAY,CAAA,OAAA,EAAS,KAAO,EAAA,IAAA,CAAK,IAAI,QAAQ,CAAA;AAAA;AAGpD,IAAA,IAAI,QAAQ,WAAa,EAAA;AACvB,MAAA,IAAA,CAAK,iBAAiB,KAAO,EAAA,CAAC,iBAAiB,CAAA,EAAG,QAAQ,WAAW,CAAA;AAAA;AAGvE,IAAA,IAAI,QAAQ,UAAY,EAAA;AACtB,MAAA,KAAA,CAAM,KAAM,CAAA,gBAAA,EAAkB,GAAK,EAAA,OAAA,CAAQ,UAAU,CAAA;AAAA;AAGvD,IAAA,IAAI,QAAQ,OAAS,EAAA;AACnB,MAAA,KAAA,CAAM,UAAU,uBAAuB,CAAA;AAAA;AAGzC,IAAI,IAAA,IAAA,EAAM,YAAY,KAAW,CAAA,EAAA;AAC/B,MAAA,KAAA,CAAM,KAAM,CAAA,iBAAA,EAAmB,GAAK,EAAA,IAAA,CAAK,OAAO,CAAA;AAAA;AAGlD,IAAM,MAAA,UAAA,GAAa,MAAM,KAAM,EAAA;AAE/B,IAAA,IAAI,QAAQ,OAAS,EAAA;AACnB,MAAA,KAAA,CAAM,QAAQ,OAAQ,CAAA,OAAA,EAAS,QAAQ,KAAQ,GAAA,OAAA,CAAQ,QAAQ,MAAM,CAAA;AAAA;AAGvE,IAAA,IAAI,QAAQ,KAAO,EAAA;AACjB,MAAM,KAAA,CAAA,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA;AAG3B,IAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,MAAM,KAAA,CAAA,MAAA,CAAO,QAAQ,MAAM,CAAA;AAAA;AAG7B,IAAM,MAAA,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAI,CAAA;AAAA,MAChC,KAAA;AAAA,MACA,IAAA,CAAK,EAAG,CAAA,UAAA,CAAW,EAAG,CAAA,YAAY,CAAC,CAAE,CAAA,KAAA,CAAM,UAAU,CAAA,CAAE,KAAM;AAAA,KAC9D,CAAA;AAED,IAAM,MAAA,IAAA,GAAO,QAAQ,CAAC,CAAA;AACtB,IAAA,MAAM,QAAQ,IAAK,CAAA,YAAA,CAAc,OAAQ,CAAA,CAAC,GAAW,GAAG,CAAA;AAExD,IAAO,OAAA;AAAA,MACL,SAAS,MAAM,IAAA,CAAK,iBAAkB,CAAA,IAAA,EAAM,UAAU,IAAI,CAAA;AAAA,MAC1D;AAAA,KACF;AAAA;AACF,EAEA,MAAM,SAAA,CACJ,QACA,EAAA,QAAA,EACA,OACsB,EAAA;AACtB,IAAA,MAAM,QAAQ,IAAK,CAAA,kBAAA,GAAqB,KAAM,CAAA,YAAA,EAAc,KAAK,QAAQ,CAAA;AACzE,IAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,MAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,MAAA,EAAQ,KAAO,EAAA,IAAA,CAAK,IAAI,QAAQ,CAAA;AAAA;AAG3D,IAAI,IAAA,OAAA,EAAS,YAAY,KAAW,CAAA,EAAA;AAClC,MAAA,KAAA,CAAM,KAAM,CAAA,iBAAA,EAAmB,GAAK,EAAA,OAAA,CAAQ,OAAO,CAAA;AAAA;AAGrD,IAAM,MAAA,IAAA,GAAO,MAAM,KAAA,CAAM,MAAO,EAAA;AAChC,IAAI,IAAA,IAAA,CAAK,WAAW,CAAG,EAAA;AACrB,MAAO,OAAA,IAAA;AAAA;AAET,IAAA,OAAA,CACE,MAAM,IAAK,CAAA,iBAAA;AAAA,MACT,CAAC,IAAK,CAAA,CAAC,CAA+B,CAAA;AAAA,MACtC,QAAA;AAAA,MACA;AAAA,OAEF,CAAC,CAAA;AAAA;AACL,EAEA,MAAM,cAAA,CACJ,MACA,EAAA,QAAA,EACA,OACmB,EAAA;AACnB,IAAA,MAAM,EAAE,mBAAA,GAAsB,IAAK,EAAA,GAAI,WAAW,EAAC;AACnD,IAAM,MAAA,KAAA,GAAQ,KAAK,kBAAmB,EAAA,CACnC,QAAQ,iBAAmB,EAAA,MAAM,CACjC,CAAA,OAAA,CAAQ,iBAAiB,CAAA;AAE5B,IAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,MAAM,CAAG,EAAA;AACzB,MAAM,KAAA,CAAA,OAAA,CAAQ,UAAU,MAAM,CAAA;AAAA,KACzB,MAAA;AACL,MAAM,KAAA,CAAA,KAAA,CAAM,QAAU,EAAA,GAAA,EAAK,MAAM,CAAA;AAAA;AAGnC,IAAA,IAAI,mBAAqB,EAAA;AACvB,MAAM,KAAA,CAAA,KAAA,CAAM,gBAAkB,EAAA,GAAA,EAAK,QAAQ,CAAA;AAAA;AAG7C,IAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,MAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,MAAA,EAAQ,KAAO,EAAA,IAAA,CAAK,IAAI,QAAQ,CAAA;AAAA;AAG3D,IAAM,MAAA,IAAA,GAAO,MAAM,KAAA,CAAM,MAAO,EAAA;AAChC,IAAA,OAAO,IAAK,CAAA,iBAAA,CAAkB,IAAM,EAAA,QAAA,EAAU,OAAO,CAAA;AAAA;AACvD,EAEA,MAAM,WACJ,QACA,EAAA,UAAA,EACA,QACA,OACA,EAAA,MAAA,EACA,WACA,OACsB,EAAA;AACtB,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,EACxB,CAAA,MAAA;AAAA,MACC;AAAA,QACE,MAAQ,EAAA,UAAA;AAAA,QACR,MAAQ,EAAA,QAAA;AAAA,QACR,OAAS,EAAA,MAAA;AAAA,QACT,OAAA;AAAA,QACA,OAAS,EAAA,KAAA;AAAA,QACT,WAAW,SAAa,IAAA;AAAA,OAC1B;AAAA,MACA,CAAC,IAAI;AAAA,KAEN,CAAA,IAAA,CAAK,SAAS,CAAA,CACd,UAAU,IAAI,CAAA;AAEjB,IAAM,MAAA,IAAA,CAAK,EAAG,CAAA,OAAO,CAAE,CAAA,KAAA,CAAM,MAAM,UAAU,CAAA,CAAE,SAAU,CAAA,cAAA,EAAgB,CAAC,CAAA;AAE1E,IAAI,IAAA,MAAA,IAAU,MAAO,CAAA,MAAA,GAAS,CAAG,EAAA;AAC/B,MAAM,MAAA,IAAA,CAAK,kBAAkB,UAAY,EAAA,MAAA,EAAQ,QAAQ,OAAQ,CAAA,CAAC,EAAE,EAAE,CAAA;AAAA;AAGxE,IAAA,OAAO,KAAK,SAAU,CAAA,OAAA,CAAQ,CAAC,CAAE,CAAA,EAAA,EAAI,UAAU,OAAO,CAAA;AAAA;AACxD,EAEA,MAAM,aACJ,QACA,EAAA,UAAA,EACA,UACA,MACA,EAAA,MAAA,EACA,QACA,OACsB,EAAA;AACtB,IAAA,MAAM,KAAQ,GAAA,IAAA,CAAK,EAAG,CAAA,SAAS,CAC5B,CAAA,KAAA,CAAM,IAAM,EAAA,GAAA,EAAK,QAAQ,CAAA,CACzB,KAAM,CAAA,QAAA,EAAU,KAAK,UAAU,CAAA;AAElC,IAAA,MAAM,MAAM,MAAO,CAAA;AAAA,MACjB,OAAS,EAAA,MAAA;AAAA,MACT,SAAW,EAAA,QAAA;AAAA,MACX,OAAA,sBAAa,IAAK,EAAA;AAAA,MAClB;AAAA,KACD,CAAA;AAED,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,MAAM,IAAK,CAAA,iBAAA,CAAkB,UAAY,EAAA,MAAA,EAAQ,QAAQ,QAAQ,CAAA;AAAA;AAGnE,IAAA,OAAO,IAAK,CAAA,SAAA,CAAU,QAAU,EAAA,QAAA,EAAU,OAAO,CAAA;AAAA;AACnD,EAEA,MAAM,YAAa,CAAA,EAAA,EAAY,WAAyC,EAAA;AACtE,IAAA,MAAM,MAAS,GAAA,MAAM,IAAK,CAAA,EAAA,CAAG,SAAS,CAAA,CACnC,MAAO,CAAA,QAAQ,CACf,CAAA,KAAA,CAAM,IAAM,EAAA,EAAE,EACd,KAAM,EAAA;AAET,IAAA,IAAI,WAAa,EAAA;AACf,MAAMC,MAAAA,KAAAA,GAAO,MAAM,IAAA,CAAK,EAAG,CAAA,SAAS,CAAE,CAAA,KAAA,CAAM,IAAM,EAAA,GAAA,EAAK,EAAE,CAAA,CAAE,MAAO,EAAA;AAClE,MAAI,IAAA,MAAA,IAAUA,QAAO,CAAG,EAAA;AACtB,QAAM,MAAA,IAAA,CAAK,EAAG,CAAA,OAAO,CAClB,CAAA,KAAA,CAAM,IAAM,EAAA,MAAA,CAAO,MAAM,CAAA,CACzB,SAAU,CAAA,cAAA,EAAgB,CAAC,CAAA;AAAA;AAEhC,MAAA,OAAOA,KAAO,GAAA,CAAA;AAAA;AAEhB,IAAM,MAAA,IAAA,GAAO,MAAM,IAAA,CAAK,EAAG,CAAA,SAAS,CAAE,CAAA,KAAA,CAAM,IAAM,EAAA,GAAA,EAAK,EAAE,CAAA,CAAE,MAAO,CAAA;AAAA,MAChE,MAAQ,EAAA;AAAA,KACT,CAAA;AACD,IAAI,IAAA,MAAA,IAAU,OAAO,CAAG,EAAA;AACtB,MAAM,MAAA,IAAA,CAAK,EAAG,CAAA,OAAO,CAClB,CAAA,KAAA,CAAM,IAAM,EAAA,MAAA,CAAO,MAAM,CAAA,CACzB,SAAU,CAAA,cAAA,EAAgB,CAAC,CAAA;AAAA;AAEhC,IAAA,OAAO,IAAO,GAAA,CAAA;AAAA;AAChB,EAEA,MAAM,UAAA,CACJ,QACA,EAAA,QAAA,EACA,KACkB,EAAA;AAClB,IAAA,MAAM,IAAK,CAAA,EAAA,CAAG,cAAc,CAAA,CACzB,MAAM,QAAU,EAAA,GAAA,EAAK,QAAQ,CAAA,CAC7B,KAAM,CAAA,UAAA,EAAY,GAAK,EAAA,QAAQ,EAC/B,MAAO,EAAA;AAEV,IAAM,MAAA,IAAA,CAAK,GACR,MAAO,CAAA;AAAA,MACN,MAAQ,EAAA,QAAA;AAAA,MACR,QAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA,sBAAe,IAAK;AAAA,KACrB,CACA,CAAA,IAAA,CAAK,cAAc,CAAA;AAEtB,IAAM,MAAA,IAAA,CAAK,GAAG,SAAS,CAAA,CACpB,MAAM,IAAM,EAAA,GAAA,EAAK,QAAQ,CAAA,CACzB,MAAO,CAAA;AAAA,MACN,KAAO,EAAA,IAAA,CAAK,EAAG,CAAA,cAAc,EAC1B,KAAM,CAAA,UAAA,EAAY,GAAK,EAAA,QAAQ,EAC/B,MAAO,CAAA,IAAA,CAAK,EAAG,CAAA,GAAA,CAAI,yBAAyB,CAAC;AAAA,KACjD,CAAA;AACH,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,gBAAiB,CAAA,QAAA,EAAkB,QAAoC,EAAA;AAC3E,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,EAAG,CAAA,cAAc,EACtC,KAAM,CAAA,QAAA,EAAU,GAAK,EAAA,QAAQ,EAC7B,KAAM,CAAA,UAAA,EAAY,GAAK,EAAA,QAAQ,EAC/B,MAAO,EAAA;AAEV,IAAA,IAAI,OAAO,CAAG,EAAA;AACZ,MAAM,MAAA,IAAA,CAAK,GAAG,SAAS,CAAA,CACpB,MAAM,IAAM,EAAA,GAAA,EAAK,QAAQ,CAAA,CACzB,MAAO,CAAA;AAAA,QACN,KAAO,EAAA,IAAA,CAAK,EAAG,CAAA,cAAc,EAC1B,KAAM,CAAA,UAAA,EAAY,GAAK,EAAA,QAAQ,EAC/B,MAAO,CAAA,IAAA,CAAK,EAAG,CAAA,GAAA,CAAI,yBAAyB,CAAC;AAAA,OACjD,CAAA;AAAA;AAEL,IAAA,OAAO,IAAO,GAAA,CAAA;AAAA;AAChB,EAEA,MAAM,iBAAkB,CAAA,MAAA,EAAgB,QAAoC,EAAA;AAC1E,IAAA,OAAO,IAAK,CAAA,UAAA,CAAW,MAAQ,EAAA,QAAA,EAAU,IAAI,CAAA;AAAA;AAC/C,EAEA,MAAM,mBACJ,CAAA,MAAA,EACA,QACkB,EAAA;AAClB,IAAA,OAAO,IAAK,CAAA,UAAA,CAAW,MAAQ,EAAA,QAAA,EAAU,KAAK,CAAA;AAAA;AAChD,EAEA,MAAc,UAAA,CACZ,MACA,EAAA,QAAA,EACA,OACkB,EAAA;AAClB,IAAA,IAAI,OAAS,EAAA;AACX,MAAA,MAAM,KAAK,EAAG,CAAA,SAAS,EACpB,KAAM,CAAA,SAAA,EAAW,KAAK,IAAI,CAAA,CAC1B,KAAM,CAAA,QAAA,EAAU,KAAK,MAAM,CAAA,CAC3B,OAAO,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA;AAG9B,IAAM,MAAA,GAAA,GAAM,MAAM,IAAK,CAAA,EAAA,CAAG,SAAS,CAChC,CAAA,KAAA,CAAM,YAAc,EAAA,GAAA,EAAK,QAAQ,CAAA,CACjC,MAAM,QAAU,EAAA,GAAA,EAAK,MAAM,CAC3B,CAAA,MAAA,CAAO,EAAE,OAAQ,EAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAE7B,IAAA,IAAI,GAAQ,KAAA,KAAA,CAAA,IAAa,GAAK,EAAA,MAAA,GAAS,CAAG,EAAA;AACxC,MAAA,IAAI,OAAS,EAAA;AACX,QAAM,MAAA,IAAA,CAAK,EAAG,CAAA,OAAO,CAClB,CAAA,KAAA,CAAM,IAAM,EAAA,GAAA,EAAK,MAAM,CAAA,CACvB,SAAU,CAAA,gBAAA,EAAkB,CAAC,CAAA;AAAA,OAC3B,MAAA;AACL,QAAM,MAAA,IAAA,CAAK,EAAG,CAAA,OAAO,CAClB,CAAA,KAAA,CAAM,IAAM,EAAA,GAAA,EAAK,MAAM,CAAA,CACvB,SAAU,CAAA,gBAAA,EAAkB,CAAC,CAAA;AAAA;AAClC;AAGF,IAAO,OAAA,GAAA,KAAQ,KAAa,CAAA,IAAA,GAAA,EAAK,MAAS,GAAA,CAAA;AAAA;AAC5C,EAEQ,kBAAqB,GAAA;AAC3B,IAAA,OAAO,IAAK,CAAA,EAAA,CAAoB,SAAS,CAAA,CAAE,OAAO,GAAG,CAAA;AAAA;AACvD,EAEA,MAAc,iBAAA,CACZ,IACA,EAAA,QAAA,EACA,OACmB,EAAA;AACnB,IAAI,IAAA,IAAA,CAAK,WAAW,CAAG,EAAA;AACrB,MAAA,OAAO,EAAC;AAAA;AAEV,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA;AACpC,IAAM,MAAA;AAAA,MACJ,YAAe,GAAA,IAAA;AAAA,MACf,eAAkB,GAAA,IAAA;AAAA,MAClB,WAAc,GAAA,IAAA;AAAA,MACd,cAAiB,GAAA;AAAA,KACnB,GAAI,WAAW,EAAC;AAChB,IAAM,MAAA,CAAC,OAAO,QAAU,EAAA,KAAA,EAAO,aAAa,OAAO,CAAA,GAAI,MAAM,OAAA,CAAQ,GAAI,CAAA;AAAA,MACvE,YAAA,GACI,IAAK,CAAA,EAAA,CAAwB,cAAc,CAAA,CACxC,QAAQ,UAAY,EAAA,SAAS,CAC7B,CAAA,MAAA,EACH,GAAA,KAAA,CAAA;AAAA,MACJ,eAAA,GACK,KAAK,aAAc,CAAA,iBAAA;AAAA,QAClB,SAAA;AAAA,QACA,OAAS,EAAA;AAAA,OAEX,GAAA,KAAA,CAAA;AAAA,MACJ,eAAe,IAAK,CAAA,UAAA,GAChB,IAAK,CAAA,UAAA,CACF,SAAS,QAAU,EAAA;AAAA,QAClB,GAAK,EAAA,CAAC,GAAG,IAAI,GAAI,CAAA,IAAA,CAAK,GAAI,CAAA,CAAC,CAAuB,KAAA,CAAA,CAAE,MAAM,CAAC,CAAC,CAAA;AAAA,QAC5D,OAAO,IAAK,CAAA;AAAA,OACb,CACA,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA,CAAA,CAAE,KAAK,CACpB,GAAA,KAAA,CAAA;AAAA,MACJ,IAAK,CAAA,gBAAA,CAAiB,cAAe,CAAA,SAAA,EAAW,UAAU,CAAA;AAAA,MAC1D,cAAA,GACI,IAAK,CAAA,EAAA,CAAG,aAAa,CAAA,CAClB,QAAS,CAAA,MAAA,EAAQ,mBAAqB,EAAA,SAAS,CAC/C,CAAA,QAAA,CAAS,WAAa,EAAA,iBAAA,EAAmB,SAAS,CAAA,CAClD,QAAS,CAAA,SAAA,EAAW,gBAAkB,EAAA,kBAAkB,CACxD,CAAA,OAAA,CAAQ,YAAc,EAAA,SAAS,CAC/B,CAAA,MAAA,CAAO,wBAA0B,EAAA,uBAAuB,CAC3D,GAAA,KAAA;AAAA,KACL,CAAA;AAED,IAAM,MAAA,QAAA,uBAAe,GAAmC,EAAA;AACxD,IAAO,KAAA,EAAA,OAAA,CAAQ,CAAC,CAA2B,KAAA;AACzC,MAAA,MAAM,KAAK,QAAS,CAAA,GAAA,CAAI,CAAE,CAAA,QAAQ,KAAK,EAAC;AACxC,MAAA,EAAA,CAAG,KAAK,CAAC,CAAA;AACT,MAAS,QAAA,CAAA,GAAA,CAAI,CAAE,CAAA,QAAA,EAAU,EAAE,CAAA;AAAA,KAC5B,CAAA;AAED,IAAM,MAAA,WAAA,uBAAkB,GAA2B,EAAA;AACnD,IAAA,QAAA,EAAU,QAAQ,CAAK,CAAA,KAAA;AACrB,MAAA,MAAM,KAAK,WAAY,CAAA,GAAA,CAAI,CAAE,CAAA,QAAQ,KAAK,EAAC;AAC3C,MAAA,EAAA,CAAG,KAAK,CAAC,CAAA;AACT,MAAY,WAAA,CAAA,GAAA,CAAI,CAAE,CAAA,QAAA,EAAU,EAAE,CAAA;AAAA,KAC/B,CAAA;AAED,IAAM,MAAA,cAAA,GAAiB,WAAe,oBAAA,IAAI,GAAsB,EAAA;AAEhE,IAAM,MAAA,UAAA,uBAAiB,GAAsB,EAAA;AAC7C,IAAS,OAAA,EAAA,OAAA,CAAQ,CAAC,CAAW,KAAA;AAC3B,MAAA,MAAM,KAAK,UAAW,CAAA,GAAA,CAAI,CAAE,CAAA,QAAQ,KAAK,EAAC;AAC1C,MAAG,EAAA,CAAA,IAAA,CAAK,EAAE,SAAS,CAAA;AACnB,MAAW,UAAA,CAAA,GAAA,CAAI,CAAE,CAAA,QAAA,EAAU,EAAE,CAAA;AAAA,KAC9B,CAAA;AAED,IAAO,OAAA,IAAA,CAAK,IAAI,CAAO,GAAA,KAAA;AACrB,MAAA,MAAM,cAAc,QAAS,CAAA,GAAA,CAAI,GAAI,CAAA,EAAE,KAAK,EAAC;AAC7C,MAAO,OAAA;AAAA,QACL,IAAI,GAAI,CAAA,EAAA;AAAA,QACR,QAAQ,GAAI,CAAA,MAAA;AAAA,QACZ,GAAA,EAAK,IAAI,MAAW,KAAA,QAAA;AAAA,QACpB,QACE,GAAI,CAAA,SAAA,IAAa,IAAI,MAAW,KAAA,QAAA,GAAW,cAAc,GAAI,CAAA,MAAA;AAAA,QAC/D,SAAS,GAAI,CAAA,OAAA;AAAA,QACb,SAAS,GAAI,CAAA,OAAA;AAAA,QACb,SAAS,GAAI,CAAA,OAAA;AAAA,QACb,SAAS,GAAI,CAAA,OAAA;AAAA,QACb,WAAW,GAAI,CAAA,SAAA;AAAA,QACf,QAAQ,GAAI,CAAA,MAAA;AAAA,QACZ,KAAO,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,KAAK,CAAA;AAAA,QAClC,KAAO,EAAA,WAAA,CAAY,GAAI,CAAA,CAAC,CAA4B,MAAA;AAAA,UAClD,QAAQ,CAAE,CAAA,MAAA;AAAA,UACV,OAAO,CAAE,CAAA,KAAA;AAAA,UACT,WAAW,CAAE,CAAA;AAAA,SACb,CAAA,CAAA;AAAA,QACF,QAAU,EAAA,WAAA,CAAY,GAAI,CAAA,GAAA,CAAI,EAAE,CAAA;AAAA,QAChC,WAAW,GAAI,CAAA,SAAA;AAAA,QACf,IAAA,EAAM,OAAO,IAAK,CAAA,CAAA,CAAA,KAAK,GAAG,EAAO,KAAA,GAAA,CAAI,MAAM,CAAK,IAAA,KAAA,CAAA;AAAA,QAChD,QAAQ,cAAe,CAAA,GAAA,CAAI,GAAI,CAAA,EAAE,KAAK,EAAC;AAAA,QACvC,OAAS,EAAA,UAAA,CAAW,GAAI,CAAA,GAAA,CAAI,EAAE;AAAA,OAChC;AAAA,KACD,CAAA;AAAA;AAEL;;;;"}
|
|
@@ -704,6 +704,14 @@ const answersRoutes = (router, options) => {
|
|
|
704
704
|
}
|
|
705
705
|
const post = await database.getPost(username, postId, false);
|
|
706
706
|
const answer = await database.getAnswer(answerId, username);
|
|
707
|
+
const previousCorrectAnswers = await database.getAnswers(
|
|
708
|
+
username,
|
|
709
|
+
{ questionId: postId, limit: 1 },
|
|
710
|
+
void 0,
|
|
711
|
+
{
|
|
712
|
+
correct: true
|
|
713
|
+
}
|
|
714
|
+
);
|
|
707
715
|
if (!post || !answer) {
|
|
708
716
|
response.status(404).send({ errors: "Post or answer not found", type: "body" });
|
|
709
717
|
return;
|
|
@@ -719,10 +727,22 @@ const answersRoutes = (router, options) => {
|
|
|
719
727
|
request,
|
|
720
728
|
[
|
|
721
729
|
{ permission: backstagePluginQetaCommon.qetaEditPostPermission, resource: post },
|
|
722
|
-
{ permission: backstagePluginQetaCommon.qetaReadAnswerPermission, resource: answer }
|
|
730
|
+
{ permission: backstagePluginQetaCommon.qetaReadAnswerPermission, resource: answer },
|
|
731
|
+
...previousCorrectAnswers.answers.map((a) => ({
|
|
732
|
+
permission: backstagePluginQetaCommon.qetaReadAnswerPermission,
|
|
733
|
+
resource: a
|
|
734
|
+
}))
|
|
723
735
|
],
|
|
724
736
|
{ throwOnDeny: true }
|
|
725
737
|
);
|
|
738
|
+
if (previousCorrectAnswers.answers.length > 0) {
|
|
739
|
+
const previousCorrectAnswer = previousCorrectAnswers.answers[0];
|
|
740
|
+
await database.markAnswerIncorrect(postId, previousCorrectAnswer.id);
|
|
741
|
+
await util.signalAnswerStats(signals, {
|
|
742
|
+
...previousCorrectAnswer,
|
|
743
|
+
correct: false
|
|
744
|
+
});
|
|
745
|
+
}
|
|
726
746
|
const marked = await database.markAnswerCorrect(postId, answerId);
|
|
727
747
|
if (!marked) {
|
|
728
748
|
response.status(404).send({ errors: "Failed to mark answer correct", type: "body" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"answers.cjs.js","sources":["../../../src/service/routes/answers.ts"],"sourcesContent":["import Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { getCreated, mapAdditionalFields } from '../util';\nimport {\n AnswersQuerySchema,\n CommentSchema,\n DeleteMetadataSchema,\n PostAnswerSchema,\n RouteOptions,\n} from '../types';\nimport { Request, Router } from 'express';\nimport {\n AnswersQuery,\n findEntityMentions,\n qetaCreateAnswerPermission,\n qetaCreateCommentPermission,\n qetaDeleteAnswerPermission,\n qetaDeleteCommentPermission,\n qetaEditAnswerPermission,\n qetaEditCommentPermission,\n qetaEditPostPermission,\n qetaReadAnswerPermission,\n qetaReadCommentPermission,\n qetaReadPostPermission,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { Response } from 'express-serve-static-core';\nimport {\n entityToJsonObject,\n signalAnswerStats,\n signalPostStats,\n validateDateRange,\n wrapAsync,\n} from './util';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const answersRoutes = (router: Router, options: RouteOptions) => {\n const { database, events, signals, notificationMgr, auditor, permissionMgr } =\n options;\n\n router.get(`/answers`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(AnswersQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const validDate = validateDateRange(\n request.query.fromDate as string,\n request.query.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const [commentsFilter, answersFilter] = await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadCommentPermission, {\n allowServicePrincipal: true,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadAnswerPermission, {\n allowServicePrincipal: true,\n }),\n ]);\n\n const opts = request.query as AnswersQuery;\n\n const answers = await database.getAnswers(username, opts, answersFilter, {\n commentsFilter,\n });\n\n await mapAdditionalFields(request, answers.answers, options, {\n checkRights: opts.checkAccess ?? false,\n });\n response.json(answers);\n });\n\n router.post(`/answers/query`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(AnswersQuerySchema);\n if (!validateQuery(request.body)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const validDate = validateDateRange(\n request.body.fromDate as string,\n request.body.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const [commentsFilter, answersFilter] = await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadCommentPermission, {\n allowServicePrincipal: true,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadAnswerPermission, {\n allowServicePrincipal: true,\n }),\n ]);\n\n const opts = request.body;\n\n const answers = await database.getAnswers(username, opts, answersFilter, {\n commentsFilter,\n });\n await mapAdditionalFields(request, answers.answers, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(answers);\n });\n\n // POST /posts/:id/answers\n router.post(`/posts/:id/answers`, async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(PostAnswerSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const postId = Number.parseInt(request.params.id, 10);\n if (Number.isNaN(postId)) {\n response.status(400).send({ errors: 'Invalid post id', type: 'body' });\n return;\n }\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n if (!post || post.type !== 'question') {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response\n .status(400)\n .send({ errors: 'Cannot add answers to obsolete posts', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaCreateAnswerPermission },\n ],\n { throwOnDeny: true },\n );\n\n const created = await getCreated(request, options);\n\n // Act\n const answer = await database.answerPost(\n username,\n postId,\n request.body.answer,\n created,\n request.body.images,\n request.body.anonymous || username === 'user:default/guest',\n );\n\n if (!answer) {\n response\n .status(400)\n .send({ errors: 'Failed to answer post', type: 'body' });\n return;\n }\n\n wrapAsync(async () => {\n const followingUsers = await Promise.all([\n database.getUsersForTags(post.tags),\n database.getUsersForEntities(post.entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(post.id),\n ]);\n const sent = await notificationMgr.onNewAnswer(\n username,\n post,\n answer,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(answer.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(username, answer, mentions, sent);\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n answer,\n question: post,\n author: username,\n },\n metadata: { action: 'post_answer' },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n signalPostStats(signals, post);\n auditor?.createEvent({\n eventId: 'create-answer',\n severityLevel: 'medium',\n request,\n meta: {\n answer: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n },\n });\n\n // Response\n response.status(201).json(answer);\n });\n\n // POST /questions/:id/answers/:answerId\n router.post(`/posts/:id/answers/:answerId`, async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(PostAnswerSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const post = await database.getPost(username, postId, false);\n const originalAnswer = await database.getAnswer(answerId, username);\n if (!originalAnswer || !post || post.type !== 'question') {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot edit answers on obsolete posts',\n type: 'body',\n });\n return;\n }\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaEditAnswerPermission, resource: originalAnswer },\n ],\n { throwOnDeny: true },\n );\n\n if (\n request.body.author &&\n request.body.author !== username &&\n request.body.author !== originalAnswer.author\n ) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n // Act\n const answer = await database.updateAnswer(\n username,\n postId,\n answerId,\n request.body.answer,\n request.body.author,\n request.body.images,\n );\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'update-answer',\n severityLevel: 'medium',\n request,\n meta: {\n from: entityToJsonObject(originalAnswer),\n to: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n // Response\n response.json(answer);\n });\n\n // POST /posts/:id/answers/:answerId/comments\n router.post(\n `/posts/:id/answers/:answerId/comments`,\n async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(CommentSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n\n if (!post) {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot add comments to obsolete posts',\n type: 'body',\n });\n return;\n }\n let answer = await database.getAnswer(answerId, username);\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n { permission: qetaCreateCommentPermission },\n ],\n { throwOnDeny: true },\n );\n\n const created = await getCreated(request, options);\n // Act\n answer = await database.commentAnswer(\n answerId,\n username,\n request.body.content,\n created,\n );\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n wrapAsync(async () => {\n if (!answer) {\n return;\n }\n\n const followingUsers = await Promise.all([\n database.getUsersForTags(post.tags),\n database.getUsersForEntities(post.entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(post.id),\n ]);\n const sent = await notificationMgr.onAnswerComment(\n username,\n post,\n answer,\n request.body.content,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(request.body.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(\n username,\n answer,\n mentions,\n sent,\n true,\n );\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer,\n comment: request.body.content,\n author: username,\n },\n metadata: { action: 'comment_answer' },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n auditor?.createEvent({\n eventId: 'comment-answer',\n severityLevel: 'medium',\n request,\n meta: {\n answer: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n comment: request.body.content,\n },\n });\n\n // Response\n response.status(201).json(answer);\n },\n );\n\n // POST /posts/:id/answers/:answerId/comments/:commentId\n router.post(\n `/posts/:id/answers/:answerId/comments/:commentId`,\n async (request, response) => {\n // Validation\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (\n Number.isNaN(postId) ||\n Number.isNaN(answerId) ||\n Number.isNaN(commentId)\n ) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n let answer = await database.getAnswer(answerId, username);\n const comment = await database.getComment(commentId, { answerId });\n\n if (!post || !answer || !comment) {\n response\n .status(404)\n .send({ errors: 'Post, answer or comment not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot edit comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n { permission: qetaEditCommentPermission, resource: comment },\n ],\n { throwOnDeny: true },\n );\n\n // Act\n answer = await database.updateAnswerComment(\n answerId,\n commentId,\n username,\n request.body.content,\n );\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n from: entityToJsonObject(comment),\n to: request.body.content,\n },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n // Response\n response.json(answer);\n },\n );\n\n // DELETE /posts/:id/answers/:answerId/comments/:commentId\n router.delete(\n `/posts/:id/answers/:answerId/comments/:commentId`,\n async (request, response) => {\n // Validation\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (\n Number.isNaN(postId) ||\n Number.isNaN(answerId) ||\n Number.isNaN(commentId)\n ) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n let answer = await database.getAnswer(answerId, username);\n const comment = await database.getComment(commentId, { answerId });\n\n if (!post || !answer || !comment) {\n response\n .status(404)\n .send({ errors: 'Post, answer or comment not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot delete comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n { permission: qetaDeleteCommentPermission, resource: comment },\n ],\n { throwOnDeny: true },\n );\n\n // Act\n if (comment.status === 'deleted' || request.body?.permanent === true) {\n if (!permissionMgr.isModerator(request)) {\n response\n .status(404)\n .send({ errors: 'Comment not found', type: 'query' });\n return;\n }\n answer = await database.deleteAnswerComment(\n answerId,\n commentId,\n username,\n true,\n );\n } else {\n answer = await database.deleteAnswerComment(\n answerId,\n commentId,\n username,\n );\n }\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n comment: entityToJsonObject(comment),\n },\n });\n\n await mapAdditionalFields(request, [answer], options);\n\n // Response\n response.json(answer);\n },\n );\n\n // GET /posts/:id/answers/:answerId\n router.get(`/posts/:id/answers/:answerId`, async (request, response) => {\n // Validation\n // Act\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n const post = await database.getPost(username, postId, false);\n let answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response.sendStatus(404);\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaEditAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response.sendStatus(404);\n return;\n }\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n auditor?.createEvent({\n eventId: 'read-answer',\n severityLevel: 'low',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n\n // Response\n response.json(answer);\n });\n\n // DELETE /posts/:id/answers/:answerId\n router.delete('/posts/:id/answers/:answerId', async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n const validateRequestBody = ajv.compile(DeleteMetadataSchema);\n if (\n Number.isNaN(postId) ||\n Number.isNaN(answerId) ||\n !validateRequestBody(request.body)\n ) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response\n .status(404)\n .send({ errors: 'Post or answer not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaDeleteAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n // Act\n let deleted = false;\n if (answer.status === 'deleted' || request.body?.permanent === true) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(404)\n .send({ errors: 'Answer not found', type: 'query' });\n return;\n }\n deleted = await database.deleteAnswer(answerId, true);\n } else {\n deleted = await database.deleteAnswer(answerId);\n if (deleted) {\n notificationMgr.onAnswerDelete(\n username,\n post,\n answer,\n request.body.reason,\n );\n }\n }\n\n if (deleted) {\n signalPostStats(signals, post);\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer,\n author: username,\n reason: request.body.reason,\n },\n metadata: { action: 'delete_answer' },\n });\n auditor?.createEvent({\n eventId: 'delete-answer',\n severityLevel: 'medium',\n request,\n meta: {\n answer: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n reason: request.body.reason,\n },\n });\n }\n\n // Response\n response.sendStatus(deleted ? 204 : 404);\n });\n\n const voteAnswer = async (\n request: Request<any>,\n response: Response,\n score: number,\n ) => {\n // Validation\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (answer === null || post === null) {\n response.sendStatus(404);\n return;\n }\n\n if (post.status === 'obsolete') {\n response\n .status(400)\n .send({ errors: 'Cannot vote on obsolete posts', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n if (answer.own) {\n response\n .status(400)\n .send({ errors: 'Cannot vote on own answer', type: 'body' });\n return;\n }\n\n // Act\n const voted = await database.voteAnswer(username, answerId, score);\n\n if (!voted) {\n response.sendStatus(404);\n return;\n }\n\n const resp = await database.getAnswer(answerId, username);\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer: resp,\n author: username,\n score,\n },\n metadata: { action: 'vote_answer' },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = score;\n\n auditor?.createEvent({\n eventId: 'vote',\n severityLevel: 'low',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n score,\n },\n });\n\n signalAnswerStats(signals, resp);\n\n // Response\n response.json(resp);\n };\n\n // GET /posts/:id/answers/:answerId/upvote\n router.get(\n `/posts/:id/answers/:answerId/upvote`,\n async (request, response) => {\n return await voteAnswer(request, response, 1);\n },\n );\n\n // GET /posts/:id/answers/:answerId/downvote\n router.get(\n `/posts/:id/answers/:answerId/downvote`,\n async (request, response) => {\n return await voteAnswer(request, response, -1);\n },\n );\n\n router.delete(\n '/posts/:id/answers/:answerId/vote',\n async (request, response) => {\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (answer === null || post === null) {\n response.sendStatus(404);\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n const deleted = await database.deleteAnswerVote(username, answerId);\n if (!deleted) {\n response.sendStatus(404);\n return;\n }\n\n const resp = await database.getAnswer(answerId, username);\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-vote',\n severityLevel: 'low',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = undefined;\n\n signalAnswerStats(signals, resp);\n\n // Response\n response.json(resp);\n },\n );\n\n // GET /posts/:id/answers/:answerId/correct\n router.get(\n `/posts/:id/answers/:answerId/correct`,\n async (request, response) => {\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response\n .status(404)\n .send({ errors: 'Post or answer not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot mark answers on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaEditPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n const marked = await database.markAnswerCorrect(postId, answerId);\n\n if (!marked) {\n response\n .status(404)\n .send({ errors: 'Failed to mark answer correct', type: 'body' });\n return;\n }\n\n wrapAsync(async () => {\n await notificationMgr.onCorrectAnswer(username, post, answer);\n });\n\n const updated = await database.getAnswer(answerId, username);\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer: updated,\n author: username,\n },\n metadata: { action: 'correct_answer' },\n });\n\n signalPostStats(signals, post);\n signalAnswerStats(signals, updated);\n\n auditor?.createEvent({\n eventId: 'correct-answer',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n\n response.sendStatus(200);\n },\n );\n\n // GET /posts/:id/answers/:answerId/incorrect\n router.get(\n `/posts/:id/answers/:answerId/incorrect`,\n async (request, response) => {\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response\n .status(404)\n .send({ errors: 'Post or answer not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaEditPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n const marked = await database.markAnswerIncorrect(postId, answerId);\n\n if (marked) {\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer,\n author: username,\n },\n metadata: { action: 'incorrect_answer' },\n });\n auditor?.createEvent({\n eventId: 'incorrect-answer',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n }\n\n response.sendStatus(marked ? 200 : 404);\n },\n );\n};\n"],"names":["Ajv","addFormats","AnswersQuerySchema","validateDateRange","qetaReadCommentPermission","qetaReadAnswerPermission","mapAdditionalFields","PostAnswerSchema","qetaReadPostPermission","qetaCreateAnswerPermission","getCreated","wrapAsync","findEntityMentions","signalPostStats","entityToJsonObject","qetaEditAnswerPermission","CommentSchema","qetaCreateCommentPermission","qetaEditCommentPermission","qetaDeleteCommentPermission","DeleteMetadataSchema","qetaDeleteAnswerPermission","signalAnswerStats","qetaEditPostPermission"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"answers.cjs.js","sources":["../../../src/service/routes/answers.ts"],"sourcesContent":["import Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { getCreated, mapAdditionalFields } from '../util';\nimport {\n AnswersQuerySchema,\n CommentSchema,\n DeleteMetadataSchema,\n PostAnswerSchema,\n RouteOptions,\n} from '../types';\nimport { Request, Router } from 'express';\nimport {\n AnswersQuery,\n findEntityMentions,\n qetaCreateAnswerPermission,\n qetaCreateCommentPermission,\n qetaDeleteAnswerPermission,\n qetaDeleteCommentPermission,\n qetaEditAnswerPermission,\n qetaEditCommentPermission,\n qetaEditPostPermission,\n qetaReadAnswerPermission,\n qetaReadCommentPermission,\n qetaReadPostPermission,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { Response } from 'express-serve-static-core';\nimport {\n entityToJsonObject,\n signalAnswerStats,\n signalPostStats,\n validateDateRange,\n wrapAsync,\n} from './util';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const answersRoutes = (router: Router, options: RouteOptions) => {\n const { database, events, signals, notificationMgr, auditor, permissionMgr } =\n options;\n\n router.get(`/answers`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(AnswersQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const validDate = validateDateRange(\n request.query.fromDate as string,\n request.query.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const [commentsFilter, answersFilter] = await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadCommentPermission, {\n allowServicePrincipal: true,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadAnswerPermission, {\n allowServicePrincipal: true,\n }),\n ]);\n\n const opts = request.query as AnswersQuery;\n\n const answers = await database.getAnswers(username, opts, answersFilter, {\n commentsFilter,\n });\n\n await mapAdditionalFields(request, answers.answers, options, {\n checkRights: opts.checkAccess ?? false,\n });\n response.json(answers);\n });\n\n router.post(`/answers/query`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(AnswersQuerySchema);\n if (!validateQuery(request.body)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const validDate = validateDateRange(\n request.body.fromDate as string,\n request.body.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const [commentsFilter, answersFilter] = await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadCommentPermission, {\n allowServicePrincipal: true,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadAnswerPermission, {\n allowServicePrincipal: true,\n }),\n ]);\n\n const opts = request.body;\n\n const answers = await database.getAnswers(username, opts, answersFilter, {\n commentsFilter,\n });\n await mapAdditionalFields(request, answers.answers, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(answers);\n });\n\n // POST /posts/:id/answers\n router.post(`/posts/:id/answers`, async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(PostAnswerSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const postId = Number.parseInt(request.params.id, 10);\n if (Number.isNaN(postId)) {\n response.status(400).send({ errors: 'Invalid post id', type: 'body' });\n return;\n }\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n if (!post || post.type !== 'question') {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response\n .status(400)\n .send({ errors: 'Cannot add answers to obsolete posts', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaCreateAnswerPermission },\n ],\n { throwOnDeny: true },\n );\n\n const created = await getCreated(request, options);\n\n // Act\n const answer = await database.answerPost(\n username,\n postId,\n request.body.answer,\n created,\n request.body.images,\n request.body.anonymous || username === 'user:default/guest',\n );\n\n if (!answer) {\n response\n .status(400)\n .send({ errors: 'Failed to answer post', type: 'body' });\n return;\n }\n\n wrapAsync(async () => {\n const followingUsers = await Promise.all([\n database.getUsersForTags(post.tags),\n database.getUsersForEntities(post.entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(post.id),\n ]);\n const sent = await notificationMgr.onNewAnswer(\n username,\n post,\n answer,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(answer.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(username, answer, mentions, sent);\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n answer,\n question: post,\n author: username,\n },\n metadata: { action: 'post_answer' },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n signalPostStats(signals, post);\n auditor?.createEvent({\n eventId: 'create-answer',\n severityLevel: 'medium',\n request,\n meta: {\n answer: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n },\n });\n\n // Response\n response.status(201).json(answer);\n });\n\n // POST /questions/:id/answers/:answerId\n router.post(`/posts/:id/answers/:answerId`, async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(PostAnswerSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const post = await database.getPost(username, postId, false);\n const originalAnswer = await database.getAnswer(answerId, username);\n if (!originalAnswer || !post || post.type !== 'question') {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot edit answers on obsolete posts',\n type: 'body',\n });\n return;\n }\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaEditAnswerPermission, resource: originalAnswer },\n ],\n { throwOnDeny: true },\n );\n\n if (\n request.body.author &&\n request.body.author !== username &&\n request.body.author !== originalAnswer.author\n ) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n // Act\n const answer = await database.updateAnswer(\n username,\n postId,\n answerId,\n request.body.answer,\n request.body.author,\n request.body.images,\n );\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'update-answer',\n severityLevel: 'medium',\n request,\n meta: {\n from: entityToJsonObject(originalAnswer),\n to: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n // Response\n response.json(answer);\n });\n\n // POST /posts/:id/answers/:answerId/comments\n router.post(\n `/posts/:id/answers/:answerId/comments`,\n async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(CommentSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n\n if (!post) {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot add comments to obsolete posts',\n type: 'body',\n });\n return;\n }\n let answer = await database.getAnswer(answerId, username);\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n { permission: qetaCreateCommentPermission },\n ],\n { throwOnDeny: true },\n );\n\n const created = await getCreated(request, options);\n // Act\n answer = await database.commentAnswer(\n answerId,\n username,\n request.body.content,\n created,\n );\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n wrapAsync(async () => {\n if (!answer) {\n return;\n }\n\n const followingUsers = await Promise.all([\n database.getUsersForTags(post.tags),\n database.getUsersForEntities(post.entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(post.id),\n ]);\n const sent = await notificationMgr.onAnswerComment(\n username,\n post,\n answer,\n request.body.content,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(request.body.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(\n username,\n answer,\n mentions,\n sent,\n true,\n );\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer,\n comment: request.body.content,\n author: username,\n },\n metadata: { action: 'comment_answer' },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n auditor?.createEvent({\n eventId: 'comment-answer',\n severityLevel: 'medium',\n request,\n meta: {\n answer: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n comment: request.body.content,\n },\n });\n\n // Response\n response.status(201).json(answer);\n },\n );\n\n // POST /posts/:id/answers/:answerId/comments/:commentId\n router.post(\n `/posts/:id/answers/:answerId/comments/:commentId`,\n async (request, response) => {\n // Validation\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (\n Number.isNaN(postId) ||\n Number.isNaN(answerId) ||\n Number.isNaN(commentId)\n ) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n let answer = await database.getAnswer(answerId, username);\n const comment = await database.getComment(commentId, { answerId });\n\n if (!post || !answer || !comment) {\n response\n .status(404)\n .send({ errors: 'Post, answer or comment not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot edit comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n { permission: qetaEditCommentPermission, resource: comment },\n ],\n { throwOnDeny: true },\n );\n\n // Act\n answer = await database.updateAnswerComment(\n answerId,\n commentId,\n username,\n request.body.content,\n );\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n from: entityToJsonObject(comment),\n to: request.body.content,\n },\n });\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n // Response\n response.json(answer);\n },\n );\n\n // DELETE /posts/:id/answers/:answerId/comments/:commentId\n router.delete(\n `/posts/:id/answers/:answerId/comments/:commentId`,\n async (request, response) => {\n // Validation\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (\n Number.isNaN(postId) ||\n Number.isNaN(answerId) ||\n Number.isNaN(commentId)\n ) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n let answer = await database.getAnswer(answerId, username);\n const comment = await database.getComment(commentId, { answerId });\n\n if (!post || !answer || !comment) {\n response\n .status(404)\n .send({ errors: 'Post, answer or comment not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot delete comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n { permission: qetaDeleteCommentPermission, resource: comment },\n ],\n { throwOnDeny: true },\n );\n\n // Act\n if (comment.status === 'deleted' || request.body?.permanent === true) {\n if (!permissionMgr.isModerator(request)) {\n response\n .status(404)\n .send({ errors: 'Comment not found', type: 'query' });\n return;\n }\n answer = await database.deleteAnswerComment(\n answerId,\n commentId,\n username,\n true,\n );\n } else {\n answer = await database.deleteAnswerComment(\n answerId,\n commentId,\n username,\n );\n }\n\n if (!answer) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n comment: entityToJsonObject(comment),\n },\n });\n\n await mapAdditionalFields(request, [answer], options);\n\n // Response\n response.json(answer);\n },\n );\n\n // GET /posts/:id/answers/:answerId\n router.get(`/posts/:id/answers/:answerId`, async (request, response) => {\n // Validation\n // Act\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n const post = await database.getPost(username, postId, false);\n let answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response.sendStatus(404);\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaEditAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response.sendStatus(404);\n return;\n }\n\n await mapAdditionalFields(request, [answer], options, { username });\n\n auditor?.createEvent({\n eventId: 'read-answer',\n severityLevel: 'low',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n\n // Response\n response.json(answer);\n });\n\n // DELETE /posts/:id/answers/:answerId\n router.delete('/posts/:id/answers/:answerId', async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n const validateRequestBody = ajv.compile(DeleteMetadataSchema);\n if (\n Number.isNaN(postId) ||\n Number.isNaN(answerId) ||\n !validateRequestBody(request.body)\n ) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response\n .status(404)\n .send({ errors: 'Post or answer not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaDeleteAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n // Act\n let deleted = false;\n if (answer.status === 'deleted' || request.body?.permanent === true) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(404)\n .send({ errors: 'Answer not found', type: 'query' });\n return;\n }\n deleted = await database.deleteAnswer(answerId, true);\n } else {\n deleted = await database.deleteAnswer(answerId);\n if (deleted) {\n notificationMgr.onAnswerDelete(\n username,\n post,\n answer,\n request.body.reason,\n );\n }\n }\n\n if (deleted) {\n signalPostStats(signals, post);\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer,\n author: username,\n reason: request.body.reason,\n },\n metadata: { action: 'delete_answer' },\n });\n auditor?.createEvent({\n eventId: 'delete-answer',\n severityLevel: 'medium',\n request,\n meta: {\n answer: entityToJsonObject(answer),\n post: entityToJsonObject(post),\n reason: request.body.reason,\n },\n });\n }\n\n // Response\n response.sendStatus(deleted ? 204 : 404);\n });\n\n const voteAnswer = async (\n request: Request<any>,\n response: Response,\n score: number,\n ) => {\n // Validation\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (answer === null || post === null) {\n response.sendStatus(404);\n return;\n }\n\n if (post.status === 'obsolete') {\n response\n .status(400)\n .send({ errors: 'Cannot vote on obsolete posts', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n if (answer.own) {\n response\n .status(400)\n .send({ errors: 'Cannot vote on own answer', type: 'body' });\n return;\n }\n\n // Act\n const voted = await database.voteAnswer(username, answerId, score);\n\n if (!voted) {\n response.sendStatus(404);\n return;\n }\n\n const resp = await database.getAnswer(answerId, username);\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer: resp,\n author: username,\n score,\n },\n metadata: { action: 'vote_answer' },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = score;\n\n auditor?.createEvent({\n eventId: 'vote',\n severityLevel: 'low',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n score,\n },\n });\n\n signalAnswerStats(signals, resp);\n\n // Response\n response.json(resp);\n };\n\n // GET /posts/:id/answers/:answerId/upvote\n router.get(\n `/posts/:id/answers/:answerId/upvote`,\n async (request, response) => {\n return await voteAnswer(request, response, 1);\n },\n );\n\n // GET /posts/:id/answers/:answerId/downvote\n router.get(\n `/posts/:id/answers/:answerId/downvote`,\n async (request, response) => {\n return await voteAnswer(request, response, -1);\n },\n );\n\n router.delete(\n '/posts/:id/answers/:answerId/vote',\n async (request, response) => {\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const username = await permissionMgr.getUsername(request);\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (answer === null || post === null) {\n response.sendStatus(404);\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n const deleted = await database.deleteAnswerVote(username, answerId);\n if (!deleted) {\n response.sendStatus(404);\n return;\n }\n\n const resp = await database.getAnswer(answerId, username);\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-vote',\n severityLevel: 'low',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = undefined;\n\n signalAnswerStats(signals, resp);\n\n // Response\n response.json(resp);\n },\n );\n\n // GET /posts/:id/answers/:answerId/correct\n router.get(\n `/posts/:id/answers/:answerId/correct`,\n async (request, response) => {\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n const previousCorrectAnswers = await database.getAnswers(\n username,\n { questionId: postId, limit: 1 },\n undefined,\n {\n correct: true,\n },\n );\n\n if (!post || !answer) {\n response\n .status(404)\n .send({ errors: 'Post or answer not found', type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot mark answers on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaEditPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ...previousCorrectAnswers.answers.map(a => ({\n permission: qetaReadAnswerPermission,\n resource: a,\n })),\n ],\n { throwOnDeny: true },\n );\n\n if (previousCorrectAnswers.answers.length > 0) {\n const previousCorrectAnswer = previousCorrectAnswers.answers[0];\n await database.markAnswerIncorrect(postId, previousCorrectAnswer.id);\n await signalAnswerStats(signals, {\n ...previousCorrectAnswer,\n correct: false,\n });\n }\n\n const marked = await database.markAnswerCorrect(postId, answerId);\n\n if (!marked) {\n response\n .status(404)\n .send({ errors: 'Failed to mark answer correct', type: 'body' });\n return;\n }\n\n wrapAsync(async () => {\n await notificationMgr.onCorrectAnswer(username, post, answer);\n });\n\n const updated = await database.getAnswer(answerId, username);\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer: updated,\n author: username,\n },\n metadata: { action: 'correct_answer' },\n });\n\n signalPostStats(signals, post);\n signalAnswerStats(signals, updated);\n\n auditor?.createEvent({\n eventId: 'correct-answer',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n\n response.sendStatus(200);\n },\n );\n\n // GET /posts/:id/answers/:answerId/incorrect\n router.get(\n `/posts/:id/answers/:answerId/incorrect`,\n async (request, response) => {\n const username = await permissionMgr.getUsername(request);\n const postId = Number.parseInt(request.params.id, 10);\n const answerId = Number.parseInt(request.params.answerId, 10);\n if (Number.isNaN(postId) || Number.isNaN(answerId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n const post = await database.getPost(username, postId, false);\n const answer = await database.getAnswer(answerId, username);\n\n if (!post || !answer) {\n response\n .status(404)\n .send({ errors: 'Post or answer not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaEditPostPermission, resource: post },\n { permission: qetaReadAnswerPermission, resource: answer },\n ],\n { throwOnDeny: true },\n );\n\n const marked = await database.markAnswerIncorrect(postId, answerId);\n\n if (marked) {\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n question: post,\n answer,\n author: username,\n },\n metadata: { action: 'incorrect_answer' },\n });\n auditor?.createEvent({\n eventId: 'incorrect-answer',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n answer: entityToJsonObject(answer),\n },\n });\n }\n\n response.sendStatus(marked ? 200 : 404);\n },\n );\n};\n"],"names":["Ajv","addFormats","AnswersQuerySchema","validateDateRange","qetaReadCommentPermission","qetaReadAnswerPermission","mapAdditionalFields","PostAnswerSchema","qetaReadPostPermission","qetaCreateAnswerPermission","getCreated","wrapAsync","findEntityMentions","signalPostStats","entityToJsonObject","qetaEditAnswerPermission","CommentSchema","qetaCreateCommentPermission","qetaEditCommentPermission","qetaDeleteCommentPermission","DeleteMetadataSchema","qetaDeleteAnswerPermission","signalAnswerStats","qetaEditPostPermission"],"mappings":"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"}
|
|
@@ -277,7 +277,9 @@ const postsRoutes = (router, options) => {
|
|
|
277
277
|
{ throwOnDeny: true }
|
|
278
278
|
);
|
|
279
279
|
await util$1.mapAdditionalFields(request, [post], options, { username });
|
|
280
|
-
|
|
280
|
+
if (!anonymous) {
|
|
281
|
+
util.signalPostStats(signals, post);
|
|
282
|
+
}
|
|
281
283
|
auditor?.createEvent({
|
|
282
284
|
eventId: "read-post",
|
|
283
285
|
severityLevel: "low",
|
|
@@ -839,9 +841,24 @@ const postsRoutes = (router, options) => {
|
|
|
839
841
|
});
|
|
840
842
|
router.put("/posts/:id/click", async (request, response) => {
|
|
841
843
|
const ret = await getPostAndCheckStatus(request, response);
|
|
842
|
-
if (!ret)
|
|
844
|
+
if (!ret) {
|
|
845
|
+
response.status(404).send({ errors: "Post not found", type: "query" });
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
843
848
|
const { postId, username } = ret;
|
|
844
849
|
await database.clickPost(username, postId);
|
|
850
|
+
const resp = await database.getPost(username, postId, false, {
|
|
851
|
+
includeComments: false,
|
|
852
|
+
includeAnswers: false,
|
|
853
|
+
includeAttachments: false,
|
|
854
|
+
includeTags: false,
|
|
855
|
+
includeEntities: false
|
|
856
|
+
});
|
|
857
|
+
if (!resp) {
|
|
858
|
+
response.status(404).send({ errors: "Post not found", type: "query" });
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
util.signalPostStats(signals, resp);
|
|
845
862
|
response.status(200).send({});
|
|
846
863
|
});
|
|
847
864
|
router.get(`/posts/:id/upvote`, async (request, response) => {
|
|
@@ -895,6 +912,7 @@ const postsRoutes = (router, options) => {
|
|
|
895
912
|
});
|
|
896
913
|
await util$1.mapAdditionalFields(request, [resp], options, { username });
|
|
897
914
|
resp.ownVote = void 0;
|
|
915
|
+
util.signalPostStats(signals, resp);
|
|
898
916
|
auditor?.createEvent({
|
|
899
917
|
eventId: "delete-vote",
|
|
900
918
|
severityLevel: "low",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posts.cjs.js","sources":["../../../src/service/routes/posts.ts"],"sourcesContent":["import { getCreated, mapAdditionalFields } from '../util';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\nimport Ajv from 'ajv';\nimport { Request, Router } from 'express';\nimport {\n findEntityMentions,\n PostsQuery,\n qetaCreateCommentPermission,\n qetaCreatePostPermission,\n qetaCreatePostReviewPermission,\n qetaDeleteCommentPermission,\n qetaDeletePostPermission,\n qetaEditCommentPermission,\n qetaEditPostPermission,\n qetaReadAnswerPermission,\n qetaReadCommentPermission,\n qetaReadPostPermission,\n qetaReadPostReviewPermission,\n qetaReadTagPermission,\n} from '@drodil/backstage-plugin-qeta-common';\nimport addFormats from 'ajv-formats';\nimport {\n CommentSchema,\n DeleteMetadataSchema,\n PostQuerySchema,\n PostReviewBodySchema,\n PostSchema,\n PostsQuerySchema,\n RouteOptions,\n URLMetadataSchema,\n} from '../types';\nimport { Response } from 'express-serve-static-core';\nimport {\n entityToJsonObject,\n extractMetadata,\n signalPostStats,\n validateDateRange,\n wrapAsync,\n} from './util';\nimport { getEntities, getTags } from './routeUtil';\nimport { PostOptions } from '../../database/QetaStore';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const postsRoutes = (router: Router, options: RouteOptions) => {\n const {\n database,\n events,\n config,\n cache,\n signals,\n notificationMgr,\n auditor,\n permissionMgr,\n } = options;\n\n const postsOlderThan = config.getOptional<HumanDuration>(\n 'qeta.contentHealth.postsOlderThan',\n ) ?? { months: 6 };\n const reviewThresholdMs = durationToMilliseconds(postsOlderThan);\n\n const getPostFilters = async (request: Request, opts: PostOptions) => {\n return await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadPostPermission, {\n allowServicePrincipal: true,\n }),\n opts.includeTags\n ? permissionMgr.getAuthorizeConditions(request, qetaReadTagPermission, {\n allowServicePrincipal: true,\n })\n : undefined,\n opts.includeComments\n ? permissionMgr.getAuthorizeConditions(\n request,\n qetaReadCommentPermission,\n { allowServicePrincipal: true },\n )\n : undefined,\n opts.includeAnswers\n ? permissionMgr.getAuthorizeConditions(\n request,\n qetaReadAnswerPermission,\n { allowServicePrincipal: true },\n )\n : undefined,\n ]);\n };\n\n const getPostAndCheckStatus = async (\n request: Request,\n response: Response,\n recordView?: boolean,\n allowServiceToken?: boolean,\n ) => {\n const username = await permissionMgr.getUsername(\n request,\n allowServiceToken,\n );\n const postId = Number.parseInt(request.params.id, 10);\n if (Number.isNaN(postId)) {\n response.status(400).send({ errors: 'Invalid post id', type: 'body' });\n return null;\n }\n\n const [tagsFilter, commentsFilter, answersFilter] = await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadTagPermission, {\n allowServicePrincipal: allowServiceToken,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadCommentPermission, {\n allowServicePrincipal: allowServiceToken,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadAnswerPermission, {\n allowServicePrincipal: allowServiceToken,\n }),\n ]);\n\n const post = await database.getPost(username, postId, recordView, {\n tagsFilter,\n commentsFilter,\n answersFilter,\n includeHealth: true,\n reviewThresholdMs,\n });\n\n if (!post) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return null;\n }\n\n if (\n post.status === 'deleted' &&\n !(await permissionMgr.isModerator(request))\n ) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return null;\n }\n\n if (post.status === 'draft' && post.author !== username) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return null;\n }\n\n return {\n post,\n username,\n postId,\n tagsFilter,\n commentsFilter,\n answersFilter,\n };\n };\n\n // GET /posts\n router.get(`/posts`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(PostsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const validDate = validateDateRange(\n request.query.fromDate as string,\n request.query.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const opts = request.query as PostsQuery;\n\n if (opts.reviewNeeded) {\n opts.obsolete = false;\n opts.includeHealth = true;\n }\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, opts);\n\n if (\n opts.status === 'deleted' &&\n !(await permissionMgr.isModerator(request))\n ) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n\n // Act\n const posts = await database.getPosts(username, opts, filter, {\n tagsFilter,\n commentsFilter,\n answersFilter,\n includeAnswers: false,\n includeComments: false,\n includeAttachments: false,\n includeExperts: false,\n includeHealth: opts.includeHealth,\n reviewThresholdMs,\n reviewNeeded: opts.reviewNeeded,\n });\n\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(posts);\n });\n\n router.post(`/posts/query`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(PostsQuerySchema);\n if (!validateQuery(request.body)) {\n response.status(400).send({ errors: validateQuery.errors, type: 'body' });\n return;\n }\n\n const validDate = validateDateRange(\n request.body.fromDate as string,\n request.body.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const opts = request.body;\n\n if (\n opts.status === 'deleted' &&\n !(await permissionMgr.isModerator(request))\n ) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, opts);\n\n if (opts.reviewNeeded) {\n opts.obsolete = false;\n opts.includeHealth = true;\n }\n\n // Act\n const posts = await database.getPosts(username, opts, filter, {\n tagsFilter,\n commentsFilter,\n answersFilter,\n includeAnswers: false,\n includeComments: false,\n includeAttachments: false,\n includeExperts: false,\n includeHealth: opts.includeHealth,\n reviewThresholdMs,\n reviewNeeded: opts.reviewNeeded,\n });\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(posts);\n });\n\n // POST /posts/suggest\n router.post(`/posts/suggest`, async (request, response) => {\n const username = await permissionMgr.getUsername(request, true);\n if (!request.body.title) {\n response.status(400).send({ errors: 'Title is required', type: 'body' });\n return;\n }\n\n const { title, content, tags, entities } = request.body;\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, {\n includeAnswers: true,\n includeComments: false,\n includeAttachments: false,\n includeExperts: false,\n });\n\n const posts = await database.suggestPosts(\n username,\n title,\n content,\n tags,\n entities,\n filter,\n { tagsFilter, commentsFilter, answersFilter },\n );\n\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: false,\n username,\n });\n response.json(posts);\n });\n\n // GET /posts/list/:type\n router.get(`/posts/list/:type`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(PostsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const optionOverride: PostsQuery = { status: 'active' };\n const type = request.params.type;\n if (type === 'unanswered') {\n optionOverride.random = true;\n optionOverride.noAnswers = true;\n } else if (type === 'incorrect') {\n optionOverride.noCorrectAnswer = true;\n optionOverride.random = true;\n } else if (type === 'hot') {\n optionOverride.includeTrend = true;\n optionOverride.orderBy = 'trend';\n } else if (type === 'own') {\n optionOverride.author = username;\n }\n const opts = { ...request.query, ...optionOverride };\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, opts);\n\n // Act\n const posts = await database.getPosts(username, opts, filter, {\n includeTotal: false,\n includeAnswers: false,\n includeAttachments: false,\n includeEntities: false,\n includeTags: false,\n includeVotes: false,\n includeExperts: false,\n includeComments: false,\n commentsFilter,\n tagsFilter,\n answersFilter,\n });\n\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(posts);\n });\n\n // GET /posts/:id\n router.get(`/posts/:id`, async (request, response) => {\n const validateQuery = ajv.compile(PostQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n const anonymous = request.query.anonymous as undefined | boolean;\n\n const ret = await getPostAndCheckStatus(\n request,\n response,\n anonymous ? !anonymous : true,\n true,\n );\n if (!ret) return;\n const { post, username } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n await mapAdditionalFields(request, [post], options, { username });\n signalPostStats(signals, post);\n\n auditor?.createEvent({\n eventId: 'read-post',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(post) },\n });\n\n response.json(post);\n });\n\n // POST /posts/:id/comments\n router.post(`/posts/:id/comments`, async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const { post, username, answersFilter, tagsFilter, commentsFilter } = ret;\n\n const created = await getCreated(request, options);\n const validateRequestBody = ajv.compile(CommentSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot add comments to obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaCreateCommentPermission },\n ],\n { throwOnDeny: true },\n );\n\n const updatedPost = await database.commentPost(\n post.id,\n username,\n request.body.content,\n created,\n { tagsFilter, commentsFilter, answersFilter },\n );\n\n if (updatedPost === null) {\n response\n .status(400)\n .send({ errors: 'Failed to comment post', type: 'body' });\n return;\n }\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n wrapAsync(async () => {\n if (!updatedPost || updatedPost.status !== 'active') {\n return;\n }\n const followingUsers = await Promise.all([\n database.getUsersForTags(updatedPost.tags),\n database.getUsersForEntities(updatedPost.entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(updatedPost.id),\n ]);\n\n const sent = await notificationMgr.onNewPostComment(\n username,\n updatedPost,\n request.body.content,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(request.body.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(\n username,\n updatedPost,\n mentions,\n sent,\n true,\n );\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post: updatedPost,\n comment: request.body.content,\n author: username,\n },\n metadata: { action: 'comment_post' },\n });\n\n auditor?.createEvent({\n eventId: 'comment-post',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(updatedPost),\n comment: request.body.content,\n },\n });\n\n response.status(201).json(updatedPost);\n });\n\n // POST /posts/:id/comments/:commentId\n router.post(`/posts/:id/comments/:commentId`, async (request, response) => {\n // Validation\n // Act\n const postId = Number.parseInt(request.params.id, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (Number.isNaN(postId) || Number.isNaN(commentId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const { post, username, answersFilter, commentsFilter, tagsFilter } = ret;\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot edit comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n const comment = await database.getComment(commentId, { postId });\n\n if (!comment) {\n response.status(404).send({ errors: 'Comment not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaEditCommentPermission, resource: comment }],\n { throwOnDeny: true },\n );\n\n const updatedPost = await database.updatePostComment(\n postId,\n commentId,\n username,\n request.body.content,\n {\n tagsFilter,\n commentsFilter,\n answersFilter,\n },\n );\n\n if (updatedPost === null) {\n response\n .status(400)\n .send({ errors: 'Failed to update post comment', type: 'body' });\n return;\n }\n\n auditor?.createEvent({\n eventId: 'update-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(updatedPost),\n from: entityToJsonObject(comment),\n to: request.body.content,\n },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // DELETE /posts/:id/comments/:commentId\n router.delete(`/posts/:id/comments/:commentId`, async (request, response) => {\n // Validation\n // Act\n const postId = Number.parseInt(request.params.id, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (Number.isNaN(postId) || Number.isNaN(commentId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const { post, username, answersFilter, tagsFilter, commentsFilter } = ret;\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot delete comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n const comment = await database.getComment(commentId, { postId });\n\n if (!comment) {\n response.status(404).send({ errors: 'Comment not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaDeleteCommentPermission, resource: comment }],\n { throwOnDeny: true },\n );\n\n let updatedPost = null;\n if (comment.status === 'deleted' || request.body?.permanent === true) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(404)\n .send({ errors: 'Comment not found', type: 'query' });\n return;\n }\n updatedPost = await database.deletePostComment(\n postId,\n commentId,\n username,\n true,\n {\n tagsFilter,\n commentsFilter,\n answersFilter,\n },\n );\n } else {\n updatedPost = await database.deletePostComment(\n postId,\n commentId,\n username,\n false,\n {\n tagsFilter,\n commentsFilter,\n answersFilter,\n },\n );\n }\n\n if (updatedPost === null) {\n response\n .status(400)\n .send({ errors: 'Failed to delete post comment', type: 'body' });\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(updatedPost),\n comment: entityToJsonObject(comment),\n },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // POST /posts\n router.post(`/posts`, async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(PostSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n await permissionMgr.authorize(\n request,\n [{ permission: qetaCreatePostPermission }],\n { throwOnDeny: true },\n );\n\n const existingTags = await database.getTags();\n const [tags, entities, username, created] = await Promise.all([\n getTags(request, options, existingTags),\n getEntities(request, config),\n permissionMgr.getUsername(request),\n getCreated(request, options),\n ]);\n\n if (request.body.author && request.body.author !== username) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n // Act\n const post = await database.createPost({\n user_ref: username,\n title: request.body.title,\n content: request.body.content,\n author: request.body.author,\n created,\n tags,\n entities,\n images: request.body.images,\n anonymous: request.body.anonymous || username === 'user:default/guest',\n type: request.body.type,\n headerImage: request.body.headerImage,\n url: request.body.url,\n status: request.body.status || 'active',\n opts: {\n includeComments: false,\n includeVotes: false,\n includeAnswers: false,\n },\n });\n\n if (!post) {\n response.status(400).send({ errors: 'Failed to post', type: 'body' });\n return;\n }\n\n wrapAsync(async () => {\n if (!post || post.status !== 'active') {\n return;\n }\n const followingUsers = await Promise.all([\n database.getUsersForTags(tags),\n database.getUsersForEntities(entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(post.id),\n ]);\n const sent = await notificationMgr.onNewPost(\n username,\n post,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(request.body.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(username, post, mentions, sent);\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'new_post' },\n });\n\n auditor?.createEvent({\n eventId: 'create-post',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n },\n });\n\n await mapAdditionalFields(request, [post], options, { username });\n\n // Response\n response.status(201).json(post);\n });\n\n // POST /posts/:id\n router.post(`/posts/:id`, async (request, response) => {\n // Validation\n\n const validateRequestBody = ajv.compile(PostSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const {\n post: originalPost,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaEditPostPermission, resource: originalPost }],\n { throwOnDeny: true },\n );\n\n if (request.body.status !== 'active' && originalPost.status === 'active') {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n if (\n request.body.author &&\n request.body.author !== username &&\n request.body.author !== originalPost.author\n ) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n const existingTags = await database.getTags();\n const [tags, entities] = await Promise.all([\n getTags(request, options, existingTags),\n getEntities(request, config),\n ]);\n\n // Act\n const post = await database.updatePost({\n id: postId,\n user_ref: username,\n author: request.body.author,\n title: request.body.title,\n content: request.body.content,\n tags,\n entities,\n images: request.body.images,\n headerImage: request.body.headerImage,\n url: request.body.url,\n status: request.body.status || 'active',\n setUpdatedBy: originalPost.status !== 'draft',\n opts: { tagsFilter, commentsFilter, answersFilter },\n });\n\n if (!post) {\n response.sendStatus(401);\n return;\n }\n\n wrapAsync(async () => {\n if (!post || post.status !== 'active') {\n return;\n }\n const newTags = tags.filter(t => !originalPost.tags?.includes(t));\n const newEntities = entities.filter(\n e => !originalPost.entities?.includes(e),\n );\n\n const followingUsers = await Promise.all([\n database.getUsersForTags(newTags),\n database.getUsersForEntities(newEntities),\n ]);\n\n const sent = await notificationMgr.onPostEdit(\n username,\n post,\n followingUsers.flat(),\n );\n const originalMentions = findEntityMentions(originalPost.content);\n const mentions = findEntityMentions(request.body.content);\n const newMentions = mentions.filter(m => !originalMentions.includes(m));\n\n if (newMentions.length > 0) {\n await notificationMgr.onMention(username, post, newMentions, sent);\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'update_post' },\n });\n\n await mapAdditionalFields(request, [post], options, { username });\n\n auditor?.createEvent({\n eventId: 'update-post',\n severityLevel: 'medium',\n request,\n meta: {\n from: entityToJsonObject(originalPost),\n to: entityToJsonObject(post),\n },\n });\n\n // Response\n response.json(post);\n });\n\n // DELETE /posts/:id\n router.delete('/posts/:id', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const validateRequestBody = ajv.compile(DeleteMetadataSchema);\n if (!validateRequestBody(request.body)) {\n response.status(400).send({ errors: 'Invalid data', type: 'body' });\n return;\n }\n\n const { post, username } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaDeletePostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n let deleted = false;\n if (post.status === 'deleted' || request.body?.permanent === true) {\n if (!(await permissionMgr.isModerator(request))) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n deleted = await database.deletePost(post.id, true);\n } else {\n deleted = await database.deletePost(post.id);\n if (deleted) {\n notificationMgr.onPostDelete(username, post, request.body.reason);\n }\n }\n\n if (deleted) {\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: post.author,\n reason: request.body.reason,\n },\n metadata: { action: 'delete_post' },\n });\n\n auditor?.createEvent({\n eventId: 'delete-post',\n severityLevel: 'medium',\n request,\n meta: { post: entityToJsonObject(post), reason: request.body.reason },\n });\n }\n\n response.sendStatus(deleted ? 204 : 404);\n });\n\n const votePost = async (\n request: Request<any>,\n response: Response,\n score: number,\n ) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n if (post.own) {\n response\n .status(400)\n .send({ errors: 'You cannot vote your own post', type: 'body' });\n return;\n }\n\n const voted = await database.votePost(username, postId, score);\n\n if (!voted) {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n const resp = await database.getPost(username, postId, false, {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeAttachments: false,\n includeTags: false,\n includeEntities: false,\n });\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n resp,\n author: username,\n score,\n },\n metadata: { action: 'vote_post' },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = score;\n\n auditor?.createEvent({\n eventId: 'vote',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(post), score },\n });\n\n signalPostStats(signals, resp);\n\n // Response\n response.json(resp);\n };\n\n // POST /posts/:id/restore\n router.post('/posts/:id/restore', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n\n if (!(await permissionMgr.isModerator(request))) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n const {\n post: originalPost,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n // Act\n const post = await database.updatePost({\n id: postId,\n status: 'active',\n user_ref: username,\n setUpdatedBy: false,\n opts: { tagsFilter, commentsFilter, answersFilter },\n });\n\n if (!post) {\n response.sendStatus(401);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'restore_post' },\n });\n\n await mapAdditionalFields(request, [post], options, { username });\n\n auditor?.createEvent({\n eventId: 'restore-post',\n severityLevel: 'medium',\n request,\n meta: {\n from: entityToJsonObject(originalPost),\n to: entityToJsonObject(post),\n },\n });\n\n // Response\n response.json(post);\n });\n\n // PUT /posts/:id/click\n router.put('/posts/:id/click', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const { postId, username } = ret;\n await database.clickPost(username, postId);\n response.status(200).send({});\n });\n\n // GET /posts/:id/upvote\n router.get(`/posts/:id/upvote`, async (request, response) => {\n return await votePost(request, response, 1);\n });\n\n // GET /posts/:id/downvote\n router.get(`/posts/:id/downvote`, async (request, response) => {\n return await votePost(request, response, -1);\n });\n\n router.delete('/posts/:id/vote', async (request, response) => {\n // Validation\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n const deleted = await database.deletePostVote(username, postId);\n if (!deleted) {\n response.sendStatus(404);\n return;\n }\n\n const resp = await database.getPost(username, postId, false, {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeAttachments: false,\n includeTags: false,\n includeEntities: false,\n });\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'delete_vote' },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = undefined;\n\n auditor?.createEvent({\n eventId: 'delete-vote',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(post) },\n });\n response.json(resp);\n });\n\n // POST /posts/:id/review\n router.post('/posts/:id/review', async (request, response) => {\n const validateRequestBody = ajv.compile(PostReviewBodySchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const { post, postId } = ret;\n\n const user = await options.permissionMgr.getUsername(request, true);\n\n await options.permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaCreatePostReviewPermission },\n ],\n { throwOnDeny: true },\n );\n\n const updatedPost = await options.database.reviewPost(\n user,\n postId,\n request.body.status,\n request.body.comment,\n );\n if (!updatedPost) {\n response.sendStatus(404);\n return;\n }\n response.json(updatedPost);\n });\n\n // GET /posts/:id/reviews\n router.get('/posts/:id/reviews', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const { post, postId } = ret;\n\n await options.permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadPostReviewPermission },\n ],\n { throwOnDeny: true },\n );\n\n const reviews = await options.database.getPostReviews(postId);\n response.json(reviews);\n });\n\n // GET /posts/:id/favorite\n router.get(`/posts/:id/favorite`, async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n const favorited = await database.favoritePost(username, postId);\n\n if (!favorited) {\n response.sendStatus(404);\n return;\n }\n\n const updatedPost = await database.getPost(\n username,\n Number.parseInt(request.params.id, 10),\n false,\n {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeEntities: false,\n includeVotes: false,\n includeTags: false,\n includeAttachments: false,\n },\n );\n\n if (!updatedPost) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'favorite-post',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(updatedPost) },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // GET /posts/:id/unfavorite\n router.get(`/posts/:id/unfavorite`, async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n const unfavorited = await database.unfavoritePost(username, postId);\n\n if (!unfavorited) {\n response.sendStatus(404);\n return;\n }\n\n const updatedPost = await database.getPost(\n username,\n Number.parseInt(request.params.id, 10),\n false,\n {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeEntities: false,\n includeVotes: false,\n includeTags: false,\n includeAttachments: false,\n },\n );\n\n if (!updatedPost) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'unfavorite-post',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(updatedPost) },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // POST /url\n router.post(`/url`, async (request, response) => {\n const validateQuery = ajv.compile(URLMetadataSchema);\n if (!validateQuery(request.body)) {\n response.status(400).send({ errors: validateQuery.errors, type: 'body' });\n return;\n }\n\n const url = new URL(request.body.url);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n response\n .status(400)\n .send({ errors: 'Invalid URL protocol', type: 'url' });\n return;\n }\n if (url.hostname === 'localhost') {\n response\n .status(400)\n .send({ errors: 'localhost not allowed', type: 'url' });\n return;\n }\n\n const cacheKey = `url:metadata:${url.toString()}`;\n const cached = await cache?.get(cacheKey);\n if (cached) {\n response.json(cached);\n return;\n }\n\n const metadata = await extractMetadata(url, options.logger);\n await cache?.set(cacheKey, metadata, { ttl: { weeks: 2 } });\n response.json(metadata);\n });\n};\n"],"names":["Ajv","addFormats","durationToMilliseconds","qetaReadPostPermission","qetaReadTagPermission","qetaReadCommentPermission","qetaReadAnswerPermission","PostsQuerySchema","validateDateRange","mapAdditionalFields","PostQuerySchema","signalPostStats","entityToJsonObject","getCreated","CommentSchema","qetaCreateCommentPermission","wrapAsync","findEntityMentions","qetaEditCommentPermission","qetaDeleteCommentPermission","PostSchema","qetaCreatePostPermission","getTags","getEntities","qetaEditPostPermission","DeleteMetadataSchema","qetaDeletePostPermission","PostReviewBodySchema","qetaCreatePostReviewPermission","qetaReadPostReviewPermission","URLMetadataSchema","extractMetadata"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"posts.cjs.js","sources":["../../../src/service/routes/posts.ts"],"sourcesContent":["import { getCreated, mapAdditionalFields } from '../util';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\nimport Ajv from 'ajv';\nimport { Request, Router } from 'express';\nimport {\n findEntityMentions,\n PostsQuery,\n qetaCreateCommentPermission,\n qetaCreatePostPermission,\n qetaCreatePostReviewPermission,\n qetaDeleteCommentPermission,\n qetaDeletePostPermission,\n qetaEditCommentPermission,\n qetaEditPostPermission,\n qetaReadAnswerPermission,\n qetaReadCommentPermission,\n qetaReadPostPermission,\n qetaReadPostReviewPermission,\n qetaReadTagPermission,\n} from '@drodil/backstage-plugin-qeta-common';\nimport addFormats from 'ajv-formats';\nimport {\n CommentSchema,\n DeleteMetadataSchema,\n PostQuerySchema,\n PostReviewBodySchema,\n PostSchema,\n PostsQuerySchema,\n RouteOptions,\n URLMetadataSchema,\n} from '../types';\nimport { Response } from 'express-serve-static-core';\nimport {\n entityToJsonObject,\n extractMetadata,\n signalPostStats,\n validateDateRange,\n wrapAsync,\n} from './util';\nimport { getEntities, getTags } from './routeUtil';\nimport { PostOptions } from '../../database/QetaStore';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const postsRoutes = (router: Router, options: RouteOptions) => {\n const {\n database,\n events,\n config,\n cache,\n signals,\n notificationMgr,\n auditor,\n permissionMgr,\n } = options;\n\n const postsOlderThan = config.getOptional<HumanDuration>(\n 'qeta.contentHealth.postsOlderThan',\n ) ?? { months: 6 };\n const reviewThresholdMs = durationToMilliseconds(postsOlderThan);\n\n const getPostFilters = async (request: Request, opts: PostOptions) => {\n return await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadPostPermission, {\n allowServicePrincipal: true,\n }),\n opts.includeTags\n ? permissionMgr.getAuthorizeConditions(request, qetaReadTagPermission, {\n allowServicePrincipal: true,\n })\n : undefined,\n opts.includeComments\n ? permissionMgr.getAuthorizeConditions(\n request,\n qetaReadCommentPermission,\n { allowServicePrincipal: true },\n )\n : undefined,\n opts.includeAnswers\n ? permissionMgr.getAuthorizeConditions(\n request,\n qetaReadAnswerPermission,\n { allowServicePrincipal: true },\n )\n : undefined,\n ]);\n };\n\n const getPostAndCheckStatus = async (\n request: Request,\n response: Response,\n recordView?: boolean,\n allowServiceToken?: boolean,\n ) => {\n const username = await permissionMgr.getUsername(\n request,\n allowServiceToken,\n );\n const postId = Number.parseInt(request.params.id, 10);\n if (Number.isNaN(postId)) {\n response.status(400).send({ errors: 'Invalid post id', type: 'body' });\n return null;\n }\n\n const [tagsFilter, commentsFilter, answersFilter] = await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadTagPermission, {\n allowServicePrincipal: allowServiceToken,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadCommentPermission, {\n allowServicePrincipal: allowServiceToken,\n }),\n permissionMgr.getAuthorizeConditions(request, qetaReadAnswerPermission, {\n allowServicePrincipal: allowServiceToken,\n }),\n ]);\n\n const post = await database.getPost(username, postId, recordView, {\n tagsFilter,\n commentsFilter,\n answersFilter,\n includeHealth: true,\n reviewThresholdMs,\n });\n\n if (!post) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return null;\n }\n\n if (\n post.status === 'deleted' &&\n !(await permissionMgr.isModerator(request))\n ) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return null;\n }\n\n if (post.status === 'draft' && post.author !== username) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return null;\n }\n\n return {\n post,\n username,\n postId,\n tagsFilter,\n commentsFilter,\n answersFilter,\n };\n };\n\n // GET /posts\n router.get(`/posts`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(PostsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const validDate = validateDateRange(\n request.query.fromDate as string,\n request.query.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const opts = request.query as PostsQuery;\n\n if (opts.reviewNeeded) {\n opts.obsolete = false;\n opts.includeHealth = true;\n }\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, opts);\n\n if (\n opts.status === 'deleted' &&\n !(await permissionMgr.isModerator(request))\n ) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n\n // Act\n const posts = await database.getPosts(username, opts, filter, {\n tagsFilter,\n commentsFilter,\n answersFilter,\n includeAnswers: false,\n includeComments: false,\n includeAttachments: false,\n includeExperts: false,\n includeHealth: opts.includeHealth,\n reviewThresholdMs,\n reviewNeeded: opts.reviewNeeded,\n });\n\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(posts);\n });\n\n router.post(`/posts/query`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(PostsQuerySchema);\n if (!validateQuery(request.body)) {\n response.status(400).send({ errors: validateQuery.errors, type: 'body' });\n return;\n }\n\n const validDate = validateDateRange(\n request.body.fromDate as string,\n request.body.toDate as string,\n );\n if (!validDate?.isValid) {\n response.status(400).send(validDate);\n return;\n }\n\n const opts = request.body;\n\n if (\n opts.status === 'deleted' &&\n !(await permissionMgr.isModerator(request))\n ) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, opts);\n\n if (opts.reviewNeeded) {\n opts.obsolete = false;\n opts.includeHealth = true;\n }\n\n // Act\n const posts = await database.getPosts(username, opts, filter, {\n tagsFilter,\n commentsFilter,\n answersFilter,\n includeAnswers: false,\n includeComments: false,\n includeAttachments: false,\n includeExperts: false,\n includeHealth: opts.includeHealth,\n reviewThresholdMs,\n reviewNeeded: opts.reviewNeeded,\n });\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(posts);\n });\n\n // POST /posts/suggest\n router.post(`/posts/suggest`, async (request, response) => {\n const username = await permissionMgr.getUsername(request, true);\n if (!request.body.title) {\n response.status(400).send({ errors: 'Title is required', type: 'body' });\n return;\n }\n\n const { title, content, tags, entities } = request.body;\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, {\n includeAnswers: true,\n includeComments: false,\n includeAttachments: false,\n includeExperts: false,\n });\n\n const posts = await database.suggestPosts(\n username,\n title,\n content,\n tags,\n entities,\n filter,\n { tagsFilter, commentsFilter, answersFilter },\n );\n\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: false,\n username,\n });\n response.json(posts);\n });\n\n // GET /posts/list/:type\n router.get(`/posts/list/:type`, async (request, response) => {\n // Validation\n const username = await permissionMgr.getUsername(request, true);\n const validateQuery = ajv.compile(PostsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const optionOverride: PostsQuery = { status: 'active' };\n const type = request.params.type;\n if (type === 'unanswered') {\n optionOverride.random = true;\n optionOverride.noAnswers = true;\n } else if (type === 'incorrect') {\n optionOverride.noCorrectAnswer = true;\n optionOverride.random = true;\n } else if (type === 'hot') {\n optionOverride.includeTrend = true;\n optionOverride.orderBy = 'trend';\n } else if (type === 'own') {\n optionOverride.author = username;\n }\n const opts = { ...request.query, ...optionOverride };\n\n const [filter, tagsFilter, commentsFilter, answersFilter] =\n await getPostFilters(request, opts);\n\n // Act\n const posts = await database.getPosts(username, opts, filter, {\n includeTotal: false,\n includeAnswers: false,\n includeAttachments: false,\n includeEntities: false,\n includeTags: false,\n includeVotes: false,\n includeExperts: false,\n includeComments: false,\n commentsFilter,\n tagsFilter,\n answersFilter,\n });\n\n await mapAdditionalFields(request, posts.posts, options, {\n checkRights: opts.checkAccess ?? false,\n username,\n });\n response.json(posts);\n });\n\n // GET /posts/:id\n router.get(`/posts/:id`, async (request, response) => {\n const validateQuery = ajv.compile(PostQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n const anonymous = request.query.anonymous as undefined | boolean;\n\n const ret = await getPostAndCheckStatus(\n request,\n response,\n anonymous ? !anonymous : true,\n true,\n );\n if (!ret) return;\n const { post, username } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n await mapAdditionalFields(request, [post], options, { username });\n if (!anonymous) {\n signalPostStats(signals, post);\n }\n\n auditor?.createEvent({\n eventId: 'read-post',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(post) },\n });\n\n response.json(post);\n });\n\n // POST /posts/:id/comments\n router.post(`/posts/:id/comments`, async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const { post, username, answersFilter, tagsFilter, commentsFilter } = ret;\n\n const created = await getCreated(request, options);\n const validateRequestBody = ajv.compile(CommentSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .send({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot add comments to obsolete posts',\n type: 'body',\n });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaCreateCommentPermission },\n ],\n { throwOnDeny: true },\n );\n\n const updatedPost = await database.commentPost(\n post.id,\n username,\n request.body.content,\n created,\n { tagsFilter, commentsFilter, answersFilter },\n );\n\n if (updatedPost === null) {\n response\n .status(400)\n .send({ errors: 'Failed to comment post', type: 'body' });\n return;\n }\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n wrapAsync(async () => {\n if (!updatedPost || updatedPost.status !== 'active') {\n return;\n }\n const followingUsers = await Promise.all([\n database.getUsersForTags(updatedPost.tags),\n database.getUsersForEntities(updatedPost.entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(updatedPost.id),\n ]);\n\n const sent = await notificationMgr.onNewPostComment(\n username,\n updatedPost,\n request.body.content,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(request.body.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(\n username,\n updatedPost,\n mentions,\n sent,\n true,\n );\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post: updatedPost,\n comment: request.body.content,\n author: username,\n },\n metadata: { action: 'comment_post' },\n });\n\n auditor?.createEvent({\n eventId: 'comment-post',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(updatedPost),\n comment: request.body.content,\n },\n });\n\n response.status(201).json(updatedPost);\n });\n\n // POST /posts/:id/comments/:commentId\n router.post(`/posts/:id/comments/:commentId`, async (request, response) => {\n // Validation\n // Act\n const postId = Number.parseInt(request.params.id, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (Number.isNaN(postId) || Number.isNaN(commentId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const { post, username, answersFilter, commentsFilter, tagsFilter } = ret;\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot edit comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n const comment = await database.getComment(commentId, { postId });\n\n if (!comment) {\n response.status(404).send({ errors: 'Comment not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaEditCommentPermission, resource: comment }],\n { throwOnDeny: true },\n );\n\n const updatedPost = await database.updatePostComment(\n postId,\n commentId,\n username,\n request.body.content,\n {\n tagsFilter,\n commentsFilter,\n answersFilter,\n },\n );\n\n if (updatedPost === null) {\n response\n .status(400)\n .send({ errors: 'Failed to update post comment', type: 'body' });\n return;\n }\n\n auditor?.createEvent({\n eventId: 'update-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(updatedPost),\n from: entityToJsonObject(comment),\n to: request.body.content,\n },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // DELETE /posts/:id/comments/:commentId\n router.delete(`/posts/:id/comments/:commentId`, async (request, response) => {\n // Validation\n // Act\n const postId = Number.parseInt(request.params.id, 10);\n const commentId = Number.parseInt(request.params.commentId, 10);\n if (Number.isNaN(postId) || Number.isNaN(commentId)) {\n response.status(400).send({ errors: 'Invalid id', type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const { post, username, answersFilter, tagsFilter, commentsFilter } = ret;\n\n if (post.status === 'obsolete') {\n response.status(400).send({\n errors: 'Cannot delete comments on obsolete posts',\n type: 'body',\n });\n return;\n }\n\n const comment = await database.getComment(commentId, { postId });\n\n if (!comment) {\n response.status(404).send({ errors: 'Comment not found', type: 'body' });\n return;\n }\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaDeleteCommentPermission, resource: comment }],\n { throwOnDeny: true },\n );\n\n let updatedPost = null;\n if (comment.status === 'deleted' || request.body?.permanent === true) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(404)\n .send({ errors: 'Comment not found', type: 'query' });\n return;\n }\n updatedPost = await database.deletePostComment(\n postId,\n commentId,\n username,\n true,\n {\n tagsFilter,\n commentsFilter,\n answersFilter,\n },\n );\n } else {\n updatedPost = await database.deletePostComment(\n postId,\n commentId,\n username,\n false,\n {\n tagsFilter,\n commentsFilter,\n answersFilter,\n },\n );\n }\n\n if (updatedPost === null) {\n response\n .status(400)\n .send({ errors: 'Failed to delete post comment', type: 'body' });\n return;\n }\n\n auditor?.createEvent({\n eventId: 'delete-comment',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(updatedPost),\n comment: entityToJsonObject(comment),\n },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // POST /posts\n router.post(`/posts`, async (request, response) => {\n // Validation\n const validateRequestBody = ajv.compile(PostSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n await permissionMgr.authorize(\n request,\n [{ permission: qetaCreatePostPermission }],\n { throwOnDeny: true },\n );\n\n const existingTags = await database.getTags();\n const [tags, entities, username, created] = await Promise.all([\n getTags(request, options, existingTags),\n getEntities(request, config),\n permissionMgr.getUsername(request),\n getCreated(request, options),\n ]);\n\n if (request.body.author && request.body.author !== username) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n // Act\n const post = await database.createPost({\n user_ref: username,\n title: request.body.title,\n content: request.body.content,\n author: request.body.author,\n created,\n tags,\n entities,\n images: request.body.images,\n anonymous: request.body.anonymous || username === 'user:default/guest',\n type: request.body.type,\n headerImage: request.body.headerImage,\n url: request.body.url,\n status: request.body.status || 'active',\n opts: {\n includeComments: false,\n includeVotes: false,\n includeAnswers: false,\n },\n });\n\n if (!post) {\n response.status(400).send({ errors: 'Failed to post', type: 'body' });\n return;\n }\n\n wrapAsync(async () => {\n if (!post || post.status !== 'active') {\n return;\n }\n const followingUsers = await Promise.all([\n database.getUsersForTags(tags),\n database.getUsersForEntities(entities),\n database.getFollowingUsers(username),\n database.getUsersWhoFavoritedPost(post.id),\n ]);\n const sent = await notificationMgr.onNewPost(\n username,\n post,\n followingUsers.flat(),\n );\n const mentions = findEntityMentions(request.body.content);\n if (mentions.length > 0) {\n await notificationMgr.onMention(username, post, mentions, sent);\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'new_post' },\n });\n\n auditor?.createEvent({\n eventId: 'create-post',\n severityLevel: 'medium',\n request,\n meta: {\n post: entityToJsonObject(post),\n },\n });\n\n await mapAdditionalFields(request, [post], options, { username });\n\n // Response\n response.status(201).json(post);\n });\n\n // POST /posts/:id\n router.post(`/posts/:id`, async (request, response) => {\n // Validation\n\n const validateRequestBody = ajv.compile(PostSchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const {\n post: originalPost,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaEditPostPermission, resource: originalPost }],\n { throwOnDeny: true },\n );\n\n if (request.body.status !== 'active' && originalPost.status === 'active') {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n if (\n request.body.author &&\n request.body.author !== username &&\n request.body.author !== originalPost.author\n ) {\n if (!(await permissionMgr.isModerator(request))) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n }\n\n const existingTags = await database.getTags();\n const [tags, entities] = await Promise.all([\n getTags(request, options, existingTags),\n getEntities(request, config),\n ]);\n\n // Act\n const post = await database.updatePost({\n id: postId,\n user_ref: username,\n author: request.body.author,\n title: request.body.title,\n content: request.body.content,\n tags,\n entities,\n images: request.body.images,\n headerImage: request.body.headerImage,\n url: request.body.url,\n status: request.body.status || 'active',\n setUpdatedBy: originalPost.status !== 'draft',\n opts: { tagsFilter, commentsFilter, answersFilter },\n });\n\n if (!post) {\n response.sendStatus(401);\n return;\n }\n\n wrapAsync(async () => {\n if (!post || post.status !== 'active') {\n return;\n }\n const newTags = tags.filter(t => !originalPost.tags?.includes(t));\n const newEntities = entities.filter(\n e => !originalPost.entities?.includes(e),\n );\n\n const followingUsers = await Promise.all([\n database.getUsersForTags(newTags),\n database.getUsersForEntities(newEntities),\n ]);\n\n const sent = await notificationMgr.onPostEdit(\n username,\n post,\n followingUsers.flat(),\n );\n const originalMentions = findEntityMentions(originalPost.content);\n const mentions = findEntityMentions(request.body.content);\n const newMentions = mentions.filter(m => !originalMentions.includes(m));\n\n if (newMentions.length > 0) {\n await notificationMgr.onMention(username, post, newMentions, sent);\n }\n });\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'update_post' },\n });\n\n await mapAdditionalFields(request, [post], options, { username });\n\n auditor?.createEvent({\n eventId: 'update-post',\n severityLevel: 'medium',\n request,\n meta: {\n from: entityToJsonObject(originalPost),\n to: entityToJsonObject(post),\n },\n });\n\n // Response\n response.json(post);\n });\n\n // DELETE /posts/:id\n router.delete('/posts/:id', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n const validateRequestBody = ajv.compile(DeleteMetadataSchema);\n if (!validateRequestBody(request.body)) {\n response.status(400).send({ errors: 'Invalid data', type: 'body' });\n return;\n }\n\n const { post, username } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaDeletePostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n let deleted = false;\n if (post.status === 'deleted' || request.body?.permanent === true) {\n if (!(await permissionMgr.isModerator(request))) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n deleted = await database.deletePost(post.id, true);\n } else {\n deleted = await database.deletePost(post.id);\n if (deleted) {\n notificationMgr.onPostDelete(username, post, request.body.reason);\n }\n }\n\n if (deleted) {\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: post.author,\n reason: request.body.reason,\n },\n metadata: { action: 'delete_post' },\n });\n\n auditor?.createEvent({\n eventId: 'delete-post',\n severityLevel: 'medium',\n request,\n meta: { post: entityToJsonObject(post), reason: request.body.reason },\n });\n }\n\n response.sendStatus(deleted ? 204 : 404);\n });\n\n const votePost = async (\n request: Request<any>,\n response: Response,\n score: number,\n ) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n if (post.own) {\n response\n .status(400)\n .send({ errors: 'You cannot vote your own post', type: 'body' });\n return;\n }\n\n const voted = await database.votePost(username, postId, score);\n\n if (!voted) {\n response.status(404).send({ errors: 'Post not found', type: 'body' });\n return;\n }\n\n const resp = await database.getPost(username, postId, false, {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeAttachments: false,\n includeTags: false,\n includeEntities: false,\n });\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n resp,\n author: username,\n score,\n },\n metadata: { action: 'vote_post' },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = score;\n\n auditor?.createEvent({\n eventId: 'vote',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(post), score },\n });\n\n signalPostStats(signals, resp);\n\n // Response\n response.json(resp);\n };\n\n // POST /posts/:id/restore\n router.post('/posts/:id/restore', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response, false, true);\n if (!ret) return;\n\n if (!(await permissionMgr.isModerator(request))) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n const {\n post: originalPost,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n // Act\n const post = await database.updatePost({\n id: postId,\n status: 'active',\n user_ref: username,\n setUpdatedBy: false,\n opts: { tagsFilter, commentsFilter, answersFilter },\n });\n\n if (!post) {\n response.sendStatus(401);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'restore_post' },\n });\n\n await mapAdditionalFields(request, [post], options, { username });\n\n auditor?.createEvent({\n eventId: 'restore-post',\n severityLevel: 'medium',\n request,\n meta: {\n from: entityToJsonObject(originalPost),\n to: entityToJsonObject(post),\n },\n });\n\n // Response\n response.json(post);\n });\n\n // PUT /posts/:id/click\n router.put('/posts/:id/click', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n const { postId, username } = ret;\n await database.clickPost(username, postId);\n\n const resp = await database.getPost(username, postId, false, {\n includeComments: false,\n includeAnswers: false,\n includeAttachments: false,\n includeTags: false,\n includeEntities: false,\n });\n\n if (!resp) {\n response.status(404).send({ errors: 'Post not found', type: 'query' });\n return;\n }\n\n signalPostStats(signals, resp);\n response.status(200).send({});\n });\n\n // GET /posts/:id/upvote\n router.get(`/posts/:id/upvote`, async (request, response) => {\n return await votePost(request, response, 1);\n });\n\n // GET /posts/:id/downvote\n router.get(`/posts/:id/downvote`, async (request, response) => {\n return await votePost(request, response, -1);\n });\n\n router.delete('/posts/:id/vote', async (request, response) => {\n // Validation\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n const deleted = await database.deletePostVote(username, postId);\n if (!deleted) {\n response.sendStatus(404);\n return;\n }\n\n const resp = await database.getPost(username, postId, false, {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeAttachments: false,\n includeTags: false,\n includeEntities: false,\n });\n\n if (resp === null) {\n response.sendStatus(404);\n return;\n }\n\n events?.publish({\n topic: 'qeta',\n eventPayload: {\n post,\n author: username,\n },\n metadata: { action: 'delete_vote' },\n });\n\n await mapAdditionalFields(request, [resp], options, { username });\n resp.ownVote = undefined;\n\n signalPostStats(signals, resp);\n\n auditor?.createEvent({\n eventId: 'delete-vote',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(post) },\n });\n response.json(resp);\n });\n\n // POST /posts/:id/review\n router.post('/posts/:id/review', async (request, response) => {\n const validateRequestBody = ajv.compile(PostReviewBodySchema);\n if (!validateRequestBody(request.body)) {\n response\n .status(400)\n .json({ errors: validateRequestBody.errors, type: 'body' });\n return;\n }\n\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const { post, postId } = ret;\n\n const user = await options.permissionMgr.getUsername(request, true);\n\n await options.permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaCreatePostReviewPermission },\n ],\n { throwOnDeny: true },\n );\n\n const updatedPost = await options.database.reviewPost(\n user,\n postId,\n request.body.status,\n request.body.comment,\n );\n if (!updatedPost) {\n response.sendStatus(404);\n return;\n }\n response.json(updatedPost);\n });\n\n // GET /posts/:id/reviews\n router.get('/posts/:id/reviews', async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const { post, postId } = ret;\n\n await options.permissionMgr.authorize(\n request,\n [\n { permission: qetaReadPostPermission, resource: post },\n { permission: qetaReadPostReviewPermission },\n ],\n { throwOnDeny: true },\n );\n\n const reviews = await options.database.getPostReviews(postId);\n response.json(reviews);\n });\n\n // GET /posts/:id/favorite\n router.get(`/posts/:id/favorite`, async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n const favorited = await database.favoritePost(username, postId);\n\n if (!favorited) {\n response.sendStatus(404);\n return;\n }\n\n const updatedPost = await database.getPost(\n username,\n Number.parseInt(request.params.id, 10),\n false,\n {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeEntities: false,\n includeVotes: false,\n includeTags: false,\n includeAttachments: false,\n },\n );\n\n if (!updatedPost) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'favorite-post',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(updatedPost) },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // GET /posts/:id/unfavorite\n router.get(`/posts/:id/unfavorite`, async (request, response) => {\n const ret = await getPostAndCheckStatus(request, response);\n if (!ret) return;\n const {\n post,\n postId,\n username,\n answersFilter,\n tagsFilter,\n commentsFilter,\n } = ret;\n\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadPostPermission, resource: post }],\n { throwOnDeny: true },\n );\n\n const unfavorited = await database.unfavoritePost(username, postId);\n\n if (!unfavorited) {\n response.sendStatus(404);\n return;\n }\n\n const updatedPost = await database.getPost(\n username,\n Number.parseInt(request.params.id, 10),\n false,\n {\n answersFilter,\n tagsFilter,\n commentsFilter,\n includeComments: false,\n includeAnswers: false,\n includeEntities: false,\n includeVotes: false,\n includeTags: false,\n includeAttachments: false,\n },\n );\n\n if (!updatedPost) {\n response.sendStatus(404);\n return;\n }\n\n auditor?.createEvent({\n eventId: 'unfavorite-post',\n severityLevel: 'low',\n request,\n meta: { post: entityToJsonObject(updatedPost) },\n });\n\n await mapAdditionalFields(request, [updatedPost], options, { username });\n\n // Response\n response.json(updatedPost);\n });\n\n // POST /url\n router.post(`/url`, async (request, response) => {\n const validateQuery = ajv.compile(URLMetadataSchema);\n if (!validateQuery(request.body)) {\n response.status(400).send({ errors: validateQuery.errors, type: 'body' });\n return;\n }\n\n const url = new URL(request.body.url);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n response\n .status(400)\n .send({ errors: 'Invalid URL protocol', type: 'url' });\n return;\n }\n if (url.hostname === 'localhost') {\n response\n .status(400)\n .send({ errors: 'localhost not allowed', type: 'url' });\n return;\n }\n\n const cacheKey = `url:metadata:${url.toString()}`;\n const cached = await cache?.get(cacheKey);\n if (cached) {\n response.json(cached);\n return;\n }\n\n const metadata = await extractMetadata(url, options.logger);\n await cache?.set(cacheKey, metadata, { ttl: { weeks: 2 } });\n response.json(metadata);\n });\n};\n"],"names":["Ajv","addFormats","durationToMilliseconds","qetaReadPostPermission","qetaReadTagPermission","qetaReadCommentPermission","qetaReadAnswerPermission","PostsQuerySchema","validateDateRange","mapAdditionalFields","PostQuerySchema","signalPostStats","entityToJsonObject","getCreated","CommentSchema","qetaCreateCommentPermission","wrapAsync","findEntityMentions","qetaEditCommentPermission","qetaDeleteCommentPermission","PostSchema","qetaCreatePostPermission","getTags","getEntities","qetaEditPostPermission","DeleteMetadataSchema","qetaDeletePostPermission","PostReviewBodySchema","qetaCreatePostReviewPermission","qetaReadPostReviewPermission","URLMetadataSchema","extractMetadata"],"mappings":"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"}
|
package/dist/service/util.cjs.js
CHANGED
|
@@ -217,7 +217,7 @@ const mapPostAnswers = async (request, resource, permissionMgr, credentials, use
|
|
|
217
217
|
return {
|
|
218
218
|
...a,
|
|
219
219
|
ownVote: a.votes?.find((v) => v.author === username)?.score,
|
|
220
|
-
own:
|
|
220
|
+
own: a.author === username,
|
|
221
221
|
canEdit,
|
|
222
222
|
canDelete,
|
|
223
223
|
expert: a.experts?.includes(resource.author),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.cjs.js","sources":["../../src/service/util.ts"],"sourcesContent":["import { Request } from 'express';\nimport { format, subDays } from 'date-fns';\nimport {\n isAnswer,\n isCollection,\n isPost,\n isTag,\n MaybeAnswer,\n MaybeCollection,\n MaybePost,\n MaybeTag,\n} from '../database/QetaStore';\nimport { Config } from '@backstage/config';\nimport { S3Client } from '@aws-sdk/client-s3';\nimport { RouteOptions } from './types';\nimport {\n Answer,\n AnswerResponse,\n CollectionResponse,\n Comment,\n PostResponse,\n qetaDeleteAnswerPermission,\n qetaDeleteCollectionPermission,\n qetaDeleteCommentPermission,\n qetaDeletePostPermission,\n qetaDeleteTagPermission,\n qetaEditAnswerPermission,\n qetaEditCollectionPermission,\n qetaEditCommentPermission,\n qetaEditPostPermission,\n qetaEditTagPermission,\n selectByPostType,\n TagResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { NodeHttpHandler } from '@smithy/node-http-handler';\nimport { HttpsProxyAgent } from 'hpagent';\nimport { compact } from 'lodash';\nimport {\n ConditionTransformer,\n createConditionTransformer,\n} from '@backstage/plugin-permission-node';\nimport { rules } from '@drodil/backstage-plugin-qeta-node';\nimport { BlobServiceClient } from '@azure/storage-blob';\nimport { DefaultAzureCredential } from '@azure/identity';\nimport { BackstageCredentials } from '@backstage/backend-plugin-api';\nimport { PermissionManager } from './PermissionManager.ts';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nexport const getResourceUrl = (\n resource: MaybePost | MaybeAnswer | MaybeTag | MaybeCollection,\n config: Config,\n absolute?: boolean,\n) => {\n if (!resource) {\n return undefined;\n }\n const basePath = (\n config.getOptionalString('qeta.route') ?? 'qeta'\n ).replaceAll(/(^\\/+)|(\\/+$)/g, '');\n const baseUrl = absolute\n ? `${config.getOptionalString('app.baseUrl') ?? ''}/${basePath}`\n : `/${basePath}`;\n\n if (isTag(resource)) {\n return `${baseUrl}/tags/${resource.tag}`;\n } else if (isCollection(resource)) {\n return `${baseUrl}/collection/${resource.id}`;\n } else if (isAnswer(resource)) {\n return `${baseUrl}/questions/${resource.postId}#answer_${resource.id}`;\n } else if (isPost(resource)) {\n const questionRoute = `${baseUrl}/questions/${resource.id}`;\n const articleRoute = `${baseUrl}/articles/${resource.id}`;\n const linkRoute = `${baseUrl}/links/${resource.id}`;\n return selectByPostType(\n resource.type,\n questionRoute,\n articleRoute,\n linkRoute,\n );\n }\n return undefined;\n};\n\n/**\n * Filter entity refs based on catalog permissions.\n * Uses catalogApi.getEntitiesByRefs which automatically filters out entities\n * the user doesn't have permission to see.\n */\nconst filterEntitiesByPermissions = async (\n entityRefs: string[] | undefined,\n routeOpts: RouteOptions,\n credentials: BackstageCredentials,\n): Promise<string[] | undefined> => {\n if (!entityRefs || entityRefs.length === 0) {\n return entityRefs;\n }\n\n try {\n // Get a plugin token on behalf of the user to call the catalog\n const { token } = await routeOpts.auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n // catalogApi.getEntitiesByRefs handles permission checks automatically\n // It only returns entities the user has permission to see\n const entities = await routeOpts.catalog.getEntitiesByRefs(\n { entityRefs },\n { token },\n );\n\n // Return only the refs of entities that were successfully retrieved\n return entities.items\n .filter(entity => entity !== undefined)\n .map(stringifyEntityRef);\n } catch (error) {\n // If there's an error, return empty array to be safe\n routeOpts.logger.warn('Error filtering entities by permissions', error);\n return [];\n }\n};\n\nexport const getCreated = async (\n req: Request<unknown>,\n options: RouteOptions,\n): Promise<Date> => {\n const allowMetadataInput = options.config.getOptionalBoolean(\n 'qeta.allowMetadataInput',\n );\n\n if (allowMetadataInput && req.body.created) {\n return new Date(req.body.created);\n }\n\n return new Date();\n};\n\nexport type QetaFilter = {\n property:\n | 'posts.id'\n | 'posts.author'\n | 'posts.type'\n | 'tags'\n | 'entityRefs'\n | 'answers.id'\n | 'answers.author'\n | 'comments.id'\n | 'comments.author'\n | 'tags.tag'\n | 'tag.experts'\n | 'collections.owner'\n | 'collections.id';\n values: Array<string | undefined>;\n};\n\nexport type QetaFilters = QetaFilter;\n\nexport const transformConditions: ConditionTransformer<QetaFilters> =\n createConditionTransformer(Object.values(rules));\n\nconst mapTagAdditionalFields = async (\n request: Request<unknown>,\n resource: TagResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n checkRights?: boolean,\n permissions?: Map<string, boolean>,\n) => {\n const [canEdit, canDelete] = await Promise.all([\n permissions?.get(`edit:tag:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditTagPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:tag:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteTagPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n ]);\n\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n return resource;\n};\n\nconst mapCollectionAdditionalFields = async (\n request: Request<unknown>,\n resource: CollectionResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n checkRights?: boolean,\n routeOpts?: RouteOptions,\n permissions?: Map<string, boolean>,\n) => {\n const [canEdit, canDelete, filteredEntities] = await Promise.all([\n permissions?.get(`edit:collection:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditCollectionPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:collection:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteCollectionPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n routeOpts\n ? filterEntitiesByPermissions(resource.entities, routeOpts, credentials)\n : resource.entities,\n ]);\n\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n resource.entities = filteredEntities;\n\n if (resource.posts && routeOpts) {\n await Promise.all(\n resource.posts.map(async post => {\n post.entities = await filterEntitiesByPermissions(\n post.entities,\n routeOpts,\n credentials,\n );\n }),\n );\n }\n\n return resource;\n};\n\nconst mapResourceComments = async (\n request: Request<unknown>,\n resource: AnswerResponse | PostResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n permissions?: Map<string, boolean>,\n) => {\n const commentArr = resource.comments ?? [];\n const comments: (Comment | null)[] = await Promise.all(\n commentArr.map(async (c: Comment) => {\n const canEdit =\n permissions?.get(`edit:comment:${c.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditCommentPermission, resource: c }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n const canDelete =\n permissions?.get(`delete:comment:${c.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteCommentPermission, resource: c }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n\n return {\n ...c,\n own: c.author === username,\n expert: c.experts?.includes(c.author),\n canEdit,\n canDelete,\n };\n }),\n );\n return compact(comments);\n};\n\nconst mapAnswerAdditionalFields = async (\n request: Request<unknown>,\n resource: AnswerResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n routeOpts?: RouteOptions,\n permissions?: Map<string, boolean>,\n) => {\n const [canEdit, canDelete, comments] = await Promise.all([\n permissions?.get(`edit:answer:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditAnswerPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:answer:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteAnswerPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n mapResourceComments(\n request,\n resource,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n ),\n ]);\n\n resource.ownVote = resource.votes?.find(v => v.author === username)?.score;\n resource.own = resource.author === username;\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n resource.expert = resource.experts?.includes(resource.author);\n resource.comments = comments;\n\n // Filter entities on the associated post if present\n if (resource.post && routeOpts) {\n resource.post.entities = await filterEntitiesByPermissions(\n resource.post.entities,\n routeOpts,\n credentials,\n );\n }\n\n return resource;\n};\n\nconst mapPostAnswers = async (\n request: Request<unknown>,\n resource: PostResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n permissions?: Map<string, boolean>,\n) => {\n const answersArray = resource.answers ?? [];\n const comments = await Promise.all(\n answersArray.map(async (a: Answer) => {\n return mapResourceComments(\n request,\n a,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n );\n }),\n );\n\n return Promise.all(\n answersArray.map(async (a: Answer, index: number) => {\n const canEdit =\n permissions?.get(`edit:answer:${a.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditAnswerPermission, resource: a }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n const canDelete =\n permissions?.get(`delete:answer:${a.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteAnswerPermission, resource: a }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n\n return {\n ...a,\n ownVote: a.votes?.find(v => v.author === username)?.score,\n own: resource.author === username,\n canEdit,\n canDelete,\n expert: a.experts?.includes(resource.author),\n comments: comments[index],\n };\n }),\n );\n};\n\nconst mapPostAdditionalFields = async (\n request: Request<unknown>,\n resource: PostResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n routeOpts?: RouteOptions,\n permissions?: Map<string, boolean>,\n) => {\n resource.ownVote = resource.votes?.find(v => v.author === username)?.score;\n resource.own = resource.author === username;\n\n const [canEdit, canDelete, answers, comments, filteredEntities] =\n await Promise.all([\n permissions?.get(`edit:post:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditPostPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:post:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeletePostPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n mapPostAnswers(\n request,\n resource,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n ),\n mapResourceComments(\n request,\n resource,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n ),\n routeOpts\n ? filterEntitiesByPermissions(resource.entities, routeOpts, credentials)\n : resource.entities,\n ]);\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n resource.answers = answers;\n resource.comments = comments;\n resource.entities = filteredEntities;\n return resource;\n};\n\nconst authorizeResourcePermissions = async (\n request: Request<unknown>,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n posts: PostResponse[],\n collections: CollectionResponse[],\n tags: TagResponse[],\n answers: AnswerResponse[],\n) => {\n const allAnswers = [\n ...answers,\n ...posts.flatMap(p => (p.answers ? p.answers : [])),\n ];\n const allComments = [\n ...posts.flatMap(p => (p.comments ? p.comments : [])),\n ...allAnswers.flatMap(a => (a.comments ? a.comments : [])),\n ];\n\n const [\n [postEditPerms, postDeletePerms],\n [collectionEditPerms, collectionDeletePerms],\n [tagEditPerms, tagDeletePerms],\n [answerEditPerms, answerDeletePerms],\n [commentEditPerms, commentDeletePerms],\n ] = await Promise.all([\n posts.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...posts.map(r => ({\n permission: qetaEditPostPermission,\n resource: r,\n })),\n ...posts.map(r => ({\n permission: qetaDeletePostPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, posts.length),\n results.slice(posts.length),\n ])\n : Promise.resolve([[], []]),\n collections.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...collections.map(r => ({\n permission: qetaEditCollectionPermission,\n resource: r,\n })),\n ...collections.map(r => ({\n permission: qetaDeleteCollectionPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, collections.length),\n results.slice(collections.length),\n ])\n : Promise.resolve([[], []]),\n tags.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...tags.map(r => ({\n permission: qetaEditTagPermission,\n resource: r,\n })),\n ...tags.map(r => ({\n permission: qetaDeleteTagPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, tags.length),\n results.slice(tags.length),\n ])\n : Promise.resolve([[], []]),\n allAnswers.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...allAnswers.map(r => ({\n permission: qetaEditAnswerPermission,\n resource: r,\n })),\n ...allAnswers.map(r => ({\n permission: qetaDeleteAnswerPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, allAnswers.length),\n results.slice(allAnswers.length),\n ])\n : Promise.resolve([[], []]),\n allComments.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...allComments.map(r => ({\n permission: qetaEditCommentPermission,\n resource: r,\n })),\n ...allComments.map(r => ({\n permission: qetaDeleteCommentPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, allComments.length),\n results.slice(allComments.length),\n ])\n : Promise.resolve([[], []]),\n ]);\n\n const permissions = new Map<string, boolean>();\n posts.forEach((r, i) => {\n permissions.set(`edit:post:${r.id}`, postEditPerms[i]);\n permissions.set(`delete:post:${r.id}`, postDeletePerms[i]);\n });\n collections.forEach((r, i) => {\n permissions.set(`edit:collection:${r.id}`, collectionEditPerms[i]);\n permissions.set(`delete:collection:${r.id}`, collectionDeletePerms[i]);\n });\n tags.forEach((r, i) => {\n permissions.set(`edit:tag:${r.id}`, tagEditPerms[i]);\n permissions.set(`delete:tag:${r.id}`, tagDeletePerms[i]);\n });\n allAnswers.forEach((r, i) => {\n permissions.set(`edit:answer:${r.id}`, answerEditPerms[i]);\n permissions.set(`delete:answer:${r.id}`, answerDeletePerms[i]);\n });\n allComments.forEach((r, i) => {\n permissions.set(`edit:comment:${r.id}`, commentEditPerms[i]);\n permissions.set(`delete:comment:${r.id}`, commentDeletePerms[i]);\n });\n\n return permissions;\n};\n\nexport const mapAdditionalFields = async (\n request: Request<unknown>,\n resources: (MaybePost | MaybeAnswer | MaybeTag | MaybeCollection)[],\n routeOpts: RouteOptions,\n options?: {\n checkRights?: boolean;\n creds?: BackstageCredentials;\n username?: string;\n },\n) => {\n if (!resources || resources.length === 0) {\n return resources;\n }\n\n const { creds, username, checkRights = true } = options ?? {};\n const { permissionMgr } = routeOpts;\n const credentials =\n creds ?? (await permissionMgr.getCredentials(request, true));\n const user =\n username ??\n (await routeOpts.permissionMgr.getUsername(request, true, credentials));\n\n const validResources = resources.filter(\n (\n r,\n ): r is PostResponse | AnswerResponse | TagResponse | CollectionResponse =>\n r !== null && r !== undefined,\n );\n\n const posts = validResources.filter(isPost) as PostResponse[];\n const collections = validResources.filter(\n isCollection,\n ) as CollectionResponse[];\n const tags = validResources.filter(isTag) as TagResponse[];\n const answers = validResources.filter(isAnswer) as AnswerResponse[];\n\n let permissions: Map<string, boolean> = new Map();\n\n if (checkRights) {\n permissions = await authorizeResourcePermissions(\n request,\n permissionMgr,\n credentials,\n posts,\n collections,\n tags,\n answers,\n );\n }\n\n await Promise.all(\n resources.map(async resource => {\n if (!resource) {\n return resource;\n }\n resource.self = getResourceUrl(resource, routeOpts.config, true);\n\n if (isTag(resource)) {\n return mapTagAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n checkRights,\n permissions,\n );\n } else if (isCollection(resource)) {\n return mapCollectionAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n checkRights,\n routeOpts,\n permissions,\n );\n } else if (isPost(resource)) {\n return mapPostAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n user,\n checkRights,\n routeOpts,\n permissions,\n );\n } else if (isAnswer(resource)) {\n return mapAnswerAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n user,\n checkRights,\n routeOpts,\n permissions,\n );\n }\n return resource;\n }),\n );\n\n return resources;\n};\nexport const stringDateTime = (dayString: string) => {\n const dateTimePeriod = Number(dayString.toString().slice(0, -1));\n return format(subDays(new Date(), dateTimePeriod), 'yyyy-MM-dd');\n};\n\nexport const getS3Client = (config: Config) => {\n const accessKeyId = config.getOptionalString('qeta.storage.accessKeyId');\n const secretAccessKey = config.getOptionalString(\n 'qeta.storage.secretAccessKey',\n );\n const region = config.getOptionalString('qeta.storage.region');\n const sessionToken = config.getOptionalString('qeta.storage.sessionToken');\n const endpoint = config.getOptionalString('qeta.storage.endpoint');\n const httpsProxy = config.getOptionalString('qeta.storage.httpsProxy');\n const forcePathStyle = config.getOptionalBoolean(\n 'qeta.storage.forcePathStyle',\n );\n const maxAttempts = config.getOptionalNumber('qeta.storage.maxAttempts');\n\n let credentials;\n if (accessKeyId && secretAccessKey) {\n credentials = {\n accessKeyId,\n secretAccessKey,\n sessionToken,\n };\n }\n return new S3Client({\n customUserAgent: 'backstage-aws-drodil-qeta-s3-storage',\n ...(credentials && { credentials }),\n ...(region && { region }),\n ...(endpoint && { endpoint }),\n ...(forcePathStyle && { forcePathStyle }),\n ...(maxAttempts && { maxAttempts }),\n ...(httpsProxy && {\n requestHandler: new NodeHttpHandler({\n httpsAgent: new HttpsProxyAgent({ proxy: httpsProxy }),\n }),\n }),\n });\n};\n\nexport const getAzureBlobServiceClient = (config: Config) => {\n const accountName = config.getOptionalString(\n 'qeta.storage.blobStorageAccountName',\n );\n const connectionString = config.getOptionalString(\n 'qeta.storage.blobStorageConnectionString',\n );\n if (connectionString) {\n return BlobServiceClient.fromConnectionString(connectionString);\n } else if (accountName) {\n return new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n new DefaultAzureCredential(),\n );\n }\n\n throw new Error(\n 'Either account name or connection string must be provided for Azure Blob Storage',\n );\n};\n"],"names":["isTag","isCollection","isAnswer","isPost","selectByPostType","stringifyEntityRef","createConditionTransformer","rules","qetaEditTagPermission","qetaDeleteTagPermission","qetaEditCollectionPermission","qetaDeleteCollectionPermission","qetaEditCommentPermission","qetaDeleteCommentPermission","compact","qetaEditAnswerPermission","qetaDeleteAnswerPermission","qetaEditPostPermission","qetaDeletePostPermission","format","subDays","S3Client","NodeHttpHandler","HttpsProxyAgent","BlobServiceClient","DefaultAzureCredential"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"util.cjs.js","sources":["../../src/service/util.ts"],"sourcesContent":["import { Request } from 'express';\nimport { format, subDays } from 'date-fns';\nimport {\n isAnswer,\n isCollection,\n isPost,\n isTag,\n MaybeAnswer,\n MaybeCollection,\n MaybePost,\n MaybeTag,\n} from '../database/QetaStore';\nimport { Config } from '@backstage/config';\nimport { S3Client } from '@aws-sdk/client-s3';\nimport { RouteOptions } from './types';\nimport {\n Answer,\n AnswerResponse,\n CollectionResponse,\n Comment,\n PostResponse,\n qetaDeleteAnswerPermission,\n qetaDeleteCollectionPermission,\n qetaDeleteCommentPermission,\n qetaDeletePostPermission,\n qetaDeleteTagPermission,\n qetaEditAnswerPermission,\n qetaEditCollectionPermission,\n qetaEditCommentPermission,\n qetaEditPostPermission,\n qetaEditTagPermission,\n selectByPostType,\n TagResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { NodeHttpHandler } from '@smithy/node-http-handler';\nimport { HttpsProxyAgent } from 'hpagent';\nimport { compact } from 'lodash';\nimport {\n ConditionTransformer,\n createConditionTransformer,\n} from '@backstage/plugin-permission-node';\nimport { rules } from '@drodil/backstage-plugin-qeta-node';\nimport { BlobServiceClient } from '@azure/storage-blob';\nimport { DefaultAzureCredential } from '@azure/identity';\nimport { BackstageCredentials } from '@backstage/backend-plugin-api';\nimport { PermissionManager } from './PermissionManager.ts';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nexport const getResourceUrl = (\n resource: MaybePost | MaybeAnswer | MaybeTag | MaybeCollection,\n config: Config,\n absolute?: boolean,\n) => {\n if (!resource) {\n return undefined;\n }\n const basePath = (\n config.getOptionalString('qeta.route') ?? 'qeta'\n ).replaceAll(/(^\\/+)|(\\/+$)/g, '');\n const baseUrl = absolute\n ? `${config.getOptionalString('app.baseUrl') ?? ''}/${basePath}`\n : `/${basePath}`;\n\n if (isTag(resource)) {\n return `${baseUrl}/tags/${resource.tag}`;\n } else if (isCollection(resource)) {\n return `${baseUrl}/collection/${resource.id}`;\n } else if (isAnswer(resource)) {\n return `${baseUrl}/questions/${resource.postId}#answer_${resource.id}`;\n } else if (isPost(resource)) {\n const questionRoute = `${baseUrl}/questions/${resource.id}`;\n const articleRoute = `${baseUrl}/articles/${resource.id}`;\n const linkRoute = `${baseUrl}/links/${resource.id}`;\n return selectByPostType(\n resource.type,\n questionRoute,\n articleRoute,\n linkRoute,\n );\n }\n return undefined;\n};\n\n/**\n * Filter entity refs based on catalog permissions.\n * Uses catalogApi.getEntitiesByRefs which automatically filters out entities\n * the user doesn't have permission to see.\n */\nconst filterEntitiesByPermissions = async (\n entityRefs: string[] | undefined,\n routeOpts: RouteOptions,\n credentials: BackstageCredentials,\n): Promise<string[] | undefined> => {\n if (!entityRefs || entityRefs.length === 0) {\n return entityRefs;\n }\n\n try {\n // Get a plugin token on behalf of the user to call the catalog\n const { token } = await routeOpts.auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n // catalogApi.getEntitiesByRefs handles permission checks automatically\n // It only returns entities the user has permission to see\n const entities = await routeOpts.catalog.getEntitiesByRefs(\n { entityRefs },\n { token },\n );\n\n // Return only the refs of entities that were successfully retrieved\n return entities.items\n .filter(entity => entity !== undefined)\n .map(stringifyEntityRef);\n } catch (error) {\n // If there's an error, return empty array to be safe\n routeOpts.logger.warn('Error filtering entities by permissions', error);\n return [];\n }\n};\n\nexport const getCreated = async (\n req: Request<unknown>,\n options: RouteOptions,\n): Promise<Date> => {\n const allowMetadataInput = options.config.getOptionalBoolean(\n 'qeta.allowMetadataInput',\n );\n\n if (allowMetadataInput && req.body.created) {\n return new Date(req.body.created);\n }\n\n return new Date();\n};\n\nexport type QetaFilter = {\n property:\n | 'posts.id'\n | 'posts.author'\n | 'posts.type'\n | 'tags'\n | 'entityRefs'\n | 'answers.id'\n | 'answers.author'\n | 'comments.id'\n | 'comments.author'\n | 'tags.tag'\n | 'tag.experts'\n | 'collections.owner'\n | 'collections.id';\n values: Array<string | undefined>;\n};\n\nexport type QetaFilters = QetaFilter;\n\nexport const transformConditions: ConditionTransformer<QetaFilters> =\n createConditionTransformer(Object.values(rules));\n\nconst mapTagAdditionalFields = async (\n request: Request<unknown>,\n resource: TagResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n checkRights?: boolean,\n permissions?: Map<string, boolean>,\n) => {\n const [canEdit, canDelete] = await Promise.all([\n permissions?.get(`edit:tag:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditTagPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:tag:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteTagPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n ]);\n\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n return resource;\n};\n\nconst mapCollectionAdditionalFields = async (\n request: Request<unknown>,\n resource: CollectionResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n checkRights?: boolean,\n routeOpts?: RouteOptions,\n permissions?: Map<string, boolean>,\n) => {\n const [canEdit, canDelete, filteredEntities] = await Promise.all([\n permissions?.get(`edit:collection:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditCollectionPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:collection:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteCollectionPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n routeOpts\n ? filterEntitiesByPermissions(resource.entities, routeOpts, credentials)\n : resource.entities,\n ]);\n\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n resource.entities = filteredEntities;\n\n if (resource.posts && routeOpts) {\n await Promise.all(\n resource.posts.map(async post => {\n post.entities = await filterEntitiesByPermissions(\n post.entities,\n routeOpts,\n credentials,\n );\n }),\n );\n }\n\n return resource;\n};\n\nconst mapResourceComments = async (\n request: Request<unknown>,\n resource: AnswerResponse | PostResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n permissions?: Map<string, boolean>,\n) => {\n const commentArr = resource.comments ?? [];\n const comments: (Comment | null)[] = await Promise.all(\n commentArr.map(async (c: Comment) => {\n const canEdit =\n permissions?.get(`edit:comment:${c.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditCommentPermission, resource: c }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n const canDelete =\n permissions?.get(`delete:comment:${c.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteCommentPermission, resource: c }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n\n return {\n ...c,\n own: c.author === username,\n expert: c.experts?.includes(c.author),\n canEdit,\n canDelete,\n };\n }),\n );\n return compact(comments);\n};\n\nconst mapAnswerAdditionalFields = async (\n request: Request<unknown>,\n resource: AnswerResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n routeOpts?: RouteOptions,\n permissions?: Map<string, boolean>,\n) => {\n const [canEdit, canDelete, comments] = await Promise.all([\n permissions?.get(`edit:answer:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditAnswerPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:answer:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteAnswerPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n mapResourceComments(\n request,\n resource,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n ),\n ]);\n\n resource.ownVote = resource.votes?.find(v => v.author === username)?.score;\n resource.own = resource.author === username;\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n resource.expert = resource.experts?.includes(resource.author);\n resource.comments = comments;\n\n // Filter entities on the associated post if present\n if (resource.post && routeOpts) {\n resource.post.entities = await filterEntitiesByPermissions(\n resource.post.entities,\n routeOpts,\n credentials,\n );\n }\n\n return resource;\n};\n\nconst mapPostAnswers = async (\n request: Request<unknown>,\n resource: PostResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n permissions?: Map<string, boolean>,\n) => {\n const answersArray = resource.answers ?? [];\n const comments = await Promise.all(\n answersArray.map(async (a: Answer) => {\n return mapResourceComments(\n request,\n a,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n );\n }),\n );\n\n return Promise.all(\n answersArray.map(async (a: Answer, index: number) => {\n const canEdit =\n permissions?.get(`edit:answer:${a.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditAnswerPermission, resource: a }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n const canDelete =\n permissions?.get(`delete:answer:${a.id}`) ??\n (checkRights\n ? await permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeleteAnswerPermission, resource: a }],\n { credentials },\n )\n .then(r => r[0])\n : false);\n\n return {\n ...a,\n ownVote: a.votes?.find(v => v.author === username)?.score,\n own: a.author === username,\n canEdit,\n canDelete,\n expert: a.experts?.includes(resource.author),\n comments: comments[index],\n };\n }),\n );\n};\n\nconst mapPostAdditionalFields = async (\n request: Request<unknown>,\n resource: PostResponse,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n username: string,\n checkRights?: boolean,\n routeOpts?: RouteOptions,\n permissions?: Map<string, boolean>,\n) => {\n resource.ownVote = resource.votes?.find(v => v.author === username)?.score;\n resource.own = resource.author === username;\n\n const [canEdit, canDelete, answers, comments, filteredEntities] =\n await Promise.all([\n permissions?.get(`edit:post:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaEditPostPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n permissions?.get(`delete:post:${resource.id}`) ??\n (checkRights\n ? permissionMgr\n .authorizeBoolean(\n request,\n [{ permission: qetaDeletePostPermission, resource }],\n {\n credentials,\n },\n )\n .then(r => r[0])\n : undefined),\n mapPostAnswers(\n request,\n resource,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n ),\n mapResourceComments(\n request,\n resource,\n permissionMgr,\n credentials,\n username,\n checkRights,\n permissions,\n ),\n routeOpts\n ? filterEntitiesByPermissions(resource.entities, routeOpts, credentials)\n : resource.entities,\n ]);\n resource.canEdit = canEdit;\n resource.canDelete = canDelete;\n resource.answers = answers;\n resource.comments = comments;\n resource.entities = filteredEntities;\n return resource;\n};\n\nconst authorizeResourcePermissions = async (\n request: Request<unknown>,\n permissionMgr: PermissionManager,\n credentials: BackstageCredentials,\n posts: PostResponse[],\n collections: CollectionResponse[],\n tags: TagResponse[],\n answers: AnswerResponse[],\n) => {\n const allAnswers = [\n ...answers,\n ...posts.flatMap(p => (p.answers ? p.answers : [])),\n ];\n const allComments = [\n ...posts.flatMap(p => (p.comments ? p.comments : [])),\n ...allAnswers.flatMap(a => (a.comments ? a.comments : [])),\n ];\n\n const [\n [postEditPerms, postDeletePerms],\n [collectionEditPerms, collectionDeletePerms],\n [tagEditPerms, tagDeletePerms],\n [answerEditPerms, answerDeletePerms],\n [commentEditPerms, commentDeletePerms],\n ] = await Promise.all([\n posts.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...posts.map(r => ({\n permission: qetaEditPostPermission,\n resource: r,\n })),\n ...posts.map(r => ({\n permission: qetaDeletePostPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, posts.length),\n results.slice(posts.length),\n ])\n : Promise.resolve([[], []]),\n collections.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...collections.map(r => ({\n permission: qetaEditCollectionPermission,\n resource: r,\n })),\n ...collections.map(r => ({\n permission: qetaDeleteCollectionPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, collections.length),\n results.slice(collections.length),\n ])\n : Promise.resolve([[], []]),\n tags.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...tags.map(r => ({\n permission: qetaEditTagPermission,\n resource: r,\n })),\n ...tags.map(r => ({\n permission: qetaDeleteTagPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, tags.length),\n results.slice(tags.length),\n ])\n : Promise.resolve([[], []]),\n allAnswers.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...allAnswers.map(r => ({\n permission: qetaEditAnswerPermission,\n resource: r,\n })),\n ...allAnswers.map(r => ({\n permission: qetaDeleteAnswerPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, allAnswers.length),\n results.slice(allAnswers.length),\n ])\n : Promise.resolve([[], []]),\n allComments.length > 0\n ? permissionMgr\n .authorizeBoolean(\n request,\n [\n ...allComments.map(r => ({\n permission: qetaEditCommentPermission,\n resource: r,\n })),\n ...allComments.map(r => ({\n permission: qetaDeleteCommentPermission,\n resource: r,\n })),\n ],\n { credentials },\n )\n .then(results => [\n results.slice(0, allComments.length),\n results.slice(allComments.length),\n ])\n : Promise.resolve([[], []]),\n ]);\n\n const permissions = new Map<string, boolean>();\n posts.forEach((r, i) => {\n permissions.set(`edit:post:${r.id}`, postEditPerms[i]);\n permissions.set(`delete:post:${r.id}`, postDeletePerms[i]);\n });\n collections.forEach((r, i) => {\n permissions.set(`edit:collection:${r.id}`, collectionEditPerms[i]);\n permissions.set(`delete:collection:${r.id}`, collectionDeletePerms[i]);\n });\n tags.forEach((r, i) => {\n permissions.set(`edit:tag:${r.id}`, tagEditPerms[i]);\n permissions.set(`delete:tag:${r.id}`, tagDeletePerms[i]);\n });\n allAnswers.forEach((r, i) => {\n permissions.set(`edit:answer:${r.id}`, answerEditPerms[i]);\n permissions.set(`delete:answer:${r.id}`, answerDeletePerms[i]);\n });\n allComments.forEach((r, i) => {\n permissions.set(`edit:comment:${r.id}`, commentEditPerms[i]);\n permissions.set(`delete:comment:${r.id}`, commentDeletePerms[i]);\n });\n\n return permissions;\n};\n\nexport const mapAdditionalFields = async (\n request: Request<unknown>,\n resources: (MaybePost | MaybeAnswer | MaybeTag | MaybeCollection)[],\n routeOpts: RouteOptions,\n options?: {\n checkRights?: boolean;\n creds?: BackstageCredentials;\n username?: string;\n },\n) => {\n if (!resources || resources.length === 0) {\n return resources;\n }\n\n const { creds, username, checkRights = true } = options ?? {};\n const { permissionMgr } = routeOpts;\n const credentials =\n creds ?? (await permissionMgr.getCredentials(request, true));\n const user =\n username ??\n (await routeOpts.permissionMgr.getUsername(request, true, credentials));\n\n const validResources = resources.filter(\n (\n r,\n ): r is PostResponse | AnswerResponse | TagResponse | CollectionResponse =>\n r !== null && r !== undefined,\n );\n\n const posts = validResources.filter(isPost) as PostResponse[];\n const collections = validResources.filter(\n isCollection,\n ) as CollectionResponse[];\n const tags = validResources.filter(isTag) as TagResponse[];\n const answers = validResources.filter(isAnswer) as AnswerResponse[];\n\n let permissions: Map<string, boolean> = new Map();\n\n if (checkRights) {\n permissions = await authorizeResourcePermissions(\n request,\n permissionMgr,\n credentials,\n posts,\n collections,\n tags,\n answers,\n );\n }\n\n await Promise.all(\n resources.map(async resource => {\n if (!resource) {\n return resource;\n }\n resource.self = getResourceUrl(resource, routeOpts.config, true);\n\n if (isTag(resource)) {\n return mapTagAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n checkRights,\n permissions,\n );\n } else if (isCollection(resource)) {\n return mapCollectionAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n checkRights,\n routeOpts,\n permissions,\n );\n } else if (isPost(resource)) {\n return mapPostAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n user,\n checkRights,\n routeOpts,\n permissions,\n );\n } else if (isAnswer(resource)) {\n return mapAnswerAdditionalFields(\n request,\n resource,\n permissionMgr,\n credentials,\n user,\n checkRights,\n routeOpts,\n permissions,\n );\n }\n return resource;\n }),\n );\n\n return resources;\n};\nexport const stringDateTime = (dayString: string) => {\n const dateTimePeriod = Number(dayString.toString().slice(0, -1));\n return format(subDays(new Date(), dateTimePeriod), 'yyyy-MM-dd');\n};\n\nexport const getS3Client = (config: Config) => {\n const accessKeyId = config.getOptionalString('qeta.storage.accessKeyId');\n const secretAccessKey = config.getOptionalString(\n 'qeta.storage.secretAccessKey',\n );\n const region = config.getOptionalString('qeta.storage.region');\n const sessionToken = config.getOptionalString('qeta.storage.sessionToken');\n const endpoint = config.getOptionalString('qeta.storage.endpoint');\n const httpsProxy = config.getOptionalString('qeta.storage.httpsProxy');\n const forcePathStyle = config.getOptionalBoolean(\n 'qeta.storage.forcePathStyle',\n );\n const maxAttempts = config.getOptionalNumber('qeta.storage.maxAttempts');\n\n let credentials;\n if (accessKeyId && secretAccessKey) {\n credentials = {\n accessKeyId,\n secretAccessKey,\n sessionToken,\n };\n }\n return new S3Client({\n customUserAgent: 'backstage-aws-drodil-qeta-s3-storage',\n ...(credentials && { credentials }),\n ...(region && { region }),\n ...(endpoint && { endpoint }),\n ...(forcePathStyle && { forcePathStyle }),\n ...(maxAttempts && { maxAttempts }),\n ...(httpsProxy && {\n requestHandler: new NodeHttpHandler({\n httpsAgent: new HttpsProxyAgent({ proxy: httpsProxy }),\n }),\n }),\n });\n};\n\nexport const getAzureBlobServiceClient = (config: Config) => {\n const accountName = config.getOptionalString(\n 'qeta.storage.blobStorageAccountName',\n );\n const connectionString = config.getOptionalString(\n 'qeta.storage.blobStorageConnectionString',\n );\n if (connectionString) {\n return BlobServiceClient.fromConnectionString(connectionString);\n } else if (accountName) {\n return new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n new DefaultAzureCredential(),\n );\n }\n\n throw new Error(\n 'Either account name or connection string must be provided for Azure Blob Storage',\n );\n};\n"],"names":["isTag","isCollection","isAnswer","isPost","selectByPostType","stringifyEntityRef","createConditionTransformer","rules","qetaEditTagPermission","qetaDeleteTagPermission","qetaEditCollectionPermission","qetaDeleteCollectionPermission","qetaEditCommentPermission","qetaDeleteCommentPermission","compact","qetaEditAnswerPermission","qetaDeleteAnswerPermission","qetaEditPostPermission","qetaDeletePostPermission","format","subDays","S3Client","NodeHttpHandler","HttpsProxyAgent","BlobServiceClient","DefaultAzureCredential"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drodil/backstage-plugin-qeta-backend",
|
|
3
|
-
"version": "3.53.
|
|
3
|
+
"version": "3.53.2",
|
|
4
4
|
"description": "Backstage.io Q&A plugin backend",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"backstage",
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
"@backstage/plugin-permission-node": "^0.10.7",
|
|
67
67
|
"@backstage/plugin-signals-node": "^0.1.27",
|
|
68
68
|
"@backstage/types": "^1.2.2",
|
|
69
|
-
"@drodil/backstage-plugin-qeta-common": "^3.53.
|
|
70
|
-
"@drodil/backstage-plugin-qeta-node": "^3.53.
|
|
69
|
+
"@drodil/backstage-plugin-qeta-common": "^3.53.2",
|
|
70
|
+
"@drodil/backstage-plugin-qeta-node": "^3.53.2",
|
|
71
71
|
"@smithy/node-http-handler": "^4.0.2",
|
|
72
72
|
"@types/express": "*",
|
|
73
73
|
"@types/mime-types": "^2.1.4",
|
|
@@ -105,9 +105,9 @@
|
|
|
105
105
|
"@backstage/plugin-search-backend-module-pg": "^0.5.51",
|
|
106
106
|
"@backstage/plugin-signals-backend": "^0.3.11",
|
|
107
107
|
"@backstage/plugin-techdocs-backend": "^2.1.3",
|
|
108
|
-
"@drodil/backstage-plugin-catalog-backend-module-qeta": "^3.53.
|
|
109
|
-
"@drodil/backstage-plugin-qeta-backend-module-openai": "^3.53.
|
|
110
|
-
"@drodil/backstage-plugin-search-backend-module-qeta": "^3.53.
|
|
108
|
+
"@drodil/backstage-plugin-catalog-backend-module-qeta": "^3.53.2",
|
|
109
|
+
"@drodil/backstage-plugin-qeta-backend-module-openai": "^3.53.2",
|
|
110
|
+
"@drodil/backstage-plugin-search-backend-module-qeta": "^3.53.2",
|
|
111
111
|
"@types/sanitize-html": "^2.9.5",
|
|
112
112
|
"@types/stopword": "^2.0.3",
|
|
113
113
|
"@types/supertest": "^2.0.12",
|