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

Adds minio provider #34

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/features/upload-file/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './aws-provider.js'
export * from './base-provider.js'
export * from './gcp-provider.js'
export * from './local-provider.js'
export * from './minio-provider.js'
95 changes: 95 additions & 0 deletions src/features/upload-file/providers/minio-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import fs from 'fs'
// eslint-disable-next-line import/no-extraneous-dependencies
import { S3 } from 'aws-sdk'
import { UploadedFile } from 'adminjs'
import { ERROR_MESSAGES, DAY_IN_MINUTES } from '../constants'

import { BaseProvider } from './base-provider'

/**
* AWS Credentials which can be set for S3 file upload.
* If not given, 'aws-sdk' will try to fetch them from
* environmental variables.
* @memberof module:@adminjs/upload
*/
export type MinIoOptions = {
/**
* MinIo endpoint
*/
endpoint: string;
/**
* AWS IAM accessKeyId. By default its value is taken from AWS_ACCESS_KEY_ID env variable
*/
accessKeyId?: string;
/**
* AWS IAM secretAccessKey. By default its value is taken from AWS_SECRET_ACCESS_KEY env variable
*/
secretAccessKey?: string;

/**
* S3 Bucket where files will be stored
*/
bucket: string;
/**
* indicates how long links should be available after page load (in minutes).
* Default to 24h. If set to 0 adapter will mark uploaded files as PUBLIC ACL.
*/
expires?: number;
}

export class MinIoProvider extends BaseProvider {
private s3: S3

private endpoint: string

public expires: number

constructor(options: MinIoOptions) {
super(options.bucket)

let AWS_S3: typeof S3
try {
// eslint-disable-next-line
const AWS = require('aws-sdk')
AWS_S3 = AWS.S3
} catch (error) {
throw new Error(ERROR_MESSAGES.NO_AWS_SDK)
}
this.expires = options.expires ?? DAY_IN_MINUTES
this.endpoint = options.endpoint
this.s3 = new AWS_S3({
s3ForcePathStyle: true, // needed with minio?
signatureVersion: 'v4',
...options })
}

public async upload(file: UploadedFile, key: string): Promise<S3.ManagedUpload.SendData> {
const uploadOptions = { partSize: 5 * 1024 * 1024, queueSize: 10 }
const tmpFile = fs.createReadStream(file.path)
const params: S3.PutObjectRequest = {
Bucket: this.bucket,
Key: key,
Body: tmpFile,
}
if (!this.expires) {
params.ACL = 'public-read'
}
return this.s3.upload(params, uploadOptions).promise()
}

public async delete(key: string, bucket: string): Promise<S3.DeleteObjectOutput> {
return this.s3.deleteObject({ Key: key, Bucket: bucket }).promise()
}

public async path(key: string, bucket: string): Promise<string> {
if (this.expires) {
return this.s3.getSignedUrl('getObject', {
Key: key,
Bucket: bucket,
Expires: this.expires,
})
}
// https://bucket.s3.amazonaws.com/key
return `${this.endpoint}/${bucket}/${key}`
}
}
2 changes: 2 additions & 0 deletions src/features/upload-file/types/upload-options.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AWSOptions } from '../providers/aws-provider.js'
import { BaseProvider } from '../providers/base-provider.js'
import { GCPOptions } from '../providers/gcp-provider.js'
import { LocalUploadOptions } from '../providers/local-provider.js'
import { MinIoOptions } from '../providers/minio-provider.js'

/**
* Function which defines where in the bucket file should be stored.
Expand Down Expand Up @@ -41,6 +42,7 @@ export type UploadOptions = {
* Options for the provider
*/
provider: {
minio?: MinIoOptions;
/** AWS Credentials */
aws?: AWSOptions,
/** GCP Credentials */
Expand Down
2 changes: 2 additions & 0 deletions src/features/upload-file/utils/get-provider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ERROR_MESSAGES } from '../constants.js'
import { AWSProvider } from '../providers/aws-provider.js'
import { GCPProvider } from '../providers/gcp-provider.js'
import { MinIoProvider } from '../providers/minio-provider'
import { BaseProvider } from '../providers/index.js'
import { LocalProvider } from '../providers/local-provider.js'
import { AvailableDefaultProviders, UploadOptions } from '../types/upload-options.type.js'
Expand Down Expand Up @@ -33,6 +34,7 @@ export const getProvider = (options: UploadOptions['provider']): GetProviderRetu
const providerOptions = options[providerName]

const providerMap: Record<AvailableDefaultProviders, () => BaseProvider> = {
minio: () => new MinIoProvider(providerOptions),
aws: () => new AWSProvider(providerOptions),
gcp: () => new GCPProvider(providerOptions),
local: () => new LocalProvider(providerOptions),
Expand Down