You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.6 KiB

11 months ago
  1. const { SystemSettings } = require("../models/systemSettings");
  2. const { validatedRequest } = require("../utils/middleware/validatedRequest");
  3. const { reqBody } = require("../utils/http");
  4. const { CommunityHub } = require("../models/communityHub");
  5. const {
  6. communityHubDownloadsEnabled,
  7. communityHubItem,
  8. } = require("../utils/middleware/communityHubDownloadsEnabled");
  9. const { EventLogs } = require("../models/eventLogs");
  10. const { Telemetry } = require("../models/telemetry");
  11. const {
  12. flexUserRoleValid,
  13. ROLES,
  14. } = require("../utils/middleware/multiUserProtected");
  15. function communityHubEndpoints(app) {
  16. if (!app) return;
  17. app.get(
  18. "/community-hub/settings",
  19. [validatedRequest, flexUserRoleValid([ROLES.admin])],
  20. async (_, response) => {
  21. try {
  22. const { connectionKey } = await SystemSettings.hubSettings();
  23. response.status(200).json({ success: true, connectionKey });
  24. } catch (error) {
  25. console.error(error);
  26. response.status(500).json({ success: false, error: error.message });
  27. }
  28. }
  29. );
  30. app.post(
  31. "/community-hub/settings",
  32. [validatedRequest, flexUserRoleValid([ROLES.admin])],
  33. async (request, response) => {
  34. try {
  35. const data = reqBody(request);
  36. const result = await SystemSettings.updateSettings(data);
  37. if (result.error) throw new Error(result.error);
  38. response.status(200).json({ success: true, error: null });
  39. } catch (error) {
  40. console.error(error);
  41. response.status(500).json({ success: false, error: error.message });
  42. }
  43. }
  44. );
  45. app.get(
  46. "/community-hub/explore",
  47. [validatedRequest, flexUserRoleValid([ROLES.admin])],
  48. async (_, response) => {
  49. try {
  50. const exploreItems = await CommunityHub.fetchExploreItems();
  51. response.status(200).json({ success: true, result: exploreItems });
  52. } catch (error) {
  53. console.error(error);
  54. response.status(500).json({
  55. success: false,
  56. result: null,
  57. error: error.message,
  58. });
  59. }
  60. }
  61. );
  62. app.post(
  63. "/community-hub/item",
  64. [validatedRequest, flexUserRoleValid([ROLES.admin]), communityHubItem],
  65. async (_request, response) => {
  66. try {
  67. response.status(200).json({
  68. success: true,
  69. item: response.locals.bundleItem,
  70. error: null,
  71. });
  72. } catch (error) {
  73. console.error(error);
  74. response.status(500).json({
  75. success: false,
  76. item: null,
  77. error: error.message,
  78. });
  79. }
  80. }
  81. );
  82. /**
  83. * Apply an item to the AnythingLLM instance. Used for simple items like slash commands and system prompts.
  84. */
  85. app.post(
  86. "/community-hub/apply",
  87. [validatedRequest, flexUserRoleValid([ROLES.admin]), communityHubItem],
  88. async (request, response) => {
  89. try {
  90. const { options = {} } = reqBody(request);
  91. const item = response.locals.bundleItem;
  92. const { error: applyError } = await CommunityHub.applyItem(item, {
  93. ...options,
  94. currentUser: response.locals?.user,
  95. });
  96. if (applyError) throw new Error(applyError);
  97. await Telemetry.sendTelemetry("community_hub_import", {
  98. itemType: response.locals.bundleItem.itemType,
  99. visibility: response.locals.bundleItem.visibility,
  100. });
  101. await EventLogs.logEvent(
  102. "community_hub_import",
  103. {
  104. itemId: response.locals.bundleItem.id,
  105. itemType: response.locals.bundleItem.itemType,
  106. },
  107. response.locals?.user?.id
  108. );
  109. response.status(200).json({ success: true, error: null });
  110. } catch (error) {
  111. console.error(error);
  112. response.status(500).json({ success: false, error: error.message });
  113. }
  114. }
  115. );
  116. /**
  117. * Import a bundle item to the AnythingLLM instance by downloading the zip file and importing it.
  118. * or whatever the item type requires. This is not used if the item is a simple text responses like
  119. * slash commands or system prompts.
  120. */
  121. app.post(
  122. "/community-hub/import",
  123. [
  124. validatedRequest,
  125. flexUserRoleValid([ROLES.admin]),
  126. communityHubItem,
  127. communityHubDownloadsEnabled,
  128. ],
  129. async (_, response) => {
  130. try {
  131. const { error: importError } = await CommunityHub.importBundleItem({
  132. url: response.locals.bundleUrl,
  133. item: response.locals.bundleItem,
  134. });
  135. if (importError) throw new Error(importError);
  136. await Telemetry.sendTelemetry("community_hub_import", {
  137. itemType: response.locals.bundleItem.itemType,
  138. visibility: response.locals.bundleItem.visibility,
  139. });
  140. await EventLogs.logEvent(
  141. "community_hub_import",
  142. {
  143. itemId: response.locals.bundleItem.id,
  144. itemType: response.locals.bundleItem.itemType,
  145. },
  146. response.locals?.user?.id
  147. );
  148. response.status(200).json({ success: true, error: null });
  149. } catch (error) {
  150. console.error(error);
  151. response.status(500).json({
  152. success: false,
  153. error: error.message,
  154. });
  155. }
  156. }
  157. );
  158. app.get(
  159. "/community-hub/items",
  160. [validatedRequest, flexUserRoleValid([ROLES.admin])],
  161. async (_, response) => {
  162. try {
  163. const { connectionKey } = await SystemSettings.hubSettings();
  164. const items = await CommunityHub.fetchUserItems(connectionKey);
  165. response.status(200).json({ success: true, ...items });
  166. } catch (error) {
  167. console.error(error);
  168. response.status(500).json({ success: false, error: error.message });
  169. }
  170. }
  171. );
  172. }
  173. module.exports = { communityHubEndpoints };