Skip to content

feat: add notifications for account delegation#12935

Open
hamza221 wants to merge 2 commits into
mainfrom
feat/delegation/add-notifications
Open

feat: add notifications for account delegation#12935
hamza221 wants to merge 2 commits into
mainfrom
feat/delegation/add-notifications

Conversation

@hamza221
Copy link
Copy Markdown
Contributor

@hamza221 hamza221 commented May 14, 2026

Part of #12403
image
Unit tests Ai-assisted

Summary by CodeRabbit

  • New Features

    • Account delegation now sends notifications to delegated users when they receive or lose delegation access to an account, including details about the delegating user and affected account.
  • Tests

    • Added comprehensive test coverage for account delegation notifications, including notifier behavior and notification delivery for both delegation and revocation scenarios.

Review Change Stack

@hamza221 hamza221 self-assigned this May 14, 2026
@hamza221 hamza221 force-pushed the feat/delegation/add-notifications branch from cbb141d to e58a3f6 Compare May 14, 2026 09:58
@hamza221 hamza221 marked this pull request as ready for review May 14, 2026 09:58
@hamza221 hamza221 force-pushed the feat/delegation/add-notifications branch from e58a3f6 to 3cffe22 Compare May 14, 2026 10:00
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
@hamza221 hamza221 force-pushed the feat/delegation/add-notifications branch from 3cffe22 to 79e2590 Compare May 14, 2026 10:08
AI-assisted: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
@hamza221 hamza221 force-pushed the feat/delegation/add-notifications branch from 4c7c5b7 to db6ddb3 Compare May 14, 2026 10:20
@hamza221
Copy link
Copy Markdown
Contributor Author

hamza221 commented May 14, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

@hamza221 I'll trigger a review of the PR now. I also noticed the PR description image shows "delagation" in the notification subtitle — that appears to be a typo for "delegation". Worth checking if that string originates from a translation key or hardcoded text.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

📝 Walkthrough

Walkthrough

DelegationService now accepts Account objects and current user IDs, triggers notifications on delegation changes, and the controller, notification system, and tests are updated to support the refactored signatures and new notification behavior.

Changes

Account Delegation with Notifications

Layer / File(s) Summary
DelegationService API and Notification Support
lib/Service/DelegationService.php
Updated delegate() and unDelegate() to accept Account objects and current user ID instead of account IDs. Extended the constructor with IUserManager, notification IManager, and ITimeFactory dependencies. Added a private notify() helper that creates and dispatches mail notifications to delegated-to users with delegation state, delegator info, and account email.
Notifier account_delegation Handler
lib/Notification/Notifier.php
Added account_delegation case to Notifier::prepare() that sets a delegation icon and populates rich subject/message content based on the delegated flag in notification parameters, distinguishing between active delegation and revocation.
Controller Integration
lib/Controller/DelegationController.php
Updated delegate() and unDelegate() to pass the resolved Account object and $this->currentUserId to DelegationService instead of the numeric account ID.
Test Updates - Service and Controller
tests/Unit/Controller/DelegationControllerTest.php, tests/Unit/Service/DelegationServiceTest.php
Updated mock expectations in controller tests to match the new method signatures. Refactored service test setup to inject user manager, notification manager, and time factory. Added notification-focused tests asserting that delegate() and unDelegate() send expected notification payloads with delegation state, delegator display name, and account email.
Notifier Test Coverage
tests/Unit/Notification/NotifierTest.php
Added new test class verifying Notifier metadata, error handling for unknown subjects, and correct notification formatting for delegation-active and revocation scenarios with expected rich subject/message templates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • nextcloud/mail#12727: Implements the account delegation MVP with similar core delegation entry points and service layer modifications.

Suggested labels

skill:backend

Suggested reviewers

  • ChristophWurst
  • kesselb
  • GretaD

Poem

A delegation dance, now refined with care,
Account objects flow through services fair,
Notifications bloom when permissions are shared,
Tests verify all, showing none was spared!
🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main feature addition: notifications for account delegation. It is concise, clear, and directly reflects the primary change across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/delegation/add-notifications

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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 (1)
tests/Unit/Service/DelegationServiceTest.php (1)

177-189: ⚡ Quick win

Assert that no notification is sent when undelegation target does not exist.

This branch currently verifies deletion is skipped, but not that IManager::notify is skipped too.

Proposed test strengthening
 	public function testUnDelegateWhenNotFound(): void {
 		$this->mockNotification();
 
+		$this->notificationManager->expects($this->never())
+			->method('notify');
+
 		$this->delegationMapper->expects($this->once())
 			->method('find')
 			->with(1, 'delegatee')
 			->willThrowException(new DoesNotExistException('Not found'));

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d7d080e5-d6ca-4d23-92b8-6cc947971454

📥 Commits

Reviewing files that changed from the base of the PR and between 114629c and db6ddb3.

📒 Files selected for processing (6)
  • lib/Controller/DelegationController.php
  • lib/Notification/Notifier.php
  • lib/Service/DelegationService.php
  • tests/Unit/Controller/DelegationControllerTest.php
  • tests/Unit/Notification/NotifierTest.php
  • tests/Unit/Service/DelegationServiceTest.php

'name' => $parameters['account_email']
]
]);
$notification->setRichMessage($l->t('{user} revoked delagation for {account}'),
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 14, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the user-facing typo in revoked delegation message.

Line 111 uses delagation, which will surface incorrect text in notifications.

Proposed fix
-					$notification->setRichMessage($l->t('{user} revoked delagation for {account}'),
+					$notification->setRichMessage($l->t('{user} revoked delegation for {account}'),
📝 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
$notification->setRichMessage($l->t('{user} revoked delagation for {account}'),
$notification->setRichMessage($l->t('{user} revoked delegation for {account}'),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

to fix

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@hamza221 — The PR description image also confirms the typo is visible in the live notification UI ("revoked delagation for hamza@nextdev.app"). Thanks for flagging it for a fix — just correct delagationdelegation on Line 111 when you get to it.

Comment on lines +53 to +55
$result = $this->delegationMapper->insert($delegation);
$this->notify($userId, $currentUserId, $account, true);
return $result;
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 14, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Isolate notification failures from delegation state changes.

notify() is called after insert/delete and can throw, which can turn a successful delegation mutation into an error response while the DB change is already committed.

Proposed hardening
-private function notify(string $userId, string $currentUserId, Account $account, bool $delegated) {
-	$notification = $this->notificationManager->createNotification();
-	$displayName = $this->userManager->get($currentUserId)?->getDisplayName() ?? $currentUserId;
-	$time = $this->time->getDateTime('now');
-	$notification
-		->setApp('mail')
-		->setUser($userId)
-		->setObject('delegation', (string)$account->getId())
-		->setSubject('account_delegation', [
-			'id' => $account->getId(),
-			'account_email' => $account->getEmail(),
-
-		])
-		->setDateTime($time)
-		->setMessage('account_delegation_changed', [
-			'id' => $account->getId(),
-			'delegated' => $delegated,
-			'current_user_id' => $currentUserId,
-			'current_user_display_name' => $displayName,
-			'account_email' => $account->getEmail(),
-		]
-		);
-	$this->notificationManager->notify($notification);
+private function notify(string $userId, string $currentUserId, Account $account, bool $delegated): void {
+	try {
+		$notification = $this->notificationManager->createNotification();
+		$displayName = $this->userManager->get($currentUserId)?->getDisplayName() ?? $currentUserId;
+		$time = $this->time->getDateTime('now');
+		$notification
+			->setApp('mail')
+			->setUser($userId)
+			->setObject('delegation', (string)$account->getId())
+			->setSubject('account_delegation', [
+				'id' => $account->getId(),
+				'account_email' => $account->getEmail(),
+			])
+			->setDateTime($time)
+			->setMessage('account_delegation_changed', [
+				'id' => $account->getId(),
+				'delegated' => $delegated,
+				'current_user_id' => $currentUserId,
+				'current_user_display_name' => $displayName,
+				'account_email' => $account->getEmail(),
+			]);
+		$this->notificationManager->notify($notification);
+	} catch (\Throwable) {
+		// best-effort notification; do not fail successful delegation state change
+	}
 }

Also applies to: 67-68, 136-159

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also valid

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The PR description image shows two delegation notifications in a dark-themed panel — one confirming delegation and one confirming revocation of hamza@nextdev.app.

@hamza221, glad we agree! Here's the hardened notify() method ready to apply:

private function notify(string $userId, string $currentUserId, Account $account, bool $delegated): void {
    try {
        $notification = $this->notificationManager->createNotification();
        $displayName = $this->userManager->get($currentUserId)?->getDisplayName() ?? $currentUserId;
        $time = $this->time->getDateTime('now');
        $notification
            ->setApp('mail')
            ->setUser($userId)
            ->setObject('delegation', (string)$account->getId())
            ->setSubject('account_delegation', [
                'id' => $account->getId(),
                'account_email' => $account->getEmail(),
            ])
            ->setDateTime($time)
            ->setMessage('account_delegation_changed', [
                'id' => $account->getId(),
                'delegated' => $delegated,
                'current_user_id' => $currentUserId,
                'current_user_display_name' => $displayName,
                'account_email' => $account->getEmail(),
            ]);
        $this->notificationManager->notify($notification);
    } catch (\Throwable) {
        // best-effort notification; do not fail a successful delegation state change
    }
}

Key points:

  • Wrapping in try/catch (\Throwable) ensures any exception from createNotification(), get(), getDateTime(), or notify() is swallowed after the DB write has already committed.
  • The explicit : void return type is also added for consistency.
  • You may optionally log the caught exception at a debug/warning level (e.g. via a LoggerInterface) so failures are still observable without surfacing to the user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant