Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic authorizations with POSTed parameter are messy #14

Open
gakuzzzz opened this issue Oct 3, 2012 · 7 comments
Open

Dynamic authorizations with POSTed parameter are messy #14

gakuzzzz opened this issue Oct 3, 2012 · 7 comments

Comments

@gakuzzzz
Copy link
Member

gakuzzzz commented Oct 3, 2012

An authorization with the action method's parameters is easy. see also https://github.com/t2v/play20-auth/wiki/Advanced-usage:-----request-parameters

But dynamic authorizations with POSTed parameter are messy.

I want to provide the easy way to do it.

@soldiermoth
Copy link

+1

@sagarsg
Copy link

sagarsg commented Jun 23, 2014

Hi,

I am trying to get the dynamic authorizations working. Is there a easy way to do this.
I would like to get the Permission from the database instead of hardcoding it.

Now,
def home = AsyncStack(AuthorityKey -> Administrator) { implicit request =>

Instead, can we do something like below -
def home = AsyncStack(AuthorityKey -> getPermission(user)) { implicit request =>

Thanks in advance.

@gakuzzzz
Copy link
Member Author

Hi,

@vogwheels, Sorry I cannot grasp your problem yet.

Is your home action's Authority changed by access user?

you can use getPermission method in authorize implementation of AuthConfig.
If all actions use same authority always, you can define the Authority type as Unit

trait AuthConfigImpl extends AuthConfig {
  type Authority = Unit
  def authorize(user: User, authority: Authority): Future[Boolean] = Future.successful {
    val permission = getPermission(user)
    permission.isAdministrator
  }  
}
def home = AsyncStack(AuthorityKey -> ()) { implicit request =>

@samco
Copy link

samco commented Feb 26, 2015

I solved the POST parameter dynamic authorization problem with a trait extending StackableController.

The trait looks something like this:

trait PostParameterAuthElement
    extends StackableController
    with AuthConfigImpl {
    self: AuthElement =>

    lazy val idForm = Form(
        single(
            "id" -> longNumber
        )
    )

    override def proceed[A](req: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Future[Result]): Future[Result] = {
        implicit val request = req
        idForm.bindFromRequest.fold(
            formWithErrors => {
                Future.successful(BadRequest("ID missing"))
            },
            id => {
                Model.findById(iId) match {
                    case Some(model) if (model.ownerId == loggedIn.id) => super.proceed(request)(f)
                    case Some(model) => authorizationFailed(request)
                    case None => Future.successful(NotFound)
                }
            }
        )
  }
}

So then the controller doesn't have the authorisation stuff in it that the example at https://github.com/t2v/play2-auth#changing-the-authorization-depending-on-the-request-parameters has.

I would need to implement a new trait for each authorisation rule and each model type. I'm pretty new to Scala so I don't know if there's a way for play2 to make this easier.

@gakuzzzz
Copy link
Member Author

gakuzzzz commented Mar 6, 2015

Hi all,

Now, I try to create a way of Dynamic authorizations with POSTed parameter #119

Using #119 makes is enable as follows

object FooController extends Controller with AuthConfigImpl with AuthElement {

  type Authority = Long
  def authorize(user: User, authority: Authority) = {
    Future.successful(user.id == authority)
  }

  def postAuth = StackAction(AuthorityFactoryKey[AnyContent] -> postedAuthority) { implicit req =>
    ... you can define any action code.
  }

  private lazy val idForm = Form {
    "id" -> longNumber
  }

  private lazy val postedAuthority: Request[AnyContent] => Either[Result, Authority] = { implicit req =>
    idForm.bindFromRequest.fold(Left.apply, Right.apply)
      .left.map(_ => BadRequest("ID missing"))
      .right.flatMap { id =>
        Model.findById(id).map(_.ownerId).toRight(NotFound)
      }
    }
  }

}

What do you say?

@samco
Copy link

samco commented Mar 6, 2015

This looks good but I am going away for a couple of weeks so won't be able to try it for a while. I will let you know how my testing goes when I get back.

@samco
Copy link

samco commented Mar 30, 2015

I have had a chance to give this a run, it works well for my purposes. Thanks for your work on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants