-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUserServiceImpl.java
More file actions
482 lines (413 loc) · 17.1 KB
/
Copy pathUserServiceImpl.java
File metadata and controls
482 lines (413 loc) · 17.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
package ch.fhnw.timerecordingbackend.service;
import ch.fhnw.timerecordingbackend.dto.authentication.ChangePasswordRequest;
import ch.fhnw.timerecordingbackend.model.Role;
import ch.fhnw.timerecordingbackend.model.SystemLog;
import ch.fhnw.timerecordingbackend.model.User;
import ch.fhnw.timerecordingbackend.model.enums.UserStatus;
import ch.fhnw.timerecordingbackend.repository.RoleRepository;
import ch.fhnw.timerecordingbackend.repository.SystemLogRepository;
import ch.fhnw.timerecordingbackend.repository.UserRepository;
import jakarta.transaction.Transactional;
import jakarta.validation.ValidationException; // Import für ValidationException
import org.slf4j.Logger; // Import für Logger
import org.slf4j.LoggerFactory; // Import für LoggerFactory
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Random; // Import für Random
/**
* Implementierung UserService Interface
* Geschöftslogik Benutzerverwaltung
* @author PD
* Code von anderen Teammitgliedern oder Quellen wird durch einzelne Kommentare deklariert
* @version 1.1 - Passwort zurücksetzten, zufälliges Passwort generieren und PasswordEncoder hinzugefügt
*/
@Service
public class UserServiceImpl implements UserService {
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final SystemLogRepository systemLogRepository;
private final PasswordEncoder passwordEncoder;
/**
* Konstruktor mit Dependency Injection
* @param userRepository
* @param roleRepository
* @param systemLogRepository
*/
public UserServiceImpl(UserRepository userRepository, RoleRepository roleRepository, SystemLogRepository systemLogRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.systemLogRepository = systemLogRepository;
this.passwordEncoder = passwordEncoder;
}
@Override // <-- Stelle sicher, dass @Override hier steht und keinen Fehler wirft
@Transactional
public boolean requestPasswordReset(String email) {
Optional<User> userOptional = userRepository.findByEmail(email);
if (userOptional.isPresent()) {
User user = userOptional.get();
SystemLog log = new SystemLog();
log.setAction("Passwort Reset angefordert");
log.setTimestamp(LocalDateTime.now());
log.setUserEmail(user.getEmail());
log.setUserId(user.getId());
log.setDetails("Benutzer " + user.getEmail() + " hat einen Passwort-Reset angefordert.");
systemLogRepository.save(log);
logger.info("Passwort-Reset angefordert für Benutzer: {}", email);
return true;
}
logger.warn("Passwort-Reset für unbekannte E-Mail angefordert: {}", email);
return false;
}
/**
* Suchmethoden
*/
@Override
public List<User> findAllUsers() {
return userRepository.findAll();
}
@Override
public List<User> findActiveUsers() {
return userRepository.findByActiveTrue();
}
@Override
public Optional<User> findById(Long id) {
return userRepository.findById(id);
}
@Override
public Optional<User> findByEmail(String email) {
return userRepository.findByEmail(email);
}
/**
* Neuen Benutzer erstellen
* @param user
* @param roleName
* @return
*/
@Override
@Transactional
public User createUser(User user, String roleName) {
// Prüfen ob Email bereits existiert
if (userRepository.existsByEmail(user.getEmail())) {
throw new ValidationException("Email existiert bereits");
}
//Zeitstempel
LocalDateTime now = LocalDateTime.now();
user.setCreatedAt(now);
user.setUpdatedAt(now);
// Rolle zuweisen
Role role = roleRepository.findByName(roleName)
.orElseThrow(() -> new ValidationException("Rolle nicht gefunden"));
user.addRole(role);
// Speichern
User savedUser = userRepository.save(user);
// System Log erstellen
SystemLog log = new SystemLog();
log.setAction("Benutzer erstellt" + user.getEmail());
log.setTimestamp(now);
log.setDetails("Benutzer ID: " + savedUser.getId() + ", Rolle: " + roleName);
systemLogRepository.save(log);
return savedUser;
}
/**
* Benurter aktualisieren
* @param id
* @param user neuer User mit allen Feldern
* @return
*/
@Override
@Transactional
public User updateUser(Long id, User user) {
// Benutzer finden
User existingUser = userRepository.findById(id)
.orElseThrow(() -> new ValidationException("Benutzer nicht gefunden"));
// Daten Aktualisieren
existingUser.setFirstName(user.getFirstName());
existingUser.setLastName(user.getLastName());
existingUser.setPlannedHoursPerDay(user.getPlannedHoursPerDay());
existingUser.setActive(user.isActive());
// Zeitstempel
LocalDateTime now = LocalDateTime.now();
existingUser.setUpdatedAt(now);
// System Log erstellen
SystemLog log = new SystemLog();
log.setAction("Benutzer aktualisiert" + user.getEmail());
log.setTimestamp(now);
log.setDetails("Benutzer ID: " + existingUser.getId());
systemLogRepository.save(log);
return userRepository.save(existingUser);
}
/**
* Passwort eines Benutzers ändern
* @param id
* @param oldPassword
* @param newPassword
* @return
*/
@Override
@Transactional
public boolean updatePassword(Long id, String oldPassword, String newPassword) {
// Benutzer finden
User user = userRepository.findById(id)
.orElseThrow(() -> new ValidationException("Benutzer nicht gefunden"));
// altes Passwort überprüfen
if (!oldPassword.equals(user.getPassword())) {
return false;
}
// Neues Passwort erstellen
user.setPassword(newPassword);
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Passwort geändert: " + user.getEmail());
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
return true;
}
/**
* Ändert das Passwort für den angemeldeten User.
* @param request enthält userId, altes und neues Passwort
*/
@Override
@Transactional
public void changePassword(ChangePasswordRequest request) {
// Aktuelle Benutzer-ID aus Security Context holen
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || !auth.isAuthenticated()) {
throw new ValidationException("Benutzer ist nicht authentifiziert");
}
String userEmail = auth.getName(); // E-Mail des eingeloggten Benutzers
// Benutzer finden
User user = userRepository.findByEmail(userEmail)
.orElseThrow(() -> new ValidationException("Benutzer nicht gefunden"));
// Altes Passwort korrekt überprüfen
if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
throw new ValidationException("Altes Passwort ist falsch");
}
// Neues Passwort verschlüsseln und setzen
user.setPassword(passwordEncoder.encode(request.getNewPassword()));
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Passwort geändert: " + user.getEmail());
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
}
/**
* Passwort zurücksetzen
* @param userId
* @return neues Passwort
*/
@Override
@Transactional
public String resetPasswordToTemporary(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new ValidationException("Benutzer nicht vorhanden"));
String tempPassword = generateRandomPassword();
user.setPassword(passwordEncoder.encode(tempPassword));
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user); // Benutzer mit neuem Passwort speichern
// Admin-Aktion loggen (optional, aber gut für die Nachvollziehbarkeit)
SystemLog adminActionLog = new SystemLog();
adminActionLog.setUserId(user.getId());
adminActionLog.setUserEmail(user.getEmail());
adminActionLog.setAction("Admin hat Passwort zurückgesetzt");
adminActionLog.setDetails("Temporäres Passwort generiert für User ID: " + userId + " (" + user.getEmail() + ")");
adminActionLog.setTimestamp(LocalDateTime.now());
// adminActionLog.setProcessedStatus("ADMIN_ACTION"); // Oder einen anderen Status für reine Admin-Aktionen
systemLogRepository.save(adminActionLog);
// --- AN DIESER STELLE LIEGT WAHRSCHEINLICH DAS PROBLEM ---
// Den ursprünglichen "Passwort Reset angefordert"-Log suchen und als "COMPLETED" markieren
List<SystemLog> requestLogs = systemLogRepository.findByUserIdAndActionAndProcessedStatusOrderByTimestampDesc(
userId,
"Passwort Reset angefordert", // GENAU PRÜFEN: Stimmt dieser String exakt mit dem in UserController überein?
"PENDING" // GENAU PRÜFEN: Stimmt dieser String exakt mit dem in UserController überein?
);
if (!requestLogs.isEmpty()) {
SystemLog requestLogToUpdate = requestLogs.get(0); // Nimm den neuesten PENDING Request
requestLogToUpdate.setProcessedStatus("COMPLETED"); // Status auf COMPLETED setzen
// Optional: Details im Log-Eintrag ergänzen
// Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// String adminUserEmail = auth != null ? auth.getName() : "Unbekannter Admin";
// requestLogToUpdate.setDetails(requestLogToUpdate.getDetails() + " - Bearbeitet von Admin (" + adminUserEmail +") am " + LocalDateTime.now());
systemLogRepository.save(requestLogToUpdate); // SEHR WICHTIG: Den aktualisierten Log speichern!
System.out.println("DEBUG: SystemLog ID " + requestLogToUpdate.getId() +
" (Action: '" + requestLogToUpdate.getAction() +
"', Initial Status: PENDING) wurde auf PROCESSED_STATUS = COMPLETED gesetzt für User ID: " + userId);
} else {
System.out.println("DEBUG: Kein PENDING SystemLog mit Action 'Passwort Reset angefordert' für User ID " + userId +
" gefunden, der auf COMPLETED gesetzt werden könnte. Überprüfe Action-String und initialen Status.");
}
return tempPassword;
}
/**
* Generiert ein zufälliges Passwort.
* @return zufälliges Passwort
*/
private String generateRandomPassword() {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder password = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 8; i++) {
password.append(chars.charAt(random.nextInt(chars.length())));
}
return password.toString();
}
/**
* Benutzer deaktivieren
* @param id
* @return
*/
@Override
@Transactional
public User deactivateUser(Long id) {
// Benutzer finden
User user = userRepository.findById(id)
.orElseThrow(() -> new ValidationException("Benutzer nicht gefunden"));
// Benutzer deaktivieren
user.deactivate();
User deactivatedUser = userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Benutzer deaktiviert: " + user.getEmail());
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
return deactivatedUser;
}
/**
* Benutzer aktivieren
* @param id
* @return
*/
@Override
@Transactional
public User activateUser(Long id) {
// Benutzer finden
User user = userRepository.findById(id)
.orElseThrow(() -> new ValidationException("Benutzer nicht gefunden"));
// Benutzer aktivieren
user.activate();
User activatedUser = userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Benutzer aktiviert: " + user.getEmail());
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
return activatedUser;
}
/**
* Benutzer Status ändern
* @param id
* @param status
* @return
*/
@Override
@Transactional
public User updateUserStatus(Long id, UserStatus status) {
// Benutzer finden
User user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Benutzer nicht gefunden"));
// Status aktualisieren
user.setStatus(status);
user.setActive(status == UserStatus.ACTIVE);
user.setUpdatedAt(LocalDateTime.now());
User updatedUser = userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Benutzerstatus geändert: " + user.getEmail() + " " + status);
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
return updatedUser;
}
/**
* Rolle zu Benutzer hinzufügen
* @param userId
* @param roleName
* @return
*/
@Override
@Transactional
public User addRoleToUser(Long userId, String roleName) {
// Benutzer finden
User user = userRepository.findById(userId)
.orElseThrow(() -> new ValidationException("Benutzer nicht gefunden"));
// Rolle finden
Role role = roleRepository.findByName(roleName)
.orElseThrow(() -> new ValidationException("Rolle nicht gefunden"));
// Rolle hinzufügen, wenn der Benutzer sie noch nicht hat
if (user.getRoles().stream().noneMatch(r -> r.getName().equals(roleName))) {
user.addRole(role);
userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Rolle hinzugefügt: " + roleName + " zu " + user.getEmail());
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
}
return user;
}
/**
* Rolle von Benutzer entfernen
* @param userId
* @param roleName
* @return
*/
@Override
@Transactional
public User removeRoleFromUser(Long userId, String roleName) {
// Benutzer finden
User user = userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("Benutzer nicht gefunden"));
// Prüfen ob der Benutzer die Rolle hat
Role roleToRemove = null;
for (Role role : user.getRoles()) {
if (role.getName().equals(roleName)) {
roleToRemove = role;
break;
}
}
// Rolle entfernen
if (roleToRemove != null) {
user.getRoles().remove(roleToRemove);
userRepository.save(user);
// Systemlog erstellen
SystemLog log = new SystemLog();
log.setAction("Rolle entfernt: " + roleName + " von " + user.getEmail());
log.setTimestamp(LocalDateTime.now());
log.setDetails("Benutzer ID: " + user.getId());
systemLogRepository.save(log);
}
return user;
}
@Override
public List<User> searchUsers(String searchTerm) {
return userRepository.searchUsers(searchTerm);
}
@Override
public boolean isAdmin(Long userId) {
Optional<User> userOptional = userRepository.findById(userId);
return userOptional.map(user -> user.hasRole("ADMIN")).orElse(false);
}
@Override
public boolean isProjectManager(Long userId) {
Optional<User> userOptional = userRepository.findById(userId);
return userOptional.map(user -> user.hasRole("MANAGER")).orElse(false);
}
@Override
public List<Role> getAllRoles() {
return roleRepository.findAll();
}
}