Merge remote-tracking branch 'forked/2.4' into upgrade-google2fa

# Conflicts:
#	composer.lock
This commit is contained in:
Max Kovalenko
2019-07-13 10:39:25 +03:00
55 changed files with 788 additions and 991 deletions

View File

@@ -60,6 +60,13 @@ final class CreateScheduleCommand
*/
public $components;
/**
* Whether to notify that the incident was reported.
*
* @var bool
*/
public $notify;
/**
* The validation rules.
*
@@ -72,6 +79,7 @@ final class CreateScheduleCommand
'scheduled_at' => 'required|string',
'completed_at' => 'nullable|string',
'components' => 'nullable|array',
'notify' => 'nullable|bool',
];
/**
@@ -83,10 +91,11 @@ final class CreateScheduleCommand
* @param string $scheduled_at
* @param string $completed_at
* @param array $components
* @param bool $notify
*
* @return void
*/
public function __construct($name, $message, $status, $scheduled_at, $completed_at, array $components = [])
public function __construct($name, $message, $status, $scheduled_at, $completed_at, $components, $notify)
{
$this->name = $name;
$this->message = $message;
@@ -94,5 +103,6 @@ final class CreateScheduleCommand
$this->scheduled_at = $scheduled_at;
$this->completed_at = $completed_at;
$this->components = $components;
$this->notify = $notify;
}
}

View File

@@ -36,18 +36,27 @@ final class ScheduleWasCreatedEvent implements ActionInterface, ScheduleEventInt
*/
public $schedule;
/**
* Whether to notify that the incident was reported.
*
* @var bool
*/
public $notify;
/**
* Create a new schedule was created event instance.
*
* @param \CachetHQ\Cachet\Models\User $user
* @param \CachetHQ\Cachet\Models\Schedule $schedule
* @param bool notify
*
* @return void
*/
public function __construct(User $user, Schedule $schedule)
public function __construct(User $user, Schedule $schedule, $notify = false)
{
$this->user = $user;
$this->schedule = $schedule;
$this->notify = $notify;
}
/**

View File

@@ -66,8 +66,7 @@ class CreateScheduleCommandHandler
{
try {
$schedule = Schedule::create($this->filter($command));
event(new ScheduleWasCreatedEvent($this->auth->user(), $schedule));
event(new ScheduleWasCreatedEvent($this->auth->user(), $schedule, (bool) $command->notify));
} catch (InvalidArgumentException $e) {
throw new ValidationException(new MessageBag([$e->getMessage()]));
}
@@ -96,6 +95,7 @@ class CreateScheduleCommandHandler
'status' => $command->status,
'scheduled_at' => $scheduledAt,
'completed_at' => $completedAt,
'notify' => $command->notify,
];
$availableParams = array_filter($params, function ($val) {

View File

@@ -51,6 +51,9 @@ class SendScheduleEmailNotificationHandler
public function handle(ScheduleEventInterface $event)
{
$schedule = $event->schedule;
if (!$event->notify) {
return false;
}
// First notify all global subscribers.
$globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get()->each(function ($subscriber) use ($schedule) {

View File

@@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Foundation\Providers;
use CachetHQ\Cachet\Http\Middleware\Acceptable;
use CachetHQ\Cachet\Http\Middleware\Authenticate;
use CachetHQ\Cachet\Http\Middleware\RemoteUserAuthenticate;
use CachetHQ\Cachet\Http\Middleware\Timezone;
use CachetHQ\Cachet\Http\Middleware\VerifyCsrfToken;
use CachetHQ\Cachet\Http\Routes\ApiSystemRoutes;
@@ -151,6 +152,7 @@ class RouteServiceProvider extends ServiceProvider
if ($applyAlwaysAuthenticate && !$this->isWhiteListedAuthRoute($routes)) {
$middleware[] = Authenticate::class;
$middleware[] = RemoteUserAuthenticate::class;
}
$router->group(['middleware' => $middleware], function (Router $router) use ($routes) {

View File

@@ -73,7 +73,8 @@ class ScheduleController extends AbstractApiController
Binput::get('status'),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
Binput::get('components', []),
Binput::get('notify', false)
));
} catch (QueryException $e) {
throw new BadRequestHttpException();

View File

@@ -45,8 +45,7 @@ class MetricController extends Controller
public function showAddMetric()
{
return View::make('dashboard.metrics.add')
->withPageTitle(trans('dashboard.metrics.add.title').' - '.trans('dashboard.dashboard'))
->withAcceptableThresholds(Metric::ACCEPTABLE_THRESHOLDS);
->withPageTitle(trans('dashboard.metrics.add.title').' - '.trans('dashboard.dashboard'));
}
/**
@@ -132,8 +131,7 @@ class MetricController extends Controller
{
return View::make('dashboard.metrics.edit')
->withPageTitle(trans('dashboard.metrics.edit.title').' - '.trans('dashboard.dashboard'))
->withMetric($metric)
->withAcceptableThresholds(Metric::ACCEPTABLE_THRESHOLDS);
->withMetric($metric);
}
/**

View File

@@ -15,6 +15,7 @@ use AltThree\Validator\ValidationException;
use CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\DeleteScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand;
use CachetHQ\Cachet\Integrations\Contracts\System;
use CachetHQ\Cachet\Models\IncidentTemplate;
use CachetHQ\Cachet\Models\Schedule;
use GrahamCampbell\Binput\Facades\Binput;
@@ -35,13 +36,21 @@ class ScheduleController extends Controller
*/
protected $subMenu = [];
/**
* The system instance.
*
* @var \CachetHQ\Cachet\Integrations\Contracts\System
*/
protected $system;
/**
* Creates a new schedule controller instance.
*
* @return void
*/
public function __construct()
public function __construct(System $system)
{
$this->system = $system;
View::share('subTitle', trans('dashboard.schedule.title'));
}
@@ -70,7 +79,8 @@ class ScheduleController extends Controller
return View::make('dashboard.maintenance.add')
->withPageTitle(trans('dashboard.schedule.add.title').' - '.trans('dashboard.dashboard'))
->withIncidentTemplates($incidentTemplates);
->withIncidentTemplates($incidentTemplates)
->withNotificationsEnabled($this->system->canNotifySubscribers());
}
/**
@@ -87,7 +97,8 @@ class ScheduleController extends Controller
Binput::get('status', Schedule::UPCOMING),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
Binput::get('components', []),
Binput::get('notify', false)
));
} catch (ValidationException $e) {
return cachet_redirect('dashboard.schedule.create')

View File

@@ -31,7 +31,7 @@ class SubscriberController extends Controller
{
return View::make('dashboard.subscribers.index')
->withPageTitle(trans('dashboard.subscribers.subscribers').' - '.trans('dashboard.dashboard'))
->withSubscribers(Subscriber::all());
->withSubscribers(Subscriber::with('subscriptions.component')->get());
}
/**

View File

@@ -15,9 +15,11 @@ use Barryvdh\Cors\HandleCors;
use CachetHQ\Cachet\Http\Middleware\Admin;
use CachetHQ\Cachet\Http\Middleware\ApiAuthentication;
use CachetHQ\Cachet\Http\Middleware\Authenticate;
use CachetHQ\Cachet\Http\Middleware\CacheControl;
use CachetHQ\Cachet\Http\Middleware\Localize;
use CachetHQ\Cachet\Http\Middleware\ReadyForUse;
use CachetHQ\Cachet\Http\Middleware\RedirectIfAuthenticated;
use CachetHQ\Cachet\Http\Middleware\RemoteUserAuthenticate;
use CachetHQ\Cachet\Http\Middleware\SetupAlreadyCompleted;
use CachetHQ\Cachet\Http\Middleware\SubscribersConfigured;
use CachetHQ\Cachet\Http\Middleware\Throttler;
@@ -44,16 +46,18 @@ class Kernel extends HttpKernel
* @var array
*/
protected $routeMiddleware = [
'admin' => Admin::class,
'can' => Authorize::class,
'cors' => HandleCors::class,
'auth' => Authenticate::class,
'auth.api' => ApiAuthentication::class,
'guest' => RedirectIfAuthenticated::class,
'localize' => Localize::class,
'ready' => ReadyForUse::class,
'setup' => SetupAlreadyCompleted::class,
'subscribers' => SubscribersConfigured::class,
'throttle' => Throttler::class,
'admin' => Admin::class,
'auth.api' => ApiAuthentication::class,
'auth.remoteuser' => RemoteUserAuthenticate::class,
'auth' => Authenticate::class,
'cache' => CacheControl::class,
'can' => Authorize::class,
'cors' => HandleCors::class,
'guest' => RedirectIfAuthenticated::class,
'localize' => Localize::class,
'ready' => ReadyForUse::class,
'setup' => SetupAlreadyCompleted::class,
'subscribers' => SubscribersConfigured::class,
'throttle' => Throttler::class,
];
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CacheControl
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$response = $next($request);
$maxAge = time() + 30;
$response->header('Cache-Control', 'public,max-age='.$maxAge);
return $response;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Http\Middleware;
use CachetHQ\Cachet\Models\User;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
class RemoteUserAuthenticate
{
/**
* Create a new remote user authenticate instance.
*
* @param \Illuminate\Contracts\Auth\Guard $auth
*
* @return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($remoteUser = $request->server('REMOTE_USER')) {
$user = User::where('email', '=', $remoteUser)->first();
if ($user instanceof User && $this->auth->guest()) {
$this->auth->login($user);
}
}
return $next($request);
}
}

View File

@@ -52,10 +52,6 @@ class SubscribersConfigured
*/
public function handle(Request $request, Closure $next)
{
if (!$this->config->get('setting.enable_subscribers')) {
return cachet_redirect('status-page');
}
return $next($request);
}
}

View File

@@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
/**
* This is the trust proxies middleware class.
@@ -42,6 +43,8 @@ class TrustProxies extends Middleware
*/
public function __construct()
{
$this->proxies = empty(env('TRUSTED_PROXIES')) ? '*' : explode(',', trim(env('TRUSTED_PROXIES')));
$proxies = Config::get('trustedproxies.proxies');
$this->proxies = empty($proxies) ? '*' : explode(',', trim($proxies));
}
}

View File

@@ -43,7 +43,7 @@ class ApiSystemRoutes
$router->group(['middleware' => ['auth.api']], function (Registrar $router) {
$router->get('ping', 'GeneralController@ping');
$router->get('version', 'GeneralController@version');
$router->get('status', 'GeneralController@status');
$router->get('status', ['uses' => 'GeneralController@status', 'middleware' => ['cache']]);
});
});
}

View File

@@ -62,13 +62,6 @@ class Metric extends Model implements HasPresenter
*/
const VISIBLE_HIDDEN = 2;
/**
* Array of acceptable threshold minutes.
*
* @var int[]
*/
const ACCEPTABLE_THRESHOLDS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60];
/**
* The model's attributes.
*
@@ -134,7 +127,6 @@ class Metric extends Model implements HasPresenter
'default_value' => 'required|numeric',
'places' => 'required|numeric|between:0,4',
'default_view' => 'required|numeric|between:0,3',
'threshold' => 'required|numeric|between:0,10',
'visible' => 'required|numeric|between:0,2',
];

View File

@@ -12,21 +12,19 @@
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Presenters\UserPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the user model.
*
* @author James Brooks <james@alt-three.com>
*/
class User extends Authenticatable implements HasPresenter
class User extends Authenticatable
{
use Notifiable, ValidatingTrait;
@@ -211,14 +209,4 @@ class User extends Authenticatable implements HasPresenter
{
return trim($this->google_2fa_secret) !== '';
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return UserPresenter::class;
}
}

View File

@@ -140,7 +140,7 @@ class ComponentStatusChangedNotification extends Notification
return (new SlackMessage())
->$status()
->content(trans('notifications.component.status_update.slack.subject'))
->content(trans('notifications.component.status_update.slack.title'))
->attachment(function ($attachment) use ($content, $notifiable) {
$attachment->title($content, cachet_route('status-page'))
->fields(array_filter([

View File

@@ -133,8 +133,7 @@ class NewIncidentNotification extends Notification
->fields(array_filter([
'ID' => "#{$this->incident->id}",
'Link' => $this->incident->permalink,
]))
->footer(trans('cachet.subscriber.unsubscribe', ['link' => cachet_route('subscribe.unsubscribe', $notifiable->verify_code)]));
]));
});
}
}

View File

@@ -124,8 +124,7 @@ class NewScheduleNotification extends Notification implements ShouldQueue
->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)]));
]));
});
}
}

View File

@@ -1,51 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Presenters;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Facades\Config;
use Laravolt\Avatar\Facade as Avatar;
use McCool\LaravelAutoPresenter\BasePresenter;
/**
* This is the user presenter class.
*
* @author James Brooks <james@alt-three.com>
*/
class UserPresenter extends BasePresenter implements Arrayable
{
/**
* Returns the users avatar.
*
* @return string
*/
public function avatar()
{
if (Config::get('setting.enable_external_dependencies')) {
return sprintf('https://www.gravatar.com/avatar/%s?size=%d', md5(strtolower($this->email)), 200);
}
return Avatar::create($this->username)->toBase64();
}
/**
* Convert the presenter instance to an array.
*
* @return string[]
*/
public function toArray()
{
return array_merge($this->wrappedObject->toArray(), [
'avatar' => $this->avatar(),
]);
}
}