@drodil/backstage-plugin-qeta-backend 3.52.5 → 3.52.6

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.
@@ -21,17 +21,29 @@ class BaseStore {
21
21
  }
22
22
  applySearchQuery(query, columns, searchQuery) {
23
23
  if (this.db.client.config.client === "pg") {
24
- const formattedQuery = searchQuery.trim().split(/\s+/).map((term) => `'${term.replace(/'/g, "''")}':*`).join(" & ");
25
- query.whereRaw(
26
- `((to_tsvector('english', CONCAT_WS(' ', ${columns.join(
27
- ","
28
- )})) @@ to_tsquery('english', ?)))`,
29
- [formattedQuery]
30
- );
24
+ const terms = searchQuery.trim().split(/\s+/);
25
+ query.andWhere((builder) => {
26
+ const coalescedColumns = columns.map((col) => `COALESCE(${col}::text, '')`).join(` || ' ' || `);
27
+ terms.forEach((term) => {
28
+ builder.andWhereRaw(`(${coalescedColumns}) %> ?`, [term]);
29
+ });
30
+ const concatenatedColumns = `LOWER(CONCAT(${columns.join(",")}))`;
31
+ terms.forEach((term) => {
32
+ builder.andWhereRaw(`${concatenatedColumns} LIKE LOWER(?)`, [
33
+ `%${term}%`
34
+ ]);
35
+ });
36
+ });
31
37
  } else {
32
- query.whereRaw(`LOWER(CONCAT(${columns.join(",")})) LIKE LOWER(?)`, [
33
- `%${searchQuery}%`
34
- ]);
38
+ query.andWhere((builder) => {
39
+ const terms = searchQuery.trim().split(/\s+/);
40
+ terms.forEach((term) => {
41
+ builder.orWhereRaw(
42
+ `LOWER(CONCAT(${columns.join(",")})) LIKE LOWER(?)`,
43
+ [`%${term}%`]
44
+ );
45
+ });
46
+ });
35
47
  }
36
48
  }
37
49
  async updateAttachments(key, content, images, id, headerImage) {
@@ -1 +1 @@
1
- {"version":3,"file":"BaseStore.cjs.js","sources":["../../../src/database/stores/BaseStore.ts"],"sourcesContent":["import { Knex } from 'knex';\nimport { QetaFilter, QetaFilters } from '../../service/util';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport {\n isAndCriteria,\n isNotCriteria,\n isOrCriteria,\n} from '@backstage/plugin-permission-node';\nimport { compact } from 'lodash';\n\nfunction isQetaFilter(filter: any): filter is QetaFilter {\n return filter.hasOwnProperty('property');\n}\n\nexport abstract class BaseStore {\n constructor(protected readonly db: Knex) {}\n\n protected mapToInteger(val: string | number | undefined): number {\n return typeof val === 'string' ? Number.parseInt(val, 10) : val ?? 0;\n }\n\n protected mapToBoolean(val: string | number | boolean | undefined): boolean {\n if (typeof val === 'string') {\n return val === 'true' || val === '1';\n }\n return typeof val === 'number' ? val > 0 : !!val;\n }\n\n protected applySearchQuery(\n query: Knex.QueryBuilder,\n columns: string[],\n searchQuery: string,\n ) {\n if (this.db.client.config.client === 'pg') {\n const formattedQuery = searchQuery\n .trim()\n .split(/\\s+/)\n .map(term => `'${term.replace(/'/g, \"''\")}':*`)\n .join(' & ');\n\n query.whereRaw(\n `((to_tsvector('english', CONCAT_WS(' ', ${columns.join(\n ',',\n )})) @@ to_tsquery('english', ?)))`,\n [formattedQuery],\n );\n } else {\n query.whereRaw(`LOWER(CONCAT(${columns.join(',')})) LIKE LOWER(?)`, [\n `%${searchQuery}%`,\n ]);\n }\n }\n\n protected async updateAttachments(\n key: 'postId' | 'answerId' | 'collectionId',\n content: string,\n images: number[],\n id: number,\n headerImage?: string,\n ) {\n if (images.length > 0) {\n await this.db('attachments')\n .whereIn('id', images)\n .update({ [key]: id });\n }\n\n const attachments = await this.db('attachments')\n .where(key, id)\n .select('uuid');\n const uuids = attachments.map(a => a.uuid);\n const toRemove = uuids.filter(uuid => {\n return !(content.includes(uuid) || headerImage?.includes(uuid));\n });\n await this.db('attachments')\n .whereIn('uuid', toRemove)\n .update({ [key]: null });\n }\n\n protected parseFilter(\n filter: PermissionCriteria<QetaFilters>,\n query: Knex.QueryBuilder,\n db: Knex,\n type: 'post' | 'answer' | 'collection' | 'tags' | 'comments' = 'post',\n negate: boolean = false,\n ): Knex.QueryBuilder {\n if (isNotCriteria(filter)) {\n return this.parseFilter(filter.not, query, db, type, !negate);\n }\n\n if (isQetaFilter(filter)) {\n const values: string[] = compact(filter.values) ?? [];\n\n let fk = 'posts.id';\n if (type === 'answer') {\n fk = 'answers.postId';\n } else if (type === 'collection') {\n fk = 'collection_posts.postId';\n }\n if (filter.property === 'tags') {\n const postIds = db('tags')\n .leftJoin('post_tags', 'tags.id', 'post_tags.tagId')\n .where('tags.tag', 'in', values)\n .select('post_tags.postId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, postIds);\n return query;\n }\n if (filter.property === 'tag.experts') {\n if (type === 'post') {\n const postIds = db('tags')\n .leftJoin('post_tags', 'tags.id', 'post_tags.tagId')\n .leftJoin('tag_experts', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('post_tags.postId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, postIds);\n return query;\n } else if (type === 'answer') {\n const answerIds = db('answers')\n .leftJoin('posts', 'answers.postId', 'posts.id')\n .leftJoin('post_tags', 'post_tags.postId', 'posts.id')\n .leftJoin('tags', 'post_tags.tagId', 'tags.id')\n .leftJoin('tag_experts', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('answers.id');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, answerIds);\n return query;\n } else if (type === 'tags') {\n const tagIds = db('tag_experts')\n .leftJoin('tags', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('tag_experts.tagId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, tagIds);\n return query;\n } else if (type === 'collection') {\n const collectionIds = db('collection_posts')\n .leftJoin('posts', 'collection_posts.postId', 'posts.id')\n .leftJoin('post_tags', 'post_tags.postId', 'posts.id')\n .leftJoin('tags', 'post_tags.tagId', 'tags.id')\n .leftJoin('tag_experts', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('collection_posts.collectionId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, collectionIds);\n return query;\n }\n }\n\n if (filter.property === 'entityRefs') {\n const postIds = db('entities')\n .leftJoin('post_entities', 'entities.id', 'post_entities.entityId')\n .where('entities.entity_ref', 'in', values)\n .select('post_entities.postId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, postIds);\n return query;\n }\n\n if (values.length === 0) {\n return negate\n ? query.whereNotNull(filter.property)\n : query.whereNull(filter.property);\n }\n\n return query[negate ? 'whereNotIn' : 'whereIn'](filter.property, values);\n }\n\n return query[negate ? 'andWhereNot' : 'andWhere'](builder => {\n const f = filter as PermissionCriteria<QetaFilters>;\n if (isOrCriteria(f)) {\n for (const subFilter of f.anyOf ?? []) {\n builder.orWhere((subQuery: Knex.QueryBuilder) =>\n this.parseFilter(subFilter, subQuery, db, type, false),\n );\n }\n } else if (isAndCriteria(f)) {\n for (const subFilter of f.allOf ?? []) {\n builder.andWhere((subQuery: Knex.QueryBuilder) =>\n this.parseFilter(subFilter, subQuery, db, type, false),\n );\n }\n } else if (isNotCriteria(f)) {\n builder.whereNot((subQuery: Knex.QueryBuilder) =>\n this.parseFilter(f.not, subQuery, db, type, false),\n );\n }\n });\n }\n}\n"],"names":["isNotCriteria","compact","isOrCriteria","isAndCriteria"],"mappings":"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"}
1
+ {"version":3,"file":"BaseStore.cjs.js","sources":["../../../src/database/stores/BaseStore.ts"],"sourcesContent":["import { Knex } from 'knex';\nimport { QetaFilter, QetaFilters } from '../../service/util';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport {\n isAndCriteria,\n isNotCriteria,\n isOrCriteria,\n} from '@backstage/plugin-permission-node';\nimport { compact } from 'lodash';\n\nfunction isQetaFilter(filter: any): filter is QetaFilter {\n return filter.hasOwnProperty('property');\n}\n\nexport abstract class BaseStore {\n constructor(protected readonly db: Knex) {}\n\n protected mapToInteger(val: string | number | undefined): number {\n return typeof val === 'string' ? Number.parseInt(val, 10) : val ?? 0;\n }\n\n protected mapToBoolean(val: string | number | boolean | undefined): boolean {\n if (typeof val === 'string') {\n return val === 'true' || val === '1';\n }\n return typeof val === 'number' ? val > 0 : !!val;\n }\n\n protected applySearchQuery(\n query: Knex.QueryBuilder,\n columns: string[],\n searchQuery: string,\n ) {\n if (this.db.client.config.client === 'pg') {\n const terms = searchQuery.trim().split(/\\s+/);\n\n query.andWhere(builder => {\n const coalescedColumns = columns\n .map(col => `COALESCE(${col}::text, '')`)\n .join(` || ' ' || `);\n\n terms.forEach(term => {\n builder.andWhereRaw(`(${coalescedColumns}) %> ?`, [term]);\n });\n\n const concatenatedColumns = `LOWER(CONCAT(${columns.join(',')}))`;\n terms.forEach(term => {\n builder.andWhereRaw(`${concatenatedColumns} LIKE LOWER(?)`, [\n `%${term}%`,\n ]);\n });\n });\n } else {\n query.andWhere(builder => {\n const terms = searchQuery.trim().split(/\\s+/);\n\n terms.forEach(term => {\n builder.orWhereRaw(\n `LOWER(CONCAT(${columns.join(',')})) LIKE LOWER(?)`,\n [`%${term}%`],\n );\n });\n });\n }\n }\n\n protected async updateAttachments(\n key: 'postId' | 'answerId' | 'collectionId',\n content: string,\n images: number[],\n id: number,\n headerImage?: string,\n ) {\n if (images.length > 0) {\n await this.db('attachments')\n .whereIn('id', images)\n .update({ [key]: id });\n }\n\n const attachments = await this.db('attachments')\n .where(key, id)\n .select('uuid');\n const uuids = attachments.map(a => a.uuid);\n const toRemove = uuids.filter(uuid => {\n return !(content.includes(uuid) || headerImage?.includes(uuid));\n });\n await this.db('attachments')\n .whereIn('uuid', toRemove)\n .update({ [key]: null });\n }\n\n protected parseFilter(\n filter: PermissionCriteria<QetaFilters>,\n query: Knex.QueryBuilder,\n db: Knex,\n type: 'post' | 'answer' | 'collection' | 'tags' | 'comments' = 'post',\n negate: boolean = false,\n ): Knex.QueryBuilder {\n if (isNotCriteria(filter)) {\n return this.parseFilter(filter.not, query, db, type, !negate);\n }\n\n if (isQetaFilter(filter)) {\n const values: string[] = compact(filter.values) ?? [];\n\n let fk = 'posts.id';\n if (type === 'answer') {\n fk = 'answers.postId';\n } else if (type === 'collection') {\n fk = 'collection_posts.postId';\n }\n if (filter.property === 'tags') {\n const postIds = db('tags')\n .leftJoin('post_tags', 'tags.id', 'post_tags.tagId')\n .where('tags.tag', 'in', values)\n .select('post_tags.postId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, postIds);\n return query;\n }\n if (filter.property === 'tag.experts') {\n if (type === 'post') {\n const postIds = db('tags')\n .leftJoin('post_tags', 'tags.id', 'post_tags.tagId')\n .leftJoin('tag_experts', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('post_tags.postId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, postIds);\n return query;\n } else if (type === 'answer') {\n const answerIds = db('answers')\n .leftJoin('posts', 'answers.postId', 'posts.id')\n .leftJoin('post_tags', 'post_tags.postId', 'posts.id')\n .leftJoin('tags', 'post_tags.tagId', 'tags.id')\n .leftJoin('tag_experts', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('answers.id');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, answerIds);\n return query;\n } else if (type === 'tags') {\n const tagIds = db('tag_experts')\n .leftJoin('tags', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('tag_experts.tagId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, tagIds);\n return query;\n } else if (type === 'collection') {\n const collectionIds = db('collection_posts')\n .leftJoin('posts', 'collection_posts.postId', 'posts.id')\n .leftJoin('post_tags', 'post_tags.postId', 'posts.id')\n .leftJoin('tags', 'post_tags.tagId', 'tags.id')\n .leftJoin('tag_experts', 'tag_experts.tagId', 'tags.id')\n .where('tag_experts.entityRef', 'in', values)\n .select('collection_posts.collectionId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, collectionIds);\n return query;\n }\n }\n\n if (filter.property === 'entityRefs') {\n const postIds = db('entities')\n .leftJoin('post_entities', 'entities.id', 'post_entities.entityId')\n .where('entities.entity_ref', 'in', values)\n .select('post_entities.postId');\n query[negate ? 'whereNotIn' : 'whereIn'](fk, postIds);\n return query;\n }\n\n if (values.length === 0) {\n return negate\n ? query.whereNotNull(filter.property)\n : query.whereNull(filter.property);\n }\n\n return query[negate ? 'whereNotIn' : 'whereIn'](filter.property, values);\n }\n\n return query[negate ? 'andWhereNot' : 'andWhere'](builder => {\n const f = filter as PermissionCriteria<QetaFilters>;\n if (isOrCriteria(f)) {\n for (const subFilter of f.anyOf ?? []) {\n builder.orWhere((subQuery: Knex.QueryBuilder) =>\n this.parseFilter(subFilter, subQuery, db, type, false),\n );\n }\n } else if (isAndCriteria(f)) {\n for (const subFilter of f.allOf ?? []) {\n builder.andWhere((subQuery: Knex.QueryBuilder) =>\n this.parseFilter(subFilter, subQuery, db, type, false),\n );\n }\n } else if (isNotCriteria(f)) {\n builder.whereNot((subQuery: Knex.QueryBuilder) =>\n this.parseFilter(f.not, subQuery, db, type, false),\n );\n }\n });\n }\n}\n"],"names":["isNotCriteria","compact","isOrCriteria","isAndCriteria"],"mappings":"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"}
@@ -9,10 +9,14 @@ class UsersStore extends BaseStore.BaseStore {
9
9
  }
10
10
  async getUsers(options) {
11
11
  const query = this.getUserBaseQuery();
12
- if (options?.entityRefs) {
12
+ if (options?.entityRefs && options.entityRefs.length > 0) {
13
13
  const authorColumn = this.db.client.config.client === "pg" ? "unique_authors.author" : "author";
14
14
  query.whereIn(authorColumn, options.entityRefs);
15
15
  }
16
+ if (options?.searchQuery) {
17
+ const authorColumn = this.db.client.config.client === "pg" ? "unique_authors.author" : "author";
18
+ this.applySearchQuery(query, [authorColumn], options.searchQuery);
19
+ }
16
20
  const totalQuery = query.clone();
17
21
  if (options?.orderBy) {
18
22
  let orderBy = options.orderBy;
@@ -27,15 +31,6 @@ class UsersStore extends BaseStore.BaseStore {
27
31
  if (options?.offset) {
28
32
  query.offset(options.offset);
29
33
  }
30
- if (options?.searchQuery) {
31
- if (this.db.client.config.client === "pg") {
32
- query.whereRaw("author % ?", [options.searchQuery]);
33
- } else {
34
- query.whereRaw("LOWER(author) LIKE LOWER(?)", [
35
- `%${options.searchQuery}%`
36
- ]);
37
- }
38
- }
39
34
  const results = await Promise.all([
40
35
  query,
41
36
  this.db(totalQuery.as("totalQuery")).count("* as CNT").first()
@@ -1 +1 @@
1
- {"version":3,"file":"UsersStore.cjs.js","sources":["../../../src/database/stores/UsersStore.ts"],"sourcesContent":["import { UserResponse, UsersResponse } from '../QetaStore';\nimport {\n UsersQuery,\n UserUsersResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { Knex } from 'knex';\nimport { BaseStore } from './BaseStore';\n\nexport interface RawUserImpact {\n userRef: string;\n impact: number;\n date: Date;\n}\n\nexport class UsersStore extends BaseStore {\n constructor(protected readonly db: Knex) {\n super(db);\n }\n\n async getUsers(\n options?: { entityRefs?: string[] } & UsersQuery,\n ): Promise<UsersResponse> {\n const query = this.getUserBaseQuery();\n if (options?.entityRefs) {\n const authorColumn =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n query.whereIn(authorColumn, options.entityRefs);\n }\n\n const totalQuery = query.clone();\n\n if (options?.orderBy) {\n let orderBy: string = options.orderBy;\n if (orderBy === 'userRef') {\n orderBy =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n }\n query.orderBy(orderBy as any, 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 if (options?.searchQuery) {\n if (this.db.client.config.client === 'pg') {\n query.whereRaw('author % ?', [options.searchQuery]);\n } else {\n query.whereRaw('LOWER(author) LIKE LOWER(?)', [\n `%${options.searchQuery}%`,\n ]);\n }\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];\n const total = this.mapToInteger((results[1] as any)?.CNT);\n\n return {\n users: rows.map((val: any) => {\n return {\n userRef: val.author,\n totalViews: this.mapToInteger(val.totalViews),\n totalQuestions: this.mapToInteger(val.totalQuestions),\n totalAnswers: this.mapToInteger(val.totalAnswers),\n totalComments: this.mapToInteger(val.totalComments),\n totalVotes: this.mapToInteger(val.totalVotes),\n totalArticles: this.mapToInteger(val.totalArticles),\n totalFollowers: this.mapToInteger(val.followerCount),\n totalLinks: this.mapToInteger(val.totalLinks),\n reputation: this.mapToInteger(val.reputation),\n answerScore: this.mapToInteger(val.answerScore),\n postScore: this.mapToInteger(val.postScore),\n correctAnswers: this.mapToInteger(val.correctAnswers),\n };\n }),\n total,\n };\n }\n\n async getUsersCount(): Promise<number> {\n if (this.db.client.config.client === 'pg') {\n const res = await this.db('unique_authors').count('* as CNT').first();\n return this.mapToInteger(res?.CNT);\n }\n const res = await this.db('posts').countDistinct('author as CNT').first();\n return this.mapToInteger(res?.CNT);\n }\n\n async getUser(user_ref: string): Promise<UserResponse | null> {\n const query = this.getUserBaseQuery();\n const authorColumn =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n const rows = await query.where(authorColumn, user_ref);\n if (rows.length === 0) {\n return null;\n }\n const val = rows[0] as any;\n return {\n userRef: val.author,\n totalViews: this.mapToInteger(val.totalViews),\n totalQuestions: this.mapToInteger(val.totalQuestions),\n totalAnswers: this.mapToInteger(val.totalAnswers),\n totalComments: this.mapToInteger(val.totalComments),\n totalVotes: this.mapToInteger(val.totalVotes),\n totalArticles: this.mapToInteger(val.totalArticles),\n totalFollowers: this.mapToInteger(val.followerCount),\n totalLinks: this.mapToInteger(val.totalLinks),\n reputation: this.mapToInteger(val.reputation),\n answerScore: this.mapToInteger(val.answerScore),\n postScore: this.mapToInteger(val.postScore),\n correctAnswers: this.mapToInteger(val.correctAnswers),\n };\n }\n\n async followUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n await this.db\n .insert({\n userRef: user_ref,\n followedUserRef,\n })\n .into('user_users');\n return true;\n }\n\n async unfollowUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n await this.db('user_users')\n .where('userRef', user_ref)\n .where('followedUserRef', followedUserRef)\n .delete();\n return true;\n }\n\n async getFollowedUsers(user_ref: string): Promise<UserUsersResponse> {\n const entities = await this.db('user_users')\n .where('userRef', user_ref)\n .select('followedUserRef');\n\n return {\n followedUserRefs: entities.map(e => e.followedUserRef),\n count: entities.length,\n };\n }\n\n async getFollowingUsers(user_ref: string): Promise<string[]> {\n const users = await this.db('user_users')\n .where('followedUserRef', user_ref)\n .select('userRef');\n return users.map(user => user.userRef);\n }\n\n private getUserBaseQuery() {\n const authorCol =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n\n return this.db('unique_authors')\n .leftJoin('user_stats_view', authorCol, 'user_stats_view.userRef')\n .select(\n authorCol,\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalViews\", 0) as \"totalViews\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalQuestions\", 0) as \"totalQuestions\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalArticles\", 0) as \"totalArticles\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalLinks\", 0) as \"totalLinks\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalAnswers\", 0) as \"totalAnswers\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalComments\", 0) as \"totalComments\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"answerVotes\", 0) as \"answerVotes\"',\n ),\n this.db.raw('COALESCE(user_stats_view.\"postVotes\", 0) as \"postVotes\"'),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalVotes\", 0) as \"totalVotes\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalPosts\", 0) as \"totalPosts\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalFollowers\", 0) as \"followerCount\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"reputation\", 0) as \"reputation\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"answerScore\", 0) as \"answerScore\"',\n ),\n this.db.raw('COALESCE(user_stats_view.\"postScore\", 0) as \"postScore\"'),\n this.db.raw(\n 'COALESCE(user_stats_view.\"correctAnswers\", 0) as \"correctAnswers\"',\n ),\n );\n }\n}\n"],"names":["BaseStore","res"],"mappings":"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"}
1
+ {"version":3,"file":"UsersStore.cjs.js","sources":["../../../src/database/stores/UsersStore.ts"],"sourcesContent":["import { UserResponse, UsersResponse } from '../QetaStore';\nimport {\n UsersQuery,\n UserUsersResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { Knex } from 'knex';\nimport { BaseStore } from './BaseStore';\n\nexport interface RawUserImpact {\n userRef: string;\n impact: number;\n date: Date;\n}\n\nexport class UsersStore extends BaseStore {\n constructor(protected readonly db: Knex) {\n super(db);\n }\n\n async getUsers(\n options?: { entityRefs?: string[] } & UsersQuery,\n ): Promise<UsersResponse> {\n const query = this.getUserBaseQuery();\n if (options?.entityRefs && options.entityRefs.length > 0) {\n const authorColumn =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n query.whereIn(authorColumn, options.entityRefs);\n }\n\n if (options?.searchQuery) {\n const authorColumn =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n this.applySearchQuery(query, [authorColumn], options.searchQuery);\n }\n\n const totalQuery = query.clone();\n\n if (options?.orderBy) {\n let orderBy: string = options.orderBy;\n if (orderBy === 'userRef') {\n orderBy =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n }\n query.orderBy(orderBy as any, 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];\n const total = this.mapToInteger((results[1] as any)?.CNT);\n\n return {\n users: rows.map((val: any) => {\n return {\n userRef: val.author,\n totalViews: this.mapToInteger(val.totalViews),\n totalQuestions: this.mapToInteger(val.totalQuestions),\n totalAnswers: this.mapToInteger(val.totalAnswers),\n totalComments: this.mapToInteger(val.totalComments),\n totalVotes: this.mapToInteger(val.totalVotes),\n totalArticles: this.mapToInteger(val.totalArticles),\n totalFollowers: this.mapToInteger(val.followerCount),\n totalLinks: this.mapToInteger(val.totalLinks),\n reputation: this.mapToInteger(val.reputation),\n answerScore: this.mapToInteger(val.answerScore),\n postScore: this.mapToInteger(val.postScore),\n correctAnswers: this.mapToInteger(val.correctAnswers),\n };\n }),\n total,\n };\n }\n\n async getUsersCount(): Promise<number> {\n if (this.db.client.config.client === 'pg') {\n const res = await this.db('unique_authors').count('* as CNT').first();\n return this.mapToInteger(res?.CNT);\n }\n const res = await this.db('posts').countDistinct('author as CNT').first();\n return this.mapToInteger(res?.CNT);\n }\n\n async getUser(user_ref: string): Promise<UserResponse | null> {\n const query = this.getUserBaseQuery();\n const authorColumn =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n const rows = await query.where(authorColumn, user_ref);\n if (rows.length === 0) {\n return null;\n }\n const val = rows[0] as any;\n return {\n userRef: val.author,\n totalViews: this.mapToInteger(val.totalViews),\n totalQuestions: this.mapToInteger(val.totalQuestions),\n totalAnswers: this.mapToInteger(val.totalAnswers),\n totalComments: this.mapToInteger(val.totalComments),\n totalVotes: this.mapToInteger(val.totalVotes),\n totalArticles: this.mapToInteger(val.totalArticles),\n totalFollowers: this.mapToInteger(val.followerCount),\n totalLinks: this.mapToInteger(val.totalLinks),\n reputation: this.mapToInteger(val.reputation),\n answerScore: this.mapToInteger(val.answerScore),\n postScore: this.mapToInteger(val.postScore),\n correctAnswers: this.mapToInteger(val.correctAnswers),\n };\n }\n\n async followUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n await this.db\n .insert({\n userRef: user_ref,\n followedUserRef,\n })\n .into('user_users');\n return true;\n }\n\n async unfollowUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n await this.db('user_users')\n .where('userRef', user_ref)\n .where('followedUserRef', followedUserRef)\n .delete();\n return true;\n }\n\n async getFollowedUsers(user_ref: string): Promise<UserUsersResponse> {\n const entities = await this.db('user_users')\n .where('userRef', user_ref)\n .select('followedUserRef');\n\n return {\n followedUserRefs: entities.map(e => e.followedUserRef),\n count: entities.length,\n };\n }\n\n async getFollowingUsers(user_ref: string): Promise<string[]> {\n const users = await this.db('user_users')\n .where('followedUserRef', user_ref)\n .select('userRef');\n return users.map(user => user.userRef);\n }\n\n private getUserBaseQuery() {\n const authorCol =\n this.db.client.config.client === 'pg'\n ? 'unique_authors.author'\n : 'author';\n\n return this.db('unique_authors')\n .leftJoin('user_stats_view', authorCol, 'user_stats_view.userRef')\n .select(\n authorCol,\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalViews\", 0) as \"totalViews\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalQuestions\", 0) as \"totalQuestions\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalArticles\", 0) as \"totalArticles\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalLinks\", 0) as \"totalLinks\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalAnswers\", 0) as \"totalAnswers\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalComments\", 0) as \"totalComments\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"answerVotes\", 0) as \"answerVotes\"',\n ),\n this.db.raw('COALESCE(user_stats_view.\"postVotes\", 0) as \"postVotes\"'),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalVotes\", 0) as \"totalVotes\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalPosts\", 0) as \"totalPosts\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"totalFollowers\", 0) as \"followerCount\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"reputation\", 0) as \"reputation\"',\n ),\n this.db.raw(\n 'COALESCE(user_stats_view.\"answerScore\", 0) as \"answerScore\"',\n ),\n this.db.raw('COALESCE(user_stats_view.\"postScore\", 0) as \"postScore\"'),\n this.db.raw(\n 'COALESCE(user_stats_view.\"correctAnswers\", 0) as \"correctAnswers\"',\n ),\n );\n }\n}\n"],"names":["BaseStore","res"],"mappings":";;;;AAcO,MAAM,mBAAmBA,mBAAU,CAAA;AAAA,EACxC,YAA+B,EAAU,EAAA;AACvC,IAAA,KAAA,CAAM,EAAE,CAAA;AADqB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AAAA;AAE/B,EAEA,MAAM,SACJ,OACwB,EAAA;AACxB,IAAM,MAAA,KAAA,GAAQ,KAAK,gBAAiB,EAAA;AACpC,IAAA,IAAI,OAAS,EAAA,UAAA,IAAc,OAAQ,CAAA,UAAA,CAAW,SAAS,CAAG,EAAA;AACxD,MAAA,MAAM,eACJ,IAAK,CAAA,EAAA,CAAG,OAAO,MAAO,CAAA,MAAA,KAAW,OAC7B,uBACA,GAAA,QAAA;AACN,MAAM,KAAA,CAAA,OAAA,CAAQ,YAAc,EAAA,OAAA,CAAQ,UAAU,CAAA;AAAA;AAGhD,IAAA,IAAI,SAAS,WAAa,EAAA;AACxB,MAAA,MAAM,eACJ,IAAK,CAAA,EAAA,CAAG,OAAO,MAAO,CAAA,MAAA,KAAW,OAC7B,uBACA,GAAA,QAAA;AACN,MAAA,IAAA,CAAK,iBAAiB,KAAO,EAAA,CAAC,YAAY,CAAA,EAAG,QAAQ,WAAW,CAAA;AAAA;AAGlE,IAAM,MAAA,UAAA,GAAa,MAAM,KAAM,EAAA;AAE/B,IAAA,IAAI,SAAS,OAAS,EAAA;AACpB,MAAA,IAAI,UAAkB,OAAQ,CAAA,OAAA;AAC9B,MAAA,IAAI,YAAY,SAAW,EAAA;AACzB,QAAA,OAAA,GACE,KAAK,EAAG,CAAA,MAAA,CAAO,MAAO,CAAA,MAAA,KAAW,OAC7B,uBACA,GAAA,QAAA;AAAA;AAER,MAAA,KAAA,CAAM,OAAQ,CAAA,OAAA,EAAgB,OAAS,EAAA,KAAA,IAAS,MAAM,CAAA;AAAA;AAGxD,IAAA,IAAI,SAAS,KAAO,EAAA;AAClB,MAAM,KAAA,CAAA,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA;AAG3B,IAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,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,KAAO,EAAA,IAAA,CAAK,GAAI,CAAA,CAAC,GAAa,KAAA;AAC5B,QAAO,OAAA;AAAA,UACL,SAAS,GAAI,CAAA,MAAA;AAAA,UACb,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,UAC5C,cAAgB,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,cAAc,CAAA;AAAA,UACpD,YAAc,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,YAAY,CAAA;AAAA,UAChD,aAAe,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,aAAa,CAAA;AAAA,UAClD,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,UAC5C,aAAe,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,aAAa,CAAA;AAAA,UAClD,cAAgB,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,aAAa,CAAA;AAAA,UACnD,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,UAC5C,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,UAC5C,WAAa,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,WAAW,CAAA;AAAA,UAC9C,SAAW,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,SAAS,CAAA;AAAA,UAC1C,cAAgB,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,cAAc;AAAA,SACtD;AAAA,OACD,CAAA;AAAA,MACD;AAAA,KACF;AAAA;AACF,EAEA,MAAM,aAAiC,GAAA;AACrC,IAAA,IAAI,IAAK,CAAA,EAAA,CAAG,MAAO,CAAA,MAAA,CAAO,WAAW,IAAM,EAAA;AACzC,MAAMC,MAAAA,IAAAA,GAAM,MAAM,IAAK,CAAA,EAAA,CAAG,gBAAgB,CAAE,CAAA,KAAA,CAAM,UAAU,CAAA,CAAE,KAAM,EAAA;AACpE,MAAO,OAAA,IAAA,CAAK,YAAaA,CAAAA,IAAAA,EAAK,GAAG,CAAA;AAAA;AAEnC,IAAM,MAAA,GAAA,GAAM,MAAM,IAAK,CAAA,EAAA,CAAG,OAAO,CAAE,CAAA,aAAA,CAAc,eAAe,CAAA,CAAE,KAAM,EAAA;AACxE,IAAO,OAAA,IAAA,CAAK,YAAa,CAAA,GAAA,EAAK,GAAG,CAAA;AAAA;AACnC,EAEA,MAAM,QAAQ,QAAgD,EAAA;AAC5D,IAAM,MAAA,KAAA,GAAQ,KAAK,gBAAiB,EAAA;AACpC,IAAA,MAAM,eACJ,IAAK,CAAA,EAAA,CAAG,OAAO,MAAO,CAAA,MAAA,KAAW,OAC7B,uBACA,GAAA,QAAA;AACN,IAAA,MAAM,IAAO,GAAA,MAAM,KAAM,CAAA,KAAA,CAAM,cAAc,QAAQ,CAAA;AACrD,IAAI,IAAA,IAAA,CAAK,WAAW,CAAG,EAAA;AACrB,MAAO,OAAA,IAAA;AAAA;AAET,IAAM,MAAA,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAO,OAAA;AAAA,MACL,SAAS,GAAI,CAAA,MAAA;AAAA,MACb,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,MAC5C,cAAgB,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,cAAc,CAAA;AAAA,MACpD,YAAc,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,YAAY,CAAA;AAAA,MAChD,aAAe,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,aAAa,CAAA;AAAA,MAClD,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,MAC5C,aAAe,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,aAAa,CAAA;AAAA,MAClD,cAAgB,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,aAAa,CAAA;AAAA,MACnD,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,MAC5C,UAAY,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,MAC5C,WAAa,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,WAAW,CAAA;AAAA,MAC9C,SAAW,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,SAAS,CAAA;AAAA,MAC1C,cAAgB,EAAA,IAAA,CAAK,YAAa,CAAA,GAAA,CAAI,cAAc;AAAA,KACtD;AAAA;AACF,EAEA,MAAM,UACJ,CAAA,QAAA,EACA,eACkB,EAAA;AAClB,IAAM,MAAA,IAAA,CAAK,GACR,MAAO,CAAA;AAAA,MACN,OAAS,EAAA,QAAA;AAAA,MACT;AAAA,KACD,CACA,CAAA,IAAA,CAAK,YAAY,CAAA;AACpB,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,YACJ,CAAA,QAAA,EACA,eACkB,EAAA;AAClB,IAAA,MAAM,IAAK,CAAA,EAAA,CAAG,YAAY,CAAA,CACvB,KAAM,CAAA,SAAA,EAAW,QAAQ,CAAA,CACzB,KAAM,CAAA,iBAAA,EAAmB,eAAe,CAAA,CACxC,MAAO,EAAA;AACV,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,iBAAiB,QAA8C,EAAA;AACnE,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,EAAG,CAAA,YAAY,CACxC,CAAA,KAAA,CAAM,SAAW,EAAA,QAAQ,CACzB,CAAA,MAAA,CAAO,iBAAiB,CAAA;AAE3B,IAAO,OAAA;AAAA,MACL,gBAAkB,EAAA,QAAA,CAAS,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,eAAe,CAAA;AAAA,MACrD,OAAO,QAAS,CAAA;AAAA,KAClB;AAAA;AACF,EAEA,MAAM,kBAAkB,QAAqC,EAAA;AAC3D,IAAM,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,EAAG,CAAA,YAAY,CACrC,CAAA,KAAA,CAAM,iBAAmB,EAAA,QAAQ,CACjC,CAAA,MAAA,CAAO,SAAS,CAAA;AACnB,IAAA,OAAO,KAAM,CAAA,GAAA,CAAI,CAAQ,IAAA,KAAA,IAAA,CAAK,OAAO,CAAA;AAAA;AACvC,EAEQ,gBAAmB,GAAA;AACzB,IAAA,MAAM,YACJ,IAAK,CAAA,EAAA,CAAG,OAAO,MAAO,CAAA,MAAA,KAAW,OAC7B,uBACA,GAAA,QAAA;AAEN,IAAO,OAAA,IAAA,CAAK,GAAG,gBAAgB,CAAA,CAC5B,SAAS,iBAAmB,EAAA,SAAA,EAAW,yBAAyB,CAChE,CAAA,MAAA;AAAA,MACC,SAAA;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,IAAA,CAAK,EAAG,CAAA,GAAA,CAAI,yDAAyD,CAAA;AAAA,MACrE,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,IAAA,CAAK,EAAG,CAAA,GAAA,CAAI,yDAAyD,CAAA;AAAA,MACrE,KAAK,EAAG,CAAA,GAAA;AAAA,QACN;AAAA;AACF,KACF;AAAA;AAEN;;;;"}
@@ -199,7 +199,6 @@ const postsRoutes = (router, options) => {
199
199
  includeAttachments: false,
200
200
  includeExperts: false
201
201
  });
202
- console.log(`Request ${JSON.stringify(request.body)}`);
203
202
  const posts = await database.suggestPosts(
204
203
  username,
205
204
  title,
@@ -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 console.log(`Request ${JSON.stringify(request.body)}`);\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 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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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ exports.up = async function up(knex) {
6
+ if (knex.client.config.client === 'pg') {
7
+ try {
8
+ await knex.raw('CREATE EXTENSION IF NOT EXISTS pg_trgm');
9
+ } catch (error) {
10
+ const message =
11
+ 'Failed to create the "pg_trgm" extension. ' +
12
+ 'Ensure that the extension is installed and that the database user running migrations ' +
13
+ 'has sufficient privileges (typically CREATE EXTENSION), or ask a database administrator ' +
14
+ 'to install the extension in the target database before running this migration. ' +
15
+ `Original error: ${
16
+ error instanceof Error ? error.message : String(error)
17
+ }`;
18
+ throw new Error(message);
19
+ }
20
+
21
+ await knex.raw(
22
+ 'CREATE INDEX IF NOT EXISTS posts_title_trgm_idx ON posts USING gin (title gin_trgm_ops)',
23
+ );
24
+ await knex.raw(
25
+ 'CREATE INDEX IF NOT EXISTS posts_content_trgm_idx ON posts USING gin (content gin_trgm_ops)',
26
+ );
27
+
28
+ await knex.raw(
29
+ 'CREATE INDEX IF NOT EXISTS posts_author_trgm_idx ON posts USING gin (author gin_trgm_ops)',
30
+ );
31
+
32
+ await knex.raw(
33
+ 'CREATE INDEX IF NOT EXISTS tags_tag_trgm_idx ON tags USING gin (tag gin_trgm_ops)',
34
+ );
35
+
36
+ await knex.raw(
37
+ 'CREATE INDEX IF NOT EXISTS answers_content_trgm_idx ON answers USING gin (content gin_trgm_ops)',
38
+ );
39
+
40
+ await knex.raw(
41
+ 'CREATE INDEX IF NOT EXISTS comments_content_trgm_idx ON comments USING gin (content gin_trgm_ops)',
42
+ );
43
+
44
+ await knex.raw(
45
+ 'CREATE INDEX IF NOT EXISTS collections_title_trgm_idx ON collections USING gin (title gin_trgm_ops)',
46
+ );
47
+
48
+ await knex.raw('DROP INDEX IF EXISTS questions_search_content_index');
49
+ await knex.raw('DROP INDEX IF EXISTS tag_search_content_index');
50
+ await knex.raw('DROP INDEX IF EXISTS collection_search_content_index');
51
+ await knex.raw('DROP INDEX IF EXISTS answer_search_content_index');
52
+ }
53
+ };
54
+
55
+ /**
56
+ * @param { import("knex").Knex } knex
57
+ * @returns { Promise<void> }
58
+ */
59
+ exports.down = async function down(knex) {
60
+ if (knex.client.config.client === 'pg') {
61
+ await knex.raw('DROP INDEX IF EXISTS posts_title_trgm_idx');
62
+ await knex.raw('DROP INDEX IF EXISTS posts_content_trgm_idx');
63
+ await knex.raw('DROP INDEX IF EXISTS posts_author_trgm_idx');
64
+ await knex.raw('DROP INDEX IF EXISTS tags_tag_trgm_idx');
65
+ await knex.raw('DROP INDEX IF EXISTS answers_content_trgm_idx');
66
+ await knex.raw('DROP INDEX IF EXISTS comments_content_trgm_idx');
67
+ await knex.raw('DROP INDEX IF EXISTS collections_title_trgm_idx');
68
+ await knex.raw('DROP EXTENSION IF EXISTS pg_trgm');
69
+
70
+ // Restore
71
+ await knex.schema.raw(
72
+ `CREATE INDEX questions_search_content_index ON questions USING GIN (to_tsvector('english', title || ' ' || content))`,
73
+ );
74
+ await knex.schema.raw(
75
+ `CREATE INDEX tag_search_content_index ON tags USING GIN (to_tsvector('english', tag || ' ' || description))`,
76
+ );
77
+ await knex.schema.raw(
78
+ `CREATE INDEX collection_search_content_index ON collections USING GIN (to_tsvector('english', title || ' ' || description))`,
79
+ );
80
+ await knex.schema.raw(
81
+ `CREATE INDEX answer_search_content_index ON answers USING GIN (to_tsvector('english', content))`,
82
+ );
83
+ }
84
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drodil/backstage-plugin-qeta-backend",
3
- "version": "3.52.5",
3
+ "version": "3.52.6",
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.52.5",
70
- "@drodil/backstage-plugin-qeta-node": "^3.52.5",
69
+ "@drodil/backstage-plugin-qeta-common": "^3.52.6",
70
+ "@drodil/backstage-plugin-qeta-node": "^3.52.6",
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.52.5",
109
- "@drodil/backstage-plugin-qeta-backend-module-openai": "^3.52.5",
110
- "@drodil/backstage-plugin-search-backend-module-qeta": "^3.52.5",
108
+ "@drodil/backstage-plugin-catalog-backend-module-qeta": "^3.52.6",
109
+ "@drodil/backstage-plugin-qeta-backend-module-openai": "^3.52.6",
110
+ "@drodil/backstage-plugin-search-backend-module-qeta": "^3.52.6",
111
111
  "@types/sanitize-html": "^2.9.5",
112
112
  "@types/stopword": "^2.0.3",
113
113
  "@types/supertest": "^2.0.12",