Skip to content

Commit

Permalink
Allow users to delete uploaded files.
Browse files Browse the repository at this point in the history
Fixes #1910
Fixes #1793
  • Loading branch information
jcoyne committed Apr 25, 2016
1 parent b42a6de commit 7598722
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 41 deletions.
4 changes: 4 additions & 0 deletions .rubocop.yml
Expand Up @@ -34,6 +34,10 @@ Style/BlockEndNewline:
Exclude:
- 'spec/**/*'

Style/SymbolProc: # https://github.com/bbatsov/rubocop/issues/3071
Exclude:
- 'app/models/sufia/uploaded_file.rb'

Style/MultilineBlockLayout:
Exclude:
- 'spec/**/*'
Expand Down
18 changes: 13 additions & 5 deletions app/controllers/sufia/uploads_controller.rb
@@ -1,8 +1,16 @@
class Sufia::UploadsController < ApplicationController
before_action :authenticate_user!
module Sufia
class UploadsController < ApplicationController
load_and_authorize_resource class: UploadedFile

def create
@uploaded_file = UploadedFile.create!(file: params[:files].first,
user: current_user)
def create
@upload.attributes = { file: params[:files].first,
user: current_user }
@upload.save!
end

def destroy
@upload.destroy
head :no_content
end
end
end
7 changes: 7 additions & 0 deletions app/models/concerns/sufia/ability.rb
Expand Up @@ -14,6 +14,13 @@ def sufia_abilities
stats_abilities
citation_abilities
proxy_deposit_abilities
uploaded_file_abilities
end

def uploaded_file_abilities
return unless registered_user?
can :create, UploadedFile
can :destroy, UploadedFile, user: current_user
end

def proxy_deposit_abilities
Expand Down
12 changes: 12 additions & 0 deletions app/models/sufia/uploaded_file.rb
@@ -0,0 +1,12 @@
module Sufia
# Store a file uploaded by a user. Eventually these files get
# attached to FileSets and pushed into Fedora.
class UploadedFile < ActiveRecord::Base
mount_uploader :file, UploadedFileUploader
belongs_to :user, class_name: '::User'

before_destroy do |obj|
obj.remove_file!
end
end
end
6 changes: 0 additions & 6 deletions app/models/uploaded_file.rb

This file was deleted.

16 changes: 4 additions & 12 deletions app/views/curation_concerns/base/_form_files.html.erb
Expand Up @@ -91,18 +91,10 @@
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
{% if (file.deleteUrl) { %}
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" name="delete" value="1" class="toggle">
{% } else { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</td>
</tr>
{% } %}
Expand Down
6 changes: 3 additions & 3 deletions app/views/sufia/batch_uploads/_form_files.html.erb
Expand Up @@ -98,9 +98,9 @@
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
<span class="size">{%=o.formatFileSize(file.size)%}</span>
<button class="btn btn-warning cancel pull-right">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
<span>Cancel</span>
<button class="btn btn-danger delete pull-right" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions app/views/sufia/uploads/create.json.jbuilder
@@ -1,10 +1,10 @@
json.files [@uploaded_file] do |uploaded_file|
json.files [@upload] do |uploaded_file|
json.id uploaded_file.id
json.name uploaded_file.file.file.filename
json.size uploaded_file.file.file.size
# TODO: implement these
# json.url "/uploads/#{uploaded_file.id}"
# json.thumbnail_url uploaded_file.id
# json.delete_url 'deleteme'
# json.delete_type 'DELETE'
json.deleteUrl sufia.polymorphic_path(uploaded_file)
json.deleteType 'DELETE'
end
1 change: 1 addition & 0 deletions config/routes.rb
Expand Up @@ -9,6 +9,7 @@
# e.g. https://scholarsphere.psu.edu/files/gm80hv36p
get '/files/:id', to: redirect('/concern/generic_works/%{id}')

delete '/uploads/:id', to: 'sufia/uploads#destroy', as: :sufia_uploaded_file
post '/uploads', to: 'sufia/uploads#create'
# This is a hack that is required because the rails form the uploader is on
# sets the _method parameter to patch when the work already exists.
Expand Down
6 changes: 3 additions & 3 deletions spec/actors/create_with_files_actor_spec.rb
Expand Up @@ -8,8 +8,8 @@
CurationConcerns::ActorStack.new(work, user, [described_class])
end
let(:user) { create(:user) }
let(:uploaded_file1) { UploadedFile.create(user: user) }
let(:uploaded_file2) { UploadedFile.create(user: user) }
let(:uploaded_file1) { Sufia::UploadedFile.create(user: user) }
let(:uploaded_file2) { Sufia::UploadedFile.create(user: user) }
let(:work) { create(:generic_work, user: user) }
let(:uploaded_file_ids) { [uploaded_file1.id, uploaded_file2.id] }
let(:attributes) { { uploaded_files: uploaded_file_ids } }
Expand All @@ -27,7 +27,7 @@
end

context "when uploaded_file_ids don't belong to me" do
let(:uploaded_file2) { UploadedFile.create }
let(:uploaded_file2) { Sufia::UploadedFile.create }
it "doesn't attach files" do
expect(AttachFilesToWorkJob).not_to receive(:perform_later)
expect(actor.create(attributes)).to be false
Expand Down
39 changes: 34 additions & 5 deletions spec/controllers/sufia/uploads_controller_spec.rb
@@ -1,9 +1,9 @@
require 'spec_helper'

describe Sufia::UploadsController do
let(:user) { create(:user) }
describe "#create" do
let(:file) { fixture_file_upload('/world.png', 'image/png') }
let(:user) { create(:user) }

context "when signed in" do
before do
Expand All @@ -12,17 +12,46 @@
it "is successful" do
post :create, files: [file], format: 'json'
expect(response).to be_success
expect(assigns(:uploaded_file)).to be_kind_of UploadedFile
expect(assigns(:uploaded_file)).to be_persisted
expect(assigns(:uploaded_file).user).to eq user
expect(assigns(:upload)).to be_kind_of Sufia::UploadedFile
expect(assigns(:upload)).to be_persisted
expect(assigns(:upload).user).to eq user
end
end

context "when not signed in" do
it "is successful" do
it "is unauthorized" do
post :create, files: [file], format: 'json'
expect(response.status).to eq 401
end
end
end

describe "#destroy" do
let(:file) { File.open(fixture_path + '/world.png') }
let(:uploaded_file) { Sufia::UploadedFile.create(file: file, user: user) }

context "when signed in" do
before do
sign_in user
end
it "destroys the uploaded file" do
delete :destroy, id: uploaded_file
expect(response.status).to eq 204
expect(assigns[:upload]).to be_destroyed
expect(File.exist?(uploaded_file.file.file.file)).to be false
end

it "doesn't destroy files that don't belong to me" do
delete :destroy, id: Sufia::UploadedFile.create(file: file)
expect(response.status).to eq 401
end
end

context "when not signed in" do
it "is redirected to sign in" do
delete :destroy, id: uploaded_file
expect(response).to redirect_to main_app.new_user_session_path
end
end
end
end
4 changes: 2 additions & 2 deletions spec/jobs/attach_files_to_work_job_spec.rb
Expand Up @@ -4,8 +4,8 @@
context "happy path" do
let(:file1) { File.open(fixture_path + '/world.png') }
let(:file2) { File.open(fixture_path + '/image.jp2') }
let(:uploaded_file1) { UploadedFile.create(file: file1) }
let(:uploaded_file2) { UploadedFile.create(file: file2) }
let(:uploaded_file1) { Sufia::UploadedFile.create(file: file1) }
let(:uploaded_file2) { Sufia::UploadedFile.create(file: file2) }
let(:generic_work) { create(:public_generic_work) }

it "attaches files, copies visibility and updates the uploaded files" do
Expand Down
4 changes: 2 additions & 2 deletions spec/jobs/batch_create_job_spec.rb
Expand Up @@ -17,8 +17,8 @@
describe "#perform" do
let(:file1) { File.open(fixture_path + '/world.png') }
let(:file2) { File.open(fixture_path + '/image.jp2') }
let(:upload1) { UploadedFile.create(user: user, file: file1) }
let(:upload2) { UploadedFile.create(user: user, file: file2) }
let(:upload1) { Sufia::UploadedFile.create(user: user, file: file1) }
let(:upload2) { Sufia::UploadedFile.create(user: user, file: file2) }
let(:title) { { upload1.id => 'File One', upload2.id => 'File Two' } }
let(:resource_types) { { upload1.id => 'Article', upload2.id => 'Image' } }
let(:metadata) { { tag: [] } }
Expand Down

0 comments on commit 7598722

Please sign in to comment.