Commit 0a70e51f authored by Jonne Haß's avatar Jonne Haß

Add a token the filename for exported user data

Also redirect to it for download, for Amazon S3
compatibility.

Prior to this patch an attacker could obtain an
users export by guessing the filename with a high
chance of success. Fully authenticating the
download request is a lot harder due to our diverse
deployment scenarios.

This brings the used method in line with the photo
export feature.

Thanks to @tomekr for the report.
parent 7648b58c
......@@ -140,7 +140,7 @@ class UsersController < ApplicationController
end
def download_profile
send_data File.open(current_user.export.path).read, type: :json, filename: current_user.export.filename
redirect_to current_user.export.url
end
def export_photos
......
......@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class ExportedPhotos < CarrierWave::Uploader::Base
class ExportedPhotos < SecureUploader
def store_dir
"uploads/users"
......@@ -12,10 +12,6 @@ class ExportedPhotos < CarrierWave::Uploader::Base
"#{model.username}_photos_#{secure_token}.zip" if original_filename.present?
end
protected
def secure_token(bytes = 16)
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.urlsafe_base64(bytes))
end
end
......@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class ExportedUser < CarrierWave::Uploader::Base
class ExportedUser < SecureUploader
def store_dir
"uploads/users"
......@@ -13,7 +13,7 @@ class ExportedUser < CarrierWave::Uploader::Base
end
def filename
"#{model.username}_diaspora_data.json.gz"
"#{model.username}_diaspora_data_#{secure_token}.json.gz"
end
end
class SecureUploader < CarrierWave::Uploader::Base
protected
def secure_token(bytes = 16)
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.urlsafe_base64(bytes))
end
end
......@@ -24,8 +24,7 @@ describe UsersController, :type => :controller do
it "downloads a user's export file" do
@user.perform_export!
get :download_profile
parsed = JSON.parse(ActiveSupport::Gzip.decompress(response.body))
expect(parsed['user']['username']).to eq @user.username
expect(response).to redirect_to(@user.export.url)
end
end
......@@ -37,7 +36,7 @@ describe UsersController, :type => :controller do
expect(response).to redirect_to(edit_user_path)
end
end
describe '#download_photos' do
it "redirects to user's photos zip file" do
@user.perform_export_photos!
......@@ -74,7 +73,7 @@ describe UsersController, :type => :controller do
get :public, :username => @user.username, :format => :atom
expect(response.body).to include('a href')
end
it 'includes reshares in the atom feed' do
reshare = FactoryGirl.create(:reshare, :author => @user.person)
get :public, :username => @user.username, :format => :atom
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment