From 24192a327f92c4ad376f870ba5070d06a9a7f8bf Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sun, 5 Jul 2020 17:35:05 +0530 Subject: [PATCH] Refactor and fix media uploads. - Fix path related issues in filesystem and S3. - Add checks for S3 "/" path prefix. - Add support for custom S3 domain names. - Remove obsolete `width` and `height` columns from media table (breaking) - Add `provider` field to media table (breaking) --- admin.go | 14 ++--- config.toml.sample | 15 +++--- frontend/README.md | 2 +- frontend/src/api/index.js | 3 +- frontend/src/components/Editor.vue | 2 +- frontend/src/main.js | 4 ++ frontend/src/utils.js | 1 + frontend/src/views/Media.vue | 10 ++-- init.go | 5 +- internal/media/media.go | 10 ++-- .../media/providers/filesystem/filesystem.go | 25 ++++----- internal/media/providers/s3/s3.go | 54 +++++++++++-------- media.go | 8 +-- queries.sql | 4 +- schema.sql | 3 +- 15 files changed, 91 insertions(+), 69 deletions(-) diff --git a/admin.go b/admin.go index 51214a002..8fa6fcc1f 100644 --- a/admin.go +++ b/admin.go @@ -11,9 +11,10 @@ import ( ) type configScript struct { - RootURL string `json:"rootURL"` - FromEmail string `json:"fromEmail"` - Messengers []string `json:"messengers"` + RootURL string `json:"rootURL"` + FromEmail string `json:"fromEmail"` + Messengers []string `json:"messengers"` + MediaProvider string `json:"media_provider"` } // handleGetConfigScript returns general configuration as a Javascript @@ -22,9 +23,10 @@ func handleGetConfigScript(c echo.Context) error { var ( app = c.Get("app").(*App) out = configScript{ - RootURL: app.constants.RootURL, - FromEmail: app.constants.FromEmail, - Messengers: app.manager.GetMessengerNames(), + RootURL: app.constants.RootURL, + FromEmail: app.constants.FromEmail, + Messengers: app.manager.GetMessengerNames(), + MediaProvider: app.constants.MediaProvider, } b = bytes.Buffer{} diff --git a/config.toml.sample b/config.toml.sample index 71362e8b8..b6607fbc0 100644 --- a/config.toml.sample +++ b/config.toml.sample @@ -166,20 +166,23 @@ provider = "filesystem" aws_secret_access_key = "" # AWS Region where S3 bucket is hosted. - aws_default_region="ap-south-1" + aws_default_region = "ap-south-1" # Bucket name. - bucket="" + bucket = "" - # Path where the files will be stored inside bucket. Empty for root. - bucket_path="" + # Path where the files will be stored inside bucket. Default is "/". + bucket_path = "/" + + # Optional full URL to the bucket. eg: https://files.mycustom.com + bucket_url = "" # "private" or "public". - bucket_type="public" + bucket_type = "public" # (Optional) Specify TTL (in seconds) for the generated presigned URL. # Expiry value is used only if the bucket is private. - expiry="86400" + expiry = 86400 [upload.filesystem] # Path to the uploads directory where media will be uploaded. diff --git a/frontend/README.md b/frontend/README.md index 1ca20fe95..51964ae51 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -5,7 +5,7 @@ It's best if the `listmonk/frontend` directory is opened in an IDE as a separate For developer setup instructions, refer to the main project's README. ## Globals -`main.js` is where Buefy is injected globally into Vue. In addition two controllers, `$api` (collection of API calls from `api/index.js`) and `$utils` (util functions from `util.js`), are also attached globaly to Vue. They are accessible within Vue as `this.$api` and `this.$utils`. +`main.js` is where Buefy is injected globally into Vue. In addition two controllers, `$api` (collection of API calls from `api/index.js`), `$utils` (util functions from `util.js`), `$serverConfig` (loaded form /api/config.js) are also attached globaly to Vue. They are accessible within Vue as `this.$api` and `this.$utils`. Some constants are defined in `constants.js`. diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index bfe02051e..bb75a9d7e 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -22,8 +22,7 @@ const http = axios.create({ return resp; } - const data = humps.camelizeKeys(resp.data); - return data; + return humps.camelizeKeys(resp.data); }, ], diff --git a/frontend/src/components/Editor.vue b/frontend/src/components/Editor.vue index 307b894df..144b33ea4 100644 --- a/frontend/src/components/Editor.vue +++ b/frontend/src/components/Editor.vue @@ -164,7 +164,7 @@ export default { }, onMediaSelect(m) { - this.$refs.quill.quill.insertEmbed(10, 'image', m.uri); + this.$refs.quill.quill.insertEmbed(10, 'image', m.url); }, }, diff --git a/frontend/src/main.js b/frontend/src/main.js index 150359430..3cc4bc349 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import Buefy from 'buefy'; +import humps from 'humps'; import App from './App.vue'; import router from './router'; @@ -14,6 +15,9 @@ Vue.config.productionTip = false; Vue.prototype.$api = api; Vue.prototype.$utils = utils; +// window.CONFIG is loaded from /api/config.js directly in a