@@ -4,6 +4,8 @@ import { AdminForthPlugin, AdminForthResourceColumn, AdminForthResource, Filters
44import { Readable } from "stream" ;
55import { RateLimiter } from "adminforth" ;
66import { randomUUID } from "crypto" ;
7+ import { interpretResource } from 'adminforth' ;
8+ import { ActionCheckSource } from 'adminforth' ;
79
810const ADMINFORTH_NOT_YET_USED_TAG = 'adminforth-candidate-for-cleanup' ;
911const jobs = new Map ( ) ;
@@ -164,32 +166,11 @@ export default class UploadPlugin extends AdminForthPlugin {
164166 minShowWidth : this . options . preview ?. minShowWidth ,
165167 generationPrompt : this . options . generation ?. generationPrompt ,
166168 recorPkFieldName : this . resourceConfig . columns . find ( ( column : any ) => column . primaryKey ) ?. name ,
169+ pathColumnName : this . options . pathColumnName ,
167170 } ;
168171 // define components which will be imported from other components
169172 this . componentPath ( 'imageGenerator.vue' ) ;
170173
171- const virtualColumn : AdminForthResourceColumn = {
172- virtual : true ,
173- name : `uploader_${ this . pluginInstanceId } ` ,
174- components : {
175- edit : {
176- file : this . componentPath ( 'uploader.vue' ) ,
177- meta : pluginFrontendOptions ,
178- } ,
179- create : {
180- file : this . componentPath ( 'uploader.vue' ) ,
181- meta : pluginFrontendOptions ,
182- } ,
183- } ,
184- showIn : {
185- create : true ,
186- edit : true ,
187- list : false ,
188- show : false ,
189- filter : false ,
190- } ,
191- } ;
192-
193174 if ( ! resourceConfig . columns [ pathColumnIndex ] . components ) {
194175 resourceConfig . columns [ pathColumnIndex ] . components = { } ;
195176 }
@@ -208,38 +189,18 @@ export default class UploadPlugin extends AdminForthPlugin {
208189 } ;
209190 }
210191
211- // insert virtual column after path column if it is not already there
212- const virtualColumnIndex = resourceConfig . columns . findIndex ( ( column : any ) => column . name === virtualColumn . name ) ;
213- if ( virtualColumnIndex === - 1 ) {
214- resourceConfig . columns . splice ( pathColumnIndex + 1 , 0 , virtualColumn ) ;
215- }
216-
217-
218- // if showIn of path column has 'create' or 'edit' remove it but use it for virtual column
219- if ( pathColumn . showIn && ( pathColumn . showIn . create !== undefined ) ) {
220- virtualColumn . showIn = { ...virtualColumn . showIn , create : pathColumn . showIn . create } ;
221- pathColumn . showIn = { ...pathColumn . showIn , create : false } ;
192+ resourceConfig . columns [ pathColumnIndex ] . components . create = {
193+ file : this . componentPath ( 'uploader.vue' ) ,
194+ meta : pluginFrontendOptions ,
222195 }
223196
224- if ( pathColumn . showIn && ( pathColumn . showIn . edit !== undefined ) ) {
225- virtualColumn . showIn = { ... virtualColumn . showIn , edit : pathColumn . showIn . edit } ;
226- pathColumn . showIn = { ... pathColumn . showIn , edit : false } ;
197+ resourceConfig . columns [ pathColumnIndex ] . components . edit = {
198+ file : this . componentPath ( 'uploader.vue' ) ,
199+ meta : pluginFrontendOptions ,
227200 }
228201
229- virtualColumn . required = pathColumn . required ;
230- virtualColumn . label = pathColumn . label ;
231- virtualColumn . editingNote = pathColumn . editingNote ;
232-
233202 // ** HOOKS FOR CREATE **//
234203
235- // add beforeSave hook to save virtual column to path column
236- resourceConfig . hooks . create . beforeSave . push ( async ( { record } : { record : any } ) => {
237- if ( record [ virtualColumn . name ] ) {
238- record [ pathColumnName ] = record [ virtualColumn . name ] ;
239- delete record [ virtualColumn . name ] ;
240- }
241- return { ok : true } ;
242- } ) ;
243204
244205 // in afterSave hook, aremove tag adminforth-not-yet-used from the file
245206 resourceConfig . hooks . create . afterSave . push ( async ( { record } : { record : any } ) => {
@@ -248,7 +209,11 @@ export default class UploadPlugin extends AdminForthPlugin {
248209 if ( record [ pathColumnName ] ) {
249210 process . env . HEAVY_DEBUG && console . log ( '🪥🪥 remove ObjectTagging' , record [ pathColumnName ] ) ;
250211 // let it crash if it fails: this is a new file which just was uploaded.
251- await this . options . storageAdapter . markKeyForNotDeletation ( record [ pathColumnName ] ) ;
212+ if ( this . options . storageAdapter . markKeyForNotDeletion !== undefined ) {
213+ await this . options . storageAdapter . markKeyForNotDeletion ( record [ pathColumnName ] ) ;
214+ } else {
215+ await this . options . storageAdapter . markKeyForNotDeletation ( record [ pathColumnName ] ) ;
216+ }
252217 }
253218 return { ok : true } ;
254219 } ) ;
@@ -291,7 +256,11 @@ export default class UploadPlugin extends AdminForthPlugin {
291256 resourceConfig . hooks . delete . afterSave . push ( async ( { record } : { record : any } ) => {
292257 if ( record [ pathColumnName ] ) {
293258 try {
294- await this . options . storageAdapter . markKeyForDeletation ( record [ pathColumnName ] ) ;
259+ if ( this . options . storageAdapter . markKeyForDeletion !== undefined ) {
260+ await this . options . storageAdapter . markKeyForDeletion ( record [ pathColumnName ] ) ;
261+ } else {
262+ await this . options . storageAdapter . markKeyForDeletation ( record [ pathColumnName ] ) ;
263+ }
295264 } catch ( e ) {
296265 // file might be e.g. already deleted, so we catch error
297266 console . error ( `Error setting tag ${ ADMINFORTH_NOT_YET_USED_TAG } to true for object ${ record [ pathColumnName ] } . File will not be auto-cleaned up` , e ) ;
@@ -303,34 +272,34 @@ export default class UploadPlugin extends AdminForthPlugin {
303272
304273 // ** HOOKS FOR EDIT **//
305274
306- // beforeSave
307- resourceConfig . hooks . edit . beforeSave . push ( async ( { record } : { record : any } ) => {
308- // null is when value is removed
309- if ( record [ virtualColumn . name ] || record [ virtualColumn . name ] === null ) {
310- record [ pathColumnName ] = record [ virtualColumn . name ] ;
311- }
312- return { ok : true } ;
313- } )
314275
315276
316277 // add edit postSave hook to delete old file and remove tag from new file
317278 resourceConfig . hooks . edit . afterSave . push ( async ( { updates, oldRecord } : { updates : any , oldRecord : any } ) => {
318279
319- if ( updates [ virtualColumn . name ] || updates [ virtualColumn . name ] === null ) {
280+ if ( updates [ pathColumnName ] || updates [ pathColumnName ] === null ) {
320281 if ( oldRecord [ pathColumnName ] ) {
321282 // put tag to delete old file
322283 try {
323- await this . options . storageAdapter . markKeyForDeletation ( oldRecord [ pathColumnName ] ) ;
284+ if ( this . options . storageAdapter . markKeyForDeletion !== undefined ) {
285+ await this . options . storageAdapter . markKeyForDeletion ( oldRecord [ pathColumnName ] ) ;
286+ } else {
287+ await this . options . storageAdapter . markKeyForDeletation ( oldRecord [ pathColumnName ] ) ;
288+ }
324289 } catch ( e ) {
325290 // file might be e.g. already deleted, so we catch error
326291 console . error ( `Error setting tag ${ ADMINFORTH_NOT_YET_USED_TAG } to true for object ${ oldRecord [ pathColumnName ] } . File will not be auto-cleaned up` , e ) ;
327292 }
328293 }
329- if ( updates [ virtualColumn . name ] !== null ) {
294+ if ( updates [ pathColumnName ] !== null ) {
330295 // remove tag from new file
331296 // in this case we let it crash if it fails: this is a new file which just was uploaded.
297+ if ( this . options . storageAdapter . markKeyForNotDeletion !== undefined ) {
298+ await this . options . storageAdapter . markKeyForNotDeletion ( updates [ pathColumnName ] ) ;
299+ } else {
332300 await this . options . storageAdapter . markKeyForNotDeletation ( updates [ pathColumnName ] ) ;
333301 }
302+ }
334303 }
335304 return { ok : true } ;
336305 } ) ;
@@ -492,6 +461,26 @@ export default class UploadPlugin extends AdminForthPlugin {
492461 } ,
493462 } ) ;
494463
464+ server . endpoint ( {
465+ method : 'POST' ,
466+ path : `/plugin/${ this . pluginInstanceId } /get-file-download-url` ,
467+ handler : async ( { body, adminUser } ) => {
468+ const { filePath } = body ;
469+ if ( ! filePath ) {
470+ return { error : 'Missing filePath' } ;
471+ }
472+ const allowedActions = await interpretResource ( adminUser , this . resourceConfig , '' , ActionCheckSource . CustomActionRequest , this . adminforth )
473+ if ( allowedActions . allowedActions . create === true || allowedActions . allowedActions . edit === true ) {
474+ const url = await this . options . storageAdapter . getDownloadUrl ( filePath , 1800 ) ;
475+
476+ return {
477+ url,
478+ } ;
479+ }
480+ return { error : 'You do not have permission to download this file' } ;
481+ } ,
482+ } ) ;
483+
495484 }
496485
497486
0 commit comments