authorize state transitions

Does anybody know how to authorize state transitions? I'm using
state_machine in my rails app to define the state of an Article
(published or unpublished). I'm also using declarative_authorization to
determine the authorizations a user has. But how do I authorize a state
transistion (determine if the user has the right to publish the
Article)?

Kind regards,

H.J. Blok

If you are using state_machine, this kind of thing is pretty
straightforward. What you want to do is define a before_transition
rule that calls a method in your model (I recommend a private method,
for this, with a name ending in ?). Have that method return true when
you want to allow the transition, or false when you don't.
State_machine will handle the rest and set an error message on your
model object.

You can also set your own errors, in the method that the
before_transition calls, when you are going to return false.

-Brian

Brian, thanks for your answer. It works.

I don't know why it didn't work the first time I was trying to authorize
the state transition. Maybe I've overlooked something.

Thanks,

HJ

Brian Hughes wrote:

Hey,

First of all - @Brian - I apologise for double sending this to you..
since can only reply to author, now Cc-ing the group email as well..

Ok, question as follows:
I'm using Restful_Authentication plugin (generated authenticated user
sessions with --include-activation and --aasm) and the
Declarative_Authorization plugin..

I'm quite a beginner, so my question might be very basic..
wanted to know if there's a way to authorize AASM's trasitions?
To begin with, how should I handle authorization for the state
transitions (or aasm_event s) of AasmRoles of User
(:active, :passive, :pending, :suspended, :unsuspended, :deleted)? and
where should this be done exactly?

Thank you :slight_smile:

tino.

Unfortunately, as you can tell from my original message, I'm a state_machine user, not an aasm user. Nor have I ever used Restful_Authentication in my of my Rails apps. So, I'm not sure I can be of any help with your problem. While aasm and state_machine both allow you to add finite state machine functionality to a Ruby class, they do so in fairly different ways. What I know about state_machine doesn't transfer over to aasm...

-Brian

Thank you Brian..

I understand :slight_smile:
Will keep trying or try other alternatives as well..
Still hoping to get some more suggestions here..

tino.

I can share my solution, maybe you can find the corresponding methods
for AASM...

For example when you have an Article, you define a before_transition
within the state definition. The before_transition uses the method
is_authorized_for? to determine if the user is authorized for the
transition.

class Article < ActiveRecord::Base
  state_machine :initial => :unpublished do
    before_transition all => all do |article, transition|
      article.is_authorized_for?(transition)
    end
    event :publish do
      transition :unpublished => :published
    end
    event :unpublish do
      transition :published => :unpublished
    end
    state :unpublished
    state :published
  end

  ...

  # Method to check if user is authorized to do state transition
  def is_authorized_for?(transition)
    permitted_to?(transition.event.to_sym)
  end
end

In your authorization_rules.rb you will have something like this:

authorization do
  role :admin do
    has_permission_on [:articles], :to => [:publish, :unpublish]
  end
end

When a authenticated user tries to alter the state of an unpublished
Article, the is_authorized_for? will only return true if the user has
the :admin role.

Hope this helps...

TINODEV wrote:

Hey,

First of all - @Brian - I apologise for double sending this to you..
since can only reply to author, now Cc-ing the group email as well..

Ok, question as follows:
I'm using Restful_Authentication plugin (generated authenticated user
sessions with --include-activation and --aasm) and the
Declarative_Authorization plugin..

A little off topic, but...get rid of restful_authentication as soon as
possible! It fills your User model with unmaintainable generated code,
and should never ever be used now that better alternatives exist. I use
Authlogic; others seem to like Devise.

Best,

Ok..

@ Marnen - At the time when looking through Authentication Plugins
didn't get the impression most developers rather use different plugins
(other thena Restful_Auth) nowadays..
on the other hand - I didn't quite ask and tried to figure it all by
myself while feeling a "newbie" (till two days ago I think) so I think
now is a good time to ask and receive answers..

HJ - Thanks you! though currently using aasm, your description of how
to use state_machine plugin was very helpful to my basic
understanding..

Now following also Marnen's remark (thanks again Marnen), I'm
wondering.. should I replace the plugins I'm using?
Restful_Authentication and AASM included?

Can you guys recommend me of plugins you find better and better-how?
(no offense to other plugins of course)? also, are they Rails 3
compatible (though currentl using InstantRails with Rails 2.3.5, but
considering to move to Rails 3 when it's s table version..)

Thanks again :slight_smile:

Best,

tino.

I can share my solution, maybe you can find the corresponding methods
for AASM...

For example when you have an Article, you define a before_transition
within the state definition. The before_transition uses the method
is_authorized_for? to determine if the user is authorized for the
transition.

class Article < ActiveRecord::Base
  state_machine :initial => :unpublished do
    before_transition all => all do |article, transition|
      article.is_authorized_for?(transition)
    end
    event :publish do
      transition :unpublished => :published
    end
    event :unpublish do
      transition :published => :unpublished
    end
    state :unpublished
    state :published
  end

  ...

  # Method to check if user is authorized to do state transition
  def is_authorized_for?(transition)
    permitted_to?(transition.event.to_sym)
  end
end

In your authorization_rules.rb you will have something like this:

authorization do
  role :admin do
    has_permission_on [:articles], :to => [:publish, :unpublish]
  end
end

When a authenticated user tries to alter the state of an unpublished
Article, the is_authorized_for? will only return true if the user has
the :admin role.

Hope this helps...