Skip to content

General: Display modal 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

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

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 you are navigated to the passkey section
  9. Create a passkey
  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

Screenshots

image

image

passkeyModalDemo

Summary by CodeRabbit

  • New Features

    • Added a modal dialog prompting users to set up passkey authentication after login, with options to set up now, remind in 30 days, or set up later.
    • User accounts now indicate if a passkey has been registered, enabling tailored prompts and UI behavior.
  • Bug Fixes

    • Improved and clarified passkey-related informational texts and translations in the user settings.
  • Style

    • Refactored icon property declarations in multiple components for consistency and maintainability.
  • Documentation

    • Updated internal comments and Javadoc to reflect recent changes and improve clarity.
  • Tests

    • Added comprehensive unit tests for the new passkey setup modal and related login flow.
    • Extended backend tests to verify correct reporting of passkey registration status.
  • Chores

    • Increased minimum test coverage thresholds in configuration files.

@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 new mechanism to track whether a user has registered a passkey, extending both backend and frontend data models to include this information. The backend adds a boolean field to the UserDTO, updates the repository to efficiently check for passkey registration, and modifies the public account resource to expose this data. The frontend adapts the User model accordingly and introduces a modal dialog that encourages users to set up a passkey, with logic to display the modal post-login based on feature flags, registration status, and local storage reminders. Several code cleanups, documentation corrections, and test additions accompany these changes.

Changes

File(s) / Path(s) Change Summary
src/main/java/de/tum/cit/aet/artemis/core/dto/UserDTO.java
src/main/webapp/app/core/user/user.model.ts
Added hasRegisteredAPasskey boolean field to DTO and frontend model; 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.
src/main/java/de/tum/cit/aet/artemis/core/web/open/PublicAccountResource.java Injected PasskeyCredentialsRepository; updated getAccount() to set hasRegisteredAPasskey in UserDTO.
src/test/java/de/tum/cit/aet/artemis/core/user/AccountResourceIntegrationTest.java Added test for new hasRegisteredAPasskey field in account response; injected utility service.
src/main/webapp/app/core/home/home.component.ts
src/main/webapp/app/core/home/home.component.spec.ts
Added logic and tests for displaying setup passkey modal post-login based on feature flag, registration status, and reminder.
src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts
.html
.spec.ts
Added new Angular component, template, and tests for passkey setup modal with reminder and navigation logic.
src/main/webapp/i18n/en/userSettings.json
src/main/webapp/i18n/de/userSettings.json
Updated passkey info texts; added modal dialog translations; removed obsolete keys.
src/main/java/de/tum/cit/aet/artemis/core/dto/passkey/ArtemisPublicKeyCredentialParametersDTO.java
src/main/java/de/tum/cit/aet/artemis/core/repository/passkey/*
src/main/java/de/tum/cit/aet/artemis/core/web/PasskeyResource.java
Updated package/import paths for passkey-related classes and documentation comments.
src/main/webapp/app/core/navbar/navbar.component.ts
src/main/webapp/app/shared/delete-dialog/component/delete-dialog.component.ts
src/main/webapp/app/core/course/overview/courses/courses.component.ts
src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts
Refactored FontAwesome icon declarations to use protected readonly properties and improved code organization.
src/main/webapp/app/core/user/settings/passkey-settings/passkey-settings.component.html Removed redundant informational text about authenticator limitation.
src/main/webapp/app/core/auth/account.service.ts Added TODO comment for future refactoring of getter/setter to use signals.
src/main/webapp/app/app.component.ts
src/main/webapp/app/app.component.spec.ts
Updated comments, capitalization, and import paths for clarity and consistency.
src/main/webapp/app/core/admin/system-notification-management/system-notification-detail.component.spec.ts Updated import paths for test helpers.
jest.config.js
gradle/jacoco.gradle
Slightly increased test coverage thresholds for Jest and Jacoco.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant HomeComponent
    participant AccountService
    participant NgbModal
    participant SetupPasskeyModalComponent

    User->>HomeComponent: Login
    HomeComponent->>AccountService: Authenticate user
    AccountService-->>HomeComponent: Return user info (hasRegisteredAPasskey)
    HomeComponent->>HomeComponent: handleLoginSuccess()
    HomeComponent->>HomeComponent: openSetupPasskeyModal()
    alt Passkey feature enabled AND !hasRegisteredAPasskey AND no reminder
        HomeComponent->>NgbModal: open(SetupPasskeyModalComponent)
        NgbModal-->>SetupPasskeyModalComponent: Display modal
        User->>SetupPasskeyModalComponent: Choose action (Setup/Remind Later/Close)
        alt Setup
            SetupPasskeyModalComponent->>NgbModal: close()
            SetupPasskeyModalComponent->>Router: navigate(/user-settings/passkeys)
        else Remind Me in 30 Days
            SetupPasskeyModalComponent->>localStorage: set reminder date
            SetupPasskeyModalComponent->>NgbModal: close()
        else Set Up Later/Close
            SetupPasskeyModalComponent->>NgbModal: close()
        end
    end
Loading

Suggested labels

feature, database, ready for review, maintainer-approved

Suggested reviewers

  • krusche
  • HawKhiem
  • AjayvirS

📜 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 a79fa4b and 4f75760.

📒 Files selected for processing (1)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.html (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.html
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: client-tests
  • GitHub Check: client-style
  • GitHub Check: client-tests-selected
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: Analyse
  • 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

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between db5bdb7 and 64703a6.

📒 Files selected for processing (12)
  • gradle/jacoco.gradle (1 hunks)
  • src/main/webapp/app/app.component.spec.ts (2 hunks)
  • src/main/webapp/app/app.component.ts (2 hunks)
  • src/main/webapp/app/core/admin/system-notification-management/system-notification-detail.component.spec.ts (1 hunks)
  • src/main/webapp/app/core/auth/account.service.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/home/home.component.spec.ts (1 hunks)
  • src/main/webapp/app/core/home/home.component.ts (4 hunks)
  • src/main/webapp/i18n/de/userSettings.json (2 hunks)
  • src/main/webapp/i18n/en/userSettings.json (2 hunks)
✅ Files skipped from review due to trivial changes (4)
  • src/main/webapp/app/core/auth/account.service.ts
  • src/main/webapp/app/core/admin/system-notification-management/system-notification-detail.component.spec.ts
  • src/main/webapp/app/app.component.ts
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.html
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/main/webapp/app/app.component.spec.ts
  • src/main/webapp/i18n/de/userSettings.json
  • gradle/jacoco.gradle
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts
  • src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts
  • src/main/webapp/i18n/en/userSettings.json
🧰 Additional context used
📓 Path-based instructions (1)
`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/home/home.component.ts
  • src/main/webapp/app/core/home/home.component.spec.ts
🧬 Code Graph Analysis (2)
src/main/webapp/app/core/home/home.component.ts (1)
src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts (1)
  • EARLIEST_SETUP_PASSKEY_REMINDER_DATE_LOCAL_STORAGE_KEY (9-9)
src/main/webapp/app/core/home/home.component.spec.ts (4)
src/test/javascript/spec/helpers/mocks/mock-router.ts (1)
  • MockRouter (5-30)
src/test/javascript/spec/helpers/mocks/service/mock-account.service.ts (1)
  • MockAccountService (7-45)
src/test/javascript/spec/helpers/mocks/service/mock-ngb-modal.service.ts (1)
  • MockNgbModalService (1-5)
src/main/webapp/app/core/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts (1)
  • EARLIEST_SETUP_PASSKEY_REMINDER_DATE_LOCAL_STORAGE_KEY (9-9)
🪛 GitHub Check: client-tests-selected
src/main/webapp/app/core/home/home.component.spec.ts

[failure] 99-99:
No overload matches this call.

🪛 GitHub Check: client-tests
src/main/webapp/app/core/home/home.component.spec.ts

[failure] 99-99:
No overload matches this call.

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • 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
🔇 Additional comments (8)
src/main/webapp/app/core/home/home.component.ts (4)

23-24: Appropriate imports added.

The necessary imports have been added to support the new passkey setup modal functionality.


50-50: NgbModal service properly injected.

The modalService is correctly injected using the recommended Angular inject function.


87-111: Well-structured implementation of passkey modal display logic.

The method contains clear and comprehensive checks before displaying the modal:

  1. Feature flag check
  2. User preference check via localStorage
  3. User registration status check

The implementation aligns with the PR objective to encourage passkey adoption.


233-234: Appropriate placement of passkey modal trigger.

Calling openSetupPasskeyModal() in the handleLoginSuccess() method ensures the modal appears right after login, which is the optimal time to prompt users about setting up passkeys.

src/main/webapp/app/core/home/home.component.spec.ts (4)

1-75: Well-structured test setup with comprehensive mock providers.

The test setup includes all necessary mocks and dependencies for thorough testing of the component, including AccountService, RouterLink, NgbModal, and other services.

Good practice to clear localStorage before each test to ensure test isolation.


77-95: Basic component functionality tests are appropriate.

Tests verify:

  • Component creation
  • Initialization with profile info
  • Prefilled username handling
  • Form validation logic

These cover the fundamental component behavior effectively.


97-141: Login process tests are thorough and well-structured.

Tests cover:

  • Successful login flow
  • Failed login handling
  • Loading state management during login process

The async/await pattern is correctly used to handle asynchronous operations.

🧰 Tools
🪛 GitHub Check: client-tests-selected

[failure] 99-99:
No overload matches this call.

🪛 GitHub Check: client-tests

[failure] 99-99:
No overload matches this call.


143-202: Comprehensive test coverage for passkey modal functionality.

Tests verify all decision paths for the modal display logic:

  • Feature flag check
  • User registration status check
  • Reminder date validation in localStorage
  • Both past and future reminder dates

The tests align perfectly with the implementation logic in the component.

Copy link

github-actions bot commented May 1, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed49m 42s 40ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 2s 939ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 48s 294ms

coderabbitai[bot]
coderabbitai bot previously approved these changes May 1, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes May 1, 2025
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.

I think one aspect is definitely a copy/paste error and should be fixed.
We can discuss the remaining aspects.

"title": "Bleib sicher mit Passkeys",
"description": {
"howItWorks": "Dein Passkey wird auf deinem Gerät gespeichert und ist durch biometrische Daten oder eine PIN gesichert, was das Einloggen schnell und sicher macht – ohne dass du dir ein Passwort merken musst.",
"recommendation": "Wir empfehlen, jetzt einen Passkey einzurichten, um die Sicherheit deines Kontos zu erhöhen und eine nahtlose und passwortfreie Anmeldung zu genießen."
Copy link
Contributor

Choose a reason for hiding this comment

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

"genießen" might sound a bit too enthusiastic, but I'm fine with it 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am open to suggestions 😂

Copy link
Contributor

Choose a reason for hiding this comment

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

"erleben" or "profitieren" maybe?

Copy link

github-actions bot commented May 1, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran195 passed3 skipped3 failed46m 50s 270ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 3s 450ms
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 2s 56ms
e2e/exercise/quiz-exercise/QuizExerciseParticipation.spec.ts
ts.Quiz Exercise Participation › DnD Quiz participation › Student can participate in DnD Quiz❌ failure2m 2s 42ms

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

Copy link

github-actions bot commented May 1, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran194 passed3 skipped4 failed53m 11s 345ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 3s 413ms
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 2s 599ms
e2e/exercise/quiz-exercise/QuizExerciseParticipation.spec.ts
ts.Quiz Exercise Participation › DnD Quiz participation › Student can participate in DnD Quiz❌ failure2m 2s 489ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 45s 502ms

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.

code lgtm - I just have a question rather than a comment:

Is this the standard way of asking to set up a setting? 30 days sounds a bit too much - at the same time, showing the pop-up every time could also be a bit aggressive.

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de May 1, 2025 15:00 Inactive
@florian-glombik
Copy link
Contributor Author

florian-glombik commented May 1, 2025

code lgtm - I just have a question rather than a comment:

Is this the standard way of asking to set up a setting? 30 days sounds a bit too much - at the same time, showing the pop-up every time could also be a bit aggressive.

@ahmetsenturk what other way would you propose? I am not quite sure which change you are expecting.

The 30 days button is only there because of the rare edge case that a user, for whichever reason, does not want to setup passkey and logs out and in to Artemis frequently (which also wont be the case for most users, who most likely activated the "remember me" functionality).
The pop up will not be displayed anymore if you created a passkey, so there's a quite easy way to get rid of the pop up.

Copy link

github-actions bot commented May 2, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran195 passed3 skipped3 failed46m 51s 235ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 3s 245ms
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 1s 908ms
e2e/exercise/quiz-exercise/QuizExerciseParticipation.spec.ts
ts.Quiz Exercise Participation › DnD Quiz participation › Student can participate in DnD Quiz❌ failure2m 2s 793ms

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 TS2, the popup was still being displayed even after setting up the passkey and signing in with passkey:

Screenshot 2025-05-02 at 09 17 28

@florian-glombik florian-glombik moved this from Ready For Review to Work In Progress in Artemis Development May 2, 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 server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Work In Progress
Development

Successfully merging this pull request may close these issues.

3 participants