0

Right now I'm making a website and I need to implement this functionality a user type Client belongs to a Company, so when it logs in, the Client should see a view regarding that company, I'm not sure how to handle this because he should see the company route ID, right now for example if the user is an Admin type I created a Namespace for it but that's because every admin can see the same info, the Client type should only see the company where he belongs, I'm not sure what should I be using, right now my route for that is defined like this

resources :companies, param: :slug, only: :show do
  resources :clients
end

That works but for example if the Client belongs to the company amazon and he logs in, he's redirected to companies/amazon/clients, and it displays the proper info but if he changes the route for another for example companies/adaddasdas/clients, it stills shows the page as well with the amazon info, that just happens if I'm trying to access the resources inside companies like :clients in this example, if I try to access the resource companies itself companies/amazon if i put something different it does not work

What I want to know is how do you guys handle that, when an user model belongs to another but given the Id(in my case slug) of the other model, the user should be able to see just the info of that Id and as well se other resources for that Model. Should I use that or a namespace, or custom layout, I'm not sure how to solve it and there's no documentation regarding that topic.

jean182
  • 3,213
  • 2
  • 16
  • 27
  • 1
    It's not a big deal. Just create a before action in your client controller that compares the client parent company (you grab the Id of the client from the params, then retrieve the Client record with a find method, and then climb to the parent) to the company that is passed in the url (you grab the slug from params, then try to find a company with that same slug with a find by methid, and then compare to what you have just found from the client id) – Maxence Oct 02 '18 at 03:43
  • Actually when I have routes with more than one param I do this check too. On top of other checks. – Maxence Oct 02 '18 at 03:45

1 Answers1

1

As explained in the comments you can do a basic ownership check in your client controller:

class Client < ApplicationController

before_action :check_client_owner

private 

def check_client_owner
    unless params[:slug].to_s == Client.find(params[:id]).company.slug.to_s
      redirect_to root_path
    end
end

end

Also you can first make a check to know if the client exists. In case someone type a client ID that doesn't exist, it will trigger an error on the previous check (Client.find(params[:id]) will not succeed).

Maxence
  • 2,029
  • 4
  • 18
  • 37
  • Thanks that solved my issue, at the end I ended up giving up with slugs, I did it with just the id but can you tell me why I receive this params "client/clients", "action"=>"index", "company_id"=>"1"} permitted: false> I mean the company_id is a string so I needed to do params[:company_id].to_i Why I'm receiving that like a string? – jean182 Oct 02 '18 at 22:39
  • I am not too sure about your question. But basically all params are strings. They are taken directly from the querystring / URL and appear as such. My `to_s` was probably redundant, just an habit. If you explicitly want an integer so yes `to_i` is useful, provided you are sure your id is a string with a number inside. if it is a pure string (that doesn't look like a number) you will get 0 : `"hello123".to_i` return `0` in console. – Maxence Oct 03 '18 at 08:03