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

248 notify user by email #258

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

248 notify user by email #258

wants to merge 44 commits into from

Conversation

iam-flo
Copy link
Contributor

@iam-flo iam-flo commented Feb 24, 2025

Motivation

We want to notify users when new bad practices are detected on their ready to merge pull requests.
This will increase interactions with Hephaestus

Description

We introduced postfix as a mail relay, a mail service, and notification settings.

Testing Instructions

Deploy the PR to staging.
Access Keycloak and give yourself "notification_access" role.
Access https://staging.hephaestus.aet.cit.tum.de/settings and enable notifications.
Access one of your pull requests on Github and add the "ready to merge" label.
Wait until you get a mail.

Screenshots (if applicable)

Bildschirmfoto 2025-03-11 um 16 01 41
Bildschirmfoto 2025-03-11 um 10 13 25

Checklist

General

  • PR title is clear and descriptive
  • PR description explains the purpose and changes
  • Code follows project coding standards
  • Self-review of the code has been done
  • Changes have been tested locally
  • Screenshots have been attached (if applicable)
  • Documentation has been updated (if applicable)

Client (if applicable)

  • UI changes look good on all screen sizes and browsers
  • No console errors or warnings
  • User experience and accessibility have been tested
  • Added Storybook stories for new components
  • Components follow design system guidelines (if applicable)

Server (if applicable)

  • Code is performant and follows best practices
  • No security vulnerabilities introduced
  • Proper error handling has been implemented
  • Added tests for new functionality
  • Changes have been tested in different environments (if applicable)

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated settings interface for managing notification preferences and account options.
    • Enhanced email functionality with dynamic templates and automated alerts for improved communication.
    • Added new endpoints for retrieving and updating user settings related to notifications.
    • Implemented a toggle for enabling/disabling email notifications in the settings component.
    • Introduced user settings management for notification preferences.
    • Added a new field for tracking whether notifications are enabled for users.
    • Added a new HTML template for notifying users about detected bad practices in pull requests.
    • Enhanced the application server with new configurations for mail settings and improved notification handling.
    • Introduced a new database column for tracking user notification settings.
    • Added new roles and user configurations for managing notification access.
    • Updated mail configuration to use environment variables for enhanced flexibility.
    • Enhanced application server service configuration with new environment variables.
    • Removed deprecated postfix service from the application stack.
  • Chores

    • Updated system configurations and deployment setups to support enhanced mailing capabilities across environments.
    • Removed deprecated mail configuration properties to streamline setup.

@iam-flo iam-flo self-assigned this Feb 24, 2025
@iam-flo iam-flo linked an issue Feb 24, 2025 that may be closed by this pull request
Copy link
Contributor

coderabbitai bot commented Feb 24, 2025

Walkthrough

This pull request introduces significant updates, including the removal of the postfix service from the compose.yaml file, the addition of email functionality and templating dependencies, and enhancements to user settings and notifications. New API endpoints for retrieving and updating notification preferences are established, along with database schema changes for user notifications. The updates also include new mail utility classes and configurations for both development and production environments, as well as corresponding OpenAPI definitions and model updates to support these features.

Changes

File(s) Change Summary
server/application-server/compose.yaml Removed the postfix service configuration, including its image, volume mounts, hostname, and network settings.
server/application-server/pom.xml Added dependencies for spring-boot-starter-mail and spring-boot-starter-thymeleaf.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java
.../UserController.java
.../UserService.java
.../UserSettingsDTO.java
Extended the User module by adding a notificationsEnabled flag, new endpoints in UserController for GET and POST on /settings, and new service methods to retrieve and update user notification settings using the UserSettingsDTO record.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
.../MailConfig.java
.../MailService.java
Introduced mail functionality with new classes for building emails (MailBuilder), configuring mail settings (MailConfig), and sending emails (MailService), including Thymeleaf template processing and error logging.
server/application-server/src/main/resources/application.yml
server/application-server/src/main/resources/application-prod.yml
Added new configurations for Thymeleaf and mail settings under both spring and hephaestus sections.
server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml
server/application-server/src/main/resources/db/master.xml
Added a Liquibase changelog file to include a new non-nullable boolean column notifications_enabled (default false) in the user table, and updated the master changelog to include it.
server/application-server/src/main/resources/mail-templates/bad-practices-detected.html Introduced a new Thymeleaf HTML email template for notifying users about detected bad practices.
server/application-server/openapi.yaml
webapp/src/app/core/modules/openapi/api/user.service.ts
.../user.serviceInterface.ts
webapp/src/app/core/modules/openapi/model/models.ts
webapp/src/app/core/modules/openapi/model/user-settings.ts
webapp/src/app/core/modules/openapi/.openapi-generator/FILES
Added new OpenAPI endpoints (GET and POST on /user/settings) along with corresponding schema definitions and TypeScript model/interface for user settings.
webapp/src/app/settings/settings.component.html
webapp/src/app/settings/settings.component.ts
Implemented new settings UI featuring notification toggling, with a reactive form and logic to save or delete account settings.

Suggested labels

feature, needs documentation, lgtm

Suggested reviewers

  • GODrums
  • FelixTJDietrich
  • milesha

Poem

I'm hopping through the lines of code, so light,
New postfix and settings shine ever so bright.
With emails and toggles, our system takes flight,
Bugs scurry away in the soft morning light.
From server to webapp, each change feels just right!
A rabbit's cheer for code done tight. 🐰

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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 generate docstrings to generate docstrings for 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 anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

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

@github-actions github-actions bot added application-server size:L This PR changes 100-499 lines, ignoring generated files. labels Feb 24, 2025
@iam-flo iam-flo marked this pull request as ready for review February 24, 2025 16:16
@dosubot dosubot bot added the enhancement New feature or request label Feb 24, 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: 7

🧹 Nitpick comments (8)
server/application-server/src/main/resources/mail-templates/bad-practices-detected.html (1)

1-5: Enhance the email template with more detailed information.

While the template includes the basic information, it could be more helpful by including:

  • A link to the specific pull request
  • More details about the detected bad practice
  • Suggestions for fixing the issue
  • A call-to-action button/link

Apply this diff to enhance the template:

 <p th:inline="text">
     Hi [[${user.name}]],
     <br>
-    We have detected the bad practice [[${badPractice}]] in your pull request. Please review the issue on Hephaestus.
+    We have detected a bad practice in your pull request #[[${pullRequest.number}]]:
+    <br><br>
+    <strong>[[${badPractice}]]</strong>
+    <br><br>
+    To help you address this issue:
+    <br>
+    [[${suggestion}]]
+    <br><br>
+    <a href="[[${pullRequestUrl}]]" style="background-color: #4CAF50; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Review on Hephaestus</a>
 </p>
server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java (1)

102-104: Add documentation for the notifications feature.

While the implementation is correct, consider adding Javadoc to document the purpose and usage of this feature.

Apply this diff to add documentation:

     @NonNull
+    /**
+     * Indicates whether the user has opted in to receive email notifications.
+     * This setting affects various notification types including bad practice alerts.
+     */
     private boolean notificationsEnabled = false;
server/application-server/compose.yaml (1)

35-44: Consider improving service reliability.

A few suggestions to enhance the postfix service configuration:

  1. Use a specific version tag instead of latest to ensure reproducible builds
  2. Add a health check to ensure the service is running correctly

Apply this diff to implement the suggestions:

   postfix:
-    image: ghcr.io/ls1admin/postfix:latest
+    image: ghcr.io/ls1admin/postfix:1.0.0  # Replace with actual version
     container_name: hephaestus-postfix
     restart: unless-stopped
     volumes:
       - ./postfix-config:/config
     hostname: hephaestus.aet.cit.tum.de
+    healthcheck:
+      test: ["CMD", "postfix", "status"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
     networks:
       - app-network
🧰 Tools
🪛 YAMLlint (1.35.1)

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)

server/application-server/src/main/resources/application.yml (1)

36-47: Consider adding additional mail security configurations.

While the basic SMTP configuration is correct, consider adding these security enhancements:

  • Enable SSL/TLS by default
  • Configure connection timeout
  • Set authentication settings explicitly
    mail:
        host: ${POSTFIX_HOST:localhost}
        port: ${POSTFIX_PORT:25}
        username: ${POSTFIX_USERNAME:}
        password: ${POSTFIX_PASSWORD:}
        properties:
            mail:
                transport:
                    protocol: smtp
                smtp:
                    starttls:
                        enable: true
+                   auth: true
+                   connectiontimeout: 5000
+                   timeout: 5000
+                   writetimeout: 5000
+                   ssl:
+                       enable: true
server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserService.java (2)

91-94: Improve logging and add null check.

The method should use parameterized logging and validate the user parameter.

    public UserSettingsDTO getUserSettings(User user) {
-       logger.info("Getting user settings with userId: " + user);
+       if (user == null) {
+           throw new IllegalArgumentException("User cannot be null");
+       }
+       logger.info("Getting user settings for user: {}", user.getLogin());
        return new UserSettingsDTO(user.isNotificationsEnabled());
    }

96-101: Add validation and improve logging.

The method should validate both parameters and use parameterized logging.

    public UserSettingsDTO updateUserSettings(User user, UserSettingsDTO userSettings) {
-       logger.info("Updating user settings with userId: " + user);
+       if (user == null || userSettings == null) {
+           throw new IllegalArgumentException("User and userSettings cannot be null");
+       }
+       logger.info("Updating notification settings to {} for user: {}", 
+           userSettings.receiveNotifications(), user.getLogin());
        user.setNotificationsEnabled(userSettings.receiveNotifications());
        userRepository.save(user);
+       logger.debug("Successfully updated notification settings for user: {}", user.getLogin());
        return new UserSettingsDTO(user.isNotificationsEnabled());
    }
server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailConfig.java (1)

16-16: Consider making enabled field final and adding @Getter.

The enabled field is only accessed through the isEnabled() method. For consistency with other fields and to follow the class's immutable design pattern:

-    private final Boolean enabled;
+    @Getter
+    private final Boolean enabled;

-    public boolean isEnabled() {
-        return enabled;
-    }

Also applies to: 40-42

server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1)

110-111: Consider using a consistent method for setting the sender address.

The code uses both setFrom and setSender which might be redundant:

-                message.setFrom("Hephaestus <" + config.getSender().getAddress() + ">");
-                message.setSender(config.getSender());
+                message.setFrom(config.getSender());
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99ec0ab and 7d984d8.

📒 Files selected for processing (13)
  • server/application-server/compose.yaml (1 hunks)
  • server/application-server/pom.xml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserController.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserService.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserSettingsDTO.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailConfig.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (1 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml (1 hunks)
  • server/application-server/src/main/resources/db/master.xml (1 hunks)
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserSettingsDTO.java
  • server/application-server/src/main/resources/db/master.xml
🧰 Additional context used
🪛 YAMLlint (1.35.1)
server/application-server/compose.yaml

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Mend Security Check
🔇 Additional comments (5)
server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml (1)

1-10: LGTM! The changelog is well-structured.

The Liquibase changelog correctly defines the new notifications_enabled column with appropriate constraints and default value.

server/application-server/pom.xml (1)

95-102: LGTM!

The required dependencies for email functionality and template rendering have been correctly added.

server/application-server/src/main/resources/application.yml (2)

32-34: LGTM!

The Thymeleaf configuration is correctly set up with a configurable template folder and HTML suffix.


71-74: LGTM!

The mail settings under the hephaestus section are correctly configured with environment variables.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (1)

13-26: LGTM!

The service class is correctly structured with proper dependency injection and logging setup.

Comment on lines 28 to 50
public void sendBadPracticesDetectedEmail(User user, String badPractice) {
logger.info("Sending bad practice detected email to user: " + user.getLogin());
if (!user.getLogin().equals("iam-flo"))
return;

MailBuilder mailBuilder = new MailBuilder(mailConfig, "Bad Practices Detected", "bad-practices-detected");
mailBuilder
.addPrimaryRecipient(user)
.fillUserPlaceholders(user, "user")
.fillBadPracticePlaceholders(badPractice, "badPractice")
.send(javaMailSender);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove hardcoded user check and improve error handling.

The method has several issues:

  1. The hardcoded user check user.getLogin().equals("iam-flo") should be removed.
  2. Missing null checks for user and badPractice parameters.
  3. No error handling for mail sending failures.

Apply this diff to fix the issues:

    public void sendBadPracticesDetectedEmail(User user, String badPractice) {
+       if (user == null || badPractice == null) {
+           logger.error("Cannot send email: user or badPractice is null");
+           return;
+       }
+
        logger.info("Sending bad practice detected email to user: {}", user.getLogin());
-       if (!user.getLogin().equals("iam-flo"))
+       if (!user.isNotificationsEnabled()) {
+           logger.debug("Notifications disabled for user: {}", user.getLogin());
            return;
+       }

        try {
            MailBuilder mailBuilder = new MailBuilder(mailConfig, "Bad Practices Detected", "bad-practices-detected");
            mailBuilder
                    .addPrimaryRecipient(user)
                    .fillUserPlaceholders(user, "user")
                    .fillBadPracticePlaceholders(badPractice, "badPractice")
                    .send(javaMailSender);
+           logger.debug("Email sent successfully to user: {}", user.getLogin());
+       } catch (Exception e) {
+           logger.error("Failed to send email to user: {}", user.getLogin(), e);
+       }
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void sendBadPracticesDetectedEmail(User user, String badPractice) {
logger.info("Sending bad practice detected email to user: " + user.getLogin());
if (!user.getLogin().equals("iam-flo"))
return;
MailBuilder mailBuilder = new MailBuilder(mailConfig, "Bad Practices Detected", "bad-practices-detected");
mailBuilder
.addPrimaryRecipient(user)
.fillUserPlaceholders(user, "user")
.fillBadPracticePlaceholders(badPractice, "badPractice")
.send(javaMailSender);
}
public void sendBadPracticesDetectedEmail(User user, String badPractice) {
if (user == null || badPractice == null) {
logger.error("Cannot send email: user or badPractice is null");
return;
}
logger.info("Sending bad practice detected email to user: {}", user.getLogin());
if (!user.isNotificationsEnabled()) {
logger.debug("Notifications disabled for user: {}", user.getLogin());
return;
}
try {
MailBuilder mailBuilder = new MailBuilder(mailConfig, "Bad Practices Detected", "bad-practices-detected");
mailBuilder
.addPrimaryRecipient(user)
.fillUserPlaceholders(user, "user")
.fillBadPracticePlaceholders(badPractice, "badPractice")
.send(javaMailSender);
logger.debug("Email sent successfully to user: {}", user.getLogin());
} catch (Exception e) {
logger.error("Failed to send email to user: {}", user.getLogin(), e);
}
}

Comment on lines 29 to 32
@Value("${hephaestus.mail.sender}") InternetAddress sender,
@Value("${hephaestus.mail.enabled}") boolean enabled,
@Value("${hephaestus.mail.signature}") String mailSignature,
TemplateEngine templateEngine
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate mail configuration parameters.

The constructor accepts critical configuration parameters but doesn't validate them. Consider adding validation to ensure the configuration is valid:

     @Autowired
     public MailConfig(
             @Value("${hephaestus.mail.sender}") InternetAddress sender,
             @Value("${hephaestus.mail.enabled}") boolean enabled,
             @Value("${hephaestus.mail.signature}") String mailSignature,
             TemplateEngine templateEngine
     ) {
+        if (sender == null) {
+            throw new IllegalArgumentException("Sender address must not be null");
+        }
+        if (templateEngine == null) {
+            throw new IllegalArgumentException("Template engine must not be null");
+        }
         this.enabled = enabled;
         this.sender = sender;
         this.signature = mailSignature;
         this.templateEngine = templateEngine;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Value("${hephaestus.mail.sender}") InternetAddress sender,
@Value("${hephaestus.mail.enabled}") boolean enabled,
@Value("${hephaestus.mail.signature}") String mailSignature,
TemplateEngine templateEngine
@Autowired
public MailConfig(
@Value("${hephaestus.mail.sender}") InternetAddress sender,
@Value("${hephaestus.mail.enabled}") boolean enabled,
@Value("${hephaestus.mail.signature}") String mailSignature,
TemplateEngine templateEngine
) {
if (sender == null) {
throw new IllegalArgumentException("Sender address must not be null");
}
if (templateEngine == null) {
throw new IllegalArgumentException("Template engine must not be null");
}
this.enabled = enabled;
this.sender = sender;
this.signature = mailSignature;
this.templateEngine = templateEngine;
}

List<User> toRecipients = new ArrayList<>();

for (User recipient : primaryRecipients) {
if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null || !recipient.getEmail().contains("@")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve email validation.

The current email validation is too basic. Consider using a more robust validation method:

-            if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null || !recipient.getEmail().contains("@")) {
+            if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null || 
+                !recipient.getEmail().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null || !recipient.getEmail().contains("@")) {
if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null ||
!recipient.getEmail().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {

Comment on lines 95 to 119

public void send(JavaMailSender mailSender) {
List<User> toRecipients = new ArrayList<>();

for (User recipient : primaryRecipients) {
if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null || !recipient.getEmail().contains("@")) {
continue;
}
toRecipients.add(recipient);
}

for (User recipient : toRecipients) {
try {
MimeMessage message = mailSender.createMimeMessage();

message.setFrom("Hephaestus <" + config.getSender().getAddress() + ">");
message.setSender(config.getSender());

message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient.getEmail()));

Context templateContext = new Context();
templateContext.setVariables(this.variables);
templateContext.setVariable("recipient", UserInfoDTO.fromUser(recipient));

message.setSubject(subject);

Multipart messageContent = new MimeMultipart();

BodyPart messageBody = new MimeBodyPart();
messageBody.setContent(config.getTemplateEngine().process(template, templateContext), "text/html; charset=utf-8");
messageContent.addBodyPart(messageBody);

message.setContent(messageContent);

if (config.isEnabled()) {
log.info("Sending Mail\n{}", messageBody.getContent());
mailSender.send(message);
} else {
log.info("Sending Mail (postfix disabled)\n{}", messageBody.getContent());
}
} catch (Exception exception) {
log.warn("Failed to send email", exception);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling and add retry mechanism.

The send method has several areas for improvement:

  1. Catch specific exceptions instead of generic Exception
  2. Add retry mechanism for transient failures
  3. Add metrics for monitoring
     public void send(JavaMailSender mailSender) {
+        if (mailSender == null) {
+            throw new IllegalArgumentException("mailSender must not be null");
+        }
         List<User> toRecipients = new ArrayList<>();

         for (User recipient : primaryRecipients) {
             if (!recipient.isNotificationsEnabled() || recipient.getEmail() == null || !recipient.getEmail().contains("@")) {
                 continue;
             }
             toRecipients.add(recipient);
         }

         for (User recipient : toRecipients) {
+            int retryCount = 0;
+            while (retryCount < 3) {
                 try {
                     MimeMessage message = mailSender.createMimeMessage();
                     // ... existing code ...
                     if (config.isEnabled()) {
                         log.info("Sending Mail\n{}", messageBody.getContent());
                         mailSender.send(message);
+                        break;
                     } else {
                         log.info("Sending Mail (postfix disabled)\n{}", messageBody.getContent());
+                        break;
                     }
-                } catch (Exception exception) {
-                    log.warn("Failed to send email", exception);
+                } catch (MessagingException e) {
+                    log.warn("Failed to send email to {}, attempt {}/3", recipient.getEmail(), retryCount + 1, e);
+                    retryCount++;
+                    if (retryCount == 3) {
+                        log.error("Failed to send email to {} after 3 attempts", recipient.getEmail(), e);
+                    }
+                    Thread.sleep(1000 * retryCount);
+                } catch (Exception e) {
+                    log.error("Unexpected error while sending email to {}", recipient.getEmail(), e);
+                    break;
                 }
+            }
         }
     }

Committable suggestion skipped: line range outside the PR's diff.

@FelixTJDietrich FelixTJDietrich marked this pull request as draft February 24, 2025 16:29
@FelixTJDietrich FelixTJDietrich marked this pull request as ready for review February 24, 2025 16:29
@iam-flo iam-flo force-pushed the 248-notify-user-by-email branch from 7d984d8 to d57d93e Compare February 24, 2025 16:34
@github-actions github-actions bot added client size:XL This PR changes 500-999 lines, ignoring generated files. and removed autocommit-openapi size:L This PR changes 100-499 lines, ignoring generated files. labels Feb 24, 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: 4

🔭 Outside diff range comments (1)
server/application-server/src/main/resources/application.yml (1)

36-74: ⚠️ Potential issue

Review mail configuration for production security.

The mail configuration has potential security concerns:

  1. Port 25 (default) is unencrypted SMTP. Consider using port 587 (STARTTLS) or 465 (SMTPS) by default.
  2. The default sender email ([email protected]) should not be used in production.

Apply this diff to enhance security:

    mail:
-        host: ${POSTFIX_HOST:localhost}
-        port: ${POSTFIX_PORT:25}
+        host: ${POSTFIX_HOST:localhost}
+        port: ${POSTFIX_PORT:587}
         username: ${POSTFIX_USERNAME:}
         password: ${POSTFIX_PASSWORD:}
         properties:
             mail:
                 transport:
                     protocol: smtp
                 smtp:
                     starttls:
                         enable: true
+                        required: true
+                    auth: true

     hephaestus:
         mail:
             enabled: ${MAIL_ENABLED:true}
-            sender: ${MAIL_SENDER:[email protected]}
+            sender: ${MAIL_SENDER:}
             signature: ${MAIL_SIGNATURE:}
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 54-54: trailing spaces

(trailing-spaces)


[error] 62-62: trailing spaces

(trailing-spaces)


[error] 67-67: trailing spaces

(trailing-spaces)

🧹 Nitpick comments (4)
webapp/src/app/core/modules/openapi/api/user.serviceInterface.ts (1)

41-52: Add proper documentation for the new methods.

The new methods lack proper documentation. Please add descriptions explaining:

  • The purpose of each method
  • Expected behavior
  • Any side effects
  • Parameter descriptions for userSettings

Apply this diff to add documentation:

     /**
-     * 
-     * 
+     * Retrieves the current user's notification settings.
+     * 
+     * @returns An Observable that emits the user's settings
      */
     getUserSettings(extraHttpRequestParams?: any): Observable<UserSettings>;

     /**
-     * 
-     * 
-     * @param userSettings 
+     * Updates the current user's notification settings.
+     * 
+     * @param userSettings The new settings to apply
+     * @returns An Observable that emits the updated settings
      */
     updateUserSettings(userSettings: UserSettings, extraHttpRequestParams?: any): Observable<UserSettings>;
webapp/src/app/core/modules/openapi/api/user.service.ts (3)

23-24: Remove unnecessary @ts-ignore.

If there is no actual type error here, consider removing the @ts-ignore for better type safety and clarity:

- // @ts-ignore
  import { UserSettings } from '../model/user-settings';

If removing @ts-ignore raises a type error, please clarify the underlying issue so we can address it properly.


221-278: Use optional chaining to simplify checks on options.

Multiple lines in this block (232, 244, 249) use the options && options.property pattern. You can adopt optional chaining to simplify your code:

      let localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept;
      ...
      let localVarHttpContext: HttpContext | undefined = options?.context;
      ...
      let localVarTransferCache: boolean | undefined = options?.transferCache;
🧰 Tools
🪛 Biome (1.9.4)

[error] 232-232: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 244-244: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 249-249: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


280-351: Adopt consistent REST practices and simplify code with optional chaining.

  1. Consider using a PUT or PATCH request for resource updates. This is a stylistic convention, but you might prefer consistency with standard REST patterns.
  2. Apply optional chaining in lines 295, 307, and 312, mirroring the refactor suggestion for getUserSettings:
  let localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept;
  ...
  let localVarHttpContext: HttpContext | undefined = options?.context;
  ...
  let localVarTransferCache: boolean | undefined = options?.transferCache;

Ensure these methods have proper test coverage (unit or integration tests) confirming that user settings are correctly retrieved and updated.

🧰 Tools
🪛 Biome (1.9.4)

[error] 295-295: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 307-307: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 312-312: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d984d8 and 0775a8f.

📒 Files selected for processing (19)
  • server/application-server/compose.yaml (1 hunks)
  • server/application-server/openapi.yaml (2 hunks)
  • server/application-server/pom.xml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserController.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserService.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserSettingsDTO.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailConfig.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (1 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml (1 hunks)
  • server/application-server/src/main/resources/db/master.xml (1 hunks)
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html (1 hunks)
  • webapp/src/app/core/modules/openapi/.openapi-generator/FILES (1 hunks)
  • webapp/src/app/core/modules/openapi/api/user.service.ts (2 hunks)
  • webapp/src/app/core/modules/openapi/api/user.serviceInterface.ts (2 hunks)
  • webapp/src/app/core/modules/openapi/model/models.ts (1 hunks)
  • webapp/src/app/core/modules/openapi/model/user-settings.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • webapp/src/app/core/modules/openapi/model/user-settings.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserSettingsDTO.java
  • server/application-server/src/main/resources/db/master.xml
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html
  • server/application-server/pom.xml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserController.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java
  • server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailConfig.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
🧰 Additional context used
🪛 Biome (1.9.4)
webapp/src/app/core/modules/openapi/api/user.service.ts

[error] 232-232: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 244-244: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 249-249: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 295-295: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 307-307: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 312-312: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 YAMLlint (1.35.1)
server/application-server/compose.yaml

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
🔇 Additional comments (5)
webapp/src/app/core/modules/openapi/model/models.ts (1)

13-13: LGTM!

The new export statement for user-settings is correctly placed and aligns with the module's export pattern.

webapp/src/app/core/modules/openapi/.openapi-generator/FILES (1)

37-37: LGTM!

The new entry for user-settings.ts is correctly placed and follows the established pattern for model files.

server/application-server/compose.yaml (2)

35-41: LGTM! Please verify the hostname configuration.

The postfix service configuration looks good, but please verify that the hostname hephaestus.aet.cit.tum.de is the correct domain for your environment.


42-43: Fix indentation in networks section.

The indentation is incorrect (8 spaces instead of 6).

Apply this diff to fix the indentation:

    networks:
-        - app-network
+      - app-network
🧰 Tools
🪛 YAMLlint (1.35.1)

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)

server/application-server/src/main/resources/application.yml (1)

32-34: LGTM!

The Thymeleaf configuration is well-structured, allowing for customization of the template folder via environment variables while providing sensible defaults.

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 (5)
webapp/src/app/settings/settings.component.html (3)

1-13: The notification settings UI looks good, consider adding feedback after save.

The notification settings section is well structured with clear labeling and a logical layout. The toggle switch for email notifications is properly bound to the form control.

Consider adding a success message or visual feedback after the settings are saved successfully to improve user experience.


12-12: Add loading state to the save button.

The save button doesn't appear to have a loading state while the settings are being saved. This could lead to user confusion if the save operation takes time.

Consider adding a loading state to the button:

-    <button hlmBtn variant="outline" class="w-full" (click)="saveSettings()">Save settings</button>
+    <button hlmBtn variant="outline" class="w-full" (click)="saveSettings()" [disabled]="settingsMutation.isPending">
+      {{ settingsMutation.isPending ? 'Saving...' : 'Save settings' }}
+    </button>

15-15: Incorrect id attribute for delete account button.

The delete account button has an id "edit-profile" which doesn't match its function.

-    <button id="edit-profile" variant="outline" brnAlertDialogTrigger hlmBtn>Delete Account</button>
+    <button id="delete-account" variant="outline" brnAlertDialogTrigger hlmBtn>Delete Account</button>
webapp/src/app/settings/settings.component.ts (2)

47-47: Consider adding a default value comment for form control.

The form control initializes with a default value of false but it's not clear if this is intentional or just a placeholder until the real value is loaded.

-  _newNotificationEnabled = new FormControl(false);
+  // Default to disabled until user settings are loaded
+  _newNotificationEnabled = new FormControl(false);

70-72: Add feedback handling in the saveSettings method.

The current implementation doesn't provide any user feedback after saving settings.

Consider modifying the saveSettings method to handle success and error states:

  saveSettings() {
-    this.settingsMutation.mutate({ receiveNotifications: this._newNotificationEnabled.value ?? false });
+    this.settingsMutation.mutate(
+      { receiveNotifications: this._newNotificationEnabled.value ?? false },
+      {
+        onSuccess: () => {
+          // Show success notification to user
+          console.log('Settings saved successfully');
+        },
+        onError: (error) => {
+          // Show error message to user
+          console.error('Failed to save settings:', error);
+        }
+      }
+    );
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0775a8f and 80783e1.

📒 Files selected for processing (2)
  • webapp/src/app/settings/settings.component.html (1 hunks)
  • webapp/src/app/settings/settings.component.ts (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
  • GitHub Check: Run Chromatic
  • GitHub Check: Mend Security Check
🔇 Additional comments (2)
webapp/src/app/settings/settings.component.html (1)

14-26: Account deletion dialog implementation looks good.

The account deletion confirmation dialog follows best practices:

  1. Clear warning about the permanent nature of the action
  2. Explicit confirmation required
  3. Easy way to cancel the action
  4. Clear labeling of actions
webapp/src/app/settings/settings.component.ts (1)

43-73: Initialize settings when component loads.

The component doesn't explicitly trigger the loading of settings when it initializes. While injectQuery may handle this automatically, it would be clearer to explicitly trigger or ensure the query runs on initialization.

It appears the component relies on the automatic execution of the query. Please verify that settings are being loaded correctly when the component is initialized. If a more explicit approach is preferred, consider adding an ngOnInit lifecycle hook that triggers the query.

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

🧹 Nitpick comments (2)
server/application-server/src/main/resources/application-prod.yml (2)

16-28: New SMTP Mail Configuration in the Spring Section

The new mail configuration under spring is clear and well-organized. It correctly defines properties such as host, port, username, password, and includes the necessary nested properties for SMTP transport and STARTTLS.

Suggestions:

  • Ensure that the environment variables (POSTFIX_HOST, POSTFIX_PORT, POSTFIX_USERNAME, and POSTFIX_PASSWORD) are properly secured and set in production.
  • Consider adding inline comments to describe each setting briefly for easier maintenance and clarity in the future.

46-50: New Hephaestus Mail Configuration Section

The addition of the mail configuration under hephaestus provides a neat way to control mail functionality specific to Hephaestus. Using environment variables to manage enabled, sender, and signature is a good approach.

Suggestions:

  • The default empty values for sender and signature may lead to unintended behavior if not explicitly configured. Consider either providing sensible defaults or adding clear documentation/comments indicating that these values must be set in a production environment when mail is enabled.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80783e1 and 27c4c16.

📒 Files selected for processing (3)
  • server/application-server/compose.yaml (1 hunks)
  • server/application-server/src/main/resources/application-prod.yml (2 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/application-server/src/main/resources/application.yml
🧰 Additional context used
🪛 YAMLlint (1.35.1)
server/application-server/compose.yaml

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Run Chromatic
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
🔇 Additional comments (2)
server/application-server/compose.yaml (2)

35-44: New Postfix Service Addition

The addition of the postfix service is well integrated. This service is configured with an appropriate image, container name, restart policy, volume binding, and hostname substitution, which aligns with the email notification functionality. Please ensure that the ./postfix-config directory contains the required configuration files for Postfix.

🧰 Tools
🪛 YAMLlint (1.35.1)

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)


43-43: Fix Indentation in Networks Section

YAMLlint reports that the list item under the networks key is indented with 8 spaces instead of the expected 6. This indentation error can lead to parsing issues.

Apply the following diff to correct the indentation:

-        - app-network
+      - app-network
🧰 Tools
🪛 YAMLlint (1.35.1)

[warning] 43-43: wrong indentation: expected 6 but found 8

(indentation)

iam-flo added a commit that referenced this pull request Mar 3, 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: 0

🧹 Nitpick comments (1)
server/application-server/src/main/resources/application-prod.yml (1)

46-50: Review of Hephaestus Mail Configuration

The introduction of the mail configuration under the hephaestus section clearly enables configurable email functionality within the application. The default sender email is provided, and the feature is gated by the MAIL_ENABLED variable. Consider adding inline comments to document the purpose of each parameter (especially the empty default for MAIL_SIGNATURE) to improve clarity and maintainability for future developers.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27c4c16 and d2e3720.

📒 Files selected for processing (3)
  • server/application-server/compose.yaml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1 hunks)
  • server/application-server/src/main/resources/application-prod.yml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • server/application-server/compose.yaml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
🔇 Additional comments (1)
server/application-server/src/main/resources/application-prod.yml (1)

16-28: Review of Spring Mail Configuration

The new mail configuration under the spring section is well structured and leverages environment variables with sensible defaults. Please verify that the empty defaults for POSTFIX_USERNAME and POSTFIX_PASSWORD are acceptable for your SMTP server—especially in cases where authentication might be required. If authentication is needed, you may need to enforce stricter defaults or additional validations.

@iam-flo iam-flo force-pushed the 248-notify-user-by-email branch from d2e3720 to 058956b Compare March 3, 2025 14:55
iam-flo added a commit that referenced this pull request Mar 3, 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: 0

🧹 Nitpick comments (9)
server/application-server/src/main/resources/application.yml (2)

36-49: Mail Settings Configuration

This block introduces comprehensive SMTP settings for Gmail. The configuration is generally correct. A few points to consider:

  • Debug Mode: The debug: true setting is useful for development, but ensure that it’s disabled in production environments (e.g., via profile-specific configurations).
  • Credential Management: The use of ${POSTFIX_USERNAME:} and ${POSTFIX_PASSWORD:} is appropriate for injecting values securely. Make sure these environment variables are properly managed in production.

76-79: Application-Level Mail Settings

The new mail section under hephaestus introduces application-specific mail settings, such as enabled, sender, and signature. This is a good separation from the SMTP configurations under spring.mail. Consider:

  • Validation: If notifications are enabled, ensure that sender is not left empty—either handle it in the application logic or provide a sensible default.
  • Documentation: Clearly document the distinction between spring.mail (for SMTP connection details) and hephaestus.mail (for application email behaviors) to aid future maintenance.
webapp/src/app/core/modules/openapi/api/user.serviceInterface.ts (1)

41-53: Add documentation for the new settings methods.

The new methods lack proper JSDoc descriptions to explain their purpose and parameters. This makes it harder for developers to understand their usage.

Improve the JSDoc documentation:

    /**
-     * 
-     * 
+     * Retrieves the current user's notification settings
+     * 
+     * @returns Observable containing the user's settings
     */
    getUserSettings(extraHttpRequestParams?: any): Observable<UserSettings>;

    /**
-     * 
-     * 
+     * Updates the current user's notification settings
+     * 
+     * @param userSettings The settings to be updated
+     * @returns Observable containing the updated user settings
     * @param userSettings 
     */
    updateUserSettings(userSettings: UserSettings, extraHttpRequestParams?: any): Observable<UserSettings>;
webapp/src/app/settings/settings.component.ts (2)

47-47: Consider using a more descriptive name for the form control.

The underscore prefix typically indicates a private property, but the naming doesn't clearly communicate what this control represents.

-  _newNotificationEnabled = new FormControl(false);
+  notificationEnabledControl = new FormControl(false);

70-72: Add feedback to user after saving settings.

The saveSettings method should provide feedback to the user after successful update or on error.

  saveSettings() {
-    this.settingsMutation.mutate({ receiveNotifications: this._newNotificationEnabled.value ?? false });
+    this.settingsMutation.mutate(
+      { receiveNotifications: this._newNotificationEnabled.value ?? false },
+      {
+        onSuccess: () => {
+          // Show success message to user
+          console.log('Settings saved successfully');
+          // You could use a toast notification service here
+        },
+        onError: (error) => {
+          console.error('Failed to save settings:', error);
+          // Show error message to user
+        }
+      }
+    );
  }
webapp/src/app/core/modules/openapi/api/user.service.ts (4)

23-24: Import looks good but consider removing the @ts-ignore comment.

The import of the UserSettings model is necessary for the new functionality, but the @ts-ignore comment suggests there might be TypeScript errors being suppressed. Consider addressing the underlying issue instead of ignoring it.

-// @ts-ignore
+// Import the UserSettings model for user notification preferences
 import { UserSettings } from '../model/user-settings';

221-278: Implement optional chaining for cleaner code in getUserSettings method.

The method looks functionally correct, but you can modernize the property access pattern using optional chaining.

-        let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
+        let localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept;

-        let localVarHttpContext: HttpContext | undefined = options && options.context;
+        let localVarHttpContext: HttpContext | undefined = options?.context;

-        let localVarTransferCache: boolean | undefined = options && options.transferCache;
+        let localVarTransferCache: boolean | undefined = options?.transferCache;
🧰 Tools
🪛 Biome (1.9.4)

[error] 232-232: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 244-244: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 249-249: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


280-351: Implement optional chaining for cleaner code in updateUserSettings method.

The method correctly handles input validation and properly implements the update functionality, but the same modernization opportunity exists here as well.

-        let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
+        let localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept;

-        let localVarHttpContext: HttpContext | undefined = options && options.context;
+        let localVarHttpContext: HttpContext | undefined = options?.context;

-        let localVarTransferCache: boolean | undefined = options && options.transferCache;
+        let localVarTransferCache: boolean | undefined = options?.transferCache;
🧰 Tools
🪛 Biome (1.9.4)

[error] 295-295: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 307-307: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 312-312: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


289-291: Consider adding type validation beyond null/undefined checks.

While checking for null/undefined is good, consider adding additional validation for the userSettings object to ensure it contains the expected properties before sending to the server.

 if (userSettings === null || userSettings === undefined) {
     throw new Error('Required parameter userSettings was null or undefined when calling updateUserSettings.');
 }
+// Validate that userSettings has the expected properties
+if (userSettings.notificationsEnabled === undefined) {
+    throw new Error('Required property notificationsEnabled was missing in userSettings parameter.');
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2e3720 and 058956b.

📒 Files selected for processing (22)
  • server/application-server/compose.yaml (1 hunks)
  • server/application-server/openapi.yaml (2 hunks)
  • server/application-server/pom.xml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserController.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserService.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserSettingsDTO.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailConfig.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (1 hunks)
  • server/application-server/src/main/resources/application-prod.yml (2 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml (1 hunks)
  • server/application-server/src/main/resources/db/master.xml (1 hunks)
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html (1 hunks)
  • webapp/src/app/core/modules/openapi/.openapi-generator/FILES (1 hunks)
  • webapp/src/app/core/modules/openapi/api/user.service.ts (2 hunks)
  • webapp/src/app/core/modules/openapi/api/user.serviceInterface.ts (2 hunks)
  • webapp/src/app/core/modules/openapi/model/models.ts (1 hunks)
  • webapp/src/app/core/modules/openapi/model/user-settings.ts (1 hunks)
  • webapp/src/app/settings/settings.component.html (1 hunks)
  • webapp/src/app/settings/settings.component.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (16)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserSettingsDTO.java
  • webapp/src/app/core/modules/openapi/model/user-settings.ts
  • server/application-server/src/main/resources/db/master.xml
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html
  • webapp/src/app/core/modules/openapi/model/models.ts
  • server/application-server/src/main/resources/db/changelog/1740410752168_changelog.xml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/User.java
  • server/application-server/openapi.yaml
  • server/application-server/compose.yaml
  • server/application-server/src/main/resources/application-prod.yml
  • webapp/src/app/core/modules/openapi/.openapi-generator/FILES
  • server/application-server/pom.xml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
  • webapp/src/app/settings/settings.component.html
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailConfig.java
🧰 Additional context used
🪛 Biome (1.9.4)
webapp/src/app/core/modules/openapi/api/user.service.ts

[error] 232-232: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 244-244: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 249-249: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 295-295: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 307-307: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 312-312: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Run Chromatic
🔇 Additional comments (10)
server/application-server/src/main/resources/application.yml (1)

32-35: Thymeleaf Configuration Added

The new Thymeleaf block correctly specifies the prefix and suffix for email templates. The use of the placeholder ${MAIL_TEMPLATE_FOLDER} with a reasonable default (classpath:/mail-templates/) ensures flexibility.

webapp/src/app/core/modules/openapi/api/user.serviceInterface.ts (1)

17-17: LGTM! Import for UserSettings added.

This addition properly enables the use of the UserSettings model with the new service methods.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserService.java (2)

91-94: Add parameter validation and improve logging.

The method has the following issues:

  1. Missing null check for the user parameter.
  2. Using string concatenation in log message which is inefficient and could cause performance issues under high load.

Apply this diff to fix the issues:

    public UserSettingsDTO getUserSettings(User user) {
-        logger.info("Getting user settings with userId: " + user);
+        if (user == null) {
+            throw new IllegalArgumentException("User cannot be null");
+        }
+        logger.info("Getting user settings with userId: {}", user);
         return new UserSettingsDTO(user.isNotificationsEnabled());
    }

96-101: Add parameter validation and improve logging.

The method has the following issues:

  1. Missing null checks for both user and userSettings parameters.
  2. Using string concatenation in log message which is inefficient and could cause performance issues under high load.

Apply this diff to fix the issues:

    public UserSettingsDTO updateUserSettings(User user, UserSettingsDTO userSettings) {
-        logger.info("Updating user settings with userId: " + user);
+        if (user == null) {
+            throw new IllegalArgumentException("User cannot be null");
+        }
+        if (userSettings == null) {
+            throw new IllegalArgumentException("User settings cannot be null");
+        }
+        logger.info("Updating user settings with userId: {}", user);
         user.setNotificationsEnabled(userSettings.receiveNotifications());
         userRepository.save(user);
         return new UserSettingsDTO(user.isNotificationsEnabled());
    }
server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/user/UserController.java (3)

33-34: Consider using constructor injection instead of field injection.

Field injection using @Autowired is not recommended as it makes the code harder to test and the dependencies less obvious.

-    @Autowired
-    private UserRepository userRepository;

     public UserController(UserService actorService) {
         this.userService = actorService;
     }
+    public UserController(UserService actorService, UserRepository userRepository) {
+        this.userService = actorService;
+        this.userRepository = userRepository;
+    }

66-75: Add input validation and improve error handling.

The endpoints need better error handling and input validation:

  1. The GET endpoint doesn't validate if the user has permission to access settings
     @GetMapping("/settings")
     public ResponseEntity<UserSettingsDTO> getUserSettings() {
+        if (!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
+            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
+        }
         var user = userRepository.getCurrentUser();
         if (user.isEmpty()) {
             return ResponseEntity.notFound().build();
         }

         UserSettingsDTO userSettings = userService.getUserSettings(user.get());
         return ResponseEntity.ok(userSettings);
     }

77-86: Add input validation and improve error handling.

The endpoints need better error handling and input validation:

  1. The POST endpoint doesn't validate if the user has permission to access settings
  2. The POST endpoint doesn't validate the request body
     @PostMapping("/settings")
     public ResponseEntity<UserSettingsDTO> updateUserSettings(@RequestBody UserSettingsDTO userSettings) {
+        if (!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
+            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
+        }
+        if (userSettings == null) {
+            return ResponseEntity.badRequest().build();
+        }
         var user = userRepository.getCurrentUser();
         if (user.isEmpty()) {
             return ResponseEntity.notFound().build();
         }

         UserSettingsDTO updatedUserSettings = userService.updateUserSettings(user.get(), userSettings);
         return ResponseEntity.ok(updatedUserSettings);
     }
webapp/src/app/settings/settings.component.ts (2)

61-64: Add error handling to settings query.

The settings query doesn't handle potential errors that could occur when fetching user settings.

  settingsQuery = injectQuery(() => ({
    queryKey: ['settings'],
-    queryFn: async () => lastValueFrom(this.userService.getUserSettings()).then((settings) => this._newNotificationEnabled.setValue(settings.receiveNotifications ?? false))
+    queryFn: async () => {
+      try {
+        const settings = await lastValueFrom(this.userService.getUserSettings());
+        this._newNotificationEnabled.setValue(settings.receiveNotifications ?? false);
+        return settings;
+      } catch (error) {
+        console.error('Failed to load settings:', error);
+        throw error;
+      }
+    }
  }));

66-68: Add error handling and proper typing to settings mutation.

The settings mutation lacks error handling and explicit return type. Adding these would improve code reliability.

  settingsMutation = injectMutation(() => ({
-    mutationFn: (settings: UserSettings) => lastValueFrom(this.userService.updateUserSettings(settings))
+    mutationFn: async (settings: UserSettings): Promise<UserSettings> => {
+      try {
+        return await lastValueFrom(this.userService.updateUserSettings(settings));
+      } catch (error) {
+        console.error('Failed to update settings:', error);
+        throw error;
+      }
+    }
  }));
webapp/src/app/core/modules/openapi/api/user.service.ts (1)

221-351: Good implementation of user settings API endpoints.

The addition of getUserSettings and updateUserSettings methods follows the same pattern as existing methods in the service, which promotes consistency. The appropriate HTTP methods (GET and POST) are used, error handling is implemented, and the methods properly support different return type observations.

🧰 Tools
🪛 Biome (1.9.4)

[error] 232-232: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 244-244: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 249-249: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 295-295: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 307-307: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 312-312: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

iam-flo added a commit that referenced this pull request Mar 3, 2025
iam-flo added a commit that referenced this pull request Mar 3, 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: 0

🧹 Nitpick comments (1)
compose.yaml (1)

69-77: New Postfix Service Integration

The new postfix service is configured to handle email notifications. The settings (image, container name, restart policy, volume mapping with a reference link, hostname, and network) are consistent with the project's structure. Please ensure that the volume path (./postfix-config) is correctly configured for the postfix container, and consider if using the latest tag is appropriate for production environments since it might introduce unforeseen updates.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d37035 and 5dd7894.

📒 Files selected for processing (1)
  • compose.yaml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Run Chromatic
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...

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

🔭 Outside diff range comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

37-40: ⚠️ Potential issue

Fix syntax errors in class structure.

There appear to be extra closing braces at the end of the file. This will cause compilation errors.

    }
-}
-    }
-}
♻️ Duplicate comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

29-35: 🛠️ Refactor suggestion

Check users' notification preferences before sending emails.

Currently, the code sends an email to all assignees without verifying if they have notifications enabled. Consider validating user preferences to avoid undesired notifications.

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
+       if (user.isNotificationsEnabled()) {
            mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       }
    }
}
🧹 Nitpick comments (2)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorScheduler.java (1)

1-53: Fix code style issues.

There's a warning in the pipeline about code style issues. Consider running Prettier with the --write flag to fix these.

🧰 Tools
🪛 GitHub Actions: Application Server QA

[warning] 1-1: Code style issues found in the above file. Run Prettier with --write to fix.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

29-35: Add error handling for email operations.

Email operations can fail for various reasons (server unavailable, invalid email address, etc.). Consider adding try-catch blocks to handle potential exceptions.

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
-       mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       try {
+           mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       } catch (Exception e) {
+           logger.error("Failed to send email notification to user {}: {}", user.getUsername(), e.getMessage());
+           // Consider whether to continue processing other users or handle the error differently
+       }
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3942922 and 1b68704.

📒 Files selected for processing (6)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorScheduler.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorScheduler.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (0 hunks)
✅ Files skipped from review due to trivial changes (1)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorScheduler.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
🧰 Additional context used
🪛 GitHub Actions: Application Server QA
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorScheduler.java

[warning] 1-1: Code style issues found in the above file. Run Prettier with --write to fix.

⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Run Chromatic
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
🔇 Additional comments (6)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorScheduler.java (3)

6-7: Import management looks correct.

The addition of the MailService import is appropriate for the new functionality being introduced.


26-30: Clean dependency injection implementation.

The autowired dependencies for PullRequestBadPracticeDetector and MailService are properly added, following the existing pattern in the class.


46-47: Task initialization looks good.

The BadPracticeDetectorTask is now properly configured with the necessary services before execution.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (3)

3-7: Imports are appropriately added.

The new imports for PullRequestBadPractice, User, and MailService are correctly included to support the email notification functionality.


12-13: List import added correctly.

The List import is appropriately added to support storing the bad practices detection results.


22-24: MailService dependency looks good.

The MailService is properly injected using the @Autowired annotation, consistent with other dependencies in this class.

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

🔭 Outside diff range comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java (1)

1-92: 💡 Verification agent

❓ Verification inconclusive

Address pipeline failures.

The pipeline reports code style issues that can be fixed with Prettier.


🏁 Script executed:

#!/bin/bash
# Run Prettier to fix code style issues
npx prettier --write "server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java"

Length of output: 247


Action Required: Address Prettier Configuration in the Pipeline

The pipeline failure appears to be due to the command not finding Prettier (i.e. “npx: command not found”). Please ensure that Prettier is properly installed and available in the execution environment. For example:

  • Verify that Node.js and npm (or an alternative Prettier installation) are installed.
  • If Prettier is installed locally, consider invoking it via its local binary (e.g., using ./node_modules/.bin/prettier --write …).
  • Double-check the PATH configuration so that npx (or the corresponding command) is accessible during pipeline execution.

Once these issues are resolved, re-run the formatting command to address the code style issues in the following file:

  • File: server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java
🧰 Tools
🪛 GitHub Actions: Application Server QA

[warning] 1-1: Code style issues found. Run Prettier with --write to fix.

🧹 Nitpick comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java (1)

36-36: Good addition of transactional boundary.

Adding the @Transactional annotation is a good practice here as it ensures that all database operations in the detectAndSyncBadPractices method are executed atomically. If an exception occurs, all changes will be rolled back, maintaining data consistency.

Consider adding a brief comment explaining why this method needs to be transactional, which would help future developers understand the design decision.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b68704 and d4692a3.

📒 Files selected for processing (1)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: Application Server QA
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java

[warning] 1-1: Code style issues found. Run Prettier with --write to fix.

⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Run Chromatic
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
🔇 Additional comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/PullRequestBadPracticeDetector.java (1)

12-13: Appropriate import added for transaction management.

The addition of the Jakarta transaction import is necessary to support the @Transactional annotation added to the method below.

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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 3

🧹 Nitpick comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

7-7: Remove unused import if not required.

If you're not using the functionality from java.util.List outside the lines changed, consider removing this import to maintain a clean codebase.

🛑 Comments failed to post (3)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/ActivityService.java (2)

38-39: 🛠️ Refactor suggestion

Adopt constructor injection for better maintainability.

Field injection (@Autowired on fields) is discouraged in some Spring best practices. Consider constructor-based injection to facilitate testing, reduce hidden dependencies, and adhere to the single responsibility principle.

-    @Autowired
-    private MailService mailService;
+    private final MailService mailService;

+    public ActivityService(PullRequestRepository pullRequestRepository,
+                           PullRequestBadPracticeRepository pullRequestBadPracticeRepository,
+                           PullRequestBadPracticeDetector pullRequestBadPracticeDetector,
+                           UserRepository userRepository,
+                           MailService mailService) {
+        this.pullRequestRepository = pullRequestRepository;
+        this.pullRequestBadPracticeRepository = pullRequestBadPracticeRepository;
+        this.pullRequestBadPracticeDetector = pullRequestBadPracticeDetector;
+        this.userRepository = userRepository;
+        this.mailService = mailService;
+    }

Committable suggestion skipped: line range outside the PR's diff.


9-9: 🛠️ Refactor suggestion

Use constructor injection or verify usage of the injected service.

Currently, you're importing and setting up MailService as a dependency but do not appear to call it here. If future usage is planned, consider constructor injection for improved testability and clarity. Otherwise, remove the unused import and field.

- import de.tum.in.www1.hephaestus.notification.MailService;

Committable suggestion skipped: line range outside the PR's diff.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

28-30: 🛠️ Refactor suggestion

Add error handling for email sending.

If the email sending fails, the code currently proceeds silently. It is good practice to handle potential exceptions, log them, and decide if a failure should block subsequent logic.

 try {
     List<PullRequestBadPractice> badPractices =
         pullRequestBadPracticeDetector.detectAndSyncBadPractices(pullRequest);
 } catch (Exception e) {
     logger.error("Error detecting or syncing bad practices for PR {}: {}", pullRequest.getId(), e.getMessage());
 }

Committable suggestion skipped: line range outside the PR's diff.

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

🔭 Outside diff range comments (1)
webapp/src/app/settings/settings.component.ts (1)

74-76: ⚠️ Potential issue

Remove duplicate code.

Lines 74-76 appear to be a duplicate of the saveSettings() method that was already defined. This is likely a copy-paste error or unresolved merge conflict.

- }
-   this.settingsMutation.mutate({ receiveNotifications: this._newNotificationEnabled.value ?? false });
- }
♻️ Duplicate comments (2)
webapp/src/app/settings/settings.component.ts (2)

61-64: 🛠️ Refactor suggestion

Refactor the query implementation to use onSuccess.

Move the form control update logic out of the queryFn to the onSuccess callback, as suggested in previous comments.

  settingsQuery = injectQuery(() => ({
    queryKey: ['settings'],
-   queryFn: async () => lastValueFrom(this.userService.getUserSettings()).then((settings) => this._newNotificationEnabled.setValue(settings.receiveNotifications ?? false))
+   queryFn: () => lastValueFrom(this.userService.getUserSettings()),
+   onSuccess: (settings: UserSettings) => {
+     this._newNotificationEnabled.setValue(settings.receiveNotifications ?? false);
+   }
  }));

66-68: 🛠️ Refactor suggestion

Add error handling and cache invalidation to settings mutation.

The mutation should handle errors and invalidate the settings query to trigger a refresh.

  settingsMutation = injectMutation(() => ({
-   mutationFn: (settings: UserSettings) => lastValueFrom(this.userService.updateUserSettings(settings))
+   mutationFn: async (settings: UserSettings): Promise<UserSettings> => {
+     try {
+       return await lastValueFrom(this.userService.updateUserSettings(settings));
+     } catch (error) {
+       console.error('Failed to update settings:', error);
+       throw error;
+     }
+   },
+   onSuccess: () => {
+     // Invalidate and refetch settings query
+     this.settingsQuery.invalidate();
+   }
  }));
🧹 Nitpick comments (4)
webapp/src/app/settings/settings.component.ts (2)

47-47: Consider naming convention for form control.

The underscore prefix typically indicates a private property, but this appears to be used in the template. Consider removing the underscore if this is intended to be part of the public API.

- _newNotificationEnabled = new FormControl(false);
+ newNotificationEnabled = new FormControl(false);

70-72: Add user feedback when saving settings.

Users should receive feedback when their settings are saved or if an error occurs.

  saveSettings() {
-   this.settingsMutation.mutate({ receiveNotifications: this._newNotificationEnabled.value ?? false });
+   this.settingsMutation.mutate(
+     { receiveNotifications: this._newNotificationEnabled.value ?? false },
+     {
+       onSuccess: () => {
+         // Add a success notification here if you have a notification service
+         console.log('Settings saved successfully');
+       },
+       onError: (error) => {
+         // Add an error notification here if you have a notification service
+         console.error('Failed to save settings:', error);
+       }
+     }
+   );
  }
server/application-server/src/main/resources/application.yml (1)

48-48: Avoid enabling mail debug by default.

It's preferable to disable mail debug in production or drive it via an environment variable like ${MAIL_DEBUG:false} to prevent verbose logging of potential sensitive information.

 debug: true
+debug: ${MAIL_DEBUG:false}
server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1)

78-119: Enhance error handling and email validation.

While the method is functional, consider the following improvements:

  1. Handle null/invalid emails: Ensure recipient.getEmail() is valid.
  2. Use a more specific exception catch block: Catching Exception is broad and can mask unexpected issues.
  3. Consider a retry mechanism for transient failures (e.g., MessagingException).

These refinements will improve reliability and maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50b9c94 and 0155d7b.

📒 Files selected for processing (18)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (3 hunks)
  • webapp/src/app/settings/settings.component.ts (4 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (2 hunks)
  • compose.yaml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (4 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (2 hunks)
  • server/application-server/src/main/resources/application.yml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (0 hunks)
  • compose.yaml (0 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (0 hunks)
  • server/application-server/src/main/resources/application.yml (2 hunks)
  • webapp/src/app/settings/settings.component.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
  • server/application-server/src/main/resources/application.yml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
  • compose.yaml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
  • server/application-server/src/main/resources/application.yml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java
  • server/application-server/src/main/resources/application.yml
  • server/application-server/src/main/resources/application.yml
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
  • GitHub Check: Run Chromatic
🔇 Additional comments (10)
webapp/src/app/settings/settings.component.ts (3)

4-6: LGTM: Appropriate imports added for notification settings functionality.

The imports for UserSettings, injectQuery, form controls, and UI components are all necessary for the new notification settings feature.

Also applies to: 19-21


36-39: LGTM: Required UI components imported to the component.

All necessary UI components for the notification toggle feature have been correctly imported.


41-41: LGTM: Using external template is good practice.

Moving from an inline template to an external HTML file improves maintainability.

server/application-server/src/main/resources/application.yml (2)

37-40: Consider using placeholders for mail host and port.

This reintroduces a hardcoded Gmail SMTP configuration, which was previously highlighted in past reviews. As suggested before, it's a best practice to keep host and port configurable via environment variables (e.g., host: ${MAIL_HOST:smtp.gmail.com}), ensuring flexibility across different environments.


77-78: Confirm the intention of disabling email by default.

Mail is currently turned off (enabled: false). Validate whether this is desired for your deployment environment. If you intend to keep it off in development only, consider conditionally controlling it via environment variables.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailBuilder.java (5)

1-20: No issues identified.

The package declaration and imports look fine.


21-39: Good structure for maintaining configuration and recipients.

Exposing subject, template, variables, and notificationNames via getters is straightforward, enabling reuse. This setup appears flexible and maintainable.


40-53: Constructor logic is clear and well-structured.

Properties are initialized with sensible defaults. Good job ensuring variables and notificationNames are instantiated to avoid NullPointerExceptions.


55-60: Addition of notification names is well-implemented.

The fluent builder pattern (returning this) is convenient for chaining. No concerns.


61-75: Recipient management is efficient.

You avoid duplicates by checking primaryRecipients.contains(user) before adding. The logic is clean and easy to follow.

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

🧹 Nitpick comments (2)
webapp/src/app/settings/settings.component.ts (2)

47-47: Consider using a more descriptive variable name.

The underscore prefix typically indicates a private variable, but the name itself could be more descriptive. Consider renaming to something like _notificationsEnabled or _receiveNotificationsControl to better reflect its purpose.

- _newNotificationEnabled = new FormControl(false);
+ _receiveNotificationsControl = new FormControl(false);

70-72: Add loading and error states to improve user experience.

The current implementation doesn't provide any visual feedback to the user during the saving process or when errors occur.

  saveSettings() {
+   if (this.settingsMutation.isPending) {
+     return; // Prevent multiple submissions while saving
+   }
    this.settingsMutation.mutate({ receiveNotifications: this._newNotificationEnabled.value ?? false });
  }

Consider updating the template to show loading indicators and error messages:

<button (click)="saveSettings()" [disabled]="settingsMutation.isPending">
  {{ settingsMutation.isPending ? 'Saving...' : 'Save Settings' }}
</button>
<div *ngIf="settingsMutation.isError" class="error-message">
  Failed to save settings. Please try again.
</div>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0155d7b and 5efb688.

📒 Files selected for processing (3)
  • webapp/src/app/settings/settings.component.ts (4 hunks)
  • webapp/src/app/settings/settings.component.ts (1 hunks)
  • webapp/src/app/settings/settings.component.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • webapp/src/app/settings/settings.component.ts
  • webapp/src/app/settings/settings.component.ts
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
  • GitHub Check: Run Chromatic
🔇 Additional comments (2)
webapp/src/app/settings/settings.component.ts (2)

61-64: Use onSuccess instead of inline logic in queryFn.

The current implementation mixes data fetching with state updates in the queryFn. Following the feedback in previous reviews and Angular best practices, separate these concerns.

  settingsQuery = injectQuery(() => ({
    queryKey: ['settings'],
-   queryFn: async () => lastValueFrom(this.userService.getUserSettings()).then((settings) => this._newNotificationEnabled.setValue(settings.receiveNotifications ?? false))
+   queryFn: () => lastValueFrom(this.userService.getUserSettings()),
+   onSuccess: (settings: UserSettings) => {
+     this._newNotificationEnabled.setValue(settings.receiveNotifications ?? false);
+   }
  }));

66-68: Add error handling and query invalidation to settings mutation.

The mutation lacks error handling and doesn't invalidate the settings query after a successful update, which means the UI won't reflect the changes without a manual refresh.

  settingsMutation = injectMutation(() => ({
-   mutationFn: (settings: UserSettings) => lastValueFrom(this.userService.updateUserSettings(settings))
+   mutationFn: async (settings: UserSettings): Promise<UserSettings> => {
+     try {
+       return await lastValueFrom(this.userService.updateUserSettings(settings));
+     } catch (error) {
+       console.error('Failed to update settings:', error);
+       throw error;
+     }
+   },
+   onSuccess: () => {
+     // Invalidate and refetch the settings query to reflect the updated state
+     this.settingsQuery.invalidate();
+   }
  }));

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

🔭 Outside diff range comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

17-17: ⚠️ Potential issue

Fix misplaced class field declaration.

The field mailService is incorrectly declared outside the class body. This will cause compilation errors.

This line should be removed as there's another properly placed declaration at lines 22-23.

-    private MailService mailService;
♻️ Duplicate comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

29-36: 🛠️ Refactor suggestion

Check users' notification preferences before sending emails.

The code sends an email to all assignees without verifying if they have notifications enabled. This could result in unwanted notifications to users who have disabled them.

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
+       if (user.isNotificationsEnabled()) {
            mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       }
    }
}
🧹 Nitpick comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

31-35: Consider logging email notification activities.

Adding logging statements would help track notification delivery and any potential issues in production.

if (!badPractices.isEmpty()) {
+   log.info("Sending bad practice notification emails for PR #{} to {} assignees", 
+            pullRequest.getNumber(), pullRequest.getAssignees().size());
    for (User user: pullRequest.getAssignees()) {
        // Check notifications enabled logic here
        mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       log.debug("Email notification sent to user {}", user.getLogin());
    }
}

You'll need to add a logger to the class:

private static final Logger log = LoggerFactory.getLogger(BadPracticeDetectorTask.class);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5efb688 and 11963ae.

📒 Files selected for processing (9)
  • server/application-server/src/main/resources/db/master.xml (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (0 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (0 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1 hunks)
  • server/application-server/src/main/resources/db/changelog/1741704706273_changelog.xml (1 hunks)
  • server/application-server/src/main/resources/db/master.xml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • server/application-server/src/main/resources/db/master.xml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/resources/db/master.xml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webhook Ingest / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Webapp / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Webapp / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/webapp
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
🔇 Additional comments (2)
server/application-server/src/main/resources/db/changelog/1741704706273_changelog.xml (2)

3-3: Update ChangeSet Author Name

The ChangeSet author has been updated from "flo (generated)" to "iam-flo", which improves traceability and properly attributes the change.


5-7: Review Removal of Default Value on notifications_enabled Column

Removing the defaultValue="false" may result in issues when adding a non-nullable column to the existing user table. Without a default, existing rows might not have an initial value, potentially causing migration failures. Please verify that this change is intentional and that an appropriate data migration plan or handling for existing records is in place.

Comment on lines 29 to 30
).toList();

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding error handling around the email sending process.

The current implementation doesn't handle potential exceptions that might occur during email sending, which could cause the entire task to fail.

List<PullRequestBadPractice> badPractices = pullRequestBadPracticeDetector.detectAndSyncBadPractices(pullRequest);

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
+       try {
            // Check notifications enabled logic here
            mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       } catch (Exception e) {
+           log.error("Failed to send email notification to user {}: {}", user.getLogin(), e.getMessage(), e);
+           // Continue processing other users even if one email fails
+       }
    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
).toList();
List<PullRequestBadPractice> badPractices = pullRequestBadPracticeDetector.detectAndSyncBadPractices(pullRequest);
if (!badPractices.isEmpty()) {
for (User user: pullRequest.getAssignees()) {
try {
// Check notifications enabled logic here
mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
} catch (Exception e) {
log.error("Failed to send email notification to user {}: {}", user.getLogin(), e.getMessage(), e);
// Continue processing other users even if one email fails
}
}
}

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

🔭 Outside diff range comments (2)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2)

17-17: ⚠️ Potential issue

Fix misplaced field declaration outside class body.

This field declaration is incorrectly placed outside of any class body, which will cause a compilation error.

This field seems to be a duplicate of the properly annotated one on line 23. Consider removing this line.


38-38: ⚠️ Potential issue

Remove extra closing brace.

There is an extra closing brace on this line that doesn't match any opening brace, which will cause a compilation error.

🧹 Nitpick comments (1)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

29-35: Consider logging information about detected bad practices.

For debugging and monitoring purposes, it would be helpful to log information about the detected bad practices and notification attempts.

List<PullRequestBadPractice> badPractices = pullRequestBadPracticeDetector.detectAndSyncBadPractices(pullRequest);

+ log.info("Detected {} bad practices for pull request {}", badPractices.size(), pullRequest.getNumber());

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
+       log.debug("Sending notification to user {} for pull request {}", user.getLogin(), pullRequest.getNumber());
        mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11963ae and e9ba682.

📒 Files selected for processing (7)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (3 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (0 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (0 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Webapp / Create and Push Multi-Arch Manifest
  • GitHub Check: Webhook Ingest / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/webhook-ingest
  • GitHub Check: Intelligence Service / Build linux/arm64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Intelligence Service / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/intelligence-service
  • GitHub Check: Application Server / Build linux/amd64 Docker Image for ghcr.io/ls1intum/hephaestus/application-server
  • GitHub Check: Run Chromatic
  • GitHub Check: Verify API Specs and Client of the Application Server (add autocommit-openapi label to PR to auto...
  • GitHub Check: Verify API Specs and Client of the Intelligence Service (add autocommit-openapi label to PR to au...
🔇 Additional comments (2)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (2)

31-35: Check users' notification preferences before sending emails.

Currently, the code sends an email to all assignees without verifying if they have notifications enabled. Consider validating user preferences to avoid undesired notifications.

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
+       if (user.isNotificationsEnabled()) {
            mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       }
    }
}

31-35: Consider adding error handling around the email sending process.

The current implementation doesn't handle potential exceptions that might occur during email sending, which could cause the entire task to fail.

if (!badPractices.isEmpty()) {
    for (User user: pullRequest.getAssignees()) {
+       try {
            // Check notifications enabled logic here
            mailService.sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices);
+       } catch (Exception e) {
+           log.error("Failed to send email notification to user {}: {}", user.getLogin(), e.getMessage(), e);
+           // Continue processing other users even if one email fails
+       }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
application-server client enhancement New feature or request ready to merge size:XL This PR changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Notify user by email
3 participants