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.

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