feat(user-settings): avatar delete + accent color

- DELETE /users/me/avatar endpoint with file cleanup
- PATCH /users/me/accent-color with hex validation (#rrggbb)
- auth.service.ts: include accentColor in user select
- AccountSettingsForm: delete-avatar button + accent color picker/save/reset
- auth-actions.ts: deleteAvatarAction + updateAccentColorAction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 08:57:31 +02:00
parent cc95395889
commit be3680d0df
4 changed files with 208 additions and 23 deletions
+1
View File
@@ -200,6 +200,7 @@ export class AuthService {
passwordHash: true,
ldapDn: true,
avatarPath: true,
accentColor: true,
},
});
+48
View File
@@ -272,6 +272,54 @@ export class UserController {
return { success: true };
}
/**
* DELETE /users/me/avatar
* Remove the current user's profile picture.
*/
@Delete('me/avatar')
async deleteAvatar(@CurrentUser() currentUser: any) {
const user = await this.prisma.user.findUnique({
where: { id: currentUser.id },
select: { avatarPath: true },
});
if (user?.avatarPath) {
const monorepoRoot = path.resolve(__dirname, '..', '..', '..', '..');
const absolutePath = path.join(monorepoRoot, user.avatarPath);
if (fs.existsSync(absolutePath)) {
fs.unlinkSync(absolutePath);
}
await this.prisma.user.update({
where: { id: currentUser.id },
data: { avatarPath: null },
});
}
return { success: true };
}
/**
* PATCH /users/me/accent-color
* Set or clear the current user's accent color.
* T-acc-01: hex color validated server-side.
*/
@Patch('me/accent-color')
async updateAccentColor(
@Body() body: { color: string | null },
@CurrentUser() currentUser: any,
) {
if (body.color !== null && body.color !== undefined && !/^#[0-9a-fA-F]{6}$/.test(body.color)) {
throw new BadRequestException('Invalid color format. Use hex (#rrggbb).');
}
await this.prisma.user.update({
where: { id: currentUser.id },
data: { accentColor: body.color ?? null },
});
return { success: true };
}
/**
* GET /users/me/avatar
* Stream the current user's avatar image.