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

General: Add cleanup service for admins #9296

Open
wants to merge 142 commits into
base: develop
Choose a base branch
from

Conversation

coolchock
Copy link
Contributor

@coolchock coolchock commented Sep 7, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding and design guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I added authorities to all new routes and checked the course groups for displaying navigation elements (links, buttons).
  • I documented the TypeScript code using JSDoc style.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Motivation and Context

Artemis stores a large amount of information, some of which can become corrupted or irrelevant over time. These records occupy significant database space, which can be reclaimed by deleting unused data. This includes old results, unresolved plagiarism cases, and unused feedback.

Currently, there are scripts for cleaning up results and feedback, but no automated process exists for clearing unresolved plagiarism cases. Additionally, orphaned entities, such as results without associated submissions or participation, remain unaddressed, leading to inefficient database usage. Furthermore, these cleanup scripts must be run manually by administrators, which is not ideal. To address these issues, a dedicated cleanup service for administrators was implemented to streamline the process.

Description

A cleanup service has been added to the admin panel, allowing administrators to select specific cleanup operations to perform on the database. They can specify a time period for which the cleanup should be executed, providing flexibility in managing old or unused data. In future iterations, a scheduled job is planned to be introduced, which will automatically execute the cleanup operations periodically, reducing the need for manual intervention and ensuring ongoing database optimization.

Steps for Testing

Prerequisites:

  • 1 Administrator
  • 1 Test Server where you have access rights
  • Test data generated using large_course_main.py script. See README in the folder quick-course-setup for more details.
  1. Log in to Artemis.
  2. Navigate to course management and select the course created by the script.
  3. Set the start and end dates of the course within the period for which you will delete data.
  4. Open the programming exercise created by the script and go to the Plagiarism section.
  5. Set the threshold to 0 and execute plagiarism detection. You should receive a few results.
  6. In Server Administration -> Cleanup Service, execute "Delete plagiarism comparisons."
  7. Verify that the plagiarism comparisons were deleted.
  8. Execute the "Delete old rated results" operation.
  9. Verify that only the last student submission has a linked result.
  10. Set the end date for the programming exercise to a past date and start a practice mode participation.
  11. In the cleanup service, execute "Delete non-rated results."
  12. Verify that the practice mode submission no longer has a linked result.

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Info: ✅ ❌ in Confirmation (assert/expect) have to be adjusted manually, also delete trivial files!

Client

Class/File Line Coverage Confirmation (assert/expect)
admin.route.ts not found (modified)
cleanup-operation.model.ts 0% ✅ ❌
cleanup-service.component.ts 82.5% ✅ ❌
data-cleanup.service.ts.ts 100%
date-time-picker.component.ts 96.66% ✅ ❌
navbar.component.ts 87.76% ✅ ❌

Server

Class/File Line Coverage Confirmation (assert/expect)
FeedbackRepository.java 86% ✅ ❌
LongFeedbackTextRepository.java 100%
ParticipantScoreRepository.java 81% ✅ ❌
RatingRepository.java not found (modified)
ResultRepository.java 96% ✅ ❌
StudentScoreRepository.java not found (modified)
TeamScoreRepository.java not found (modified)
TextBlockRepository.java not found (modified)
CleanupJobExecution.java 80% ✅ ❌
CleanupJobType.java 100%
CleanupServiceExecutionRecordDTO.java 100%
CleanupJobExecutionRepository.java not found (added)
DataCleanupService.java 100%
AdminOldDataCleanupResource.java 100%
PlagiarismComparisonRepository.java 100%

Screenshots

View from the navigation bar
image

Cleanup service
image

Confirmation dialog
image

Summary by CodeRabbit

  • New Features

    • Introduced a new CleanupServiceComponent for managing data cleanup operations in the admin interface.
    • Added a new route for the CleanupServiceComponent in the admin module.
    • Enhanced the navbar with a new cleanup icon and breadcrumb translation for the cleanup service.
    • Added multiple new cleanup repository interfaces and methods for managing orphaned and outdated data across various entities.
    • Added new translations for the cleanup service in both German and English.
  • Bug Fixes

    • Clarified transactional behavior in various repository methods to improve code readability.
  • Documentation

    • Added new documentation for the Cleanup Service, detailing data deletion operations and types.
    • Updated the index to include the new cleanup service documentation.
  • Tests

    • Added comprehensive integration tests for various cleanup operations to ensure data integrity.

@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) labels Sep 7, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8b5eb3d and df5565d.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (1)
  • src/main/webapp/app/admin/admin.route.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/admin/admin.route.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

🔇 Additional comments (2)
src/main/webapp/app/admin/admin.route.ts (2)

23-23: LGTM! Import statement follows Angular guidelines.

The import statement follows proper Angular conventions with correct component naming and module organization.


154-160: Verify navbar integration and translations.

The route is properly configured, but let's ensure it's fully integrated with the navigation system.

✅ Verification successful

Route is properly integrated with navbar and translations

The verification confirms that:

  • The route is referenced in the navbar template (src/main/webapp/app/shared/layouts/navbar/navbar.component.html)
  • Translation keys exist in both English and German:
    • Menu item: global.menu.admin.cleanupService
    • Page title: cleanupService.title
    • All required table translations in cleanupService.json
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify navbar integration and translations for the cleanup service

# Test 1: Check if the route is referenced in the navbar template
echo "Checking navbar template for cleanup service link..."
rg -l "cleanup-service" "src/main/webapp/app/layouts/"

# Test 2: Verify translation key exists
echo "Checking translation files for 'cleanupService.title'..."
rg -l "cleanupService.title" "src/main/webapp/i18n/"

Length of output: 416


Script:

#!/bin/bash
# Let's try a broader search to locate the navbar and translation files

# Find navbar-related files
echo "Finding navbar-related files..."
fd navbar

# Find translation files
echo "Finding translation files..."
fd "\.json$" --type f

# Once we find the files, let's check their content
echo "Checking for cleanup-service route references..."
rg -l "cleanup-service"

# Check for translation key pattern
echo "Checking for cleanupService translations..."
rg "cleanupService"

Length of output: 37479

src/main/webapp/app/admin/admin.route.ts Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

35-42: Enhance readability by uppercasing SQL keywords

Per the coding guidelines (sql:uppercase), SQL keywords should be in uppercase to improve readability and maintain consistency across the codebase. Please update the SQL queries in the methods to use uppercase keywords.

Apply these diffs to update the queries:

For deleteLongFeedbackTextForOrphanResult() (lines 35-42):

 @Query("""
-        delete from LongFeedbackText lft
-        where lft.feedback.id in (
-            select f.id
-            from Feedback f
-            where f.result.participation is null
-                and f.result.submission is null
-            )
+        DELETE FROM LongFeedbackText lft
+        WHERE lft.feedback.id IN (
+            SELECT f.id
+            FROM Feedback f
+            WHERE f.result.participation IS NULL
+                AND f.result.submission IS NULL
+            )
        """)

For deleteLongFeedbackTextForOrphanedFeedback() (lines 52-58):

 @Query("""
-        delete from LongFeedbackText lft
-        where lft.feedback in (
-            select f
-            from Feedback f
-            where f.result is null
-            )
+        DELETE FROM LongFeedbackText lft
+        WHERE lft.feedback IN (
+            SELECT f
+            FROM Feedback f
+            WHERE f.result IS NULL
+            )
        """)

For deleteLongFeedbackTextForRatedResultsWhereCourseDateBetween() (lines 73-90):

 @Query("""
-        delete from LongFeedbackText lft
-        where lft.feedback in (
-            select f
-            from Feedback f
-                left join f.result r
-                left join r.participation p
-                left join p.exercise e
-                left join e.course c
-            where f.result.id not in (
-                select max(r2.id)
-                from Result r2
-                where r2.participation.id = p.id
-                    and r2.rated = true
-                )
-                and c.endDate < :deleteTo
-                and c.startDate > :deleteFrom
-            )
+        DELETE FROM LongFeedbackText lft
+        WHERE lft.feedback IN (
+            SELECT f
+            FROM Feedback f
+                LEFT JOIN f.result r
+                LEFT JOIN r.participation p
+                LEFT JOIN p.exercise e
+                LEFT JOIN e.course c
+            WHERE f.result.id NOT IN (
+                SELECT MAX(r2.id)
+                FROM Result r2
+                WHERE r2.participation.id = p.id
+                    AND r2.rated = TRUE
+                )
+                AND c.endDate < :deleteTo
+                AND c.startDate > :deleteFrom
+            )
        """)

For deleteLongFeedbackTextForNonRatedResultsWhereCourseDateBetween() (lines 105-122):

 @Query("""
-        delete from LongFeedbackText lft
-        where lft.feedback in (
-            select f
-            from Feedback f
-                left join f.result r
-                left join r.participation p
-                left join p.exercise e
-                left join e.course c
-            where f.result.id not in (
-                select max(r2.id)
-                from Result r2
-                where r2.participation.id = p.id
-                    and r2.rated = false
-                )
-                and c.endDate < :deleteTo
-                and c.startDate > :deleteFrom
-            )
+        DELETE FROM LongFeedbackText lft
+        WHERE lft.feedback IN (
+            SELECT f
+            FROM Feedback f
+                LEFT JOIN f.result r
+                LEFT JOIN r.participation p
+                LEFT JOIN p.exercise e
+                LEFT JOIN e.course c
+            WHERE f.result.id NOT IN (
+                SELECT MAX(r2.id)
+                FROM Result r2
+                WHERE r2.participation.id = p.id
+                    AND r2.rated = FALSE
+                )
+                AND c.endDate < :deleteTo
+                AND c.startDate > :deleteFrom
+            )
        """)

Also applies to: 52-58, 73-90, 105-122

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between df5565d and ff94897.

📒 Files selected for processing (7)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/PlagiarismComparisonCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/StudentScoreCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TeamScoreCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/PlagiarismComparisonCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/StudentScoreCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TeamScoreCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (1)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

26-124: Overall implementation adheres to best practices

The repository interface is well-defined, and the methods align with the cleanup objectives described in the PR. The use of appropriate annotations and parameterization is consistent with the coding guidelines.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (3)

31-31: Improve transaction documentation.

The comment "ok because of delete" doesn't provide sufficient context about why this transaction is acceptable despite the avoid_transactions guideline. Consider expanding the documentation to explain the necessity of the transaction for data consistency in this cleanup operation.


74-80: Enhance method documentation.

While the documentation explains the purpose, it would be helpful to add:

  • Expected behavior for edge cases (e.g., what happens if there are multiple results with the same timestamp?)
  • Performance characteristics for large datasets
  • Example scenarios showing the before and after state

1-105: Consider performance impact of cleanup operations.

The cleanup operations involve complex queries and deletions that could impact system performance. Consider:

  1. Adding batch processing to handle large deletions
  2. Implementing rate limiting or chunking for large datasets
  3. Adding monitoring/logging to track cleanup operation duration and impact
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ff94897 and ab28dd2.

📒 Files selected for processing (4)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/FeedbackRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1 hunks)
  • src/main/webapp/i18n/de/global.json (1 hunks)
  • src/main/webapp/i18n/en/global.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/FeedbackRepository.java
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/webapp/i18n/de/global.json (1)

Pattern src/main/webapp/i18n/de/**/*.json: German language translations should be informal (dutzen) and should never be formal (sietzen). So the user should always be addressed with "du/dein" and never with "sie/ihr".

🔇 Additional comments (4)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (2)

1-25: LGTM! Well-structured repository interface.

The class is well-organized with proper imports, documentation, and Spring annotations. It follows the repository pattern and Java conventions.


61-62: Review date range logic.

The current date conditions c.endDate < :deleteTo AND c.startDate > :deleteFrom might be counterintuitive. This would only match courses that:

  • Started after the deleteFrom date
  • Ended before the deleteTo date

This means a course that spans the entire period would be excluded. Consider if you meant:

c.startDate < :deleteTo AND c.endDate > :deleteFrom
src/main/webapp/i18n/en/global.json (1)

119-120: LGTM! The new menu entry follows existing conventions.

The addition of the "cleanupService" entry in the admin menu section is appropriate and well-placed. The key and value follow the established naming conventions (camelCase for keys, Title Case for values) used throughout the file, maintaining consistency with other menu items.

src/main/webapp/i18n/de/global.json (1)

119-120: LGTM! The translation and placement look good.

The German translation "Aufräumdienst" for the cleanup service is appropriate and follows the informal language requirement. The entry is properly placed within the admin section.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ab28dd2 and a03e853.

📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (3)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (3)

1-26: LGTM! Well-structured repository interface.

The class follows all coding guidelines including proper package naming, specific imports (no star imports), and appropriate Spring annotations.


28-39: LGTM! Clean and efficient orphaned result cleanup.

The method follows SQL best practices with uppercase keywords and uses appropriate annotations. The transaction usage is properly justified in the comment.


41-54: LGTM! Well-optimized query for latest results.

The method is well-documented and implements an efficient query pattern using MAX and GROUP BY without subqueries.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 29, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🧹 Outside diff range and nitpick comments (7)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1)

73-81: Enhance method documentation with performance implications.

While the documentation clearly explains the functionality, it would be helpful to add information about:

  • Expected execution time for large datasets
  • Potential impact on database performance during deletion
  • Recommended batch size or time window constraints
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1)

24-32: Enhance method documentation

While the documentation is thorough, consider adding:

  • Example usage scenarios
  • Information about potential exceptions
  • Explicit mention of void return type

Example enhancement:

/**
 * Deletes {@link ParticipantScore} entries where the associated {@link Result} is not the latest rated result
 * for a {@link Participation}, within courses conducted between the specified date range.
 * This query removes participant scores linked to results that are not the most recent rated results, for courses
 * whose end date is before {@code deleteTo} and start date is after {@code deleteFrom}.
 *
 * @param deleteFrom the start date for selecting courses
 * @param deleteTo   the end date for selecting courses
 * @return void
 * @throws IllegalArgumentException if deleteFrom is after deleteTo
 * 
 * Example:
 * <pre>
 * ZonedDateTime from = ZonedDateTime.now().minusYears(1);
 * ZonedDateTime to = ZonedDateTime.now();
 * repository.deleteParticipantScoresForNonLatestLastResultsWhereCourseDateBetween(from, to);
 * </pre>
 */

Also applies to: 56-64, 88-96, 119-128

src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (4)

60-60: Add class-level documentation.

Add a comprehensive Javadoc comment to describe the purpose of this integration test class, the cleanup operations being tested, and any important setup requirements.

Example:

/**
 * Integration tests for the cleanup service that handles deletion of outdated or irrelevant data.
 * Tests cover:
 * - Deletion of orphaned entities (feedback, scores, results)
 * - Cleanup of old plagiarism comparisons
 * - Removal of non-rated and rated results
 * - Access control for cleanup operations
 *
 * The tests use two courses (old and new) to verify that cleanup operations correctly target
 * data based on course dates while preserving current data.
 */
@IntegrationTest
class CleanupIntegrationTest extends AbstractSpringIntegrationJenkinsGitlabTest {

64-66: Document date constants and their significance.

The date constants DELETE_FROM and DELETE_TO lack documentation explaining their purpose and why these specific time ranges were chosen.

Add comments to explain:

/**
 * Start date for cleanup operations, set to 12 months ago to cover old data
 */
private static final ZonedDateTime DELETE_FROM = ZonedDateTime.now().minusMonths(12);

/**
 * End date for cleanup operations, set to 6 months ago to preserve recent data
 */
private static final ZonedDateTime DELETE_TO = ZonedDateTime.now().minusMonths(6);

536-548: Enhance helper method documentation and validation.

The createFeedbackWithLinkedLongFeedback method needs documentation and validation.

Add Javadoc and validation:

/**
 * Creates a Feedback entity with an associated LongFeedbackText.
 * The text content is generated using the feedback's hashcode.
 *
 * @return The persisted Feedback entity with linked LongFeedbackText
 */
private Feedback createFeedbackWithLinkedLongFeedback() {
    Objects.requireNonNull(feedbackRepository, "FeedbackRepository must be initialized");
    
    Feedback feedback = new Feedback();
    feedback = feedbackRepository.save(feedback);
    // ... rest of the method
}

550-556: Add validation to createTextBlockForFeedback.

The createTextBlockForFeedback method should validate its input parameter.

Add validation:

/**
 * Creates a TextBlock entity associated with the given Feedback.
 * The text content is generated using the feedback's hashcode.
 *
 * @param feedback The Feedback entity to associate with the TextBlock
 * @return The persisted TextBlock entity
 * @throws IllegalArgumentException if feedback is null
 */
private TextBlock createTextBlockForFeedback(Feedback feedback) {
    Objects.requireNonNull(feedback, "Feedback must not be null");
    Objects.requireNonNull(textBlockRepository, "TextBlockRepository must be initialized");
    
    TextBlock textBlock = new TextBlock();
    textBlock.setFeedback(feedback);
    textBlock.setText("text" + feedback.hashCode());
    textBlock.computeId();
    return textBlockRepository.save(textBlock);
}
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java (1)

109-109: Use lowercase Boolean literals in JPQL queries

In the query for deleteOldNonRatedFeedbackWhereCourseDateBetween(), the condition AND r.rated = FALSE uses uppercase FALSE. JPQL recognizes lowercase true and false literals.

Consider changing FALSE to lowercase false for consistency and correctness:

-                    AND r.rated = FALSE
+                    AND r.rated = false
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a03e853 and 86c32b3.

📒 Files selected for processing (7)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java
🧰 Additional context used
📓 Path-based instructions (6)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

🪛 ast-grep
src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java

[warning] 176-177: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExerciseRepository.findByCourseIdWithCategories(newCourse.getId()).getFirst(), new ProgrammingSubmission(),
student.getLogin())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 212-212: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-orphans", new LinkedMultiValueMap<>(), null, CleanupServiceExecutionRecordDTO.class, HttpStatus.OK)
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 241-241: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 242-242: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 243-243: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 254-254: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 255-255: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 256-256: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 293-293: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new PlagiarismMatch())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 311-311: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new PlagiarismMatch())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 526-526: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-orphans", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 527-527: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-plagiarism-comparisons", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 528-528: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-non-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 529-529: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-old-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 530-530: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-old-submission-versions", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 531-531: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-old-feedback", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 176-177: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExerciseRepository.findByCourseIdWithCategories(newCourse.getId()).getFirst(), new ProgrammingSubmission(),
student.getLogin())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 212-212: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-orphans", new LinkedMultiValueMap<>(), null, CleanupServiceExecutionRecordDTO.class, HttpStatus.OK)
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 241-241: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 242-242: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 243-243: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 254-254: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 255-255: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 256-256: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 293-293: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new PlagiarismMatch())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 311-311: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new PlagiarismMatch())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 526-526: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-orphans", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 527-527: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-plagiarism-comparisons", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 528-528: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-non-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 529-529: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-old-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 530-530: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-old-submission-versions", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 531-531: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-old-feedback", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

🔇 Additional comments (5)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (3)

1-22: LGTM! Well-structured repository interface.

The class is properly organized with specific imports, clear documentation, and appropriate annotations.


24-35: LGTM! Clean and efficient implementation.

The method effectively handles cleanup of orphaned results with a straightforward query and proper transaction management.


37-71: 🛠️ Refactor suggestion

Consider adding index hint for performance optimization.

The query involves multiple joins and conditions on the course dates. Consider adding an index hint to leverage the appropriate index for the date range scan, which could significantly improve query performance.

 @Query("""
-            DELETE FROM Result r
+            DELETE /*+ INDEX(c course_dates_idx) */ FROM Result r

Likely invalid or redundant comment.

src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1)

348-348: ⚠️ Potential issue

Fix incorrect entity being saved.

There's a bug where oldParticipantScore2 is saving oldParticipantScore1 instead of itself.

Apply this fix:

-oldParticipantScore2 = studentScoreRepository.save(oldParticipantScore1);
+oldParticipantScore2 = studentScoreRepository.save(oldParticipantScore2);

Likely invalid or redundant comment.

src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1)

149-153: ⚠️ Potential issue

Ensure compatibility with Java versions prior to 16 by adjusting stream operations.

The use of .toList() in streams is a feature introduced in Java 16. If the project targets Java versions prior to 16, this may cause compatibility issues. Consider using Collectors.toList() instead to maintain compatibility.

Apply this change:

 }).toList();
+}).collect(Collectors.toList());

Ensure this aligns with the project's Java version compatibility requirements.

Run the following script to check the project's Java version setting:

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (6)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (3)

19-22: Enhance class documentation

The current documentation could be more specific about:

  • When and why these cleanup methods should be used
  • The potential impact of running these cleanup operations
  • Any prerequisites or considerations before using these methods

Consider expanding the documentation:

/**
 * Spring Data JPA repository for cleaning up old and orphaned participant scores.
 * This repository provides methods to clean up:
 * - Participant scores linked to non-latest rated results
 * - Participant scores with inconsistent rated/non-rated status
 * - Participant scores within specific course date ranges
 * 
 * IMPORTANT: These cleanup methods permanently delete data and should only be used:
 * - During scheduled maintenance windows
 * - After backing up the database
 * - With appropriate date ranges to avoid affecting active courses
 */

27-35: Enhance method documentation

The documentation should include:

  • The impact of running this cleanup
  • Any prerequisites or validations that should be performed
  • Examples of typical date ranges

Consider expanding the documentation:

/**
 * Deletes {@link ParticipantScore} entries where the associated {@link Result} is not the latest rated result
 * for a {@link Participation}, within courses conducted between the specified date range.
 * This query removes participant scores linked to results that are not the most recent rated results, for courses
 * whose end date is before {@code deleteTo} and start date is after {@code deleteFrom}.
 *
 * IMPORTANT: This operation permanently deletes data. Ensure that:
 * - The date range excludes active courses
 * - A database backup exists
 * - No assessments are in progress
 *
 * @param deleteFrom the start date for selecting courses (e.g., "2023-01-01")
 * @param deleteTo   the end date for selecting courses (e.g., "2023-06-30")
 * @throws IllegalArgumentException if deleteFrom is after deleteTo
 */

118-118: Fix query formatting

The closing parenthesis is misaligned, affecting readability.

-                    AND c.startDate > :deleteFrom                                                                       )
+                    AND c.startDate > :deleteFrom
+                )
src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1)

64-64: Add class-level documentation.

Add a comprehensive Javadoc comment to describe the purpose and scope of this integration test class.

/**
 * Integration tests for the cleanup service functionality.
 * Tests various cleanup operations including:
 * - Deletion of orphaned data
 * - Cleanup of plagiarism comparisons
 * - Removal of non-rated and old rated results
 * - Verification of cleanup job execution records
 */
class CleanupIntegrationTest extends AbstractSpringIntegrationJenkinsGitlabTest {
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (2)

70-92: Consider inclusive date comparisons in the query.

The query uses strict inequality operators c.endDate < :deleteTo and c.startDate > :deleteFrom. If the intention is to include courses that end exactly on deleteTo or start exactly on deleteFrom, consider using <= and >= to make the date range inclusive.


106-125: Mirror inclusive date comparisons for consistency.

Similar to the previous method, adjust the date comparisons in the query to use <= and >= if you want to include courses that start or end on the boundary dates. This ensures consistency and avoids unintentional exclusion of courses on those dates.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 86c32b3 and ec82065.

📒 Files selected for processing (6)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/FeedbackCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java
🧰 Additional context used
📓 Path-based instructions (4)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

🪛 ast-grep
src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java

[warning] 180-181: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExerciseRepository.findByCourseIdWithCategories(newCourse.getId()).getFirst(), new ProgrammingSubmission(),
student.getLogin())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 216-216: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-orphans", new LinkedMultiValueMap<>(), null, CleanupServiceExecutionRecordDTO.class, HttpStatus.OK)
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 245-245: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 246-246: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 247-247: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 258-258: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 259-259: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 260-260: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 297-297: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new PlagiarismMatch())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 315-315: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new PlagiarismMatch())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 530-530: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-orphans", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 531-531: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-plagiarism-comparisons", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 532-532: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-non-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 533-533: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-old-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 534-534: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-old-submission-versions", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 535-535: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/admin/cleanup/delete-old-feedback", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 180-181: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExerciseRepository.findByCourseIdWithCategories(newCourse.getId()).getFirst(), new ProgrammingSubmission(),
student.getLogin())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 216-216: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-orphans", new LinkedMultiValueMap<>(), null, CleanupServiceExecutionRecordDTO.class, HttpStatus.OK)
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 245-245: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 246-246: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 247-247: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise1, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 258-258: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student1")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 259-259: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student2")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 260-260: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (textExercise2, ParticipationFactory.generateTextSubmission("", Language.GERMAN, true), TEST_PREFIX + "student3")
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 297-297: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new PlagiarismMatch())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 315-315: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new PlagiarismMatch())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 530-530: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-orphans", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 531-531: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-plagiarism-comparisons", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 532-532: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-non-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 533-533: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-old-rated-results", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 534-534: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-old-submission-versions", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 535-535: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/admin/cleanup/delete-old-feedback", HttpStatus.FORBIDDEN, new LinkedMultiValueMap<>())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

🔇 Additional comments (3)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1)

122-131: LGTM! Well-documented edge case handling

The documentation clearly explains the purpose of this cleanup method and the edge case it handles for maintaining data integrity.

src/test/java/de/tum/cit/aet/artemis/core/CleanupIntegrationTest.java (1)

352-352: ⚠️ Potential issue

Fix incorrect entity being saved.

The wrong entity is being saved to the repository.

-oldParticipantScore2 = studentScoreRepository.save(oldParticipantScore1);
+oldParticipantScore2 = studentScoreRepository.save(oldParticipantScore2);

Likely invalid or redundant comment.

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

52-59: Good implementation of deleteLongFeedbackTextForOrphanedFeedback.

The method correctly deletes LongFeedbackText entries linked to Feedback with a null Result, effectively cleaning up orphaned feedback texts.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1)

25-25: Consider adding preview capabilities for administrators.

To enhance administrator confidence when performing cleanup operations, consider adding methods that:

  1. Return statistics about what would be deleted (e.g., count of results by type, age distribution)
  2. Support dry-run mode to preview which records would be affected

This would help administrators validate the scope and impact of cleanup operations before execution.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ec82065 and 9e0e807.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (2)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ResultCleanupRepository.java (2)

1-25: LGTM! Well-structured repository interface.

The class is properly organized with specific imports and appropriate annotations. The documentation clearly indicates the purpose and usage restrictions.


27-38: LGTM! Clean and efficient implementation.

The method effectively handles orphaned result cleanup with a straightforward query. The transaction annotation is properly justified in the comment.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 30, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9e0e807 and 6d75d51.

⛔ Files ignored due to path filters (1)
  • docs/admin/cleanup/cleanup-menu.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (6)
  • docs/admin/cleanup-service.rst (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminCleanupResource.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/admin/cleanup-service.rst
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminCleanupResource.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (3)
Learnt from: undernagruzez
PR: ls1intum/Artemis#9296
File: src/main/java/de/tum/in/www1/artemis/repository/cleanup/DataCleanupRepository.java:8-8
Timestamp: 2024-09-13T11:32:35.988Z
Learning: In the `DataCleanupRepository` interface, the `deleteOrphans()` method is intended to delete all orphan entities that are important in the context and does not require a parameter to specify the entity type.
Learnt from: undernagruzez
PR: ls1intum/Artemis#9296
File: src/main/java/de/tum/in/www1/artemis/repository/cleanup/DataCleanupRepository.java:8-8
Timestamp: 2024-10-08T15:35:42.972Z
Learning: In the `DataCleanupRepository` interface, the `deleteOrphans()` method is intended to delete all orphan entities that are important in the context and does not require a parameter to specify the entity type.
Learnt from: undernagruzez
PR: ls1intum/Artemis#9296
File: src/main/java/de/tum/in/www1/artemis/repository/cleanup/DataCleanupRepository.java:8-8
Timestamp: 2024-10-08T15:35:48.768Z
Learning: In the `DataCleanupRepository` interface, the `deleteOrphans()` method is intended to delete all orphan entities that are important in the context and does not require a parameter to specify the entity type.
🔇 Additional comments (4)
src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (4)

28-65: Well-structured constructor with proper dependency injection

The constructor correctly utilizes constructor injection to manage dependencies, adhering to the coding guideline di:constructor_injection. All necessary repositories are injected, and their assignments are clear and concise.


128-136: ⚠️ Potential issue

Validate date parameters in deleteNonLatestRatedResults

Consistent input validation enhances reliability. Ensure deleteFrom and deleteTo are valid before proceeding with deletions.

Add validation as shown:

 public CleanupServiceExecutionRecordDTO deleteNonLatestRatedResults(ZonedDateTime deleteFrom, ZonedDateTime deleteTo) {
+    if (deleteFrom == null || deleteTo == null || deleteFrom.isAfter(deleteTo)) {
+        throw new IllegalArgumentException("Invalid date range provided.");
+    }
     this.longFeedbackTextCleanupRepository.deleteLongFeedbackTextForRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
     // Other deletion methods
     return CleanupServiceExecutionRecordDTO.of(this.createCleanupJobExecution(CleanupJobType.RATED_RESULTS, deleteFrom, deleteTo));
 }

Likely invalid or redundant comment.


149-154: Ensure compatibility of .toList() method with project Java version

The use of .toList() in streams is a Java 16 feature. Verify that the project targets Java 16 or higher to avoid compatibility issues.

Run the following script to check the project's Java version configuration:

✅ Verification successful

.toList() usage is compatible with project's Java version

The project is configured to use Java 21 as specified in build.gradle:

sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21

Since .toList() was introduced in Java 16 and the project uses Java 21, the usage is fully compatible and no changes are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the Java version specified in the project's build files.

# Check Gradle build files
rg 'sourceCompatibility\s*=\s*[\'"]1\.(\d+)[\'"]' build.gradle

# Check Maven POM files
rg '<maven.compiler.source>(.*?)</maven.compiler.source>' pom.xml

Length of output: 93


Script:

#!/bin/bash
# Let's try different approaches to find Java version information

# Check build.gradle with different patterns
rg "sourceCompatibility|targetCompatibility" build.gradle

# Check pom.xml with broader patterns
rg -A 2 "<java.version>|<maven.compiler" pom.xml

# Look for Spring Boot version which might indicate Java version
rg "spring-boot" pom.xml

# Check for any Gradle wrapper properties
fd "gradle-wrapper.properties" -x cat

# Check for any Java version related configuration in application properties
fd "application.properties|application.yml" -x cat

Length of output: 27107


95-99: ⚠️ Potential issue

Add input validation for date parameters in deletePlagiarismComparisons

To prevent unintended behavior and ensure robustness, validate that deleteFrom and deleteTo are not null and that deleteFrom is not after deleteTo. This aligns with best practices for error handling.

Consider adding validation as follows:

 public CleanupServiceExecutionRecordDTO deletePlagiarismComparisons(ZonedDateTime deleteFrom, ZonedDateTime deleteTo) {
+    if (deleteFrom == null || deleteTo == null || deleteFrom.isAfter(deleteTo)) {
+        throw new IllegalArgumentException("Invalid date range provided.");
+    }
     var pcIds = plagiarismComparisonCleanupRepository.findPlagiarismComparisonIdWithStatusNoneThatBelongToCourseWithDates(deleteFrom, deleteTo);
     plagiarismComparisonCleanupRepository.deleteByIdIn(pcIds);
     return CleanupServiceExecutionRecordDTO.of(this.createCleanupJobExecution(CleanupJobType.PLAGIARISM_COMPARISONS, deleteFrom, deleteTo));
 }

Likely invalid or redundant comment.

Comment on lines +156 to +167
private CleanupJobExecution createCleanupJobExecution(CleanupJobType cleanupJobType, ZonedDateTime deleteFrom, ZonedDateTime deleteTo) {
var entry = new CleanupJobExecution();
entry.setCleanupJobType(cleanupJobType);
if (deleteFrom != null) {
entry.setDeleteFrom(deleteFrom);
}
if (deleteTo != null) {
entry.setDeleteTo(deleteTo);
}
entry.setDeletionTimestamp(ZonedDateTime.now());
return this.cleanupJobExecutionRepository.save(entry);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using a builder pattern for CleanupJobExecution creation

Implementing a builder pattern can improve readability and maintainability, especially as the object construction logic grows.

Example:

CleanupJobExecution entry = CleanupJobExecution.builder()
    .cleanupJobType(cleanupJobType)
    .deleteFrom(deleteFrom)
    .deleteTo(deleteTo)
    .deletionTimestamp(ZonedDateTime.now())
    .build();

Ensure that the CleanupJobExecution class supports the builder pattern.

Comment on lines +110 to +118
public CleanupServiceExecutionRecordDTO deleteNonLatestNonRatedResults(ZonedDateTime deleteFrom, ZonedDateTime deleteTo) {
this.longFeedbackTextCleanupRepository.deleteLongFeedbackTextForNonRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
this.textBlockCleanupRepository.deleteTextBlockForNonRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
this.feedbackCleanupRepository.deleteOldNonRatedFeedbackWhereCourseDateBetween(deleteFrom, deleteTo);
this.participantScoreCleanupRepository.deleteParticipantScoresForLatestNonRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
this.participantScoreCleanupRepository.deleteParticipantScoresForNonRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
this.resultCleanupRepository.deleteNonLatestNonRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
return CleanupServiceExecutionRecordDTO.of(this.createCleanupJobExecution(CleanupJobType.NON_RATED_RESULTS, deleteFrom, deleteTo));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate date parameters in deleteNonLatestNonRatedResults

Adding input validation for deleteFrom and deleteTo ensures the method handles invalid inputs gracefully and prevents potential errors.

Apply the following change:

 public CleanupServiceExecutionRecordDTO deleteNonLatestNonRatedResults(ZonedDateTime deleteFrom, ZonedDateTime deleteTo) {
+    if (deleteFrom == null || deleteTo == null || deleteFrom.isAfter(deleteTo)) {
+        throw new IllegalArgumentException("Invalid date range provided.");
+    }
     this.longFeedbackTextCleanupRepository.deleteLongFeedbackTextForNonRatedResultsWhereCourseDateBetween(deleteFrom, deleteTo);
     // Other deletion methods
     return CleanupServiceExecutionRecordDTO.of(this.createCleanupJobExecution(CleanupJobType.NON_RATED_RESULTS, deleteFrom, deleteTo));
 }

Committable suggestion was skipped due to low confidence.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (5)
docs/admin/cleanup-service.rst (3)

13-23: Add safety warnings for irreversible operations.

Since deletion operations are irreversible and could affect course data, consider adding warning notes about:

  • The permanent nature of deletions
  • Recommendation to backup data before cleanup
  • Impact on related data and system performance during cleanup

Example addition:

.. warning::
   Cleanup operations are irreversible. It is recommended to:
   
   * Backup your data before performing cleanup operations
   * Run cleanup operations during off-peak hours
   * Review the date ranges carefully before proceeding

45-45: Enhance cleanup operation tracking details.

Consider expanding the documentation to include:

  • How to access the cleanup operation history
  • What information is logged for each operation
  • How long the cleanup operation records are retained

6-7: Document planned automation features.

The PR objectives mention future plans for scheduled cleanup jobs. Consider adding a section about:

  • Upcoming automation features
  • How scheduled cleanups will work
  • Configuration options for automated cleanup

This will help set expectations and provide a complete picture of the feature roadmap.

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

1-126: Consider implementing batch processing for large-scale cleanup

For databases with significant amounts of data, these cleanup operations could potentially affect performance. Consider:

  1. Implementing batch processing to delete records in chunks
  2. Adding a limit parameter to control the number of records deleted in each operation
  3. Monitoring query execution time and impact on database performance

This would help manage memory usage and reduce the risk of long-running transactions.

src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminCleanupResource.java (1)

28-28: Avoid Trailing Slash in @RequestMapping Path

The @RequestMapping annotation at line 28 includes a trailing slash:

@RequestMapping("api/admin/cleanup/")

Including a trailing slash can sometimes lead to inconsistent URL mappings or require clients to be mindful of the slash when constructing requests.

Consider removing the trailing slash for consistency:

-@RequestMapping("api/admin/cleanup/")
+@RequestMapping("api/admin/cleanup")
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9e0e807 and 6d75d51.

⛔ Files ignored due to path filters (1)
  • docs/admin/cleanup/cleanup-menu.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (6)
  • docs/admin/cleanup-service.rst (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminCleanupResource.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/ParticipantScoreCleanupRepository.java
  • src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/TextBlockCleanupRepository.java
🧰 Additional context used
📓 Path-based instructions (3)
src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminCleanupResource.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (3)
Learnt from: undernagruzez
PR: ls1intum/Artemis#9296
File: src/main/java/de/tum/in/www1/artemis/repository/cleanup/DataCleanupRepository.java:8-8
Timestamp: 2024-09-13T11:32:35.988Z
Learning: In the `DataCleanupRepository` interface, the `deleteOrphans()` method is intended to delete all orphan entities that are important in the context and does not require a parameter to specify the entity type.
Learnt from: undernagruzez
PR: ls1intum/Artemis#9296
File: src/main/java/de/tum/in/www1/artemis/repository/cleanup/DataCleanupRepository.java:8-8
Timestamp: 2024-10-08T15:35:42.972Z
Learning: In the `DataCleanupRepository` interface, the `deleteOrphans()` method is intended to delete all orphan entities that are important in the context and does not require a parameter to specify the entity type.
Learnt from: undernagruzez
PR: ls1intum/Artemis#9296
File: src/main/java/de/tum/in/www1/artemis/repository/cleanup/DataCleanupRepository.java:8-8
Timestamp: 2024-10-08T15:35:48.768Z
Learning: In the `DataCleanupRepository` interface, the `deleteOrphans()` method is intended to delete all orphan entities that are important in the context and does not require a parameter to specify the entity type.
🔇 Additional comments (10)
docs/admin/cleanup-service.rst (1)

40-43: Clarify result validation criteria.

The documentation mentions "latest valid result" but doesn't specify:

  • What makes a result "valid"
  • How the "latest" is determined (timestamp, version, etc.)
  • Whether manual verification is possible before deletion

Consider adding examples or specific criteria for result validation.

src/main/java/de/tum/cit/aet/artemis/assessment/repository/cleanup/LongFeedbackTextCleanupRepository.java (3)

1-19: LGTM: Clean imports and proper package structure

The imports are specific and well-organized, following the coding guidelines.


20-26: LGTM: Well-documented repository with appropriate annotations

The repository is properly configured with clear documentation and correct Spring annotations.


87-88: Review date comparison logic

The date conditions c.startDate > :deleteFrom might be counterintuitive. This means newer courses (with later start dates) are being cleaned up while older courses are preserved. Verify if this is the intended behavior.

Also applies to: 121-122

✅ Verification successful

The previous search might have been too specific. Let's broaden our search to understand the date-based cleanup patterns in the codebase and locate the specific file for further analysis.


Let's examine the complete implementation and any similar cleanup repositories to understand if this date comparison logic is consistent with other cleanup implementations.


Let's examine other cleanup repositories and the cleanup service to understand if this date comparison logic aligns with the overall cleanup strategy of the application.


Date comparison logic is correct and consistent with the cleanup strategy

After examining the complete implementation and related cleanup repositories, the date comparison logic c.startDate > :deleteFrom AND c.endDate < :deleteTo is correct and intentional. This pattern is consistently used across the codebase to:

  1. Clean up courses that have ended (endDate < deleteTo)
  2. But not too old courses (startDate > deleteFrom)

This allows the system to maintain a "sliding window" of course data, preserving very old historical data while cleaning up more recent but completed courses. The same pattern is used in ResultCleanupRepository and is orchestrated by DataCleanupService.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar date comparison patterns in other cleanup repositories
rg -U "startDate\s*>\s*:deleteFrom.*endDate\s*<\s*:deleteTo" --type java

Length of output: 74


Script:

#!/bin/bash
# Let's search for any date-based cleanup logic in the repository
rg -U "(?i)(cleanup|delete).*(?:start|end)date" --type java -A 3

# Also search for the specific class to understand the context better
rg -l "class LongFeedbackTextCleanupRepository" --type java

Length of output: 1617


Script:

#!/bin/bash
# Let's look at the entire file content to understand the cleanup logic
fd -e java "LongFeedbackTextCleanupRepository" -x cat {}

# Also search for any similar cleanup repositories to understand the pattern
rg -l "CleanupRepository" --type java

Length of output: 6358


Script:

#!/bin/bash
# Let's examine other cleanup repositories to compare their date-based cleanup logic
fd -e java "StudentScoreCleanupRepository|TeamScoreCleanupRepository|ResultCleanupRepository" -x cat {}

# Also look for the cleanup service to understand the overall cleanup strategy
cat src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java

Length of output: 18031

src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java (6)

28-65: Dependencies are properly injected via constructor

The class utilizes constructor injection for all its dependencies, adhering to the dependency injection best practices outlined in the coding guidelines (di:constructor_injection). This promotes better testability and maintainability.


73-85: deleteOrphans method implementation is correct

The deleteOrphans method systematically deletes orphaned entities by invoking the appropriate repository methods. The implementation follows the Single Responsibility Principle by ensuring each call addresses a specific orphaned entity type.


110-118: deleteNonLatestNonRatedResults method handles cleanup effectively

The method correctly sequences the deletion operations for non-rated results and associated data within the specified date range. It aligns with the coding guidelines for database operations (db:{perf_queries}) by delegating to repository methods that presumably handle bulk deletions efficiently.


128-136: deleteNonLatestRatedResults method is well-structured

Similar to the non-rated results cleanup, this method effectively cleans up rated results while preserving the latest entries. It maintains consistency and follows best practices for modularity and readability.


149-154: getLastExecutions method correctly retrieves execution records

The method efficiently retrieves the last execution record for each cleanup job type using streams. The use of Arrays.stream() and .map() enhances readability.


156-167: Creation of CleanupJobExecution is handled appropriately

The private method createCleanupJobExecution constructs the CleanupJobExecution object correctly, setting optional fields based on the presence of deleteFrom and deleteTo parameters. This approach ensures flexibility for different cleanup job types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assessment Pull requests that affect the corresponding module client Pull requests that update TypeScript code. (Added Automatically!) communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. documentation exam Pull requests that affect the corresponding module plagiarism Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

10 participants