I have a User class with a field called admin which is a boolean that determines if the user is or is not an administrator. I want to make it impossible for the last administrator for an account to be removed from the system. I need to protect against this both when deleting a user and when editing a user as you can revoke a user''s administrator privileges via a form. User belongs_to :account. Account has_many :Users I was thinking that the best way to do this would involve either before_update and before_destroy or a validation. I think I know how to write the before_delete as that just involves knowing which user you are going to delete and checking if its account has more than one administrator. I am unsure how to write before_update as that requires not only knowing which user you are going to update but also if the updated info would make that user no longer have admin status. I have no idea where to start for the validation if I was to go that route for similar reasons as the before_update. Do any of you have any examples of code that prevents the deletion/update of an object based on a particular field''s value? Thank you, Matthew Margolis blog.mattmargolis.net
I do this: before_destroy :dont_kill_uberadmin def dont_kill_uberadmin raise "Cannot do this" if self.name == "?ber" end got it from the agile book I believe ------------- Timothy Johnson Interactive Director Found Interactive www.foundinteractive.com h: 540-908-4801 c: 540-810-3637 On Jun 23, 2006, at 2:07 PM, Matthew Margolis wrote:> I have a User class with a field called admin which is a boolean that > determines if the user is or is not an administrator. I want to make > it impossible for the last administrator for an account to be removed > from the system. I need to protect against this both when deleting a > user and when editing a user as you can revoke a user''s administrator > privileges via a form. > > User belongs_to :account. > Account has_many :Users > > I was thinking that the best way to do this would involve either > before_update and before_destroy or a validation. I think I know how > to write the before_delete as that just involves knowing which user > you are going to delete and checking if its account has more than one > administrator. I am unsure how to write before_update as that > requires not only knowing which user you are going to update but also > if the updated info would make that user no longer have admin status. > I have no idea where to start for the validation if I was to go that > route for similar reasons as the before_update. > > Do any of you have any examples of code that prevents the > deletion/update of an object based on a particular field''s value? > > > Thank you, > Matthew Margolis > blog.mattmargolis.net > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Matthew Margolis wrote:> Do any of you have any examples of code that prevents the > deletion/update of an object based on a particular field''s value?I''ve done this, but not in the model. It''s pretty easy form the controller. def delete_user user = User.find(params[:id]) if user && user.admin? && User.count(:conditions => ''admin = 1'') == 1 flash[:notice] = "Can''t delete last admin!" else user.destroy flash[:notice] = "User was deleted." end redirect_to :action => ''list'' end Doing it from the model might a bit trickier. -- Posted via http://www.ruby-forum.com/.
Not so, my example was in the model, but it can be done multiple ways I guess. -- Timothy Johnson On Jun 23, 2006, at 2:18 PM, Alex Wayne wrote:> Matthew Margolis wrote: >> Do any of you have any examples of code that prevents the >> deletion/update of an object based on a particular field''s value? > > I''ve done this, but not in the model. It''s pretty easy form the > controller. > > def delete_user > user = User.find(params[:id]) > if user && user.admin? && User.count(:conditions => ''admin = 1'') == 1 > flash[:notice] = "Can''t delete last admin!" > else > user.destroy > flash[:notice] = "User was deleted." > end > redirect_to :action => ''list'' > end > > Doing it from the model might a bit trickier. > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Timothy Johnson wrote:> Not so, my example was in the model, but it can be done multiple ways > I guess. > > -- > Timothy Johnson > > > On Jun 23, 2006, at 2:18 PM, Alex Wayne wrote: > >> Matthew Margolis wrote: >>> Do any of you have any examples of code that prevents the >>> deletion/update of an object based on a particular field''s value? >> >> I''ve done this, but not in the model. It''s pretty easy form the >> controller. >> >> def delete_user >> user = User.find(params[:id]) >> if user && user.admin? && User.count(:conditions => ''admin = 1'') == 1 >> flash[:notice] = "Can''t delete last admin!" >> else >> user.destroy >> flash[:notice] = "User was deleted." >> end >> redirect_to :action => ''list'' >> end >> >> Doing it from the model might a bit trickier. >> >> -- >> Posted via http://www.ruby-forum.com/. >> _______________________________________________ >> Rails mailing list >> Rails@lists.rubyonrails.org >> http://lists.rubyonrails.org/mailman/listinfo/rails > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/railsTimothy, I am familiar with that approach but unfortunately I have multiple accounts each with its own set of administrators so this will not work for me. Alex''s solution works fine for my needs for delete, I could write something similar for update. I was hoping to get this done in the model but controller code should be fine here. I am definitely still open to a way to do this in the model if anyone has any ideas. Thank you, Matthew Margolis blog.mattmargolis.net
On 6/23/06, Matthew Margolis <mrmargolis@wisc.edu> wrote:> I am definitely still open to a way to do this in the model if anyone > has any ideas.You can still use the basic before_destroy hook and call a method. I would also create a method that returns the number (or a hash or something) of the admins on an account. This should probably be a class method. You can then utilize that method in the before_destroy hook to determine if there are additional admins. Sorry, I''m thinking Java today, but psuedocode would look like: before_destroy :dont_delete_last_admin def dont_delete_last_admin raise "Unable to delete final admin on account" if self.count_admins <= 1 end def self.count_admins ''utilize User collection to search for admins, return count end -Curtis
Michael Greenly
2006-Jun-23 22:55 UTC
[Rails] Re: Re: Don''t un-admin the last administrator
Curtis Spendlove wrote:> On 6/23/06, Matthew Margolis <mrmargolis@wisc.edu> wrote: >> I am definitely still open to a way to do this in the model if anyone >> has any ideas.My approach to this has always been that an admin can not remove them self from the admin role and a user can not delete them self. With this approach the last user can not be deleted and the last user must be the last admin. I''ve also always handled this in the controller. To me a model shouldn''t have to know about anything outside it''s domain and session information is outside the domain of the User model. (to me) from: http://st-www.cs.uiuc.edu/users/smarch/st-docs/mvc.html > The controller interprets the mouse and keyboard inputs from the user, > commanding the model and/or the view to change as appropriate. In my case my controller (as described above) is deciding when it''s appropriate to act on the users input -- Posted via http://www.ruby-forum.com/.
Matthew Margolis
2006-Jun-24 03:29 UTC
[Rails] Re: Re: Don''t un-admin the last administrator
Michael Greenly wrote:> Curtis Spendlove wrote: > >> On 6/23/06, Matthew Margolis <mrmargolis@wisc.edu> wrote: >> >>> I am definitely still open to a way to do this in the model if anyone >>> has any ideas. >>> > > My approach to this has always been that an admin can not remove them > self from the admin role and a user can not delete them self. With this > approach the last user can not be deleted and the last user must be the > last admin. > > I''ve also always handled this in the controller. To me a model > shouldn''t have to know about anything outside it''s domain and session > information is outside the domain of the User model. (to me) > > from: http://st-www.cs.uiuc.edu/users/smarch/st-docs/mvc.html > > > The controller interprets the mouse and keyboard inputs from the > user, > > commanding the model and/or the view to change as appropriate. > > In my case my controller (as described above) is deciding when it''s > appropriate to act on the users input > > >I really like this approach! Thank you so much. Matthew Margolis blog.mattmargolis.net
Justin Forder
2006-Jun-24 10:52 UTC
[Rails] Re: Re: Don''t un-admin the last administrator
Michael Greenly wrote:> Curtis Spendlove wrote: >> On 6/23/06, Matthew Margolis <mrmargolis@wisc.edu> wrote: >>> I am definitely still open to a way to do this in the model if anyone >>> has any ideas. > > My approach to this has always been that an admin can not remove them > self from the admin role and a user can not delete them self. With this > approach the last user can not be deleted and the last user must be the > last admin.If I remember right, Dave Thomas initially chose that approach for the AWDR tutorial, but then realised that if there are two admins, and they are both logged on concurrently, each can delete the other.> I''ve also always handled this in the controller. To me a model > shouldn''t have to know about anything outside it''s domain and session > information is outside the domain of the User model. (to me)I agree. regards Justin
Michael Greenly
2006-Jun-24 13:29 UTC
[Rails] Re: Re: Re: Don''t un-admin the last administrator
> > If I remember right, Dave Thomas initially chose that approach for the > AWDR tutorial, but then realised that if there are two admins, and they > are both logged on concurrently, each can delete the other. >This isn''t an issue. Which ever admin is first will win. The second will no longer have the necessary permissions to remove the first from the role. -- Posted via http://www.ruby-forum.com/.
Justin Forder
2006-Jun-27 06:33 UTC
[Rails] Re: Re: Re: Don''t un-admin the last administrator
Michael Greenly wrote:>> If I remember right, Dave Thomas initially chose that approach for the >> AWDR tutorial, but then realised that if there are two admins, and they >> are both logged on concurrently, each can delete the other. >> > > This isn''t an issue. Which ever admin is first will win. The second > will no longer have the necessary permissions to remove the first from > the role.If you choose to retrieve user/role information from the DB to authorise every HTTP request, then you are right. (To be completely watertight the reading of user/role information would have to be in the same transaction as the authorised action.) If you cache the relevant info in the session, then admins with concurrent sessions can delete each other. In AWDR the admins are the only ones who log in, and authorisation is just based on having a user ID in the session (see section 11.3 in the first edition), so the problem arises. You can read Dave Thomas''s post on the subject here: http://article.gmane.org/gmane.comp.lang.ruby.rails/22094 regards Justin