From 0281bc2703180bcbb2cdb659405074a4381be5ba Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 15 Oct 2025 18:41:36 +0100 Subject: [PATCH] Add docs for todos-auth-fluent example --- Hummingbird.docc/Examples/ExamplesGuide.md | 12 ++++ .../Examples/OTPAuthenticationExample.md | 4 +- Hummingbird.docc/Examples/TodosAuthExample.md | 56 +++++++++++++++++++ .../AuthenticatorMiddlewareGuide.md | 4 +- .../HummingbirdFluent/HummingbirdFluent.md | 4 ++ .../HummingbirdOTP/HummingbirdOTP.md | 1 + Hummingbird.docc/index.md | 2 +- 7 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 Hummingbird.docc/Examples/ExamplesGuide.md create mode 100644 Hummingbird.docc/Examples/TodosAuthExample.md diff --git a/Hummingbird.docc/Examples/ExamplesGuide.md b/Hummingbird.docc/Examples/ExamplesGuide.md new file mode 100644 index 0000000000..8e59b685e1 --- /dev/null +++ b/Hummingbird.docc/Examples/ExamplesGuide.md @@ -0,0 +1,12 @@ +# Examples + +Documentation for some of the larger example projects in the hummingbird-examples repository. + +The hummingbird project comes with an extensive array of examples in the [hummingbird-examples](https://github.com/hummingbird-project/hummingbird-examples/) repository. These show you how to use many features of the framework, how to implement common web server features and how the framework interacts with other third party products. A number of these examples are quite extensive and deserve a little more documentation. + +## Topics + +### Examples + +- +- diff --git a/Hummingbird.docc/Examples/OTPAuthenticationExample.md b/Hummingbird.docc/Examples/OTPAuthenticationExample.md index d88362621d..28bdcd12ff 100644 --- a/Hummingbird.docc/Examples/OTPAuthenticationExample.md +++ b/Hummingbird.docc/Examples/OTPAuthenticationExample.md @@ -8,12 +8,12 @@ This example starts with a standard username/password login. There is a link to ## Database -`PostgresNIO` and ``PostgresMigrations`` are used in this example to access and store your persistent data. The demo creates two tables and an index. +`PostgresNIO` and ``PostgresMigrations`` are used in this example to access and store your persistent data. The example creates two tables and an index. - Table `users` with columns `id`, `name`, `email`, `passwordHash` - Table `totp` with columns `user_id` and `secret` - Index for `email` in table `users` -You can find the migrations for these in the [Migrations folder](https://github.com/hummingbird-project/hummingbird-examples/tree/main/auth-otp/Sources/App/Migrations). These are added to the migration list in the `buildApplication` function. We need to apply these migrations before the server starts but after the PostgresClient connection manager background process has started. This can be done by calling the ``/PostgresMigrations/DatabaseMigrations/apply(client:groups:logger:dryRun:)`` function inside a closure sent to ``/Hummingbird/Application/beforeServerStarts(perform:)``. +You can find the migrations for these in the [Migrations folder](https://github.com/hummingbird-project/hummingbird-examples/tree/main/auth-otp/Sources/App/Migrations). These are added to the migration list in the `buildApplication` function. We need to apply these migrations before the server starts but after the PostgresClient connection manager background process has started. This can be done by calling the ``/PostgresMigrations/DatabaseMigrations/apply(client:groups:logger:dryRun:)`` function inside a closure sent to ``/Hummingbird/Application/beforeServerStarts(perform:)``. The first time you run this example you should run it with the `--migrate` parameter to perform the migrations. On top of the two tables created, the example uses the postgres driver ``/HummingbirdPostgres/PostgresPersistDriver`` for the persist framework to store session keys. You will find out more about the persist framework at and there is a guide to the migration support in . diff --git a/Hummingbird.docc/Examples/TodosAuthExample.md b/Hummingbird.docc/Examples/TodosAuthExample.md new file mode 100644 index 0000000000..c9c8c43074 --- /dev/null +++ b/Hummingbird.docc/Examples/TodosAuthExample.md @@ -0,0 +1,56 @@ +# Todos with Authentication Example + +Example combining Authentication with CRUD operations using fluent-kit + +> The source code for this example can be found [here](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent) + +This example starts with a standard username/password login. There is a link to a signup screen where you can enter your name, email and password. When you return to the login screen you can use your email and password to access the main page. On the main page is a text box and a "Add Todo" button. Whenever the button is pressed the contents of the text box is added as a Todo, which is then displayed in the list above. Each Todo can then be flagged as complete or deleted. + +## Database + +The example uses an SQLite database stored in a file. It then uses [Fluent](https://github.com/Vapor/fluent-kit) to interact with that database. Fluent is a database ORM developed by the Vapor team. While Vapor is also a web framework, the Fluent ORM works with any web framework including Hummingbird. We have built a supporting package ``HummingbirdFluent`` that helps integrate Fluent into Hummingbird projects. + +This example creates two tables +- Table `users` with fields `id`, `name`, `email`, `password` +- Table `todos` with fields `id`, `title`, `owner_id`, `completed` and `url` + +The migrations to create these can be found in the [Migrations folder](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent/Sources/App/Migrations). The first time you run this example you should run it with the `--migrate` parameter to perform the database migrations. + +## Walkthrough + +The example has three controllers +- [`UserController`](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent/Sources/App/Controllers/UserController.swift): API for creating, login and logout of users. +- [`TodoController`](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent/Sources/App/Controllers/TodoController.swift): API for creating, accessing, updating, listing and deleting Todos. +- [`WebController`](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent/Sources/App/Controllers/WebController.swift): Provides dynamically generated webpages. + +## Authentication + +For authentication purposes the example uses ``/HummingbirdBasicAuth/BasicAuthenticator`` to provide a standard username/password login and ``/HummingbirdAuth/SessionAuthenticator`` for authenticating based off a session id. Both of these require a repository type that defines how to access a user based off either a username or session identifier. The example contains a [`UserRepository`](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent/Sources/App/Repositories/UserRepository.swift) that conforms to the relevant protocols (``/HummingbirdBasicAuth/UserPasswordRepository`` and ``/HummingbirdAuth/UserSessionRepository``) needed for it to be used with these authenticator middleware. + +To use the `SessionAuthenticator` we also need to add the ``/HummingbirdAuth/SessionMiddleware``. This extracts session id from the request and responds with `set-cookie` headers if the session needs updated. The session middleware converts the session id into the data associated with the session, in this case a user id. This id is then converted by the authenticator middleware into a `User`. + +## UserController + +The `UserController` has four endpoints +- `POST /api/users`: Creates a new user. This is only used in tests as user creation is done using Form POST. +- `POST /api/users/login`: Creates a session for the user. The user is provided by the `BasicAuthenticator` middleware. Again this is only used in tests. +- `POST /api/users/logout`: Clears the session for the current user. The user is provided by the `SessionAuthenticator` middleware. +- `GET /api/user`: Returns the ID of the currently logged in user. Again the user is provided by the `SessionAuthenticator` middleware. + +## TodoController + +The `TodoController` provides the API for the CRUD operations to create, read, update and delete todos. The operations are all done using the Fluent ORM. All endpoints include the `SessionAuthenticator` middleware. The endpoints are all inside a group which transforms the application `RequestContext` [`AppRequestContext`](https://github.com/hummingbird-project/hummingbird-examples/blob/main/todos-auth-fluent/Sources/App/RequestContext.swift) into a new [`TodoContext`](https://github.com/hummingbird-project/hummingbird-examples/blob/4db5c2d840eb93aba19737e9e080f6f293683423/todos-auth-fluent/Sources/App/Controllers/TodoController.swift#L25) which requires an Identity (logged in user). If the context doesn't have an identity then the transformation throws an HTTP unauthorized error. Now all routes using this `TodoContext` are guaranteed to have a logged in user. + +## WebController + +The `WebController` uses ``Mustache`` to render HTML. The mustache template library is loaded in `buildApplication` and passed to the `WebController` on creation. The login, signup, error and home pages are generated using mustache temlates. The templates can be found in a subfolder of the [Resources](https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-auth-fluent/Sources/App/Resources/templates) folder. + +The `WebController` has six endpoints +- `GET /login`: Login webpage. +- `POST /login`: Performs login using HTML form POST. +- `GET /signup`: Sign up webpage +- `POST /signup`: Creates a new user using HTML form POST. +- `GET /`: Home page displaying todo list. This route has the additional `SessionAuthenticator` and `RedirectMiddleware` applied to it. + +The `WebController` also includes a couple of additional middleware. A [`RedirectMiddleware`](https://github.com/hummingbird-project/hummingbird-examples/blob/4db5c2d840eb93aba19737e9e080f6f293683423/todos-auth-fluent/Sources/App/Controllers/WebController.swift#L22) which will return a redirect response to the login page if the user tries to access the home page while not authenticated and an [`ErrorMiddleware`](https://github.com/hummingbird-project/hummingbird-examples/blob/main/todos-auth-fluent/Sources/App/Middleware/ErrorPageMiddleware.swift) that returns a web page displaying any errors caught while accessing any of the web pages. + diff --git a/Hummingbird.docc/HummingbirdAuth/AuthenticatorMiddlewareGuide.md b/Hummingbird.docc/HummingbirdAuth/AuthenticatorMiddlewareGuide.md index 6e1d5570dc..74418df84b 100644 --- a/Hummingbird.docc/HummingbirdAuth/AuthenticatorMiddlewareGuide.md +++ b/Hummingbird.docc/HummingbirdAuth/AuthenticatorMiddlewareGuide.md @@ -69,4 +69,6 @@ router.addMiddleware { - ``HummingbirdAuth/AuthenticatorMiddleware`` - ``HummingbirdAuth/AuthRequestContext`` -- ``HummingbirdAuth/IsAuthenticatedMiddleware`` \ No newline at end of file +- ``HummingbirdAuth/IsAuthenticatedMiddleware`` +- +- \ No newline at end of file diff --git a/Hummingbird.docc/HummingbirdFluent/HummingbirdFluent.md b/Hummingbird.docc/HummingbirdFluent/HummingbirdFluent.md index a3a0e46dc0..9af4eb351e 100644 --- a/Hummingbird.docc/HummingbirdFluent/HummingbirdFluent.md +++ b/Hummingbird.docc/HummingbirdFluent/HummingbirdFluent.md @@ -69,3 +69,7 @@ For more information: ### Storage - ``FluentPersistDriver`` + +## See Also + +- \ No newline at end of file diff --git a/Hummingbird.docc/HummingbirdOTP/HummingbirdOTP.md b/Hummingbird.docc/HummingbirdOTP/HummingbirdOTP.md index 2f1b1bdac7..99fd508c75 100644 --- a/Hummingbird.docc/HummingbirdOTP/HummingbirdOTP.md +++ b/Hummingbird.docc/HummingbirdOTP/HummingbirdOTP.md @@ -18,3 +18,4 @@ One time passwords - ``Hummingbird`` - ``HummingbirdAuth`` +- diff --git a/Hummingbird.docc/index.md b/Hummingbird.docc/index.md index 93dc638980..04ed63a6dc 100644 --- a/Hummingbird.docc/index.md +++ b/Hummingbird.docc/index.md @@ -79,7 +79,7 @@ Below is a list of guides and tutorials to help you get started with building yo ### Examples -- +- ### Reference Documentation