Verschiebung nach anderem RePo - nun pro Projekt getrennt
This commit is contained in:
512
src/main/java/de/oaa/xxx/gruppe/GruppeController.java
Normal file
512
src/main/java/de/oaa/xxx/gruppe/GruppeController.java
Normal file
@@ -0,0 +1,512 @@
|
||||
package de.oaa.xxx.gruppe;
|
||||
|
||||
import de.oaa.xxx.gruppe.dto.*;
|
||||
import de.oaa.xxx.gruppe.entity.*;
|
||||
import de.oaa.xxx.gruppe.repository.*;
|
||||
import de.oaa.xxx.social.entity.KommentarEntity;
|
||||
import de.oaa.xxx.social.repository.KommentarRepository;
|
||||
import de.oaa.xxx.user.UserEntity;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
import de.oaa.xxx.user.UserService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/gruppen")
|
||||
public class GruppeController {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GruppeController.class);
|
||||
|
||||
private final GruppeRepository gruppeRepository;
|
||||
private final GruppenmitgliedRepository mitgliedRepository;
|
||||
private final BeitrittsanfrageRepository anfrageRepository;
|
||||
private final GruppenbeitragRepository beitragRepository;
|
||||
private final UmfrageOptionRepository optionRepository;
|
||||
private final UmfrageStimmeRepository stimmeRepository;
|
||||
private final GruppenbeitragLikeRepository likeRepository;
|
||||
private final BeitragMeldungRepository meldungRepository;
|
||||
private final KommentarRepository kommentarRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final UserService userService;
|
||||
|
||||
public GruppeController(GruppeRepository gruppeRepository,
|
||||
GruppenmitgliedRepository mitgliedRepository,
|
||||
BeitrittsanfrageRepository anfrageRepository,
|
||||
GruppenbeitragRepository beitragRepository,
|
||||
UmfrageOptionRepository optionRepository,
|
||||
UmfrageStimmeRepository stimmeRepository,
|
||||
GruppenbeitragLikeRepository likeRepository,
|
||||
BeitragMeldungRepository meldungRepository,
|
||||
KommentarRepository kommentarRepository,
|
||||
UserRepository userRepository,
|
||||
UserService userService) {
|
||||
this.gruppeRepository = gruppeRepository;
|
||||
this.mitgliedRepository = mitgliedRepository;
|
||||
this.anfrageRepository = anfrageRepository;
|
||||
this.beitragRepository = beitragRepository;
|
||||
this.optionRepository = optionRepository;
|
||||
this.stimmeRepository = stimmeRepository;
|
||||
this.likeRepository = likeRepository;
|
||||
this.meldungRepository = meldungRepository;
|
||||
this.kommentarRepository = kommentarRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
record CreateGruppeRequest(String name, String beschreibung, String bild, boolean isPrivate) {}
|
||||
record JoinRequest(String nachricht) {}
|
||||
record UpdateGruppeRequest(String name, String beschreibung, String bild, Boolean isPrivate) {}
|
||||
|
||||
// ── GET /gruppe/search?q= ──
|
||||
|
||||
@GetMapping("/search")
|
||||
public ResponseEntity<List<GruppeDto>> search(@RequestParam String q, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
List<GruppeEntity> gruppen = gruppeRepository.findByNameContainingIgnoreCase(q)
|
||||
.stream().limit(30).toList();
|
||||
List<UUID> gruppeIds = gruppen.stream().map(GruppeEntity::getGruppeId).toList();
|
||||
Map<UUID, LocalDateTime> latestActivity = buildLatestActivityMap(gruppeIds);
|
||||
List<GruppeDto> result = gruppen.stream()
|
||||
.map(g -> toDto(g, myId))
|
||||
.sorted((a, b) -> {
|
||||
LocalDateTime la = latestActivity.getOrDefault(a.gruppeId(), a.createdAt());
|
||||
LocalDateTime lb = latestActivity.getOrDefault(b.gruppeId(), b.createdAt());
|
||||
return lb.compareTo(la);
|
||||
})
|
||||
.toList();
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
// ── GET /gruppe/mine ──
|
||||
|
||||
@GetMapping("/mine")
|
||||
public ResponseEntity<List<GruppeDto>> mine(Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
List<GruppeEntity> gruppen = mitgliedRepository.findByUserId(myId)
|
||||
.stream()
|
||||
.map(m -> gruppeRepository.findById(m.getGruppeId()).orElse(null))
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
List<UUID> gruppeIds = gruppen.stream().map(GruppeEntity::getGruppeId).toList();
|
||||
Map<UUID, LocalDateTime> latestActivity = buildLatestActivityMap(gruppeIds);
|
||||
List<GruppeDto> result = gruppen.stream()
|
||||
.map(g -> toDto(g, myId))
|
||||
.sorted((a, b) -> {
|
||||
LocalDateTime la = latestActivity.getOrDefault(a.gruppeId(), a.createdAt());
|
||||
LocalDateTime lb = latestActivity.getOrDefault(b.gruppeId(), b.createdAt());
|
||||
return lb.compareTo(la);
|
||||
})
|
||||
.toList();
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
// ── GET /gruppe/{id} ──
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<GruppeDto> getGruppe(@PathVariable UUID id, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
return gruppeRepository.findById(id)
|
||||
.map(g -> ResponseEntity.ok(toDto(g, myId)))
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
// ── POST /gruppe ──
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<GruppeDto> createGruppe(@RequestBody CreateGruppeRequest req, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (req.name() == null || req.name().isBlank()) return ResponseEntity.badRequest().build();
|
||||
|
||||
GruppeEntity gruppe = new GruppeEntity();
|
||||
gruppe.setGruppeId(UUID.randomUUID());
|
||||
gruppe.setName(req.name().trim());
|
||||
gruppe.setBeschreibung(req.beschreibung());
|
||||
gruppe.setBild(req.bild());
|
||||
gruppe.setPrivate(req.isPrivate());
|
||||
gruppe.setCreatedAt(LocalDateTime.now());
|
||||
gruppe.setCreatedByUserId(myId);
|
||||
gruppeRepository.save(gruppe);
|
||||
|
||||
GruppenmitgliedEntity admin = new GruppenmitgliedEntity();
|
||||
admin.setMitgliedId(UUID.randomUUID());
|
||||
admin.setGruppeId(gruppe.getGruppeId());
|
||||
admin.setUserId(myId);
|
||||
admin.setRolle(GruppenRolle.ADMIN);
|
||||
admin.setJoinedAt(LocalDateTime.now());
|
||||
mitgliedRepository.save(admin);
|
||||
LOGGER.info("User {} hat Gruppe '{}' ({}) erstellt", myId, gruppe.getName(), gruppe.getGruppeId());
|
||||
|
||||
return ResponseEntity.status(201).body(toDto(gruppe, myId));
|
||||
}
|
||||
|
||||
// ── PUT /gruppe/{id} ──
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<GruppeDto> updateGruppe(@PathVariable UUID id,
|
||||
@RequestBody UpdateGruppeRequest req,
|
||||
Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
var gruppeOpt = gruppeRepository.findById(id);
|
||||
if (gruppeOpt.isEmpty()) return ResponseEntity.notFound().build();
|
||||
GruppeEntity gruppe = gruppeOpt.get();
|
||||
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
if (req.name() != null && !req.name().isBlank()) gruppe.setName(req.name().trim());
|
||||
if (req.beschreibung() != null) gruppe.setBeschreibung(req.beschreibung());
|
||||
if (req.bild() != null) gruppe.setBild(req.bild());
|
||||
if (req.isPrivate() != null) gruppe.setPrivate(req.isPrivate());
|
||||
gruppeRepository.save(gruppe);
|
||||
LOGGER.debug("User {} hat Gruppe {} aktualisiert", myId, id);
|
||||
|
||||
return ResponseEntity.ok(toDto(gruppe, myId));
|
||||
}
|
||||
|
||||
// ── DELETE /gruppe/{id} ──
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> deleteGruppe(@PathVariable UUID id, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
var gruppeOpt = gruppeRepository.findById(id);
|
||||
if (gruppeOpt.isEmpty()) return ResponseEntity.notFound().build();
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
// Cascade delete
|
||||
List<GruppenbeitragEntity> beitraege = beitragRepository.findByGruppeIdOrderByCreatedAtDesc(id);
|
||||
for (GruppenbeitragEntity b : beitraege) {
|
||||
UUID bid = b.getBeitragId();
|
||||
meldungRepository.deleteByBeitragId(bid);
|
||||
stimmeRepository.deleteByBeitragId(bid);
|
||||
optionRepository.deleteByBeitragId(bid);
|
||||
likeRepository.deleteByBeitragId(bid);
|
||||
// Kommentare on GROUP_POST
|
||||
List<KommentarEntity> kommentare = kommentarRepository
|
||||
.findByTargetTypeAndTargetIdOrderByCreatedAtAsc("GROUP_POST", bid);
|
||||
for (KommentarEntity k : kommentare) {
|
||||
kommentarRepository.delete(k);
|
||||
}
|
||||
}
|
||||
beitragRepository.deleteByGruppeId(id);
|
||||
anfrageRepository.deleteByGruppeId(id);
|
||||
mitgliedRepository.deleteByGruppeId(id);
|
||||
gruppeRepository.deleteById(id);
|
||||
LOGGER.info("User {} hat Gruppe {} gelöscht", myId, id);
|
||||
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── POST /gruppe/{id}/join ──
|
||||
|
||||
@PostMapping("/{id}/join")
|
||||
public ResponseEntity<Void> join(@PathVariable UUID id,
|
||||
@RequestBody(required = false) JoinRequest req,
|
||||
Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
var gruppeOpt = gruppeRepository.findById(id);
|
||||
if (gruppeOpt.isEmpty()) return ResponseEntity.notFound().build();
|
||||
GruppeEntity gruppe = gruppeOpt.get();
|
||||
|
||||
if (mitgliedRepository.findFirstByGruppeIdAndUserId(id, myId).isPresent())
|
||||
return ResponseEntity.status(409).build();
|
||||
|
||||
if (gruppe.isPrivate()) {
|
||||
// Check no pending request already
|
||||
var existingReq = anfrageRepository.findByGruppeIdAndUserId(id, myId);
|
||||
if (existingReq.isPresent() && existingReq.get().getStatus() == AnfrageStatus.AUSSTEHEND)
|
||||
return ResponseEntity.status(409).build();
|
||||
|
||||
BeitrittsanfrageEntity anfrage = new BeitrittsanfrageEntity();
|
||||
anfrage.setAnfrageId(UUID.randomUUID());
|
||||
anfrage.setGruppeId(id);
|
||||
anfrage.setUserId(myId);
|
||||
anfrage.setNachricht(req != null ? req.nachricht() : null);
|
||||
anfrage.setAngefragtAt(LocalDateTime.now());
|
||||
anfrage.setStatus(AnfrageStatus.AUSSTEHEND);
|
||||
anfrageRepository.save(anfrage);
|
||||
LOGGER.info("User {} hat Beitrittsanfrage für private Gruppe {} gestellt", myId, id);
|
||||
return ResponseEntity.status(201).build();
|
||||
} else {
|
||||
GruppenmitgliedEntity mitglied = new GruppenmitgliedEntity();
|
||||
mitglied.setMitgliedId(UUID.randomUUID());
|
||||
mitglied.setGruppeId(id);
|
||||
mitglied.setUserId(myId);
|
||||
mitglied.setRolle(GruppenRolle.MITGLIED);
|
||||
mitglied.setJoinedAt(LocalDateTime.now());
|
||||
mitgliedRepository.save(mitglied);
|
||||
LOGGER.info("User {} ist Gruppe {} beigetreten", myId, id);
|
||||
return ResponseEntity.status(201).build();
|
||||
}
|
||||
}
|
||||
|
||||
// ── DELETE /gruppe/{id}/leave ──
|
||||
|
||||
@DeleteMapping("/{id}/leave")
|
||||
public ResponseEntity<Void> leave(@PathVariable UUID id, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
mitgliedRepository.deleteByGruppeIdAndUserId(id, myId);
|
||||
LOGGER.info("User {} hat Gruppe {} verlassen", myId, id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── GET /gruppe/{id}/members ──
|
||||
|
||||
@GetMapping("/{id}/members")
|
||||
public ResponseEntity<List<Map<String, Object>>> getMembers(@PathVariable UUID id, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (mitgliedRepository.findFirstByGruppeIdAndUserId(id, myId).isEmpty())
|
||||
return ResponseEntity.status(403).build();
|
||||
|
||||
List<Map<String, Object>> result = mitgliedRepository.findByGruppeId(id).stream()
|
||||
.map(m -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("mitgliedId", m.getMitgliedId());
|
||||
map.put("userId", m.getUserId());
|
||||
map.put("rolle", m.getRolle().name());
|
||||
map.put("joinedAt", m.getJoinedAt());
|
||||
userRepository.findById(m.getUserId()).ifPresent(u -> {
|
||||
map.put("userName", u.getName());
|
||||
map.put("userPicture", u.getProfilePicture());
|
||||
});
|
||||
return map;
|
||||
})
|
||||
.toList();
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
// ── DELETE /gruppe/{id}/members/{userId} ──
|
||||
|
||||
@DeleteMapping("/{id}/members/{userId}")
|
||||
public ResponseEntity<Void> removeMember(@PathVariable UUID id,
|
||||
@PathVariable UUID userId,
|
||||
Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
mitgliedRepository.deleteByGruppeIdAndUserId(id, userId);
|
||||
LOGGER.warn("Admin {} hat User {} aus Gruppe {} entfernt", myId, userId, id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── POST /gruppe/{id}/members/{userId}/promote ──
|
||||
|
||||
@PostMapping("/{id}/members/{userId}/promote")
|
||||
public ResponseEntity<Void> promote(@PathVariable UUID id,
|
||||
@PathVariable UUID userId,
|
||||
Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
var m = mitgliedRepository.findFirstByGruppeIdAndUserId(id, userId);
|
||||
if (m.isEmpty()) return ResponseEntity.notFound().build();
|
||||
m.get().setRolle(GruppenRolle.ADMIN);
|
||||
mitgliedRepository.save(m.get());
|
||||
LOGGER.info("Admin {} hat User {} in Gruppe {} zum Admin befördert", myId, userId, id);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
// ── GET /gruppe/{id}/requests ──
|
||||
|
||||
@GetMapping("/{id}/requests")
|
||||
public ResponseEntity<List<BeitrittsanfrageDto>> getRequests(@PathVariable UUID id, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
List<BeitrittsanfrageDto> dtos = anfrageRepository
|
||||
.findByGruppeIdAndStatus(id, AnfrageStatus.AUSSTEHEND)
|
||||
.stream()
|
||||
.map(a -> {
|
||||
UserEntity u = userRepository.findById(a.getUserId()).orElse(null);
|
||||
return new BeitrittsanfrageDto(a.getAnfrageId(), a.getGruppeId(), a.getUserId(),
|
||||
u != null ? u.getName() : "Unbekannt",
|
||||
u != null ? u.getProfilePicture() : null,
|
||||
a.getNachricht(), a.getAngefragtAt());
|
||||
})
|
||||
.toList();
|
||||
return ResponseEntity.ok(dtos);
|
||||
}
|
||||
|
||||
// ── POST /gruppe/{id}/requests/{reqId}/approve ──
|
||||
|
||||
@PostMapping("/{id}/requests/{reqId}/approve")
|
||||
public ResponseEntity<Void> approveRequest(@PathVariable UUID id,
|
||||
@PathVariable UUID reqId,
|
||||
Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
var anfOpt = anfrageRepository.findById(reqId);
|
||||
if (anfOpt.isEmpty()) return ResponseEntity.notFound().build();
|
||||
BeitrittsanfrageEntity anfrage = anfOpt.get();
|
||||
anfrage.setStatus(AnfrageStatus.GENEHMIGT);
|
||||
anfrageRepository.save(anfrage);
|
||||
LOGGER.info("Admin {} hat Beitrittsanfrage {} (User: {}) für Gruppe {} genehmigt", myId, reqId, anfrage.getUserId(), id);
|
||||
|
||||
if (mitgliedRepository.findFirstByGruppeIdAndUserId(id, anfrage.getUserId()).isEmpty()) {
|
||||
GruppenmitgliedEntity mitglied = new GruppenmitgliedEntity();
|
||||
mitglied.setMitgliedId(UUID.randomUUID());
|
||||
mitglied.setGruppeId(id);
|
||||
mitglied.setUserId(anfrage.getUserId());
|
||||
mitglied.setRolle(GruppenRolle.MITGLIED);
|
||||
mitglied.setJoinedAt(LocalDateTime.now());
|
||||
mitgliedRepository.save(mitglied);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
// ── DELETE /gruppe/{id}/requests/{reqId} ──
|
||||
|
||||
@DeleteMapping("/{id}/requests/{reqId}")
|
||||
public ResponseEntity<Void> rejectRequest(@PathVariable UUID id,
|
||||
@PathVariable UUID reqId,
|
||||
Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
||||
|
||||
var anfOpt = anfrageRepository.findById(reqId);
|
||||
if (anfOpt.isEmpty()) return ResponseEntity.notFound().build();
|
||||
BeitrittsanfrageEntity anfrage = anfOpt.get();
|
||||
anfrage.setStatus(AnfrageStatus.ABGELEHNT);
|
||||
anfrageRepository.save(anfrage);
|
||||
LOGGER.debug("Admin {} hat Beitrittsanfrage {} für Gruppe {} abgelehnt", myId, reqId, id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── GET /gruppen/reports/pending/count ──
|
||||
|
||||
@GetMapping("/reports/pending/count")
|
||||
public ResponseEntity<Long> pendingReportsCount(Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
long count = mitgliedRepository.findByUserId(myId).stream()
|
||||
.filter(m -> m.getRolle() == GruppenRolle.ADMIN)
|
||||
.mapToLong(m -> {
|
||||
List<GruppenbeitragEntity> beitraege = beitragRepository.findByGruppeIdOrderByCreatedAtDesc(m.getGruppeId());
|
||||
List<UUID> ids = beitraege.stream().map(GruppenbeitragEntity::getBeitragId).toList();
|
||||
return ids.isEmpty() ? 0L : meldungRepository.findByBeitragIdIn(ids).size();
|
||||
})
|
||||
.sum();
|
||||
return ResponseEntity.ok(count);
|
||||
}
|
||||
|
||||
// ── GET /gruppen/requests/pending/count ──
|
||||
|
||||
@GetMapping("/requests/pending/count")
|
||||
public ResponseEntity<Long> pendingRequestCount(Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
long count = mitgliedRepository.findByUserId(myId).stream()
|
||||
.filter(m -> m.getRolle() == GruppenRolle.ADMIN)
|
||||
.mapToLong(m -> anfrageRepository.findByGruppeIdAndStatus(m.getGruppeId(), AnfrageStatus.AUSSTEHEND).size())
|
||||
.sum();
|
||||
return ResponseEntity.ok(count);
|
||||
}
|
||||
|
||||
// ── GET /gruppe/requests/mine ──
|
||||
|
||||
@GetMapping("/requests/mine")
|
||||
public ResponseEntity<List<Map<String, Object>>> myRequests(Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
List<Map<String, Object>> result = anfrageRepository.findByUserIdAndStatus(myId, AnfrageStatus.AUSSTEHEND)
|
||||
.stream()
|
||||
.map(a -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("anfrageId", a.getAnfrageId());
|
||||
map.put("gruppeId", a.getGruppeId());
|
||||
map.put("nachricht", a.getNachricht());
|
||||
map.put("angefragtAt", a.getAngefragtAt());
|
||||
gruppeRepository.findById(a.getGruppeId()).ifPresent(g -> map.put("gruppeName", g.getName()));
|
||||
return map;
|
||||
})
|
||||
.toList();
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
// ── DELETE /gruppe/{id}/requests/mine (withdraw own request) ──
|
||||
|
||||
@DeleteMapping("/{id}/requests/mine")
|
||||
public ResponseEntity<Void> withdrawRequest(@PathVariable UUID id, Principal principal) {
|
||||
UUID myId = resolveMyId(principal);
|
||||
if (myId == null) return ResponseEntity.status(401).build();
|
||||
|
||||
anfrageRepository.findByGruppeIdAndUserId(id, myId).ifPresent(a -> {
|
||||
if (a.getStatus() == AnfrageStatus.AUSSTEHEND) {
|
||||
anfrageRepository.delete(a);
|
||||
LOGGER.debug("User {} hat eigene Beitrittsanfrage für Gruppe {} zurückgezogen", myId, id);
|
||||
}
|
||||
});
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── Helpers ──
|
||||
|
||||
private Map<UUID, LocalDateTime> buildLatestActivityMap(List<UUID> gruppeIds) {
|
||||
if (gruppeIds.isEmpty()) return Map.of();
|
||||
Map<UUID, LocalDateTime> map = new HashMap<>();
|
||||
beitragRepository.findLatestCreatedAtByGruppeIds(gruppeIds).forEach(row -> {
|
||||
UUID gId = (UUID) row[0];
|
||||
LocalDateTime latest = (LocalDateTime) row[1];
|
||||
map.put(gId, latest);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
private UUID resolveMyId(Principal principal) {
|
||||
if (principal == null) return null;
|
||||
return userService.requireUser(principal).getUserId();
|
||||
}
|
||||
|
||||
private boolean isAdmin(UUID gruppeId, UUID userId) {
|
||||
return mitgliedRepository.findFirstByGruppeIdAndUserId(gruppeId, userId)
|
||||
.map(m -> m.getRolle() == GruppenRolle.ADMIN)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
GruppeDto toDto(GruppeEntity g, UUID myId) {
|
||||
long memberCount = mitgliedRepository.countByGruppeId(g.getGruppeId());
|
||||
long postCount = beitragRepository.findByGruppeIdOrderByCreatedAtDesc(g.getGruppeId()).size();
|
||||
String myRole = mitgliedRepository.findFirstByGruppeIdAndUserId(g.getGruppeId(), myId)
|
||||
.map(m -> m.getRolle().name())
|
||||
.orElse(null);
|
||||
String myRequestStatus = null;
|
||||
if (myRole == null) {
|
||||
myRequestStatus = anfrageRepository.findByGruppeIdAndUserId(g.getGruppeId(), myId)
|
||||
.filter(a -> a.getStatus() == AnfrageStatus.AUSSTEHEND)
|
||||
.map(a -> a.getStatus().name())
|
||||
.orElse(null);
|
||||
}
|
||||
return new GruppeDto(g.getGruppeId(), g.getName(), g.getBeschreibung(), g.getBild(),
|
||||
g.isPrivate(), g.getCreatedAt(), memberCount, postCount, myRole, myRequestStatus);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user