diff --git a/api/src/app/routes/users/index.ts b/api/src/app/routes/users/index.ts index 67e9c43..c7283bc 100644 --- a/api/src/app/routes/users/index.ts +++ b/api/src/app/routes/users/index.ts @@ -255,6 +255,40 @@ const usersRoutes: FastifyPluginAsync = async (app) => { return user; } ); + + app.put<{ Params: { id: string }; Body: UpdateUserSettingsBody; Reply: User | { error: string } }>( + "/:id", + { + preValidation: [app.authenticate, adminGuard], + preHandler: [app.csrfProtection], + }, + async (request, reply) => { + const { id } = request.params; + const updates = request.body; + + // If slug is being updated, check if it's unique + if (updates.slug) { + const existingUser = await userService.getUserBySlug(updates.slug); + if (existingUser && existingUser.id !== id) { + return reply.code(400).send({ error: "Slug already taken" }); + } + } + + const updatedUser = await userService.updateUserSettings(id, updates); + if (!updatedUser) { + return reply.code(404).send({ error: "User not found" }); + } + + await AuditService.logFromRequest(request, { + action: AuditAction.entryUpdate, + category: AuditCategory.admin, + targetUserId: id, + details: `Admin updated profile for user: ${updatedUser.username}`, + }); + + return updatedUser; + } + ); }; export default usersRoutes; diff --git a/apps/frontend/src/app/components/admin-reports/admin-reports.component.ts b/apps/frontend/src/app/components/admin-reports/admin-reports.component.ts index 2f1469a..73ca422 100644 --- a/apps/frontend/src/app/components/admin-reports/admin-reports.component.ts +++ b/apps/frontend/src/app/components/admin-reports/admin-reports.component.ts @@ -1529,10 +1529,30 @@ export class AdminReportsComponent implements OnInit { editProfile(report: ProfileReportWithUsers): void { const userId = report.reportedUser.id; + const username = report.reportedUser.username; - // Navigate to profile page using ObjectId - this.router.navigate(['/profile', userId]); - this.toastService.success('Navigate to profile to edit'); + // Load the full profile first to get current values + this.userService.getProfile(userId).subscribe({ + next: (profile) => { + const newBio = prompt(`Edit bio for ${username}:`, profile.bio || ''); + + if (newBio !== null) { + this.userService.adminUpdateUser(userId, { bio: newBio }).subscribe({ + next: () => { + this.toastService.success('Profile updated successfully'); + this.loadReports(); + this.closeProfileReviewModal(); + }, + error: (err) => { + this.toastService.error(err.message ?? 'Failed to update profile'); + } + }); + } + }, + error: (err) => { + this.toastService.error(err.message ?? 'Failed to load profile'); + } + }); } makeProfilePrivate(report: ProfileReportWithUsers): void { diff --git a/apps/frontend/src/app/services/user.service.ts b/apps/frontend/src/app/services/user.service.ts index 93c6ff3..45f67d9 100644 --- a/apps/frontend/src/app/services/user.service.ts +++ b/apps/frontend/src/app/services/user.service.ts @@ -85,4 +85,8 @@ export class UserService { makeProfilePrivate(userId: string): Observable { return this.api.post(`/users/${userId}/make-private`, {}); } + + adminUpdateUser(userId: string, settings: UpdateUserSettingsRequest): Observable { + return this.api.put(`/users/${userId}`, settings); + } }