Skip to content

General: Ask users to setup passkeys after login #10766

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

Merged
merged 67 commits into from
May 7, 2025

Conversation

florian-glombik
Copy link
Contributor

@florian-glombik florian-glombik commented Apr 29, 2025

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. - Not really, but breaking up the UserDTO is out of scope for this PR
  • 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 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.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • 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

We recently introduced passkey support in Artemis in #10656.

We now want to advertise passkeys as the preferred authentication mechanism. Therefore users shall be informed via a modal if they have not yet registered a passkey.

It was an active decision to notify users each time until they have registered at least one passkey.

Description

  • extended UserDTO.java to contain whether the user has registered a passkey or not
  • renamed the webauthn package to passkey
  • added PasskeyCredentialRepository#existsByUserId to easily infer if a user has a passkey or not
  • registered an effect in the root component of the app to display the passkey information modal (only if passkeys are enabled and if the user is logged in and has not yet registered at least one passkey)
  • defined constants (icons) before the rest of the component
  • Removed not required comments and unused variables from integration test

Steps for Testing

These are many steps, but it should only take around 5 minutes as it is mostly logging in and out of Artemis.

  1. Log in to Artemis
  2. See the Popup
  3. Click Set Up Later
  4. Logout
  5. Log in to Artemis
  6. See the Popup again
  7. Click Setup Passkey
  8. See that a browser native pop up appears where you are asked for a 2nd factor (e.g. fingerprint / facescan / pin)
  9. See an success alert that indicates that your passkey has been created
  10. Logout of Artemis
  11. Log in to Artemis
  12. See that the popup is not displayed anymore
  13. Delete the passkey (user-settings < passkey)
  14. Logout of Artemis
  15. Login to Artemis
  16. See the Popup again
  17. Press Remind me in 30 days
  18. Logout of Artemis
  19. Log in to Artemis
  20. See that the modal is not displayed

(You can clear/adjust earliestSetupPasskeyReminderDate from your local storage if you want to check that after 30 days the modal will be displayed again)

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Performance Review

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
setup-passkey-modal.component.ts 100%
home.component.ts 77.37%

Screenshots

image

image

passkeyModalDemoDirectlySetupPasskey

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a modal dialog prompting users to set up passkey authentication after login, with options to set up now, later, or be reminded in 30 days.
    • Added a new indicator showing whether a user has registered at least one passkey.
  • Enhancements

    • Refined passkey settings page with improved descriptions and success messages.
    • Passkey addition is now handled via a reusable utility function for better consistency.
  • Bug Fixes

    • Improved error handling and user feedback during passkey registration.
  • Style

    • Updated icon declarations for better code consistency.
    • Improved and clarified comments in various files.
  • Documentation

    • Updated and expanded localization for passkey-related features in English and German.
  • Tests

    • Added comprehensive tests for the new passkey setup modal and related user flows.
    • Enhanced test coverage for account and home components.

@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Apr 29, 2025
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module labels Apr 29, 2025
Copy link
Contributor

coderabbitai bot commented Apr 29, 2025

Walkthrough

This update introduces a user-facing modal to encourage passkey setup, adds backend and frontend support to track if a user has registered a passkey, and refactors passkey registration logic into a reusable utility. It also updates localization, test coverage, and code organization, including moving repository classes and improving icon property declarations.

Changes

Files/Paths Change Summary
src/main/java/de/tum/cit/aet/artemis/core/dto/UserDTO.java,
src/main/webapp/app/core/user/user.model.ts
Added a boolean field/property to indicate if a user has registered a passkey; updated constructors and accessors accordingly.
src/main/java/de/tum/cit/aet/artemis/core/repository/PasskeyCredentialsRepository.java Added existsByUserId method for efficient passkey existence check by user ID.
src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicAccountResource.java Injected PasskeyCredentialsRepository, updated getAccount() to set passkey registration status on UserDTO.
src/test/java/de/tum/cit/aet/artemis/core/user/AccountResourceIntegrationTest.java Added integration test for passkey registration status in account resource; injected utility service.
src/main/java/de/tum/cit/aet/artemis/core/dto/passkey/ArtemisPublicKeyCredentialParametersDTO.java,
src/main/java/de/tum/cit/aet/artemis/core/web/PasskeyResource.java
Updated import paths for COSEAlgorithm and ArtemisUserCredentialRepository to new package.
src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/ArtemisPublicKeyCredentialUserEntityRepository.java,
ArtemisUserCredentialRepository.java,
COSEAlgorithm.java,
HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository.java,
HazelcastPublicKeyCredentialRequestOptionsRepository.java
Moved repository and related classes from webauthn to passkey package.
src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisPublicKeyCredentialCreationOptionsFilter.java,
ArtemisWebAuthnConfigurer.java
Updated Javadoc comments to reference new repository package paths.
src/main/webapp/app/core/home/home.component.ts Added openSetupPasskeyModal() to display modal after login if passkey not registered; calls modal on successful login.
src/main/webapp/app/core/home/home.component.spec.ts Added comprehensive unit tests for HomeComponent, including modal logic and login flow.
src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts,
setup-passkey-modal.component.html,
setup-passkey-modal.component.spec.ts
Added new Angular modal component for passkey setup, its template, and unit tests.
src/main/webapp/app/core/user/settings/passkey-settings/passkey-settings.component.ts Refactored passkey addition logic to use new addNewPasskey utility; updated method names and code structure.
src/main/webapp/app/core/user/settings/passkey-settings/util/credential.util.ts Added addNewPasskey utility function for passkey registration with robust error handling.
src/main/webapp/app/core/user/settings/passkey-settings/passkey-settings.component.html Updated button click handler to match refactored method; removed obsolete informational text.
src/main/webapp/app/core/user/settings/passkey-settings/util/credential-option.util.ts Removed authenticatorSelection from credential options.
src/main/webapp/app/core/user/settings/passkey-settings/util/credential-option.util.spec.ts Updated tests to match changes in credential options utility.
src/main/webapp/app/core/user/settings/passkey-settings/passkey-settings.component.spec.ts Updated tests to call new method for adding passkeys.
src/main/webapp/app/core/navbar/navbar.component.ts,
app/shared/delete-dialog/component/delete-dialog.component.ts,
app/core/course/overview/courses/courses.component.ts,
app/shared/exercise-filter/exercise-filter-modal.component.ts
Changed FontAwesome icon declarations to protected readonly or adjusted visibility; removed unused icons.
src/main/webapp/app/app.component.ts,
app.component.spec.ts
Improved comments for clarity and updated test import paths and suite name.
src/main/webapp/app/core/auth/account.service.ts Added TODO comment for future refactoring.
src/main/webapp/app/core/admin/system-notification-management/system-notification-detail.component.spec.ts Updated test import paths for mocks.
src/main/webapp/i18n/en/userSettings.json,
i18n/de/userSettings.json
Updated and expanded localization for passkey-related UI, added modal strings, improved info texts.
gradle/jacoco.gradle Increased minimum instruction coverage thresholds for several modules.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant HomeComponent
    participant AccountService
    participant NgbModal
    participant SetupPasskeyModalComponent

    User->>HomeComponent: Login
    HomeComponent->>AccountService: login()
    AccountService-->>HomeComponent: login success
    HomeComponent->>HomeComponent: openSetupPasskeyModal()
    HomeComponent->>NgbModal: open(SetupPasskeyModalComponent)
    NgbModal-->>SetupPasskeyModalComponent: instantiate modal
    SetupPasskeyModalComponent->>User: User interacts (set up, remind later, close)
Loading
sequenceDiagram
    participant User
    participant SetupPasskeyModalComponent
    participant WebauthnApiService
    participant AlertService

    User->>SetupPasskeyModalComponent: Click "Set Up Passkey"
    SetupPasskeyModalComponent->>WebauthnApiService: getRegistrationOptions()
    WebauthnApiService-->>SetupPasskeyModalComponent: registration options
    SetupPasskeyModalComponent->>Browser: navigator.credentials.create()
    Browser-->>SetupPasskeyModalComponent: credential (or error)
    alt Success
        SetupPasskeyModalComponent->>WebauthnApiService: registerCredential()
        WebauthnApiService-->>SetupPasskeyModalComponent: success
        SetupPasskeyModalComponent->>AlertService: success alert
    else Error
        SetupPasskeyModalComponent->>AlertService: error alert
    end
    SetupPasskeyModalComponent->>SetupPasskeyModalComponent: close modal
Loading

Suggested reviewers

  • krusche
  • HawKhiem

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e75b183 and 206ba64.

📒 Files selected for processing (2)
  • gradle/jacoco.gradle (1 hunks)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts
  • gradle/jacoco.gradle
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: client-tests-selected
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: Analyse
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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
Contributor

@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: 2

🧹 Nitpick comments (6)
src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts (1)

1-22: Base unit test added; consider expanding coverage
Good start verifying the component instantiation. To improve test robustness and meet meaningful coverage guidelines, consider adding specs that simulate user interactions with the modal—e.g., opening/closing logic, button clicks, and reactive signal updates.

src/main/webapp/app/core/user/user.model.ts (1)

42-42: Property naming inconsistency between parameter and class property.

The parameter name hasRegisteredPasskeys (plural) differs from the property name hasRegisteredAPasskey (singular), which could lead to confusion.

Consider making the naming consistent between parameter and class property:

-        hasRegisteredPasskeys?: boolean,
+        hasRegisteredAPasskey?: boolean,

And then:

-        this.hasRegisteredAPasskey = hasRegisteredPasskeys;
+        this.hasRegisteredAPasskey = hasRegisteredAPasskey;

Also applies to: 55-55

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

53-53: Consider tracking this TODO in your issue system.

While the TODO comment provides good documentation for future refactoring, it might be beneficial to create a formal issue or task to ensure this work isn't forgotten.

src/main/java/de/tum/cit/aet/artemis/core/dto/UserDTO.java (1)

243-249: Getter and setter methods implemented correctly.

The methods follow Java conventions and naming standards. However, the setter parameter name hasCreatedPasskeys differs from the field name hasRegisteredAPasskey, which could cause confusion.

Consider renaming the parameter to match the field name for consistency:

-public void setHasRegisteredAPasskey(boolean hasCreatedPasskeys) {
-    this.hasRegisteredAPasskey = hasCreatedPasskeys;
+public void setHasRegisteredAPasskey(boolean hasRegisteredAPasskey) {
+    this.hasRegisteredAPasskey = hasRegisteredAPasskey;
}
src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicAccountResource.java (1)

169-170: Variable name could better match field name.

The variable name hasUserRegisteredAPasskey is similar but not identical to the DTO field name hasRegisteredAPasskey, which could potentially cause confusion.

Consider renaming for consistency:

-boolean hasUserRegisteredAPasskey = this.passkeyCredentialsRepository.existsByUserId(user.getId());
+boolean hasRegisteredAPasskey = this.passkeyCredentialsRepository.existsByUserId(user.getId());
src/main/webapp/app/app.component.ts (1)

79-82: Consider a more explicit approach to detect login screen

The current approach infers the user is on the login screen when they're not authenticated, which works but could be more explicit.

-        const isUserOnLoginScreen = !this.accountService.isAuthenticatedSignal();
+        // Check if user is authenticated (not on login screen)
+        const isAuthenticated = this.accountService.isAuthenticatedSignal();
+        if (!isAuthenticated) {
-        if (isUserOnLoginScreen) {
            return;
        }

This makes the intention clearer - we're checking if the user is authenticated rather than inferring they're on the login screen.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e722184 and 63941ac.

📒 Files selected for processing (25)
  • src/main/java/de/tum/cit/aet/artemis/core/dto/UserDTO.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/dto/passkey/ArtemisPublicKeyCredentialParametersDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/PasskeyCredentialsRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/ArtemisPublicKeyCredentialUserEntityRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/ArtemisUserCredentialRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/COSEAlgorithm.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/HazelcastPublicKeyCredentialRequestOptionsRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisPublicKeyCredentialCreationOptionsFilter.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisWebAuthnConfigurer.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/PasskeyResource.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicAccountResource.java (3 hunks)
  • src/main/webapp/app/app.component.ts (5 hunks)
  • src/main/webapp/app/core/auth/account.service.ts (2 hunks)
  • src/main/webapp/app/core/course/overview/courses/courses.component.ts (1 hunks)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.html (1 hunks)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts (1 hunks)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts (1 hunks)
  • src/main/webapp/app/core/navbar/navbar.component.ts (1 hunks)
  • src/main/webapp/app/core/user/settings/passkey-settings/passkey-settings.component.html (0 hunks)
  • src/main/webapp/app/core/user/user.model.ts (3 hunks)
  • src/main/webapp/app/shared/delete-dialog/component/delete-dialog.component.ts (1 hunks)
  • src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts (2 hunks)
  • src/main/webapp/i18n/de/userSettings.json (2 hunks)
  • src/main/webapp/i18n/en/userSettings.json (2 hunks)
💤 Files with no reviewable changes (1)
  • src/main/webapp/app/core/user/settings/passkey-settings/passkey-settings.component.html
🧰 Additional context used
📓 Path-based instructions (4)
`src/main/java/**/*.java`: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,de...

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/repository/passkey/ArtemisUserCredentialRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/dto/passkey/ArtemisPublicKeyCredentialParametersDTO.java
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/HazelcastPublicKeyCredentialRequestOptionsRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisWebAuthnConfigurer.java
  • src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisPublicKeyCredentialCreationOptionsFilter.java
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/ArtemisPublicKeyCredentialUserEntityRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/repository/PasskeyCredentialsRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/web/PasskeyResource.java
  • src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/COSEAlgorithm.java
  • src/main/java/de/tum/cit/aet/artemis/core/dto/UserDTO.java
  • src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicAccountResource.java
`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:PascalC...

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/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts
  • src/main/webapp/app/core/course/overview/courses/courses.component.ts
  • src/main/webapp/app/core/user/user.model.ts
  • src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts
  • src/main/webapp/app/shared/delete-dialog/component/delete-dialog.component.ts
  • src/main/webapp/app/app.component.ts
  • src/main/webapp/app/core/auth/account.service.ts
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts
  • src/main/webapp/app/core/navbar/navbar.component.ts
`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/...

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".

  • src/main/webapp/i18n/de/userSettings.json
`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/**/*.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/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.html
🧬 Code Graph Analysis (2)
src/main/webapp/app/app.component.ts (1)
src/main/webapp/app/app.constants.ts (1)
  • FEATURE_PASSKEY (40-40)
src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts (1)
src/main/webapp/app/app.component.ts (1)
  • Component (23-185)
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: Analyse
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: client-tests-selected
  • GitHub Check: server-tests
  • GitHub Check: server-style
🔇 Additional comments (42)
src/main/webapp/app/core/course/overview/courses/courses.component.ts (1)

42-45: Appropriate icon property declaration

The FontAwesome icon properties have been moved to appear before the injected services, improving the component structure by grouping similar declarations together. The use of protected readonly is appropriate for template-accessible properties that shouldn't be modified.

src/main/java/de/tum/cit/aet/artemis/core/repository/PasskeyCredentialsRepository.java (1)

29-34: Well-optimized query for checking user passkey existence

The added method efficiently checks for passkey existence using a direct boolean return value rather than fetching and counting all records. The query follows Java and SQL best practices with:

  • Proper parameter annotation
  • SQL keywords in uppercase
  • Clear and concise method naming
  • Efficient query design (using COUNT > 0 pattern)

This approach is more performant than retrieving the full list of credentials and checking its size.

src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts (3)

3-3: Icon import cleanup

The import statement has been simplified to only include the faFilter icon, removing the unnecessary faBackward icon import.


36-36: Appropriate icon accessibility

Changed the faFilter icon from public to protected readonly, which is the appropriate access level for template-only properties and prevents accidental mutation.


38-38: Proper service injection

The activeModal injection has been repositioned within the class while maintaining its private access modifier, following Angular's best practices for dependency injection using the inject() function.

src/main/webapp/app/shared/delete-dialog/component/delete-dialog.component.ts (1)

22-27: Improved icon property declarations

The FontAwesome icon properties have been changed from public instance fields to protected readonly class properties, which:

  • Prevents accidental mutation of icon references
  • Provides appropriate access level for template-only properties
  • Maintains consistency with similar icon declarations across the codebase
  • Follows Angular best practices for component properties

This change aligns with the pattern seen in other components in this PR.

src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/COSEAlgorithm.java (1)

1-1: Package relocation updated for COSEAlgorithm
The package declaration has been moved to de.tum.cit.aet.artemis.core.repository.passkey. Ensure that all references and import statements in related classes and DTOs have been updated to this new path.

src/main/java/de/tum/cit/aet/artemis/core/dto/passkey/ArtemisPublicKeyCredentialParametersDTO.java (1)

13-13: Import path updated to new passkey package
The COSEAlgorithm import now reflects its relocation under de.tum.cit.aet.artemis.core.repository.passkey. No further action is required here.

src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/ArtemisUserCredentialRepository.java (1)

1-1: Relocated repository to passkey package
The package declaration has been updated to de.tum.cit.aet.artemis.core.repository.passkey. Confirm that any dependent imports (e.g., in security configuration or resource classes) have been adjusted accordingly.

src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/ArtemisPublicKeyCredentialUserEntityRepository.java (1)

1-1: Repository package updated for passkey functionality
The package has been moved to de.tum.cit.aet.artemis.core.repository.passkey. Verify there are no leftover references to the old webauthn package in your codebase.

src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/HazelcastPublicKeyCredentialRequestOptionsRepository.java (1)

1-1:

✅ Verification successful

Verify package rename consistency
The class has been moved to the passkey package. Please ensure that there are no remaining imports or references to the old webauthn package for this class anywhere in the codebase.


🏁 Script executed:

#!/bin/bash
# Verify no stale imports from old package
rg -n 'de\.tum\.cit\.aet\.artemis\.core\.repository\.webauthn\.HazelcastPublicKeyCredentialRequestOptionsRepository'

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Broad search for any remaining imports or references to the old `webauthn` package
rg -n 'de\.tum\.cit\.aet\.artemis\.core\.repository\.webauthn\.' -t java

Length of output: 74


No stale webauthn imports detected
A repository‐wide search for de.tum.cit.aet.artemis.core.repository.webauthn. returned no results, confirming the package rename is consistent.

src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository.java (1)

1-1:

✅ Verification successful

Verify package relocation for creation options repository
The package declaration was updated to passkey. Confirm that all Javadoc links and import statements referring to this repository class in other modules (e.g., security config, filters) have been updated accordingly.


🏁 Script executed:

#!/bin/bash
# Search for references to the old package location
rg -n 'de\.tum\.cit\.aet\.artemis\.core\.repository\.webauthn\.HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository'

Length of output: 130


🏁 Script executed:

#!/bin/bash
# Search for all occurrences of the relocated repository class (imports, Javadoc links, usage)
rg -n 'HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository'

Length of output: 1626


All references correctly updated to the new package location
The Javadoc links in both security classes now point to
de.tum.cit.aet.artemis.core.repository.passkey.HazelcastHttpSessionPublicKeyCredentialCreationOptionsRepository, so no further changes are needed:

  • src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisPublicKeyCredentialCreationOptionsFilter.java (Javadoc link at line 46)
  • src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisWebAuthnConfigurer.java (Javadoc link at line 42)
src/main/java/de/tum/cit/aet/artemis/core/web/PasskeyResource.java (1)

27-27: Import updated to new package
The import for ArtemisUserCredentialRepository has been correctly updated to the passkey package. No further action needed here.

src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisWebAuthnConfigurer.java (1)

42-43: Javadoc links corrected for custom repositories
The Javadoc now references the relocated Hazelcast repositories in the passkey package. This aligns with the broader refactoring and documentation is now consistent.

src/main/java/de/tum/cit/aet/artemis/core/security/passkey/ArtemisPublicKeyCredentialCreationOptionsFilter.java (1)

46-46: Package path update correctly reflects refactoring.

The updated Javadoc reference to the repository class aligns with the broader refactoring where passkey-related classes were moved from the webauthn package to the more appropriately named passkey package.

src/main/webapp/app/core/user/user.model.ts (1)

18-21: Well-documented property addition.

The added property is properly documented with a clear description of its purpose.

src/main/webapp/i18n/de/userSettings.json (2)

88-88: Improved passkey description.

The updated description is more concise and focuses on the security benefits of passkeys, which helps users better understand their value.


109-117: Well-structured translations for the new modal component.

The added translations for the passkey setup modal properly use the informal "du" form as required in the German translation guidelines. All necessary keys for the modal component are present with clear and informative messaging.

src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.html (1)

1-29: Well-structured modal with proper accessibility and localization.

The modal template is well-organized with clear sections and proper accessibility attributes. It correctly uses the jhiTranslate directive for all text content and includes appropriate icon indicators.

Two minor improvements to consider:

  1. Add type="submit" to the primary button since the form has an ngSubmit handler
  2. The form element isn't necessary since you're using click handlers rather than form submission
-<form name="exerciseFilterForm" (ngSubmit)="navigateToSetupPasskey()">
+<div>
   ...
-            <button type="button" class="btn btn-primary" (click)="navigateToSetupPasskey()">
+            <button type="submit" class="btn btn-primary" (click)="navigateToSetupPasskey()">
   ...
-</form>
+</div>
src/main/webapp/app/core/auth/account.service.ts (3)

1-1: Good job updating imports to include signal.

The import statement correctly includes the signal function from @angular/core, which aligns with modern Angular practices.


51-51: Well-structured reactive signal for authentication state.

The use of signals for tracking authentication state is a good approach, making this state reactive and readily consumable by components. This follows Angular's recommended patterns for state management.


60-64: Good implementation of reactive signal updates.

The code properly updates both the traditional boolean flag and the new signal when authentication state changes. The variable naming is clear and descriptive.

src/main/java/de/tum/cit/aet/artemis/core/dto/UserDTO.java (1)

74-78: Good addition of passkey registration field with documentation.

The new field is properly documented with a clear comment explaining its purpose. The default value of false is appropriate as the absence of passkeys is the default state.

src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts (6)

1-8: Imports are clean and well-organized.

The imports are appropriately organized and include only what's needed for the component functionality.


9-14: Component setup follows Angular best practices.

The component uses the standalone component pattern with explicit imports, which is a modern Angular approach. The template and style file references are correct.


15-18: Icon declarations are properly structured.

The FontAwesome icons are declared as protected readonly properties, making them accessible to the template while preventing modification.


19-20: Good use of modern dependency injection.

Using inject() for dependency injection follows current Angular best practices.


22-25: Navigation method is clear and focused.

The method correctly closes the modal before navigation, preventing UI issues. The path to the passkey setup page is correctly specified.


27-29: Modal close method is simple and effective.

Good separation of concerns with a dedicated method for closing the modal.

src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicAccountResource.java (4)

40-40: Added import for PasskeyCredentialsRepository.

Appropriate import for the new repository dependency.


68-69: Good use of constructor injection for new repository.

Following the dependency injection principle by using constructor injection for the repository.


70-77: Constructor properly initializes all dependencies.

The constructor has been updated to include and initialize the new repository dependency.


175-175: Properly sets passkey registration status on UserDTO.

This correctly transfers the passkey registration status from the repository check to the UserDTO being returned to the client.

src/main/webapp/i18n/en/userSettings.json (2)

88-88: Good concise description of passkeys

The revised text focuses on the security benefits of passkeys without being overly technical, making it more accessible to users.


109-117: Well-structured modal content with clear user guidance

The new passkey modal text is well-organized with:

  • A clear title that emphasizes security
  • An explanation of how passkeys work and their benefits
  • A recommendation that encourages adoption without being too pushy
  • Appropriately labeled buttons that give users a choice

This content aligns perfectly with the PR objective of prompting users to set up passkeys after login.

src/main/webapp/app/app.component.ts (7)

1-1: Appropriate import of Angular reactive primitives

The addition of effect and inject is necessary for the reactive approach used to manage the passkey modal display.


18-21: Well-organized imports for the passkey feature

All necessary dependencies for the passkey modal functionality are properly imported.


42-43: Services properly injected using the recommended inject pattern

Following Angular's recommended dependency injection pattern with the inject() function.


61-61: Feature flag initialization

Good practice to initialize the feature flag as disabled by default.


94-96: Good use of Angular's effect() for reactive modal display

Using Angular's reactive effect() ensures the modal logic runs at the appropriate times - both initially and whenever the tracked dependencies change.


114-114: Proper initialization of feature flag in ngOnInit

The code correctly initializes the isPasskeyEnabled flag by checking if the feature is active using the profile service.


63-89: 🛠️ Refactor suggestion

Well-documented and implemented method for conditionally displaying the passkey modal

The openSetupPasskeyModal() method is:

  • Thoroughly documented with JSDoc comments explaining the purpose and conditions
  • Properly checks all necessary conditions before showing the modal
  • Uses clean, early-return patterns for improved readability

However, there's a potential null reference issue that should be addressed.

-        if (!this.accountService.userIdentity || this.accountService.userIdentity.hasRegisteredAPasskey) {
+        const { userIdentity } = this.accountService;
+        if (!userIdentity || userIdentity.hasRegisteredAPasskey) {
            return;
        }

This makes the code safer by avoiding a potential null reference when accessing the hasRegisteredAPasskey property.

Likely an incorrect or invalid review comment.

@github-project-automation github-project-automation bot moved this from Work In Progress to Ready For Review in Artemis Development Apr 29, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes May 7, 2025
Copy link

github-actions bot commented May 7, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 796ms
TestResultTime ⏱
No test annotations available

Copy link
Contributor

@marlonnienaber marlonnienaber left a comment

Choose a reason for hiding this comment

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

I inspected changes to the code. Looks good. Reapprove

Copy link
Contributor

@tobias-lippert tobias-lippert left a comment

Choose a reason for hiding this comment

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

code

@helios-aet helios-aet bot temporarily deployed to artemis-test4.artemis.cit.tum.de May 7, 2025 19:10 Inactive
@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de May 7, 2025 19:10 Inactive
Copy link
Contributor

@az108 az108 left a comment

Choose a reason for hiding this comment

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

Tested on TS4, works without any issues. Tried the remind me after 30 day option after that the remind me later option and in the end the setup passkey option. All work as intended 👍

Copy link
Contributor

@ahmetsenturk ahmetsenturk left a comment

Choose a reason for hiding this comment

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

tested on TS4, works as described 👍

@florian-glombik florian-glombik moved this from Ready For Review to Developer Approved in Artemis Development May 7, 2025
Copy link

github-actions bot commented May 7, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran197 passed3 skipped1 failed1h 35s 962ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 47s 467ms

@krusche krusche changed the title General: Display modal to setup passkeys after login General: Ask users to setup passkeys after login May 7, 2025
@krusche krusche merged commit f67a6f0 into develop May 7, 2025
49 of 56 checks passed
@krusche krusche deleted the feature/general/display-passkey-popup-on-login branch May 7, 2025 20:02
@github-project-automation github-project-automation bot moved this from Developer Approved to Merged in Artemis Development May 7, 2025
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!) core Pull requests that affect the corresponding module ready for review ready to merge server Pull requests that update Java code. (Added Automatically!) tests
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

7 participants