Move devices endpoint from /devices to /my/devices

Keep legacy /devices routes for backwards compatibility with mobile
apps not yet updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Rosa Gutierrez
2026-03-03 15:09:34 +00:00
committed by Rosa Gutierrez
parent f6ed923e75
commit 53df0e405b
5 changed files with 31 additions and 24 deletions
@@ -1,4 +1,4 @@
class DevicesController < ApplicationController
class My::DevicesController < ApplicationController
disallow_account_scope
before_action :set_device, only: :destroy
@@ -16,7 +16,7 @@ class DevicesController < ApplicationController
def destroy
@device.destroy
respond_to do |format|
format.html { redirect_to saas.devices_path, notice: "Device removed" }
format.html { redirect_to saas.my_devices_path, notice: "Device removed" }
format.json { head :no_content }
end
end
@@ -17,7 +17,7 @@
Added <%= local_datetime_tag(device.created_at, style: :daysago) %>
</span>
</div>
<%= button_to saas.device_path(device), method: :delete, class: "btn btn--circle-mobile txt-small", data: { confirm: "Remove this device?" }, form: { class: "flex-item-no-shrink" } do %>
<%= button_to saas.my_device_path(device), method: :delete, class: "btn btn--circle-mobile txt-small", data: { confirm: "Remove this device?" }, form: { class: "flex-item-no-shrink" } do %>
<%= icon_tag "trash", class: "icon--mobile-only" %>
<span class="overflow-ellipsis">Remove</span>
<% end %>
@@ -5,7 +5,7 @@
<p class="txt-small">
You have <%= pluralize(Current.identity.devices.count, "mobile device") %> registered for push notifications.
</p>
<%= link_to "Manage devices", saas.devices_path, class: "btn txt-small" %>
<%= link_to "Manage devices", saas.my_devices_path, class: "btn txt-small" %>
<% else %>
<p class="txt-small color-secondary">
No mobile devices registered. Install the iOS or Android app to receive push notifications on your phone.
+8 -1
View File
@@ -1,7 +1,14 @@
Fizzy::Saas::Engine.routes.draw do
Queenbee.routes(self)
resources :devices, only: [ :index, :create, :destroy ]
namespace :my do
resources :devices, only: [ :index, :create, :destroy ]
end
# Legacy /devices routes for mobile apps not yet updated to /my/devices
get "/devices", to: redirect("/my/devices")
post "/devices", to: "my/devices#create"
delete "/devices/:id", to: "my/devices#destroy"
namespace :admin do
mount Audits1984::Engine, at: "/console"
@@ -1,6 +1,6 @@
require "test_helper"
class DevicesControllerTest < ActionDispatch::IntegrationTest
class My::DevicesControllerTest < ActionDispatch::IntegrationTest
setup do
@identity = identities(:david)
sign_in_as :david
@@ -9,7 +9,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "index shows identity's devices" do
@identity.devices.create!(token: "test_token_123", platform: "apple", name: "iPhone 15 Pro")
untenanted { get saas.devices_path }
untenanted { get saas.my_devices_path }
assert_response :success
assert_select "strong", "iPhone 15 Pro"
@@ -19,7 +19,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "index shows empty state when no devices" do
@identity.devices.delete_all
untenanted { get saas.devices_path }
untenanted { get saas.my_devices_path }
assert_response :success
assert_select "h1", /No devices registered/
@@ -36,7 +36,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "index requires authentication" do
sign_out
untenanted { get saas.devices_path }
untenanted { get saas.my_devices_path }
assert_response :redirect
end
@@ -46,7 +46,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
assert_difference -> { ApplicationPushDevice.count }, 1 do
untenanted do
post saas.devices_path, params: {
post saas.my_devices_path, params: {
token: token,
platform: "apple",
name: "iPhone 15 Pro"
@@ -65,7 +65,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "creates android device" do
untenanted do
post saas.devices_path, params: {
post saas.my_devices_path, params: {
token: SecureRandom.hex(32),
platform: "google",
name: "Pixel 8"
@@ -92,7 +92,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
# Current identity registers the same token with their own device
assert_difference -> { ApplicationPushDevice.count }, 1 do
untenanted do
post saas.devices_path, params: {
post saas.my_devices_path, params: {
token: shared_token,
platform: "apple",
name: "David's iPhone"
@@ -113,7 +113,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "rejects invalid platform" do
untenanted do
post saas.devices_path, params: {
post saas.my_devices_path, params: {
token: SecureRandom.hex(32),
platform: "windows",
name: "Surface"
@@ -125,7 +125,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "rejects missing token" do
untenanted do
post saas.devices_path, params: {
post saas.my_devices_path, params: {
platform: "apple",
name: "iPhone"
}, as: :json
@@ -138,7 +138,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
sign_out
untenanted do
post saas.devices_path, params: {
post saas.my_devices_path, params: {
token: SecureRandom.hex(32),
platform: "apple"
}, as: :json
@@ -155,16 +155,16 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
)
assert_difference -> { ApplicationPushDevice.count }, -1 do
untenanted { delete saas.device_path(device) }
untenanted { delete saas.my_device_path(device) }
end
assert_redirected_to saas.devices_path(script_name: nil)
assert_redirected_to saas.my_devices_path(script_name: nil)
assert_not ApplicationPushDevice.exists?(device.id)
end
test "returns not found when device not found by id" do
assert_no_difference "ApplicationPushDevice.count" do
untenanted { delete saas.device_path(id: "nonexistent") }
untenanted { delete saas.my_device_path(id: "nonexistent") }
end
assert_response :not_found
@@ -179,7 +179,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
)
assert_no_difference "ApplicationPushDevice.count" do
untenanted { delete saas.device_path(device) }
untenanted { delete saas.my_device_path(device) }
end
assert_response :not_found
@@ -195,7 +195,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
sign_out
untenanted { delete saas.device_path(device) }
untenanted { delete saas.my_device_path(device) }
assert_response :redirect
assert ApplicationPushDevice.exists?(device.id)
@@ -209,7 +209,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
)
assert_difference -> { ApplicationPushDevice.count }, -1 do
untenanted { delete saas.device_path("token_to_unregister"), as: :json }
untenanted { delete saas.my_device_path("token_to_unregister"), as: :json }
end
assert_response :no_content
@@ -218,7 +218,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
test "returns not found when device not found by token" do
assert_no_difference "ApplicationPushDevice.count" do
untenanted { delete saas.device_path("nonexistent_token"), as: :json }
untenanted { delete saas.my_device_path("nonexistent_token"), as: :json }
end
assert_response :not_found
@@ -233,7 +233,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
)
assert_no_difference "ApplicationPushDevice.count" do
untenanted { delete saas.device_path("other_identity_token"), as: :json }
untenanted { delete saas.my_device_path("other_identity_token"), as: :json }
end
assert_response :not_found
@@ -249,7 +249,7 @@ class DevicesControllerTest < ActionDispatch::IntegrationTest
sign_out
untenanted { delete saas.device_path("my_token"), as: :json }
untenanted { delete saas.my_device_path("my_token"), as: :json }
assert_response :redirect
assert ApplicationPushDevice.exists?(device.id)