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.

202 lines
6.3 KiB

  1. const _ = require('lodash')
  2. const sanitize = require('sanitize-filename')
  3. const graphHelper = require('../../helpers/graph')
  4. const assetHelper = require('../../helpers/asset')
  5. /* global WIKI */
  6. module.exports = {
  7. Query: {
  8. async assets() { return {} }
  9. },
  10. Mutation: {
  11. async assets() { return {} }
  12. },
  13. AssetQuery: {
  14. async list(obj, args, context) {
  15. let cond = {
  16. folderId: args.folderId === 0 ? null : args.folderId
  17. }
  18. if (args.kind !== 'ALL') {
  19. cond.kind = args.kind.toLowerCase()
  20. }
  21. const result = await WIKI.models.assets.query().where(cond)
  22. return result.map(a => ({
  23. ...a,
  24. kind: a.kind.toUpperCase()
  25. }))
  26. },
  27. async folders(obj, args, context) {
  28. const result = await WIKI.models.assetFolders.query().where({
  29. parentId: args.parentFolderId === 0 ? null : args.parentFolderId
  30. })
  31. // TODO: Filter by page rules
  32. return result
  33. }
  34. },
  35. AssetMutation: {
  36. /**
  37. * Create New Asset Folder
  38. */
  39. async createFolder(obj, args, context) {
  40. try {
  41. const folderSlug = sanitize(args.slug).toLowerCase()
  42. const parentFolderId = args.parentFolderId === 0 ? null : args.parentFolderId
  43. const result = await WIKI.models.assetFolders.query().where({
  44. parentId: parentFolderId,
  45. slug: folderSlug
  46. }).first()
  47. if (!result) {
  48. await WIKI.models.assetFolders.query().insert({
  49. slug: folderSlug,
  50. name: folderSlug,
  51. parentId: parentFolderId
  52. })
  53. return {
  54. responseResult: graphHelper.generateSuccess('Asset Folder has been created successfully.')
  55. }
  56. } else {
  57. throw new WIKI.Error.AssetFolderExists()
  58. }
  59. } catch (err) {
  60. return graphHelper.generateError(err)
  61. }
  62. },
  63. /**
  64. * Rename an Asset
  65. */
  66. async renameAsset(obj, args, context) {
  67. try {
  68. const filename = sanitize(args.filename).toLowerCase()
  69. const asset = await WIKI.models.assets.query().findById(args.id)
  70. if (asset) {
  71. // Check for extension mismatch
  72. if (!_.endsWith(filename, asset.ext)) {
  73. throw new WIKI.Error.AssetRenameInvalidExt()
  74. }
  75. // Check for non-dot files changing to dotfile
  76. if (asset.ext.length > 0 && filename.length - asset.ext.length < 1) {
  77. throw new WIKI.Error.AssetRenameInvalid()
  78. }
  79. // Check for collision
  80. const assetCollision = await WIKI.models.assets.query().where({
  81. filename,
  82. folderId: asset.folderId
  83. }).first()
  84. if (assetCollision) {
  85. throw new WIKI.Error.AssetRenameCollision()
  86. }
  87. // Get asset folder path
  88. let hierarchy = []
  89. if (asset.folderId) {
  90. hierarchy = await WIKI.models.assetFolders.getHierarchy(asset.folderId)
  91. }
  92. // Check source asset permissions
  93. const assetSourcePath = (asset.folderId) ? hierarchy.map(h => h.slug).join('/') + `/${asset.filename}` : asset.filename
  94. if (!WIKI.auth.checkAccess(context.req.user, ['manage:assets'], { path: assetSourcePath })) {
  95. throw new WIKI.Error.AssetRenameForbidden()
  96. }
  97. // Check target asset permissions
  98. const assetTargetPath = (asset.folderId) ? hierarchy.map(h => h.slug).join('/') + `/${filename}` : filename
  99. if (!WIKI.auth.checkAccess(context.req.user, ['write:assets'], { path: assetTargetPath })) {
  100. throw new WIKI.Error.AssetRenameTargetForbidden()
  101. }
  102. // Update filename + hash
  103. const fileHash = assetHelper.generateHash(assetTargetPath)
  104. await WIKI.models.assets.query().patch({
  105. filename: filename,
  106. hash: fileHash
  107. }).findById(args.id)
  108. // Delete old asset cache
  109. await asset.deleteAssetCache()
  110. // Rename in Storage
  111. await WIKI.models.storage.assetEvent({
  112. event: 'renamed',
  113. asset: {
  114. ...asset,
  115. path: assetSourcePath,
  116. destinationPath: assetTargetPath,
  117. moveAuthorId: context.req.user.id,
  118. moveAuthorName: context.req.user.name,
  119. moveAuthorEmail: context.req.user.email
  120. }
  121. })
  122. return {
  123. responseResult: graphHelper.generateSuccess('Asset has been renamed successfully.')
  124. }
  125. } else {
  126. throw new WIKI.Error.AssetInvalid()
  127. }
  128. } catch (err) {
  129. return graphHelper.generateError(err)
  130. }
  131. },
  132. /**
  133. * Delete an Asset
  134. */
  135. async deleteAsset(obj, args, context) {
  136. try {
  137. const asset = await WIKI.models.assets.query().findById(args.id)
  138. if (asset) {
  139. // Check permissions
  140. const assetPath = await asset.getAssetPath()
  141. if (!WIKI.auth.checkAccess(context.req.user, ['manage:assets'], { path: assetPath })) {
  142. throw new WIKI.Error.AssetDeleteForbidden()
  143. }
  144. await WIKI.models.knex('assetData').where('id', args.id).del()
  145. await WIKI.models.assets.query().deleteById(args.id)
  146. await asset.deleteAssetCache()
  147. // Delete from Storage
  148. await WIKI.models.storage.assetEvent({
  149. event: 'deleted',
  150. asset: {
  151. ...asset,
  152. path: assetPath,
  153. authorId: context.req.user.id,
  154. authorName: context.req.user.name,
  155. authorEmail: context.req.user.email
  156. }
  157. })
  158. return {
  159. responseResult: graphHelper.generateSuccess('Asset has been deleted successfully.')
  160. }
  161. } else {
  162. throw new WIKI.Error.AssetInvalid()
  163. }
  164. } catch (err) {
  165. return graphHelper.generateError(err)
  166. }
  167. },
  168. /**
  169. * Flush Temporary Uploads
  170. */
  171. async flushTempUploads(obj, args, context) {
  172. try {
  173. await WIKI.models.assets.flushTempUploads()
  174. return {
  175. responseResult: graphHelper.generateSuccess('Temporary Uploads have been flushed successfully.')
  176. }
  177. } catch (err) {
  178. return graphHelper.generateError(err)
  179. }
  180. }
  181. }
  182. // File: {
  183. // folder(fl) {
  184. // return fl.getFolder()
  185. // }
  186. // }
  187. }