Skip to content

Commit

Permalink
allow users to delete devices
Browse files Browse the repository at this point in the history
  • Loading branch information
timcowlishaw committed Dec 21, 2024
1 parent 20582bd commit 5019cba
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 4 deletions.
25 changes: 25 additions & 0 deletions app/controllers/ui/devices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ def update
end
end

def delete
find_device!
return unless authorize_device! :destroy?, :delete_device_forbidden
@title = I18n.t(:delete_device_title, name: @device.name)
add_breadcrumbs(
[I18n.t(:show_user_title, owner: helpers.possessive(@device.owner, current_user)), ui_user_path(@device.owner.username)],
[I18n.t(:show_device_title, name: @device.name), ui_device_path(@device.id)],
[I18n.t(:edit_device_title, name: @device.name), edit_ui_device_path(@device.id)],
[I18n.t(:delete_device_title, name: @device.name), delete_ui_device_path(@device.id)]
)
end

def destroy
find_device!
return unless authorize_device! :destroy?, :delete_device_forbidden
if @device.name != params[:name]
flash[:alert] = I18n.t(:delete_device_wrong_name)
redirect_to delete_ui_device_path(@device.id)
return
end
@device.archive!
flash[:success] = I18n.t(:delete_device_success)
redirect_to ui_user_path(current_user.username)
end

private

def device_params
Expand Down
7 changes: 7 additions & 0 deletions app/views/ui/devices/delete.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<%= bootstrap_form_tag url: ui_device_path(@device.id), method: :delete do |f| %>
<p><%= t(:delete_device_warning_html, name: @device.name) %></p>
<%= f.text_field :name, label: t(:delete_device_name_label) %>
<div class="mt-4">
<%= f.primary t(:delete_device_submit), class: "btn btn-danger w-100 w-md-auto" %>
</div>
<% end %>
4 changes: 4 additions & 0 deletions app/views/ui/devices/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@
<div class="mt-5">
<%= f.primary t(:edit_user_submit), class: "btn btn-primary w-100 w-md-auto" %>
</div>
<% if authorize? @device, :destroy? %>
<h2 class="mt-5 mb-3"><%= t(:edit_device_other_actions_subhead) %></h2>
<div><%= link_to t(:edit_device_delete_device_submit), delete_ui_device_path(@device.id), class: "btn btn-danger w-100 w-md-auto" %></div>
<% end %>
<% end %>
1 change: 0 additions & 1 deletion app/views/ui/users/delete.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<%= bootstrap_form_tag url: ui_user_path(@user.id), method: :delete do |f| %>
<%= f.hidden_field :token, value: @token %>
<p><%= t(:delete_user_warning_html, username: current_user.username) %></p>
<%= f.text_field :username, label: t(:delete_user_username_label, owner: possessive(@user, current_user)) %>
<div class="mt-4">
Expand Down
4 changes: 4 additions & 0 deletions config/locales/controllers/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ en:
edit_device_forbidden: "You are not allowed to edit settings for that kit!"
update_device_success: "The kit's settings have been updated!"
update_device_failure: "Some errors prevented us from updating the kit's settings. Please check below and try again!"
delete_device_title: "Delete kit: %{name}"
delete_device_forbidden: "You are not allowed to delete that kit!"
delete_device_success: "The kit has been deleted!"
delete_device_wrong_name: "That kit name did not match! Please try again."
7 changes: 6 additions & 1 deletion config/locales/views/devices/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ en:
edit_device_tags_blurb: "Kits can be grouped by tags. Choose from the available tags or submit a tag request on the Forum."
edit_device_tags_label: "Tags"
edit_device_postprocessing_subhead: "Postprocessing information"
edit_device_postprocessing_blurb: "Follow the instructions here to generate a valid JSON containing the postprocessing information for your device. This is an advanced feature and it's not required for standard Smart Citizen Kits!"
edit_device_postprocessing_blurb: "Follow the instructions here to generate a valid JSON containing the postprocessing information for your kit. This is an advanced feature and it's not required for standard Smart Citizen Kits!"
edit_device_hardware_url_label: "Hardware URL"
edit_device_other_actions_subhead: "Other actions"
edit_device_delete_device_submit: "Delete this kit"
delete_device_warning_html: "🚨<strong>Warning!</strong> This will permanently delete the kit <strong>%{name}</strong>.🚨"
delete_device_name_label: "To confirm, type the kit name below:"
delete_device_submit: "I understand, delete the kit"
4 changes: 2 additions & 2 deletions config/locales/views/users/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ en:
show_user_edit_cta: "Edit %{owner} profile"
show_user_secrets_cta: "Show %{owner} API keys"
show_user_log_out_cta: "Sign out"
show_user_devices_heading: "Devices"
show_user_devices_heading: "Kits"
show_user_no_devices_message: "%{username} has no kits yet!"
secrets_user_blurb_html: This key gives you access to your data in the SmartCitizen platform using the <a href="https://developer.smartcitizen.me/" target="_blank">REST API</a>. <strong>Please keep it safe and do not share with anyone, just as you would with a password</strong>.
secrets_user_api_key_label: API key
Expand All @@ -24,7 +24,7 @@ en:
edit_user_public_profile_subhead: "Public profile"
edit_user_other_actions_subhead: "Other Actions"
edit_user_delete_account_submit: "Permanently delete %{owner} account"
delete_user_warning_html: "🚨<strong>Warning!</strong> This will permanently delete the account <strong>%{username}</strong> and all of its devices.🚨"
delete_user_warning_html: "🚨<strong>Warning!</strong> This will permanently delete the account <strong>%{username}</strong> and all of its kits.🚨"
delete_user_username_label: "To confirm, type %{owner} username below:"
delete_user_submit: "I understand, delete %{owner} account"
users_password_reset_landing_confirmation_label: "Confirm new password"
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
resources :devices, as: "devices" do
member do
get :edit
get :delete
end
end

Expand Down
80 changes: 80 additions & 0 deletions spec/controllers/ui/devices_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,85 @@
end
end
end

describe "delete" do
context "when the device's owner is logged in" do
it "displays the delete device form" do
get :delete, params: { id: device.id }, session: { user_id: user.try(:id) }
expect(response).to have_http_status(:success)
expect(response).to render_template(:delete)
end
end

context "when a different user is logged in" do
let(:owner) { create(:user) }
it "redirects to the ui users page" do
get :delete, params: { id: device.id }, session: { user_id: user.try(:id) }
expect(response).to redirect_to(ui_user_path(user.username))
expect(flash[:alert]).to be_present
end
end

context "when no user is logged in" do
let(:user) { nil }
it "redirects to the login page" do
get :delete, params: { id: device.id }, session: { user_id: user.try(:id) }
expect(response).to redirect_to(login_path)
expect(flash[:alert]).to be_present
end
end
end

describe "destroy" do
context "when the device's owner is logged in" do
context "when the correct device name is provided" do
it "archives the devicer, and redirects to the user's profile" do
expect_any_instance_of(Device).to receive(:archive!)
delete :destroy,
params: { id: device.id, name: device.name },
session: { user_id: user.try(:id) }
expect(response).to redirect_to(ui_user_path(user.username))
expect(flash[:success]).to be_present
end
end

context "when an incorrect device name is provided" do
it "does not archive the device and redirects to the delete page" do
expect_any_instance_of(Device).not_to receive(:archive!)
delete :destroy,
params: { id: device.id, name: "a wrong device name" },
session: { user_id: user.try(:id) }
expect(response).to redirect_to(delete_ui_device_path(device.id))
expect(flash[:alert]).to be_present
end
end
end

context "when a different user is logged in" do
let(:owner) { create(:user) }

it "does not archive the device and redirects to the ui users page" do
expect_any_instance_of(Device).not_to receive(:archive!)
delete :destroy,
params: { id: device.id, name: device.name },
session: { user_id: user.try(:id) }
expect(response).to redirect_to(ui_user_path(user.username))
expect(flash[:alert]).to be_present
end
end

context "when no user is logged in" do
let(:user) { nil }

it "does not archive the user and redirets to the login page" do
expect_any_instance_of(Device).not_to receive(:archive!)
delete :destroy,
params: { id: device.id, name: device.name },
session: { user_id: user.try(:id) }
expect(response).to redirect_to(login_path)
expect(flash[:alert]).to be_present
end
end
end
end

23 changes: 23 additions & 0 deletions spec/features/device_management_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,27 @@
expect(page).to have_current_path(ui_device_path(device.id))
expect(page).to have_content("new device name")
end


scenario "User deletes a device" do
password = "password123"
username = "username"
device_name = "devicename"
user = create(:user, username: username, password: password, password_confirmation: password)
device = create(:device, name: device_name, owner: user)
visit "/login"
fill_in "Username or email", with: user.email
fill_in "Password", with: password
click_on "Sign into your account"
click_on device_name
click_on "Edit kit settings"
click_on "Delete this kit"
expect(page).to have_current_path(delete_ui_device_path(device.id))
fill_in "To confirm, type the kit name below:", with: device_name
click_on "I understand, delete the kit"
expect(page).to have_current_path(ui_user_path(username))
expect(page).to have_content("The kit has been deleted!")
expect(page).not_to have_content(device_name)
expect(device.reload).to be_archived
end
end

0 comments on commit 5019cba

Please sign in to comment.