Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COL-10 deletion #575

Merged
merged 6 commits into from
Apr 11, 2024
Merged
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
11 changes: 9 additions & 2 deletions colab-api/src/main/java/ch/colabproject/colab/api/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

import ch.colabproject.colab.api.model.user.HashMethod;
import ch.colabproject.colab.api.ws.channel.model.WebsocketChannel;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.security.SecureRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
* Some global helper methods
Expand All @@ -21,6 +22,12 @@
*/
public class Helper {

/** Text used for the fields createdBy / modifiedBy / erasedBy whenever the user is unknown (should never happen) */
public static final String UNKNOWN_USER = "UNKNOWN_USER";

/** Text used for the fields createdBy / modifiedBy / erasedBy when the change is made through a scheduled job */
public static final String SCHEDULED_JOB = "SCHEDULED_JOB";

/**
* The co.LAB base uniform resource name
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package ch.colabproject.colab.api.controller;

import ch.colabproject.colab.api.controller.common.DeletionManager;
import ch.colabproject.colab.api.controller.document.ExternalDataManager;
import ch.colabproject.colab.api.controller.monitoring.CronJobLogManager;
import ch.colabproject.colab.api.model.monitoring.CronJobLogName;
Expand Down Expand Up @@ -42,13 +43,17 @@ public class CronTab {
@Inject
private CronJobLogManager cronJobLogManager;

/** To access coLAB entities for deletion */
@Inject
private DeletionManager deletionManager;

/**
* Each minute
*/
@Schedule(hour = "*", minute = "*", persistent = false)
public void saveActivityDates() {
logger.trace("CRON: Persist activity dates to database");
sessionManager.writeActivityDatesToDatabase();
sessionManager.writeActivityDatesToDatabaseInTrn();
cronJobLogManager.updateCronJobLogLastRunTime(CronJobLogName.SAVE_ACTIVITIES_DATE);
}

Expand All @@ -58,7 +63,7 @@ public void saveActivityDates() {
@Schedule(hour = "0", minute = "0", persistent = false)
public void dropOldHttpSession() {
logger.info("CRON: drop expired http session");
sessionManager.clearExpiredHttpSessions();
sessionManager.clearExpiredHttpSessionsInTrn();
cronJobLogManager.updateCronJobLogLastRunTime(CronJobLogName.DROP_OLD_HTTP_SESSIONS);
}

Expand All @@ -71,4 +76,24 @@ public void dropOldUrlMetadata() {
externalDataManager.clearOutdated();
cronJobLogManager.updateCronJobLogLastRunTime(CronJobLogName.DROP_OLD_URL_METADATA);
}

/**
* each one o'clock, definitively delete data
*/
@Schedule(hour = "1", minute = "0", persistent = false)
public void cleanBinColabEntities() {
logger.info("CRON: clean bin");
deletionManager.cleanBinInTrn();
cronJobLogManager.updateCronJobLogLastRunTime(CronJobLogName.CLEAN_BIN);
}

/**
* each one o'clock, definitively delete data
*/
@Schedule(hour = "1", minute = "30", persistent = false)
public void deleteForeverColabEntities() {
logger.info("CRON: Delete forever old obsolete colab entities");
deletionManager.deleteForeverInTrn();
cronJobLogManager.updateCronJobLogLastRunTime(CronJobLogName.DELETE_FOREVER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package ch.colabproject.colab.api.controller.card;

import ch.colabproject.colab.api.Helper;
import ch.colabproject.colab.api.controller.common.DeletionManager;
import ch.colabproject.colab.api.controller.document.DocumentManager;
import ch.colabproject.colab.api.controller.document.IndexGeneratorHelper;
Expand All @@ -16,10 +17,12 @@
import ch.colabproject.colab.api.model.card.CardContent;
import ch.colabproject.colab.api.model.card.CardContentStatus;
import ch.colabproject.colab.api.model.common.ConversionStatus;
import ch.colabproject.colab.api.model.common.DeletionStatus;
import ch.colabproject.colab.api.model.document.Document;
import ch.colabproject.colab.api.model.link.StickyNoteLink;
import ch.colabproject.colab.api.persistence.jpa.card.CardContentDao;
import ch.colabproject.colab.api.persistence.jpa.document.DocumentDao;
import ch.colabproject.colab.api.setup.ColabConfiguration;
import ch.colabproject.colab.generator.model.exceptions.HttpErrorMessage;
import ch.colabproject.colab.generator.model.exceptions.MessageI18nKey;
import org.slf4j.Logger;
Expand Down Expand Up @@ -296,30 +299,62 @@ public void restoreCardContentFromBin(Long cardContentId) {
/**
* Set the deletion status to TO_DELETE.
* <p>
* It means that the card content is only visible in the bin panel.
* It means that the card content is no more visible.
*
* @param cardContentId the id of the card content
*/
public void markCardContentAsToDeleteForever(Long cardContentId) {
logger.debug("mark card content #{} as to delete forever", cardContentId);
public void flagCardContentAsToDeleteForever(Long cardContentId) {
logger.debug("flag card content #{} as to delete forever", cardContentId);

CardContent cardContent = assertAndGetCardContent(cardContentId);

if (!checkDeletionAcceptability(cardContent)) {
throw HttpErrorMessage.dataError(MessageI18nKey.DATA_INTEGRITY_FAILURE);
}

deletionManager.markAsToDeleteForever(cardContent);
deletionManager.flagAsToDeleteForever(cardContent);
}

/**
* For the card contents which are since a long time in bin, set the deletion status to TO_DELETE.
* <p>
* It means that the card contents are no more visible.
*/
public void removeOldCardContentsFromBin() {
int nbWaitingDays = ColabConfiguration.getNbDaysToWaitBeforeBinCleaning();

List<CardContent> oldCardContentsToRemoveFromBin =
cardContentDao.findOldDeletedCardContents(DeletionStatus.BIN, nbWaitingDays);

logger.debug("Remove from bin {} card contents since more than {} days in bin",
oldCardContentsToRemoveFromBin.size(), nbWaitingDays);

oldCardContentsToRemoveFromBin
.forEach(cardContent ->
deletionManager.flagAsToDeleteForever(Helper.SCHEDULED_JOB, cardContent));
}

/**
* Delete the card contents ready to be deleted
*/
public void deleteForeverOldCardContents() {
int nbWaitingDays = ColabConfiguration.getNbDaysToWaitBeforePermanentDeletion();

List<CardContent> oldToDeleteCardContents =
cardContentDao.findOldDeletedCardContents(DeletionStatus.TO_DELETE, nbWaitingDays);

logger.debug("Forever deletion of {} older than {} days card contents",
oldToDeleteCardContents.size(), nbWaitingDays);

oldToDeleteCardContents.forEach(this::deleteCardContent);
}

/**
* Delete the given card content
*
* @param cardContentId the id of the card content to delete
* @param cardContent the card content to delete
*/
public void deleteCardContent(Long cardContentId) {
CardContent cardContent = assertAndGetCardContent(cardContentId);

public void deleteCardContent(CardContent cardContent) {
if (!checkDeletionAcceptability(cardContent)) {
throw HttpErrorMessage.dataError(MessageI18nKey.DATA_INTEGRITY_FAILURE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
*/
package ch.colabproject.colab.api.controller.card;

import ch.colabproject.colab.api.Helper;
import ch.colabproject.colab.api.controller.card.grid.Grid;
import ch.colabproject.colab.api.controller.card.grid.GridPosition;
import ch.colabproject.colab.api.controller.common.DeletionManager;
import ch.colabproject.colab.api.controller.document.ResourceReferenceSpreadingHelper;
import ch.colabproject.colab.api.controller.token.TokenManager;
import ch.colabproject.colab.api.model.card.AbstractCardType;
import ch.colabproject.colab.api.model.card.Card;
import ch.colabproject.colab.api.model.card.CardContent;
import ch.colabproject.colab.api.model.card.CardType;
import ch.colabproject.colab.api.model.common.DeletionStatus;
import ch.colabproject.colab.api.model.link.ActivityFlowLink;
import ch.colabproject.colab.api.model.link.StickyNoteLink;
import ch.colabproject.colab.api.model.project.Project;
import ch.colabproject.colab.api.model.team.acl.Assignment;
import ch.colabproject.colab.api.persistence.jpa.card.CardDao;
import ch.colabproject.colab.api.setup.ColabConfiguration;
import ch.colabproject.colab.generator.model.exceptions.HttpErrorMessage;
import ch.colabproject.colab.generator.model.exceptions.MessageI18nKey;
import org.slf4j.Logger;
Expand Down Expand Up @@ -70,6 +74,10 @@ public class CardManager {
@Inject
private CardContentManager cardContentManager;

/** Token Facade */
@Inject
private TokenManager tokenManager;

/**
* Resource reference spreading specific logic handling
*/
Expand Down Expand Up @@ -403,30 +411,65 @@ private boolean isAnyAncestorDeleted(Card card) {
/**
* Set the deletion status to TO_DELETE.
* <p>
* It means that the card is only visible in the bin panel.
* It means that the card is no more visible.
*
* @param cardId the id of the card
*/
public void markCardAsToDeleteForever(Long cardId) {
logger.debug("mark card #{} as to delete forever", cardId);
public void flagCardAsToDeleteForever(Long cardId) {
logger.debug("flag card #{} as to delete forever", cardId);

Card card = assertAndGetCard(cardId);

deletionManager.markAsToDeleteForever(card);
deletionManager.flagAsToDeleteForever(card);
}

/**
* For the cards which are since a long time in bin, set the deletion status to TO_DELETE.
* <p>
* It means that the cards are no more visible.
*/
public void removeOldCardsFromBin() {
int nbWaitingDays = ColabConfiguration.getNbDaysToWaitBeforeBinCleaning();

List<Card> oldCardsToRemoveFromBin =
cardDao.findOldDeletedCards(DeletionStatus.BIN, nbWaitingDays);

logger.debug("Remove from bin {} cards since more than {} days in bin",
oldCardsToRemoveFromBin.size(), nbWaitingDays);

oldCardsToRemoveFromBin
.forEach(card -> {
deletionManager.flagAsToDeleteForever(Helper.SCHEDULED_JOB, card);
});
}

/**
* Delete the cards ready to be deleted
*/
public void deleteForeverOldCards() {
int nbWaitingDays = ColabConfiguration.getNbDaysToWaitBeforePermanentDeletion();

List<Card> oldToDeleteCards =
cardDao.findOldDeletedCards(DeletionStatus.TO_DELETE, nbWaitingDays);

logger.debug("Forever deletion of {} older than {} days cards",
oldToDeleteCards.size(), nbWaitingDays);

oldToDeleteCards.forEach(this::deleteCard);
}

/**
* Delete the given card
*
* @param cardId the id of the card to delete
* @param card the card to delete
*/
public void deleteCard(Long cardId) {
Card card = assertAndGetCard(cardId);

private void deleteCard(Card card) {
if (!checkDeletionAcceptability(card)) {
throw HttpErrorMessage.dataError(MessageI18nKey.DATA_INTEGRITY_FAILURE);
}

tokenManager.deleteSharingLinkTokensByCard(card);

card.getParent().getSubCards().remove(card);

if (card.hasCardType()) {
Expand Down
Loading