Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/controllers/api/v1/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ def index
render json: users, status: :ok
end

def destroy_self
authorize(current_user)

result = Users::DestroySelf.result(user: current_user, password: confirmation_password)

if result.success?
render json: { message: "Account deleted successfully" }, status: :ok
else
render json: { error: "Unable to delete account. Error: #{result.error}" }, status: :unprocessable_entity
end
end

private

def page
Expand All @@ -20,6 +32,10 @@ def page
def per_page
params[:per_page]
end

def confirmation_password
params[:password]
end
end
end
end
2 changes: 2 additions & 0 deletions app/models/health_insurance.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class HealthInsurance < ApplicationRecord
acts_as_paranoid

belongs_to :user, optional: true

has_many :event_procedures, dependent: :destroy
Expand Down
2 changes: 2 additions & 0 deletions app/models/hospital.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class Hospital < ApplicationRecord
acts_as_paranoid

has_many :event_procedures, dependent: :destroy

validates :name, presence: true
Expand Down
2 changes: 2 additions & 0 deletions app/models/medical_shift.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class MedicalShift < ApplicationRecord
acts_as_paranoid

has_enumeration_for :workload, with: MedicalShifts::Workloads, create_helpers: true

monetize :amount
Expand Down
4 changes: 3 additions & 1 deletion app/models/patient.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# frozen_string_literal: true

class Patient < ApplicationRecord
has_many :event_procedures, dependent: :restrict_with_exception
acts_as_paranoid

has_many :event_procedures, dependent: :destroy
belongs_to :user

validates :name, presence: true
Expand Down
2 changes: 2 additions & 0 deletions app/models/procedure.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class Procedure < ApplicationRecord
acts_as_paranoid

monetize :amount

belongs_to :user, optional: true
Expand Down
2 changes: 2 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class User < ApplicationRecord
acts_as_paranoid

# Include default devise modules. Others available are:
# :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
Expand Down
20 changes: 20 additions & 0 deletions app/operations/users/destroy_self.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module Users
class DestroySelf < Actor
input :user, type: User
input :password, type: String

def call
fail!(error: "Wrong password") unless valid_password?

ActiveRecord::Base.transaction { user.destroy_fully! }
end

private

def valid_password?
user.valid_password?(password)
end
end
end
4 changes: 4 additions & 0 deletions app/policies/user_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ class UserPolicy < ApplicationPolicy
def index?
user.admin?
end

def destroy_self?
user == record
end
end
6 changes: 5 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
end
resources :patients, only: %i[index create update destroy]
resources :procedures, only: %i[index create update destroy]
resources :users, only: [:index]
resources :users, only: [:index] do
collection do
delete :destroy_self
end
end

get "/event_procedures_dashboard/amount_by_day", to: "event_procedures_dashboard#amount_by_day"
get "/pdf_reports/generate", to: "pdf_reports#generate", defaults: { format: :pdf }
Expand Down
1 change: 0 additions & 1 deletion db/migrate/20240303152300_add_user_ref_to_patients.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

class AddUserRefToPatients < ActiveRecord::Migration[7.0]
def change
Patient.destroy_all
add_reference :patients, :user, foreign_key: true
end
end
11 changes: 0 additions & 11 deletions db/migrate/20240713155011_update_patients_names.rb

This file was deleted.

8 changes: 8 additions & 0 deletions db/migrate/20250512170444_add_deleted_at_to_patients.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class AddDeletedAtToPatients < ActiveRecord::Migration[7.1]
def change
add_column :patients, :deleted_at, :datetime
add_index :patients, :deleted_at
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class AddDeletedAtToHealthInsurances < ActiveRecord::Migration[7.1]
def change
add_column :health_insurances, :deleted_at, :datetime
add_index :health_insurances, :deleted_at
end
end
8 changes: 8 additions & 0 deletions db/migrate/20250512170622_add_deleted_at_to_medical_shifts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class AddDeletedAtToMedicalShifts < ActiveRecord::Migration[7.1]
def change
add_column :medical_shifts, :deleted_at, :datetime
add_index :medical_shifts, :deleted_at
end
end
8 changes: 8 additions & 0 deletions db/migrate/20250512170640_add_deleted_at_to_procedures.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class AddDeletedAtToProcedures < ActiveRecord::Migration[7.1]
def change
add_column :procedures, :deleted_at, :datetime
add_index :procedures, :deleted_at
end
end
8 changes: 8 additions & 0 deletions db/migrate/20250512170820_add_deleted_at_to_hospitals.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class AddDeletedAtToHospitals < ActiveRecord::Migration[7.1]
def change
add_column :hospitals, :deleted_at, :datetime
add_index :hospitals, :deleted_at
end
end
8 changes: 8 additions & 0 deletions db/migrate/20250512172117_add_deleted_at_to_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class AddDeletedAtToUsers < ActiveRecord::Migration[7.1]
def change
add_column :users, :deleted_at, :datetime
add_index :users, :deleted_at
end
end
14 changes: 13 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion spec/models/patient_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

RSpec.describe Patient do
describe "associations" do
it { is_expected.to have_many(:event_procedures).dependent(:restrict_with_exception) }
it { is_expected.to have_many(:event_procedures).dependent(:destroy) }
it { is_expected.to belong_to(:user) }
end

Expand Down
12 changes: 12 additions & 0 deletions spec/policies/user_policy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,17 @@

it { is_expected.to forbid_actions(%i[index]) }
end

context "when user tries to destroy themselves" do
subject { described_class.new(user, user) }

it { is_expected.to permit_action(:destroy_self) }
end

context "when user tries to destroy another user" do
subject { described_class.new(user, admin) }

it { is_expected.to forbid_action(:destroy_self) }
end
end
end
2 changes: 1 addition & 1 deletion spec/requests/api/v1/medical_shifts_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@
end

it { expect(response).to have_http_status(:not_found) }
it { expect(response.parsed_body[:error]).to eq("Couldn't find MedicalShift with 'id'=#{fake_id}") }
it { expect(response.parsed_body[:error]).to include("Couldn't find MedicalShift with 'id'=#{fake_id}") }
end

context "when medical_shift cannot be destroyed" do
Expand Down
25 changes: 16 additions & 9 deletions spec/requests/api/v1/patients_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,22 +169,29 @@
include_examples "delete request returns ok", Patient

context "when patient cannot be destroyed" do
it "returns unprocessable_content" do
create(:event_procedure, patient: patient, user: user)
let(:patient) { create(:patient) }
let(:errors) do
instance_double(
ActiveModel::Errors,
full_messages: ["Cannot delete record because of dependent event_procedures"]
)
end

delete path, headers: headers
before do
allow(Patient).to receive(:destroy).with(patient.id.to_s).and_return(patient)
allow(patient).to receive_messages(destroy: false, errors: errors)
allow(patient).to receive(:errors).and_return(errors)
end

expect(response).to have_http_status(:unprocessable_content)
it "returns unauthorized" do
delete path, headers: headers
expect(response).to have_http_status(:unauthorized)
end

it "returns errors" do
create(:event_procedure, patient: patient, user: user)

delete path, headers: headers

expect(response.parsed_body).to eq(
{ "error" => "Cannot delete record because of dependent event_procedures" }
)
expect(response.parsed_body).to include({ "error" => "not allowed to destroy? this Patient" })
end
end

Expand Down
Loading
Loading