feat(sprint-6): Phase 2 — DSGVO consent management
Deploy to Production / test (push) Has been cancelled
Deploy to Production / deploy (push) Has been cancelled

- V6 migration: consents table with audit columns
- Consent entity, repository, service (grant/revoke/check)
- ConsentController: GET/POST/DELETE consent endpoints
- DSGVO export (Art. 15): full personal data JSON download
- DSGVO deletion (Art. 17): anonymization + account deactivation
- Frontend: consent banner (modal, cannot dismiss), privacy settings page
- React Query hooks for consent + DSGVO operations
- Full i18n (de/en) for consent and DSGVO namespaces
This commit is contained in:
Patrick Plate
2026-06-12 22:22:48 +02:00
parent b38902a7ee
commit 3232d2f7fd
17 changed files with 2227 additions and 0 deletions
@@ -0,0 +1,74 @@
package de.cannamanage.domain.entity;
import de.cannamanage.domain.enums.ConsentType;
import jakarta.persistence.*;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "consents")
public class Consent extends AbstractTenantEntity {
@Column(name = "user_id", nullable = false)
private UUID userId;
@Enumerated(EnumType.STRING)
@Column(name = "consent_type", nullable = false, length = 50)
private ConsentType consentType;
@Column(name = "granted", nullable = false)
private boolean granted = false;
@Column(name = "granted_at")
private Instant grantedAt;
@Column(name = "revoked_at")
private Instant revokedAt;
@Column(name = "ip_address", length = 45)
private String ipAddress;
@Column(name = "user_agent", columnDefinition = "TEXT")
private String userAgent;
@Column(name = "version", nullable = false)
private int version = 1;
@Column(name = "updated_at")
private Instant updatedAt;
@PreUpdate
void onUpdate() {
this.updatedAt = Instant.now();
}
// --- Getters & Setters ---
public UUID getUserId() { return userId; }
public void setUserId(UUID userId) { this.userId = userId; }
public ConsentType getConsentType() { return consentType; }
public void setConsentType(ConsentType consentType) { this.consentType = consentType; }
public boolean isGranted() { return granted; }
public void setGranted(boolean granted) { this.granted = granted; }
public Instant getGrantedAt() { return grantedAt; }
public void setGrantedAt(Instant grantedAt) { this.grantedAt = grantedAt; }
public Instant getRevokedAt() { return revokedAt; }
public void setRevokedAt(Instant revokedAt) { this.revokedAt = revokedAt; }
public String getIpAddress() { return ipAddress; }
public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; }
public String getUserAgent() { return userAgent; }
public void setUserAgent(String userAgent) { this.userAgent = userAgent; }
public int getVersion() { return version; }
public void setVersion(int version) { this.version = version; }
public Instant getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; }
}
@@ -0,0 +1,10 @@
package de.cannamanage.domain.enums;
/**
* Types of DSGVO consent that can be granted or revoked by users.
*/
public enum ConsentType {
DATA_PROCESSING,
MARKETING,
ANALYTICS
}