From 3dc8a2db6d6af3176570b1bea7dbda3a08748bd6 Mon Sep 17 00:00:00 2001 From: Adrian Salceanu Date: Sun, 4 Jul 2021 22:34:09 +0200 Subject: [PATCH] Updated README --- README.md | 120 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index f82461e..12f9e61 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,35 @@ Authentication plugin for `Genie.jl` ## Installation -Add the `GenieAuthentication` plugin to your Genie app dependencies. +The `GenieAuthentication` package is an authentication plugin for `Genie.jl`, the highly productive Julia web framework. +As such, it requires installation within the environment of a `Genie.jl` MVC application, allowing the plugin to install +its files (which include models, controllers, database migrations, plugins, and other files). -First load the Genie app's environment: +### Load your `Genie.jl` app + +First load the `Genie.jl` application, for example using ```bash -$ cd /path/to/your/genie_app +$> cd /path/to/your/genie_app -$ bin/repl +$> ./bin/repl ``` +Alternatively, you can create a new `Genie.jl` MVC application (`SearchLight.jl` ORM support is required in order to store +the user accounts into the database). If you are not sure how to do that, please follow the documentation for `Genie.jl`, +for example at . + +### Add the plugin + Next, add the plugin: ```julia julia> ] -(MyGenieApp) pkg> add https://github.com/GenieFramework/GenieAuthentication.jl#master +(MyGenieApp) pkg> add GenieAuthentication ``` -Once added, we can use it to add its files to the Genie app (required only upon installation): +Once added, we can use it to add its files to the `Genie.jl` app (required only upon installation): ```julia julia> using GenieAuthentication @@ -34,12 +44,13 @@ The above command will set up the plugin's files within your Genie app (will pot ## Usage -The main plugin file should now be found in the `plugins/` folder within your Genie app. It sets up configuration and registers routes. +The main plugin file should now be found in the `plugins/` folder within your `Genie.jl` app. It sets up configuration and registers routes. --- **HEADS UP** -Make sure to comment out the `/register` routes if you don't want to provide user registration features. Otherwise you run the risk of allowing random users to create accounts and expose your application! +Make sure to uncomment out the `/register` routes in `plugins/genie_authentication.jl` if you want to provide user registration features. +They are disabled by default in order to eliminate the risk of accidentally allowing random users to create accounts and expose your application. --- @@ -58,101 +69,112 @@ This will create the necessary table. --- **HEADS UP** -If your app wasn't already set up to work with SearchLight, you need to add SearchLight support first. Please check the Genie documentation on how to do that. +If your app wasn't already set up to work with `SearchLight.jl`, you need to add `SearchLight.jl` support first. +Please check the `Genie.jl` documentation on how to do that, for example at . --- ### Set up the successful login route -Upon a successful login, the plugin will redirect the user to the `:get_home` route. Please make sure you define the route and name it accordingly, ex: +Upon a successful login, the plugin will redirect the user to the `:success` route, which invokes `AuthenticationController.success`. -```julia -route("/admin", AdminController.index, named = :get_home) -``` +--- -If for any reason you can't define the route, you can alternatively edit the code in the `login()` function in `app/resources/authentication/AuthenticationController.jl` and change `:get_home` with your desired route. Editing the controller, however, is not recommended, as future updates might overwrite your changes. +### Enforcing authentication ---- +Now that we have a functional authentication system, there are two ways of enforcing authentication. -### Forcing authentication +#### `@authenticate!` -Now that we have a functional authentication system, we can use a Genie controller `before` hook to force authentication. Add this to the controller files which you want placed behind auth: +The `@authenticate!` macro will enforce authentication - meaning that it will check if a user is authenticated, and if not, +it will automatically throw an `ExceptionalResponse` `Exception` and force a redirect to the `:show_login` route which displays the login form. -```julia -before() = authenticated() || throw(ExceptionalResponse(redirect(:show_login))) -``` +We can use this anywhere in our route handling code, for example within routes: -The `before` hook will automatically be invoked by `Genie.Router` before actually executing the route handler. By throwing an `ExceptionalResponse` `Exception` we force a redirect to the `:show_login` route which displays the login form. +```julia +# routes.jl +using GenieAuthentication -#### Example +route("/protected") do; @authenticated! + # this code is only accessible for authenticated users +end +``` -This is how we would limit access to a full module by forcing authentication: +Or within handler functions inside controllers: ```julia -module AdminController - -using GenieAuthentication, Genie.Renderer, Genie.Exceptions, Genie.Renderer.Html +# routes.jl +route("/protected", ProtectedController.secret) +``` -before() = authenticated() || throw(ExceptionalResponse(redirect(:show_login))) +```julia +# ProtectedController.jl +using GenieAuthentication -function index() - h1("Welcome Admin") |> html -end +function secret() + @authenticated! + # this code is only accessible for authenticated users end ``` --- **HEADS UP** -If you're throwing an `ExceptionalResponse` as the result of the failed authentication, make sure to also be `using Genie.Exceptions`. +If you're throwing an `ExceptionalResponse` as the result of the failed authentication, make sure to also be `using Genie.Exceptions`. --- -#### Example +#### `authenticated()` -The plugin can also be used within functions. +In addition to the imperative style of the `@authenticated!` macro, we can also use the `authenticated()` function which +returns a `bool` indicated if a user is currently authenticated. -```julia -module AdminController +It is especially used for adding dynamic UI elements based on the state of the authentication: -using GenieAuthentication, Genie.Renderer, Genie.Exceptions, Genie.Renderer.Html +```html +
+
+ <% if ! authenticated() %> + Login + <% end %> +
+
+``` + +We can also use it to mimic the behaviour of `@authenticated!`: + +```julia +using GenieAuthentication # This function _can not_ be accessed without authentication function index() authenticated() || throw(ExceptionalResponse(redirect(:show_login))) - h1("Welcome Admin") |> html -end - -# This function _can_ be accessed without authentication -function terms_and_conditions() - # content here -end + h1("Welcome Admin") |> html end ``` -Or even: +Or to perform custom actions: ```julia using GenieAuthentication -route("/you/shant/pass") do +route("/you/shant/pass") do authenticated() || return "Can't touch this!" - + "You're welcome!" end ``` ---- +--- ### Adding a user -You can create a user at the REPL like this (using stronger usernames and passwords though 🙈): +You can create a user at the REPL like this (using stronger usernames and passwords though 🙈): ```julia julia> u = User(email = "admin@admin", name = "Admin", password = Users.hash_password("admin"), username = "admin") julia> save!(u) ``` -