mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 08:49:06 +08:00
FEATURE: new 'allow_staff_to_upload_any_file_in_pm' site setting
This commit is contained in:
parent
16475bae89
commit
54e8fb0d89
|
@ -239,8 +239,9 @@ export default Ember.Component.extend({
|
|||
});
|
||||
|
||||
$element.on('fileuploadsubmit', (e, data) => {
|
||||
const isUploading = validateUploadedFiles(data.files);
|
||||
data.formData = { type: "composer" };
|
||||
const isPrivateMessage = this.get("composer.privateMessage");
|
||||
const isUploading = validateUploadedFiles(data.files, { isPrivateMessage });
|
||||
data.formData = { type: "composer", for_private_message: isPrivateMessage };
|
||||
this.setProperties({ uploadProgress: 0, isUploading });
|
||||
return isUploading;
|
||||
});
|
||||
|
|
|
@ -185,6 +185,12 @@ export function validateUploadedFile(file, opts) {
|
|||
if (!name) { return false; }
|
||||
|
||||
// check that the uploaded file is authorized
|
||||
if (Discourse.SiteSettings.allow_staff_to_upload_any_file_in_pm) {
|
||||
if (opts["isPrivateMessage"] && Discourse.User.current("staff")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if (opts["imagesOnly"]) {
|
||||
if (!isAnImage(name) && !isAuthorizedImage(name)) {
|
||||
bootbox.alert(I18n.t('post.errors.upload_not_authorized', { authorized_extensions: authorizedImagesExtensions() }));
|
||||
|
|
|
@ -14,14 +14,15 @@ class UploadsController < ApplicationController
|
|||
|
||||
url = params[:url]
|
||||
file = params[:file] || params[:files]&.first
|
||||
for_private_message = params[:for_private_message]
|
||||
|
||||
if params[:synchronous] && (current_user.staff? || is_api?)
|
||||
data = create_upload(file, url, type)
|
||||
data = create_upload(file, url, type, for_private_message)
|
||||
render json: data.as_json
|
||||
else
|
||||
Scheduler::Defer.later("Create Upload") do
|
||||
begin
|
||||
data = create_upload(file, url, type)
|
||||
data = create_upload(file, url, type, for_private_message)
|
||||
ensure
|
||||
MessageBus.publish("/uploads/#{type}", (data || {}).as_json, client_ids: [params[:client_id]])
|
||||
end
|
||||
|
@ -58,7 +59,7 @@ class UploadsController < ApplicationController
|
|||
raise Discourse::NotFound
|
||||
end
|
||||
|
||||
def create_upload(file, url, type)
|
||||
def create_upload(file, url, type, for_private_message = false)
|
||||
if file.nil?
|
||||
if url.present? && is_api?
|
||||
maximum_upload_size = [SiteSetting.max_image_size_kb, SiteSetting.max_attachment_size_kb].max.kilobytes
|
||||
|
@ -77,7 +78,10 @@ class UploadsController < ApplicationController
|
|||
|
||||
return { errors: [I18n.t("upload.file_missing")] } if tempfile.nil?
|
||||
|
||||
upload = UploadCreator.new(tempfile, filename, type: type, content_type: content_type).create_for(current_user.id)
|
||||
opts = { type: type, content_type: content_type }
|
||||
opts[:for_private_message] = true if for_private_message
|
||||
|
||||
upload = UploadCreator.new(tempfile, filename, opts).create_for(current_user.id)
|
||||
|
||||
if upload.errors.empty? && current_user.admin?
|
||||
retain_hours = params[:retain_hours].to_i
|
||||
|
|
|
@ -13,8 +13,9 @@ class Upload < ActiveRecord::Base
|
|||
|
||||
has_many :optimized_images, dependent: :destroy
|
||||
|
||||
attr_accessor :is_attachment_for_group_message
|
||||
attr_accessor :for_group_message
|
||||
attr_accessor :for_theme
|
||||
attr_accessor :for_private_message
|
||||
|
||||
validates_presence_of :filesize
|
||||
validates_presence_of :original_filename
|
||||
|
|
|
@ -1191,6 +1191,8 @@ en:
|
|||
|
||||
png_to_jpg_quality: "Quality of the converted JPG file (1 is lowest quality, 99 is best quality, 100 to disable)."
|
||||
|
||||
allow_staff_to_upload_any_file_in_pm: "Allow staff members to upload any files in PM."
|
||||
|
||||
enable_flash_video_onebox: "Enable embedding of swf and flv (Adobe Flash) links in oneboxes. WARNING: may introduce security risks."
|
||||
|
||||
default_invitee_trust_level: "Default trust level (0-4) for invited users."
|
||||
|
|
|
@ -798,6 +798,9 @@ files:
|
|||
default: 95
|
||||
min: 1
|
||||
max: 100
|
||||
allow_staff_to_upload_any_file_in_pm:
|
||||
default: true
|
||||
client: true
|
||||
|
||||
trust:
|
||||
default_trust_level:
|
||||
|
|
|
@ -577,7 +577,7 @@ module Email
|
|||
# read attachment
|
||||
File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded }
|
||||
# create the upload for the user
|
||||
opts = { is_attachment_for_group_message: options[:is_group_message] }
|
||||
opts = { for_group_message: options[:is_group_message] }
|
||||
upload = UploadCreator.new(tmp, attachment.filename, opts).create_for(options[:user].id)
|
||||
if upload && upload.errors.empty?
|
||||
# try to inline images
|
||||
|
|
|
@ -16,8 +16,9 @@ class UploadCreator
|
|||
# - type (string)
|
||||
# - content_type (string)
|
||||
# - origin (string)
|
||||
# - is_attachment_for_group_message (boolean)
|
||||
# - for_group_message (boolean)
|
||||
# - for_theme (boolean)
|
||||
# - for_private_message (boolean)
|
||||
def initialize(file, filename, opts = {})
|
||||
@upload = Upload.new
|
||||
@file = file
|
||||
|
@ -78,13 +79,9 @@ class UploadCreator
|
|||
@upload.width, @upload.height = ImageSizer.resize(*@image_info.size)
|
||||
end
|
||||
|
||||
if @opts[:is_attachment_for_group_message]
|
||||
@upload.is_attachment_for_group_message = true
|
||||
end
|
||||
|
||||
if @opts[:for_theme]
|
||||
@upload.for_theme = true
|
||||
end
|
||||
@upload.for_private_message = true if @opts[:for_private_message]
|
||||
@upload.for_group_message = true if @opts[:for_group_message]
|
||||
@upload.for_theme = true if @opts[:for_theme]
|
||||
|
||||
return @upload unless @upload.save
|
||||
|
||||
|
|
|
@ -5,8 +5,13 @@ module Validators; end
|
|||
class Validators::UploadValidator < ActiveModel::Validator
|
||||
|
||||
def validate(upload)
|
||||
# staff can upload any file in PM
|
||||
if upload.for_private_message && SiteSetting.allow_staff_to_upload_any_file_in_pm
|
||||
return true if upload.user&.staff?
|
||||
end
|
||||
|
||||
# check the attachment blacklist
|
||||
if upload.is_attachment_for_group_message && SiteSetting.allow_all_attachments_for_group_messages
|
||||
if upload.for_group_message && SiteSetting.allow_all_attachments_for_group_messages
|
||||
return upload.original_filename =~ SiteSetting.attachment_filename_blacklist_regex
|
||||
end
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ describe UploadsController do
|
|||
end
|
||||
|
||||
it 'parameterize the type' do
|
||||
subject.expects(:create_upload).with(logo, nil, "super_long_type_with_charssuper_long_type_with_char")
|
||||
subject.expects(:create_upload).with(logo, nil, "super_long_type_with_charssuper_long_type_with_char", nil)
|
||||
xhr :post, :create, file: logo, type: "super \# long \//\\ type with \\. $%^&*( chars" * 5
|
||||
end
|
||||
|
||||
|
@ -52,11 +52,11 @@ describe UploadsController do
|
|||
expect(response.status).to eq 200
|
||||
|
||||
expect(message.channel).to eq("/uploads/avatar")
|
||||
expect(message.data).to be
|
||||
expect(message.data["id"]).to be
|
||||
end
|
||||
|
||||
it 'is successful with an attachment' do
|
||||
SiteSetting.stubs(:authorized_extensions).returns("*")
|
||||
SiteSetting.authorized_extensions = "*"
|
||||
|
||||
Jobs.expects(:enqueue).never
|
||||
|
||||
|
@ -66,7 +66,7 @@ describe UploadsController do
|
|||
|
||||
expect(response.status).to eq 200
|
||||
expect(message.channel).to eq("/uploads/composer")
|
||||
expect(message.data).to be
|
||||
expect(message.data["id"]).to be
|
||||
end
|
||||
|
||||
it 'is successful with synchronous api' do
|
||||
|
@ -110,7 +110,7 @@ describe UploadsController do
|
|||
end
|
||||
|
||||
it 'properly returns errors' do
|
||||
SiteSetting.stubs(:max_attachment_size_kb).returns(1)
|
||||
SiteSetting.max_attachment_size_kb = 1
|
||||
|
||||
Jobs.expects(:enqueue).never
|
||||
|
||||
|
@ -123,17 +123,30 @@ describe UploadsController do
|
|||
end
|
||||
|
||||
it 'ensures allow_uploaded_avatars is enabled when uploading an avatar' do
|
||||
SiteSetting.stubs(:allow_uploaded_avatars).returns(false)
|
||||
SiteSetting.allow_uploaded_avatars = false
|
||||
xhr :post, :create, file: logo, type: "avatar"
|
||||
expect(response).to_not be_success
|
||||
end
|
||||
|
||||
it 'ensures sso_overrides_avatar is not enabled when uploading an avatar' do
|
||||
SiteSetting.stubs(:sso_overrides_avatar).returns(true)
|
||||
SiteSetting.sso_overrides_avatar = true
|
||||
xhr :post, :create, file: logo, type: "avatar"
|
||||
expect(response).to_not be_success
|
||||
end
|
||||
|
||||
it 'allows staff to upload any file in PM' do
|
||||
SiteSetting.authorized_extensions = "jpg"
|
||||
SiteSetting.allow_staff_to_upload_any_file_in_pm = true
|
||||
@user.update_columns(moderator: true)
|
||||
|
||||
message = MessageBus.track_publish do
|
||||
xhr :post, :create, file: text_file, type: "composer", for_private_message: true
|
||||
end.first
|
||||
|
||||
expect(response).to be_success
|
||||
expect(message.data["id"]).to be
|
||||
end
|
||||
|
||||
it 'returns an error when it could not determine the dimensions of an image' do
|
||||
Jobs.expects(:enqueue).with(:create_avatar_thumbnails, anything).never
|
||||
|
||||
|
@ -194,7 +207,7 @@ describe UploadsController do
|
|||
|
||||
context "prevent anons from downloading files" do
|
||||
|
||||
before { SiteSetting.stubs(:prevent_anons_from_downloading_files).returns(true) }
|
||||
before { SiteSetting.prevent_anons_from_downloading_files = true }
|
||||
|
||||
it "returns 404 when an anonymous user tries to download a file" do
|
||||
Upload.expects(:find_by).never
|
||||
|
|
|
@ -65,11 +65,22 @@ test("new user cannot upload attachments", function() {
|
|||
});
|
||||
|
||||
test("ensures an authorized upload", function() {
|
||||
const html = { name: "unauthorized.html" };
|
||||
sandbox.stub(bootbox, "alert");
|
||||
not(validUpload([{ name: "unauthorized.html" }]));
|
||||
ok(bootbox.alert.calledWith(I18n.t('post.errors.upload_not_authorized', { authorized_extensions: authorizedExtensions() })));
|
||||
});
|
||||
|
||||
test("staff can upload anything in PM", function() {
|
||||
const files = [{ name: "some.docx" }];
|
||||
Discourse.SiteSettings.authorized_extensions = "jpeg";
|
||||
Discourse.SiteSettings.allow_staff_to_upload_any_file_in_pm = true;
|
||||
|
||||
Discourse.User.resetCurrent(Discourse.User.create({ moderator: true }));
|
||||
|
||||
sandbox.stub(bootbox, "alert");
|
||||
|
||||
not(validUpload([html]));
|
||||
ok(bootbox.alert.calledWith(I18n.t('post.errors.upload_not_authorized', { authorized_extensions: authorizedExtensions() })));
|
||||
not(validUpload(files));
|
||||
ok(validUpload(files, { isPrivateMessage: true }));
|
||||
});
|
||||
|
||||
var imageSize = 10 * 1024;
|
||||
|
|
Loading…
Reference in New Issue
Block a user