This felt like a better way of defining public routes as it gave more control. Adding REGEX_PATHS
alongside PUBLIC_PATHS
allowed for a more flexible and fine grained auth check.
Using the following code in the public_path
method worked really well.
private def public_path?(path)
return true if PUBLIC_PATHS.includes?(path)
REGEX_PATHS.any? { |word| path =~ word }
end
We are checking if any of the PUBLIC_PATHS
or REGEX_PATHS
matches the path
from the context.request
. If there is a match this will return true and move on to the next middleware.
Here is the entire authenticate.cr file for you to see what the PUBLIC_PATHS
and REGEX_PATHS
definition looks like.
class HTTP::Server::Context
property current_user : User?
end
class Authenticate < Amber::Pipe::Base
PUBLIC_PATHS = ["/", "/posts", "/signin", "/session", "/signup", "/registration"]
REGEX_PATHS = [
/^\/posts\/([0-9]+)$/,
]
def call(context)
user_id = context.session["user_id"]?
if user = User.find user_id
context.current_user = user
call_next(context)
else
return call_next(context) if public_path?(context.request.path)
context.flash[:warning] = "Please Sign In"
context.response.headers.add "Location", "/signin"
context.response.status_code = 302
end
end
private def public_path?(path)
return true if PUBLIC_PATHS.includes?(path)
REGEX_PATHS.any? { |word| path =~ word }
end
end
I hope this has helped you in Protecting your routes in the Amber framework. And make sure you come and join us in the Amber gitter channel.