Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/main/java/de/tum/cit/aet/TumApplyApp.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package de.tum.cit.aet;

import de.tum.cit.aet.core.config.ApplicantRetentionProperties;
import de.tum.cit.aet.core.config.ApplicationProperties;
import de.tum.cit.aet.core.config.CRLFLogConverter;
import de.tum.cit.aet.core.config.UserRetentionProperties;
import jakarta.annotation.PostConstruct;
import java.net.InetAddress;
import java.net.UnknownHostException;
Expand All @@ -20,7 +22,9 @@
import tech.jhipster.config.JHipsterConstants;

@SpringBootApplication
@EnableConfigurationProperties({ LiquibaseProperties.class, ApplicationProperties.class })
@EnableConfigurationProperties(
{ LiquibaseProperties.class, ApplicationProperties.class, UserRetentionProperties.class, ApplicantRetentionProperties.class }
)
public class TumApplyApp {

private static final Logger LOG = LoggerFactory.getLogger(TumApplyApp.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Configuration properties for applicant data retention settings.
*
* <p>Maps properties prefixed with {@code applicant.retention} from the application
* configuration into this class. Unknown fields are not allowed to ensure strict
* configuration validation.</p>
*/
package de.tum.cit.aet.core.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "applicant.retention", ignoreUnknownFields = false)
public class ApplicantRetentionProperties {

private Integer daysBeforeDeletion;

private Boolean enabled;

private Boolean dryRun;

private Integer batchSize;

private Integer maxRuntimeMinutes;

public Integer getBatchSize() {
return batchSize;
}

public void setBatchSize(Integer batchSize) {
this.batchSize = batchSize;
}

public Integer getDaysBeforeDeletion() {
return daysBeforeDeletion;
}

public void setDaysBeforeDeletion(Integer daysBeforeDeletion) {
this.daysBeforeDeletion = daysBeforeDeletion;
}

public Boolean getDryRun() {
return dryRun;
}

public void setDryRun(Boolean dryRun) {
this.dryRun = dryRun;
}

public Boolean getEnabled() {
return enabled;
}

public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}

public Integer getMaxRuntimeMinutes() {
return maxRuntimeMinutes;
}

public void setMaxRuntimeMinutes(Integer maxRuntimeMinutes) {
this.maxRuntimeMinutes = maxRuntimeMinutes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package de.tum.cit.aet.core.config;

import java.util.UUID;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* Configuration properties for user retention and scheduled cleanup behavior.
* <p>
* Includes settings for inactivity thresholds, applicant data deletion timing,
* job execution parameters (cron, batch size, max runtime), and placeholders for
* representing deleted users (ID, email, names, language). Supports enabling/disabling
* the feature and running in dry-run mode.
*/
@ConfigurationProperties(prefix = "user.retention", ignoreUnknownFields = false)
public class UserRetentionProperties {

private Integer inactiveDaysBeforeDeletion;

private Boolean enabled;

private Boolean dryRun;

private Integer batchSize;

private Integer maxRuntimeMinutes;

private String cron;

private UUID deletedUserId;

private String deletedUserEmail;

private String deletedUserFirstName;

private String deletedUserLastName;

private String deletedUserLanguage;

public Integer getBatchSize() {
return batchSize;
}

public void setBatchSize(Integer batchSize) {
this.batchSize = batchSize;
}

public Boolean getDryRun() {
return dryRun;
}

public void setDryRun(Boolean dryRun) {
this.dryRun = dryRun;
}

public Boolean getEnabled() {
return enabled;
}

public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}

public Integer getInactiveDaysBeforeDeletion() {
return inactiveDaysBeforeDeletion;
}

public void setInactiveDaysBeforeDeletion(Integer inactiveDaysBeforeDeletion) {
this.inactiveDaysBeforeDeletion = inactiveDaysBeforeDeletion;
}

public Integer getMaxRuntimeMinutes() {
return maxRuntimeMinutes;
}

public void setMaxRuntimeMinutes(Integer maxRuntimeMinutes) {
this.maxRuntimeMinutes = maxRuntimeMinutes;
}

public String getCron() {
return cron;
}

public void setCron(String cron) {
this.cron = cron;
}

public UUID getDeletedUserId() {
return deletedUserId;
}

public void setDeletedUserId(UUID deletedUserId) {
this.deletedUserId = deletedUserId;
}

public String getDeletedUserEmail() {
return deletedUserEmail;
}

public void setDeletedUserEmail(String deletedUserEmail) {
this.deletedUserEmail = deletedUserEmail;
}

public String getDeletedUserFirstName() {
return deletedUserFirstName;
}

public void setDeletedUserFirstName(String deletedUserFirstName) {
this.deletedUserFirstName = deletedUserFirstName;
}

public String getDeletedUserLastName() {
return deletedUserLastName;
}

public void setDeletedUserLastName(String deletedUserLastName) {
this.deletedUserLastName = deletedUserLastName;
}

public String getDeletedUserLanguage() {
return deletedUserLanguage;
}

public void setDeletedUserLanguage(String deletedUserLanguage) {
this.deletedUserLanguage = deletedUserLanguage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ public interface DocumentDictionaryRepository extends TumApplyJpaRepository<Docu
Set<DocumentDictionary> findAllByApplicant(Applicant applicant);

Set<DocumentDictionary> findAllByApplicationApplicationId(UUID applicationId);

void deleteByApplication(Application application);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package de.tum.cit.aet.core.repository;

import de.tum.cit.aet.core.domain.Document;
import de.tum.cit.aet.usermanagement.domain.User;
import java.util.Optional;
import java.util.UUID;
import org.springframework.stereotype.Repository;

@Repository
public interface DocumentRepository extends TumApplyJpaRepository<Document, UUID> {
Optional<Document> findBySha256Id(String sha256Id);

void deleteByUploadedBy(User uploadedBy);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import de.tum.cit.aet.core.domain.DepartmentImage;
import de.tum.cit.aet.core.domain.Image;
import de.tum.cit.aet.core.domain.ResearchGroupImage;
import de.tum.cit.aet.usermanagement.domain.User;
import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
Expand Down Expand Up @@ -86,4 +88,24 @@ default List<DepartmentImage> findDefaultJobBannersBySchool(UUID schoolId) {
*/
@Query("SELECT di FROM DepartmentImage di WHERE di.department IS NULL")
List<DepartmentImage> findOrphanedDepartmentImages();

/**
* Deletes the profile image associated with the given user.
*
* @param userId the ID of the user whose profile image should be deleted
*/
@Modifying
@Query("DELETE FROM Image i WHERE i.uploadedBy.userId = :userId AND TYPE(i) = ProfileImage")
void deleteProfileImageByUser(@Param("userId") UUID userId);

/**
* Updates all {@link Image} records uploaded by the given {@code user} to associate them with the
* provided {@code deletedUser} instead of the original user.
*
* @param user the user whose uploaded images should be dissociated
* @param deletedUser the user to set as the uploader for those images
*/
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("UPDATE Image i SET i.uploadedBy = :deletedUser WHERE i.uploadedBy = :user")
void dissociateImagesFromUser(@Param("user") User user, @Param("deletedUser") User deletedUser);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package de.tum.cit.aet.core.retention;

import de.tum.cit.aet.core.config.ApplicantRetentionProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
@Slf4j
public class ApplicantRetentionJob {

private final ApplicantRetentionProperties properties;

@Scheduled(cron = "${user.retention.cron:0 27 3 * * *}", zone = "UTC")
public void deleteApplicantData() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package de.tum.cit.aet.core.retention;

public class ApplicantRetentionService {}
Loading
Loading