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: Provide theia clone information on redirect #9379

Open
wants to merge 27 commits into
base: feature/re-key
Choose a base branch
from

Conversation

iyannsch
Copy link
Contributor

@iyannsch iyannsch commented Sep 28, 2024

Tip

This PR stacks on top of feature/bearer-support and feature/re-key

Deploy to TS9 for @Theia profile

Use the artemis_admin credentials for login.

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.

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).
  • I tested all changes and their related features with all corresponding user types on a test server configured with Gitlab and Jenkins.

Motivation and Context

The Theia User-Flow aims to integrate seamlessly into the existing Artemis exercise flow. When users click on the Open Online IDE button, we want to require as few clicks as possible before the exercise can be worked. In #8723, we defined that no further login should be required - at least for working with the repository.
In separate repositories, I already implemented the Theia LandingPage which can accept the git clone token for the user and instantly spawn a new session with the repo cloned using the token.

Fixes #9357

Description

This PR clears up the UI, moving the Open in Online IDE button into the existing <Code> button. Catering to the required data-sharing, the user's clone token, the user's exercise repo, and the configured Theia Settings are passed to the Landing Page.

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Create a ProgrammingExercise with enabled online IDE and selected online IDE image. You might want to choose Java17 for simplicity.
  2. Open the exercise in the student view.
  3. Verify that the Code button contains the Open Online IDE button.
  4. Verify that on-click a new tab opens and contains the correct parameters as query params (in the URL)
  • appDef should match your selected Image
  • gitUri should match your clone URL and the git token
  • artemisToken should be existent but you don't have to verify that

Here, you can see a screenshot highlighting the relevant parts.
Bildschirmfoto 2024-10-04 um 14 46 58

Exam Mode Testing

Make sure that none of that functionality is visible in the Exam Mode.

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

Test Coverage

Class/File Line Coverage Confirmation (assert/expect)
app/shared/components/code-button 95%

Screenshots

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a method to exchange cookies for bearer tokens for user authentication.
    • Introduced a new token generation method that allows for additional claims and enhanced validity control.
    • Enhanced JWT extraction and validation to support both cookie and Authorization header.
    • Added functionality to generate a new token and return it as both a cookie and bearer token.
    • Simplified WebSocket handshake process by directly extracting and validating JWT from requests.
    • Integrated support for the Theia online IDE, including checks for configuration and enabling the IDE based on exercise properties.
    • Added a new API endpoint to retrieve build configurations for programming exercises.
  • Bug Fixes

    • Removed deprecated functionality related to the Theia online IDE, simplifying the user interface.
  • Tests

    • Enhanced testing coverage for new authentication features.

@iyannsch iyannsch requested a review from a team as a code owner September 28, 2024 13:13
@iyannsch iyannsch self-assigned this Sep 28, 2024
Copy link

coderabbitai bot commented Sep 28, 2024

Walkthrough

The changes introduce significant updates to the JWT handling and token management in a Java and TypeScript application. Key modifications include the addition of a reKey method in the PublicUserJwtResource class for generating and returning tokens, enhancements to the JWTCookieService for cookie management, and improvements to the JWTFilter for JWT extraction and validation. Additionally, a new method in the AccountService facilitates the exchange of cookies for bearer tokens, reflecting a comprehensive approach to user authentication.

Changes

Files Change Summary
src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicUserJwtResource.java Added methods reKey and getTheiaToken for token generation and updated constructor and authorize method to handle new token functionality.
src/main/java/de/tum/cit/aet/artemis/core/security/jwt/JWTCookieService.java Introduced method buildTheiaCookie for creating cookies with specific flags.
src/main/java/de/tum/cit/aet/artemis/core/security/jwt/JWTFilter.java Updated doFilter method and added methods for JWT extraction and validation, replacing previous cookie validation logic.
src/main/java/de/tum/cit/aet/artemis/core/security/jwt/TokenProvider.java Added method createToken for flexible JWT creation with additional claims and updated existing method to utilize the new one.
src/main/webapp/app/core/auth/account.service.ts Introduced rekeyCookieToBearerToken method for exchanging cookies for bearer tokens.
src/main/webapp/app/shared/components/code-button/code-button.component.ts Enhanced CodeButtonComponent to support Theia IDE, adding properties and methods to manage Theia integration.
src/main/java/de/tum/cit/aet/artemis/core/config/websocket/WebsocketConfiguration.java Updated Websocket configuration to simplify JWT cookie handling during WebSocket handshake.
src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java Modified JSON serialization behavior by adding and removing @JsonIgnoreProperties annotations to prevent circular references.
src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java Added a new endpoint for retrieving programming exercise build configurations and integrated ProgrammingExerciseBuildConfigRepository.

Assessment against linked issues

Objective Addressed Explanation
Provide clone information for Theia Sessions when opening the IDE (#9357) The changes do not address the requirements related to providing clone information for Theia sessions.

Possibly related issues

Possibly related PRs

Suggested labels

ready for review, feature, lti

Suggested reviewers

  • JohannesStoehr
  • SimonEntholzer
  • az108
  • krusche
  • EneaGore
  • b-fein
  • coolchock
  • undernagruzez
  • pzdr7

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.

@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 28, 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: 11

🧹 Outside diff range comments (4)
src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts (1)

Line range hint 1-35: Consider enhancing type safety and consistency across mock methods.

The MockProgrammingExerciseService class is well-structured and consistent in its approach to mocking service methods. To further improve its robustness and usefulness in tests, consider the following suggestions:

  1. Use TypeScript's generic types with of() to ensure type safety. For example:

    getBuildConfig = (exerciseId: number) => of<ProgrammingExerciseBuildConfig>({});
  2. Consider creating a base interface or type for the service, which this mock class can implement. This would ensure that the mock service stays in sync with the actual service interface.

  3. For methods that return empty objects, consider using of(null) or of(undefined) instead of of({}), unless an empty object is the expected return type.

  4. Add JSDoc comments to methods, especially for those with complex parameter structures, to improve readability and maintainability.

These changes would enhance the overall quality and reliability of the mock service in test scenarios.

src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts (2)

Line range hint 117-121: LGTM! Consider refactoring for code reuse.

The addition of code to set localVCEnabled and athenaEnabled based on active profiles aligns with the PR objectives and follows Angular best practices.

Consider refactoring the profile checking logic into a separate method to reduce code duplication:

private setProfileFlags(profiles: string[] | undefined) {
  this.localVCEnabled = profiles?.includes(PROFILE_LOCALVC) ?? false;
  this.athenaEnabled = profiles?.includes(PROFILE_ATHENA) ?? false;
}

ngOnInit(): void {
  // ... existing code ...

  if (this.exercise.type === ExerciseType.PROGRAMMING) {
    this.profileService.getProfileInfo().subscribe((profileInfo) => {
      this.setProfileFlags(profileInfo.activeProfiles);
    });
  } else if (this.exercise.type === ExerciseType.TEXT) {
    this.editorLabel = 'openTextEditor';
    this.profileService.getProfileInfo().subscribe((profileInfo) => {
      this.setProfileFlags(profileInfo.activeProfiles);
    });
  }

  // ... rest of the method ...
}

This refactoring improves code reuse and maintainability.

Also applies to: 126-128


Duplicate Assignments Detected for athenaEnabled

  • The property athenaEnabled is assigned multiple times within exercise-details-student-actions.component.ts (Lines 11-24), which may be redundant.

Please review these assignments to ensure they are both necessary and intentional.

🔗 Analysis chain

Line range hint 52-53: LGTM! Please clarify the purpose of new properties.

The removal of Theia-related properties and the addition of localVCEnabled and athenaEnabled properties align with the PR objectives.

Could you please clarify the specific use cases for localVCEnabled and athenaEnabled? This will help ensure that these new properties are used appropriately throughout the component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of localVCEnabled and athenaEnabled
echo "Usage of localVCEnabled:"
rg '\blocalVCEnabled\b' src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts
echo "Usage of athenaEnabled:"
rg '\bathenaEnabled\b' src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts

Length of output: 680

src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (1)

Line range hint 1-1010: Consider refactoring for improved maintainability.

While the current implementation is functional and follows a consistent pattern, consider the following suggestions for future improvements:

  1. Split the controller: This file is quite large and handles many different operations. Consider splitting it into smaller, more focused controller classes based on functionality (e.g., ProgrammingExerciseCreationController, ProgrammingExerciseUpdateController, etc.).

  2. Extract common operations: Some operations, like authorization checks and error handling, are repeated across multiple methods. Consider extracting these into separate service methods to reduce duplication and improve maintainability.

  3. Use of constants: Consider defining constants for common string literals (e.g., error messages, entity names) to improve consistency and ease of maintenance.

These suggestions are not critical for the current functionality but could help improve the overall structure and maintainability of the codebase in the long term.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 85fc9b7 and 2ab444e.

📒 Files selected for processing (11)
  • src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseBuildConfigRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (6 hunks)
  • src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts (2 hunks)
  • src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.html (0 hunks)
  • src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts (1 hunks)
  • src/main/webapp/app/shared/components/code-button/code-button.component.html (1 hunks)
  • src/main/webapp/app/shared/components/code-button/code-button.component.ts (5 hunks)
  • src/test/javascript/spec/component/overview/exercise-details/exercise-details-student-actions.component.spec.ts (0 hunks)
  • src/test/javascript/spec/component/shared/code-button.component.spec.ts (5 hunks)
  • src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts (2 hunks)
💤 Files not reviewed due to no reviewable changes (2)
  • src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.html
  • src/test/javascript/spec/component/overview/exercise-details/exercise-details-student-actions.component.spec.ts
🧰 Additional context used
📓 Path-based instructions (9)
src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.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/programming/repository/ProgrammingExerciseBuildConfigRepository.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/programming/web/ProgrammingExerciseResource.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/app/exercises/programming/manage/services/programming-exercise.service.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

src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.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

src/main/webapp/app/shared/components/code-button/code-button.component.html (1)

Pattern src/main/webapp/**/*.html: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

src/main/webapp/app/shared/components/code-button/code-button.component.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

src/test/javascript/spec/component/shared/code-button.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (1)
Learnt from: Hialus
PR: ls1intum/Artemis#8607
File: src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java:64-64
Timestamp: 2024-06-15T20:04:18.637Z
Learning: For the Artemis project, import statements are automatically managed by formatters and should not be commented on.
🪛 Biome
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[error] 144-144: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)


[error] 409-409: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)


[error] 413-413: Forbidden non-null assertion.

Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator

(lint/style/noNonNullAssertion)

🔇 Additional comments (21)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseBuildConfigRepository.java (1)

38-47: LGTM! The new method enhances repository functionality.

The addition of the findByExerciseIdElseThrow method is a valuable enhancement to the repository. It follows our coding guidelines, maintains consistency with existing methods, and provides a useful abstraction for error handling when retrieving build configs.

src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts (1)

5-5: LGTM: Import statement added correctly.

The new import for ProgrammingExerciseBuildConfig is properly added and consistent with the existing import style.

src/main/webapp/app/shared/components/code-button/code-button.component.html (1)

Line range hint 1-106: Overall assessment: Good implementation with room for minor improvements

The changes in this file successfully integrate the online IDE button into the existing code button component. The implementation aligns well with the PR objectives and follows Angular best practices. The conditional rendering and security measures are appropriately implemented.

A few minor suggestions were made to improve usability and user experience, particularly for mobile devices and during the IDE startup process. These improvements would further enhance the seamless integration of Theia into the Artemis exercise flow.

src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts (1)

Line range hint 1-524: Overall, the changes look good and align with the PR objectives.

The modifications to this component successfully remove Theia-related functionality and integrate new features as intended. The code adheres to Angular best practices and the provided coding guidelines.

A few minor suggestions have been made for improvement:

  1. Organizing imports alphabetically
  2. Clarifying the purpose of new properties
  3. Refactoring profile checking logic for better code reuse

These suggestions aim to enhance code readability and maintainability. Great job on implementing these changes!

src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts (1)

664-666: LGTM: New method getBuildConfig added correctly.

The new getBuildConfig method is well-implemented and consistent with the existing codebase. It follows the established patterns for HTTP requests and return types.

src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (2)

501-514: LGTM! New endpoint for retrieving build config implemented correctly.

The new getBuildConfig method is well-implemented:

  • It uses proper access control with @EnforceAtLeastStudentInExercise.
  • The request is logged for debugging purposes.
  • It correctly retrieves the build config from the repository.
  • The response is properly constructed and returned.

The implementation looks good and follows the existing patterns in the class.


Line range hint 165-178: LGTM! Constructor updated correctly to include new repository.

The constructor has been properly updated to include the new ProgrammingExerciseBuildConfigRepository:

  • The new parameter is added in a logical position.
  • The parameter is correctly assigned to the class field in the constructor body.
  • The change maintains the existing code style and structure.

This update is consistent with the addition of the new getBuildConfig method.

src/main/webapp/app/shared/components/code-button/code-button.component.ts (5)

13-13: Import Statement Updated Correctly

Importing PROFILE_THEIA is appropriate for enabling Theia IDE integration.


16-16: faDesktop Icon Imported Successfully

The faDesktop icon is correctly imported for use in the component.


19-19: ProgrammingExerciseService Injected Properly

The ProgrammingExerciseService is correctly imported and injected into the constructor for fetching build configurations.

Also applies to: 92-92


75-76: Properties Added for Theia Integration

New properties theiaEnabled and theiaPortalURL are added to manage the state and URL for Theia IDE, following camelCase naming conventions.


81-81: faDesktop Icon Assigned Correctly

The faDesktop icon is correctly assigned to be used in the template.

src/test/javascript/spec/component/shared/code-button.component.spec.ts (9)

8-8: Import statement is appropriate.

The classes Exercise and ExerciseType are correctly imported and utilized in the test code.


32-36: Import statements are necessary and correct.

The imported entities are required for the new tests and are appropriately used.


43-43: Declaration of programmingExerciseService is proper.

This service is needed for injecting and spying on methods within the tests.


51-52: Spy instances for getProfileInfo and getBuildConfig are correctly declared.

These spies are essential for mocking the return values in the tests.


97-104: exercise object is well-defined for testing purposes.

The properties are appropriately set to simulate various scenarios in the tests.


127-127: Mocking ProgrammingExerciseService using MockProgrammingExerciseService.

This aligns with the guideline to mock irrelevant dependencies using NgMocks.


129-134: Proper initialization and mocking of getProfileInfo.

The use of compileComponents().then() ensures the component is compiled before mocking, which is acceptable in this context.


140-140: Injection of ProgrammingExerciseService into the test bed is appropriate.

This allows for effective spying and mocking of its methods.


478-559: Parameterized tests effectively cover multiple scenarios.

The use of it.each provides comprehensive coverage for different configurations, enhancing test reliability.

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 comments (1)
src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts (1)

Issues Found: Remove or update references to startOnlineIDE in code-button.component.html.

The startOnlineIDE method is still being referenced in src/main/webapp/app/shared/components/code-button/code-button.component.html. Please remove or update this reference to prevent potential runtime errors.

🔗 Analysis chain

Line range hint 1-341: LGTM! Verify template file for any lingering references.

The removal of the startOnlineIDE method aligns with the PR objectives of removing Theia-related functionality.

Please run the following script to check if there are any remaining references to the removed startOnlineIDE method in the component's template file:


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: 8

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 389f5fd and 7ce3a49.

📒 Files selected for processing (1)
  • src/main/webapp/app/shared/components/code-button/code-button.component.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/shared/components/code-button/code-button.component.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

🪛 Biome
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[error] 144-144: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

@dmytropolityka dmytropolityka changed the title Draft: Programming: Provide theia clone information on redirect Programming: Provide theia clone information on redirect Sep 30, 2024
@iyannsch iyannsch marked this pull request as draft September 30, 2024 08:20
@iyannsch iyannsch marked this pull request as ready for review September 30, 2024 08:54
@github-actions github-actions bot added core Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module labels Oct 3, 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: 9

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 7ce3a49 and 4160302.

📒 Files selected for processing (5)
  • src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicUserJwtResource.java (2 hunks)
  • src/main/webapp/app/core/auth/account.service.ts (1 hunks)
  • src/main/webapp/app/shared/components/code-button/code-button.component.ts (5 hunks)
  • src/test/javascript/spec/component/shared/code-button.component.spec.ts (5 hunks)
  • src/test/javascript/spec/helpers/mocks/service/mock-account.service.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicUserJwtResource.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/app/core/auth/account.service.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

src/main/webapp/app/shared/components/code-button/code-button.component.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

src/test/javascript/spec/component/shared/code-button.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/helpers/mocks/service/mock-account.service.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

🪛 Biome
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[error] 364-364: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

src/test/javascript/spec/component/shared/code-button.component.spec.ts

[error] 600-600: Forbidden non-null assertion.

Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator

(lint/style/noNonNullAssertion)

🪛 GitHub Check: client-tests-selected
src/test/javascript/spec/component/shared/code-button.component.spec.ts

[failure] 601-601:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ appDef: string; gitUri: string; gitToken: string; }'.

🪛 GitHub Check: client-tests
src/test/javascript/spec/component/shared/code-button.component.spec.ts

[failure] 601-601:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ appDef: string; gitUri: string; gitToken: string; }'.

🔇 Additional comments (5)
src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicUserJwtResource.java (3)

30-30: LGTM: New imports are appropriate and follow guidelines.

The new imports for RequestParam and EnforceAtLeastStudent are correctly added and specific to the new functionality. They adhere to the guideline of avoiding star imports.

Also applies to: 37-37


Line range hint 1-173: Summary: Changes align well with PR objectives, with minor suggestions for improvement.

The implementation of the new reKey method in PublicUserJwtResource aligns well with the PR objectives of streamlining the user experience and minimizing clicks for accessing the online IDE. The changes are focused, well-implemented, and adhere to the provided coding guidelines.

Key points:

  1. The new method provides a way to re-key the user's authentication token, which can be returned as a bearer token or set as a cookie.
  2. The implementation follows good practices such as the single responsibility principle and proper use of annotations.
  3. Minor suggestions for improvement include adding Javadoc comments and using more descriptive parameter names.
  4. A security verification is recommended to ensure the new endpoint doesn't introduce vulnerabilities.

Overall, the changes effectively contribute to the goal of enhancing the integration of Theia within the Artemis platform, improving the user experience for programming exercises.


99-115: Verify security implications of the new re-key endpoint.

While the new reKey method is well-implemented and doesn't affect existing functionality, it's crucial to ensure that this new endpoint doesn't introduce any security vulnerabilities. Please verify the following:

  1. The @EnforceAtLeastStudent annotation provides sufficient access control for this sensitive operation.
  2. The token generation process in jwtCookieService.buildLoginCookie(true) is secure and uses appropriate expiration times.
  3. Proper logging is in place for this operation to track potential misuse.
  4. Consider rate limiting this endpoint to prevent abuse.

To help verify the security of this new endpoint, you can run the following commands:

src/main/webapp/app/core/auth/account.service.ts (1)

Line range hint 1-390: Overall assessment: Changes are well-implemented and align with PR objectives

The addition of the rekeyCookieToBearerToken method to the AccountService is a well-executed change that supports the PR's goal of enhancing the Theia User-Flow integration. The implementation adheres to Angular style guidelines and integrates smoothly with the existing service without introducing breaking changes.

To ensure the changes work as expected across the codebase:

This will help verify that the new authentication method is properly integrated and that there are no outstanding TODOs related to the Theia integration.

src/main/webapp/app/shared/components/code-button/code-button.component.ts (1)

403-406: 🧹 Nitpick (assertive)

Inform the user if the IDE window cannot be opened

If the call to window.open fails (e.g., due to a popup blocker), the user may not understand why nothing happened. Consider adding a user-friendly message to inform them.

Modify the code as follows:

if (!newWindow) {
+    alert('Please disable your popup blocker to open the online IDE.');
    return;
}

This will help users troubleshoot the issue more easily.

Likely invalid or redundant comment.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 4160302 and eae2c89.

📒 Files selected for processing (1)
  • src/main/webapp/app/shared/components/code-button/code-button.component.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/shared/components/code-button/code-button.component.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

🪛 Biome
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[error] 382-384: Expected a statement but instead found '}

async startOnlineIDE()'.

Expected a statement here.

(parse)


[error] 396-396: Illegal return statement outside of a function

(parse)


[error] 364-364: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

🪛 GitHub Check: client-tests-selected
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[failure] 382-382:
Declaration or statement expected.


[failure] 384-384:
Unexpected keyword or identifier.


[failure] 384-384:
';' expected.

🪛 GitHub Check: client-tests
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[failure] 382-382:
Declaration or statement expected.


[failure] 384-384:
Unexpected keyword or identifier.


[failure] 384-384:
';' expected.

🪛 GitHub Check: client-compilation
src/main/webapp/app/shared/components/code-button/code-button.component.ts

[failure] 382-382:
Declaration or statement expected.


[failure] 384-384:
Unexpected keyword or identifier.


[failure] 384-384:
';' expected.

🔇 Additional comments (3)
src/main/webapp/app/shared/components/code-button/code-button.component.ts (3)

385-392: Validate Data Before Form Submission

Ensure that all required data fields are present before submitting the form to prevent unexpected errors.

Consider adding checks to validate the data object:

if (!data.appDef || !data.gitUri || !data.artemisToken) {
    alert('Missing required data to start the Online IDE.');
    return;
}

76-77: 🛠️ Refactor suggestion

Rename theiaPortalURL to Follow CamelCase Convention

Per the coding guidelines, property names should be in camelCase. The property theiaPortalURL should be renamed to theiaPortalUrl for consistency.

Apply this diff to rename the property:

-    theiaPortalURL: string;
+    theiaPortalUrl: string;

Remember to update all references to this property in the code.

Likely invalid or redundant comment.


401-402: ⚠️ Potential issue

Consider Using POST Method for Submitting Sensitive Data

The gitToken and artemisToken are sensitive information and should not be sent via a GET request, as query parameters may be logged or exposed in browser history. Switching to POST enhances security by transmitting data in the request body.

Apply this diff to change the form method to POST:

-        form.method = 'GET';
+        form.method = 'POST';
         form.action = this.theiaPortalURL;

Ensure that the server endpoint accepts POST requests and handles the data appropriately.

Likely invalid or redundant comment.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 3, 2024
@janthoXO janthoXO added stacked-pr PR that depends on another PR and removed ready for review labels Oct 3, 2024
@github-actions github-actions bot added the deployment-error Added by deployment workflows if an error occured label 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: 0

🧹 Outside diff range and nitpick comments (2)
src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java (1)

28-28: Consider caching strategy for build configurations.

While the JSON serialization is properly handled with @JsonIgnoreProperties, consider implementing caching for frequently accessed build configurations to improve performance, especially since this configuration will be more frequently accessed with the enhanced Theia integration. This could be achieved using Spring's caching abstractions or a distributed cache like Redis for better scalability.

src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (1)

503-516: Consider enhancing error handling and logging.

The endpoint is well-implemented with proper security, documentation, and response handling. However, consider these improvements:

  1. Add more detailed error handling for specific scenarios
  2. Enhance logging to include user context for better traceability

Example enhancement:

 @GetMapping("programming-exercises/{exerciseId}/build-config")
 @EnforceAtLeastStudentInExercise
 public ResponseEntity<ProgrammingExerciseBuildConfig> getBuildConfig(@PathVariable long exerciseId) {
-    log.debug("REST request to get build config of ProgrammingExercise : {}", exerciseId);
+    var user = userRepository.getUserWithGroupsAndAuthorities();
+    log.debug("REST request to get build config of ProgrammingExercise : {} by user : {}", exerciseId, user.getLogin());
     var buildConfig = programmingExerciseBuildConfigRepository.findByExerciseIdElseThrow(exerciseId);

     return ResponseEntity.ok().body(buildConfig);
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 685a483 and 575379b.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/core/config/websocket/WebsocketConfiguration.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/core/config/websocket/WebsocketConfiguration.java
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.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/programming/web/ProgrammingExerciseResource.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/programming/web/ProgrammingExerciseResource.java (3)
Learnt from: Hialus
PR: ls1intum/Artemis#8607
File: src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java:64-64
Timestamp: 2024-06-15T20:04:18.637Z
Learning: For the Artemis project, import statements are automatically managed by formatters and should not be commented on.
Learnt from: Hialus
PR: ls1intum/Artemis#8607
File: src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java:64-64
Timestamp: 2024-10-08T15:35:42.972Z
Learning: For the Artemis project, import statements are automatically managed by formatters and should not be commented on.
Learnt from: Hialus
PR: ls1intum/Artemis#8607
File: src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java:64-64
Timestamp: 2024-10-08T15:35:48.767Z
Learning: For the Artemis project, import statements are automatically managed by formatters and should not be commented on.
🔇 Additional comments (1)
src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseResource.java (1)

120-121: LGTM! Field declaration and constructor injection are well implemented.

The changes follow the coding guidelines by:

  • Using constructor injection
  • Properly declaring the field as private final
  • Initializing the field in the constructor

Also applies to: 165-167, 178-178

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 29, 2024
@iyannsch iyannsch added deploy:artemis-test9 Testserver for Project Theia and removed deployment-error Added by deployment workflows if an error occured labels Oct 29, 2024
@github-actions github-actions bot added lock:artemis-test9 and removed deploy:artemis-test9 Testserver for Project Theia labels Oct 29, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 29, 2024
@github-actions github-actions bot added the config-change Pull requests that change the config in a way that they require a deployment via Ansible. label Oct 29, 2024
Copy link

github-actions bot commented Nov 6, 2024

There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions.

@github-actions github-actions bot added the stale label Nov 6, 2024
@iyannsch iyannsch changed the base branch from develop to feature/re-key November 7, 2024 09:25
@iyannsch iyannsch changed the base branch from feature/re-key to develop November 7, 2024 09:25
@iyannsch iyannsch dismissed coderabbitai[bot]’s stale review November 7, 2024 09:25

The base branch was changed.

@iyannsch iyannsch changed the base branch from develop to feature/re-key November 7, 2024 09:45
…ture/programming-exercises/provide-theia-clone-information-on-redirect
@github-actions github-actions bot removed the core Pull requests that affect the corresponding module label Nov 7, 2024
Copy link
Contributor

@JohannesStoehr JohannesStoehr left a comment

Choose a reason for hiding this comment

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

Reapprove after merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client Pull requests that update TypeScript code. (Added Automatically!) config-change Pull requests that change the config in a way that they require a deployment via Ansible. programming Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) stacked-pr PR that depends on another PR tests
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

Programming exercises: Provide clone information for Theia Sessions
6 participants