0
votes

I'm developing an app where I want to limit the access to assets. I have created additional folder

secret/

which holds the data. Then I created route

/media/secret/*file     controllers.Media.file(file)

and controller Media

public class Media extends Controller
{
@Authenticate
public Result file(String file)
{
    String path = /home/foo/secretpath/
    File f = new File(path, file);
    if(!f.exists())
    {
        return notFound();
    }

    return ok(f, true);
}

This kinda works, only problem is there is no Etag or cache control. Checking the Assets.scala implementation (https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/controllers/Assets.scala) everything is already developed here. My question is

  1. Should I write additional code to implement Etag and Cache-Control? If yes, how? I cannot read scala
  2. If there is a way to use Assets class, how to make it work? Returning Action will not trigger @Authenticate so I can validate if its ok or not.
1

1 Answers

2
votes

You can use action composition, see: https://www.playframework.com/documentation/2.2.x/ScalaActionsComposition

In a nutshell this should solve your problem:

(1) New action

def OnlyAuthenticated[A](action: Action[A]) = Action.async(action.parser) { request =>
    request.session.get("username") match {
        case Some(username) =>
            User.findByUsername(username) match {
                case Some(user) =>
                    action(request)
                case _ =>
                    Future.successful(Forbidden(views.html.defaultpages.unauthorized.render()))
            }
        case _ =>
            Future.successful(Redirect(routes.Application.login(request.path)))
    }
}

(2) Controller action

def privateAsset(file:String) = OnlyAuthenticated{
    Assets.at(s"/private", file)
}

(3) Route

GET     /private/*file      controllers.Application.privateAsset(file)