Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Communication: Improve push notifications for the iOS mobile app #9787

Merged

Conversation

PaRangger
Copy link
Contributor

@PaRangger PaRangger commented Nov 15, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I documented the Java code using JavaDoc style.

Motivation and Context

Currently, the notifications in iOS are running as background notifications. To change this, we need to send different payloads to iOS18 devices, while keeping the iOS17 and lower devices the same.

Description

I added a column to the push_notification_device_configuration table, which tells the system what version of payload to send.

Steps for Testing

Prerequisites:

  • 2 Students
  • 1 Course with communication enabled
  • 1 iOS Device with the newest Testflight build
  1. Log in to Artemis on the iOS device with user 1
  2. Activate Notifications
  3. Navigate to course
  4. Navigate to communication
  5. Create a post in any channel
  6. Log into artemis in the webclient with user 2
  7. Go to same course and communication channel
  8. Write an answer to the previously created post
  9. Verify that you get a notification on you iOS device

Testserver States

Note

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







Review Progress

Performance Review

Code Review

  • Code Review 1

Manual Tests

  • Test 1
  • Test 2

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced notifications now include additional contextual information such as author image URLs and identifiers for posts, improving clarity and engagement.
    • Introduced a new option to save notifications without sending them immediately, providing greater flexibility in notification management.
  • Bug Fixes

    • Improved error handling for notification types, ensuring clearer exceptions for unsupported scenarios.
  • Documentation

    • Updated placeholder signatures for various notification types to reflect new fields, enhancing clarity on available metadata.
  • Chores

    • Added a new constant for push notification versioning to support future updates.

@PaRangger PaRangger self-assigned this Nov 15, 2024
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. communication Pull requests that affect the corresponding module labels Nov 15, 2024
@github-actions github-actions bot added tests core Pull requests that affect the corresponding module labels Nov 15, 2024
@PaRangger PaRangger changed the title Development: Add changes for new iOS notification system Notifications: Add changes for new iOS notification system Nov 15, 2024
Copy link

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

@github-actions github-actions bot added the stale label Nov 28, 2024
@PaRangger PaRangger removed the stale label Nov 28, 2024
@PaRangger PaRangger temporarily deployed to artemis-test4.artemis.cit.tum.de December 3, 2024 08:53 — with GitHub Actions Inactive
@PaRangger PaRangger marked this pull request as ready for review December 3, 2024 09:12
@PaRangger PaRangger requested a review from a team as a code owner December 3, 2024 09:12
anian03
anian03 previously approved these changes Dec 3, 2024
Copy link
Member

@anian03 anian03 left a comment

Choose a reason for hiding this comment

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

Tested during testing session on TS4 and Artemis 1.5.1, works as expected

Copy link

coderabbitai bot commented Dec 3, 2024

Walkthrough

The pull request introduces modifications across several classes related to notification handling in the application. Key changes include the addition of new parameters for image URLs and identifiers in notification creation methods, updates to method signatures, and the introduction of a new enum for push notification API types. The changes enhance the detail and contextual information in notifications without altering the fundamental control flow or error handling.

Changes

File Change Summary
src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java Updated createAnnouncementNotification and createPlaceholdersNewAnnouncementPost methods to include imageUrl, authorId, and postId in their signatures and placeholders.
src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java Modified createNotification and createPlaceholdersNewReply methods to accept new parameters: imageUrl, userId, postingId, and parentPostId. Enhanced error handling and control flow for notification types.
src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java Introduced a new enum PushNotificationApiType with constants DEFAULT and IOS_V2, including methods for retrieving database keys.
src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java Added a new field apiType, updated constructor, and introduced a getter method for apiType.
src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java Expanded the record to include PushNotificationApiType apiType and added a constructor for backward compatibility.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java Updated createNotification and createPlaceholdersNewMessageChannelText methods to include imageUrl, userId, and postId in their signatures and placeholders.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java Modified notifyGroupsWithNotificationType method to include a boolean onlySave parameter for controlling notification dispatch.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java Adjusted sendNotification and sendRelayRequest methods for better clarity in variable declarations and added an argument for API type in RelayNotificationRequest.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java Added a new field apiType to the record to accommodate additional API type information.
src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java Updated register method to include apiType in the PushNotificationDeviceConfiguration constructor.
src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java Introduced a new constant PUSH_NOTIFICATION_MINOR_VERSION set to 2.
src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java Added static fields POST_ID and USER_ID for test setup, enhancing the initialization of test data.
src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java Updated comments for clarity on versioning steps related to notification placeholders.
src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java Enhanced test setup by ensuring unique IDs for Post and AnswerPost objects.
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java Updated constructor calls for PushNotificationDeviceConfiguration to include PushNotificationApiType.
src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java Modified constructor calls for PushNotificationDeviceConfiguration to include PushNotificationApiType.
src/test/resources/placeholder-signatures.json Added new fields to various notification types to include imageUrl, userId, postingId, and parentPostId for enhanced metadata.

Possibly related PRs

Suggested labels

client, ready to merge, bugfix

Suggested reviewers

  • JohannesStoehr
  • SimonEntholzer
  • BBesrour
  • HawKhiem
  • anian03
  • ole-ve
  • zagemello

Warning

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

🔧 pmd (7.7.0)
src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java

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


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4417ed2 and e6792b8.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

Documentation and Community

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (9)
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (1)

3-3: Consider using PushNotificationApiType instead of short for apiType

Using short for the apiType reduces type safety and may lead to errors. Consider using the PushNotificationApiType enum directly to enhance clarity and type safety.

Apply this diff to update the record definition:

-public record RelayNotificationRequest(String initializationVector, String payloadCipherText, String token, short apiType) {
+public record RelayNotificationRequest(String initializationVector, String payloadCipherText, String token, PushNotificationApiType apiType) {
src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (3)

Line range hint 121-134: Update equals method to include apiType field

The equals method should be updated to include the new apiType field for proper entity comparison.

Apply this diff:

     PushNotificationDeviceConfiguration that = (PushNotificationDeviceConfiguration) object;
     // Use compareTo rather than equals for dates to ensure timestamps and dates with the same time are considered equal
     // This is caused by Java internal design having different classes for Date (java.util) and Timestamp (java.sql)
-    return token.equals(that.token) && deviceType == that.deviceType && expirationDate.compareTo(that.expirationDate) == 0 && Arrays.equals(secretKey, that.secretKey)
-            && owner.equals(that.owner);
+    return token.equals(that.token) && deviceType == that.deviceType && expirationDate.compareTo(that.expirationDate) == 0 
+            && Arrays.equals(secretKey, that.secretKey) && owner.equals(that.owner) 
+            && apiType == that.apiType;

Line range hint 136-140: Update hashCode method to include apiType field

The hashCode method should be updated to maintain consistency with equals.

Apply this diff:

     @Override
     public int hashCode() {
-        int result = Objects.hash(token, deviceType, expirationDate, owner);
+        int result = Objects.hash(token, deviceType, expirationDate, owner, apiType);
         result = 31 * result + Arrays.hashCode(secretKey);
         return result;
     }

Line range hint 142-145: Update toString to include apiType field

The toString method should include the new field for better debugging.

Apply this diff:

     @Override
     public String toString() {
         return "PushNotificationDeviceConfiguration{" + "token='" + token + '\'' + ", deviceType=" + deviceType + ", expirationDate=" + expirationDate + ", secretKey="
-                + Arrays.toString(secretKey) + ", owner=" + owner + '}';
+                + Arrays.toString(secretKey) + ", owner=" + owner + ", apiType=" + apiType + '}';
     }
src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (1)

108-110: Add logging for apiType registration

Consider adding debug logging for the apiType being registered to aid in troubleshooting.

Add this before saving the configuration:

         PushNotificationDeviceConfiguration deviceConfiguration = new PushNotificationDeviceConfiguration(pushNotificationRegisterBody.token(),
                 pushNotificationRegisterBody.deviceType(), expirationDate, newKey.getEncoded(), user, apiType);
+        log.debug("Registering device with apiType: {}", apiType);
         pushNotificationDeviceConfigurationRepository.save(deviceConfiguration);
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1)

87-90: Consider null-safe image URL handling using Optional

The current implementation uses a ternary operator for null checking. Consider using Optional for more idiomatic null handling.

-var imageUrl = createdMessage.getAuthor().getImageUrl() == null ? "" : createdMessage.getAuthor().getImageUrl();
+var imageUrl = Optional.ofNullable(createdMessage.getAuthor().getImageUrl()).orElse("");
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (1)

160-162: Consider extracting notification data creation to a separate method

The creation of notification data could be extracted to improve readability and testability.

+private PushNotificationData createNotificationData(Notification notification, String date) {
+    return new PushNotificationData(
+        notification.getTransientPlaceholderValuesAsArray(),
+        notification.getTarget(),
+        NotificationType.findCorrespondingNotificationType(notification.getTitle()).name(),
+        date,
+        Constants.PUSH_NOTIFICATION_VERSION
+    );
+}
src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1)

379-383: LGTM! Consider enhancing version documentation.

The addition of PUSH_NOTIFICATION_MINOR_VERSION follows semantic versioning principles and aligns with the goal of supporting multiple iOS versions.

Consider adding more detailed documentation about version compatibility:

 /**
- * The value of the version field we send with each push notification to the native clients (Android & iOS).
+ * The value of the minor version field we send with each push notification to the native clients.
+ * Minor version changes indicate backward-compatible enhancements to the notification payload.
+ * Current version mapping:
+ * - 2: Added support for iOS 18 notification payload
+ * - 1: Initial version supporting iOS 17 and earlier
  */
src/test/resources/placeholder-signatures.json (1)

114-125: Consider consolidating duplicate field structures.

Multiple notification types (CONVERSATION_NEW_REPLY_MESSAGE, CONVERSATION_USER_MENTIONED, NEW_REPLY_FOR_*_POST) share identical field structures. This repetition could be simplified using a shared schema or type.

Consider creating a common reply notification structure that can be reused:

{
  "replyNotificationFields": {
    "imageUrl": "java.lang.String",
    "userId": "java.lang.String",
    "postingId": "java.lang.String",
    "parentPostId": "java.lang.String"
  }
}

Also applies to: 174-185, 402-413, 441-452, 480-491, 519-530

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a82ca47 and 4417ed2.

⛔ Files ignored due to path filters (2)
  • src/main/resources/config/liquibase/changelog/20241114122713_changelog.xml is excluded by !**/*.xml
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (17)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java (3 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java (2 hunks)
  • src/test/resources/placeholder-signatures.json (8 hunks)
👮 Files not reviewed due to content moderation or server errors (3)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java
🧰 Additional context used
📓 Path-based instructions (16)
src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java (1)

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

🔇 Additional comments (15)
src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java (1)

6-10: Verify that JSON serialization and deserialization handle the new apiType field correctly

The addition of the apiType field and overloaded constructors may affect JSON serialization/deserialization. Ensure that all serialization frameworks handle the new field appropriately.

Run the following script to check for usages of PushNotificationRegisterBody in serialization contexts:

✅ Verification successful

Based on the gathered information, I can now provide the final response:

JSON serialization of PushNotificationRegisterBody is handled correctly by Spring's default mechanisms

The code is safe because:

  1. The class is a Java record, which automatically provides proper serialization/deserialization behavior
  2. Integration tests in PushNotificationResourceTest verify the serialization works correctly through REST endpoints
  3. The apiType field has a default value through the secondary constructor, ensuring backward compatibility
  4. Spring Boot's default ObjectMapper configuration handles enum serialization automatically
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find usages of PushNotificationRegisterBody in REST endpoints and check for serialization annotations.

# Search in REST controllers for methods using PushNotificationRegisterBody
rg '@RestController' -A 10 | rg 'PushNotificationRegisterBody' -A 5 | rg '@RequestBody'

# Check for JsonCreator and JsonProperty annotations in PushNotificationRegisterBody
rg 'PushNotificationRegisterBody' -A 5 | rg '@JsonCreator|@JsonProperty'

Length of output: 156


Script:

#!/bin/bash
# Let's try a different approach to find usages and serialization handling

# Find all files containing PushNotificationRegisterBody
echo "=== Files containing PushNotificationRegisterBody ==="
rg -l "PushNotificationRegisterBody"

# Look for REST endpoints or controller methods using this class
echo -e "\n=== REST endpoint usages ==="
rg -B 5 -A 5 "PushNotificationRegisterBody.*@RequestBody|@RequestBody.*PushNotificationRegisterBody"

# Check the record class implementation and any annotations
echo -e "\n=== Record class implementation ==="
rg -B 3 -A 10 "record PushNotificationRegisterBody"

# Look for test cases that might involve serialization
echo -e "\n=== Test cases ==="
rg -B 3 -A 5 "PushNotificationRegisterBody" "*Test.java"

Length of output: 3648


Script:

#!/bin/bash
# Let's check the test file specifically and look for serialization tests

echo "=== Test file content ==="
cat src/test/java/de/tum/cit/aet/artemis/communication/notification/PushNotificationResourceTest.java

echo -e "\n=== Check for ObjectMapper or similar JSON handling ==="
rg -B 3 -A 3 "ObjectMapper|@Test.*PushNotificationRegisterBody" src/test/java/de/tum/cit/aet/artemis/communication/notification/PushNotificationResourceTest.java

# Let's also check if there are any custom serializers/deserializers
echo -e "\n=== Check for custom serializers/deserializers ==="
rg -l "JsonSerializer|JsonDeserializer"

Length of output: 4915


Script:

#!/bin/bash
# Let's check the test infrastructure and Spring configuration for JSON handling

# Check the base test class for ObjectMapper configuration
echo "=== Base Test Class Configuration ==="
cat src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractSpringIntegrationIndependentTest.java

# Check for Spring test configuration files
echo -e "\n=== Spring Test Configuration ==="
fd -e yml -e yaml -e properties . src/test/resources/

# Check if there are any custom configurations for ObjectMapper in main application
echo -e "\n=== Main Application Configuration ==="
rg -l "ObjectMapper|@JsonTest|@SpringBootTest" src/main/java/

Length of output: 21156

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java (1)

1-23: LGTM!

The implementation of the PushNotificationApiType enum is clean and follows best practices.

src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java (1)

45-48: LGTM!

The test updates correctly reflect the changes in the PushNotificationDeviceConfiguration constructor.

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (3)

38-40: LGTM: Field annotations are correctly applied

The apiType field is properly annotated with @Enumerated and @Column for JPA persistence.


61-69: LGTM: Constructor maintains backward compatibility

The new constructor overload properly handles the apiType parameter while maintaining backward compatibility through the existing constructor.


115-117: LGTM: Getter method follows Java conventions

The getApiType method follows Java getter naming conventions and provides proper access to the field.

src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java (1)

33-38: LGTM: Documentation improvements enhance clarity

The updated documentation clearly distinguishes between breaking and non-breaking changes, providing better guidance for version management.

src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (1)

104-105: LGTM: Proper null handling with default value

The code correctly handles null apiType by defaulting to PushNotificationApiType.DEFAULT.

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java (2)

31-31: LGTM: Import added for new enum type

The import statement for PushNotificationApiType is correctly added to support the new API type functionality.


74-76: LGTM: Appropriate API types assigned in test setup

The test setup correctly initializes the device configurations with appropriate API types:

  • PushNotificationApiType.IOS_V2 for Apple devices
  • PushNotificationApiType.DEFAULT for Firebase devices

This aligns with the PR objective of supporting the new iOS notification system while maintaining compatibility.

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1)

98-99: Verify parameter ordering consistency

The parameter ordering in the method signature has been updated to include new fields. Ensure that the order of parameters in the placeholders array matches the order expected by the mobile client.

✅ Verification successful

Let me search for more context about how these placeholders are used in notifications and mobile clients.


Let me search for the notification text templates to see how these placeholders are used.


Let me try one more search to find the i18n files with a different approach.


Let me check the content of these notification translation files to understand the placeholder usage.


Based on the i18n files, I can now generate the final response as I have found the template that uses these placeholders.

Parameter ordering is correct and consistent

The placeholders in the array match the expected order in the notification template:

  • courseTitle{{ placeholderValues.0 }}
  • messageContent{{ placeholderValues.1 }}
  • messageCreationDate{{ placeholderValues.2 }}
  • conversationName{{ placeholderValues.3 }}
  • authorName{{ placeholderValues.4 }}
  • conversationType{{ placeholderValues.5 }}
  • imageUrl{{ placeholderValues.6 }}
  • userId{{ placeholderValues.7 }}
  • postId{{ placeholderValues.8 }}

The order in the array matches how they are used in the notification templates for both English and German translations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of these placeholders in the mobile client code
rg -A 5 "createPlaceholdersNewMessageChannelText" 

Length of output: 2578


Script:

#!/bin/bash
# Search for notification text templates or constants that might use these placeholders
rg -A 5 "NEW_MESSAGE_CHANNEL_TEXT" 

# Search for any mobile-related notification handling code
rg -A 5 "MobileNotification" 

# Look for any notification template or message pattern definitions
ast-grep --pattern 'String[] NOTIFICATION_PLACEHOLDERS = $_'

Length of output: 5037


Script:

#!/bin/bash
# Search for the notification text template in i18n files
fd -e json -e properties . | xargs rg -A 5 "artemisApp.conversationNotification.text.newMessageChannel"

# Look for any mobile notification handling code in Java
ast-grep --pattern 'class $_ implements MobileNotification { $$$ }'

Length of output: 767


Script:

#!/bin/bash
# Search for i18n files in src directory
fd i18n src

# If we find i18n files, let's look inside them for the notification text
rg -l "conversationNotification" $(fd i18n src)

# Also search for any mobile-specific notification classes
rg -A 5 "class.*Notification.*Mobile"

Length of output: 413


Script:

#!/bin/bash
# Check the content of notification files
cat src/main/webapp/i18n/en/notification.json
cat src/main/webapp/i18n/de/notification.json

# Also look for any notification template definitions
rg "artemisApp.conversationNotification.text" src/main/webapp/i18n/

Length of output: 29943

src/test/resources/placeholder-signatures.json (2)

78-86: LGTM! New fields added to CONVERSATION_NEW_MESSAGE.

The addition of imageUrl, userId, and postId fields enhances the notification payload with necessary metadata.


333-341: LGTM! New fields added to NEW_ANNOUNCEMENT_POST.

The addition of imageUrl, authorId, and postId fields is consistent with the notification enhancement pattern.

src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java (2)

245-247: LGTM! Proper null handling for imageUrl.

The code correctly handles null imageUrl by defaulting to an empty string.


254-256: LGTM! Updated method signature with new parameters.

The method signature update aligns with the changes in placeholder-signatures.json.

Copy link

coderabbitai bot commented Dec 3, 2024

Walkthrough

The pull request introduces multiple modifications across several classes related to notification handling within the application. Key changes include the enhancement of notification data structures by adding new parameters such as imageUrl, authorId, and postId in various notification factory methods. A new enum, PushNotificationApiType, is introduced to manage API types for push notifications. Additionally, several classes are updated to accommodate these changes, including adjustments to constructors and method signatures, ensuring that notifications carry more contextual information.

Changes

File Change Summary
src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java - Updated createAnnouncementNotification and createPlaceholdersNewAnnouncementPost methods to include imageUrl, authorId, and postId.
- Method signatures modified to reflect new parameters.
src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java - Updated createNotification and createPlaceholdersNewReply methods to include imageUrl, userId, postingId, and parentPostId.
- Enhanced error handling for unsupported notification types and user input validation.
src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java - New enum PushNotificationApiType added with constants DEFAULT and IOS_V2, including methods for retrieving database keys.
src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java - Added apiType field to the class and updated constructor and getter method to handle this new field.
src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java - Updated record to include PushNotificationApiType apiType and added a secondary constructor for backward compatibility.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java - Updated createNotification and createPlaceholdersNewMessageChannelText methods to include imageUrl, userId, and postId.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java - Updated notifyGroupsWithNotificationType method to include a boolean onlySave parameter for flexible notification handling.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java - Adjusted sendNotification method to include new parameter handling for notifications.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java - Updated record to include a new field apiType of type short.
src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java - Modified register method to include handling of apiType from pushNotificationRegisterBody.
src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java - Added new constant PUSH_NOTIFICATION_MINOR_VERSION.
src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java - Added static fields POST_ID and USER_ID for test setup.
src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java - Clarified documentation for notification placeholder modifications.
src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java - Enhanced setup for Post and AnswerPost objects with unique identifiers.
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java - Updated constructor calls for PushNotificationDeviceConfiguration to include PushNotificationApiType.
src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java - Modified constructor calls for PushNotificationDeviceConfiguration to include PushNotificationApiType.
src/test/resources/placeholder-signatures.json - Added new fields to various notification types to accommodate imageUrl, userId, postId, authorId, postingId, and parentPostId.

Possibly related PRs

Suggested labels

client, ready to merge, component:Communication, bugfix

Suggested reviewers

  • JohannesStoehr
  • SimonEntholzer
  • az108
  • florian-glombik
  • BBesrour
  • rabeatwork

Warning

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

🔧 pmd (7.7.0)
src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java

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

  • 13 others

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

Documentation and Community

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (10)
src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java (1)

218-218: Consider using a test utility for ID generation

The pattern of manually setting IDs for test objects could be improved by using a test utility method. This would make the tests more maintainable and reduce duplication.

Consider creating a utility method like:

-        post.setId(1L);
-        answerPostPost.setId(2L);
-        answerPost.setId(1L);
+        TestUtil.setTestEntityId(post, 1L);
+        TestUtil.setTestEntityId(answerPostPost, 2L);
+        TestUtil.setTestEntityId(answerPost, 1L);

Add this utility method to your test utilities:

public class TestUtil {
    public static void setTestEntityId(DomainObject entity, Long id) {
        entity.setId(id);
    }
}

Also applies to: 227-227, 229-229

src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java (1)

33-38: Documentation improvements look good, but could be even more helpful with examples.

The split between breaking and non-breaking changes is well documented. This distinction is particularly important given the PR's focus on iOS notification system changes.

Consider adding examples of what constitutes breaking vs non-breaking changes to make the documentation more actionable. For example:

 * 2a. In case of breaking changes, increment the {{@link Constants#PUSH_NOTIFICATION_VERSION}}. This ensures that old versions of the native apps discard your new
- * notifications.
+ * notifications. Example: Removing or renaming existing fields, changing field types.
 * 2b. In case of non-breaking changes, increment the {{@link Constants#PUSH_NOTIFICATION_MINOR_VERSION}} for better traceability
+ * Example: Adding new optional fields while maintaining backward compatibility.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (2)

3-3: Add Javadoc documentation for the record and its fields.

Please add documentation explaining:

  • The purpose of this record
  • The meaning and format of each field
  • Valid values for apiType
  • Any validation rules or constraints
+/**
+ * Represents a request to relay a push notification to a device.
+ *
+ * @param initializationVector The initialization vector used for encryption
+ * @param payloadCipherText The encrypted notification payload
+ * @param token The device token for notification delivery
+ * @param apiType The notification API version to use (e.g., DEFAULT or IOS_V2)
+ */
public record RelayNotificationRequest(String initializationVector, String payloadCipherText, String token, short apiType) {

3-3: Add validation for required fields.

Consider adding validation to ensure that required fields are not null or empty. This can be done using a compact constructor.

public record RelayNotificationRequest(String initializationVector, String payloadCipherText, String token, short apiType) {
+    public RelayNotificationRequest {
+        if (initializationVector == null || initializationVector.isEmpty()) {
+            throw new IllegalArgumentException("initializationVector must not be null or empty");
+        }
+        if (payloadCipherText == null || payloadCipherText.isEmpty()) {
+            throw new IllegalArgumentException("payloadCipherText must not be null or empty");
+        }
+        if (token == null || token.isEmpty()) {
+            throw new IllegalArgumentException("token must not be null or empty");
+        }
+    }
}
src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java (1)

1-23: Add JavaDoc comments for enum and methods

Consider adding JavaDoc comments to the PushNotificationApiType enum and its methods (getDatabaseKey(), fromDatabaseKey()) to enhance code readability and provide clear documentation for other developers.

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (1)

38-41: Annotate apiType with @Enumerated(EnumType.STRING)

Currently, apiType is annotated with @Enumerated without specifying the EnumType. It's recommended to explicitly define the EnumType for clarity and to avoid potential issues with the database representation.

Apply this diff to specify the enum type:

 @Enumerated
+@Enumerated(EnumType.STRING)
 @Column(name = "api_type")
 private PushNotificationApiType apiType;

Alternatively, if you prefer to store the enum ordinal:

 @Enumerated
+@Enumerated(EnumType.ORDINAL)
 @Column(name = "api_type")
 private PushNotificationApiType apiType;

Ensure that the chosen EnumType aligns with your database schema and data requirements.

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java (1)

74-74: LGTM! Consider adding edge cases.

The test setup correctly differentiates between Apple and Firebase configurations. Consider adding test cases for:

  1. Handling null apiType
  2. Migration scenarios from DEFAULT to IOS_V2

Also applies to: 76-76

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1)

87-87: LGTM! Consider extracting default value.

The null check with empty string default is appropriate. Consider extracting the empty string to a constant for consistency.

+private static final String DEFAULT_IMAGE_URL = "";
-var imageUrl = createdMessage.getAuthor().getImageUrl() == null ? "" : createdMessage.getAuthor().getImageUrl();
+var imageUrl = createdMessage.getAuthor().getImageUrl() == null ? DEFAULT_IMAGE_URL : createdMessage.getAuthor().getImageUrl();
src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1)

379-383: Add documentation for version compatibility.

The new PUSH_NOTIFICATION_MINOR_VERSION constant would benefit from documentation explaining the version compatibility matrix between iOS versions and notification payload versions.

Add Javadoc explaining version compatibility:

    /**
     * The value of the version field we send with each push notification to the native clients (Android & iOS).
+    * Version compatibility:
+    * - Major version 1:
+    *   - Minor version 1: iOS 17 and earlier
+    *   - Minor version 2: iOS 18+
     */
    public static final int PUSH_NOTIFICATION_MINOR_VERSION = 2;
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (1)

160-162: Add null checks for new notification data fields.

The new fields added to PushNotificationData should be validated to handle potential null values gracefully.

Consider adding null checks or using Optional for the new fields:

-            var notificationData = new PushNotificationData(notification.getTransientPlaceholderValuesAsArray(), notification.getTarget(), type.name(), date,
-                    Constants.PUSH_NOTIFICATION_VERSION);
+            var placeholders = notification.getTransientPlaceholderValuesAsArray();
+            var target = Objects.requireNonNull(notification.getTarget(), "Notification target cannot be null");
+            var typeName = type.name();
+            var notificationData = new PushNotificationData(placeholders, target, typeName, date,
+                    Constants.PUSH_NOTIFICATION_VERSION);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a82ca47 and 4417ed2.

⛔ Files ignored due to path filters (2)
  • src/main/resources/config/liquibase/changelog/20241114122713_changelog.xml is excluded by !**/*.xml
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (17)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java (3 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java (2 hunks)
  • src/test/resources/placeholder-signatures.json (8 hunks)
👮 Files not reviewed due to content moderation or server errors (3)
  • src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java
  • src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java
🧰 Additional context used
📓 Path-based instructions (16)
src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationPlaceholderSignatureTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/push_notifications/AppleFirebasePushNotificationServiceTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/GroupNotificationService.java (1)

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

src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationFactoryTest.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/GroupNotificationFactory.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationApiType.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java (1)

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

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java (1)

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

🔇 Additional comments (7)
src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java (1)

Line range hint 1-624: Verify test coverage for notification ID handling

The addition of explicit IDs suggests that notification handling might depend on these IDs. However, there are no explicit tests verifying this behavior.

Let's verify if there are any ID-dependent notification handling tests:

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java (1)

3-3: Verify the impact of this breaking change.

The addition of the apiType parameter is a breaking change that requires updates to all clients. Please ensure that:

  1. All constructor calls are updated
  2. Any serialization/deserialization code handles the new field
  3. Database migrations preserve existing data
✅ Verification successful

Let me gather more context about the changes and serialization handling.


Let me check one more aspect to understand if this is a new file and how the ApiType is defined.


Based on the gathered information, I can now provide the final response:

The apiType parameter addition is properly handled and doesn't require manual verification.

The change is safe because:

  1. The apiType parameter is properly integrated with a default value (PushNotificationApiType.DEFAULT) in the registration flow
  2. The only usage of RelayNotificationRequest constructor is in PushNotificationService where it correctly passes the apiType from the device configuration
  3. The PushNotificationApiType enum is properly persisted in the database with an @Enumerated column
  4. The registration flow handles backward compatibility by making the apiType parameter optional in PushNotificationRegisterBody, defaulting to PushNotificationApiType.DEFAULT
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for existing constructor calls that need to be updated
rg "new RelayNotificationRequest\(" --type java

# Search for any JSON serialization/deserialization of this class
rg "RelayNotificationRequest" -A 5 -B 5 --type java | rg -i "json|objectmapper|serialize|deserialize"

Length of output: 773


Script:

#!/bin/bash
# Check git history for this file to understand if this is a new file or modification
git log --oneline -- src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java

# Look for any database related code for this class
rg "RelayNotificationRequest" -A 5 -B 5 --type java | rg -i "repository|entity|database|jpa"

# Check the implementation of getApiType() to understand the conversion
ast-grep --pattern 'getApiType()'

Length of output: 733


Script:

#!/bin/bash
# Find the ApiType enum or class definition
rg "ApiType" -A 10 -B 2 --type java

# Check if RelayNotificationRequest is a new file by looking for deleted lines
git diff HEAD~1 -- src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/RelayNotificationRequest.java

Length of output: 27629

src/main/java/de/tum/cit/aet/artemis/communication/dto/PushNotificationRegisterBody.java (1)

6-10: Ensure default apiType maintains backward compatibility

Adding the apiType parameter to the record and providing a constructor that defaults it to PushNotificationApiType.DEFAULT ensures backward compatibility with existing code that doesn't specify apiType. This is a good practice to prevent breaking changes.

src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java (1)

45-48: Update test constructors with new apiType parameter

The test cases have been appropriately updated to include the new apiType parameter in the PushNotificationDeviceConfiguration constructor. This ensures that the tests reflect the updated class structure and continue to verify the intended functionality.

src/main/java/de/tum/cit/aet/artemis/communication/web/PushNotificationResource.java (2)

27-27: LGTM! Good handling of backward compatibility.

The addition of PushNotificationApiType with a default fallback ensures smooth transition and maintains compatibility with existing clients.

Also applies to: 104-105


109-109: Verify constructor parameter ordering.

The constructor parameter ordering looks correct, but let's verify all usages to ensure consistency.

✅ Verification successful

Let me verify the constructor definition to ensure the parameter ordering matches all usages.


Let me try a different approach to find the constructor definition.


Constructor parameter ordering is correct

All constructor calls in the codebase match the parameter order defined in the class: token, deviceType, expirationDate, secretKey, owner, apiType. The implementation in PushNotificationResource.java correctly follows this order.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all PushNotificationDeviceConfiguration constructor calls
ast-grep --pattern 'new PushNotificationDeviceConfiguration($$$)'

Length of output: 2710


Script:

#!/bin/bash
# Search for PushNotificationDeviceConfiguration class definition
ast-grep --pattern 'class PushNotificationDeviceConfiguration {
  $$$
  PushNotificationDeviceConfiguration($$$) {
    $$$
  }
  $$$
}'

Length of output: 261


Script:

#!/bin/bash
# Search for PushNotificationDeviceConfiguration class file and show its content
fd PushNotificationDeviceConfiguration.java --exec cat {}

Length of output: 4447

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/push_notifications/PushNotificationService.java (1)

173-174: Consider version compatibility in payload construction.

The code should handle different payload versions based on the device's iOS version.

Consider implementing a version-specific payload builder:

  1. Create a PayloadBuilder interface
  2. Implement version-specific builders (iOS17PayloadBuilder, iOS18PayloadBuilder)
  3. Use the appropriate builder based on device configuration

@anian03
Copy link
Member

anian03 commented Dec 3, 2024

After more intense testing with iOS versions 1.5.1 and 1.4.1, everything seems to work as expected – but "Exercise released" notifications are sent twice (they even show up twice in the notification sheet inside the app, so this is stored like that on the server). Seems like this is unrelated to this PR as I was able to reproduce the same thing on another Test Server

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 3, 2024
…s-api-to-notifications' into feature/communication/add-new-ios-api-to-notifications
@PaRangger PaRangger dismissed stale reviews from coderabbitai[bot] and anian03 via e6792b8 December 3, 2024 17:18
@PaRangger PaRangger temporarily deployed to artemis-test4.artemis.cit.tum.de December 3, 2024 18:09 — with GitHub Actions Inactive
@krusche krusche added this to the 7.7.4 milestone Dec 3, 2024
@krusche krusche changed the title Notifications: Add changes for new iOS notification system Communication: Improve push notifications for the iOS mobile app Dec 3, 2024
@krusche krusche merged commit 663684f into develop Dec 3, 2024
46 of 50 checks passed
@krusche krusche deleted the feature/communication/add-new-ios-api-to-notifications branch December 3, 2024 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. 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.

3 participants