Skip to content

Commit

Permalink
Updated README
Browse files Browse the repository at this point in the history
  • Loading branch information
essenciary committed Jul 4, 2021
1 parent 04cbaed commit 3dc8a2d
Showing 1 changed file with 71 additions and 49 deletions.
120 changes: 71 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://genieframework.github.io/Genie.jl/dev/tutorials/4-1--Developing_MVC_Web_Apps.html>.

### 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
Expand All @@ -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.

---

Expand All @@ -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 <https://genieframework.github.io/Genie.jl/dev/tutorials/4-1--Developing_MVC_Web_Apps.html#Connecting-to-the-database>.

---

### 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
<div class="row align-items-center">
<div class="col col-12 text-center">
<% if ! authenticated() %>
<a href="/login" class="btn btn-light btn-lg" style="color: #fff;">Login</a>
<% end %>
</div>
</div>
```

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)
```

2 comments on commit 3dc8a2d

@essenciary
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/40227

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.0.0 -m "<description of version>" 3dc8a2db6d6af3176570b1bea7dbda3a08748bd6
git push origin v1.0.0

Please sign in to comment.