From c74474241a55a86fbb94ee135466eb543dd3230d Mon Sep 17 00:00:00 2001 From: Johan Carlberg Date: Sun, 22 Feb 2026 21:37:21 +0100 Subject: [PATCH] Show expiration time of password link in invites and forgotten password emails. --- Resources/Views/email/invite.leaf | 6 ++++-- Resources/Views/email/reset.leaf | 6 ++++-- Sources/ManageableUsers/Controllers/AdminController.swift | 2 +- .../Controllers/AuthenticationController.swift | 8 +++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Resources/Views/email/invite.leaf b/Resources/Views/email/invite.leaf index 90a14d2..e06fa85 100644 --- a/Resources/Views/email/invite.leaf +++ b/Resources/Views/email/invite.leaf @@ -1,3 +1,5 @@ -Välkommen till #(host). +Welcome to #(host). -För att aktivera ditt konto, gå till #baseURL/auth/password/#(token) och skriv in ett lösenord. +To activate your account, go to #baseURL/auth/password/#(token) and enter a password. + +The link is valid until #date(expiration, "yyyy-MM-dd HH:mm (z)"). diff --git a/Resources/Views/email/reset.leaf b/Resources/Views/email/reset.leaf index 1286e7d..797d1a2 100644 --- a/Resources/Views/email/reset.leaf +++ b/Resources/Views/email/reset.leaf @@ -1,3 +1,5 @@ -Du har begärt ett nytt lösenord på #(host). +You have requested a new password on #(host). -För att ändra ditt lösenord, gå till #baseURL/auth/password/#(token) och skriv in ett lösenord. +To change your password, go to #baseURL/auth/password/#(token) and enter a password. + +The link is valid until #date(expiration, "yyyy-MM-dd HH:mm (z)"). diff --git a/Sources/ManageableUsers/Controllers/AdminController.swift b/Sources/ManageableUsers/Controllers/AdminController.swift index 804a856..3683c36 100644 --- a/Sources/ManageableUsers/Controllers/AdminController.swift +++ b/Sources/ManageableUsers/Controllers/AdminController.swift @@ -88,7 +88,7 @@ public struct AdminController: Sendable where User.SessionID let token = try await UserToken.create (connection: connection).token try await User.create (email: invitation.email, fullname: invitation.fullname, roles: invitation.roles, token: token, on: connection) let host = try Environment.baseURL.host() ?? "" - let body = try await request.view.render ("email/invite", ["token": token, "host": host]) + let body = try await request.view.render ("email/invite", AuthenticationController.TokenEmailContext (token: token, host: host, expiration: Calendar.current.date (byAdding: .day, value: 1, to: Date()) ?? Date())) .data let message = Email (sender: Email.Contact (emailAddress: try Environment.emailSender), recipients: [Email.Contact(emailAddress: invitation.email)], diff --git a/Sources/ManageableUsers/Controllers/AuthenticationController.swift b/Sources/ManageableUsers/Controllers/AuthenticationController.swift index 193d36f..7e8e7f7 100644 --- a/Sources/ManageableUsers/Controllers/AuthenticationController.swift +++ b/Sources/ManageableUsers/Controllers/AuthenticationController.swift @@ -91,6 +91,12 @@ public struct AuthenticationController: Sendable where User.S let email: String } + struct TokenEmailContext: Encodable { + let token: String + let host: String + let expiration: Date + } + func forgotPassword (request: Request) async throws -> Response { let input = try request.content.decode (Input.self) @@ -101,7 +107,7 @@ public struct AuthenticationController: Sendable where User.S let token = try await UserToken.create (connection: connection).token try await User.store (token: token, userId: user.id, on: connection) let host = try Environment.baseURL.host() ?? "" - let body = try await request.view.render ("email/reset", ["token": token, "host": host, "section": "login"]) + let body = try await request.view.render ("email/reset", TokenEmailContext (token: token, host: host, expiration: Calendar.current.date (byAdding: .hour, value: 1, to: Date()) ?? Date())) .data let message = Email (sender: Email.Contact (emailAddress: try Environment.emailSender), recipients: [Email.Contact(emailAddress: input.email)],