6 changed files with 162 additions and 0 deletions
@ -0,0 +1,18 @@
|
||||
class CsvDownloadsController < ApplicationController |
||||
before_action :authenticate_user! |
||||
|
||||
def download |
||||
csv_download = CsvDownload.find(params[:id]) |
||||
authorize csv_download |
||||
|
||||
downloader = Csv::Downloader.new(csv_download:) |
||||
|
||||
if Rails.env.development? |
||||
downloader.call |
||||
send_file downloader.path, filename: csv_download.filename, type: "text/csv" |
||||
else |
||||
presigned_url = downloader.presigned_url |
||||
redirect_to presigned_url, allow_other_host: true |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,12 @@
|
||||
class CsvDownloadPolicy |
||||
attr_reader :current_user, :csv_download |
||||
|
||||
def initialize(current_user, csv_download) |
||||
@current_user = current_user |
||||
@csv_download = csv_download |
||||
end |
||||
|
||||
def download? |
||||
@current_user == @csv_download.user || @current_user.support? || @current_user.organisation == @csv_download.organisation |
||||
end |
||||
end |
@ -0,0 +1,50 @@
|
||||
class Csv::Downloader |
||||
attr_reader :csv_download |
||||
|
||||
delegate :path, to: :file |
||||
|
||||
def initialize(csv_download:) |
||||
@csv_download = csv_download |
||||
end |
||||
|
||||
def call |
||||
download |
||||
end |
||||
|
||||
def delete_local_file! |
||||
file.unlink |
||||
end |
||||
|
||||
def presigned_url |
||||
s3_storage_service.get_presigned_url(csv_download.filename, 60, response_content_disposition: "attachment; filename=#{csv_download.filename}") |
||||
end |
||||
|
||||
private |
||||
|
||||
def download |
||||
io = storage_service.get_file_io(csv_download.filename) |
||||
file.write(io.read) |
||||
io.close |
||||
file.close |
||||
end |
||||
|
||||
def file |
||||
@file ||= Tempfile.new |
||||
end |
||||
|
||||
def storage_service |
||||
@storage_service ||= if FeatureToggle.upload_enabled? |
||||
s3_storage_service |
||||
else |
||||
local_disk_storage_service |
||||
end |
||||
end |
||||
|
||||
def s3_storage_service |
||||
Storage::S3Service.new(Configuration::EnvConfigurationService.new, ENV["BULK_UPLOAD_BUCKET"]) |
||||
end |
||||
|
||||
def local_disk_storage_service |
||||
Storage::LocalDiskService.new |
||||
end |
||||
end |
@ -0,0 +1,8 @@
|
||||
FactoryBot.define do |
||||
factory :csv_download do |
||||
download_type { "lettings" } |
||||
user { create(:user) } |
||||
organisation { user.organisation } |
||||
filename { "lettings.csv" } |
||||
end |
||||
end |
@ -0,0 +1,68 @@
|
||||
require "rails_helper" |
||||
|
||||
RSpec.describe CsvDownloadsController, type: :request do |
||||
describe "GET #download" do |
||||
let(:csv_user) { create(:user) } |
||||
let(:csv_download) { create(:csv_download, user: csv_user, organisation: csv_user.organisation) } |
||||
let(:get_file_io) do |
||||
io = StringIO.new |
||||
io.write("hello") |
||||
io.rewind |
||||
io |
||||
end |
||||
let(:mock_storage_service) { instance_double(Storage::S3Service, get_file_io:, get_presigned_url: "https://example.com") } |
||||
|
||||
before do |
||||
allow(Storage::S3Service).to receive(:new).and_return(mock_storage_service) |
||||
end |
||||
|
||||
context "when user is not signed in" do |
||||
it "redirects to sign in page" do |
||||
get "/csv-downloads/#{csv_download.id}/download" |
||||
expect(response).to redirect_to("/account/sign-in") |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in" do |
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
context "and the user is from a different organisation" do |
||||
let(:user) { create(:user) } |
||||
|
||||
before do |
||||
get "/csv-downloads/#{csv_download.id}/download" |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
expect(response).to have_http_status(:unauthorized) |
||||
end |
||||
end |
||||
|
||||
context "and is the user who generated the csv" do |
||||
let(:user) { csv_user } |
||||
|
||||
before do |
||||
get "/csv-downloads/#{csv_download.id}/download" |
||||
end |
||||
|
||||
it "allows downloading the csv" do |
||||
expect(response).to have_http_status(:found) |
||||
end |
||||
end |
||||
|
||||
context "and is the user is from the same organisation" do |
||||
let(:user) { create(:user, organisation: csv_user.organisation) } |
||||
|
||||
before do |
||||
get "/csv-downloads/#{csv_download.id}/download" |
||||
end |
||||
|
||||
it "allows downloading the csv" do |
||||
expect(response).to have_http_status(:found) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue