6.2 KiB
ManagableUsers
A package providing basic user management when using the Vapor web framework and a PostgreSQL database.
Provides controllers and middleware for authenticating users. This includes web pages for logging in, handling of forgotten password by sending tokens via email, and logging out.
Provides controllers for managing users. This includes administration pages and inviting users via email.
Note: This package uses raw SQL for accessing the database, so there are no Fluent model for users,
but the database is connected using Fluent, so the it can still be used for other items.
Try out
The package contains an executable target SampleApp with a minimal implementation demonstrating the
functionality.
You can try this to asses the functionality provided by this package, or you can use it as a template for starting your own project.
Database
To run SampleApp, a database is needed.
If you don't already have PostgreSQL installed, refer to postgresql.org for options.
There's a SQL script provided for creating the tables needed by SampleApp.
$ psql --file=Resources/Database/Create.sql
For creating a new database named sampleapp, create the tables, and a corresponding user do the following:
$ psql --dbname=postgres --command="CREATE DATABASE sampleapp"
$ psql --dbname=sampleapp --command="CREATE ROLE sampleapp WITH LOGIN PASSWORD 'sampleapp_password'"
$ psql --dbname=sampleapp --file=Resources/Database/Create.sql
$ psql --dbname=sampleapp --command="GRANT CONNECT ON DATABASE sampleapp TO sampleapp"
$ psql --dbname=sampleapp --command="GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO sampleapp"
There's also a script for creating an initial user:
$ psql --dbname=sampleapp --file=Resources/Database/InitialUser.sql --variable=email=someone@example.com
The script will return a password URL for setting the password (assuming that the service runs on https://example.com/, it needs to be changed to the actual host to be usable). The email address is used for logging in, and can also be used for resetting passwords via email if you have email delivery setup.
Running Application
You can run the application with swift run, or from an IDE such as Xcode.
A number of environment variables are needed for proper function.
DATABASE_HOST: Host for the PostgreSQL server, defaults tolocalhostDATABASE_PORT: Port for the PostgreSQL server, defaults to5432DATABASE_NAME: Name of the database, defaults tosampleappDATABASE_USERNAME: Username for accessing the database, defaults tosampleappDATABASE_PASSWORD: Password for accessing the database, defaults tosampleapp_passwordBASE_URL: URL for accessing the web site (e.g.http://localhost:8080)SMTP_HOST,SMTP_PORT,SMTP_ENCRYPTION,SMTP_TIMEOUT,SMTP_USERNAME,SMTP_PASSWORDandSMTP_USE_ESMTP: Configuring email delivery, see the documentation for the SwiftSMTP package for details.LOG_LEVEL: Desired level of logging, defaulting toinfo.
The application will write to the log that it has started and which port it's listening on.
Using application
Use the URL returned from the InitialUser.sql script above in a browser. Make sure to adapt it to the actual setup
(e.g. http://localhost:8080/auth/password/2lG91bumxxvm9Ky7xLy1Nxz2mJoxjRCS with defaults and without a reverse proxy).
A form for setting a password should be provided at that URL. After setting a password, that password and the email
address provided to the InitialUser.sql script can then be used for logging in.
Getting Started
Create a new Vapor project, or reuse an existing one.
Dependencies
Add dependency on managable-users by adding the package to Package.swift as
.package(url: "https://git.carlberg.org/public/manageable-users.git", from: "1.0.0"),
…and adding to the executable target's dependencies as
.product(name: "ManagableUsers", package: "managable-users"),
``
Copy the contents of the `Resources/Views` folder from the `managable-users` into the `Resources/Views` folder
in the new project, and also copy the contents of the `Public` folder into the `Public` folder.
In the `configure.swift` file, add the import
```swift
import ManagableUsers
…and add
try await ManagableUsers.configure (app)
into the configure() function.
In the routes.swift file, add the import
import ManagableUsers
…and replace everything in the routes() function with
let sessioned = app.grouped (app.sessions.middleware)
.grouped (BasicUser.sessionAuthenticator())
let loggedIn = sessioned
.grouped (BasicUser.redirectMiddleware (path: "auth/login"))
let api = sessioned
.grouped("api")
AuthenticationController<BasicUser>().routes (sessioned, api: api)
AdminController<BasicUser>().routes (loggedIn, api: api)
struct WelcomeContext: Encodable {
let user: BasicUser?
let section: String
}
loggedIn.get { req async throws in
return try await req.view.render("welcome", WelcomeContext (user: req.auth.get (BasicUser.self), section: "home"))
}
Extending
To add useful functionality, just add more routes to routes.swift.
To use a consistent look, use base.leaf in your Leaf templates for pages.
To add items to the main menu, do that in configure.swift by replacing
try await ManagableUsers.configure (app)
with something like
try await ManagableUsers.configure(app, mainMenu: [MenuItem (section: "inventory", path: "inventory", name: "Inventory")])
For MenuItem
sectioncorresponds to thesectionincluded in the rendering context supplied to Leaf.pathcorresponds to the URL path to the start page of that section.nameis the name that will be displayed in the menu.roleis an optional role that is required to access that section.- If
nilor omitted, it will be shown to all logged in users. - Corresponds to the
namecolumn in therolestable.
- If