storage.mjs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import _ from 'lodash-es'
  2. import { generateError, generateSuccess } from '../../helpers/graph.mjs'
  3. import { v4 as uuid } from 'uuid'
  4. export default {
  5. Query: {
  6. async storageTargets (obj, args, context, info) {
  7. const dbTargets = await WIKI.db.storage.getTargets({ siteId: args.siteId })
  8. // targets = _.sortBy(targets.map(tgt => {
  9. // const targetInfo = _.find(WIKI.data.storage, ['module', tgt.key]) || {}
  10. // return {
  11. // ...targetInfo,
  12. // ...tgt,
  13. // hasSchedule: (targetInfo.schedule !== false),
  14. // syncInterval: targetInfo.syncInterval || targetInfo.schedule || 'P0D',
  15. // syncIntervalDefault: targetInfo.schedule,
  16. // config: _.sortBy(_.transform(tgt.config, (res, value, key) => {
  17. // const configData = _.get(targetInfo.props, key, false)
  18. // if (configData) {
  19. // res.push({
  20. // key,
  21. // value: JSON.stringify({
  22. // ...configData,
  23. // value: (configData.sensitive && value.length > 0) ? '********' : value
  24. // })
  25. // })
  26. // }
  27. // }, []), 'key')
  28. // }
  29. // }), ['title', 'key'])
  30. return _.sortBy(WIKI.storage.defs.map(md => {
  31. const dbTarget = dbTargets.find(tg => tg.module === md.key)
  32. return {
  33. id: dbTarget?.id ?? uuid(),
  34. isEnabled: dbTarget?.isEnabled ?? false,
  35. module: md.key,
  36. title: md.title,
  37. description: md.description,
  38. icon: md.icon,
  39. banner: md.banner,
  40. vendor: md.vendor,
  41. website: md.website,
  42. contentTypes: {
  43. activeTypes: dbTarget?.contentTypes?.activeTypes ?? md.contentTypes.defaultTypesEnabled,
  44. largeThreshold: dbTarget?.contentTypes?.largeThreshold ?? md.contentTypes.defaultLargeThreshold
  45. },
  46. assetDelivery: {
  47. isStreamingSupported: md?.assetDelivery?.isStreamingSupported ?? false,
  48. isDirectAccessSupported: md?.assetDelivery?.isDirectAccessSupported ?? false,
  49. streaming: dbTarget?.assetDelivery?.streaming ?? md?.assetDelivery?.defaultStreamingEnabled ?? false,
  50. directAccess: dbTarget?.assetDelivery?.directAccess ?? md?.assetDelivery?.defaultDirectAccessEnabled ?? false
  51. },
  52. versioning: {
  53. isSupported: md?.versioning?.isSupported ?? false,
  54. isForceEnabled: md?.versioning?.isForceEnabled ?? false,
  55. enabled: dbTarget?.versioning?.enabled ?? md?.versioning?.defaultEnabled ?? false
  56. },
  57. sync: {},
  58. status: {},
  59. setup: {
  60. handler: md?.setup?.handler,
  61. state: dbTarget?.state?.setup ?? 'notconfigured',
  62. values: md.setup?.handler ?
  63. _.transform(md.setup.defaultValues,
  64. (r, v, k) => {
  65. r[k] = dbTarget?.config?.[k] ?? v
  66. }, {}) :
  67. {}
  68. },
  69. config: _.transform(md.props, (r, v, k) => {
  70. const cfValue = dbTarget?.config?.[k] ?? v.default
  71. r[k] = {
  72. ...v,
  73. value: v.sensitive && cfValue ? '********' : cfValue,
  74. ...v.enum && {
  75. enum: v.enum.map(o => {
  76. if (o.indexOf('|') > 0) {
  77. const oParsed = o.split('|')
  78. return {
  79. value: oParsed[0],
  80. label: oParsed[1]
  81. }
  82. } else {
  83. return {
  84. value: o,
  85. label: o
  86. }
  87. }
  88. })
  89. }
  90. }
  91. }, {}),
  92. actions: md.actions
  93. }
  94. }), ['title'])
  95. }
  96. },
  97. Mutation: {
  98. async updateStorageTargets (obj, args, context) {
  99. WIKI.logger.debug(`Updating storage targets for site ${args.siteId}...`)
  100. try {
  101. const dbTargets = await WIKI.db.storage.getTargets({ siteId: args.siteId })
  102. for (const tgt of args.targets) {
  103. const md = _.find(WIKI.storage.defs, ['key', tgt.module])
  104. if (!md) {
  105. throw new Error('Invalid module key for non-existent storage target.')
  106. }
  107. const dbTarget = _.find(dbTargets, ['id', tgt.id])
  108. // -> Build update config object
  109. const updatedConfig = dbTarget?.config ?? {}
  110. if (tgt.config) {
  111. for (const [key, prop] of Object.entries(md.props)) {
  112. if (prop.readOnly) { continue }
  113. if (!Object.prototype.hasOwnProperty.call(tgt.config, key)) { continue }
  114. if (prop.sensitive && tgt.config[key] === '********') { continue }
  115. updatedConfig[key] = tgt.config[key]
  116. }
  117. }
  118. // -> Target doesn't exist yet in the DB, let's create it
  119. if (!dbTarget) {
  120. WIKI.logger.debug(`No existing DB configuration for module ${tgt.module}. Creating a new one...`)
  121. await WIKI.db.storage.query().insert({
  122. id: tgt.id,
  123. module: tgt.module,
  124. siteId: args.siteId,
  125. isEnabled: tgt.isEnabled ?? false,
  126. contentTypes: {
  127. activeTypes: tgt.contentTypes ?? md.contentTypes.defaultTypesEnabled ?? [],
  128. largeThreshold: tgt.largeThreshold ?? md.contentTypes.defaultLargeThreshold ?? '5MB'
  129. },
  130. assetDelivery: {
  131. streaming: tgt.assetDeliveryFileStreaming ?? md?.assetDelivery?.defaultStreamingEnabled ?? false,
  132. directAccess: tgt.assetDeliveryDirectAccess ?? md?.assetDelivery?.defaultDirectAccessEnabled ?? false
  133. },
  134. versioning: {
  135. enabled: tgt.useVersioning ?? md?.versioning?.defaultEnabled ?? false
  136. },
  137. state: {
  138. current: 'ok'
  139. },
  140. config: updatedConfig
  141. })
  142. } else {
  143. WIKI.logger.debug(`Updating DB configuration for module ${tgt.module}...`)
  144. await WIKI.db.storage.query().patch({
  145. isEnabled: tgt.isEnabled ?? dbTarget.isEnabled ?? false,
  146. contentTypes: {
  147. activeTypes: tgt.contentTypes ?? dbTarget?.contentTypes?.activeTypes ?? [],
  148. largeThreshold: tgt.largeThreshold ?? dbTarget?.contentTypes?.largeThreshold ?? '5MB'
  149. },
  150. assetDelivery: {
  151. streaming: tgt.assetDeliveryFileStreaming ?? dbTarget?.assetDelivery?.streaming ?? false,
  152. directAccess: tgt.assetDeliveryDirectAccess ?? dbTarget?.assetDelivery?.directAccess ?? false
  153. },
  154. versioning: {
  155. enabled: tgt.useVersioning ?? dbTarget?.versioning?.enabled ?? false
  156. },
  157. config: updatedConfig
  158. }).where('id', tgt.id)
  159. }
  160. }
  161. // await WIKI.db.storage.initTargets()
  162. return {
  163. operation: generateSuccess('Storage targets updated successfully')
  164. }
  165. } catch (err) {
  166. return generateError(err)
  167. }
  168. },
  169. async setupStorageTarget (obj, args, context) {
  170. try {
  171. const tgt = await WIKI.db.storage.query().findById(args.targetId)
  172. if (!tgt) {
  173. throw new Error('Not storage target matching this ID')
  174. }
  175. const md = _.find(WIKI.storage.defs, ['key', tgt.module])
  176. if (!md) {
  177. throw new Error('No matching storage module installed.')
  178. }
  179. if (!await WIKI.db.storage.ensureModule(md.key)) {
  180. throw new Error('Failed to load storage module. Check logs for details.')
  181. }
  182. const result = await WIKI.storage.modules[md.key].setup(args.targetId, args.state)
  183. return {
  184. operation: generateSuccess('Storage target setup step succeeded'),
  185. state: result
  186. }
  187. } catch (err) {
  188. return generateError(err)
  189. }
  190. },
  191. async destroyStorageTargetSetup (obj, args, context) {
  192. try {
  193. const tgt = await WIKI.db.storage.query().findById(args.targetId)
  194. if (!tgt) {
  195. throw new Error('Not storage target matching this ID')
  196. }
  197. const md = _.find(WIKI.storage.defs, ['key', tgt.module])
  198. if (!md) {
  199. throw new Error('No matching storage module installed.')
  200. }
  201. if (!await WIKI.db.storage.ensureModule(md.key)) {
  202. throw new Error('Failed to load storage module. Check logs for details.')
  203. }
  204. await WIKI.storage.modules[md.key].setupDestroy(args.targetId)
  205. return {
  206. operation: generateSuccess('Storage target setup configuration destroyed succesfully.')
  207. }
  208. } catch (err) {
  209. return generateError(err)
  210. }
  211. },
  212. async executeStorageAction (obj, args, context) {
  213. try {
  214. await WIKI.db.storage.executeAction(args.targetKey, args.handler)
  215. return {
  216. operation: generateSuccess('Action completed.')
  217. }
  218. } catch (err) {
  219. return generateError(err)
  220. }
  221. }
  222. }
  223. }