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

Programming exercises: Fix image export in combination with tooltip text #9879

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

badkeyy
Copy link
Contributor

@badkeyy badkeyy commented Nov 27, 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.

Changes affecting Programming Exercises

  • High priority: I tested all changes and their related features with all corresponding user types on a test server configured with the integrated lifecycle setup (LocalVC and LocalCI).

Motivation and Context

Fixes #9823

Description

With this PR, the Artemis Server now correctly extracts uploaded images from the markdown of exercises to include them in an exercise export, even when a tooltip text is specified. To achieve this, the code differentiates between two types of image URLs: those with tooltip text and those without. Using RegEx, it adjusts the corresponding substring operations based on the URL type.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Programming Exercise
  1. Create an exercise
  2. Add an image to the exercise description (e.g. by dragging and dropping an image into the text area)
  3. Add a tooltip text as described above, e.g. "ShownOnHover"
  4. Save the exercise, and download it using the 'Download Exercise' button in the exercise's overview page
  5. Unzip it, and look inside the files/ directory. It should contain the image

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

Exam Mode Test

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Summary by CodeRabbit

  • New Features

    • Enhanced handling of embedded file markdown syntax to support hover text in problem statements.
  • Bug Fixes

    • Added logging for export errors when the problem statement is null, improving error tracking.

@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) exercise Pull requests that affect the corresponding module labels Nov 27, 2024
@badkeyy badkeyy marked this pull request as ready for review November 27, 2024 12:30
@badkeyy badkeyy requested a review from a team as a code owner November 27, 2024 12:30
Copy link

coderabbitai bot commented Nov 27, 2024

Walkthrough

The changes introduce a new regex pattern, EMBEDDED_FILE_MARKDOWN_WITH_HOVERTEXT, to enhance the extraction of embedded file paths from markdown syntax that includes hover text. The copyFilesEmbeddedWithMarkdownSyntax method is updated to conditionally extract file paths based on this regex. Additionally, the exportProblemStatementWithEmbeddedFiles method now logs a warning if the problem statement is null. These modifications improve the handling of embedded files and ensure appropriate logging of export errors.

Changes

File Path Change Summary
src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseWithSubmissionsExportService.java Introduced new regex for embedded file markdown with hover text; updated file path extraction logic; added logging for null problem statements.

Assessment against linked issues

Objective Addressed Explanation
Ensure images with tooltip text are included in exercise export (#9823)

Possibly related PRs

Suggested labels

bugfix, feature, tests, ready for review, client

Suggested reviewers

  • BBesrour
  • DominikRemo
  • coolchock
  • sarpsahinalp
  • kaancayli
  • dmytropolityka
  • FelixTJDietrich

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 pmd (7.7.0)
src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseWithSubmissionsExportService.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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/exercise/service/ExerciseWithSubmissionsExportService.java (1)

134-142: Consider improving robustness of path extraction

While the basic functionality is correct, consider these improvements:

  1. Cache the Pattern compilation
  2. Add validation for the extracted path
  3. Handle escaped quotes in tooltip text
 private static final Pattern HOVER_TEXT_PATTERN = Pattern.compile(EMBEDDED_FILE_MARKDOWN_WITH_HOVERTEXT);
 
 private void copyFilesEmbeddedWithMarkdownSyntax(...) {
     for (String embeddedFile : embeddedFilesWithMarkdownSyntax) {
         String lastPartOfMatchedString = embeddedFile.substring(embeddedFile.lastIndexOf("]") + 1);
         String filePath;
 
-        if (Pattern.compile(EMBEDDED_FILE_MARKDOWN_WITH_HOVERTEXT).matcher(lastPartOfMatchedString).matches()) {
+        if (HOVER_TEXT_PATTERN.matcher(lastPartOfMatchedString).matches()) {
             filePath = lastPartOfMatchedString.substring(lastPartOfMatchedString.indexOf("(") + 1, lastPartOfMatchedString.indexOf(" "));
         } else {
             filePath = lastPartOfMatchedString.substring(lastPartOfMatchedString.indexOf("(") + 1, lastPartOfMatchedString.indexOf(")"));
         }
+        if (!isValidMarkdownPath(filePath)) {
+            log.warn("Invalid markdown file path: {}", filePath);
+            continue;
+        }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 83ac531 and 34bf0e8.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseWithSubmissionsExportService.java (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseWithSubmissionsExportService.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/exercise/service/ExerciseWithSubmissionsExportService.java (2)

46-47: LGTM: Well-defined regex constant for hover text extraction

The new regex pattern correctly matches markdown image syntax with tooltip text, following the format ![alt](/api/files/markdown/path "tooltip").


134-142: Verify path extraction security

The current implementation might be vulnerable to path traversal if the input is not properly sanitized. Please verify that:

  1. The path is properly sanitized before being used
  2. The path cannot escape the intended directory
  3. Input validation is performed on the markdown content
✅ Verification successful

Let me gather more information about how the file paths are handled in the codebase, particularly focusing on the class that contains the code under review.


Let me check how the extracted file paths are used and if there's any validation before their usage.


Let me check one final aspect about how the paths are handled after extraction, particularly in the constructFilenameAndCopyFile method and the FilePathService usage.


Let me check one final aspect about the path validation and conversion between public and actual paths in FilePathService.


Path extraction is properly secured through multiple layers of validation

The implementation is secure against path traversal for the following reasons:

  1. The extracted file path is only used to get the filename component (filePath.replace(API_MARKDOWN_FILE_PATH, ""))
  2. The actual file path is constructed using FilePathService.getMarkdownFilePath().resolve(fileName), which ensures files can only be accessed within the markdown directory
  3. The FilePathService includes path validation:
    • Normalizes paths to remove ../ and ./
    • Validates paths against known allowed directories
    • Throws exceptions for unknown or invalid paths
  4. The constructFilenameAndCopyFile method uses safe file operations within the designated directories
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for path traversal prevention in the codebase

# Look for path sanitization
rg -A 5 "sanitize.*(?i)path|(?i)path.*sanitize"

# Look for path traversal prevention
rg -A 5 "normalize.*(?i)path|(?i)path.*normalize"

# Look for FilePathService usage
ast-grep --pattern 'FilePathService.$_'

Length of output: 31431


Script:

#!/bin/bash
# Check the implementation of ExerciseWithSubmissionsExportService and related path handling
ast-grep --pattern 'class ExerciseWithSubmissionsExportService {
  $$$
}'

# Look for the pattern constant definition
rg "EMBEDDED_FILE_MARKDOWN_WITH_HOVERTEXT" -A 2

# Check for any path validation or sanitization in the same file
rg -g "ExerciseWithSubmissionsExportService.java" "sanitize|validate|normalize|check.*path"

Length of output: 2603


Script:

#!/bin/bash
# Check how the extracted filePath is used in ExerciseWithSubmissionsExportService
rg -g "ExerciseWithSubmissionsExportService.java" -A 5 -B 5 "filePath ="

# Look for FileService usage and path validation in the service
ast-grep --pattern 'class FileService {
  $$$
  sanitizeByCheckingIfPathStartsWithSubPathElseThrow($_, $_) {
    $$$
  }
  $$$
}'

# Check if there's any validation after path extraction
rg -g "ExerciseWithSubmissionsExportService.java" "FileService\.sanitize|FilePathService\."

Length of output: 4868


Script:

#!/bin/bash
# Check the implementation of constructFilenameAndCopyFile and related path handling
ast-grep --pattern 'constructFilenameAndCopyFile($$$) {
  $$$
}'

# Look for FilePathService implementation and its path validation
ast-grep --pattern 'class FilePathService {
  $$$
}'

# Check for any path validation in the markdown file handling
rg -g "FilePathService.java" "getMarkdownFilePath|markdown.*path" -A 5

Length of output: 1531


Script:

#!/bin/bash
# Check for path validation in FilePathService
rg -g "FilePathService.java" "actualPathForPublicPath|publicPathForActualPath" -A 10

# Look for the actual implementation of constructFilenameAndCopyFile in ExerciseWithSubmissionsExportService
rg -g "ExerciseWithSubmissionsExportService.java" -A 15 "private void constructFilenameAndCopyFile"

# Check for any security-related path validation in FileService
rg -g "FileService.java" "sanitize.*path|validate.*path|check.*path" -A 5

Length of output: 9365

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exercise Pull requests that affect the corresponding module ready for review server Pull requests that update Java code. (Added Automatically!)
Projects
Status: Work In Progress
Development

Successfully merging this pull request may close these issues.

Images from exercise descriptions are not exported under certain conditions
3 participants