diff --git a/.env.example b/.env.example index 291cda69dd35..fc3d5603e7b0 100644 --- a/.env.example +++ b/.env.example @@ -32,3 +32,7 @@ REDIS_DATABASE=null REDIS_PORT=null GITHUB_TOKEN=null + +NEXMO_KEY=null +NEXMO_SECRET=null +NEXMO_SMS_FROM=Cachet diff --git a/app/Bus/Commands/System/Mail/TestMailCommand.php b/app/Bus/Commands/System/Mail/TestMailCommand.php deleted file mode 100644 index 782ea8735af8..000000000000 --- a/app/Bus/Commands/System/Mail/TestMailCommand.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final class TestMailCommand -{ - /** - * The user to send the notification to. - * - * @var \CachetHQ\Cachet\Models\User - */ - public $user; - - /** - * Create a new test mail command. - * - * @param \CachetHQ\Cachet\Models\User $user - * - * @return void - */ - public function __construct(User $user) - { - $this->user = $user; - } -} diff --git a/app/Bus/Events/Incident/IncidentWasReportedEvent.php b/app/Bus/Events/Incident/IncidentWasReportedEvent.php index a93e7b02a291..b361a4d4c5f0 100644 --- a/app/Bus/Events/Incident/IncidentWasReportedEvent.php +++ b/app/Bus/Events/Incident/IncidentWasReportedEvent.php @@ -22,15 +22,24 @@ final class IncidentWasReportedEvent implements IncidentEventInterface */ public $incident; + /** + * Whether to notify that the incident was reported. + * + * @var bool + */ + public $notify; + /** * Create a new incident has reported event instance. * * @param \CachetHQ\Cachet\Models\Incident $incident + * @param bool $notify * * @return void */ - public function __construct(Incident $incident) + public function __construct(Incident $incident, $notify = false) { $this->incident = $incident; + $this->notify = $notify; } } diff --git a/app/Bus/Events/User/UserAcceptedInviteEvent.php b/app/Bus/Events/User/UserAcceptedInviteEvent.php new file mode 100644 index 000000000000..776db37e705f --- /dev/null +++ b/app/Bus/Events/User/UserAcceptedInviteEvent.php @@ -0,0 +1,51 @@ + + */ +final class UserAcceptedInviteEvent implements UserEventInterface +{ + /** + * The user that accepted the invite. + * + * @var \CachetHQ\Cachet\Models\User + */ + public $user; + + /** + * The invite that the user accepted. + * + * @var \CachetHQ\Cachet\Models\Invite + */ + public $invite; + + /** + * Create a new user accepted invite event class. + * + * @param \CachetHQ\Cachet\Models\User $user + * @param \CachetHQ\Cachet\Models\Invite $invite + * + * @return void + */ + public function __construct(User $user, Invite $invite) + { + $this->user = $user; + $this->invite = $invite; + } +} diff --git a/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php b/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php index 0e46f78dcab1..100ad8bfe926 100644 --- a/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php +++ b/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php @@ -105,9 +105,7 @@ public function handle(ReportIncidentCommand $command) )); } - $incident->update(['notify' => (bool) $command->notify]); - - event(new IncidentWasReportedEvent($incident)); + event(new IncidentWasReportedEvent($incident, (bool) $command->notify)); return $incident; } diff --git a/app/Bus/Handlers/Commands/Subscriber/SubscribeSubscriberCommandHandler.php b/app/Bus/Handlers/Commands/Subscriber/SubscribeSubscriberCommandHandler.php index dba6948f26de..6a9839c72858 100644 --- a/app/Bus/Handlers/Commands/Subscriber/SubscribeSubscriberCommandHandler.php +++ b/app/Bus/Handlers/Commands/Subscriber/SubscribeSubscriberCommandHandler.php @@ -17,6 +17,7 @@ use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Subscriber; use CachetHQ\Cachet\Models\Subscription; +use CachetHQ\Cachet\Notifications\Subscriber\VerifySubscriptionNotification; /** * This is the subscribe subscriber command handler. @@ -49,7 +50,7 @@ public function handle(SubscribeSubscriberCommand $command) $components = Component::all(); } - $components->map(function ($component) use ($subscriber) { + $components->each(function ($component) use ($subscriber) { Subscription::create([ 'subscriber_id' => $subscriber->id, 'component_id' => $component->id, @@ -59,9 +60,11 @@ public function handle(SubscribeSubscriberCommand $command) if ($command->verified) { dispatch(new VerifySubscriberCommand($subscriber)); } else { - event(new SubscriberHasSubscribedEvent($subscriber)); + $subscriber->notify(new VerifySubscriptionNotification()); } + event(new SubscriberHasSubscribedEvent($subscriber)); + $subscriber->load('subscriptions'); return $subscriber; diff --git a/app/Bus/Handlers/Commands/System/Mail/TestMailCommandHandler.php b/app/Bus/Handlers/Commands/System/Mail/TestMailCommandHandler.php deleted file mode 100644 index 09d052c266d1..000000000000 --- a/app/Bus/Handlers/Commands/System/Mail/TestMailCommandHandler.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ -class TestMailCommandHandler -{ - /** - * The mailer instance. - * - * @var \Illuminate\Contracts\Mail\Mailer - */ - protected $mailer; - - /** - * Create a test mail command handler. - * - * @param \Illuminate\Contracts\Mail\Mailer $mailer - * - * @return void - */ - public function __construct(MailQueue $mailer) - { - $this->mailer = $mailer; - } - - /** - * Handle the test mail command. - * - * @param \CachetHQ\Cachet\Bus\Commands\System\Mail\TestMailCommand $command - * - * @return void - */ - public function handle(TestMailCommand $command) - { - $mail = [ - 'email' => $command->user->email, - 'subject' => trans('dashboard.settings.mail.email.subject'), - ]; - - $this->mailer->queue([ - 'html' => 'emails.system.test-html', - 'text' => 'emails.system.test-text', - ], $mail, function ($message) use ($mail) { - $message->to($mail['email'])->subject($mail['subject']); - }); - } -} diff --git a/app/Bus/Handlers/Commands/User/InviteUserCommandHandler.php b/app/Bus/Handlers/Commands/User/InviteUserCommandHandler.php index fc515d5e6c1c..164a4220308b 100644 --- a/app/Bus/Handlers/Commands/User/InviteUserCommandHandler.php +++ b/app/Bus/Handlers/Commands/User/InviteUserCommandHandler.php @@ -14,6 +14,7 @@ use CachetHQ\Cachet\Bus\Commands\User\InviteUserCommand; use CachetHQ\Cachet\Bus\Events\User\UserWasInvitedEvent; use CachetHQ\Cachet\Models\Invite; +use CachetHQ\Cachet\Notifications\User\InviteUserNotification; /** * This is the invite user command handler. @@ -36,6 +37,8 @@ public function handle(InviteUserCommand $command) 'email' => $email, ]); + $invite->notify(new InviteUserNotification()); + event(new UserWasInvitedEvent($invite)); } } diff --git a/app/Bus/Handlers/Events/Component/SendComponentUpdateEmailNotificationHandler.php b/app/Bus/Handlers/Events/Component/SendComponentUpdateEmailNotificationHandler.php index 7ed768a3868c..aed7ce1a62e5 100644 --- a/app/Bus/Handlers/Events/Component/SendComponentUpdateEmailNotificationHandler.php +++ b/app/Bus/Handlers/Events/Component/SendComponentUpdateEmailNotificationHandler.php @@ -14,18 +14,10 @@ use CachetHQ\Cachet\Bus\Events\Component\ComponentStatusWasUpdatedEvent; use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Subscriber; -use Illuminate\Contracts\Mail\MailQueue; -use McCool\LaravelAutoPresenter\Facades\AutoPresenter; +use CachetHQ\Cachet\Notifications\Component\ComponentStatusChangedNotification; class SendComponentUpdateEmailNotificationHandler { - /** - * The mailer instance. - * - * @var \Illuminate\Contracts\Mail\Mailer - */ - protected $mailer; - /** * The subscriber instance. * @@ -36,14 +28,12 @@ class SendComponentUpdateEmailNotificationHandler /** * Create a new send incident email notification handler. * - * @param \Illuminate\Contracts\Mail\Mailer $mailer * @param \CachetHQ\Cachet\Models\Subscriber $subscriber * * @return void */ - public function __construct(MailQueue $mailer, Subscriber $subscriber) + public function __construct(Subscriber $subscriber) { - $this->mailer = $mailer; $this->subscriber = $subscriber; } @@ -66,9 +56,9 @@ public function handle(ComponentStatusWasUpdatedEvent $event) // First notify all global subscribers. $globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get(); - foreach ($globalSubscribers as $subscriber) { - $this->notify($component, $subscriber); - } + $globalSubscribers->each(function ($subscriber) use ($component, $event) { + $subscriber->notify(new ComponentStatusChangedNotification($component, $event->new_status)); + }); $notified = $globalSubscribers->pluck('id')->all(); @@ -81,37 +71,8 @@ public function handle(ComponentStatusWasUpdatedEvent $event) return in_array($subscriber->id, $notified); }); - foreach ($componentSubscribers as $subscriber) { - $this->notify($component, $subscriber); - } - } - - /** - * Send notification to subscriber. - * - * @param \CachetHQ\Cachet\Models\Component $component - * @param \CachetHQ\Cachet\Models\Subscriber $subscriber - * - * @return \Illuminate\Database\Eloquent\Collection - */ - public function notify(Component $component, Subscriber $subscriber) - { - $component = AutoPresenter::decorate($component); - - $mail = [ - 'subject' => trans('cachet.subscriber.email.component.subject'), - 'component_name' => $component->name, - 'component_human_status' => $component->human_status, - ]; - - $mail['email'] = $subscriber->email; - $mail['manage_link'] = cachet_route('subscribe.manage', [$subscriber->verify_code]); - - $this->mailer->queue([ - 'html' => 'emails.components.update-html', - 'text' => 'emails.components.update-text', - ], $mail, function ($message) use ($mail) { - $message->to($mail['email'])->subject($mail['subject']); + $componentSubscribers->each(function ($subscriber) use ($component, $event) { + $subscriber->notify(new ComponentStatusChangedNotification($component, $event->new_status)); }); } } diff --git a/app/Bus/Handlers/Events/Incident/SendIncidentEmailNotificationHandler.php b/app/Bus/Handlers/Events/Incident/SendIncidentEmailNotificationHandler.php index cef908d96038..82bddcda71e0 100644 --- a/app/Bus/Handlers/Events/Incident/SendIncidentEmailNotificationHandler.php +++ b/app/Bus/Handlers/Events/Incident/SendIncidentEmailNotificationHandler.php @@ -13,19 +13,10 @@ use CachetHQ\Cachet\Bus\Events\Incident\IncidentWasReportedEvent; use CachetHQ\Cachet\Models\Subscriber; -use Illuminate\Contracts\Mail\MailQueue; -use Illuminate\Mail\Message; -use McCool\LaravelAutoPresenter\Facades\AutoPresenter; +use CachetHQ\Cachet\Notifications\Incident\NewIncidentNotification; class SendIncidentEmailNotificationHandler { - /** - * The mailer instance. - * - * @var \Illuminate\Contracts\Mail\Mailer - */ - protected $mailer; - /** * The subscriber instance. * @@ -36,14 +27,12 @@ class SendIncidentEmailNotificationHandler /** * Create a new send incident email notification handler. * - * @param \Illuminate\Contracts\Mail\Mailer $mailer * @param \CachetHQ\Cachet\Models\Subscriber $subscriber * * @return void */ - public function __construct(MailQueue $mailer, Subscriber $subscriber) + public function __construct(Subscriber $subscriber) { - $this->mailer = $mailer; $this->subscriber = $subscriber; } @@ -56,23 +45,25 @@ public function __construct(MailQueue $mailer, Subscriber $subscriber) */ public function handle(IncidentWasReportedEvent $event) { - if (!$event->incident->notify) { + $incident = $event->incident; + + if (!$event->notify) { return false; } // Only send emails for public incidents. - if ($event->incident->visible === 0) { + if (!$incident->visible) { return; } // First notify all global subscribers. $globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get(); - foreach ($globalSubscribers as $subscriber) { - $this->notify($event, $subscriber); - } + $globalSubscribers->each(function ($subscriber) use ($incident) { + $subscriber->notify(new NewIncidentNotification($incident)); + }); - if (!$event->incident->component) { + if (!$incident->component) { return; } @@ -81,53 +72,12 @@ public function handle(IncidentWasReportedEvent $event) // Notify the remaining component specific subscribers. $componentSubscribers = $this->subscriber ->isVerified() - ->forComponent($event->incident->component->id) + ->forComponent($incident->component->id) ->get() ->reject(function ($subscriber) use ($notified) { return in_array($subscriber->id, $notified); + })->each(function ($subscriber) use ($incident) { + $subscriber->notify(new NewIncidentNotification($incident)); }); - - foreach ($componentSubscribers as $subscriber) { - $this->notify($event, $subscriber); - } - } - - /** - * Send notification to subscriber. - * - * @param \CachetHQ\Cachet\Bus\Events\IncidentWasReportedEvent $event - * @param \CachetHQ\Cachet\Models\Subscriber $subscriber - * - * @return \Illuminate\Database\Eloquent\Collection - */ - public function notify(IncidentWasReportedEvent $event, $subscriber) - { - $incident = AutoPresenter::decorate($event->incident); - $component = AutoPresenter::decorate($event->incident->component); - - $mail = [ - 'email' => $subscriber->email, - 'subject' => trans('cachet.subscriber.email.incident.subject', [ - 'status' => $incident->human_status, - 'name' => $incident->name, - ]), - 'has_component' => ($event->incident->component) ? true : false, - 'component_name' => $component ? $component->name : null, - 'name' => $incident->name, - 'timestamp' => $incident->occurred_at_formatted, - 'status' => $incident->human_status, - 'html_content' => $incident->formatted_message, - 'text_content' => $incident->message, - 'token' => $subscriber->token, - 'manage_link' => cachet_route('subscribe.manage', [$subscriber->verify_code]), - 'unsubscribe_link' => cachet_route('subscribe.unsubscribe', [$subscriber->verify_code]), - ]; - - $this->mailer->queue([ - 'html' => 'emails.incidents.new-html', - 'text' => 'emails.incidents.new-text', - ], $mail, function (Message $message) use ($mail) { - $message->to($mail['email'])->subject($mail['subject']); - }); } } diff --git a/app/Bus/Handlers/Events/IncidentUpdate/SendIncidentUpdateEmailNotificationHandler.php b/app/Bus/Handlers/Events/IncidentUpdate/SendIncidentUpdateEmailNotificationHandler.php new file mode 100644 index 000000000000..86ed8147c97d --- /dev/null +++ b/app/Bus/Handlers/Events/IncidentUpdate/SendIncidentUpdateEmailNotificationHandler.php @@ -0,0 +1,80 @@ +subscriber = $subscriber; + } + + /** + * Handle the event. + * + * @param \CachetHQ\Cachet\Bus\Events\IncidentUpdate\IncidentUpdateWasReportedEvent $event + * + * @return void + */ + public function handle(IncidentUpdateWasReportedEvent $event) + { + $update = $event->update; + $incident = $update->incident; + + // Only send emails for public incidents. + if (!$incident->visible) { + return; + } + + // First notify all global subscribers. + $globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get(); + + $globalSubscribers->each(function ($subscriber) use ($update) { + $subscriber->notify(new IncidentUpdatedNotification($update)); + }); + + if (!$incident->component) { + return; + } + + $notified = $globalSubscribers->pluck('id')->all(); + + // Notify the remaining component specific subscribers. + $componentSubscribers = $this->subscriber + ->isVerified() + ->forComponent($incident->component->id) + ->get() + ->reject(function ($subscriber) use ($notified) { + return in_array($subscriber->id, $notified); + })->each(function ($subscriber) use ($incident) { + $subscriber->notify(new IncidentUpdatedNotification($incident)); + }); + } +} diff --git a/app/Bus/Handlers/Events/Schedule/SendScheduleEmailNotificationHandler.php b/app/Bus/Handlers/Events/Schedule/SendScheduleEmailNotificationHandler.php index 45d485f64bce..11e6b377034d 100644 --- a/app/Bus/Handlers/Events/Schedule/SendScheduleEmailNotificationHandler.php +++ b/app/Bus/Handlers/Events/Schedule/SendScheduleEmailNotificationHandler.php @@ -13,9 +13,7 @@ use CachetHQ\Cachet\Bus\Events\Schedule\ScheduleEventInterface; use CachetHQ\Cachet\Models\Subscriber; -use Illuminate\Contracts\Mail\MailQueue; -use Illuminate\Mail\Message; -use McCool\LaravelAutoPresenter\Facades\AutoPresenter; +use CachetHQ\Cachet\Notifications\Schedule\NewScheduleNotification; /** * This is the send schedule event notification handler. @@ -24,13 +22,6 @@ */ class SendScheduleEmailNotificationHandler { - /** - * The mailer instance. - * - * @var \Illuminate\Contracts\Mail\MailQueue - */ - protected $mailer; - /** * The subscriber instance. * @@ -39,16 +30,14 @@ class SendScheduleEmailNotificationHandler protected $subscriber; /** - * Create a new send maintenance email notification handler. + * Create a new send schedule email notification handler. * - * @param \Illuminate\Contracts\Mail\Mailer $mailer * @param \CachetHQ\Cachet\Models\Subscriber $subscriber * * @return void */ - public function __construct(MailQueue $mailer, Subscriber $subscriber) + public function __construct(Subscriber $subscriber) { - $this->mailer = $mailer; $this->subscriber = $subscriber; } @@ -61,62 +50,11 @@ public function __construct(MailQueue $mailer, Subscriber $subscriber) */ public function handle(ScheduleEventInterface $event) { - // First notify all global subscribers. - $globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get(); - - foreach ($globalSubscribers as $subscriber) { - $this->notify($event, $subscriber); - } - - $notified = $globalSubscribers->pluck('id')->all(); - - // Notify the remaining component specific subscribers. - $componentSubscribers = $this->subscriber - ->isVerified() - ->forComponent($event->incident->component->id) - ->get() - ->reject(function ($subscriber) use ($notified) { - return in_array($subscriber->id, $notified); - }); - - foreach ($componentSubscribers as $subscriber) { - $this->notify($event, $subscriber); - } - } + $schedule = $event->schedule; - /** - * Send notification to subscriber. - * - * @param \CachetHQ\Cachet\Bus\Events\Schedule\ScheduleEventInterface $event - * @param \CachetHQ\Cachet\Models\Subscriber $subscriber - * - * @return \Illuminate\Database\Eloquent\Collection - */ - public function notify(ScheduleEventInterface $event, $subscriber) - { - $incident = AutoPresenter::decorate($event->incident); - $component = AutoPresenter::decorate($event->incident->component); - - $mail = [ - 'email' => $subscriber->email, - 'subject' => trans('cachet.subscriber.email.maintenance.subject', [ - 'name' => $incident->name, - ]), - 'name' => $incident->name, - 'timestamp' => $incident->scheduled_at_formatted, - 'status' => $incident->human_status, - 'html_content' => $incident->formatted_message, - 'text_content' => $incident->message, - 'token' => $subscriber->token, - 'manage_link' => cachet_route('subscribe.manage', [$subscriber->verify_code]), - 'unsubscribe_link' => cachet_route('subscribe.unsubscribe', [$subscriber->verify_code]), - ]; - - $this->mailer->queue([ - 'html' => 'emails.incidents.maintenance-html', - 'text' => 'emails.incidents.maintenance-text', - ], $mail, function (Message $message) use ($mail) { - $message->to($mail['email'])->subject($mail['subject']); + // First notify all global subscribers. + $globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get()->each(function ($subscriber) use ($schedule) { + $subscriber->notify(new NewScheduleNotification($schedule)); }); } } diff --git a/app/Bus/Handlers/Events/Subscriber/SendSubscriberVerificationEmailHandler.php b/app/Bus/Handlers/Events/Subscriber/SendSubscriberVerificationEmailHandler.php deleted file mode 100644 index fc07b4057915..000000000000 --- a/app/Bus/Handlers/Events/Subscriber/SendSubscriberVerificationEmailHandler.php +++ /dev/null @@ -1,61 +0,0 @@ -mailer = $mailer; - } - - /** - * Handle the event. - * - * @param \CachetHQ\Cachet\Bus\Events\SubscriberHasSubscribedEvent $event - * - * @return void - */ - public function handle(SubscriberHasSubscribedEvent $event) - { - $mail = [ - 'email' => $event->subscriber->email, - 'subject' => 'Confirm your subscription.', - 'link' => cachet_route('subscribe.verify', ['code' => $event->subscriber->verify_code]), - ]; - - $this->mailer->queue([ - 'html' => 'emails.subscribers.verify-html', - 'text' => 'emails.subscribers.verify-text', - ], $mail, function (Message $message) use ($mail) { - $message->to($mail['email'])->subject($mail['subject']); - }); - } -} diff --git a/app/Bus/Handlers/Events/User/SendInviteUserEmailHandler.php b/app/Bus/Handlers/Events/User/SendInviteUserEmailHandler.php deleted file mode 100644 index 12111cdf78bf..000000000000 --- a/app/Bus/Handlers/Events/User/SendInviteUserEmailHandler.php +++ /dev/null @@ -1,61 +0,0 @@ -mailer = $mailer; - } - - /** - * Handle the event. - * - * @param \CachetHQ\Cachet\Bus\Events\UserWasInvitedEvent $event - * - * @return void - */ - public function handle(UserWasInvitedEvent $event) - { - $mail = [ - 'email' => $event->invite->email, - 'subject' => 'You have been invited.', - 'link' => cachet_route('signup.invite', [$event->invite->code]), - ]; - - $this->mailer->queue([ - 'html' => 'emails.users.invite-html', - 'text' => 'emails.users.invite-text', - ], $mail, function (Message $message) use ($mail) { - $message->to($mail['email'])->subject($mail['subject']); - }); - } -} diff --git a/app/Foundation/Providers/ComposerServiceProvider.php b/app/Foundation/Providers/ComposerServiceProvider.php index 5ca975cb821d..9f16a67d3d06 100644 --- a/app/Foundation/Providers/ComposerServiceProvider.php +++ b/app/Foundation/Providers/ComposerServiceProvider.php @@ -38,7 +38,7 @@ public function boot(Factory $factory) { $factory->composer('*', AppComposer::class); $factory->composer('*', CurrentUserComposer::class); - $factory->composer(['index', 'single-incident', 'subscribe.*', 'signup', 'dashboard.settings.theme', 'emails.*'], ThemeComposer::class); + $factory->composer(['index', 'single-incident', 'subscribe.*', 'signup', 'dashboard.settings.theme', 'notifications::email'], ThemeComposer::class); $factory->composer('dashboard.*', DashboardComposer::class); $factory->composer(['setup.*', 'dashboard.settings.localization'], TimezoneLocaleComposer::class); diff --git a/app/Foundation/Providers/EventServiceProvider.php b/app/Foundation/Providers/EventServiceProvider.php index 7ee8d180079b..935b398c318b 100644 --- a/app/Foundation/Providers/EventServiceProvider.php +++ b/app/Foundation/Providers/EventServiceProvider.php @@ -52,7 +52,7 @@ class EventServiceProvider extends ServiceProvider // ], 'CachetHQ\Cachet\Bus\Events\IncidentUpdate\IncidentUpdateWasReportedEvent' => [ - // + 'CachetHQ\Cachet\Bus\Handlers\Events\IncidentUpdate\SendIncidentUpdateEmailNotificationHandler', ], 'CachetHQ\Cachet\Bus\Events\IncidentUpdate\IncidentUpdateWasUpdatedEvent' => [ // @@ -91,7 +91,7 @@ class EventServiceProvider extends ServiceProvider // ], 'CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasCreatedEvent' => [ - // 'CachetHQ\Cachet\Bus\Handlers\Events\Schedule\SendScheduleEmailNotificationHandler', + 'CachetHQ\Cachet\Bus\Handlers\Events\Schedule\SendScheduleEmailNotificationHandler', ], 'CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasRemovedEvent' => [ // @@ -100,7 +100,7 @@ class EventServiceProvider extends ServiceProvider // ], 'CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasSubscribedEvent' => [ - 'CachetHQ\Cachet\Bus\Handlers\Events\Subscriber\SendSubscriberVerificationEmailHandler', + // ], 'CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasUnsubscribedEvent' => [ // @@ -123,6 +123,9 @@ class EventServiceProvider extends ServiceProvider 'CachetHQ\Cachet\Bus\Events\System\SystemWasUpdatedEvent' => [ // ], + 'CachetHQ\Cachet\Bus\Events\User\UserAcceptedInviteEvent' => [ + // + ], 'CachetHQ\Cachet\Bus\Events\User\UserDisabledTwoAuthEvent' => [ // ], @@ -148,7 +151,7 @@ class EventServiceProvider extends ServiceProvider // ], 'CachetHQ\Cachet\Bus\Events\User\UserWasInvitedEvent' => [ - 'CachetHQ\Cachet\Bus\Handlers\Events\User\SendInviteUserEmailHandler', + // ], 'CachetHQ\Cachet\Bus\Events\User\UserWasRemovedEvent' => [ // diff --git a/app/Http/Controllers/Dashboard/SettingsController.php b/app/Http/Controllers/Dashboard/SettingsController.php index 36b1e8fa9e3f..682fc5e9ebc7 100644 --- a/app/Http/Controllers/Dashboard/SettingsController.php +++ b/app/Http/Controllers/Dashboard/SettingsController.php @@ -12,9 +12,9 @@ namespace CachetHQ\Cachet\Http\Controllers\Dashboard; use CachetHQ\Cachet\Bus\Commands\System\Config\UpdateConfigCommand; -use CachetHQ\Cachet\Bus\Commands\System\Mail\TestMailCommand; use CachetHQ\Cachet\Integrations\Contracts\Credits; use CachetHQ\Cachet\Models\User; +use CachetHQ\Cachet\Notifications\System\SystemTestNotification; use CachetHQ\Cachet\Settings\Repository; use Exception; use GrahamCampbell\Binput\Facades\Binput; @@ -294,7 +294,7 @@ public function showMailView() */ public function testMail() { - dispatch(new TestMailCommand(Auth::user())); + Auth::user()->notify(new SystemTestNotification()); return cachet_redirect('dashboard.settings.mail') ->withSuccess(trans('dashboard.notifications.awesome')); diff --git a/app/Http/Routes/Dashboard/ApiRoutes.php b/app/Http/Routes/Dashboard/ApiRoutes.php index a07f9c4aff07..46d186dc2bb9 100644 --- a/app/Http/Routes/Dashboard/ApiRoutes.php +++ b/app/Http/Routes/Dashboard/ApiRoutes.php @@ -45,7 +45,7 @@ public function map(Registrar $router) $router->get('incidents/templates', 'ApiController@getIncidentTemplate'); $router->post('components/groups/order', 'ApiController@postUpdateComponentGroupOrder'); $router->post('components/order', 'ApiController@postUpdateComponentOrder'); - $router->post('components/{component}', 'ApiController@postUpdateComponent'); + $router->any('components/{component}', 'ApiController@postUpdateComponent'); }); } } diff --git a/app/Models/Invite.php b/app/Models/Invite.php index 6514c57f9f42..b917b3f1a044 100644 --- a/app/Models/Invite.php +++ b/app/Models/Invite.php @@ -12,9 +12,18 @@ namespace CachetHQ\Cachet\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Notifications\Notifiable; +/** + * This is the invite class. + * + * @author Joseph Cohen + * @author James Brooks + */ class Invite extends Model { + use Notifiable; + /** * The attributes that should be casted to native types. * @@ -42,21 +51,11 @@ public static function boot() self::creating(function ($invite) { if (!$invite->code) { - $invite->code = self::generateInviteCode(); + $invite->code = str_random(20); } }); } - /** - * Returns an invite code. - * - * @return string - */ - public static function generateInviteCode() - { - return str_random(20); - } - /** * Determines if the invite was claimed. * diff --git a/app/Models/Subscriber.php b/app/Models/Subscriber.php index 4ca768b2e21b..de3e3838c105 100644 --- a/app/Models/Subscriber.php +++ b/app/Models/Subscriber.php @@ -15,11 +15,19 @@ use CachetHQ\Cachet\Presenters\SubscriberPresenter; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Notifications\Notifiable; use McCool\LaravelAutoPresenter\HasPresenter; +/** + * This is the subscriber model. + * + * @author Joseph Cohen + * @author James Brooks + * @author Graham Campbell + */ class Subscriber extends Model implements HasPresenter { - use ValidatingTrait; + use Notifiable, ValidatingTrait; /** * The attributes that should be casted to native types. @@ -27,10 +35,12 @@ class Subscriber extends Model implements HasPresenter * @var string[] */ protected $casts = [ - 'email' => 'string', - 'verify_code' => 'string', - 'verified_at' => 'date', - 'global' => 'bool', + 'email' => 'string', + 'phone_number' => 'string', + 'slack_webhook_url' => 'string', + 'verify_code' => 'string', + 'verified_at' => 'date', + 'global' => 'bool', ]; /** @@ -40,6 +50,8 @@ class Subscriber extends Model implements HasPresenter */ protected $fillable = [ 'email', + 'phone_number', + 'slack_webhook_url', 'verified_at', 'global', ]; @@ -50,7 +62,9 @@ class Subscriber extends Model implements HasPresenter * @var string[] */ public $rules = [ - 'email' => 'required|email', + 'email' => 'nullable|email', + 'phone_number' => 'nullable|string', + 'slack_webhook_url' => 'nullable|url', ]; /** @@ -145,6 +159,26 @@ public static function generateVerifyCode() return str_random(42); } + /** + * Route notifications for the Nexmo channel. + * + * @return string + */ + public function routeNotificationForNexmo() + { + return $this->phone_number; + } + + /** + * Route notifications for the Slack channel. + * + * @return string + */ + public function routeNotificationForSlack() + { + return $this->slack_webhook_url; + } + /** * Get the presenter class. * diff --git a/app/Notifications/Component/ComponentStatusChangedNotification.php b/app/Notifications/Component/ComponentStatusChangedNotification.php new file mode 100644 index 000000000000..2f034e44e20f --- /dev/null +++ b/app/Notifications/Component/ComponentStatusChangedNotification.php @@ -0,0 +1,151 @@ + + */ +class ComponentStatusChangedNotification extends Notification +{ + use Queueable; + + /** + * The component that changed. + * + * @var \CachetHQ\Cachet\Models\Component + */ + protected $component; + + /** + * The component status we're now at. + * + * @var int + */ + protected $status; + + /** + * Create a new notification instance. + * + * @param \CachetHQ\Cachet\Models\Component $component + * @param int $status + * + * @return void + */ + public function __construct(Component $component, $status) + { + $this->component = AutoPresenter::decorate($component); + $this->status = $status; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail', 'nexmo', 'slack']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $content = trans('notifications.component.status_update.content', [ + 'name' => $this->component->name, + 'old_status' => $this->component->human_status, + 'new_status' => trans("cachet.components.status.{$this->status}"), + ]); + + return (new MailMessage()) + ->subject(trans('notifications.component.status_update.subject')) + ->greeting(trans('notifications.component.status_update.title')) + ->line($content) + ->action('View', cachet_route('status-page')) + ->line(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + } + + /** + * Get the Nexmo / SMS representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\NexmoMessage + */ + public function toNexmo($notifiable) + { + $content = trans('notifications.component.status_update.content', [ + 'name' => $this->component->name, + 'old_status' => $this->component->human_status, + 'new_status' => trans("cachet.components.status.{$this->status}"), + ]); + + return (new NexmoMessage())->content($content); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\SlackMessage + */ + public function toSlack($notifiable) + { + $content = trans('notifications.component.status_update.content', [ + 'name' => $this->component->name, + 'old_status' => $this->component->human_status, + 'new_status' => trans("cachet.components.status.{$this->status}"), + ]); + + $status = 'info'; + + if ($this->status <= 1) { + $status = 'success'; + } elseif ($this->status === 2) { + $status = 'warning'; + } elseif ($this->status >= 3) { + $status = 'error'; + } + + return (new SlackMessage()) + ->$status() + ->content(trans('notifications.component.status_update.title')) + ->attachment(function ($attachment) use ($content, $notifiable) { + $attachment->title($content, cachet_route('status-page')) + ->fields(array_filter([ + 'Component' => $this->component->name, + 'Old Status' => $this->component->human_status, + 'New Status' => trans("cachet.components.status.{$this->status}"), + 'Link' => $this->component->link, + ])) + ->footer(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + }); + } +} diff --git a/app/Notifications/Incident/NewIncidentNotification.php b/app/Notifications/Incident/NewIncidentNotification.php new file mode 100644 index 000000000000..3aee2b8117d3 --- /dev/null +++ b/app/Notifications/Incident/NewIncidentNotification.php @@ -0,0 +1,136 @@ + + */ +class NewIncidentNotification extends Notification +{ + use Queueable; + + /** + * The incident. + * + * @var \CachetHQ\Cachet\Models\Incident + */ + protected $incident; + + /** + * Create a new notification instance. + * + * @param \CachetHQ\Cachet\Models\Incident $incident + * + * @return void + */ + public function __construct(Incident $incident) + { + $this->incident = AutoPresenter::decorate($incident); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail', 'nexmo', 'slack']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $content = trans('notifications.incident.new.content', [ + 'name' => $this->incident->name, + ]); + + return (new MailMessage()) + ->subject(trans('notifications.incident.new.subject')) + ->greeting(trans('notifications.incident.new.title', ['app_name' => Config::get('setting.app_name')])) + ->line($content) + ->action('View Incident', cachet_route('incident', [$this->incident])) + ->line(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + } + + /** + * Get the Nexmo / SMS representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\NexmoMessage + */ + public function toNexmo($notifiable) + { + $content = trans('notifications.incident.new.content', [ + 'name' => $this->incident->name, + ]); + + return (new NexmoMessage())->content($content); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\SlackMessage + */ + public function toSlack($notifiable) + { + $content = trans('notifications.incident.new.content', [ + 'name' => $this->incident->name, + ]); + + $status = 'info'; + + if ($this->incident->status === Incident::FIXED) { + $status = 'success'; + } elseif ($this->incident->status === Incident::WATCHED) { + $status = 'warning'; + } else { + $status = 'error'; + } + + return (new SlackMessage()) + ->$status() + ->content(trans('notifications.incident.new.title', ['app_name' => Config::get('setting.app_name')])) + ->attachment(function ($attachment) use ($content) { + $attachment->title($content) + ->timestamp($this->incident->getWrappedObject()->occurred_at) + ->fields(array_filter([ + 'ID' => "#{$this->incident->id}", + 'Link' => $this->incident->permalink, + ])) + ->footer(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + }); + } +} diff --git a/app/Notifications/IncidentUpdate/IncidentUpdatedNotification.php b/app/Notifications/IncidentUpdate/IncidentUpdatedNotification.php new file mode 100644 index 000000000000..7986c54c4e99 --- /dev/null +++ b/app/Notifications/IncidentUpdate/IncidentUpdatedNotification.php @@ -0,0 +1,143 @@ + + */ +class IncidentUpdatedNotification extends Notification +{ + use Queueable; + + /** + * The incident update. + * + * @var \CachetHQ\Cachet\Models\Incident + */ + protected $update; + + /** + * Create a new notification instance. + * + * @param \CachetHQ\Cachet\Models\IncidentUpdate $update + * + * @return void + */ + public function __construct(IncidentUpdate $update) + { + $this->update = AutoPresenter::decorate($update); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail', 'nexmo', 'slack']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $content = trans('notifications.incident.update.content', [ + 'name' => $this->update->name, + 'time' => $this->update->created_at_diff, + ]); + + return (new MailMessage()) + ->subject(trans('notifications.incident.update.subject')) + ->greeting(trans('notifications.incident.update.title', [ + 'name' => $this->update->incident->name, + 'new_status' => $this->update->human_status, + ])) + ->line($content) + ->action('View Incident', cachet_route('incident', [$this->update->incident])) + ->line(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + } + + /** + * Get the Nexmo / SMS representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\NexmoMessage + */ + public function toNexmo($notifiable) + { + $content = trans('notifications.incident.update.content', [ + 'name' => $this->update->incident->name, + ]); + + return (new NexmoMessage())->content($content); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\SlackMessage + */ + public function toSlack($notifiable) + { + $content = trans('notifications.incident.update.content', [ + 'name' => $this->update->incident->name, + ]); + + $status = 'info'; + + if ($this->update->status === Incident::FIXED) { + $status = 'success'; + } elseif ($this->update->status === Incident::WATCHED) { + $status = 'warning'; + } else { + $status = 'error'; + } + + return (new SlackMessage()) + ->$status() + ->content(trans('notifications.incident.update.title', [ + 'name' => $this->update->incident->name, + 'new_status' => $this->update->human_status, + ])) + ->attachment(function ($attachment) use ($content) { + $attachment->title($content) + ->timestamp($this->update->getWrappedObject()->created_at) + ->fields(array_filter([ + 'ID' => "#{$this->update->id}", + 'Link' => $this->update->permalink, + ])) + ->footer(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + }); + } +} diff --git a/app/Notifications/Schedule/NewScheduleNotification.php b/app/Notifications/Schedule/NewScheduleNotification.php new file mode 100644 index 000000000000..f2fb3075a01e --- /dev/null +++ b/app/Notifications/Schedule/NewScheduleNotification.php @@ -0,0 +1,127 @@ + + */ +class NewScheduleNotification extends Notification +{ + use Queueable; + + /** + * The schedule. + * + * @var \CachetHQ\Cachet\Models\Schedule + */ + protected $schedule; + + /** + * Create a new notification instance. + * + * @param \CachetHQ\Cachet\Models\Schedule $schedule + * + * @return void + */ + public function __construct(Schedule $schedule) + { + $this->schedule = AutoPresenter::decorate($schedule); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail', 'nexmo', 'slack']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $content = trans('notifications.schedule.new.content', [ + 'name' => $this->schedule->name, + 'date' => $this->schedule->scheduled_at_formatted, + ]); + + return (new MailMessage()) + ->subject(trans('notifications.schedule.new.subject')) + ->greeting(trans('notifications.schedule.new.title')) + ->line($content) + ->action('View Schedule', cachet_route('schedule', [$this->schedule])) + ->line(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + } + + /** + * Get the Nexmo / SMS representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\NexmoMessage + */ + public function toNexmo($notifiable) + { + $content = trans('notifications.schedule.new.content', [ + 'name' => $this->schedule->name, + 'date' => $this->schedule->scheduled_at_formatted, + ]); + + return (new NexmoMessage())->content($content); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\SlackMessage + */ + public function toSlack($notifiable) + { + $content = trans('notifications.schedule.new.content', [ + 'name' => $this->schedule->name, + 'date' => $this->schedule->scheduled_at_formatted, + ]); + + return (new SlackMessage()) + ->content(trans('notifications.schedule.new.title')) + ->attachment(function ($attachment) use ($content) { + $attachment->title($content) + ->timestamp($this->schedule->getWrappedObject()->scheduled_at) + ->fields(array_filter([ + 'ID' => "#{$this->schedule->id}", + 'Status' => $this->schedule->human_status, + ])) + ->footer(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)])); + }); + } +} diff --git a/app/Notifications/Subscriber/VerifySubscriptionNotification.php b/app/Notifications/Subscriber/VerifySubscriptionNotification.php new file mode 100644 index 000000000000..8d781115cbf2 --- /dev/null +++ b/app/Notifications/Subscriber/VerifySubscriptionNotification.php @@ -0,0 +1,55 @@ + + */ +class VerifySubscriptionNotification extends Notification +{ + use Queueable; + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->subject(trans('notifications.subscriber.verify.subject')) + ->greeting(trans('notifications.subscriber.verify.title', ['app_name' => Config::get('setting.app_name')])) + ->action(trans('notifications.subscriber.verify.action'), cachet_route('subscribe.verify', ['code' => $notifiable->verify_code])) + ->line(trans('notifications.subscriber.verify.content', ['app_name' => Config::get('setting.app_name')])); + } +} diff --git a/app/Notifications/System/SystemTestNotification.php b/app/Notifications/System/SystemTestNotification.php new file mode 100644 index 000000000000..6958ec194e43 --- /dev/null +++ b/app/Notifications/System/SystemTestNotification.php @@ -0,0 +1,53 @@ + + */ +class SystemTestNotification extends Notification +{ + use Queueable; + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->subject(trans('notifications.system.test.subject')) + ->greeting(trans('notifications.system.test.title')) + ->line(trans('notifications.system.test.content')); + } +} diff --git a/app/Notifications/User/InviteUserNotification.php b/app/Notifications/User/InviteUserNotification.php new file mode 100644 index 000000000000..4b6267f69b00 --- /dev/null +++ b/app/Notifications/User/InviteUserNotification.php @@ -0,0 +1,55 @@ + + */ +class InviteUserNotification extends Notification +{ + use Queueable; + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return string[] + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->subject(trans('notifications.user.invite.subject')) + ->greeting(trans('notifications.user.invite.title', ['app_name' => Config::get('setting.app_name')])) + ->action(trans('notifications.user.invite.action'), cachet_route('signup.invite', [$notifiable->code])) + ->line(trans('notifications.user.invite.content', ['app_name' => Config::get('setting.app_name')])); + } +} diff --git a/composer.json b/composer.json index c4a85bd145c7..4064eaa9da70 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,6 @@ "backup-manager/laravel": "^1.1", "barryvdh/laravel-cors": "^0.8", "doctrine/dbal": "^2.5", - "fedeisas/laravel-mail-css-inliner": "^1.5", "fideloper/proxy": "^3.1", "graham-campbell/binput": "^3.5", "graham-campbell/core": "^5.1", @@ -45,10 +44,11 @@ "guzzlehttp/guzzle": "^6.2.1", "laravel/framework": "5.3.*", "mccool/laravel-auto-presenter": "^4.3", + "nexmo/client": "@beta", "pragmarx/google2fa": "^0.7.1", "predis/predis": "^1.1", - "twig/twig": "^1.26.1", - "roumen/feed": "^2.10.4" + "roumen/feed": "^2.10.4", + "twig/twig": "^1.26.1" }, "require-dev": { "alt-three/testbench": "^1.9", diff --git a/composer.lock b/composer.lock index 683abc20b98f..51cfa069b768 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8a12e392376c66089b5435df09154936", - "content-hash": "4da236537bf5c691b4297b065c6669eb", + "hash": "63bbf3c3c93ca5e9a9b21a16156fdf4e", + "content-hash": "6f8ada6770ff17a57e4b6079e800443c", "packages": [ { "name": "alt-three/badger", @@ -2089,6 +2089,64 @@ ], "time": "2016-12-15 18:03:17" }, + { + "name": "lcobucci/jwt", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "ddce703826f9c5229781933b1a39069e38e6a0f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/ddce703826f9c5229781933b1a39069e38e6a0f3", + "reference": "ddce703826f9c5229781933b1a39069e38e6a0f3", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=5.5" + }, + "require-dev": { + "mdanter/ecc": "~0.3.1", + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "~4.5", + "squizlabs/php_codesniffer": "~2.3" + }, + "suggest": { + "mdanter/ecc": "Required to use Elliptic Curves based algorithms." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2016-10-31 20:09:32" + }, { "name": "league/commonmark", "version": "0.13.4", @@ -2527,6 +2585,52 @@ ], "time": "2015-11-04 20:07:17" }, + { + "name": "nexmo/client", + "version": "1.0.0-beta3", + "source": { + "type": "git", + "url": "https://github.com/Nexmo/nexmo-php.git", + "reference": "83aa47336da9fa927ce62cb9fa3cbdaff1aeaaa0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nexmo/nexmo-php/zipball/83aa47336da9fa927ce62cb9fa3cbdaff1aeaaa0", + "reference": "83aa47336da9fa927ce62cb9fa3cbdaff1aeaaa0", + "shasum": "" + }, + "require": { + "lcobucci/jwt": "^3.2", + "php": ">=5.4", + "php-http/client-implementation": "^1.0", + "php-http/guzzle6-adapter": "^1.0", + "zendframework/zend-diactoros": "^1.3" + }, + "require-dev": { + "php-http/mock-client": "^0.3.0", + "phpunit/phpunit": "^5.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nexmo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tim Lytle", + "email": "tim@nexmo.com", + "homepage": "http://twitter.com/tjlytle", + "role": "Developer" + } + ], + "description": "PHP Client for using Nexmo's API.", + "time": "2016-09-14 03:43:04" + }, { "name": "nikic/php-parser", "version": "v3.0.2", @@ -2626,6 +2730,172 @@ ], "time": "2016-11-07 23:38:38" }, + { + "name": "php-http/guzzle6-adapter", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/guzzle6-adapter.git", + "reference": "a56941f9dc6110409cfcddc91546ee97039277ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/a56941f9dc6110409cfcddc91546ee97039277ab", + "reference": "a56941f9dc6110409cfcddc91546ee97039277ab", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "php-http/httplug": "^1.0" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0" + }, + "require-dev": { + "ext-curl": "*", + "php-http/adapter-integration-tests": "^0.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Adapter\\Guzzle6\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + } + ], + "description": "Guzzle 6 HTTP Adapter", + "homepage": "http://httplug.io", + "keywords": [ + "Guzzle", + "http" + ], + "time": "2016-05-10 06:13:32" + }, + { + "name": "php-http/httplug", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "php-http/promise": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "time": "2016-08-31 08:30:17" + }, + { + "name": "php-http/promise", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/dc494cdc9d7160b9a09bd5573272195242ce7980", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980", + "shasum": "" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "time": "2016-01-26 13:27:02" + }, { "name": "pragmarx/google2fa", "version": "v0.7.1", @@ -4128,6 +4398,56 @@ "environment" ], "time": "2016-09-01 10:05:43" + }, + { + "name": "zendframework/zend-diactoros", + "version": "1.3.7", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-diactoros.git", + "reference": "969ff423d3f201da3ff718a5831bb999bb0669b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/969ff423d3f201da3ff718a5831bb999bb0669b0", + "reference": "969ff423d3f201da3ff718a5831bb999bb0669b0", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "~1.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6 || ^5.5", + "squizlabs/php_codesniffer": "^2.3.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev", + "dev-develop": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://github.com/zendframework/zend-diactoros", + "keywords": [ + "http", + "psr", + "psr-7" + ], + "time": "2016-10-11 13:25:21" } ], "packages-dev": [ @@ -5881,7 +6201,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "nexmo/client": 10 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/config/app.php b/config/app.php index b40ff7ef24ec..ef08a1e52add 100644 --- a/config/app.php +++ b/config/app.php @@ -177,7 +177,6 @@ AltThree\Emoji\EmojiServiceProvider::class, BackupManager\Laravel\Laravel5ServiceProvider::class, Barryvdh\Cors\ServiceProvider::class, - Fedeisas\LaravelMailCssInliner\LaravelMailCssInlinerServiceProvider::class, Fideloper\Proxy\TrustedProxyServiceProvider::class, GrahamCampbell\Binput\BinputServiceProvider::class, GrahamCampbell\Exceptions\ExceptionsServiceProvider::class, diff --git a/config/css-inliner.php b/config/css-inliner.php deleted file mode 100644 index f1e9c78bf342..000000000000 --- a/config/css-inliner.php +++ /dev/null @@ -1,41 +0,0 @@ - true, - - /* - |-------------------------------------------------------------------------- - | Remove classes - |-------------------------------------------------------------------------- - | - | Settings this to false disables the removal of class attributes from - | your html elements (do not enable this if you use media queries) - | - */ - - 'strip-classes' => true, - -]; diff --git a/config/services.php b/config/services.php index c4d0f901299e..7cf70c7b12ce 100644 --- a/config/services.php +++ b/config/services.php @@ -36,6 +36,12 @@ 'secret' => env('MAIL_PASSWORD'), ], + 'nexmo' => [ + 'key' => env('NEXMO_KEY'), + 'secret' => env('NEXMO_SECRET'), + 'sms_from' => env('NEXMO_SMS_FROM'), + ], + 'ses' => [ 'key' => env('MAIL_USERNAME'), 'secret' => env('MAIL_PASSWORD'), diff --git a/database/migrations/2016_12_29_124643_AlterTableSubscribersAddPhoneNumberSlackColumns.php b/database/migrations/2016_12_29_124643_AlterTableSubscribersAddPhoneNumberSlackColumns.php new file mode 100644 index 000000000000..a47b79404f57 --- /dev/null +++ b/database/migrations/2016_12_29_124643_AlterTableSubscribersAddPhoneNumberSlackColumns.php @@ -0,0 +1,43 @@ +string('email')->nullable()->default(null)->change(); + $table->string('phone_number')->nullable()->default(null)->after('verify_code'); + $table->string('slack_webhook_url')->nullable()->default(null)->after('phone_number'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('subscribers', function (Blueprint $table) { + $table->dropColumn(['phone_number', 'slack_webhook_url']); + }); + } +} diff --git a/database/migrations/2016_12_29_155956_AlterTableComponentsMakeLinkNullable.php b/database/migrations/2016_12_29_155956_AlterTableComponentsMakeLinkNullable.php new file mode 100644 index 000000000000..47cd317e8091 --- /dev/null +++ b/database/migrations/2016_12_29_155956_AlterTableComponentsMakeLinkNullable.php @@ -0,0 +1,39 @@ +text('link')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/database/migrations/2017_01_03_143916_create_notifications_table.php b/database/migrations/2017_01_03_143916_create_notifications_table.php new file mode 100644 index 000000000000..d38e48c28dbd --- /dev/null +++ b/database/migrations/2017_01_03_143916_create_notifications_table.php @@ -0,0 +1,44 @@ +uuid('id')->primary(); + $table->string('type'); + $table->morphs('notifiable'); + $table->text('data'); + $table->timestamp('read_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('notifications'); + } +} diff --git a/resources/lang/en/cachet.php b/resources/lang/en/cachet.php index 9739f86da1dc..5f2749932ca7 100644 --- a/resources/lang/en/cachet.php +++ b/resources/lang/en/cachet.php @@ -76,9 +76,10 @@ // Subscriber 'subscriber' => [ - 'subscribe' => 'Subscribe to get the updates', - 'button' => 'Subscribe', - 'manage' => [ + 'subscribe' => 'Subscribe to get the updates', + 'unsubscribe' => 'Unsubscribe at :link', + 'button' => 'Subscribe', + 'manage' => [ 'no_subscriptions' => 'You\'re currently subscribed to all updates.', 'my_subscriptions' => 'You\'re currently subscribed to the following updates.', ], @@ -91,32 +92,6 @@ 'unsubscribed' => 'Your email subscription has been cancelled.', 'failure' => 'Something went wrong with the subscription.', 'already-subscribed' => 'Cannot subscribe :email because they\'re already subscribed.', - 'verify' => [ - 'text' => "Please confirm your email subscription to :app_name status updates.\n:link", - 'html' => '

Please confirm your email subscription to :app_name status updates.

', - 'button' => 'Confirm Subscription', - ], - 'maintenance' => [ - 'subject' => '[Maintenance Scheduled] :name', - ], - 'incident' => [ - 'subject' => '[New Incident] :status: :name', - ], - 'component' => [ - 'subject' => 'Component Status Update', - 'text' => 'The component :component_name has seen a status change. The component is now at :component_human_status.\nThank you, :app_name', - 'html' => '

The component :component_name has seen a status change. The component is now at :component_human_status.

Thank you, :app_name

', - 'tooltip-title' => 'Subscribe to notifications for :component_name.', - ], - ], - ], - - 'users' => [ - 'email' => [ - 'invite' => [ - 'text' => "You have been invited to the team :app_name status page, to sign up follow the next link.\n:link\nThank you, :app_name", - 'html' => '

You have been invited to the team :app_name status page, to sign up follow the next link.

:link

Thank you, :app_name

', - ], ], ], diff --git a/resources/lang/en/notifications.php b/resources/lang/en/notifications.php new file mode 100644 index 000000000000..4db80e7c00ec --- /dev/null +++ b/resources/lang/en/notifications.php @@ -0,0 +1,65 @@ + [ + 'status_update' => [ + 'subject' => 'Component Status Updated', + 'title' => 'A component\'s status was updated!', + 'content' => ':name status changed from :old_status to :new_status.', + ], + ], + 'incident' => [ + 'new' => [ + 'subject' => 'New Incident Reported', + 'content' => ':name was reported', + 'title' => 'A new incident was reported at :app_name status page.', + 'action' => 'View', + ], + 'update' => [ + 'subject' => 'Incident Updated', + 'content' => ':name was updated', + 'title' => ':name was updated to :new_status', + 'action' => 'View', + ], + ], + 'schedule' => [ + 'new' => [ + 'subject' => 'New Schedule Created', + 'content' => ':name was scheduled for :date', + 'title' => 'A new scheduled maintenance was created.', + 'action' => 'View', + ], + ], + 'subscriber' => [ + 'verify' => [ + 'subject' => 'Verify Your Subscription', + 'content' => 'Click to verify your subscription to :app_name status page.', + 'title' => 'Verify your subscription to :app_name status page.', + 'action' => 'Verify', + ], + ], + 'system' => [ + 'test' => [ + 'subject' => 'Ping from Cachet!', + 'content' => 'This is a test notification from Cachet!', + 'title' => '🔔', + ], + ], + 'user' => [ + 'invite' => [ + 'subject' => 'Your invitation is inside...', + 'content' => 'You have been invited to join :app_name status page.', + 'title' => 'You\'re invited to join :app_name status page.', + 'action' => 'Accept', + ], + ], +]; diff --git a/resources/views/dashboard/incidents/add.blade.php b/resources/views/dashboard/incidents/add.blade.php index 7dc91b199a35..7a3a48d40e36 100644 --- a/resources/views/dashboard/incidents/add.blade.php +++ b/resources/views/dashboard/incidents/add.blade.php @@ -115,14 +115,12 @@ - @if($enable_subscribers)
- @endif
diff --git a/resources/views/emails/components/update-html.blade.php b/resources/views/emails/components/update-html.blade.php deleted file mode 100644 index d99acb78231c..000000000000 --- a/resources/views/emails/components/update-html.blade.php +++ /dev/null @@ -1,20 +0,0 @@ -@extends('layout.emails') - -@section('content') -{!! trans('cachet.subscriber.email.component.html', ['component_name' => $component_name, 'component_human_status' => $component_human_status, 'app_name' => $app_name]) !!} - - - - - -
- -
-@stop diff --git a/resources/views/emails/components/update-text.blade.php b/resources/views/emails/components/update-text.blade.php deleted file mode 100644 index 935a8e7e542b..000000000000 --- a/resources/views/emails/components/update-text.blade.php +++ /dev/null @@ -1,7 +0,0 @@ -{!! trans('cachet.subscriber.email.component.text', ['component_name' => $component_name, 'component_human_status' => $component_human_status, 'app_name' => $app_name]) !!} - -{!! trans('cachet.subscriber.email.manage') !!} {{ $manage_link }} - -@if($show_support) -{!! trans('cachet.powered_by', ['app' => $app_name]) !!} -@endif diff --git a/resources/views/emails/incidents/maintenance-html.blade.php b/resources/views/emails/incidents/maintenance-html.blade.php deleted file mode 100644 index b521492502ba..000000000000 --- a/resources/views/emails/incidents/maintenance-html.blade.php +++ /dev/null @@ -1,40 +0,0 @@ -@extends('layout.emails') - -@section('content') -

{!! $name !!}

- - - - - -
-

- {!! $status !!} - {!! $html_content !!} - {!! $timestamp !!} -

-
- - - - - -
- -
- - - - - -
-

{!! trans('cachet.subscriber.email.unsubscribe') !!}

-
-@stop diff --git a/resources/views/emails/incidents/maintenance-text.blade.php b/resources/views/emails/incidents/maintenance-text.blade.php deleted file mode 100644 index 6c2d54bbfc27..000000000000 --- a/resources/views/emails/incidents/maintenance-text.blade.php +++ /dev/null @@ -1,13 +0,0 @@ -{!! $name !!} - -{!! $status !!} -{!! $text_content !!} -{!! $timestamp !!} - -{!! trans('cachet.subscriber.email.manage') !!} {{ $manage_link }} - -{!! trans('cachet.subscriber.email.unsubscribe') !!} {{ $unsubscribe_link }} - -@if($show_support) -{!! trans('cachet.powered_by', ['app' => $app_name]) !!} -@endif diff --git a/resources/views/emails/incidents/new-html.blade.php b/resources/views/emails/incidents/new-html.blade.php deleted file mode 100644 index c30598c001b9..000000000000 --- a/resources/views/emails/incidents/new-html.blade.php +++ /dev/null @@ -1,40 +0,0 @@ -@extends('layout.emails') - -@section('content') -

{!! $name !!}

- - - - - -
-

- {!! $status !!} @if($has_component) ({{ $component_name }}) @endif - {!! $html_content !!} - {!! $timestamp !!} -

-
- - - - - -
- -
- - - - - -
-

{!! trans('cachet.subscriber.email.unsubscribe') !!}

-
-@stop diff --git a/resources/views/emails/incidents/new-text.blade.php b/resources/views/emails/incidents/new-text.blade.php deleted file mode 100644 index 80616d1ef601..000000000000 --- a/resources/views/emails/incidents/new-text.blade.php +++ /dev/null @@ -1,17 +0,0 @@ -{!! $name !!} - -{!! $status !!} -{!! $text_content !!} -{!! $timestamp !!} - -@if($has_component) -({{ $component_name }}) -@endif - -{!! trans('cachet.subscriber.email.manage') !!} {{ $manage_link }} - -{!! trans('cachet.subscriber.email.unsuscribe') !!} {{ $unsubscribe_link }} - -@if($show_support) -{!! trans('cachet.powered_by', ['app' => $app_name]) !!} -@endif diff --git a/resources/views/emails/subscribers/verify-html.blade.php b/resources/views/emails/subscribers/verify-html.blade.php deleted file mode 100644 index edc100091f85..000000000000 --- a/resources/views/emails/subscribers/verify-html.blade.php +++ /dev/null @@ -1,20 +0,0 @@ -@extends('layout.emails') - -@section('content') -{!! trans('cachet.subscriber.email.verify.html', ['app_name' => $app_name]) !!} - - - - - -
- -
-@stop diff --git a/resources/views/emails/subscribers/verify-text.blade.php b/resources/views/emails/subscribers/verify-text.blade.php deleted file mode 100644 index b45eb8a6179c..000000000000 --- a/resources/views/emails/subscribers/verify-text.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -{{ trans('cachet.subscriber.email.verify.text', ['app_name' => $app_name, 'link' => $link]) }} - -@if($show_support) -{!! trans('cachet.powered_by', ['app' => $app_name]) !!} -@endif diff --git a/resources/views/emails/system/test-html.blade.php b/resources/views/emails/system/test-html.blade.php deleted file mode 100644 index e04b99914d30..000000000000 --- a/resources/views/emails/system/test-html.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -@extends('layout.emails') - -@section('content') -{{ trans('dashboard.settings.mail.email.body') }} -@stop diff --git a/resources/views/emails/system/test-text.blade.php b/resources/views/emails/system/test-text.blade.php deleted file mode 100644 index 0fc6a49e2886..000000000000 --- a/resources/views/emails/system/test-text.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -{{ trans('dashboard.settings.mail.email.body') }} - -@if($show_support) -{!! trans('cachet.powered_by', ['app' => $app_name]) !!} -@endif diff --git a/resources/views/emails/users/invite-html.blade.php b/resources/views/emails/users/invite-html.blade.php deleted file mode 100644 index 8a01d8fb511d..000000000000 --- a/resources/views/emails/users/invite-html.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -@extends('layout.emails') - -@section('content') -{!! trans('cachet.users.email.invite.html', ['app_name' => $app_name, 'link' => $link]) !!} -@stop diff --git a/resources/views/emails/users/invite-text.blade.php b/resources/views/emails/users/invite-text.blade.php deleted file mode 100644 index 2195b31a163a..000000000000 --- a/resources/views/emails/users/invite-text.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -{{ trans('cachet.users.email.invite.text', ['app_name' => $app_name, 'link' => $link]) }} - -@if($show_support) -{!! trans('cachet.powered_by', ['app' => $app_name]) !!} -@endif diff --git a/resources/views/layout/emails.blade.php b/resources/views/layout/emails.blade.php deleted file mode 100644 index bc1363888ee2..000000000000 --- a/resources/views/layout/emails.blade.php +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - {{ $app_name }} - - - - - - - - - - diff --git a/resources/views/partials/email-css.blade.php b/resources/views/partials/email-css.blade.php deleted file mode 100644 index 5fc5ea97e492..000000000000 --- a/resources/views/partials/email-css.blade.php +++ /dev/null @@ -1,143 +0,0 @@ - diff --git a/tests/Api/SubscriberTest.php b/tests/Api/SubscriberTest.php index 85eae916ff45..22fd9155d451 100644 --- a/tests/Api/SubscriberTest.php +++ b/tests/Api/SubscriberTest.php @@ -11,6 +11,8 @@ namespace CachetHQ\Tests\Cachet\Api; +use Illuminate\Support\Facades\Notification; + /** * This is the subscriber test class. * @@ -41,6 +43,8 @@ public function testCreateSubscriber() { $this->beUser(); + Notification::fake(); + $this->expectsEvents('CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasSubscribedEvent'); $this->post('/api/v1/subscribers', [ @@ -55,6 +59,10 @@ public function testCreateSubscriberAutoVerified() { $this->beUser(); + Notification::fake(); + + $this->expectsEvents('CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasSubscribedEvent'); + $this->post('/api/v1/subscribers', [ 'email' => 'support@alt-three.com', 'verify' => true, diff --git a/tests/Bus/Commands/System/Mail/TestMailCommandTest.php b/tests/Bus/Commands/System/Mail/TestMailCommandTest.php deleted file mode 100644 index 1e92f46e6c17..000000000000 --- a/tests/Bus/Commands/System/Mail/TestMailCommandTest.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ -class TestMailCommandTest extends AbstractTestCase -{ - use CommandTrait; - - protected function getObjectAndParams() - { - $params = ['user' => new User()]; - $object = new TestMailCommand($params['user']); - - return compact('params', 'object'); - } - - protected function objectHasRules() - { - return false; - } - - protected function getHandlerClass() - { - return TestMailCommandHandler::class; - } -} diff --git a/tests/Bus/Events/Component/ComponentStatusWasUpdatedEventTest.php b/tests/Bus/Events/Component/ComponentStatusWasUpdatedEventTest.php index 4747ca3b073a..c8ae1e3a59cd 100644 --- a/tests/Bus/Events/Component/ComponentStatusWasUpdatedEventTest.php +++ b/tests/Bus/Events/Component/ComponentStatusWasUpdatedEventTest.php @@ -40,7 +40,7 @@ public function testComponentUpdateEmailWasSent() $this->app['events']->fire(new ComponentStatusWasUpdatedEvent($component, 1, 2)); $this->seeMessageFor($subscriber->email); - $this->seeMessageWithSubject(trans('cachet.subscriber.email.component.subject')); + $this->seeMessageWithSubject(trans('notifications.component.status_update.subject')); $message = $this->getMailer()->lastMessage(); diff --git a/tests/Bus/Events/Incident/IncidentWasReportedEventTest.php b/tests/Bus/Events/Incident/IncidentWasReportedEventTest.php index c6f880f6e680..b556351285f8 100644 --- a/tests/Bus/Events/Incident/IncidentWasReportedEventTest.php +++ b/tests/Bus/Events/Incident/IncidentWasReportedEventTest.php @@ -28,8 +28,11 @@ protected function objectHasHandlers() protected function getObjectAndParams() { - $params = ['incident' => new Incident()]; - $object = new IncidentWasReportedEvent($params['incident']); + $params = [ + 'incident' => new Incident(), + 'notify' => true, + ]; + $object = new IncidentWasReportedEvent($params['incident'], $params['notify']); return compact('params', 'object'); } diff --git a/tests/Bus/Events/IncidentUpdate/IncidentUpdateWasReportedEventTest.php b/tests/Bus/Events/IncidentUpdate/IncidentUpdateWasReportedEventTest.php index f7d014781823..971cc2b6cd79 100644 --- a/tests/Bus/Events/IncidentUpdate/IncidentUpdateWasReportedEventTest.php +++ b/tests/Bus/Events/IncidentUpdate/IncidentUpdateWasReportedEventTest.php @@ -18,7 +18,7 @@ class IncidentUpdateWasReportedEventTest extends AbstractIncidentUpdateEventTest { protected function objectHasHandlers() { - return false; + return true; } protected function getObjectAndParams() diff --git a/tests/Bus/Events/Schedule/ScheduleWasCreatedEventTest.php b/tests/Bus/Events/Schedule/ScheduleWasCreatedEventTest.php index 8ac349db5314..635daf67cf68 100644 --- a/tests/Bus/Events/Schedule/ScheduleWasCreatedEventTest.php +++ b/tests/Bus/Events/Schedule/ScheduleWasCreatedEventTest.php @@ -18,7 +18,7 @@ class ScheduleWasCreatedEventTest extends AbstractScheduleEventTestCase { protected function objectHasHandlers() { - return false; + return true; } protected function getObjectAndParams() diff --git a/tests/Bus/Events/Subscriber/SubscriberHasSubscribedEventTest.php b/tests/Bus/Events/Subscriber/SubscriberHasSubscribedEventTest.php index 0bf1e6617799..52a88b924ab9 100644 --- a/tests/Bus/Events/Subscriber/SubscriberHasSubscribedEventTest.php +++ b/tests/Bus/Events/Subscriber/SubscriberHasSubscribedEventTest.php @@ -18,7 +18,7 @@ class SubscriberHasSubscribedEventTest extends AbstractSubscriberEventTestCase { protected function objectHasHandlers() { - return true; + return false; } protected function getObjectAndParams() diff --git a/tests/Bus/Events/User/UserAcceptedInviteEventTest.php b/tests/Bus/Events/User/UserAcceptedInviteEventTest.php new file mode 100644 index 000000000000..e948fc76ce35 --- /dev/null +++ b/tests/Bus/Events/User/UserAcceptedInviteEventTest.php @@ -0,0 +1,40 @@ + + */ +class UserAcceptedInviteEventTest extends AbstractUserEventTestCase +{ + protected function objectHasHandlers() + { + return false; + } + + protected function getObjectAndParams() + { + $params = [ + 'user' => new User(), + 'invite' => new Invite(), + ]; + $object = new UserAcceptedInviteEvent($params['user'], $params['invite']); + + return compact('params', 'object'); + } +} diff --git a/tests/Bus/Events/User/UserWasInvitedEventTest.php b/tests/Bus/Events/User/UserWasInvitedEventTest.php index acdfbd71e053..af63507e407b 100644 --- a/tests/Bus/Events/User/UserWasInvitedEventTest.php +++ b/tests/Bus/Events/User/UserWasInvitedEventTest.php @@ -23,7 +23,7 @@ class UserWasInvitedEventTest extends AbstractUserEventTestCase { protected function objectHasHandlers() { - return true; + return false; } protected function getObjectAndParams()