Compare commits

...

6 Commits

Author SHA1 Message Date
7c58b9021a Merge remote-tracking branch 'origin/dev' into dev
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 50s
Build and Push Docker Images / build-frontend (push) Successful in 25s
Build and Push Docker Images / build-website (push) Successful in 22s
Build and Push Docker Images / build-central-services-api (push) Successful in 22s
Build and Push Docker Images / build-docs (push) Successful in 22s
Build and Push Docker Images / build-central-services-admin (push) Successful in 23s
2026-09-04 07:48:52 +02:00
62eef04a6b KI-AGENT: Password-Reset gegen hängenden Mailversand absichern 2026-09-04 07:47:43 +02:00
a298712973 Merge remote-tracking branch 'origin/dev' into dev 2026-08-31 21:44:33 +02:00
12130395e3 Merge remote-tracking branch 'origin/dev' into dev 2026-08-31 21:40:50 +02:00
1ae76380a9 Merge remote-tracking branch 'origin/dev' into dev 2026-08-31 21:37:21 +02:00
40bd1769ee KI-AGENT: Upload-Timeout für Tenant-Import erhöhen 2026-08-27 08:51:01 +02:00
3 changed files with 31 additions and 6 deletions

View File

@@ -6,7 +6,7 @@ import { sendMail } from "../../utils/mailer";
import { authUsers } from "../../../db/schema";
import { authTenantUsers } from "../../../db/schema";
import { tenants } from "../../../db/schema";
import { eq } from "drizzle-orm";
import { and, eq } from "drizzle-orm";
import {
createAccessToken,
issueRefreshToken,
@@ -211,6 +211,8 @@ export default async function authRoutes(server: FastifyInstance) {
.select({
id: authUsers.id,
email: authUsers.email,
passwordHash: authUsers.passwordHash,
mustChangePassword: authUsers.must_change_password,
})
.from(authUsers)
.where(eq(authUsers.email, email.toLowerCase()))
@@ -228,12 +230,11 @@ export default async function authRoutes(server: FastifyInstance) {
.update(authUsers)
.set({
passwordHash,
// @ts-ignore
mustChangePassword: true,
must_change_password: true,
})
.where(eq(authUsers.id, user.id));
await sendMail(
const mailResult = await sendMail(
user.email,
"FEDEO | Dein neues Passwort",
`
@@ -244,6 +245,23 @@ export default async function authRoutes(server: FastifyInstance) {
`
);
if (!mailResult.success) {
// Ein fehlgeschlagener Mailversand darf das bisherige Passwort nicht
// unbrauchbar machen. Die Hash-Bedingung schützt parallele Resets.
await server.db
.update(authUsers)
.set({
passwordHash: user.passwordHash,
must_change_password: user.mustChangePassword,
})
.where(and(
eq(authUsers.id, user.id),
eq(authUsers.passwordHash, passwordHash),
));
return reply.code(502).send({ error: "Password reset email could not be sent" });
}
return { success: true };
});
}

View File

@@ -7,6 +7,11 @@ export const initMailer = async () => {
host: secrets.MAILER_SMTP_HOST,
port: Number(secrets.MAILER_SMTP_PORT) || 587,
secure: secrets.MAILER_SMTP_SSL === "true", // true für 465, false für andere Ports
// Ohne explizite Timeouts kann ein API-Request bei einem nicht erreichbaren
// SMTP-Server mehrere Minuten offen bleiben.
connectionTimeout: 10_000,
greetingTimeout: 10_000,
socketTimeout: 20_000,
auth: {
user: secrets.MAILER_SMTP_USER,
pass: secrets.MAILER_SMTP_PASS,

View File

@@ -10,6 +10,8 @@ services:
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.transport.respondingtimeouts.readtimeout=10m
- --entrypoints.websecure.transport.respondingtimeouts.readtimeout=10m
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --certificatesresolvers.letsencrypt.acme.tlschallenge=true