mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 12:02:46 +08:00
DEV: Rename secure_media to secure_uploads (#18376)
This commit renames all secure_media related settings to secure_uploads_* along with the associated functionality. This is being done because "media" does not really cover it, we aren't just doing this for images and videos etc. but for all uploads in the site. Additionally, in future we want to secure more types of uploads, and enable a kind of "mixed mode" where some uploads are secure and some are not, so keeping media in the name is just confusing. This also keeps compatibility with the `secure-media-uploads` path, and changes new secure URLs to be `secure-uploads`. Deprecated settings: * secure_media -> secure_uploads * secure_media_allow_embed_images_in_emails -> secure_uploads_allow_embed_images_in_emails * secure_media_max_email_embed_image_size_kb -> secure_uploads_max_email_embed_image_size_kb
This commit is contained in:
parent
70b96ac4e7
commit
8ebd5edd1e
|
@ -21,8 +21,8 @@ export function nativeLazyLoading(api) {
|
||||||
// Support for smallUpload should be maintained until Post::BAKED_VERSION is bumped higher than 2
|
// Support for smallUpload should be maintained until Post::BAKED_VERSION is bumped higher than 2
|
||||||
const { smallUpload, dominantColor } = img.dataset;
|
const { smallUpload, dominantColor } = img.dataset;
|
||||||
|
|
||||||
if (siteSettings.secure_media && smallUpload) {
|
if (siteSettings.secure_uploads && smallUpload) {
|
||||||
// Secure media requests go through the app. In topics with many images,
|
// Secure uploads requests go through the app. In topics with many images,
|
||||||
// this makes it very easy to hit rate limiters. Skipping the low-res
|
// this makes it very easy to hit rate limiters. Skipping the low-res
|
||||||
// placeholders reduces the chance of this problem occuring.
|
// placeholders reduces the chance of this problem occuring.
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -19,6 +19,7 @@ const SERVER_SIDE_ONLY = [
|
||||||
/^\/assets\//,
|
/^\/assets\//,
|
||||||
/^\/uploads\//,
|
/^\/uploads\//,
|
||||||
/^\/secure-media-uploads\//,
|
/^\/secure-media-uploads\//,
|
||||||
|
/^\/secure-uploads\//,
|
||||||
/^\/stylesheets\//,
|
/^\/stylesheets\//,
|
||||||
/^\/site_customizations\//,
|
/^\/site_customizations\//,
|
||||||
/^\/raw\//,
|
/^\/raw\//,
|
||||||
|
|
|
@ -97,7 +97,7 @@ const ORIGINAL_SETTINGS = {
|
||||||
enable_personal_messages: true,
|
enable_personal_messages: true,
|
||||||
personal_message_enabled_groups: "11", // TL1 group
|
personal_message_enabled_groups: "11", // TL1 group
|
||||||
unicode_usernames: false,
|
unicode_usernames: false,
|
||||||
secure_media: false,
|
secure_uploads: false,
|
||||||
external_emoji_url: "",
|
external_emoji_url: "",
|
||||||
remove_muted_tags_from_latest: "always",
|
remove_muted_tags_from_latest: "always",
|
||||||
enable_group_directory: true,
|
enable_group_directory: true,
|
||||||
|
|
|
@ -997,12 +997,12 @@ eviltrout</p>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("attachment - mapped url - secure media disabled", function (assert) {
|
test("attachment - mapped url - secure uploads disabled", function (assert) {
|
||||||
function lookupUploadUrls() {
|
function lookupUploadUrls() {
|
||||||
let cache = {};
|
let cache = {};
|
||||||
cache["upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf"] = {
|
cache["upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf"] = {
|
||||||
short_url: "upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
short_url: "upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
||||||
url: "/secure-media-uploads/original/3X/c/b/o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
url: "/secure-uploads/original/3X/c/b/o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
||||||
short_path: "/uploads/short-url/blah",
|
short_path: "/uploads/short-url/blah",
|
||||||
};
|
};
|
||||||
return cache;
|
return cache;
|
||||||
|
@ -1010,20 +1010,20 @@ eviltrout</p>
|
||||||
assert.cookedOptions(
|
assert.cookedOptions(
|
||||||
"[test.pdf|attachment](upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf)",
|
"[test.pdf|attachment](upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf)",
|
||||||
{
|
{
|
||||||
siteSettings: { secure_media: false },
|
siteSettings: { secure_uploads: false },
|
||||||
lookupUploadUrls,
|
lookupUploadUrls,
|
||||||
},
|
},
|
||||||
`<p><a class="attachment" href="/uploads/short-url/blah">test.pdf</a></p>`,
|
`<p><a class="attachment" href="/uploads/short-url/blah">test.pdf</a></p>`,
|
||||||
"It returns the correct attachment link HTML when the URL is mapped without secure media"
|
"It returns the correct attachment link HTML when the URL is mapped without secure uploads"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("attachment - mapped url - secure media enabled", function (assert) {
|
test("attachment - mapped url - secure uploads enabled", function (assert) {
|
||||||
function lookupUploadUrls() {
|
function lookupUploadUrls() {
|
||||||
let cache = {};
|
let cache = {};
|
||||||
cache["upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf"] = {
|
cache["upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf"] = {
|
||||||
short_url: "upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
short_url: "upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
||||||
url: "/secure-media-uploads/original/3X/c/b/o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
url: "/secure-uploads/original/3X/c/b/o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf",
|
||||||
short_path: "/uploads/short-url/blah",
|
short_path: "/uploads/short-url/blah",
|
||||||
};
|
};
|
||||||
return cache;
|
return cache;
|
||||||
|
@ -1031,11 +1031,11 @@ eviltrout</p>
|
||||||
assert.cookedOptions(
|
assert.cookedOptions(
|
||||||
"[test.pdf|attachment](upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf)",
|
"[test.pdf|attachment](upload://o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf)",
|
||||||
{
|
{
|
||||||
siteSettings: { secure_media: true },
|
siteSettings: { secure_uploads: true },
|
||||||
lookupUploadUrls,
|
lookupUploadUrls,
|
||||||
},
|
},
|
||||||
`<p><a class="attachment" href="/secure-media-uploads/original/3X/c/b/o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf">test.pdf</a></p>`,
|
`<p><a class="attachment" href="/secure-uploads/original/3X/c/b/o8iobpLcW3WSFvVH7YQmyGlKmGM.pdf">test.pdf</a></p>`,
|
||||||
"It returns the correct attachment link HTML when the URL is mapped with secure media"
|
"It returns the correct attachment link HTML when the URL is mapped with secure uploads"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1052,12 +1052,12 @@ eviltrout</p>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("video - mapped url - secure media enabled", function (assert) {
|
test("video - mapped url - secure uploads enabled", function (assert) {
|
||||||
function lookupUploadUrls() {
|
function lookupUploadUrls() {
|
||||||
let cache = {};
|
let cache = {};
|
||||||
cache["upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4"] = {
|
cache["upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4"] = {
|
||||||
short_url: "upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4",
|
short_url: "upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4",
|
||||||
url: "/secure-media-uploads/original/3X/c/b/test.mp4",
|
url: "/secure-uploads/original/3X/c/b/test.mp4",
|
||||||
short_path: "/uploads/short-url/blah",
|
short_path: "/uploads/short-url/blah",
|
||||||
};
|
};
|
||||||
return cache;
|
return cache;
|
||||||
|
@ -1065,16 +1065,16 @@ eviltrout</p>
|
||||||
assert.cookedOptions(
|
assert.cookedOptions(
|
||||||
"![baby shark|video](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4)",
|
"![baby shark|video](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp4)",
|
||||||
{
|
{
|
||||||
siteSettings: { secure_media: true },
|
siteSettings: { secure_uploads: true },
|
||||||
lookupUploadUrls,
|
lookupUploadUrls,
|
||||||
},
|
},
|
||||||
`<p><div class="video-container">
|
`<p><div class="video-container">
|
||||||
<video width="100%" height="100%" preload="metadata" controls>
|
<video width="100%" height="100%" preload="metadata" controls>
|
||||||
<source src="/secure-media-uploads/original/3X/c/b/test.mp4">
|
<source src="/secure-uploads/original/3X/c/b/test.mp4">
|
||||||
<a href="/secure-media-uploads/original/3X/c/b/test.mp4">/secure-media-uploads/original/3X/c/b/test.mp4</a>
|
<a href="/secure-uploads/original/3X/c/b/test.mp4">/secure-uploads/original/3X/c/b/test.mp4</a>
|
||||||
</video>
|
</video>
|
||||||
</div></p>`,
|
</div></p>`,
|
||||||
"It returns the correct video HTML when the URL is mapped with secure media, removing data-orig-src"
|
"It returns the correct video HTML when the URL is mapped with secure uploads, removing data-orig-src"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1089,12 +1089,12 @@ eviltrout</p>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("audio - mapped url - secure media enabled", function (assert) {
|
test("audio - mapped url - secure uploads enabled", function (assert) {
|
||||||
function lookupUploadUrls() {
|
function lookupUploadUrls() {
|
||||||
let cache = {};
|
let cache = {};
|
||||||
cache["upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3"] = {
|
cache["upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3"] = {
|
||||||
short_url: "upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3",
|
short_url: "upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3",
|
||||||
url: "/secure-media-uploads/original/3X/c/b/test.mp3",
|
url: "/secure-uploads/original/3X/c/b/test.mp3",
|
||||||
short_path: "/uploads/short-url/blah",
|
short_path: "/uploads/short-url/blah",
|
||||||
};
|
};
|
||||||
return cache;
|
return cache;
|
||||||
|
@ -1102,14 +1102,14 @@ eviltrout</p>
|
||||||
assert.cookedOptions(
|
assert.cookedOptions(
|
||||||
"![baby shark|audio](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3)",
|
"![baby shark|audio](upload://eyPnj7UzkU0AkGkx2dx8G4YM1Jx.mp3)",
|
||||||
{
|
{
|
||||||
siteSettings: { secure_media: true },
|
siteSettings: { secure_uploads: true },
|
||||||
lookupUploadUrls,
|
lookupUploadUrls,
|
||||||
},
|
},
|
||||||
`<p><audio preload="metadata" controls>
|
`<p><audio preload="metadata" controls>
|
||||||
<source src="/secure-media-uploads/original/3X/c/b/test.mp3">
|
<source src="/secure-uploads/original/3X/c/b/test.mp3">
|
||||||
<a href="/secure-media-uploads/original/3X/c/b/test.mp3">/secure-media-uploads/original/3X/c/b/test.mp3</a>
|
<a href="/secure-uploads/original/3X/c/b/test.mp3">/secure-uploads/original/3X/c/b/test.mp3</a>
|
||||||
</audio></p>`,
|
</audio></p>`,
|
||||||
"It returns the correct audio HTML when the URL is mapped with secure media, removing data-orig-src"
|
"It returns the correct audio HTML when the URL is mapped with secure uploads, removing data-orig-src"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ module("Unit | Utility | pretty-text/upload-short-url", function (hooks) {
|
||||||
lookup = lookupCachedUploadUrl("upload://a.jpeg");
|
lookup = lookupCachedUploadUrl("upload://a.jpeg");
|
||||||
assert.deepEqual(lookup, {});
|
assert.deepEqual(lookup, {});
|
||||||
|
|
||||||
await resolveAllShortUrls(ajax, { secure_media: false }, fixture());
|
await resolveAllShortUrls(ajax, { secure_uploads: false }, fixture());
|
||||||
await settled();
|
await settled();
|
||||||
|
|
||||||
lookup = lookupCachedUploadUrl("upload://a.jpeg");
|
lookup = lookupCachedUploadUrl("upload://a.jpeg");
|
||||||
|
@ -143,7 +143,7 @@ module("Unit | Utility | pretty-text/upload-short-url", function (hooks) {
|
||||||
|
|
||||||
test("resolveAllShortUrls - href + src replaced correctly", async function (assert) {
|
test("resolveAllShortUrls - href + src replaced correctly", async function (assert) {
|
||||||
stubUrls();
|
stubUrls();
|
||||||
await resolveAllShortUrls(ajax, { secure_media: false }, fixture());
|
await resolveAllShortUrls(ajax, { secure_uploads: false }, fixture());
|
||||||
await settled();
|
await settled();
|
||||||
|
|
||||||
let image1 = fixture().querySelector("img");
|
let image1 = fixture().querySelector("img");
|
||||||
|
@ -167,7 +167,7 @@ module("Unit | Utility | pretty-text/upload-short-url", function (hooks) {
|
||||||
|
|
||||||
test("resolveAllShortUrls - url with full origin replaced correctly", async function (assert) {
|
test("resolveAllShortUrls - url with full origin replaced correctly", async function (assert) {
|
||||||
stubUrls();
|
stubUrls();
|
||||||
await resolveAllShortUrls(ajax, { secure_media: false }, fixture());
|
await resolveAllShortUrls(ajax, { secure_uploads: false }, fixture());
|
||||||
await settled();
|
await settled();
|
||||||
let video = fixture().querySelectorAll("video")[1];
|
let video = fixture().querySelectorAll("video")[1];
|
||||||
|
|
||||||
|
@ -177,25 +177,25 @@ module("Unit | Utility | pretty-text/upload-short-url", function (hooks) {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolveAllShortUrls - when secure media is enabled use the attachment full URL", async function (assert) {
|
test("resolveAllShortUrls - when secure uploads is enabled use the attachment full URL", async function (assert) {
|
||||||
stubUrls(
|
stubUrls(
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
short_url: "upload://c.pdf",
|
short_url: "upload://c.pdf",
|
||||||
url: "/secure-media-uploads/default/original/3X/c/b/3.pdf",
|
url: "/secure-uploads/default/original/3X/c/b/3.pdf",
|
||||||
short_path: "/uploads/short-url/c.pdf",
|
short_path: "/uploads/short-url/c.pdf",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
await resolveAllShortUrls(ajax, { secure_media: true }, fixture());
|
await resolveAllShortUrls(ajax, { secure_uploads: true }, fixture());
|
||||||
await settled();
|
await settled();
|
||||||
|
|
||||||
let link = fixture().querySelector("a");
|
let link = fixture().querySelector("a");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
link.getAttribute("href"),
|
link.getAttribute("href"),
|
||||||
"/secure-media-uploads/default/original/3X/c/b/3.pdf"
|
"/secure-uploads/default/original/3X/c/b/3.pdf"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -143,14 +143,12 @@ module("Unit | Utility | url", function () {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("routeTo redirects secure media URLS because they are server side only", async function (assert) {
|
test("routeTo redirects secure uploads URLS because they are server side only", async function (assert) {
|
||||||
sinon.stub(DiscourseURL, "redirectTo");
|
sinon.stub(DiscourseURL, "redirectTo");
|
||||||
sinon.stub(DiscourseURL, "handleURL");
|
sinon.stub(DiscourseURL, "handleURL");
|
||||||
DiscourseURL.routeTo("/secure-media-uploads/original/1X/test.pdf");
|
DiscourseURL.routeTo("/secure-uploads/original/1X/test.pdf");
|
||||||
assert.ok(
|
assert.ok(
|
||||||
DiscourseURL.redirectTo.calledWith(
|
DiscourseURL.redirectTo.calledWith("/secure-uploads/original/1X/test.pdf")
|
||||||
"/secure-media-uploads/original/1X/test.pdf"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -525,7 +525,7 @@ export function setup(opts, siteSettings, state) {
|
||||||
getOptions.f = () => opts.discourse;
|
getOptions.f = () => opts.discourse;
|
||||||
|
|
||||||
opts.discourse.limitedSiteSettings = {
|
opts.discourse.limitedSiteSettings = {
|
||||||
secureMedia: siteSettings.secure_media,
|
secureUploads: siteSettings.secure_uploads,
|
||||||
enableDiffhtmlPreview: siteSettings.enable_diffhtml_preview,
|
enableDiffhtmlPreview: siteSettings.enable_diffhtml_preview,
|
||||||
traditionalMarkdownLinebreaks: siteSettings.traditional_markdown_linebreaks,
|
traditionalMarkdownLinebreaks: siteSettings.traditional_markdown_linebreaks,
|
||||||
enableMarkdownLinkify: siteSettings.enable_markdown_linkify,
|
enableMarkdownLinkify: siteSettings.enable_markdown_linkify,
|
||||||
|
|
|
@ -112,11 +112,12 @@ function getAttributeBasedUrl(dataAttribute, cachedUpload, siteSettings) {
|
||||||
return cachedUpload.url;
|
return cachedUpload.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// attachments should use the full /secure-media-uploads/ URL
|
// attachments should use the full /secure-media-uploads/ or
|
||||||
// in this case for permission checks
|
// /secure-uploads/ URL in this case for permission checks
|
||||||
if (
|
if (
|
||||||
siteSettings.secure_media &&
|
siteSettings.secure_uploads &&
|
||||||
cachedUpload.url.includes("secure-media-uploads")
|
(cachedUpload.url.includes("secure-media-uploads") ||
|
||||||
|
cachedUpload.url.includes("secure-uploads"))
|
||||||
) {
|
) {
|
||||||
return cachedUpload.url;
|
return cachedUpload.url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,11 +136,12 @@ function rule(state) {
|
||||||
}
|
}
|
||||||
} else if (token.tag === "a") {
|
} else if (token.tag === "a") {
|
||||||
if (mapped) {
|
if (mapped) {
|
||||||
// when secure media is enabled we want the full /secure-media-uploads/
|
// when secure uploads is enabled we want the full /secure-media-uploads or /secure-uploads
|
||||||
// url to take advantage of access control security
|
// url to take advantage of access control security
|
||||||
if (
|
if (
|
||||||
state.md.options.discourse.limitedSiteSettings.secureMedia &&
|
state.md.options.discourse.limitedSiteSettings.secureUploads &&
|
||||||
mapped.url.includes("secure-media-uploads")
|
(mapped.url.includes("secure-media-uploads") ||
|
||||||
|
mapped.url.includes("secure-uploads"))
|
||||||
) {
|
) {
|
||||||
token.attrs[srcIndex][1] = mapped.url;
|
token.attrs[srcIndex][1] = mapped.url;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,7 +28,7 @@ workbox.routing.registerRoute(
|
||||||
plugins: [
|
plugins: [
|
||||||
new workbox.cacheableResponse.Plugin({
|
new workbox.cacheableResponse.Plugin({
|
||||||
statuses: [200] // opaque responses will return status code '0'
|
statuses: [200] // opaque responses will return status code '0'
|
||||||
}), // for s3 secure media signed urls
|
}), // for s3 secure uploads signed urls
|
||||||
new workbox.expiration.Plugin({
|
new workbox.expiration.Plugin({
|
||||||
maxAgeSeconds: 7* 24 * 60 * 60, // 7 days
|
maxAgeSeconds: 7* 24 * 60 * 60, // 7 days
|
||||||
maxEntries: 250,
|
maxEntries: 250,
|
||||||
|
|
|
@ -94,7 +94,7 @@ private
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_publish_enabled
|
def ensure_publish_enabled
|
||||||
if !SiteSetting.enable_page_publishing? || SiteSetting.secure_media
|
if !SiteSetting.enable_page_publishing? || SiteSetting.secure_uploads
|
||||||
raise Discourse::NotFound
|
raise Discourse::NotFound
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,13 +5,13 @@ require "mini_mime"
|
||||||
class UploadsController < ApplicationController
|
class UploadsController < ApplicationController
|
||||||
include ExternalUploadHelpers
|
include ExternalUploadHelpers
|
||||||
|
|
||||||
requires_login except: [:show, :show_short, :show_secure]
|
requires_login except: [:show, :show_short, :_show_secure_deprecated, :show_secure]
|
||||||
|
|
||||||
skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required, only: [:show, :show_short, :show_secure]
|
skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required, only: [:show, :show_short, :_show_secure_deprecated, :show_secure]
|
||||||
protect_from_forgery except: :show
|
protect_from_forgery except: :show
|
||||||
|
|
||||||
before_action :is_asset_path, :apply_cdn_headers, only: [:show, :show_short, :show_secure]
|
before_action :is_asset_path, :apply_cdn_headers, only: [:show, :show_short, :_show_secure_deprecated, :show_secure]
|
||||||
before_action :external_store_check, only: [:show_secure]
|
before_action :external_store_check, only: [:_show_secure_deprecated, :show_secure]
|
||||||
|
|
||||||
SECURE_REDIRECT_GRACE_SECONDS = 5
|
SECURE_REDIRECT_GRACE_SECONDS = 5
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ class UploadsController < ApplicationController
|
||||||
sha1 = Upload.sha1_from_base62_encoded(params[:base62])
|
sha1 = Upload.sha1_from_base62_encoded(params[:base62])
|
||||||
|
|
||||||
if upload = Upload.find_by(sha1: sha1)
|
if upload = Upload.find_by(sha1: sha1)
|
||||||
if upload.secure? && SiteSetting.secure_media?
|
if upload.secure? && SiteSetting.secure_uploads?
|
||||||
return handle_secure_upload_request(upload)
|
return handle_secure_upload_request(upload)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -125,6 +125,13 @@ class UploadsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Kept to avoid rebaking old posts with /show-secure-uploads/ in their
|
||||||
|
# contents, this will ensure the uploads in these posts continue to
|
||||||
|
# work in future.
|
||||||
|
def _show_secure_deprecated
|
||||||
|
show_secure
|
||||||
|
end
|
||||||
|
|
||||||
def show_secure
|
def show_secure
|
||||||
# do not serve uploads requested via XHR to prevent XSS
|
# do not serve uploads requested via XHR to prevent XSS
|
||||||
return xhr_not_allowed if request.xhr?
|
return xhr_not_allowed if request.xhr?
|
||||||
|
@ -139,9 +146,9 @@ class UploadsController < ApplicationController
|
||||||
return render_404 if upload.blank?
|
return render_404 if upload.blank?
|
||||||
|
|
||||||
return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil?
|
return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil?
|
||||||
return handle_secure_upload_request(upload, path_with_ext) if SiteSetting.secure_media?
|
return handle_secure_upload_request(upload, path_with_ext) if SiteSetting.secure_uploads?
|
||||||
|
|
||||||
# we don't want to 404 here if secure media gets disabled
|
# we don't want to 404 here if secure uploads gets disabled
|
||||||
# because all posts with secure uploads will show broken media
|
# because all posts with secure uploads will show broken media
|
||||||
# until rebaked, which could take some time
|
# until rebaked, which could take some time
|
||||||
#
|
#
|
||||||
|
|
|
@ -67,6 +67,10 @@ module EmailHelper
|
||||||
border-color: #454545 !important;
|
border-color: #454545 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-stripped-secure-upload] {
|
||||||
|
border-color: #454545 !important;
|
||||||
|
}
|
||||||
|
|
||||||
[dm='text-color'] {
|
[dm='text-color'] {
|
||||||
color: #dddddd;
|
color: #dddddd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,9 +108,9 @@ module Jobs
|
||||||
class UploadCreateError < StandardError; end
|
class UploadCreateError < StandardError; end
|
||||||
|
|
||||||
def attempt_download(src, user_id)
|
def attempt_download(src, user_id)
|
||||||
# secure-media-uploads endpoint prevents anonymous downloads, so we
|
# secure-uploads endpoint prevents anonymous downloads, so we
|
||||||
# need the presigned S3 URL here
|
# need the presigned S3 URL here
|
||||||
src = Upload.signed_url_from_secure_media_url(src) if Upload.secure_media_url?(src)
|
src = Upload.signed_url_from_secure_uploads_url(src) if Upload.secure_uploads_url?(src)
|
||||||
|
|
||||||
hotlinked = download(src)
|
hotlinked = download(src)
|
||||||
raise ImageBrokenError if !hotlinked
|
raise ImageBrokenError if !hotlinked
|
||||||
|
@ -147,7 +147,7 @@ module Jobs
|
||||||
].compact.map { |s| normalize_src(s) }
|
].compact.map { |s| normalize_src(s) }
|
||||||
|
|
||||||
if Discourse.store.has_been_uploaded?(src) || normalize_src(src).start_with?(*local_bases) || src =~ /\A\/[^\/]/i
|
if Discourse.store.has_been_uploaded?(src) || normalize_src(src).start_with?(*local_bases) || src =~ /\A\/[^\/]/i
|
||||||
return false if !(src =~ /\/uploads\// || Upload.secure_media_url?(src))
|
return false if !(src =~ /\/uploads\// || Upload.secure_uploads_url?(src))
|
||||||
|
|
||||||
# Someone could hotlink a file from a different site on the same CDN,
|
# Someone could hotlink a file from a different site on the same CDN,
|
||||||
# so check whether we have it in this database
|
# so check whether we have it in this database
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Jobs
|
module Jobs
|
||||||
# Sometimes we need to update a _lot_ of ACLs on S3 (such as when secure media
|
# Sometimes we need to update a _lot_ of ACLs on S3 (such as when secure uploads
|
||||||
# is enabled), and since it takes ~1s per upload to update the ACL, this is
|
# is enabled), and since it takes ~1s per upload to update the ACL, this is
|
||||||
# best spread out over many jobs instead of having to do the whole thing serially.
|
# best spread out over many jobs instead of having to do the whole thing serially.
|
||||||
class SyncAclsForUploads < ::Jobs::Base
|
class SyncAclsForUploads < ::Jobs::Base
|
||||||
|
|
|
@ -309,7 +309,7 @@ class Post < ActiveRecord::Base
|
||||||
options[:user_id] = post_user.id if post_user
|
options[:user_id] = post_user.id if post_user
|
||||||
options[:omit_nofollow] = true if omit_nofollow?
|
options[:omit_nofollow] = true if omit_nofollow?
|
||||||
|
|
||||||
if self.with_secure_media?
|
if self.with_secure_uploads?
|
||||||
each_upload_url do |url|
|
each_upload_url do |url|
|
||||||
uri = URI.parse(url)
|
uri = URI.parse(url)
|
||||||
if FileHelper.is_supported_media?(File.basename(uri.path))
|
if FileHelper.is_supported_media?(File.basename(uri.path))
|
||||||
|
@ -517,8 +517,8 @@ class Post < ActiveRecord::Base
|
||||||
ReviewableFlaggedPost.pending.find_by(target: self)
|
ReviewableFlaggedPost.pending.find_by(target: self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_secure_media?
|
def with_secure_uploads?
|
||||||
return false if !SiteSetting.secure_media?
|
return false if !SiteSetting.secure_uploads?
|
||||||
SiteSetting.login_required? || \
|
SiteSetting.login_required? || \
|
||||||
(topic.present? && (topic.private_message? || topic.category&.read_restricted))
|
(topic.present? && (topic.private_message? || topic.category&.read_restricted))
|
||||||
end
|
end
|
||||||
|
@ -971,7 +971,7 @@ class Post < ActiveRecord::Base
|
||||||
UploadReference.where(target: self).delete_all
|
UploadReference.where(target: self).delete_all
|
||||||
UploadReference.insert_all(upload_references) if upload_references.size > 0
|
UploadReference.insert_all(upload_references) if upload_references.size > 0
|
||||||
|
|
||||||
if SiteSetting.secure_media?
|
if SiteSetting.secure_uploads?
|
||||||
Upload.where(
|
Upload.where(
|
||||||
id: upload_ids, access_control_post_id: nil
|
id: upload_ids, access_control_post_id: nil
|
||||||
).where(
|
).where(
|
||||||
|
@ -1033,7 +1033,7 @@ class Post < ActiveRecord::Base
|
||||||
next if Rails.configuration.multisite && src.exclude?(current_db)
|
next if Rails.configuration.multisite && src.exclude?(current_db)
|
||||||
|
|
||||||
src = "#{SiteSetting.force_https ? "https" : "http"}:#{src}" if src.start_with?("//")
|
src = "#{SiteSetting.force_https ? "https" : "http"}:#{src}" if src.start_with?("//")
|
||||||
next unless Discourse.store.has_been_uploaded?(src) || Upload.secure_media_url?(src) || (include_local_upload && src =~ /\A\/[^\/]/i)
|
next unless Discourse.store.has_been_uploaded?(src) || Upload.secure_uploads_url?(src) || (include_local_upload && src =~ /\A\/[^\/]/i)
|
||||||
|
|
||||||
path = begin
|
path = begin
|
||||||
URI(UrlHelper.unencode(GlobalSetting.cdn_url ? src.sub(GlobalSetting.cdn_url, "") : src))&.path
|
URI(UrlHelper.unencode(GlobalSetting.cdn_url ? src.sub(GlobalSetting.cdn_url, "") : src))&.path
|
||||||
|
|
|
@ -186,7 +186,7 @@ class Upload < ActiveRecord::Base
|
||||||
"upload://#{short_url_basename}"
|
"upload://#{short_url_basename}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def uploaded_before_secure_media_enabled?
|
def uploaded_before_secure_uploads_enabled?
|
||||||
original_sha1.blank?
|
original_sha1.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -204,14 +204,14 @@ class Upload < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.consider_for_reuse(upload, post)
|
def self.consider_for_reuse(upload, post)
|
||||||
return upload if !SiteSetting.secure_media? || upload.blank? || post.blank?
|
return upload if !SiteSetting.secure_uploads? || upload.blank? || post.blank?
|
||||||
return nil if !upload.matching_access_control_post?(post) || upload.uploaded_before_secure_media_enabled?
|
return nil if !upload.matching_access_control_post?(post) || upload.uploaded_before_secure_uploads_enabled?
|
||||||
upload
|
upload
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.secure_media_url?(url)
|
def self.secure_uploads_url?(url)
|
||||||
# we do not want to exclude topic links that for whatever reason
|
# we do not want to exclude topic links that for whatever reason
|
||||||
# have secure-media-uploads in the URL e.g. /t/secure-media-uploads-are-cool/223452
|
# have secure-uploads in the URL e.g. /t/secure-uploads-are-cool/223452
|
||||||
route = UrlHelper.rails_route_from_url(url)
|
route = UrlHelper.rails_route_from_url(url)
|
||||||
return false if route.blank?
|
return false if route.blank?
|
||||||
route[:action] == "show_secure" && route[:controller] == "uploads" && FileHelper.is_supported_media?(url)
|
route[:action] == "show_secure" && route[:controller] == "uploads" && FileHelper.is_supported_media?(url)
|
||||||
|
@ -219,14 +219,14 @@ class Upload < ActiveRecord::Base
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.signed_url_from_secure_media_url(url)
|
def self.signed_url_from_secure_uploads_url(url)
|
||||||
route = UrlHelper.rails_route_from_url(url)
|
route = UrlHelper.rails_route_from_url(url)
|
||||||
url = Rails.application.routes.url_for(route.merge(only_path: true))
|
url = Rails.application.routes.url_for(route.merge(only_path: true))
|
||||||
secure_upload_s3_path = url[url.index(route[:path])..-1]
|
secure_upload_s3_path = url[url.index(route[:path])..-1]
|
||||||
Discourse.store.signed_url_for_path(secure_upload_s3_path)
|
Discourse.store.signed_url_for_path(secure_upload_s3_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.secure_media_url_from_upload_url(url)
|
def self.secure_uploads_url_from_upload_url(url)
|
||||||
return url if !url.include?(SiteSetting.Upload.absolute_base_url)
|
return url if !url.include?(SiteSetting.Upload.absolute_base_url)
|
||||||
uri = URI.parse(url)
|
uri = URI.parse(url)
|
||||||
Rails.application.routes.url_for(
|
Rails.application.routes.url_for(
|
||||||
|
|
|
@ -290,7 +290,7 @@ class TopicViewSerializer < ApplicationSerializer
|
||||||
SiteSetting.enable_page_publishing? &&
|
SiteSetting.enable_page_publishing? &&
|
||||||
scope.is_staff? &&
|
scope.is_staff? &&
|
||||||
object.published_page.present? &&
|
object.published_page.present? &&
|
||||||
!SiteSetting.secure_media
|
!SiteSetting.secure_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
def thumbnails
|
def thumbnails
|
||||||
|
|
|
@ -17,6 +17,6 @@ class UploadSerializer < ApplicationSerializer
|
||||||
:dominant_color
|
:dominant_color
|
||||||
|
|
||||||
def url
|
def url
|
||||||
object.for_site_setting ? object.url : UrlHelper.cook_url(object.url, secure: SiteSetting.secure_media? && object.secure)
|
object.for_site_setting ? object.url : UrlHelper.cook_url(object.url, secure: SiteSetting.secure_uploads? && object.secure)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,6 +45,7 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
|
||||||
/^\/site_customizations/,
|
/^\/site_customizations/,
|
||||||
/^\/uploads/,
|
/^\/uploads/,
|
||||||
/^\/secure-media-uploads/,
|
/^\/secure-media-uploads/,
|
||||||
|
/^\/secure-uploads/,
|
||||||
/^\/javascripts\//,
|
/^\/javascripts\//,
|
||||||
/^\/images\//,
|
/^\/images\//,
|
||||||
/^\/stylesheets\//,
|
/^\/stylesheets\//,
|
||||||
|
|
|
@ -139,7 +139,7 @@ en:
|
||||||
unsubscribe_not_allowed: "Happens when unsubscribing via email is not allowed for this user."
|
unsubscribe_not_allowed: "Happens when unsubscribing via email is not allowed for this user."
|
||||||
email_not_allowed: "Happens when the email address is not on the allowlist or is on the blocklist."
|
email_not_allowed: "Happens when the email address is not on the allowlist or is on the blocklist."
|
||||||
unrecognized_error: "Unrecognized Error"
|
unrecognized_error: "Unrecognized Error"
|
||||||
secure_media_placeholder: "Redacted: This site has secure media enabled, visit the topic or click View Media to see the attached media."
|
secure_uploads_placeholder: "Redacted: This site has secure uploads enabled, visit the topic or click View Media to see the attached uploads."
|
||||||
view_redacted_media: "View Media"
|
view_redacted_media: "View Media"
|
||||||
|
|
||||||
errors: &errors
|
errors: &errors
|
||||||
|
@ -210,7 +210,7 @@ en:
|
||||||
page_publishing_requirements: "Page publishing cannot be enabled if secure media is enabled."
|
page_publishing_requirements: "Page publishing cannot be enabled if secure media is enabled."
|
||||||
s3_backup_requires_s3_settings: "You cannot use S3 as backup location unless you've provided the '%{setting_name}'."
|
s3_backup_requires_s3_settings: "You cannot use S3 as backup location unless you've provided the '%{setting_name}'."
|
||||||
s3_bucket_reused: "You cannot use the same bucket for 's3_upload_bucket' and 's3_backup_bucket'. Choose a different bucket or use a different path for each bucket."
|
s3_bucket_reused: "You cannot use the same bucket for 's3_upload_bucket' and 's3_backup_bucket'. Choose a different bucket or use a different path for each bucket."
|
||||||
secure_media_requirements: "S3 uploads must be enabled before enabling secure media."
|
secure_uploads_requirements: "S3 uploads must be enabled before enabling secure uploads."
|
||||||
share_quote_facebook_requirements: "You must set a Facebook app id to enable quote sharing for Facebook."
|
share_quote_facebook_requirements: "You must set a Facebook app id to enable quote sharing for Facebook."
|
||||||
second_factor_cannot_enforce_with_socials: "You cannot enforce 2FA with social logins enabled. You must first disable login via: %{auth_provider_names}"
|
second_factor_cannot_enforce_with_socials: "You cannot enforce 2FA with social logins enabled. You must first disable login via: %{auth_provider_names}"
|
||||||
second_factor_cannot_be_enforced_with_disabled_local_login: "You cannot enforce 2FA if local logins are disabled."
|
second_factor_cannot_be_enforced_with_disabled_local_login: "You cannot enforce 2FA if local logins are disabled."
|
||||||
|
@ -2219,9 +2219,12 @@ en:
|
||||||
bootstrap_mode_min_users: "Minimum number of users required to disable bootstrap mode (set to 0 to disable)"
|
bootstrap_mode_min_users: "Minimum number of users required to disable bootstrap mode (set to 0 to disable)"
|
||||||
|
|
||||||
prevent_anons_from_downloading_files: "Prevent anonymous users from downloading attachments."
|
prevent_anons_from_downloading_files: "Prevent anonymous users from downloading attachments."
|
||||||
secure_media: 'Limits access to ALL uploads (images, video, audio, text, pdfs, zips, and others). If “login required” is enabled, only logged-in users can access uploads. Otherwise, access will be limited only for media uploads in private messages and private categories. WARNING: This setting is complex and requires deep administrative understanding. See <a target="_blank" href="https://meta.discourse.org/t/secure-media-uploads/140017">the secure media topic on Meta</a> for details.'
|
secure_media: 'DEPRECATED: Use the secure_uploads setting instead, will be removed in Discourse 3.0.'
|
||||||
secure_media_allow_embed_images_in_emails: "Allows embedding secure images that would normally be redacted in emails, if their size is smaller than the 'secure media max email embed image size kb' setting."
|
secure_uploads: 'Limits access to ALL uploads (images, video, audio, text, pdfs, zips, and others). If "login required” is enabled, only logged-in users can access uploads. Otherwise, access will be limited only for media uploads in private messages and private categories. WARNING: This setting is complex and requires deep administrative understanding. See <a target="_blank" href="https://meta.discourse.org/t/-/140017">the secure uploads topic on Meta</a> for details.'
|
||||||
secure_media_max_email_embed_image_size_kb: "The size cutoff for secure images that will be embedded in emails if the 'secure media allow embed in emails' setting is enabled. Without that setting enabled, this setting has no effect."
|
secure_media_allow_embed_images_in_emails: "DEPRECATED: Use secure_uploads_allow_embed_images_in_emails, will remove in Discourse 3.0."
|
||||||
|
secure_uploads_allow_embed_images_in_emails: "Allows embedding secure images that would normally be redacted in emails, if their size is smaller than the 'secure uploads max email embed image size kb' setting."
|
||||||
|
secure_media_max_email_embed_image_size_kb: "DEPRECATED: Use secure_uploads_max_email_embed_image_size_kb, will be removed in Discourse 3.0."
|
||||||
|
secure_uploads_max_email_embed_image_size_kb: "The size cutoff for secure images that will be embedded in emails if the 'secure uploads allow embed in emails' setting is enabled. Without that setting enabled, this setting has no effect."
|
||||||
slug_generation_method: "Choose a slug generation method. 'encoded' will generate percent encoding string. 'none' will disable slug at all."
|
slug_generation_method: "Choose a slug generation method. 'encoded' will generate percent encoding string. 'none' will disable slug at all."
|
||||||
|
|
||||||
enable_emoji: "Enable emoji"
|
enable_emoji: "Enable emoji"
|
||||||
|
|
|
@ -110,7 +110,7 @@ server {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^/secure-media-uploads/ {
|
location ~ ^/(secure-media-uploads/|secure-uploads)/ {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Request-Start "t=${msec}";
|
proxy_set_header X-Request-Start "t=${msec}";
|
||||||
|
|
|
@ -583,7 +583,12 @@ Discourse::Application.routes.draw do
|
||||||
end
|
end
|
||||||
# used to download attachments (old route)
|
# used to download attachments (old route)
|
||||||
get "uploads/:site/:id/:sha" => "uploads#show", constraints: { site: /\w+/, id: /\d+/, sha: /\h{16}/, format: /.*/ }
|
get "uploads/:site/:id/:sha" => "uploads#show", constraints: { site: /\w+/, id: /\d+/, sha: /\h{16}/, format: /.*/ }
|
||||||
get "secure-media-uploads/*path(.:extension)" => "uploads#show_secure", constraints: { extension: /[a-z0-9\._]+/i }
|
|
||||||
|
# NOTE: secure-media-uploads is the old form, all new URLs generated for
|
||||||
|
# secure uploads will be secure-uploads, this is left in for backwards
|
||||||
|
# compat without needing to rebake all posts for each site.
|
||||||
|
get "secure-media-uploads/*path(.:extension)" => "uploads#_show_secure_deprecated", constraints: { extension: /[a-z0-9\._]+/i }
|
||||||
|
get "secure-uploads/*path(.:extension)" => "uploads#show_secure", constraints: { extension: /[a-z0-9\._]+/i }
|
||||||
|
|
||||||
get "posts" => "posts#latest", id: "latest_posts", constraints: { format: /(json|rss)/ }
|
get "posts" => "posts#latest", id: "latest_posts", constraints: { format: /(json|rss)/ }
|
||||||
get "private-posts" => "posts#latest", id: "private_posts", constraints: { format: /(json|rss)/ }
|
get "private-posts" => "posts#latest", id: "private_posts", constraints: { format: /(json|rss)/ }
|
||||||
|
|
|
@ -1365,12 +1365,24 @@ files:
|
||||||
secure_media:
|
secure_media:
|
||||||
default: false
|
default: false
|
||||||
client: true
|
client: true
|
||||||
|
hidden: true
|
||||||
secure_media_allow_embed_images_in_emails:
|
secure_media_allow_embed_images_in_emails:
|
||||||
default: true
|
default: true
|
||||||
|
hidden: true
|
||||||
secure_media_max_email_embed_image_size_kb:
|
secure_media_max_email_embed_image_size_kb:
|
||||||
default: 1024
|
default: 1024
|
||||||
min: 1
|
min: 1
|
||||||
max: 10240
|
max: 10240
|
||||||
|
hidden: true
|
||||||
|
secure_uploads:
|
||||||
|
default: false
|
||||||
|
client: true
|
||||||
|
secure_uploads_allow_embed_images_in_emails:
|
||||||
|
default: true
|
||||||
|
secure_uploads_max_email_embed_image_size_kb:
|
||||||
|
default: 1024
|
||||||
|
min: 1
|
||||||
|
max: 10240
|
||||||
enable_s3_uploads:
|
enable_s3_uploads:
|
||||||
default: false
|
default: false
|
||||||
client: true
|
client: true
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SetSecureUploadsSettingsBasedOnSecureMediaEquivalent < ActiveRecord::Migration[7.0]
|
||||||
|
def up
|
||||||
|
secure_media_enabled = DB.query_single("SELECT value FROM site_settings WHERE name = 'secure_media'")
|
||||||
|
|
||||||
|
if secure_media_enabled.present? && secure_media_enabled[0] == "t"
|
||||||
|
execute <<~SQL
|
||||||
|
INSERT INTO site_settings(name, data_type, value, created_at, updated_at)
|
||||||
|
VALUES ('secure_uploads', 5, 't', now(), now())
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
secure_media_allow_embed_images_in_emails = DB.query_single("SELECT value FROM site_settings WHERE name = 'secure_media_allow_embed_images_in_emails'")
|
||||||
|
|
||||||
|
if secure_media_allow_embed_images_in_emails.present? && secure_media_allow_embed_images_in_emails[0] == "t"
|
||||||
|
execute <<~SQL
|
||||||
|
INSERT INTO site_settings(name, data_type, value, created_at, updated_at)
|
||||||
|
VALUES ('secure_uploads_allow_embed_images_in_emails', 5, 't', now(), now())
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
secure_media_max_email_embed_image_size_kb = DB.query_single("SELECT value FROM site_settings WHERE name = 'secure_media_max_email_embed_image_size_kb'")
|
||||||
|
|
||||||
|
if secure_media_max_email_embed_image_size_kb.present?
|
||||||
|
execute <<~SQL
|
||||||
|
INSERT INTO site_settings(name, data_type, value, created_at, updated_at)
|
||||||
|
VALUES ('secure_uploads_max_email_embed_image_size_kb', 3, '#{secure_uploads_max_email_embed_image_size_kb[0]}', now(), now())
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
|
@ -22,7 +22,7 @@ class CookedPostProcessor
|
||||||
@cooking_options = post.cooking_options || opts[:cooking_options] || {}
|
@cooking_options = post.cooking_options || opts[:cooking_options] || {}
|
||||||
@cooking_options[:topic_id] = post.topic_id
|
@cooking_options[:topic_id] = post.topic_id
|
||||||
@cooking_options = @cooking_options.symbolize_keys
|
@cooking_options = @cooking_options.symbolize_keys
|
||||||
@with_secure_media = @post.with_secure_media?
|
@with_secure_uploads = @post.with_secure_uploads?
|
||||||
@category_id = @post&.topic&.category_id
|
@category_id = @post&.topic&.category_id
|
||||||
|
|
||||||
cooked = post.cook(post.raw, @cooking_options)
|
cooked = post.cook(post.raw, @cooking_options)
|
||||||
|
@ -225,14 +225,14 @@ class CookedPostProcessor
|
||||||
resized_h = (h * ratio).to_i
|
resized_h = (h * ratio).to_i
|
||||||
|
|
||||||
if !cropped && upload.width && resized_w > upload.width
|
if !cropped && upload.width && resized_w > upload.width
|
||||||
cooked_url = UrlHelper.cook_url(upload.url, secure: @post.with_secure_media?)
|
cooked_url = UrlHelper.cook_url(upload.url, secure: @post.with_secure_uploads?)
|
||||||
srcset << ", #{cooked_url} #{ratio.to_s.sub(/\.0$/, "")}x"
|
srcset << ", #{cooked_url} #{ratio.to_s.sub(/\.0$/, "")}x"
|
||||||
elsif t = upload.thumbnail(resized_w, resized_h)
|
elsif t = upload.thumbnail(resized_w, resized_h)
|
||||||
cooked_url = UrlHelper.cook_url(t.url, secure: @post.with_secure_media?)
|
cooked_url = UrlHelper.cook_url(t.url, secure: @post.with_secure_uploads?)
|
||||||
srcset << ", #{cooked_url} #{ratio.to_s.sub(/\.0$/, "")}x"
|
srcset << ", #{cooked_url} #{ratio.to_s.sub(/\.0$/, "")}x"
|
||||||
end
|
end
|
||||||
|
|
||||||
img["srcset"] = "#{UrlHelper.cook_url(img["src"], secure: @post.with_secure_media?)}#{srcset}" if srcset.present?
|
img["srcset"] = "#{UrlHelper.cook_url(img["src"], secure: @post.with_secure_uploads?)}#{srcset}" if srcset.present?
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
img["src"] = upload.url
|
img["src"] = upload.url
|
||||||
|
@ -250,7 +250,7 @@ class CookedPostProcessor
|
||||||
lightbox.add_child(img)
|
lightbox.add_child(img)
|
||||||
|
|
||||||
# then, the link to our larger image
|
# then, the link to our larger image
|
||||||
src = UrlHelper.cook_url(img["src"], secure: @post.with_secure_media?)
|
src = UrlHelper.cook_url(img["src"], secure: @post.with_secure_uploads?)
|
||||||
a = create_link_node("lightbox", src)
|
a = create_link_node("lightbox", src)
|
||||||
img.add_next_sibling(a)
|
img.add_next_sibling(a)
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ class CookedPostProcessor
|
||||||
@doc.css("img[#{selector}]").each do |img|
|
@doc.css("img[#{selector}]").each do |img|
|
||||||
custom_emoji = img["class"]&.include?("emoji-custom") && Emoji.custom?(img["title"])
|
custom_emoji = img["class"]&.include?("emoji-custom") && Emoji.custom?(img["title"])
|
||||||
img[selector] = UrlHelper.cook_url(
|
img[selector] = UrlHelper.cook_url(
|
||||||
img[selector].to_s, secure: @post.with_secure_media? && !custom_emoji
|
img[selector].to_s, secure: @post.with_secure_uploads? && !custom_emoji
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -384,7 +384,7 @@ class CookedPostProcessor
|
||||||
|
|
||||||
still_an_image = false
|
still_an_image = false
|
||||||
elsif info&.downloaded? && upload = info&.upload
|
elsif info&.downloaded? && upload = info&.upload
|
||||||
img["src"] = UrlHelper.cook_url(upload.url, secure: @with_secure_media)
|
img["src"] = UrlHelper.cook_url(upload.url, secure: @with_secure_uploads)
|
||||||
img.delete(PrettyText::BLOCKED_HOTLINKED_SRC_ATTR)
|
img.delete(PrettyText::BLOCKED_HOTLINKED_SRC_ATTR)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -175,10 +175,10 @@ module CookedProcessorMixin
|
||||||
# FastImage fails when there's no scheme
|
# FastImage fails when there's no scheme
|
||||||
absolute_url = SiteSetting.scheme + ":" + absolute_url if absolute_url.start_with?("//")
|
absolute_url = SiteSetting.scheme + ":" + absolute_url if absolute_url.start_with?("//")
|
||||||
|
|
||||||
# we can't direct FastImage to our secure-media-uploads url because it bounces
|
# we can't direct FastImage to our secure-uploads url because it bounces
|
||||||
# anonymous requests with a 404 error
|
# anonymous requests with a 404 error
|
||||||
if url && Upload.secure_media_url?(url)
|
if url && Upload.secure_uploads_url?(url)
|
||||||
absolute_url = Upload.signed_url_from_secure_media_url(absolute_url)
|
absolute_url = Upload.signed_url_from_secure_uploads_url(absolute_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
return unless is_valid_image_url?(absolute_url)
|
return unless is_valid_image_url?(absolute_url)
|
||||||
|
|
|
@ -242,7 +242,7 @@ module Email
|
||||||
|
|
||||||
# Embeds any of the secure images that have been attached inline,
|
# Embeds any of the secure images that have been attached inline,
|
||||||
# removing the redaction notice.
|
# removing the redaction notice.
|
||||||
if SiteSetting.secure_media_allow_embed_images_in_emails
|
if SiteSetting.secure_uploads_allow_embed_images_in_emails
|
||||||
style.inline_secure_images(@message.attachments, @message_attachments_index)
|
style.inline_secure_images(@message.attachments, @message_attachments_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -357,8 +357,8 @@ module Email
|
||||||
end
|
end
|
||||||
|
|
||||||
def should_attach_image?(upload, optimized_1X = nil)
|
def should_attach_image?(upload, optimized_1X = nil)
|
||||||
return if !SiteSetting.secure_media_allow_embed_images_in_emails || !upload.secure?
|
return if !SiteSetting.secure_uploads_allow_embed_images_in_emails || !upload.secure?
|
||||||
return if (optimized_1X&.filesize || upload.filesize) > SiteSetting.secure_media_max_email_embed_image_size_kb.kilobytes
|
return if (optimized_1X&.filesize || upload.filesize) > SiteSetting.secure_uploads_max_email_embed_image_size_kb.kilobytes
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -257,10 +257,10 @@ module Email
|
||||||
end
|
end
|
||||||
|
|
||||||
def inline_secure_images(attachments, attachments_index)
|
def inline_secure_images(attachments, attachments_index)
|
||||||
stripped_media = @fragment.css('[data-stripped-secure-media]')
|
stripped_media = @fragment.css('[data-stripped-secure-media], [data-stripped-secure-upload]')
|
||||||
upload_shas = {}
|
upload_shas = {}
|
||||||
stripped_media.each do |div|
|
stripped_media.each do |div|
|
||||||
url = div['data-stripped-secure-media']
|
url = div['data-stripped-secure-media'] || div['data-stripped-secure-upload']
|
||||||
filename = File.basename(url)
|
filename = File.basename(url)
|
||||||
filename_bare = filename.gsub(File.extname(filename), "")
|
filename_bare = filename.gsub(File.extname(filename), "")
|
||||||
sha1 = filename_bare.partition('_').first
|
sha1 = filename_bare.partition('_').first
|
||||||
|
@ -269,7 +269,9 @@ module Email
|
||||||
uploads = Upload.select(:original_filename, :sha1).where(sha1: upload_shas.values)
|
uploads = Upload.select(:original_filename, :sha1).where(sha1: upload_shas.values)
|
||||||
|
|
||||||
stripped_media.each do |div|
|
stripped_media.each do |div|
|
||||||
upload = uploads.find { |upl| upl.sha1 == upload_shas[div['data-stripped-secure-media']] }
|
upload = uploads.find do |upl|
|
||||||
|
upl.sha1 == (upload_shas[div['data-stripped-secure-media']] || upload_shas[div['data-stripped-secure-upload']])
|
||||||
|
end
|
||||||
next if !upload
|
next if !upload
|
||||||
|
|
||||||
if attachments[attachments_index[upload.sha1]]
|
if attachments[attachments_index[upload.sha1]]
|
||||||
|
@ -294,7 +296,7 @@ module Email
|
||||||
def to_html
|
def to_html
|
||||||
# needs to be before class + id strip because we need to style redacted
|
# needs to be before class + id strip because we need to style redacted
|
||||||
# media and also not double-redact already redacted from lower levels
|
# media and also not double-redact already redacted from lower levels
|
||||||
replace_secure_media_urls if SiteSetting.secure_media?
|
replace_secure_uploads_urls if SiteSetting.secure_uploads?
|
||||||
strip_classes_and_ids
|
strip_classes_and_ids
|
||||||
replace_relative_urls
|
replace_relative_urls
|
||||||
|
|
||||||
|
@ -369,13 +371,13 @@ module Email
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def replace_secure_media_urls
|
def replace_secure_uploads_urls
|
||||||
# strip again, this can be done at a lower level like in the user
|
# strip again, this can be done at a lower level like in the user
|
||||||
# notification template but that may not catch everything
|
# notification template but that may not catch everything
|
||||||
PrettyText.strip_secure_media(@fragment)
|
PrettyText.strip_secure_uploads(@fragment)
|
||||||
|
|
||||||
style('div.secure-media-notice', 'border: 5px solid #e9e9e9; padding: 5px; display: inline-block;')
|
style('div.secure-upload-notice', 'border: 5px solid #e9e9e9; padding: 5px; display: inline-block;')
|
||||||
style('div.secure-media-notice a', "color: #{SiteSetting.email_link_color}")
|
style('div.secure-upload-notice a', "color: #{SiteSetting.email_link_color}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def correct_first_body_margin
|
def correct_first_body_margin
|
||||||
|
|
|
@ -543,7 +543,7 @@ class Guardian
|
||||||
|
|
||||||
def can_publish_page?(topic)
|
def can_publish_page?(topic)
|
||||||
return false if !SiteSetting.enable_page_publishing?
|
return false if !SiteSetting.enable_page_publishing?
|
||||||
return false if SiteSetting.secure_media?
|
return false if SiteSetting.secure_uploads?
|
||||||
return false if topic.blank?
|
return false if topic.blank?
|
||||||
return false if topic.private_message?
|
return false if topic.private_message?
|
||||||
return false unless can_see_topic?(topic)
|
return false unless can_see_topic?(topic)
|
||||||
|
|
|
@ -398,7 +398,7 @@ class PostCreator
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_uploads_secure_status
|
def update_uploads_secure_status
|
||||||
@post.update_uploads_secure_status(source: "post creator") if SiteSetting.secure_media?
|
@post.update_uploads_secure_status(source: "post creator") if SiteSetting.secure_uploads?
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_owned_bookmarks
|
def delete_owned_bookmarks
|
||||||
|
|
|
@ -488,14 +488,14 @@ module PrettyText
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.strip_secure_media(doc)
|
def self.strip_secure_uploads(doc)
|
||||||
# images inside a lightbox or other link
|
# images inside a lightbox or other link
|
||||||
doc.css('a[href]').each do |a|
|
doc.css('a[href]').each do |a|
|
||||||
next if !Upload.secure_media_url?(a['href'])
|
next if !Upload.secure_uploads_url?(a['href'])
|
||||||
|
|
||||||
non_image_media = %w(video audio).include?(a&.parent&.name)
|
non_image_media = %w(video audio).include?(a&.parent&.name)
|
||||||
target = non_image_media ? a.parent : a
|
target = non_image_media ? a.parent : a
|
||||||
next if target.to_s.include?('stripped-secure-view-media')
|
next if target.to_s.include?('stripped-secure-view-media') || target.to_s.include?('stripped-secure-view-upload')
|
||||||
|
|
||||||
next if a.css('img[src]').empty? && !non_image_media
|
next if a.css('img[src]').empty? && !non_image_media
|
||||||
|
|
||||||
|
@ -509,12 +509,12 @@ module PrettyText
|
||||||
else
|
else
|
||||||
url = img['src']
|
url = img['src']
|
||||||
end
|
end
|
||||||
a.add_next_sibling secure_media_placeholder(doc, url, width: img['width'], height: img['height'])
|
a.add_next_sibling secure_uploads_placeholder(doc, url, width: img['width'], height: img['height'])
|
||||||
a.remove
|
a.remove
|
||||||
else
|
else
|
||||||
width = non_image_media ? nil : a.at_css('img').attr('width')
|
width = non_image_media ? nil : a.at_css('img').attr('width')
|
||||||
height = non_image_media ? nil : a.at_css('img').attr('height')
|
height = non_image_media ? nil : a.at_css('img').attr('height')
|
||||||
target.add_next_sibling secure_media_placeholder(doc, a['href'], width: width, height: height)
|
target.add_next_sibling secure_uploads_placeholder(doc, a['href'], width: width, height: height)
|
||||||
target.remove
|
target.remove
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -551,20 +551,20 @@ module PrettyText
|
||||||
height = 16
|
height = 16
|
||||||
end
|
end
|
||||||
|
|
||||||
if Upload.secure_media_url?(url)
|
if Upload.secure_uploads_url?(url)
|
||||||
img.add_next_sibling secure_media_placeholder(doc, url, onebox_type: onebox_type, width: width, height: height)
|
img.add_next_sibling secure_uploads_placeholder(doc, url, onebox_type: onebox_type, width: width, height: height)
|
||||||
img.remove
|
img.remove
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.secure_media_placeholder(doc, url, onebox_type: false, width: nil, height: nil)
|
def self.secure_uploads_placeholder(doc, url, onebox_type: false, width: nil, height: nil)
|
||||||
data_width = width ? "data-width=#{width}" : ''
|
data_width = width ? "data-width=#{width}" : ''
|
||||||
data_height = height ? "data-height=#{height}" : ''
|
data_height = height ? "data-height=#{height}" : ''
|
||||||
data_onebox_type = onebox_type ? "data-onebox-type='#{onebox_type}'" : ''
|
data_onebox_type = onebox_type ? "data-onebox-type='#{onebox_type}'" : ''
|
||||||
<<~HTML
|
<<~HTML
|
||||||
<div class="secure-media-notice" data-stripped-secure-media="#{url}" #{data_onebox_type} #{data_width} #{data_height}>
|
<div class="secure-upload-notice" data-stripped-secure-upload="#{url}" #{data_onebox_type} #{data_width} #{data_height}>
|
||||||
#{I18n.t('emails.secure_media_placeholder')} <a class='stripped-secure-view-media' href="#{url}">#{I18n.t("emails.view_redacted_media")}</a>.
|
#{I18n.t('emails.secure_uploads_placeholder')} <a class='stripped-secure-view-upload' href="#{url}">#{I18n.t("emails.view_redacted_media")}</a>.
|
||||||
</div>
|
</div>
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
@ -572,7 +572,7 @@ module PrettyText
|
||||||
def self.format_for_email(html, post = nil)
|
def self.format_for_email(html, post = nil)
|
||||||
doc = Nokogiri::HTML5.fragment(html)
|
doc = Nokogiri::HTML5.fragment(html)
|
||||||
DiscourseEvent.trigger(:reduce_cooked, doc, post)
|
DiscourseEvent.trigger(:reduce_cooked, doc, post)
|
||||||
strip_secure_media(doc) if post&.with_secure_media?
|
strip_secure_uploads(doc) if post&.with_secure_uploads?
|
||||||
strip_image_wrapping(doc)
|
strip_image_wrapping(doc)
|
||||||
convert_vimeo_iframes(doc)
|
convert_vimeo_iframes(doc)
|
||||||
make_all_links_absolute(doc)
|
make_all_links_absolute(doc)
|
||||||
|
|
|
@ -70,11 +70,11 @@ module PrettyText
|
||||||
sha1, url, extension, original_filename, secure = row
|
sha1, url, extension, original_filename, secure = row
|
||||||
|
|
||||||
if short_urls = reverse_map[sha1]
|
if short_urls = reverse_map[sha1]
|
||||||
secure_media = SiteSetting.secure_media? && secure
|
secure_uploads = SiteSetting.secure_uploads? && secure
|
||||||
|
|
||||||
short_urls.each do |short_url|
|
short_urls.each do |short_url|
|
||||||
result[short_url] = {
|
result[short_url] = {
|
||||||
url: secure_media ? Upload.secure_media_url_from_upload_url(url) : Discourse.store.cdn_url(url),
|
url: secure_uploads ? Upload.secure_uploads_url_from_upload_url(url) : Discourse.store.cdn_url(url),
|
||||||
short_path: Upload.short_path(sha1: sha1, extension: extension),
|
short_path: Upload.short_path(sha1: sha1, extension: extension),
|
||||||
base62_sha1: Upload.base62_sha1(sha1)
|
base62_sha1: Upload.base62_sha1(sha1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ module SiteSettings::DeprecatedSettings
|
||||||
['default_categories_regular', 'default_categories_normal', true, '3.0'],
|
['default_categories_regular', 'default_categories_normal', true, '3.0'],
|
||||||
['min_trust_to_send_messages', 'personal_message_enabled_groups', false, '3.0'],
|
['min_trust_to_send_messages', 'personal_message_enabled_groups', false, '3.0'],
|
||||||
['enable_personal_messages', 'personal_message_enabled_groups', false, '3.0'],
|
['enable_personal_messages', 'personal_message_enabled_groups', false, '3.0'],
|
||||||
|
['secure_media', 'secure_uploads', true, '3.0'],
|
||||||
|
['secure_media_allow_embed_images_in_emails', 'secure_uploads_allow_embed_images_in_emails', true, '3.0'],
|
||||||
|
['secure_media_max_email_embed_image_size_kb', 'secure_uploads_max_email_embed_image_size_kb', true, '3.0'],
|
||||||
]
|
]
|
||||||
|
|
||||||
def setup_deprecated_methods
|
def setup_deprecated_methods
|
||||||
|
|
|
@ -162,12 +162,12 @@ module SiteSettings::Validations
|
||||||
validate_error :s3_upload_bucket_is_required if SiteSetting.s3_upload_bucket.blank?
|
validate_error :s3_upload_bucket_is_required if SiteSetting.s3_upload_bucket.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_secure_media(new_val)
|
def validate_secure_uploads(new_val)
|
||||||
validate_error :secure_media_requirements if new_val == "t" && !SiteSetting.Upload.enable_s3_uploads
|
validate_error :secure_uploads_requirements if new_val == "t" && !SiteSetting.Upload.enable_s3_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_enable_page_publishing(new_val)
|
def validate_enable_page_publishing(new_val)
|
||||||
validate_error :page_publishing_requirements if new_val == "t" && SiteSetting.secure_media?
|
validate_error :page_publishing_requirements if new_val == "t" && SiteSetting.secure_uploads?
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_share_quote_buttons(new_val)
|
def validate_share_quote_buttons(new_val)
|
||||||
|
|
|
@ -518,16 +518,16 @@ task "uploads:sync_s3_acls" => :environment do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task "uploads:disable_secure_media" => :environment do
|
task "uploads:disable_secure_uploads" => :environment do
|
||||||
RailsMultisite::ConnectionManagement.each_connection do |db|
|
RailsMultisite::ConnectionManagement.each_connection do |db|
|
||||||
unless Discourse.store.external?
|
unless Discourse.store.external?
|
||||||
puts "This task only works for external storage."
|
puts "This task only works for external storage."
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "Disabling secure media and resetting uploads to not secure in #{db}...", ""
|
puts "Disabling secure upload and resetting uploads to not secure in #{db}...", ""
|
||||||
|
|
||||||
SiteSetting.secure_media = false
|
SiteSetting.secure_uploads = false
|
||||||
|
|
||||||
secure_uploads = Upload.joins(:upload_references).where(upload_references: { target_type: 'Post' }).where(secure: true)
|
secure_uploads = Upload.joins(:upload_references).where(upload_references: { target_type: 'Post' }).where(secure: true)
|
||||||
secure_upload_count = secure_uploads.count
|
secure_upload_count = secure_uploads.count
|
||||||
|
@ -537,7 +537,7 @@ task "uploads:disable_secure_media" => :environment do
|
||||||
secure_uploads.update_all(
|
secure_uploads.update_all(
|
||||||
secure: false,
|
secure: false,
|
||||||
security_last_changed_at: Time.zone.now,
|
security_last_changed_at: Time.zone.now,
|
||||||
security_last_changed_reason: "marked as not secure by disable_secure_media task"
|
security_last_changed_reason: "marked as not secure by disable_secure_uploads task"
|
||||||
)
|
)
|
||||||
|
|
||||||
post_ids_to_rebake = DB.query_single(
|
post_ids_to_rebake = DB.query_single(
|
||||||
|
@ -550,11 +550,11 @@ task "uploads:disable_secure_media" => :environment do
|
||||||
puts "", "Rebaking and uploading complete!", ""
|
puts "", "Rebaking and uploading complete!", ""
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "", "Secure media is now disabled!", ""
|
puts "", "Secure uploads are now disabled!", ""
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Run this task whenever the secure_media or login_required
|
# Run this task whenever the secure_uploads or login_required
|
||||||
# settings are changed for a Discourse instance to update
|
# settings are changed for a Discourse instance to update
|
||||||
# the upload secure flag and S3 upload ACLs. Any uploads that
|
# the upload secure flag and S3 upload ACLs. Any uploads that
|
||||||
# have their secure status changed will have all associated posts
|
# have their secure status changed will have all associated posts
|
||||||
|
@ -569,12 +569,12 @@ task "uploads:secure_upload_analyse_and_update" => :environment do
|
||||||
puts "Analyzing security for uploads in #{db}...", ""
|
puts "Analyzing security for uploads in #{db}...", ""
|
||||||
all_upload_ids_changed, post_ids_to_rebake = nil
|
all_upload_ids_changed, post_ids_to_rebake = nil
|
||||||
Upload.transaction do
|
Upload.transaction do
|
||||||
# If secure media is enabled we need to first set the access control post of
|
# If secure upload is enabled we need to first set the access control post of
|
||||||
# all post uploads (even uploads that are linked to multiple posts). If the
|
# all post uploads (even uploads that are linked to multiple posts). If the
|
||||||
# upload is not set to secure media then this has no other effect on the upload,
|
# upload is not set to secure upload then this has no other effect on the upload,
|
||||||
# but we _must_ know what the access control post is because the with_secure_media?
|
# but we _must_ know what the access control post is because the with_secure_uploads?
|
||||||
# method is on the post, and this knows about the category security & PM status
|
# method is on the post, and this knows about the category security & PM status
|
||||||
if SiteSetting.secure_media?
|
if SiteSetting.secure_uploads?
|
||||||
update_uploads_access_control_post
|
update_uploads_access_control_post
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
##
|
##
|
||||||
# There are certain conditions with secure media when the security of
|
# There are certain conditions with secure uploads when the security of
|
||||||
# uploads will need to change depending on the context they reside in.
|
# uploads will need to change depending on the context they reside in.
|
||||||
#
|
#
|
||||||
# For example on these conditions:
|
# For example on these conditions:
|
||||||
|
@ -38,16 +38,16 @@ class TopicUploadSecurityManager
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return if !SiteSetting.secure_media
|
return if !SiteSetting.secure_uploads
|
||||||
|
|
||||||
# we only want to do this if secure media is enabled. if
|
# we only want to do this if secure uploads is enabled. if
|
||||||
# the setting is turned on after a site has been running
|
# the setting is turned on after a site has been running
|
||||||
# already, we want to make sure that any post moves after
|
# already, we want to make sure that any post moves after
|
||||||
# this are handled and upload secure statuses and ACLs
|
# this are handled and upload secure statuses and ACLs
|
||||||
# are updated appropriately, as well as setting the access control
|
# are updated appropriately, as well as setting the access control
|
||||||
# post for secure uploads missing it.
|
# post for secure uploads missing it.
|
||||||
#
|
#
|
||||||
# examples (all after secure media is enabled):
|
# examples (all after secure uploads is enabled):
|
||||||
#
|
#
|
||||||
# -> a public topic is moved to a private category after
|
# -> a public topic is moved to a private category after
|
||||||
# -> a PM is converted to a public topic
|
# -> a PM is converted to a public topic
|
||||||
|
|
|
@ -94,15 +94,15 @@ class UploadCreator
|
||||||
if !external_upload_too_big
|
if !external_upload_too_big
|
||||||
sha1 = Upload.generate_digest(@file)
|
sha1 = Upload.generate_digest(@file)
|
||||||
end
|
end
|
||||||
if SiteSetting.secure_media || external_upload_too_big
|
if SiteSetting.secure_uploads || external_upload_too_big
|
||||||
unique_hash = generate_fake_sha1_hash
|
unique_hash = generate_fake_sha1_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
# we do not check for duplicate uploads if secure media is
|
# we do not check for duplicate uploads if secure uploads is
|
||||||
# enabled because we use a unique access hash to differentiate
|
# enabled because we use a unique access hash to differentiate
|
||||||
# between uploads instead of the sha1, and to get around various
|
# between uploads instead of the sha1, and to get around various
|
||||||
# access/permission issues for uploads
|
# access/permission issues for uploads
|
||||||
if !SiteSetting.secure_media && !external_upload_too_big
|
if !SiteSetting.secure_uploads && !external_upload_too_big
|
||||||
# do we already have that upload?
|
# do we already have that upload?
|
||||||
@upload = Upload.find_by(sha1: sha1)
|
@upload = Upload.find_by(sha1: sha1)
|
||||||
|
|
||||||
|
@ -140,8 +140,8 @@ class UploadCreator
|
||||||
@upload.user_id = user_id
|
@upload.user_id = user_id
|
||||||
@upload.original_filename = fixed_original_filename || @filename
|
@upload.original_filename = fixed_original_filename || @filename
|
||||||
@upload.filesize = filesize
|
@upload.filesize = filesize
|
||||||
@upload.sha1 = (SiteSetting.secure_media? || external_upload_too_big) ? unique_hash : sha1
|
@upload.sha1 = (SiteSetting.secure_uploads? || external_upload_too_big) ? unique_hash : sha1
|
||||||
@upload.original_sha1 = SiteSetting.secure_media? ? sha1 : nil
|
@upload.original_sha1 = SiteSetting.secure_uploads? ? sha1 : nil
|
||||||
@upload.url = ""
|
@upload.url = ""
|
||||||
@upload.origin = @opts[:origin][0...1000] if @opts[:origin]
|
@upload.origin = @opts[:origin][0...1000] if @opts[:origin]
|
||||||
@upload.extension = image_type || File.extname(@filename)[1..10]
|
@upload.extension = image_type || File.extname(@filename)[1..10]
|
||||||
|
@ -173,7 +173,7 @@ class UploadCreator
|
||||||
|
|
||||||
add_metadata!
|
add_metadata!
|
||||||
|
|
||||||
if SiteSetting.secure_media
|
if SiteSetting.secure_uploads
|
||||||
secure, reason = UploadSecurity.new(@upload, @opts.merge(creating: true)).should_be_secure_with_reason
|
secure, reason = UploadSecurity.new(@upload, @opts.merge(creating: true)).should_be_secure_with_reason
|
||||||
attrs = @upload.secure_params(secure, reason, "upload creator")
|
attrs = @upload.secure_params(secure, reason, "upload creator")
|
||||||
@upload.assign_attributes(attrs)
|
@upload.assign_attributes(attrs)
|
||||||
|
|
|
@ -66,8 +66,8 @@ class UploadSecurity
|
||||||
[false, "no checks satisfied"]
|
[false, "no checks satisfied"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def secure_media_disabled_check
|
def secure_uploads_disabled_check
|
||||||
!SiteSetting.secure_media?
|
!SiteSetting.secure_uploads?
|
||||||
end
|
end
|
||||||
|
|
||||||
def insecure_creation_for_modifiers_check
|
def insecure_creation_for_modifiers_check
|
||||||
|
@ -96,14 +96,14 @@ class UploadSecurity
|
||||||
|
|
||||||
# whether the upload should remain secure or not after posting depends on its context,
|
# whether the upload should remain secure or not after posting depends on its context,
|
||||||
# which is based on the post it is linked to via access_control_post_id.
|
# which is based on the post it is linked to via access_control_post_id.
|
||||||
# if that post is with_secure_media? then the upload should also be secure.
|
# if that post is with_secure_uploads? then the upload should also be secure.
|
||||||
# this may change to false if the upload was set to secure on upload e.g. in
|
# this may change to false if the upload was set to secure on upload e.g. in
|
||||||
# a post composer then it turned out that the post itself was not in a secure context
|
# a post composer then it turned out that the post itself was not in a secure context
|
||||||
#
|
#
|
||||||
# a post is with secure media if it is a private message or in a read restricted
|
# a post is with secure uploads if it is a private message or in a read restricted
|
||||||
# category
|
# category
|
||||||
def access_control_post_has_secure_media_check
|
def access_control_post_has_secure_uploads_check
|
||||||
access_control_post&.with_secure_media?
|
access_control_post&.with_secure_uploads?
|
||||||
end
|
end
|
||||||
|
|
||||||
def uploading_in_composer_check
|
def uploading_in_composer_check
|
||||||
|
@ -127,7 +127,7 @@ class UploadSecurity
|
||||||
|
|
||||||
def insecure_context_checks
|
def insecure_context_checks
|
||||||
{
|
{
|
||||||
secure_media_disabled: "secure media is disabled",
|
secure_uploads_disabled: "secure uploads is disabled",
|
||||||
insecure_creation_for_modifiers: "one or more creation for_modifiers was satisfied",
|
insecure_creation_for_modifiers: "one or more creation for_modifiers was satisfied",
|
||||||
public_type: "upload is public type",
|
public_type: "upload is public type",
|
||||||
custom_emoji: "upload is used for custom emoji",
|
custom_emoji: "upload is used for custom emoji",
|
||||||
|
@ -138,7 +138,7 @@ class UploadSecurity
|
||||||
def secure_context_checks
|
def secure_context_checks
|
||||||
{
|
{
|
||||||
login_required: "login is required",
|
login_required: "login is required",
|
||||||
access_control_post_has_secure_media: "access control post dictates security",
|
access_control_post_has_secure_uploads: "access control post dictates security",
|
||||||
secure_creation_for_modifiers: "one or more creation for_modifiers was satisfied",
|
secure_creation_for_modifiers: "one or more creation for_modifiers was satisfied",
|
||||||
uploading_in_composer: "uploading via the composer",
|
uploading_in_composer: "uploading via the composer",
|
||||||
already_secure: "upload is already secure"
|
already_secure: "upload is already secure"
|
||||||
|
@ -149,7 +149,7 @@ class UploadSecurity
|
||||||
# of whether an upload should be secure or not, and thus should be returned
|
# of whether an upload should be secure or not, and thus should be returned
|
||||||
# immediately if there is an access control post
|
# immediately if there is an access control post
|
||||||
def priority_check?(check)
|
def priority_check?(check)
|
||||||
check == :access_control_post_has_secure_media && access_control_post
|
check == :access_control_post_has_secure_uploads && access_control_post
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_check(check)
|
def perform_check(check)
|
||||||
|
|
|
@ -57,7 +57,7 @@ class UrlHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.secure_proxy_without_cdn(url)
|
def self.secure_proxy_without_cdn(url)
|
||||||
self.absolute(Upload.secure_media_url_from_upload_url(url), nil)
|
self.absolute(Upload.secure_uploads_url_from_upload_url(url), nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.escape_uri(uri)
|
def self.escape_uri(uri)
|
||||||
|
@ -105,14 +105,14 @@ class UrlHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.cook_url(url, secure: false, local: nil)
|
def self.cook_url(url, secure: false, local: nil)
|
||||||
is_secure = SiteSetting.secure_media && secure
|
is_secure = SiteSetting.secure_uploads && secure
|
||||||
local = is_local(url) if local.nil?
|
local = is_local(url) if local.nil?
|
||||||
return url if !local
|
return url if !local
|
||||||
|
|
||||||
url = is_secure ? secure_proxy_without_cdn(url) : absolute_without_cdn(url)
|
url = is_secure ? secure_proxy_without_cdn(url) : absolute_without_cdn(url)
|
||||||
|
|
||||||
# we always want secure media to come from
|
# we always want secure uploads to come from
|
||||||
# Discourse.base_url_no_prefix/secure-media-uploads
|
# Discourse.base_url_no_prefix/secure-uploads
|
||||||
# to avoid asset_host mixups
|
# to avoid asset_host mixups
|
||||||
return schemaless(url) if is_secure
|
return schemaless(url) if is_secure
|
||||||
|
|
||||||
|
|
|
@ -222,14 +222,14 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
||||||
expect(post.raw).to eq(raw)
|
expect(post.raw).to eq(raw)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media enabled for an upload that has already been downloaded and exists" do
|
context "when secure uploads enabled for an upload that has already been downloaded and exists" do
|
||||||
it "doesnt redownload the secure upload" do
|
it "doesnt redownload the secure upload" do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
upload = Fabricate(:secure_upload_s3, secure: true)
|
upload = Fabricate(:secure_upload_s3, secure: true)
|
||||||
stub_s3(upload)
|
stub_s3(upload)
|
||||||
url = Upload.secure_media_url_from_upload_url(upload.url)
|
url = Upload.secure_uploads_url_from_upload_url(upload.url)
|
||||||
url = Discourse.base_url + url
|
url = Discourse.base_url + url
|
||||||
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
||||||
upload.update(access_control_post: post)
|
upload.update(access_control_post: post)
|
||||||
|
@ -240,12 +240,12 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
||||||
context "when the upload original_sha1 is missing" do
|
context "when the upload original_sha1 is missing" do
|
||||||
it "redownloads the upload" do
|
it "redownloads the upload" do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
upload = Fabricate(:upload_s3, secure: true)
|
upload = Fabricate(:upload_s3, secure: true)
|
||||||
stub_s3(upload)
|
stub_s3(upload)
|
||||||
Upload.stubs(:signed_url_from_secure_media_url).returns(upload.url)
|
Upload.stubs(:signed_url_from_secure_uploads_url).returns(upload.url)
|
||||||
url = Upload.secure_media_url_from_upload_url(upload.url)
|
url = Upload.secure_uploads_url_from_upload_url(upload.url)
|
||||||
url = Discourse.base_url + url
|
url = Discourse.base_url + url
|
||||||
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
||||||
upload.update(access_control_post: post)
|
upload.update(access_control_post: post)
|
||||||
|
@ -261,12 +261,12 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
||||||
context "when the upload access_control_post is different to the current post" do
|
context "when the upload access_control_post is different to the current post" do
|
||||||
it "redownloads the upload" do
|
it "redownloads the upload" do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
upload = Fabricate(:secure_upload_s3, secure: true)
|
upload = Fabricate(:secure_upload_s3, secure: true)
|
||||||
stub_s3(upload)
|
stub_s3(upload)
|
||||||
Upload.stubs(:signed_url_from_secure_media_url).returns(upload.url)
|
Upload.stubs(:signed_url_from_secure_uploads_url).returns(upload.url)
|
||||||
url = Upload.secure_media_url_from_upload_url(upload.url)
|
url = Upload.secure_uploads_url_from_upload_url(upload.url)
|
||||||
url = Discourse.base_url + url
|
url = Discourse.base_url + url
|
||||||
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
||||||
upload.update(access_control_post: Fabricate(:post))
|
upload.update(access_control_post: Fabricate(:post))
|
||||||
|
@ -466,14 +466,14 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
||||||
expect(subject.should_download_image?(Fabricate(:upload).url)).to eq(false)
|
expect(subject.should_download_image?(Fabricate(:upload).url)).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media enabled" do
|
context "when secure uploads enabled" do
|
||||||
it 'should return false for secure-media-upload url' do
|
it 'should return false for secure-upload url' do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
upload = Fabricate(:upload_s3, secure: true)
|
upload = Fabricate(:upload_s3, secure: true)
|
||||||
stub_s3(upload)
|
stub_s3(upload)
|
||||||
url = Upload.secure_media_url_from_upload_url(upload.url)
|
url = Upload.secure_uploads_url_from_upload_url(upload.url)
|
||||||
expect(subject.should_download_image?(url)).to eq(false)
|
expect(subject.should_download_image?(url)).to eq(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe Jobs::UpdatePostUploadsSecureStatus do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
stub_s3_store
|
stub_s3_store
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when login_required" do
|
context "when login_required" do
|
||||||
|
|
|
@ -485,7 +485,7 @@ RSpec.describe CookedPostProcessor do
|
||||||
stub_upload(upload)
|
stub_upload(upload)
|
||||||
|
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:optimized_size) { "600x500" }
|
let(:optimized_size) { "600x500" }
|
||||||
|
@ -496,7 +496,7 @@ RSpec.describe CookedPostProcessor do
|
||||||
|
|
||||||
let(:cooked_html) do
|
let(:cooked_html) do
|
||||||
<<~HTML
|
<<~HTML
|
||||||
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/secure-media-uploads/original/1X/#{upload.sha1}.png" data-download-href="//test.localhost/uploads/short-url/#{upload.base62_sha1}.unknown?dl=1" title="large.png"><img src="" alt="large.png" data-base62-sha1="#{upload.base62_sha1}" width="600" height="500"><div class="meta">
|
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/secure-uploads/original/1X/#{upload.sha1}.png" data-download-href="//test.localhost/uploads/short-url/#{upload.base62_sha1}.unknown?dl=1" title="large.png"><img src="" alt="large.png" data-base62-sha1="#{upload.base62_sha1}" width="600" height="500"><div class="meta">
|
||||||
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">large.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg>
|
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">large.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg>
|
||||||
</div></a></div></p>
|
</div></a></div></p>
|
||||||
HTML
|
HTML
|
||||||
|
@ -1074,13 +1074,13 @@ RSpec.describe CookedPostProcessor do
|
||||||
Oneboxer.unstub(:onebox)
|
Oneboxer.unstub(:onebox)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the post is with_secure_media and the upload is secure and secure media is enabled" do
|
context "when the post is with_secure_uploads and the upload is secure and secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
upload.update(secure: true)
|
upload.update(secure: true)
|
||||||
|
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not use the direct URL, uses the cooked URL instead (because of the private ACL preventing w/h fetch)" do
|
it "does not use the direct URL, uses the cooked URL instead (because of the private ACL preventing w/h fetch)" do
|
||||||
|
@ -1091,7 +1091,7 @@ RSpec.describe CookedPostProcessor do
|
||||||
|
|
||||||
PostHotlinkedMedia.create!(url: "//image.com/avatar.png", post: post, status: 'downloaded', upload: upload)
|
PostHotlinkedMedia.create!(url: "//image.com/avatar.png", post: post, status: 'downloaded', upload: upload)
|
||||||
|
|
||||||
cooked_url = "https://localhost/secure-media-uploads/test.png"
|
cooked_url = "https://localhost/secure-uploads/test.png"
|
||||||
UrlHelper.expects(:cook_url).with(upload.url, secure: true).returns(cooked_url)
|
UrlHelper.expects(:cook_url).with(upload.url, secure: true).returns(cooked_url)
|
||||||
|
|
||||||
cpp = CookedPostProcessor.new(post, invalidate_oneboxes: true)
|
cpp = CookedPostProcessor.new(post, invalidate_oneboxes: true)
|
||||||
|
@ -1417,8 +1417,8 @@ RSpec.describe CookedPostProcessor do
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't use CDN for secure media" do
|
it "doesn't use CDN for secure uploads" do
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
stored_path = Discourse.store.get_path_for_upload(upload)
|
stored_path = Discourse.store.get_path_for_upload(upload)
|
||||||
upload.update_column(:url, "#{SiteSetting.Upload.absolute_base_url}/#{stored_path}")
|
upload.update_column(:url, "#{SiteSetting.Upload.absolute_base_url}/#{stored_path}")
|
||||||
|
@ -1431,11 +1431,11 @@ RSpec.describe CookedPostProcessor do
|
||||||
|
|
||||||
expect(cpp.html).to match_html <<~HTML
|
expect(cpp.html).to match_html <<~HTML
|
||||||
<p>This post has a local emoji <img src="https://local.cdn.com/images/emoji/twitter/+1.png?v=#{Emoji::EMOJI_VERSION}" title=":+1:" class="emoji" alt=":+1:" loading="lazy" width="20" height="20"> and an external upload</p>
|
<p>This post has a local emoji <img src="https://local.cdn.com/images/emoji/twitter/+1.png?v=#{Emoji::EMOJI_VERSION}" title=":+1:" class="emoji" alt=":+1:" loading="lazy" width="20" height="20"> and an external upload</p>
|
||||||
<p><img src="/secure-media-uploads/#{stored_path}" alt="smallest.png" data-base62-sha1="#{upload.base62_sha1}" width="10" height="20"></p>
|
<p><img src="/secure-uploads/#{stored_path}" alt="smallest.png" data-base62-sha1="#{upload.base62_sha1}" width="10" height="20"></p>
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't use the secure media URL for custom emoji" do
|
it "doesn't use the secure uploads URL for custom emoji" do
|
||||||
CustomEmoji.create!(name: 'trout', upload: upload)
|
CustomEmoji.create!(name: 'trout', upload: upload)
|
||||||
Emoji.clear_cache
|
Emoji.clear_cache
|
||||||
Emoji.load_custom
|
Emoji.load_custom
|
||||||
|
@ -1484,9 +1484,9 @@ RSpec.describe CookedPostProcessor do
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
it "oneboxes video using secure url when secure_media is enabled" do
|
it "oneboxes video using secure url when secure_uploads is enabled" do
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
video_upload.update_column(:secure, true)
|
video_upload.update_column(:secure, true)
|
||||||
|
|
||||||
the_post = Fabricate(:post, raw: "This post has an S3 video onebox:\n#{video_upload.url}")
|
the_post = Fabricate(:post, raw: "This post has an S3 video onebox:\n#{video_upload.url}")
|
||||||
|
@ -1494,7 +1494,7 @@ RSpec.describe CookedPostProcessor do
|
||||||
cpp = CookedPostProcessor.new(the_post)
|
cpp = CookedPostProcessor.new(the_post)
|
||||||
cpp.post_process_oneboxes
|
cpp.post_process_oneboxes
|
||||||
|
|
||||||
secure_url = video_upload.url.sub(SiteSetting.s3_cdn_url, "#{Discourse.base_url}/secure-media-uploads")
|
secure_url = video_upload.url.sub(SiteSetting.s3_cdn_url, "#{Discourse.base_url}/secure-uploads")
|
||||||
|
|
||||||
expect(cpp.html).to match_html <<~HTML
|
expect(cpp.html).to match_html <<~HTML
|
||||||
<p>This post has an S3 video onebox:</p><div class="onebox video-onebox">
|
<p>This post has an S3 video onebox:</p><div class="onebox video-onebox">
|
||||||
|
@ -1506,9 +1506,9 @@ RSpec.describe CookedPostProcessor do
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
it "oneboxes only audio/video and not images when secure_media is enabled" do
|
it "oneboxes only audio/video and not images when secure_uploads is enabled" do
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
video_upload.update_column(:secure, true)
|
video_upload.update_column(:secure, true)
|
||||||
|
|
||||||
|
@ -1541,8 +1541,8 @@ RSpec.describe CookedPostProcessor do
|
||||||
cpp = CookedPostProcessor.new(the_post)
|
cpp = CookedPostProcessor.new(the_post)
|
||||||
cpp.post_process_oneboxes
|
cpp.post_process_oneboxes
|
||||||
|
|
||||||
secure_video_url = video_upload.url.sub(SiteSetting.s3_cdn_url, "#{Discourse.base_url}/secure-media-uploads")
|
secure_video_url = video_upload.url.sub(SiteSetting.s3_cdn_url, "#{Discourse.base_url}/secure-uploads")
|
||||||
secure_audio_url = audio_upload.url.sub(SiteSetting.s3_cdn_url, "#{Discourse.base_url}/secure-media-uploads")
|
secure_audio_url = audio_upload.url.sub(SiteSetting.s3_cdn_url, "#{Discourse.base_url}/secure-uploads")
|
||||||
|
|
||||||
expect(cpp.html).to match_html <<~HTML
|
expect(cpp.html).to match_html <<~HTML
|
||||||
<p>This post has a video upload.</p>
|
<p>This post has a video upload.</p>
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'email/sender'
|
||||||
|
|
||||||
RSpec.describe Email::Sender do
|
RSpec.describe Email::Sender do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media_allow_embed_images_in_emails = false
|
SiteSetting.secure_uploads_allow_embed_images_in_emails = false
|
||||||
end
|
end
|
||||||
fab!(:post) { Fabricate(:post) }
|
fab!(:post) { Fabricate(:post) }
|
||||||
let(:mock_smtp_transaction_response) { "250 Ok: queued as 2l3Md07BObzB8kRyHZeoN0baSUAhzc7A-NviRioOr80=@mailhog.example" }
|
let(:mock_smtp_transaction_response) { "250 Ok: queued as 2l3Md07BObzB8kRyHZeoN0baSUAhzc7A-NviRioOr80=@mailhog.example" }
|
||||||
|
@ -535,15 +535,15 @@ RSpec.describe Email::Sender do
|
||||||
.to contain_exactly(*[small_pdf, large_pdf, csv_file].map(&:original_filename))
|
.to contain_exactly(*[small_pdf, large_pdf, csv_file].map(&:original_filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media enabled" do
|
context "when secure uploads enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
store = stub_s3_store
|
store = stub_s3_store
|
||||||
|
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.email_total_attachment_size_limit_kb = 14_000
|
SiteSetting.email_total_attachment_size_limit_kb = 14_000
|
||||||
SiteSetting.secure_media_max_email_embed_image_size_kb = 5_000
|
SiteSetting.secure_uploads_max_email_embed_image_size_kb = 5_000
|
||||||
|
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
Jobs::PullHotlinkedImages.any_instance.expects(:execute)
|
Jobs::PullHotlinkedImages.any_instance.expects(:execute)
|
||||||
|
@ -566,7 +566,7 @@ RSpec.describe Email::Sender do
|
||||||
|
|
||||||
context "when embedding secure images in email is allowed" do
|
context "when embedding secure images in email is allowed" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media_allow_embed_images_in_emails = true
|
SiteSetting.secure_uploads_allow_embed_images_in_emails = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can inline images with duplicate names" do
|
it "can inline images with duplicate names" do
|
||||||
|
@ -590,7 +590,7 @@ RSpec.describe Email::Sender do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not embed images that are too big" do
|
it "does not embed images that are too big" do
|
||||||
SiteSetting.secure_media_max_email_embed_image_size_kb = 1
|
SiteSetting.secure_uploads_max_email_embed_image_size_kb = 1
|
||||||
Email::Sender.new(message, :valid_type).send
|
Email::Sender.new(message, :valid_type).send
|
||||||
expect(message.attachments.length).to eq(3)
|
expect(message.attachments.length).to eq(3)
|
||||||
end
|
end
|
||||||
|
|
|
@ -208,32 +208,32 @@ RSpec.describe Email::Styles do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "replace_secure_media_urls" do
|
describe "replace_secure_uploads_urls" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:attachments) { { 'testimage.png' => stub(url: 'email/test.png') } }
|
let(:attachments) { { 'testimage.png' => stub(url: 'email/test.png') } }
|
||||||
it "replaces secure media within a link with a placeholder" do
|
it "replaces secure uploads within a link with a placeholder" do
|
||||||
frag = html_fragment("<a href=\"#{Discourse.base_url}\/secure-media-uploads/original/1X/testimage.png\"><img src=\"/secure-media-uploads/original/1X/testimage.png\"></a>")
|
frag = html_fragment("<a href=\"#{Discourse.base_url}\/secure-uploads/original/1X/testimage.png\"><img src=\"/secure-uploads/original/1X/testimage.png\"></a>")
|
||||||
expect(frag.at('img')).not_to be_present
|
expect(frag.at('img')).not_to be_present
|
||||||
expect(frag.to_s).to include("Redacted")
|
expect(frag.to_s).to include("Redacted")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "replaces secure images with a placeholder" do
|
it "replaces secure images with a placeholder" do
|
||||||
frag = html_fragment("<img src=\"/secure-media-uploads/original/1X/testimage.png\">")
|
frag = html_fragment("<img src=\"/secure-uploads/original/1X/testimage.png\">")
|
||||||
expect(frag.at('img')).not_to be_present
|
expect(frag.at('img')).not_to be_present
|
||||||
expect(frag.to_s).to include("Redacted")
|
expect(frag.to_s).to include("Redacted")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not replace topic links with secure-media-uploads in the name" do
|
it "does not replace topic links with secure-uploads in the name" do
|
||||||
frag = html_fragment("<a href=\"#{Discourse.base_url}\/t/secure-media-uploads/235723\">Visit Topic</a>")
|
frag = html_fragment("<a href=\"#{Discourse.base_url}\/t/secure-uploads/235723\">Visit Topic</a>")
|
||||||
expect(frag.to_s).not_to include("Redacted")
|
expect(frag.to_s).not_to include("Redacted")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "works in lightboxes with missing srcset attribute" do
|
it "works in lightboxes with missing srcset attribute" do
|
||||||
frag = html_fragment("<a href=\"#{Discourse.base_url}\/secure-media-uploads/original/1X/testimage.png\" class=\"lightbox\"><img src=\"/secure-media-uploads/original/1X/testimage.png\"></a>")
|
frag = html_fragment("<a href=\"#{Discourse.base_url}\/secure-uploads/original/1X/testimage.png\" class=\"lightbox\"><img src=\"/secure-uploads/original/1X/testimage.png\"></a>")
|
||||||
expect(frag.at('img')).not_to be_present
|
expect(frag.at('img')).not_to be_present
|
||||||
expect(frag.to_s).to include("Redacted")
|
expect(frag.to_s).to include("Redacted")
|
||||||
end
|
end
|
||||||
|
@ -241,8 +241,8 @@ RSpec.describe Email::Styles do
|
||||||
it "works in lightboxes with srcset attribute set" do
|
it "works in lightboxes with srcset attribute set" do
|
||||||
frag = html_fragment(
|
frag = html_fragment(
|
||||||
<<~HTML
|
<<~HTML
|
||||||
<a href="#{Discourse.base_url}/secure-media-uploads/original/1X/testimage.png" class="lightbox">
|
<a href="#{Discourse.base_url}/secure-uploads/original/1X/testimage.png" class="lightbox">
|
||||||
<img src="/secure-media-uploads/original/1X/testimage.png" srcset="/secure-media-uploads/optimized/1X/testimage.png, /secure-media-uploads/original/1X/testimage.png 1.5x" />
|
<img src="/secure-uploads/original/1X/testimage.png" srcset="/secure-uploads/optimized/1X/testimage.png, /secure-uploads/original/1X/testimage.png 1.5x" />
|
||||||
</a>
|
</a>
|
||||||
HTML
|
HTML
|
||||||
)
|
)
|
||||||
|
@ -252,7 +252,7 @@ RSpec.describe Email::Styles do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "skips links with no images as children" do
|
it "skips links with no images as children" do
|
||||||
frag = html_fragment("<a href=\"#{Discourse.base_url}\/secure-media-uploads/original/1X/testimage.png\"><span>Clearly not an image</span></a>")
|
frag = html_fragment("<a href=\"#{Discourse.base_url}\/secure-uploads/original/1X/testimage.png\"><span>Clearly not an image</span></a>")
|
||||||
expect(frag.to_s).to include("not an image")
|
expect(frag.to_s).to include("not an image")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -261,16 +261,16 @@ RSpec.describe Email::Styles do
|
||||||
describe "inline_secure_images" do
|
describe "inline_secure_images" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
fab!(:upload) { Fabricate(:upload, original_filename: 'testimage.png', secure: true, sha1: '123456') }
|
fab!(:upload) { Fabricate(:upload, original_filename: 'testimage.png', secure: true, sha1: '123456') }
|
||||||
let(:attachments) { [stub(url: 'cid:email/test.png')] }
|
let(:attachments) { [stub(url: 'cid:email/test.png')] }
|
||||||
let(:attachments_index) { { upload.sha1 => 0 } }
|
let(:attachments_index) { { upload.sha1 => 0 } }
|
||||||
let(:html) { "<a href=\"#{Discourse.base_url}\/secure-media-uploads/original/1X/123456.png\"><img src=\"/secure-media-uploads/original/1X/123456.png\" width=\"20\" height=\"30\"></a>" }
|
let(:html) { "<a href=\"#{Discourse.base_url}\/secure-uploads/original/1X/123456.png\"><img src=\"/secure-uploads/original/1X/123456.png\" width=\"20\" height=\"30\"></a>" }
|
||||||
|
|
||||||
def strip_and_inline
|
def strip_and_inline
|
||||||
# strip out the secure media
|
# strip out the secure uploads
|
||||||
styler = Email::Styles.new(html)
|
styler = Email::Styles.new(html)
|
||||||
styler.format_basic
|
styler.format_basic
|
||||||
styler.format_html
|
styler.format_html
|
||||||
|
@ -285,7 +285,7 @@ RSpec.describe Email::Styles do
|
||||||
it "inlines attachments where stripped-secure-media data attr is present" do
|
it "inlines attachments where stripped-secure-media data attr is present" do
|
||||||
strip_and_inline
|
strip_and_inline
|
||||||
expect(@frag.to_s).to include("cid:email/test.png")
|
expect(@frag.to_s).to include("cid:email/test.png")
|
||||||
expect(@frag.css('[data-stripped-secure-media]')).not_to be_present
|
expect(@frag.css('[data-stripped-secure-upload]')).not_to be_present
|
||||||
expect(@frag.children.attr('style').value).to eq("width: 20px; height: 30px;")
|
expect(@frag.children.attr('style').value).to eq("width: 20px; height: 30px;")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -294,17 +294,17 @@ RSpec.describe Email::Styles do
|
||||||
strip_and_inline
|
strip_and_inline
|
||||||
|
|
||||||
expect(@frag.to_s).not_to include("cid:email/test.png")
|
expect(@frag.to_s).not_to include("cid:email/test.png")
|
||||||
expect(@frag.css('[data-stripped-secure-media]')).to be_present
|
expect(@frag.css('[data-stripped-secure-upload]')).to be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when an optimized image is used instead of the original" do
|
context "when an optimized image is used instead of the original" do
|
||||||
let(:html) { "<a href=\"#{Discourse.base_url}\/secure-media-uploads/optimized/2X/1/123456_2_20x30.png\"><img src=\"/secure-media-uploads/optimized/2X/1/123456_2_20x30.png\" width=\"20\" height=\"30\"></a>" }
|
let(:html) { "<a href=\"#{Discourse.base_url}\/secure-uploads/optimized/2X/1/123456_2_20x30.png\"><img src=\"/secure-uploads/optimized/2X/1/123456_2_20x30.png\" width=\"20\" height=\"30\"></a>" }
|
||||||
|
|
||||||
it "inlines attachments where the stripped-secure-media data attr is present" do
|
it "inlines attachments where the stripped-secure-media data attr is present" do
|
||||||
optimized = Fabricate(:optimized_image, upload: upload, width: 20, height: 30)
|
optimized = Fabricate(:optimized_image, upload: upload, width: 20, height: 30)
|
||||||
strip_and_inline
|
strip_and_inline
|
||||||
expect(@frag.to_s).to include("cid:email/test.png")
|
expect(@frag.to_s).to include("cid:email/test.png")
|
||||||
expect(@frag.css('[data-stripped-secure-media]')).not_to be_present
|
expect(@frag.css('[data-stripped-secure-upload]')).not_to be_present
|
||||||
expect(@frag.children.attr('style').value).to eq("width: 20px; height: 30px;")
|
expect(@frag.children.attr('style').value).to eq("width: 20px; height: 30px;")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -321,11 +321,11 @@ RSpec.describe Email::Styles do
|
||||||
<<~HTML
|
<<~HTML
|
||||||
<aside class="onebox allowlistedgeneric">
|
<aside class="onebox allowlistedgeneric">
|
||||||
<header class="source">
|
<header class="source">
|
||||||
<img src="#{Discourse.base_url}/secure-media-uploads/original/1X/#{siteicon.sha1}.ico" class="site-icon" width="64" height="64">
|
<img src="#{Discourse.base_url}/secure-uploads/original/1X/#{siteicon.sha1}.ico" class="site-icon" width="64" height="64">
|
||||||
<a href="https://test.com/article" target="_blank" rel="noopener" title="02:33PM - 24 October 2020">Test</a>
|
<a href="https://test.com/article" target="_blank" rel="noopener" title="02:33PM - 24 October 2020">Test</a>
|
||||||
</header>
|
</header>
|
||||||
<article class="onebox-body">
|
<article class="onebox-body">
|
||||||
<div class="aspect-image" style="--aspect-ratio:20/30;"><img src="#{Discourse.base_url}/secure-media-uploads/optimized/2X/1/123456_2_20x30.png" class="thumbnail d-lazyload" width="20" height="30" srcset="#{Discourse.base_url}/secure-media-uploads/optimized/2X/1/123456_2_20x30.png"></div>
|
<div class="aspect-image" style="--aspect-ratio:20/30;"><img src="#{Discourse.base_url}/secure-uploads/optimized/2X/1/123456_2_20x30.png" class="thumbnail d-lazyload" width="20" height="30" srcset="#{Discourse.base_url}/secure-uploads/optimized/2X/1/123456_2_20x30.png"></div>
|
||||||
|
|
||||||
<h3><a href="https://test.com/article" target="_blank" rel="noopener">Test</a></h3>
|
<h3><a href="https://test.com/article" target="_blank" rel="noopener">Test</a></h3>
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ RSpec.describe Email::Styles do
|
||||||
strip_and_inline
|
strip_and_inline
|
||||||
expect(@frag.to_s).to include("cid:email/test.png")
|
expect(@frag.to_s).to include("cid:email/test.png")
|
||||||
expect(@frag.to_s).to include("cid:email/test2.ico")
|
expect(@frag.to_s).to include("cid:email/test2.ico")
|
||||||
expect(@frag.css('[data-stripped-secure-media]')).not_to be_present
|
expect(@frag.css('[data-stripped-secure-upload]')).not_to be_present
|
||||||
expect(@frag.css('[data-embedded-secure-image]')[0].attr('style')).to eq('width: 16px; height: 16px;')
|
expect(@frag.css('[data-embedded-secure-image]')[0].attr('style')).to eq('width: 16px; height: 16px;')
|
||||||
expect(@frag.css('[data-embedded-secure-image]')[1].attr('style')).to eq('width: 60px; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;')
|
expect(@frag.css('[data-embedded-secure-image]')[1].attr('style')).to eq('width: 60px; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;')
|
||||||
end
|
end
|
||||||
|
@ -354,11 +354,11 @@ RSpec.describe Email::Styles do
|
||||||
<<~HTML
|
<<~HTML
|
||||||
<aside class="onebox allowlistedgeneric">
|
<aside class="onebox allowlistedgeneric">
|
||||||
<header class="source">
|
<header class="source">
|
||||||
<img src="#{Discourse.base_url}/secure-media-uploads/original/1X/#{siteicon.sha1}.ico" class="site-icon" width="64" height="64">
|
<img src="#{Discourse.base_url}/secure-uploads/original/1X/#{siteicon.sha1}.ico" class="site-icon" width="64" height="64">
|
||||||
<a href="https://test.com/article" target="_blank" rel="noopener" title="02:33PM - 24 October 2020">Test</a>
|
<a href="https://test.com/article" target="_blank" rel="noopener" title="02:33PM - 24 October 2020">Test</a>
|
||||||
</header>
|
</header>
|
||||||
<article class="onebox-body">
|
<article class="onebox-body">
|
||||||
<img src="#{Discourse.base_url}/secure-media-uploads/original/1X/123456.png" class="thumbnail onebox-avatar" width="20" height="30">
|
<img src="#{Discourse.base_url}/secure-uploads/original/1X/123456.png" class="thumbnail onebox-avatar" width="20" height="30">
|
||||||
|
|
||||||
<h3><a href="https://test.com/article" target="_blank" rel="noopener">Test</a></h3>
|
<h3><a href="https://test.com/article" target="_blank" rel="noopener">Test</a></h3>
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ RSpec.describe Email::Styles do
|
||||||
strip_and_inline
|
strip_and_inline
|
||||||
expect(@frag.to_s).to include("cid:email/test.png")
|
expect(@frag.to_s).to include("cid:email/test.png")
|
||||||
expect(@frag.to_s).to include("cid:email/test2.ico")
|
expect(@frag.to_s).to include("cid:email/test2.ico")
|
||||||
expect(@frag.css('[data-stripped-secure-media]')).not_to be_present
|
expect(@frag.css('[data-stripped-secure-upload]')).not_to be_present
|
||||||
expect(@frag.css('[data-embedded-secure-image]')[1].attr('style')).to eq('width: 60px; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;')
|
expect(@frag.css('[data-embedded-secure-image]')[1].attr('style')).to eq('width: 60px; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -405,7 +405,7 @@ RSpec.describe Email::Styles do
|
||||||
</div>
|
</div>
|
||||||
<div class="user">
|
<div class="user">
|
||||||
<a href="https://github.com/udan11" target="_blank" rel="noopener">
|
<a href="https://github.com/udan11" target="_blank" rel="noopener">
|
||||||
<img alt="udan11" src="#{Discourse.base_url}/secure-media-uploads/original/1X/123456.png" class="onebox-avatar-inline" width="20" height="20">
|
<img alt="udan11" src="#{Discourse.base_url}/secure-uploads/original/1X/123456.png" class="onebox-avatar-inline" width="20" height="20">
|
||||||
udan11
|
udan11
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -428,7 +428,7 @@ RSpec.describe Email::Styles do
|
||||||
it "keeps the special onebox styles" do
|
it "keeps the special onebox styles" do
|
||||||
strip_and_inline
|
strip_and_inline
|
||||||
expect(@frag.to_s).to include("cid:email/test.png")
|
expect(@frag.to_s).to include("cid:email/test.png")
|
||||||
expect(@frag.css('[data-stripped-secure-media]')).not_to be_present
|
expect(@frag.css('[data-stripped-secure-upload]')).not_to be_present
|
||||||
expect(@frag.css('[data-embedded-secure-image]')[0].attr('style')).to eq('width: 20px; height: 20px; float: none; vertical-align: middle; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;')
|
expect(@frag.css('[data-embedded-secure-image]')[0].attr('style')).to eq('width: 20px; height: 20px; float: none; vertical-align: middle; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -173,9 +173,9 @@ RSpec.describe FileStore::BaseStore do
|
||||||
expect(file.class).to eq(File)
|
expect(file.class).to eq(File)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return the file when secure media are enabled" do
|
it "should return the file when secure uploads are enabled" do
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
stub_request(:head, "https://s3-upload-bucket.s3.#{SiteSetting.s3_region}.amazonaws.com/")
|
stub_request(:head, "https://s3-upload-bucket.s3.#{SiteSetting.s3_region}.amazonaws.com/")
|
||||||
signed_url = Discourse.store.signed_url_for_path(upload_s3.url)
|
signed_url = Discourse.store.signed_url_for_path(upload_s3.url)
|
||||||
|
|
|
@ -3864,10 +3864,10 @@ RSpec.describe Guardian do
|
||||||
expect(Guardian.new(admin).can_publish_page?(post.topic)).to eq(false)
|
expect(Guardian.new(admin).can_publish_page?(post.topic)).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure_media is also enabled" do
|
context "when secure_uploads is also enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is false for everyone" do
|
it "is false for everyone" do
|
||||||
|
|
|
@ -1839,7 +1839,7 @@ RSpec.describe PostCreator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "secure media uploads" do
|
describe "secure uploads uploads" do
|
||||||
fab!(:image_upload) { Fabricate(:upload, secure: true) }
|
fab!(:image_upload) { Fabricate(:upload, secure: true) }
|
||||||
fab!(:user2) { Fabricate(:user) }
|
fab!(:user2) { Fabricate(:user) }
|
||||||
fab!(:public_topic) { Fabricate(:topic) }
|
fab!(:public_topic) { Fabricate(:topic) }
|
||||||
|
@ -1847,7 +1847,7 @@ RSpec.describe PostCreator do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "png|jpg|gif|mp4"
|
SiteSetting.authorized_extensions = "png|jpg|gif|mp4"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
stub_upload(image_upload)
|
stub_upload(image_upload)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1242,13 +1242,13 @@ RSpec.describe PostRevisor do
|
||||||
expect(post.reload.upload_references.pluck(:upload_id)).to contain_exactly(image2.id, image3.id, image4.id)
|
expect(post.reload.upload_references.pluck(:upload_id)).to contain_exactly(image2.id, image3.id, image4.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with secure media uploads" do
|
context "with secure uploads uploads" do
|
||||||
let!(:image5) { Fabricate(:secure_upload) }
|
let!(:image5) { Fabricate(:secure_upload) }
|
||||||
before do
|
before do
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "png|jpg|gif|mp4"
|
SiteSetting.authorized_extensions = "png|jpg|gif|mp4"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
stub_upload(image5)
|
stub_upload(image5)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1125,19 +1125,19 @@ RSpec.describe PrettyText do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#strip_secure_media" do
|
describe "#strip_secure_uploads" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.s3_cdn_url = "https://s3.cdn.com"
|
SiteSetting.s3_cdn_url = "https://s3.cdn.com"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "replaces secure video content" do
|
it "replaces secure video content" do
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<video width="100%" height="100%" controls="">
|
<video width="100%" height="100%" controls="">
|
||||||
<source src="#{base_url}/secure-media-uploads/original/1X/some-video.mp4">
|
<source src="#{base_url}/secure-uploads/original/1X/some-video.mp4">
|
||||||
<a href="#{base_url}/secure-media-uploads/original/1X/some-video.mp4">Video label</a>
|
<a href="#{base_url}/secure-uploads/original/1X/some-video.mp4">Video label</a>
|
||||||
</source>
|
</source>
|
||||||
</video>
|
</video>
|
||||||
HTML
|
HTML
|
||||||
|
@ -1145,58 +1145,58 @@ RSpec.describe PrettyText do
|
||||||
md = PrettyText.format_for_email(html, post)
|
md = PrettyText.format_for_email(html, post)
|
||||||
|
|
||||||
expect(md).not_to include('<video')
|
expect(md).not_to include('<video')
|
||||||
expect(md.to_s).to match(I18n.t("emails.secure_media_placeholder"))
|
expect(md.to_s).to match(I18n.t("emails.secure_uploads_placeholder"))
|
||||||
expect(md.to_s).not_to match(SiteSetting.Upload.s3_cdn_url)
|
expect(md.to_s).not_to match(SiteSetting.Upload.s3_cdn_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "replaces secure audio content" do
|
it "replaces secure audio content" do
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<audio controls>
|
<audio controls>
|
||||||
<source src="#{base_url}/secure-media-uploads/original/1X/some-audio.mp3">
|
<source src="#{base_url}/secure-uploads/original/1X/some-audio.mp3">
|
||||||
<a href="#{base_url}/secure-media-uploads/original/1X/some-audio.mp3">Audio label</a>
|
<a href="#{base_url}/secure-uploads/original/1X/some-audio.mp3">Audio label</a>
|
||||||
</source>
|
</source>
|
||||||
</audio>
|
</audio>
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
md = PrettyText.format_for_email(html, post)
|
md = PrettyText.format_for_email(html, post)
|
||||||
|
|
||||||
expect(md).not_to include('<video')
|
expect(md).not_to include('<audio')
|
||||||
expect(md.to_s).to match(I18n.t("emails.secure_media_placeholder"))
|
expect(md.to_s).to match(I18n.t("emails.secure_uploads_placeholder"))
|
||||||
expect(md.to_s).not_to match(SiteSetting.Upload.s3_cdn_url)
|
expect(md.to_s).not_to match(SiteSetting.Upload.s3_cdn_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "replaces secure media within a link with a placeholder, keeping the url in an attribute" do
|
it "replaces secure uploads within a link with a placeholder, keeping the url in an attribute" do
|
||||||
url = "#{Discourse.base_url}\/secure-media-uploads/original/1X/testimage.png"
|
url = "#{Discourse.base_url}\/secure-uploads/original/1X/testimage.png"
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<a href=\"#{url}\"><img src=\"/secure-media-uploads/original/1X/testimage.png\"></a>
|
<a href=\"#{url}\"><img src=\"/secure-uploads/original/1X/testimage.png\"></a>
|
||||||
HTML
|
HTML
|
||||||
md = PrettyText.format_for_email(html, post)
|
md = PrettyText.format_for_email(html, post)
|
||||||
expect(md).not_to include('<img')
|
expect(md).not_to include('<img')
|
||||||
expect(md).to include("Redacted")
|
expect(md).to include("Redacted")
|
||||||
expect(md).to include("data-stripped-secure-media=\"#{url}\"")
|
expect(md).to include("data-stripped-secure-upload=\"#{url}\"")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not create nested redactions from double processing because of the view media link" do
|
it "does not create nested redactions from double processing because of the view media link" do
|
||||||
url = "#{Discourse.base_url}\/secure-media-uploads/original/1X/testimage.png"
|
url = "#{Discourse.base_url}\/secure-uploads/original/1X/testimage.png"
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<a href=\"#{url}\"><img src=\"/secure-media-uploads/original/1X/testimage.png\"></a>
|
<a href=\"#{url}\"><img src=\"/secure-uploads/original/1X/testimage.png\"></a>
|
||||||
HTML
|
HTML
|
||||||
md = PrettyText.format_for_email(html, post)
|
md = PrettyText.format_for_email(html, post)
|
||||||
md = PrettyText.format_for_email(md, post)
|
md = PrettyText.format_for_email(md, post)
|
||||||
|
|
||||||
expect(md.scan(/stripped-secure-view-media/).length).to eq(1)
|
expect(md.scan(/stripped-secure-view-upload/).length).to eq(1)
|
||||||
expect(md.scan(/Redacted/).length).to eq(1)
|
expect(md.scan(/Redacted/).length).to eq(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "replaces secure images with a placeholder, keeping the url in an attribute" do
|
it "replaces secure images with a placeholder, keeping the url in an attribute" do
|
||||||
url = "/secure-media-uploads/original/1X/testimage.png"
|
url = "/secure-uploads/original/1X/testimage.png"
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<img src=\"#{url}\" width=\"20\" height=\"20\">
|
<img src=\"#{url}\" width=\"20\" height=\"20\">
|
||||||
HTML
|
HTML
|
||||||
md = PrettyText.format_for_email(html, post)
|
md = PrettyText.format_for_email(html, post)
|
||||||
expect(md).not_to include('<img')
|
expect(md).not_to include('<img')
|
||||||
expect(md).to include("Redacted")
|
expect(md).to include("Redacted")
|
||||||
expect(md).to include("data-stripped-secure-media=\"#{url}\"")
|
expect(md).to include("data-stripped-secure-upload=\"#{url}\"")
|
||||||
expect(md).to include("data-width=\"20\"")
|
expect(md).to include("data-width=\"20\"")
|
||||||
expect(md).to include("data-height=\"20\"")
|
expect(md).to include("data-height=\"20\"")
|
||||||
end
|
end
|
||||||
|
|
|
@ -210,10 +210,10 @@ RSpec.describe SiteSettings::Validations do
|
||||||
expect { subject.validate_enable_page_publishing("t") }.not_to raise_error
|
expect { subject.validate_enable_page_publishing("t") }.not_to raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
context "if secure media is enabled" do
|
context "if secure uploads is enabled" do
|
||||||
let(:error_message) { I18n.t("errors.site_settings.page_publishing_requirements") }
|
let(:error_message) { I18n.t("errors.site_settings.page_publishing_requirements") }
|
||||||
before do
|
before do
|
||||||
enable_secure_media
|
enable_secure_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is not ok" do
|
it "is not ok" do
|
||||||
|
@ -223,8 +223,8 @@ RSpec.describe SiteSettings::Validations do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#validate_secure_media" do
|
describe "#validate_secure_uploads" do
|
||||||
let(:error_message) { I18n.t("errors.site_settings.secure_media_requirements") }
|
let(:error_message) { I18n.t("errors.site_settings.secure_uploads_requirements") }
|
||||||
|
|
||||||
context "when the new value is true" do
|
context "when the new value is true" do
|
||||||
context 'if site setting for enable_s3_uploads is enabled' do
|
context 'if site setting for enable_s3_uploads is enabled' do
|
||||||
|
@ -233,7 +233,7 @@ RSpec.describe SiteSettings::Validations do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be ok" do
|
it "should be ok" do
|
||||||
expect { subject.validate_secure_media("t") }.not_to raise_error
|
expect { subject.validate_secure_uploads("t") }.not_to raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ RSpec.describe SiteSettings::Validations do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is not ok" do
|
it "is not ok" do
|
||||||
expect { subject.validate_secure_media("t") }.to raise_error(Discourse::InvalidParameters, error_message)
|
expect { subject.validate_secure_uploads("t") }.to raise_error(Discourse::InvalidParameters, error_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "if global s3 setting is enabled" do
|
context "if global s3 setting is enabled" do
|
||||||
|
@ -252,7 +252,7 @@ RSpec.describe SiteSettings::Validations do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be ok" do
|
it "should be ok" do
|
||||||
expect { subject.validate_secure_media("t") }.not_to raise_error
|
expect { subject.validate_secure_uploads("t") }.not_to raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,10 +27,10 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
context "when the topic category is read restricted" do
|
context "when the topic category is read restricted" do
|
||||||
let(:category) { Fabricate(:private_category, group: group) }
|
let(:category) { Fabricate(:private_category, group: group) }
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
||||||
end
|
end
|
||||||
|
@ -49,7 +49,7 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is disabled" do
|
context "when secure uploads is disabled" do
|
||||||
it "changes the upload secure statuses to false and updates ACLs and rebakes" do
|
it "changes the upload secure statuses to false and updates ACLs and rebakes" do
|
||||||
expect_upload_status_to_change_and_rebake
|
expect_upload_status_to_change_and_rebake
|
||||||
end
|
end
|
||||||
|
@ -59,10 +59,10 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
context "when the topic is a private message" do
|
context "when the topic is a private message" do
|
||||||
let(:topic) { Fabricate(:private_message_topic, category: category, user: user) }
|
let(:topic) { Fabricate(:private_message_topic, category: category, user: user) }
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
||||||
end
|
end
|
||||||
|
@ -81,7 +81,7 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is disabled" do
|
context "when secure uploads is disabled" do
|
||||||
it "changes the upload secure statuses to false and updates ACLs and rebakes" do
|
it "changes the upload secure statuses to false and updates ACLs and rebakes" do
|
||||||
expect_upload_status_to_change_and_rebake
|
expect_upload_status_to_change_and_rebake
|
||||||
end
|
end
|
||||||
|
@ -89,10 +89,10 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the topic is public" do
|
context "when the topic is public" do
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
||||||
end
|
end
|
||||||
|
@ -125,7 +125,7 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
[upload, upload2, upload3].each { |upl| stub_upload(upl) }
|
||||||
end
|
end
|
||||||
|
@ -142,9 +142,9 @@ RSpec.describe TopicUploadSecurityManager do
|
||||||
expect(upload3.reload.access_control_post).to eq(post4)
|
expect(upload3.reload.access_control_post).to eq(post4)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is not enabled" do
|
context "when secure uploads is not enabled" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media = false
|
SiteSetting.secure_uploads = false
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not change the upload secure status and does not set the access control post" do
|
it "does not change the upload secure status and does not set the access control post" do
|
||||||
|
|
|
@ -305,7 +305,7 @@ RSpec.describe UploadCreator do
|
||||||
setup_s3
|
setup_s3
|
||||||
stub_s3_store
|
stub_s3_store
|
||||||
|
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
SiteSetting.authorized_extensions = 'pdf|svg|jpg'
|
SiteSetting.authorized_extensions = 'pdf|svg|jpg'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ RSpec.describe UploadCreator do
|
||||||
|
|
||||||
it 'should return signed URL for secure attachments in S3' do
|
it 'should return signed URL for secure attachments in S3' do
|
||||||
SiteSetting.authorized_extensions = 'pdf'
|
SiteSetting.authorized_extensions = 'pdf'
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
upload = UploadCreator.new(pdf_file, pdf_filename, opts).create_for(user.id)
|
upload = UploadCreator.new(pdf_file, pdf_filename, opts).create_for(user.id)
|
||||||
stored_upload = Upload.last
|
stored_upload = Upload.last
|
||||||
|
@ -399,12 +399,12 @@ RSpec.describe UploadCreator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when SiteSetting.secure_media is enabled" do
|
context "when SiteSetting.secure_uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
stub_s3_store
|
stub_s3_store
|
||||||
|
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not return the existing upload, as duplicate uploads are allowed" do
|
it "does not return the existing upload, as duplicate uploads are allowed" do
|
||||||
|
@ -413,18 +413,18 @@ RSpec.describe UploadCreator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with secure media functionality" do
|
context "with secure uploads functionality" do
|
||||||
let(:filename) { "logo.jpg" }
|
let(:filename) { "logo.jpg" }
|
||||||
let(:file) { file_from_fixtures(filename) }
|
let(:file) { file_from_fixtures(filename) }
|
||||||
let(:opts) { {} }
|
let(:opts) { {} }
|
||||||
let(:result) { UploadCreator.new(file, filename, opts).create_for(user.id) }
|
let(:result) { UploadCreator.new(file, filename, opts).create_for(user.id) }
|
||||||
|
|
||||||
context "when SiteSetting.secure_media enabled" do
|
context "when SiteSetting.secure_uploads enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
stub_s3_store
|
stub_s3_store
|
||||||
|
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets an original_sha1 on the upload created because the sha1 column is securerandom in this case" do
|
it "sets an original_sha1 on the upload created because the sha1 column is securerandom in this case" do
|
||||||
|
|
|
@ -161,7 +161,7 @@ RSpec.describe UploadRecovery do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not create a duplicate upload when secure uploads are enabled' do
|
it 'does not create a duplicate upload when secure uploads are enabled' do
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
upload.verification_status = Upload.verification_statuses[:invalid_etag]
|
upload.verification_status = Upload.verification_statuses[:invalid_etag]
|
||||||
upload.save!
|
upload.save!
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ RSpec.describe UploadSecurity do
|
||||||
let(:opts) { { type: type, creating: true } }
|
let(:opts) { { type: type, creating: true } }
|
||||||
subject { described_class.new(upload, opts) }
|
subject { described_class.new(upload, opts) }
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when login_required (everything should be secure except public context items)" do
|
context "when login_required (everything should be secure except public context items)" do
|
||||||
|
@ -126,7 +126,7 @@ RSpec.describe UploadSecurity do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the access control post has_secure_media?" do
|
context "when the access control post has_secure_uploads?" do
|
||||||
before do
|
before do
|
||||||
upload.update(access_control_post_id: post_in_secure_context.id)
|
upload.update(access_control_post_id: post_in_secure_context.id)
|
||||||
end
|
end
|
||||||
|
@ -138,7 +138,7 @@ RSpec.describe UploadSecurity do
|
||||||
before do
|
before do
|
||||||
post_in_secure_context.trash!
|
post_in_secure_context.trash!
|
||||||
end
|
end
|
||||||
it "still determines whether the post has secure media; returns true" do
|
it "still determines whether the post has secure uploads; returns true" do
|
||||||
expect(subject.should_be_secure?).to eq(true)
|
expect(subject.should_be_secure?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -180,7 +180,7 @@ RSpec.describe UploadSecurity do
|
||||||
upload.update(original_filename: 'test.pdf')
|
upload.update(original_filename: 'test.pdf')
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the access control post has_secure_media?" do
|
context "when the access control post has_secure_uploads?" do
|
||||||
before do
|
before do
|
||||||
upload.update(access_control_post: post_in_secure_context)
|
upload.update(access_control_post: post_in_secure_context)
|
||||||
end
|
end
|
||||||
|
@ -191,9 +191,9 @@ RSpec.describe UploadSecurity do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is disabled" do
|
context "when secure uploads is disabled" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media = false
|
SiteSetting.secure_uploads = false
|
||||||
end
|
end
|
||||||
it "returns false" do
|
it "returns false" do
|
||||||
expect(subject.should_be_secure?).to eq(false)
|
expect(subject.should_be_secure?).to eq(false)
|
||||||
|
|
|
@ -197,7 +197,7 @@ RSpec.describe UrlHelper do
|
||||||
|
|
||||||
FileStore::S3Store.any_instance.stubs(:has_been_uploaded?).returns(true)
|
FileStore::S3Store.any_instance.stubs(:has_been_uploaded?).returns(true)
|
||||||
|
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def cooked
|
def cooked
|
||||||
|
@ -209,12 +209,12 @@ RSpec.describe UrlHelper do
|
||||||
|
|
||||||
it "returns the secure_proxy_without_cdn url, with no asset host URL change" do
|
it "returns the secure_proxy_without_cdn url, with no asset host URL change" do
|
||||||
expect(cooked).to eq(
|
expect(cooked).to eq(
|
||||||
"//test.localhost/secure-media-uploads/dev/original/3X/2/e/2e6f2ef81b6910ea592cd6d21ee897cd51cf72e4.jpeg"
|
"//test.localhost/secure-uploads/dev/original/3X/2/e/2e6f2ef81b6910ea592cd6d21ee897cd51cf72e4.jpeg"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure_media setting is disabled" do
|
context "when secure_uploads setting is disabled" do
|
||||||
before { SiteSetting.secure_media = false }
|
before { SiteSetting.secure_uploads = false }
|
||||||
|
|
||||||
it "returns the local_cdn_url" do
|
it "returns the local_cdn_url" do
|
||||||
expect(cooked).to eq(
|
expect(cooked).to eq(
|
||||||
|
|
|
@ -344,7 +344,7 @@ RSpec.describe OptimizedImage do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the thumbnail is properly generated" do
|
context "when the thumbnail is properly generated" do
|
||||||
context "with secure media disabled" do
|
context "with secure uploads disabled" do
|
||||||
let(:s3_upload) { Fabricate(:upload_s3) }
|
let(:s3_upload) { Fabricate(:upload_s3) }
|
||||||
let(:optimized_path) { %r{/optimized/\d+X.*/#{s3_upload.sha1}_2_100x200\.png} }
|
let(:optimized_path) { %r{/optimized/\d+X.*/#{s3_upload.sha1}_2_100x200\.png} }
|
||||||
|
|
||||||
|
|
|
@ -149,25 +149,25 @@ RSpec.describe Post do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with_secure_media?" do
|
describe "with_secure_uploads?" do
|
||||||
let(:topic) { Fabricate(:topic) }
|
let(:topic) { Fabricate(:topic) }
|
||||||
let!(:post) { Fabricate(:post, topic: topic) }
|
let!(:post) { Fabricate(:post, topic: topic) }
|
||||||
it "returns false if secure media is not enabled" do
|
it "returns false if secure uploads is not enabled" do
|
||||||
expect(post.with_secure_media?).to eq(false)
|
expect(post.with_secure_uploads?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
context "if login_required" do
|
context "if login_required" do
|
||||||
before { SiteSetting.login_required = true }
|
before { SiteSetting.login_required = true }
|
||||||
|
|
||||||
it "returns true" do
|
it "returns true" do
|
||||||
expect(post.with_secure_media?).to eq(true)
|
expect(post.with_secure_uploads?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ RSpec.describe Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns true" do
|
it "returns true" do
|
||||||
expect(post.with_secure_media?).to eq(true)
|
expect(post.with_secure_uploads?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ RSpec.describe Post do
|
||||||
let(:topic) { Fabricate(:private_message_topic) }
|
let(:topic) { Fabricate(:private_message_topic) }
|
||||||
|
|
||||||
it "returns true" do
|
it "returns true" do
|
||||||
expect(post.with_secure_media?).to eq(true)
|
expect(post.with_secure_uploads?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1476,11 +1476,11 @@ RSpec.describe Post do
|
||||||
expect(post.reload.upload_references.pluck(:id)).to_not contain_exactly(post_uploads_ids)
|
expect(post.reload.upload_references.pluck(:id)).to_not contain_exactly(post_uploads_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets the access_control_post_id on uploads in the post that don't already have the value set" do
|
it "sets the access_control_post_id on uploads in the post that don't already have the value set" do
|
||||||
|
@ -1523,7 +1523,7 @@ RSpec.describe Post do
|
||||||
|
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
attachment_upload.update!(original_filename: "hello.csv")
|
attachment_upload.update!(original_filename: "hello.csv")
|
||||||
|
|
||||||
|
@ -1531,8 +1531,8 @@ RSpec.describe Post do
|
||||||
stub_upload(image_upload)
|
stub_upload(image_upload)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "marks image and attachment uploads as secure in PMs when secure_media is ON" do
|
it "marks image and attachment uploads as secure in PMs when secure_uploads is ON" do
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
post = Fabricate(:post, raw: raw, user: user, topic: Fabricate(:private_message_topic, user: user))
|
post = Fabricate(:post, raw: raw, user: user, topic: Fabricate(:private_message_topic, user: user))
|
||||||
post.link_post_uploads
|
post.link_post_uploads
|
||||||
post.update_uploads_secure_status(source: "test")
|
post.update_uploads_secure_status(source: "test")
|
||||||
|
@ -1543,8 +1543,8 @@ RSpec.describe Post do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "marks image uploads as not secure in PMs when when secure_media is ON" do
|
it "marks image uploads as not secure in PMs when when secure_uploads is ON" do
|
||||||
SiteSetting.secure_media = false
|
SiteSetting.secure_uploads = false
|
||||||
post = Fabricate(:post, raw: raw, user: user, topic: Fabricate(:private_message_topic, user: user))
|
post = Fabricate(:post, raw: raw, user: user, topic: Fabricate(:private_message_topic, user: user))
|
||||||
post.link_post_uploads
|
post.link_post_uploads
|
||||||
post.update_uploads_secure_status(source: "test")
|
post.update_uploads_secure_status(source: "test")
|
||||||
|
@ -1556,7 +1556,7 @@ RSpec.describe Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "marks attachments as secure when relevant setting is enabled" do
|
it "marks attachments as secure when relevant setting is enabled" do
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
private_category = Fabricate(:private_category, group: Fabricate(:group))
|
private_category = Fabricate(:private_category, group: Fabricate(:group))
|
||||||
post = Fabricate(:post, raw: raw, user: user, topic: Fabricate(:topic, user: user, category: private_category))
|
post = Fabricate(:post, raw: raw, user: user, topic: Fabricate(:topic, user: user, category: private_category))
|
||||||
post.link_post_uploads
|
post.link_post_uploads
|
||||||
|
@ -1697,7 +1697,7 @@ RSpec.describe Post do
|
||||||
it "correctly identifies secure uploads" do
|
it "correctly identifies secure uploads" do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
SiteSetting.authorized_extensions = "pdf|png|jpg|csv"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
|
|
||||||
upload1 = Fabricate(:upload_s3, secure: true)
|
upload1 = Fabricate(:upload_s3, secure: true)
|
||||||
upload2 = Fabricate(:upload_s3, secure: true)
|
upload2 = Fabricate(:upload_s3, secure: true)
|
||||||
|
|
|
@ -399,9 +399,9 @@ RSpec.describe Upload do
|
||||||
|
|
||||||
let(:upload) { Fabricate(:upload, original_filename: "small.pdf", extension: "pdf", secure: true) }
|
let(:upload) { Fabricate(:upload, original_filename: "small.pdf", extension: "pdf", secure: true) }
|
||||||
|
|
||||||
it 'marks a local attachment as secure if secure media enabled' do
|
it 'marks a local attachment as secure if secure uploads enabled' do
|
||||||
upload.update!(secure: false, access_control_post: Fabricate(:private_message_post))
|
upload.update!(secure: false, access_control_post: Fabricate(:private_message_post))
|
||||||
enable_secure_media
|
enable_secure_uploads
|
||||||
|
|
||||||
expect { upload.update_secure_status }
|
expect { upload.update_secure_status }
|
||||||
.to change { upload.secure }
|
.to change { upload.secure }
|
||||||
|
@ -409,7 +409,7 @@ RSpec.describe Upload do
|
||||||
expect(upload.secure).to eq(true)
|
expect(upload.secure).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'marks a local attachment as not secure if secure media enabled' do
|
it 'marks a local attachment as not secure if secure uploads enabled' do
|
||||||
expect { upload.update_secure_status }
|
expect { upload.update_secure_status }
|
||||||
.to change { upload.secure }
|
.to change { upload.secure }
|
||||||
|
|
||||||
|
@ -428,9 +428,9 @@ RSpec.describe Upload do
|
||||||
expect(upload.secure).to eq(false)
|
expect(upload.secure).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with secure media enabled" do
|
context "with secure uploads enabled" do
|
||||||
before do
|
before do
|
||||||
enable_secure_media
|
enable_secure_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not mark an image upload as not secure when there is no access control post id, to avoid unintentional exposure" do
|
it "does not mark an image upload as not secure when there is no access control post id, to avoid unintentional exposure" do
|
||||||
|
@ -543,9 +543,9 @@ RSpec.describe Upload do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable_secure_media
|
def enable_secure_uploads
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
stub_upload(upload)
|
stub_upload(upload)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -568,54 +568,54 @@ RSpec.describe Upload do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".secure_media_url_from_upload_url" do
|
describe ".secure_uploads_url_from_upload_url" do
|
||||||
before do
|
before do
|
||||||
# must be done so signed_url_for_path exists
|
# must be done so signed_url_for_path exists
|
||||||
enable_secure_media
|
enable_secure_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
it "gets the secure media url from an S3 upload url" do
|
it "gets the secure uploads url from an S3 upload url" do
|
||||||
upload = Fabricate(:upload_s3, secure: true)
|
upload = Fabricate(:upload_s3, secure: true)
|
||||||
url = upload.url
|
url = upload.url
|
||||||
secure_url = Upload.secure_media_url_from_upload_url(url)
|
secure_url = Upload.secure_uploads_url_from_upload_url(url)
|
||||||
expect(secure_url).not_to include(SiteSetting.Upload.absolute_base_url)
|
expect(secure_url).not_to include(SiteSetting.Upload.absolute_base_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".secure_media_url?" do
|
describe ".secure_uploads_url?" do
|
||||||
it "works for a secure media url with or without schema + host" do
|
it "works for a secure uploads url with or without schema + host" do
|
||||||
url = "//localhost:3000/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
url = "//localhost:3000/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(true)
|
expect(Upload.secure_uploads_url?(url)).to eq(true)
|
||||||
url = "/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
url = "/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(true)
|
expect(Upload.secure_uploads_url?(url)).to eq(true)
|
||||||
url = "http://localhost:3000/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
url = "http://localhost:3000/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(true)
|
expect(Upload.secure_uploads_url?(url)).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not get false positives on a topic url" do
|
it "does not get false positives on a topic url" do
|
||||||
url = "/t/secure-media-uploads-are-cool/42839"
|
url = "/t/secure-uploads-are-cool/42839"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(false)
|
expect(Upload.secure_uploads_url?(url)).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns true only for secure media URL for actual media (images/video/audio)" do
|
it "returns true only for secure uploads URL for actual media (images/video/audio)" do
|
||||||
url = "/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.mp4"
|
url = "/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.mp4"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(true)
|
expect(Upload.secure_uploads_url?(url)).to eq(true)
|
||||||
url = "/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
url = "/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.png"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(true)
|
expect(Upload.secure_uploads_url?(url)).to eq(true)
|
||||||
url = "/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.mp3"
|
url = "/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.mp3"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(true)
|
expect(Upload.secure_uploads_url?(url)).to eq(true)
|
||||||
url = "/secure-media-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.pdf"
|
url = "/secure-uploads/original/2X/f/f62055931bb702c7fd8f552fb901f977e0289a18.pdf"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(false)
|
expect(Upload.secure_uploads_url?(url)).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not work for regular upload urls" do
|
it "does not work for regular upload urls" do
|
||||||
url = "/uploads/default/test_0/original/1X/e1864389d8252958586c76d747b069e9f68827e3.png"
|
url = "/uploads/default/test_0/original/1X/e1864389d8252958586c76d747b069e9f68827e3.png"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(false)
|
expect(Upload.secure_uploads_url?(url)).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not raise for invalid URLs" do
|
it "does not raise for invalid URLs" do
|
||||||
url = "http://URL:%20https://google.com"
|
url = "http://URL:%20https://google.com"
|
||||||
expect(Upload.secure_media_url?(url)).to eq(false)
|
expect(Upload.secure_uploads_url?(url)).to eq(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ RSpec.describe 'Multisite s3 uploads', type: :multisite do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'secure uploads' do
|
describe 'secure uploadss' do
|
||||||
let(:store) { FileStore::S3Store.new }
|
let(:store) { FileStore::S3Store.new }
|
||||||
let(:client) { Aws::S3::Client.new(stub_responses: true) }
|
let(:client) { Aws::S3::Client.new(stub_responses: true) }
|
||||||
let(:resource) { Aws::S3::Resource.new(client: client) }
|
let(:resource) { Aws::S3::Resource.new(client: client) }
|
||||||
|
@ -209,10 +209,10 @@ RSpec.describe 'Multisite s3 uploads', type: :multisite do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when secure media are enabled" do
|
describe "when secure uploads are enabled" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.login_required = true
|
SiteSetting.login_required = true
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
s3_helper.stubs(:s3_client).returns(client)
|
s3_helper.stubs(:s3_client).returns(client)
|
||||||
Discourse.stubs(:store).returns(store)
|
Discourse.stubs(:store).returns(store)
|
||||||
end
|
end
|
||||||
|
|
|
@ -100,10 +100,10 @@ RSpec.describe PublishedPagesController do
|
||||||
published_page.topic.tags = [Fabricate(:tag, name: "recipes")]
|
published_page.topic.tags = [Fabricate(:tag, name: "recipes")]
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns 404" do
|
it "returns 404" do
|
||||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe UploadsController, type: [:multisite, :request] do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
upload.update(secure: true)
|
upload.update(secure: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -399,9 +399,9 @@ RSpec.describe UploadsController do
|
||||||
expect(response).to redirect_to(upload.url)
|
expect(response).to redirect_to(upload.url)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when upload is secure and secure media enabled" do
|
context "when upload is secure and secure uploads enabled" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
upload.update(secure: true)
|
upload.update(secure: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -448,8 +448,8 @@ RSpec.describe UploadsController do
|
||||||
describe "local store" do
|
describe "local store" do
|
||||||
fab!(:image_upload) { upload_file("smallest.png") }
|
fab!(:image_upload) { upload_file("smallest.png") }
|
||||||
|
|
||||||
it "does not return secure media when using local store" do
|
it "does not return secure uploads when using local store" do
|
||||||
secure_url = image_upload.url.sub("/uploads", "/secure-media-uploads")
|
secure_url = image_upload.url.sub("/uploads", "/secure-uploads")
|
||||||
get secure_url
|
get secure_url
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
expect(response.status).to eq(404)
|
||||||
|
@ -458,12 +458,12 @@ RSpec.describe UploadsController do
|
||||||
|
|
||||||
describe "s3 store" do
|
describe "s3 store" do
|
||||||
let(:upload) { Fabricate(:upload_s3) }
|
let(:upload) { Fabricate(:upload_s3) }
|
||||||
let(:secure_url) { upload.url.sub(SiteSetting.Upload.absolute_base_url, "/secure-media-uploads") }
|
let(:secure_url) { upload.url.sub(SiteSetting.Upload.absolute_base_url, "/secure-uploads") }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "*"
|
SiteSetting.authorized_extensions = "*"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return 404 for anonymous requests requests" do
|
it "should return 404 for anonymous requests requests" do
|
||||||
|
@ -479,7 +479,7 @@ RSpec.describe UploadsController do
|
||||||
expect(response.redirect_url).to match("Amz-Expires")
|
expect(response.redirect_url).to match("Amz-Expires")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return secure media URL when looking up urls" do
|
it "should return secure uploads URL when looking up urls" do
|
||||||
upload.update_column(:secure, true)
|
upload.update_column(:secure, true)
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ RSpec.describe UploadsController do
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
result = response.parsed_body
|
result = response.parsed_body
|
||||||
expect(result[0]["url"]).to match("secure-media-uploads")
|
expect(result[0]["url"]).to match("secure-uploads")
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the upload cannot be found from the URL" do
|
context "when the upload cannot be found from the URL" do
|
||||||
|
@ -571,9 +571,9 @@ RSpec.describe UploadsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is disabled" do
|
context "when secure uploads is disabled" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media = false
|
SiteSetting.secure_uploads = false
|
||||||
end
|
end
|
||||||
|
|
||||||
context "if the upload is secure false, meaning the ACL is probably public" do
|
context "if the upload is secure false, meaning the ACL is probably public" do
|
||||||
|
@ -582,7 +582,7 @@ RSpec.describe UploadsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should redirect to the regular show route" do
|
it "should redirect to the regular show route" do
|
||||||
secure_url = upload.url.sub(SiteSetting.Upload.absolute_base_url, "/secure-media-uploads")
|
secure_url = upload.url.sub(SiteSetting.Upload.absolute_base_url, "/secure-uploads")
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
get secure_url
|
get secure_url
|
||||||
|
|
||||||
|
@ -597,7 +597,7 @@ RSpec.describe UploadsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should redirect to the presigned URL still otherwise we will get a 403" do
|
it "should redirect to the presigned URL still otherwise we will get a 403" do
|
||||||
secure_url = upload.url.sub(SiteSetting.Upload.absolute_base_url, "/secure-media-uploads")
|
secure_url = upload.url.sub(SiteSetting.Upload.absolute_base_url, "/secure-uploads")
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
get secure_url
|
get secure_url
|
||||||
|
|
||||||
|
@ -622,23 +622,23 @@ RSpec.describe UploadsController do
|
||||||
expect(result[0]["short_path"]).to eq(upload.short_path)
|
expect(result[0]["short_path"]).to eq(upload.short_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'secure media' do
|
describe 'secure uploads' do
|
||||||
let(:upload) { Fabricate(:upload_s3, secure: true) }
|
let(:upload) { Fabricate(:upload_s3, secure: true) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.authorized_extensions = "pdf|png"
|
SiteSetting.authorized_extensions = "pdf|png"
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns secure url for a secure media upload' do
|
it 'returns secure url for a secure uploads upload' do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
post "/uploads/lookup-urls.json", params: { short_urls: [upload.short_url] }
|
post "/uploads/lookup-urls.json", params: { short_urls: [upload.short_url] }
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
result = response.parsed_body
|
result = response.parsed_body
|
||||||
expect(result[0]["url"]).to match("/secure-media-uploads")
|
expect(result[0]["url"]).to match("/secure-uploads")
|
||||||
expect(result[0]["short_path"]).to eq(upload.short_path)
|
expect(result[0]["short_path"]).to eq(upload.short_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -650,7 +650,7 @@ RSpec.describe UploadsController do
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
result = response.parsed_body
|
result = response.parsed_body
|
||||||
expect(result[0]["url"]).to match("/secure-media-uploads")
|
expect(result[0]["url"]).to match("/secure-uploads")
|
||||||
expect(result[0]["short_path"]).to eq(upload.short_path)
|
expect(result[0]["short_path"]).to eq(upload.short_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -487,10 +487,10 @@ RSpec.describe TopicViewSerializer do
|
||||||
expect(json[:published_page][:slug]).to eq(published_page.slug)
|
expect(json[:published_page][:slug]).to eq(published_page.slug)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't return the published page" do
|
it "doesn't return the published page" do
|
||||||
|
|
|
@ -18,17 +18,17 @@ RSpec.describe UploadSerializer do
|
||||||
context "when the upload is secure" do
|
context "when the upload is secure" do
|
||||||
fab!(:upload) { Fabricate(:secure_upload) }
|
fab!(:upload) { Fabricate(:secure_upload) }
|
||||||
|
|
||||||
context "when secure media is disabled" do
|
context "when secure uploads is disabled" do
|
||||||
it "just returns the normal URL, otherwise S3 errors are encountered" do
|
it "just returns the normal URL, otherwise S3 errors are encountered" do
|
||||||
UrlHelper.expects(:cook_url).with(upload.url, secure: false)
|
UrlHelper.expects(:cook_url).with(upload.url, secure: false)
|
||||||
subject.to_json
|
subject.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure uploads is enabled" do
|
||||||
before do
|
before do
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the cooked URL based on the upload URL" do
|
it "returns the cooked URL based on the upload URL" do
|
||||||
|
|
|
@ -13,9 +13,16 @@ module UploadsHelpers
|
||||||
stub_request(:head, "https://#{SiteSetting.s3_upload_bucket}.s3.#{SiteSetting.s3_region}.amazonaws.com/")
|
stub_request(:head, "https://#{SiteSetting.s3_upload_bucket}.s3.#{SiteSetting.s3_region}.amazonaws.com/")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO (martin) Remove this alias once discourse-chat plugin has been
|
||||||
|
# updated to use secure_uploads instead.
|
||||||
def enable_secure_media
|
def enable_secure_media
|
||||||
|
enable_secure_uploads
|
||||||
|
DiscourseEvent.trigger(:site_setting_changed, :secure_media, false, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_secure_uploads
|
||||||
setup_s3
|
setup_s3
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_upload(upload)
|
def stub_upload(upload)
|
||||||
|
|
|
@ -52,9 +52,9 @@ RSpec.describe "tasks/uploads" do
|
||||||
uploads.each { |upload| stub_upload(upload) }
|
uploads.each { |upload| stub_upload(upload) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when secure media is enabled" do
|
context "when secure upload is enabled" do
|
||||||
before do
|
before do
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets an access_control_post for each post upload, using the first linked post in the case of multiple links" do
|
it "sets an access_control_post for each post upload, using the first linked post in the case of multiple links" do
|
||||||
|
@ -155,10 +155,10 @@ RSpec.describe "tasks/uploads" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "uploads:disable_secure_media" do
|
describe "uploads:disable_secure_uploads" do
|
||||||
def invoke_task
|
def invoke_task
|
||||||
capture_stdout do
|
capture_stdout do
|
||||||
Rake::Task['uploads:disable_secure_media'].invoke
|
Rake::Task['uploads:disable_secure_uploads'].invoke
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ RSpec.describe "tasks/uploads" do
|
||||||
setup_s3
|
setup_s3
|
||||||
uploads.each { |upload| stub_upload(upload) }
|
uploads.each { |upload| stub_upload(upload) }
|
||||||
|
|
||||||
SiteSetting.secure_media = true
|
SiteSetting.secure_uploads = true
|
||||||
UploadReference.create(target: post1, upload: upload1)
|
UploadReference.create(target: post1, upload: upload1)
|
||||||
UploadReference.create(target: post1, upload: upload2)
|
UploadReference.create(target: post1, upload: upload2)
|
||||||
UploadReference.create(target: post2, upload: upload3)
|
UploadReference.create(target: post2, upload: upload3)
|
||||||
|
@ -186,9 +186,9 @@ RSpec.describe "tasks/uploads" do
|
||||||
let(:upload4) { Fabricate(:upload_s3, secure: true, access_control_post: post2) }
|
let(:upload4) { Fabricate(:upload_s3, secure: true, access_control_post: post2) }
|
||||||
let(:upload5) { Fabricate(:upload_s3, secure: false) }
|
let(:upload5) { Fabricate(:upload_s3, secure: false) }
|
||||||
|
|
||||||
it "disables the secure media setting" do
|
it "disables the secure upload setting" do
|
||||||
invoke_task
|
invoke_task
|
||||||
expect(SiteSetting.secure_media).to eq(false)
|
expect(SiteSetting.secure_uploads).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "updates all secure uploads to secure: false" do
|
it "updates all secure uploads to secure: false" do
|
||||||
|
|
Loading…
Reference in New Issue
Block a user