mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-16 08:35:07 +00:00
f06a3c7ab3
Invitations produced no in-app notification at all, and neither did self-registration: the whole Clients module raised none. The only admin-facing signal when an account appeared was an email to whatever raw addresses an operator typed into a setting -- addresses that need not correspond to any account in this installation, and that plenty of installations never fill in. An invitation could be accepted and nobody signed in would ever be told. So: one new type, client_registered, reaching the bell and /notifications. One type for both doors on purpose. A client arriving through the public form and one arriving through an invitation are the same event to the person being told -- an account now exists that did not -- and a second type would buy nothing, because preferences here govern email only, so it could not have been switched off separately anyway. Which door it came through is one click away in the activity log and on the invitations screen. In-app only, the reasoning client_uploaded already states: email for this event is sent separately to that address list, and routing it through Notifier's mail dispatch too would risk double-emailing any staff member who is also on it. Two things worth stating about who gets it. Recipients are resolved at the call site, because Notifier authorizes nothing by design -- its security contract is explicit that a broad query must never be handed to it. And a client-scoped staff member is deliberately not told: their whole view is the clients assigned to them, and a brand-new account is assigned to nobody, so it would link them to a screen they are refused. Which is also why the notification links to the clients list filtered to the address, and not to clients.edit: that route is gated by edit_clients while these recipients are chosen by manage_clients. A notification that refuses the person it was sent to is worse than one that lands a click short. Translated in all sixteen locales, and the redemption was driven through a real browser to see the row arrive. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPk8qAs38pudYGWwmGkYPe
28 lines
931 B
PHP
28 lines
931 B
PHP
<?php
|
|
|
|
use App\Modules\Api\ApiServiceProvider;
|
|
use App\Modules\Audit\AuditServiceProvider;
|
|
use App\Modules\Clients\ClientsServiceProvider;
|
|
use App\Modules\Comments\CommentsServiceProvider;
|
|
use App\Modules\Files\FilesServiceProvider;
|
|
use App\Modules\Groups\GroupsServiceProvider;
|
|
use App\Modules\Identity\IdentityServiceProvider;
|
|
use App\Modules\Notifications\NotificationsServiceProvider;
|
|
use App\Modules\Platform\Branding\BrandingServiceProvider;
|
|
use App\Modules\Platform\PlatformServiceProvider;
|
|
use App\Providers\AppServiceProvider;
|
|
|
|
return [
|
|
ApiServiceProvider::class,
|
|
AuditServiceProvider::class,
|
|
ClientsServiceProvider::class,
|
|
CommentsServiceProvider::class,
|
|
FilesServiceProvider::class,
|
|
GroupsServiceProvider::class,
|
|
IdentityServiceProvider::class,
|
|
NotificationsServiceProvider::class,
|
|
PlatformServiceProvider::class,
|
|
BrandingServiceProvider::class,
|
|
AppServiceProvider::class,
|
|
];
|