|
@@ -1,3 +1,4 @@
|
|
|
|
|
+import type { GetObjectCommandInput, HeadObjectCommandInput } from '@aws-sdk/client-s3';
|
|
|
import {
|
|
import {
|
|
|
S3Client,
|
|
S3Client,
|
|
|
HeadObjectCommand,
|
|
HeadObjectCommand,
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
PutObjectCommand,
|
|
PutObjectCommand,
|
|
|
DeleteObjectCommand,
|
|
DeleteObjectCommand,
|
|
|
ListObjectsCommand,
|
|
ListObjectsCommand,
|
|
|
- type GetObjectCommandInput,
|
|
|
|
|
ObjectCannedACL,
|
|
ObjectCannedACL,
|
|
|
} from '@aws-sdk/client-s3';
|
|
} from '@aws-sdk/client-s3';
|
|
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
@@ -35,19 +35,7 @@ interface FileMeta {
|
|
|
size: number;
|
|
size: number;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type AwsCredential = {
|
|
|
|
|
- accessKeyId: string,
|
|
|
|
|
- secretAccessKey: string
|
|
|
|
|
-}
|
|
|
|
|
-type AwsConfig = {
|
|
|
|
|
- credentials: AwsCredential,
|
|
|
|
|
- region: string,
|
|
|
|
|
- endpoint: string,
|
|
|
|
|
- bucket: string,
|
|
|
|
|
- forcePathStyle?: boolean
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const isFileExists = async(s3: S3Client, params) => {
|
|
|
|
|
|
|
+const isFileExists = async(s3: S3Client, params: HeadObjectCommandInput) => {
|
|
|
try {
|
|
try {
|
|
|
await s3.send(new HeadObjectCommand(params));
|
|
await s3.send(new HeadObjectCommand(params));
|
|
|
}
|
|
}
|
|
@@ -60,22 +48,20 @@ const isFileExists = async(s3: S3Client, params) => {
|
|
|
return true;
|
|
return true;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const getAwsConfig = (): AwsConfig => {
|
|
|
|
|
- return {
|
|
|
|
|
|
|
+const getS3Bucket = (): string | undefined => {
|
|
|
|
|
+ return configManager.getConfig('crowi', 'aws:s3Bucket') ?? undefined; // return undefined when getConfig() returns null
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const S3Factory = (): S3Client => {
|
|
|
|
|
+ return new S3Client({
|
|
|
credentials: {
|
|
credentials: {
|
|
|
accessKeyId: configManager.getConfig('crowi', 'aws:s3AccessKeyId'),
|
|
accessKeyId: configManager.getConfig('crowi', 'aws:s3AccessKeyId'),
|
|
|
secretAccessKey: configManager.getConfig('crowi', 'aws:s3SecretAccessKey'),
|
|
secretAccessKey: configManager.getConfig('crowi', 'aws:s3SecretAccessKey'),
|
|
|
},
|
|
},
|
|
|
region: configManager.getConfig('crowi', 'aws:s3Region'),
|
|
region: configManager.getConfig('crowi', 'aws:s3Region'),
|
|
|
endpoint: configManager.getConfig('crowi', 'aws:s3CustomEndpoint'),
|
|
endpoint: configManager.getConfig('crowi', 'aws:s3CustomEndpoint'),
|
|
|
- bucket: configManager.getConfig('crowi', 'aws:s3Bucket'),
|
|
|
|
|
forcePathStyle: configManager.getConfig('crowi', 'aws:s3CustomEndpoint') != null, // s3ForcePathStyle renamed to forcePathStyle in v3
|
|
forcePathStyle: configManager.getConfig('crowi', 'aws:s3CustomEndpoint') != null, // s3ForcePathStyle renamed to forcePathStyle in v3
|
|
|
- };
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const S3Factory = (): S3Client => {
|
|
|
|
|
- const config = getAwsConfig();
|
|
|
|
|
- return new S3Client(config);
|
|
|
|
|
|
|
+ });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const getFilePathOnStorage = (attachment) => {
|
|
const getFilePathOnStorage = (attachment) => {
|
|
@@ -148,11 +134,10 @@ class AwsFileUploader extends AbstractFileUploader {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
const filePath = getFilePathOnStorage(attachment);
|
|
const filePath = getFilePathOnStorage(attachment);
|
|
|
|
|
|
|
|
const params = {
|
|
const params = {
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
Key: filePath,
|
|
Key: filePath,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -191,7 +176,6 @@ class AwsFileUploader extends AbstractFileUploader {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
const filePath = getFilePathOnStorage(attachment);
|
|
const filePath = getFilePathOnStorage(attachment);
|
|
|
const lifetimeSecForTemporaryUrl = configManager.getConfig('crowi', 'aws:lifetimeSecForTemporaryUrl');
|
|
const lifetimeSecForTemporaryUrl = configManager.getConfig('crowi', 'aws:lifetimeSecForTemporaryUrl');
|
|
|
|
|
|
|
@@ -200,7 +184,7 @@ class AwsFileUploader extends AbstractFileUploader {
|
|
|
const isDownload = opts?.download ?? false;
|
|
const isDownload = opts?.download ?? false;
|
|
|
const contentHeaders = new ContentHeaders(attachment, { inline: !isDownload });
|
|
const contentHeaders = new ContentHeaders(attachment, { inline: !isDownload });
|
|
|
const params: GetObjectCommandInput = {
|
|
const params: GetObjectCommandInput = {
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
Key: filePath,
|
|
Key: filePath,
|
|
|
ResponseContentType: contentHeaders.contentType?.value.toString(),
|
|
ResponseContentType: contentHeaders.contentType?.value.toString(),
|
|
|
ResponseContentDisposition: contentHeaders.contentDisposition?.value.toString(),
|
|
ResponseContentDisposition: contentHeaders.contentDisposition?.value.toString(),
|
|
@@ -241,14 +225,13 @@ module.exports = (crowi) => {
|
|
|
throw new Error('AWS is not configured.');
|
|
throw new Error('AWS is not configured.');
|
|
|
}
|
|
}
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
|
|
|
|
|
const filePaths = attachments.map((attachment) => {
|
|
const filePaths = attachments.map((attachment) => {
|
|
|
return { Key: getFilePathOnStorage(attachment) };
|
|
return { Key: getFilePathOnStorage(attachment) };
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const totalParams = {
|
|
const totalParams = {
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
Delete: { Objects: filePaths },
|
|
Delete: { Objects: filePaths },
|
|
|
};
|
|
};
|
|
|
return s3.send(new DeleteObjectsCommand(totalParams));
|
|
return s3.send(new DeleteObjectsCommand(totalParams));
|
|
@@ -259,10 +242,9 @@ module.exports = (crowi) => {
|
|
|
throw new Error('AWS is not configured.');
|
|
throw new Error('AWS is not configured.');
|
|
|
}
|
|
}
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
|
|
|
|
|
const params = {
|
|
const params = {
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
Key: filePath,
|
|
Key: filePath,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -284,13 +266,12 @@ module.exports = (crowi) => {
|
|
|
logger.debug(`File uploading: fileName=${attachment.fileName}`);
|
|
logger.debug(`File uploading: fileName=${attachment.fileName}`);
|
|
|
|
|
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
|
|
|
|
|
const filePath = getFilePathOnStorage(attachment);
|
|
const filePath = getFilePathOnStorage(attachment);
|
|
|
const contentHeaders = new ContentHeaders(attachment);
|
|
const contentHeaders = new ContentHeaders(attachment);
|
|
|
|
|
|
|
|
return s3.send(new PutObjectCommand({
|
|
return s3.send(new PutObjectCommand({
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
Key: filePath,
|
|
Key: filePath,
|
|
|
Body: fileStream,
|
|
Body: fileStream,
|
|
|
ACL: ObjectCannedACL.public_read,
|
|
ACL: ObjectCannedACL.public_read,
|
|
@@ -302,10 +283,9 @@ module.exports = (crowi) => {
|
|
|
|
|
|
|
|
lib.saveFile = async function({ filePath, contentType, data }) {
|
|
lib.saveFile = async function({ filePath, contentType, data }) {
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
|
|
|
|
|
return s3.send(new PutObjectCommand({
|
|
return s3.send(new PutObjectCommand({
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
ContentType: contentType,
|
|
ContentType: contentType,
|
|
|
Key: filePath,
|
|
Key: filePath,
|
|
|
Body: data,
|
|
Body: data,
|
|
@@ -329,9 +309,8 @@ module.exports = (crowi) => {
|
|
|
|
|
|
|
|
const files: FileMeta[] = [];
|
|
const files: FileMeta[] = [];
|
|
|
const s3 = S3Factory();
|
|
const s3 = S3Factory();
|
|
|
- const awsConfig = getAwsConfig();
|
|
|
|
|
const params = {
|
|
const params = {
|
|
|
- Bucket: awsConfig.bucket,
|
|
|
|
|
|
|
+ Bucket: getS3Bucket(),
|
|
|
};
|
|
};
|
|
|
let shouldContinue = true;
|
|
let shouldContinue = true;
|
|
|
let nextMarker: string | undefined;
|
|
let nextMarker: string | undefined;
|