This commit is contained in:
Bastian Wagner
2026-06-29 14:34:34 +02:00
parent ecb902565d
commit 9a721f9e86
18 changed files with 884 additions and 7 deletions

View File

@@ -23,6 +23,7 @@ import {
PublicUserSearchResult,
} from './auth.types';
import { AppEvents } from '../events/app-events';
import type { TaskDigestPreference } from '../tasks/task-digest.types';
import { RefreshTokenEntity } from './refresh-token.entity';
import { UserEntity } from './user.entity';
@@ -359,6 +360,34 @@ export class AuthService {
return this.toPublicUser(savedUser);
}
async updateTaskDigestPreference(
userId: string,
preference: unknown,
): Promise<PublicUser> {
const user = await this.usersRepository.findOne({
where: { id: userId },
});
if (!user) {
throw new UnauthorizedException('Authenticated user is required.');
}
user.taskDigestPreference = this.normalizeTaskDigestPreference(preference);
const savedUser = await this.usersRepository.save(user);
await this.auditLogService?.record({
actorUserId: savedUser.id,
actorEmail: savedUser.email,
action: 'user.task_digest_updated',
entityType: 'user',
entityId: savedUser.id,
metadata: { taskDigestPreference: savedUser.taskDigestPreference },
});
return this.toPublicUser(savedUser);
}
private normalizeEmail(email?: string): string {
const normalizedEmail = email?.trim().toLowerCase();
@@ -377,6 +406,14 @@ export class AuthService {
return normalizedName || undefined;
}
private normalizeTaskDigestPreference(value: unknown): TaskDigestPreference {
if (value === 'none' || value === 'morning' || value === 'both') {
return value;
}
throw new BadRequestException('Task digest preference is invalid.');
}
private requirePassword(password?: string): string {
if (!password || password.length < 8) {
throw new BadRequestException(
@@ -495,6 +532,7 @@ export class AuthService {
name: user.name ?? undefined,
verified: user.verified,
onboardingCompleted: user.onboardingCompleted === true,
taskDigestPreference: user.taskDigestPreference ?? 'both',
};
}
}