From ee0a44559040e83ce7d184bef57372f9c3602a75 Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Thu, 13 Aug 2020 20:05:01 +0900
Subject: [PATCH] Option objectStorageSetPublicRead (#6645)

---
 locales/ja-JP.yml                                  |  1 +
 .../1597230137744-objectStorageSetPublicRead.ts    | 14 ++++++++++++++
 src/client/pages/instance/settings.vue             |  4 ++++
 src/models/entities/meta.ts                        |  5 +++++
 src/server/api/endpoints/admin/update-meta.ts      |  8 ++++++++
 src/server/api/endpoints/meta.ts                   |  1 +
 src/services/drive/add-file.ts                     |  1 +
 7 files changed, 34 insertions(+)
 create mode 100644 migration/1597230137744-objectStorageSetPublicRead.ts

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 073a497620..96398db6ac 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -468,6 +468,7 @@ objectStorageUseSSL: "SSLを使用する"
 objectStorageUseSSLDesc: "API接続にhttpsを使用しない場合はオフにしてください"
 objectStorageUseProxy: "Proxyを利用する"
 objectStorageUseProxyDesc: "API接続にproxyを利用しない場合はオフにしてください"
+objectStorageSetPublicRead: "アップロード時に'public-read'を設定する"
 serverLogs: "サーバーログ"
 deleteAll: "全て削除"
 showFixedPostForm: "タイムライン上部に投稿フォームを表示する"
diff --git a/migration/1597230137744-objectStorageSetPublicRead.ts b/migration/1597230137744-objectStorageSetPublicRead.ts
new file mode 100644
index 0000000000..f040f2afdd
--- /dev/null
+++ b/migration/1597230137744-objectStorageSetPublicRead.ts
@@ -0,0 +1,14 @@
+import {MigrationInterface, QueryRunner} from "typeorm";
+
+export class objectStorageSetPublicRead1597230137744 implements MigrationInterface {
+    name = 'objectStorageSetPublicRead1597230137744'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "meta" ADD "objectStorageSetPublicRead" boolean NOT NULL DEFAULT false`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageSetPublicRead"`);
+    }
+
+}
diff --git a/src/client/pages/instance/settings.vue b/src/client/pages/instance/settings.vue
index 8318807d43..0c0e506ab8 100644
--- a/src/client/pages/instance/settings.vue
+++ b/src/client/pages/instance/settings.vue
@@ -161,6 +161,7 @@
 				</div>
 				<mk-switch v-model="objectStorageUseSSL" :disabled="!useObjectStorage">{{ $t('objectStorageUseSSL') }}<template #desc>{{ $t('objectStorageUseSSLDesc') }}</template></mk-switch>
 				<mk-switch v-model="objectStorageUseProxy" :disabled="!useObjectStorage">{{ $t('objectStorageUseProxy') }}<template #desc>{{ $t('objectStorageUseProxyDesc') }}</template></mk-switch>
+				<mk-switch v-model="objectStorageSetPublicRead" :disabled="!useObjectStorage">{{ $t('objectStorageSetPublicRead') }}</mk-switch>
 			</template>
 		</div>
 		<div class="_footer">
@@ -306,6 +307,7 @@ export default Vue.extend({
 			objectStorageSecretKey: null,
 			objectStorageUseSSL: false,
 			objectStorageUseProxy: false,
+			objectStorageSetPublicRead: false,
 			enableTwitterIntegration: false,
 			twitterConsumerKey: null,
 			twitterConsumerSecret: null,
@@ -373,6 +375,7 @@ export default Vue.extend({
 		this.objectStorageSecretKey = this.meta.objectStorageSecretKey;
 		this.objectStorageUseSSL = this.meta.objectStorageUseSSL;
 		this.objectStorageUseProxy = this.meta.objectStorageUseProxy;
+		this.objectStorageSetPublicRead = this.meta.objectStorageSetPublicRead;
 		this.enableTwitterIntegration = this.meta.enableTwitterIntegration;
 		this.twitterConsumerKey = this.meta.twitterConsumerKey;
 		this.twitterConsumerSecret = this.meta.twitterConsumerSecret;
@@ -522,6 +525,7 @@ export default Vue.extend({
 				objectStorageSecretKey: this.objectStorageSecretKey ? this.objectStorageSecretKey : null,
 				objectStorageUseSSL: this.objectStorageUseSSL,
 				objectStorageUseProxy: this.objectStorageUseProxy,
+				objectStorageSetPublicRead: this.objectStorageSetPublicRead,
 				enableTwitterIntegration: this.enableTwitterIntegration,
 				twitterConsumerKey: this.twitterConsumerKey,
 				twitterConsumerSecret: this.twitterConsumerSecret,
diff --git a/src/models/entities/meta.ts b/src/models/entities/meta.ts
index 622d28bead..d1eecf6277 100644
--- a/src/models/entities/meta.ts
+++ b/src/models/entities/meta.ts
@@ -370,4 +370,9 @@ export class Meta {
 		default: true,
 	})
 	public objectStorageUseProxy: boolean;
+
+	@Column('boolean', {
+		default: false,
+	})
+	public objectStorageSetPublicRead: boolean;
 }
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index dffe7ffe7f..fea6cb539f 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -418,6 +418,10 @@ export const meta = {
 
 		objectStorageUseProxy: {
 			validator: $.optional.bool
+		},
+
+		objectStorageSetPublicRead: {
+			validator: $.optional.bool
 		}
 	}
 };
@@ -673,6 +677,10 @@ export default define(meta, async (ps, me) => {
 		set.objectStorageUseProxy = ps.objectStorageUseProxy;
 	}
 
+	if (ps.objectStorageSetPublicRead !== undefined) {
+		set.objectStorageSetPublicRead = ps.objectStorageSetPublicRead;
+	}
+
 	await getConnection().transaction(async transactionalEntityManager => {
 		const meta = await transactionalEntityManager.findOne(Meta, {
 			order: {
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index eefc370124..f011a6751f 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -195,6 +195,7 @@ export default define(meta, async (ps, me) => {
 		response.objectStorageSecretKey = instance.objectStorageSecretKey;
 		response.objectStorageUseSSL = instance.objectStorageUseSSL;
 		response.objectStorageUseProxy = instance.objectStorageUseProxy;
+		response.objectStorageSetPublicRead = instance.objectStorageSetPublicRead;
 	}
 
 	return response;
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index 969dc04069..0e56d7a055 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -212,6 +212,7 @@ async function upload(key: string, stream: fs.ReadStream | Buffer, type: string,
 	} as S3.PutObjectRequest;
 
 	if (filename) params.ContentDisposition = contentDisposition('inline', filename);
+	if (meta.objectStorageSetPublicRead) params.ACL = 'public-read';
 
 	const s3 = getS3(meta);