Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local Provider attempting to create upload in root partition #35

Open
DanStockham opened this issue Sep 8, 2021 · 1 comment
Open

Comments

@DanStockham
Copy link

Describe the bug
The local provider in the @adminbro/upload module is attempting to create a directory in the root partition of unix instance instead of using the designated bucket directory built in the root level of the project.

Also, the upload components are not referring to the path of the file on the serving directory but uses the physical address of the directory the file uploaded to.

Installed libraries and their versions

  • @admin-bro/express ^3.1.0
  • @admin-bro/mongoose ^1.1.0
  • @admin-bro/upload ^1.3.1
  • express ~4.16.1

To Reproduce
This is the adminbro setup with models being used for the file upload

routes/admin.js

...
const adminBro = new AdminBro({
  databases: [mongoose],
  rootPath: '/admin',
  branding: {
      companyName: 'My resume site',
      logo: false
  },
  resources: [{
    resource: Experience,
    options: {
        properties: {
            uploadedFile: { isVisible: false }
        }
    },
    features: [uploadFeature({
        provider: { local: { bucket: path.join(__dirname, '../uploads') } },
        properties: {
            key: 'uploadedFile.path',
            bucket: 'uploadedFile.folder',
            mimeType: 'uploadedFile.type',
            size: 'uploadedFile.size',
            filename: 'uploadedFile.filename',
            file: 'uploadFile'
        },
        uploadPath: (record, filename) => (
            `${record.id()}/${filename}`
        )
    }),]
  }]
})
...

models/experience.js

const mongoose = require('mongoose');
const { Schema } = mongoose;

const UploadedFile = new Schema({
    path: String,
    type: String,
    size: Number,
    folder: String,
    filename: String
});

const schema = new Schema({
    role: String,
    organization: String,
    lengthOfService: {
        startDate: Date,
        endDate: Date
    },
    uploadedFile: UploadedFile,
    description: String

});

module.exports = mongoose.model('Experience', schema);

When the instance is started and I attempt to create an entry with the file upload, It will be successful however, the image fails to render to the admin page.

image

After saving...

image

If you look at uploadedFile.folder and uploadedFile.filepath they both point to a physical address. Which makes sense, because the bucket is pointing to a physical address not the serving directory address and whatever the prop is for the component is passing that down.

But that shouldn't even be the case to refer to the absolute address of the upload directory, it should be referring to the relative filepath in the project which is the project directory

node_modules/@admin-bro/upload/src/features/upload-file/providers/local-provider.ts

...
/**
 * Options required by the LocalAdapter
 *
 * @memberof module:@admin-bro/upload
 */
export type LocalUploadOptions = {
  /**
   * Path where files will be stored. For example: `path.join(__dirname, '../public')`
   */
  bucket: string;
}

export class LocalProvider extends BaseProvider {
  constructor(options: LocalUploadOptions) {
    super(options.bucket)
    if (!existsSync(options.bucket)) {
      throw new Error(ERROR_MESSAGES.NO_DIRECTORY(options.bucket))
    }
  }

  public async upload(file: UploadedFile, key: string): Promise<any> {
    const filePath = this.path(key)

    await fs.promises.mkdir(path.dirname(filePath), { recursive: true })
    await fs.promises.rename(file.path, filePath)
  }

  public async delete(key: string, bucket: string): Promise<any> {
    await fs.promises.unlink(this.path(key, bucket))
  }

  // eslint-disable-next-line class-methods-use-this
  public path(key: string, bucket?: string): string {
    return `${path.join(bucket || this.bucket, key)}`
  }
}

Expected behavior
What's expected is that, even if the absolute path is provided, that the frontend should refer to the key of the file, not the folder path. Or atleast the local provider uses the project root not the root partition of the local instances to place uploaded folers

Desktop (please complete the following information if relevant):

  • OS: Linux Mint 20.1 Cinnamon / 5.4.0-81-generic
  • Browser Version 1.29.77 Chromium: 93.0.4577.63 (Official Build) (64-bit)

Additional context
Is there a way to change the src of the image on the frontend so we can pass along the file path to the serving directory?

@dziraf dziraf transferred this issue from SoftwareBrothers/adminjs Dec 28, 2021
@sampaio23
Copy link

Hello!
I have exactly the same problem, using the configuration in the example-app in this repo. Did you manage to find a way to solve this?
Best regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants