handle account/organization destroy with multiple users, redirects

33 Views Asked by At

This app has the structure of users have many organizations through memberships.

class User < ApplicationRecord
    has_many :memberships, dependent: :destroy
    has_many :organizations, through: :memberships
....
end

class Membership < ApplicationRecord
    belongs_to :organization, touch: true
    belongs_to :user, counter_cache: true
..
end

class Organization < ApplicationRecord
  has_many :memberships, dependent: :destroy
  has_many :members, through: :memberships, source: :user
...
end

The Organization can be destroyed by owners, attribute on memberships, from there call backs will take care of destroying associations.

There are before_actions that check user/organizations associations exists. So the moment the user hits a url with an organization that has been deleted, they would be redirected. But this seems wrong.

My question is while the current_user would follow the controller action redirect. How should the other users be handled? Should they hit the before_actions and let those redirects handle it? Can an after_destroy call back handle this; that seems like breaking the MVC pattern tho and then you have to deal with if the user is "on" that organization or another.

Hell has this been discussed and this has a name that I'm not aware of.

Much appreciated.

EDIT: Controller checks:

class Organizations::BaseController < ApplicationController
  before_action :restrict_user_by_role

  protected

  def restrict_user_by_role
    if organization_set?
      if !member?
        flash[:warning] = t("restricted_roles")
        redirect_to redirect_path
      elsif !current_membership.can_view_organization?
        flash[:warning] = t("restricted_roles")
        redirect_to redirect_path
      end
    else
      id = params[:parm_passed]
      unless Membership.current_member_check(id).exists?
        flash[:warning] = t("restricted_roles")
        refresh_or_redirect_to redirect_path
        return
      else
        organization = Organization.find_by(id: id)
        set_organization(organization)
        @organization = current_organization
      end
    end
  end
end

organization_set? current_membership member? are all concerns that are set with each request, while can_view_program?, Membership.current_member_check(id).exists? are authorization checks on the model record.

This is just some of the checks, but the basic idea that is used.

1

There are 1 best solutions below

4
mechnicov On

Looks like your restrict_user_by_role make few things (non SRP). It should only check authorization rule and redirect if it fails. It shouldn't set instance variables. If before filter redirect somewhere, main action is not executed

To simplify your code make 3 checks: presence of current user, presence of current organization, ownership of current organization by current user. If one of these conditions is false — redirect user

def restrict_user_by_role
  if current_user.nil? || current_organization.nil? || !current_organization.owners.include?(current_user)
    flash[:warning] = t("restricted_roles")
    redirect_to redirect_path
  end
end