简体   繁体   中英

Rails3 - Permission Model Before_Save Check?

I have a permission model in my app, that ties (Users, Roles, Projects) together.

What I'm looking to learn how to do is prevent a user for removing himself for their project...

Can you give me feedback on the following?

class Permission < ActiveRecord::Base
.
.
.
  #admin_lock makes sure the user who created the project, is always the admin
  before_save :admin_lock

  def before_save
    #Get the Project Object
    project = Find(self.project_id)
    if project.creator_id == current_user.id
      # SOME HOW ABORT OR SEND BACK Not Allowed?
    else
      #continue, do nothing
    end
  end  

end

Is that look like the right approach?

Also, I'm not sure how to do the following two things above:

  • How to abort prevent the save, and send back an error msg?
  • Get the devise, current_user.id in the model, that doesn't seem possible, so how do Rails gurus do stuff like the above?

Thanks for reading through

How to abort prevent the save, and send back an error msg?

return false during the callback chain tells activemodel to stop (similar to how adding errors to the model during a validation tells it to stop at that point)

self.errors.add_to_base "msg" will add an error to the model, which can then be rendered on the view.

Get the devise, current_user.id in the model, that doesn't seem possible, so how do Rails gurus do stuff like the above?

Models shouldn't really know about things like the current request, if at all possible, you should be locking things down at the controller/action level.

EDIT:

So, the role of controllers is to deal with everything involved in getting the correct information together based on the request, and passing it to the view (which becomes the response). People often say "make your models fat and your controllers skinny", but that could be said of any system that embraces object oriented design -- your logic should be in objects when possible.

That being said, the whole point of controllers is to deal with routing the right things to the right places, and authentication is definitely a concern of routing.

You could easily move the line comparing creator_id to user id in the action, and react based on that.

Now, sometimes you genuinely need that stuff in the model and there is no way around it. That becomes a problem, because you need to fight rails to get it there. One way would be to attr_accessor a current_user field on your model, and pass that in on initialize. Another would be to remove the fields from the params hash that a user is not allowed to change in the action. Neither is really that nice though.

Agreed with Matt that you should try to use the controller for the redirect. The model should have the logic to determine if the redirect is appropriate. Maybe something like

class ProjectsController < ApplicationController
  def update
    redirect_to(projects_url, :alert => "You can't remove yourself from this project.") and return if Role.unauthorized_action?(:update, params[:project])
    @project = Project.find(params[:id])
    if @project.update_attributes(params[:project])
    ...
  end

class Role
  def self.unauthorized_action?(action, params)
    # your logic here
  end

You should check out CanCan for some ideas.

  1. In permission model take one field project_creater as boolean
  2. In project model
     before_create :set_project_ownership \n  def set_project_ownership \n     self.permissions.build(user_id: User.current.id, project_creater: true) \n  end  
  3. In project controller
     before_filter :set_current_user  
  4. In Application controller
     def set_current_user \n  User.current = current_user \nend  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM