mirror of
https://github.com/cachethq/cachet.git
synced 2026-03-07 12:37:01 +00:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c57ed65fa | ||
|
|
e0fd2db5ea | ||
|
|
7e1d0ebc75 | ||
|
|
7f0a77ffa1 | ||
|
|
a3f696e5b3 | ||
|
|
fe0cc779b9 | ||
|
|
02a240a172 | ||
|
|
47d0d4e007 | ||
|
|
3e6a9fc77f | ||
|
|
94d92aa6dc | ||
|
|
a35ea250da | ||
|
|
a1346deda9 | ||
|
|
07db5defb7 | ||
|
|
f26d4c41c5 | ||
|
|
a88eadf79f | ||
|
|
78eb149fc6 | ||
|
|
dfa602f1f5 | ||
|
|
352090d90f | ||
|
|
bffb244506 | ||
|
|
108a1fa0dd | ||
|
|
647fb5a4d5 | ||
|
|
8dec726bc4 | ||
|
|
9f920634db | ||
|
|
2934f9be67 | ||
|
|
6756c037c9 | ||
|
|
83e979cc25 | ||
|
|
438964c1dd | ||
|
|
9a8e9a47c4 | ||
|
|
5e05b859ae | ||
|
|
4becca76f3 | ||
|
|
46578f9407 | ||
|
|
0a30a07c43 | ||
|
|
3e9b560640 | ||
|
|
ca263d8b50 | ||
|
|
6986ee95d3 | ||
|
|
fd429a6ea7 | ||
|
|
59f69f6d99 | ||
|
|
f5756ff4bf | ||
|
|
5e907ba04f | ||
|
|
d12748a49d | ||
|
|
eeaa4cbc91 | ||
|
|
2f8db16161 | ||
|
|
96d90aff65 | ||
|
|
1b60d00bba | ||
|
|
b0049611af | ||
|
|
95bbb955aa | ||
|
|
ad414a11e0 | ||
|
|
f76e9bab06 | ||
|
|
9aa5972040 | ||
|
|
11b1125cf8 | ||
|
|
2467d24702 | ||
|
|
a62860fda3 | ||
|
|
c91344f79c | ||
|
|
a4819099eb | ||
|
|
99d599e1c7 | ||
|
|
77d1a45538 | ||
|
|
b5ca990ae5 | ||
|
|
9d6ef75597 | ||
|
|
5299d9ea16 | ||
|
|
d6a55a6540 | ||
|
|
38a4fb710f | ||
|
|
6496f8c928 | ||
|
|
c20f1ac785 |
2
.bowerrc
2
.bowerrc
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"directory": "vendor/bower_components",
|
||||
"directory": "app/assets/bower_components",
|
||||
"interactive": false
|
||||
}
|
||||
|
||||
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
.git
|
||||
26
.env.example
26
.env.example
@@ -1,26 +0,0 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://localhost
|
||||
APP_KEY=SomeRandomString
|
||||
|
||||
DB_DRIVER=mysql
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=cachet
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=database
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ADDRESS=null
|
||||
MAIL_NAME=null
|
||||
|
||||
REDIS_HOST=null
|
||||
REDIS_DATABASE=null
|
||||
REDIS_PORT=null
|
||||
11
.env.example.php
Normal file
11
.env.example.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'APP_DEBUG' => getenv('APP_DEBUG') ?: false,
|
||||
'DB_DRIVER' => 'mysql',
|
||||
'DB_HOST' => 'localhost',
|
||||
'DB_DATABASE' => 'cachet',
|
||||
'DB_USERNAME' => 'homestead',
|
||||
'DB_PASSWORD' => 'secret',
|
||||
'CACHE_DRIVER' => 'apc',
|
||||
];
|
||||
14
.env.heroku.php
Normal file
14
.env.heroku.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
$dbURL = parse_url(getenv('DATABASE_URL'));
|
||||
$dbName = substr($dbURL["path"], 1);
|
||||
|
||||
return [
|
||||
'APP_DEBUG' => getenv('APP_DEBUG') ?: false,
|
||||
'DB_HOST' => $dbURL['host'],
|
||||
'DB_DATABASE' => $dbName,
|
||||
'DB_USERNAME' => $dbURL['user'],
|
||||
'DB_PASSWORD' => $dbURL['pass'],
|
||||
'DB_DRIVER' => 'pgsql',
|
||||
'CACHE_DRIVER' => 'apc',
|
||||
];
|
||||
10
.gitattributes
vendored
10
.gitattributes
vendored
@@ -1,3 +1,9 @@
|
||||
* text=auto
|
||||
*.css linguist-vendored
|
||||
*.less linguist-vendored
|
||||
|
||||
/tests export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/phpunit.xml export-ignore
|
||||
/CONTRIBUTING.md export-ignore
|
||||
/INSTALL.md export-ignore
|
||||
/README.md export-ignore
|
||||
|
||||
26
.gitignore
vendored
26
.gitignore
vendored
@@ -1,4 +1,24 @@
|
||||
.env
|
||||
node_modules
|
||||
phpunit.xml
|
||||
# Laravel
|
||||
bootstrap/compiled.php
|
||||
vendor
|
||||
|
||||
# Configuration
|
||||
.env.*.php
|
||||
.env.php
|
||||
config.codekit
|
||||
!.env.heroku.php
|
||||
!.env.example.php
|
||||
|
||||
# Assets
|
||||
app/assets/bower_components
|
||||
node_modules
|
||||
public/dist
|
||||
public/css
|
||||
public/js
|
||||
|
||||
# Packages
|
||||
npm-debug.log
|
||||
.vagrant
|
||||
|
||||
# PHPUnit
|
||||
phpunit.xml
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.5.9
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- nightly
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
|
||||
sudo: false
|
||||
|
||||
install: travis_retry composer install --no-interaction --ignore-platform-reqs --no-scripts --prefer-source
|
||||
|
||||
before_script: php artisan cachet:one-click-deploy
|
||||
|
||||
script:
|
||||
- bash -c 'if [ "$TRAVIS_PHP_VERSION" == "hhvm" ]; then vendor/bin/phpunit; fi;'
|
||||
- bash -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then vendor/bin/phpunit --coverage-clover build/logs/clover.xml; fi;'
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
|
||||
## Creating issues
|
||||
|
||||
Feature requests and bug reports should be made by using the [issue tracker](https://github.com/cachethq/Cachet/issues). Support questions should be directed to our support email; [support@alt-three.com](mailto:support@alt-three.com?subject=Cachet Support).
|
||||
Issues should be made by using the [issue tracker](https://github.com/cachethq/Cachet/issues).
|
||||
|
||||
**Always be respectful.** Organization members reserve the right to lock topics if they feel necessary.
|
||||
Things to remember:
|
||||
|
||||
- Be descriptive
|
||||
- Be respectful of others
|
||||
|
||||
## Languages
|
||||
|
||||
When needing to add labels, placeholders or general text, you **must not** write directly into the source file, rather make use of the `./resources/lang/` directory.
|
||||
|
||||
Always provide the English translation and copy your English string to all other languages - making sure that the indentation and alignment of the arrays are updated.
|
||||
When needing to add labels, placeholders or general text, you **must not** write directly into the source file, rather make use of the `./app/lang/` directory. Always provide the English translation and copy your English string to all other languages - making sure that the indentation and alignment of the arrays are updated.
|
||||
|
||||
## Coding Standards
|
||||
|
||||
@@ -19,9 +20,9 @@ Please follow existing coding standards:
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Controller;
|
||||
namespace Foo\Bar\Controller;
|
||||
|
||||
use CachetHQ\Cachet\Bar;
|
||||
use Foo\Bar\Bar;
|
||||
|
||||
class Foo extends Bar
|
||||
{
|
||||
@@ -49,13 +50,14 @@ class Foo extends Bar
|
||||
}
|
||||
```
|
||||
- Braces on a new line following: `namespace`, `use`, `function` and `class`.
|
||||
- Line lengths have a soft 80 limit and hard 120 length.
|
||||
- PHP constants should be in lowercase; `true`, `false` and `null`.
|
||||
- Defined constants should always be in uppercase.
|
||||
- Never leave trailing spaces at the end of a line.
|
||||
- Files should end with one blank line.
|
||||
- Do not use `# Bash` style comments.
|
||||
- Always add or update Docblocs to functions.
|
||||
- We use [StyleCI](https://styleci.io) to automatically check code standards in Pull Requests. If your PR fails the CI check, then apply the supplied patch and re-push.
|
||||
- If your pull request consists of more than two commits, you **must** squash them into one.
|
||||
|
||||
If you're still unsure, then take a look at existing code.
|
||||
|
||||
@@ -73,6 +75,8 @@ If you're not particularly fond of the command line, you can get one of GitHub's
|
||||
|
||||
If you're feeling adventurous, you can become a Git & GitHub master with the [Git Path on Code School](https://www.codeschool.com/paths/git).
|
||||
|
||||
## .editorconfig
|
||||
There is always the Cachet Gitter chat to ask any questions you may have:
|
||||
|
||||
[](https://gitter.im/cachethq/Cachet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
You should also make use of the [.editorconfig](/.editorconfig) file found within the root of the repository. It'll make sure that your editor is setup with the same file settings.
|
||||
|
||||
42
Dockerfile
Normal file
42
Dockerfile
Normal file
@@ -0,0 +1,42 @@
|
||||
FROM debian:jessie
|
||||
|
||||
ENV DB_DRIVER=mysql \
|
||||
ENV=production \
|
||||
DB_DATABASE=cachet \
|
||||
DB_HOST= \
|
||||
DB_USERNAME= \
|
||||
DB_PASSWORD= \
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
COPY . /var/www/html/
|
||||
WORKDIR /var/www/html/
|
||||
|
||||
# Using nodesource and debian jessie packages instead of compiling from scratch
|
||||
RUN echo "APT::Install-Recommends \"0\";" >> /etc/apt/apt.conf.d/02recommends && \
|
||||
echo "APT::Install-Suggests \"0\";" >> /etc/apt/apt.conf.d/02recommends && \
|
||||
apt-get -qq update && \
|
||||
apt-get -qq install \
|
||||
ca-certificates nginx php5-fpm=5.* php5-curl php5-readline php5-mcrypt php5-mysql php5-apcu php5-cli \
|
||||
git sqlite libsqlite3-dev curl supervisor && \
|
||||
apt-get clean && apt-get autoremove -qq && \
|
||||
rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man /tmp/* && \
|
||||
chown -R www-data /var/www/html
|
||||
|
||||
# Hardcode the Illuminate key in app/config/app.php. If you want security, feel free
|
||||
# to override the key in your own container with a 'php artisan key:generate' :)
|
||||
RUN sed -i "s/'key' => '\w.*/'key' => 'f20d3e5ae02125a94bd60203a4edfbde',/" app/config/app.php && \
|
||||
grep key app/config/app.php
|
||||
|
||||
# copy the various nginx and supervisor conf (to handle both fpm and nginx)
|
||||
RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf ;\
|
||||
echo "daemon off;" >> /etc/nginx/nginx.conf ;\
|
||||
mv /var/www/html/docker/php-fpm-pool.conf /etc/php5/fpm/pool.d/www.conf ;\
|
||||
rm -f /etc/nginx/sites-enabled/* && rm -f /etc/nginx/conf.d/* && mv /var/www/html/docker/nginx-site.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
RUN curl -sS https://getcomposer.org/installer | php && php composer.phar install --no-dev -o
|
||||
|
||||
COPY docker/supervisord.conf /etc/supervisor/supervisord.conf
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015 Alt Three Services Limited.
|
||||
Copyright (c) 2015 James Brooks and individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1
Procfile
Normal file
1
Procfile
Normal file
@@ -0,0 +1 @@
|
||||
web: vendor/bin/heroku-php-nginx -C nginx.conf public
|
||||
92
README.md
92
README.md
@@ -1,46 +1,44 @@
|
||||
# Cachet
|
||||
# Cachet [](https://heroku.com/deploy)
|
||||
|
||||
[](https://styleci.io/repos/26730195/)
|
||||
[](https://travis-ci.org/cachethq/Cachet)
|
||||
[](https://scrutinizer-ci.com/g/cachethq/Cachet)
|
||||
[](LICENSE)
|
||||
[](http://translate.cachethq.io/project/cachet)
|
||||
[](LICENSE)
|
||||
[](https://gitter.im/cachethq/Cachet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||

|
||||
|
||||
**Currently in development. Things may change or break until a solid release has been announced.**
|
||||
|
||||
## Features
|
||||
|
||||
- List your services components
|
||||
- Log incidents
|
||||
- Apply custom CSS to the status page
|
||||
- Markdown support for incident messages
|
||||
- JSON API
|
||||
- Translated into eleven languages
|
||||
- Metrics
|
||||
- Cross-database support: MySQL, PostgreSQL and SQLite
|
||||
- Subscriber notifications via Email
|
||||
- Two factor authentication, with Google Authenticator
|
||||
- List your services components.
|
||||
- Log incidents.
|
||||
- Apply a custom stylesheet to the status page.
|
||||
- Markdown support for incident messages.
|
||||
- RESTful API.
|
||||
- Translated into several languages.
|
||||
- Easy Heroku deployment.
|
||||
- Metrics.
|
||||
- Cross-database support: MySQL, PostgreSQL and SQLite.
|
||||
|
||||
## Requirements
|
||||
|
||||
- PHP 5.5.9+ or newer
|
||||
- PHP 5.4 or newer
|
||||
- mcrypt extension
|
||||
- [Composer](https://getcomposer.org)
|
||||
|
||||
### Development Requirements
|
||||
|
||||
Theses extra dependencies are required to develop Cachet:
|
||||
The following extra dependencies are required to develop Cachet.
|
||||
|
||||
- Node.js
|
||||
- Bower
|
||||
- Gulp
|
||||
+ Bower
|
||||
+ Gulp
|
||||
|
||||
## Installation, Upgrades and Documentation
|
||||
## Installation & Documentation
|
||||
|
||||
You can now find our documentation at [https://docs.cachethq.io](https://docs.cachethq.io).
|
||||
|
||||
- [Installing Cachet](https://docs.cachethq.io/docs/installing-cachet)
|
||||
- [Getting started with Docker](https://docs.cachethq.io/docs/get-started-with-docker)
|
||||
- [Getting started with Vagrant](https://docs.cachethq.io/docs/get-started-with-vagrant)
|
||||
You can now find our documentation at [https://docs.cachethq.io](https://docs.cachethq.io) or, directly at [http://cachet.readme.io](http://cachet.readme.io) if the first link fails to load. [Cachet Demo](https://demo.cachethq.io)
|
||||
|
||||
### Demo Account
|
||||
|
||||
@@ -49,7 +47,53 @@ To test out the demo, you may login to the [Dashboard](https://demo.cachethq.io/
|
||||
- **Username:** test@test.com
|
||||
- **Password:** test123
|
||||
|
||||
The demo is reset every half hour.
|
||||
The demo is reset every half past the hour.
|
||||
|
||||
## What Cachet is not
|
||||
|
||||
Here is a list of things that Cachet is not or does not do:
|
||||
|
||||
1. It does not monitor your services. It works only as a way to display the status of your services. *However, Cachet is able to receive updates from third-party services via its API.*
|
||||
2. It does not work on a plugin system. There are no monitoring services to extend.
|
||||
3. It's not a Twitter clone.
|
||||
|
||||
## Quickstart with Docker
|
||||
|
||||
Run a DB container (you can either pass in environment variables for the DB, or mount a config with `-v /my/database.php:/var/www/html/app/config/database.php`):
|
||||
|
||||
```bash
|
||||
$ export DB_USERNAME=cachet
|
||||
$ export DB_PASSWORD=cachet
|
||||
$ export DB_ROOT_PASSWORD=cachet
|
||||
$ export DB_DATABASE=cachet
|
||||
$ docker run --name mysql -e MYSQL_USER=$DB_USERNAME -e MYSQL_PASSWORD=$DB_PASSWORD -e MYSQL_ROOT_PASSWORD=$DB_ROOT_PASSWORD -e MYSQL_DATABASE=$DB_DATABASE -d mysql
|
||||
```
|
||||
|
||||
Initialize the DB if you haven't yet:
|
||||
|
||||
```bash
|
||||
$ docker run --link mysql:mysql -e DB_HOST=mysql -e DB_DATABASE=$DB_DATABASE -e DB_USERNAME=$DB_USERNAME -e DB_PASSWORD=$DB_PASSWORD cachethq/cachet:latest php artisan migrate --force
|
||||
```
|
||||
|
||||
Run Cachet:
|
||||
|
||||
```bash
|
||||
$ docker run -d --name cachet --link mysql:mysql -p 80:8000 -e DB_HOST=mysql -e DB_DATABASE=$DB_DATABASE -e DB_USERNAME=$DB_USERNAME -e DB_PASSWORD=$DB_PASSWORD cachethq/cachet:latest
|
||||
```
|
||||
|
||||
Now go to `http://<ipdockerisboundto>/setup` and have fun!
|
||||
|
||||
Note: When running in production you should ensure that you enable SSL.
|
||||
This is commonly achieved by running Nginx with your certificates on your Docker host, service or load balancers in-front of the running container, or by adding your custom SSL certificates and configuration to the supplied Nginx configuration.
|
||||
|
||||
## Addons
|
||||
|
||||
- [cachet-monitor](https://github.com/castawaylabs/cachet-monitor) - For url monitoring. Automatic incident updates
|
||||
- [sensu-cachet](https://github.com/bimlendu/sensu-cachethq) - Sensu handler for updating CachetHQ.
|
||||
|
||||
## Read more about Cachet
|
||||
|
||||
For more information on why I started developing Cachet, check out my [Cachet articles on my blog](https://james-brooks.uk/tag/cachet/?utm_source=github&utm_medium=readme&utm_campaign=github-cachet).
|
||||
|
||||
## Translations
|
||||
|
||||
|
||||
34
app.json
Normal file
34
app.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "Cachet",
|
||||
"description": "An open source status page system.",
|
||||
"keywords": [
|
||||
"cachet",
|
||||
"laravel",
|
||||
"status",
|
||||
"page"
|
||||
],
|
||||
"website": "https://cachethq.io",
|
||||
"logo": "https://raw.githubusercontent.com/cachethq/assets/79336a33c24b28c470a89742671e0e291813d004/images/icon/Cachet-Icon.png",
|
||||
"success_url": "/setup",
|
||||
"repository": "https://github.com/cachethq/Cachet",
|
||||
"addons": [
|
||||
"heroku-postgresql"
|
||||
],
|
||||
"env": {
|
||||
"ENV": {
|
||||
"value": "heroku",
|
||||
"description": "Warning: Do not modify this value on Heroku deployments."
|
||||
},
|
||||
"BUILDPACK_URL": {
|
||||
"value": "https://github.com/heroku/heroku-buildpack-php",
|
||||
"description": "Warning: Do not modify this value on Heroku deployments."
|
||||
},
|
||||
"CACHE_DRIVER": {
|
||||
"value": "apc",
|
||||
"description": "Warning: Do not modify this value on Heroku deployments."
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"postdeploy": "php artisan migrate --env=heroku; php artisan key:generate;"
|
||||
}
|
||||
}
|
||||
@@ -1,36 +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\Composers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class AppComposer
|
||||
{
|
||||
/**
|
||||
* Index page view composer.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$isEnabled = (bool) Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
|
||||
$withData = [
|
||||
'subscribersEnabled' => $isEnabled && $mailAddress && $mailFrom,
|
||||
];
|
||||
|
||||
$view->with($withData);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +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\Composers;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LoggedUserComposer
|
||||
{
|
||||
/**
|
||||
* Bind data to the view.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$view->with('loggedUser', Auth::user());
|
||||
}
|
||||
}
|
||||
@@ -1,37 +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\Composers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class ThemeComposer
|
||||
{
|
||||
/**
|
||||
* Bind data to the view.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$view->with('themeBackgroundColor', Setting::get('style_background_color'));
|
||||
$view->with('themeTextColor', Setting::get('style_text_color'));
|
||||
|
||||
$viewData = $view->getData();
|
||||
$themeView = array_only($viewData, preg_grep('/^theme/', array_keys($viewData)));
|
||||
$hasThemeSettings = array_filter($themeView, function ($data) {
|
||||
return $data != null;
|
||||
});
|
||||
|
||||
$view->with('themeSetup', !empty($hasThemeSettings));
|
||||
}
|
||||
}
|
||||
@@ -1,37 +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\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
'CachetHQ\Cachet\Console\Commands\FixPermissionsCommand',
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('queue:work --sleep=3 --tries=3')->everyMinute();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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\Events;
|
||||
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
|
||||
class CustomerHasSubscribedEvent
|
||||
{
|
||||
/**
|
||||
* The customer who has subscribed.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
public $subscriber;
|
||||
|
||||
/**
|
||||
* Create a new customer has subscribed event instance.
|
||||
*/
|
||||
public function __construct(Subscriber $subscriber)
|
||||
{
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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\Events;
|
||||
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
|
||||
class IncidentHasReportedEvent
|
||||
{
|
||||
/**
|
||||
* The incident that has been reported.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public $incident;
|
||||
|
||||
/**
|
||||
* Create a new incident has reported event instance.
|
||||
*/
|
||||
public function __construct(Incident $incident)
|
||||
{
|
||||
$this->incident = $incident;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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\Events;
|
||||
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
|
||||
class MaintenanceHasScheduledEvent
|
||||
{
|
||||
/**
|
||||
* The incident that has been reported.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public $incident;
|
||||
|
||||
/**
|
||||
* Create a new maintenance has scheduled event instance.
|
||||
*/
|
||||
public function __construct(Incident $incident)
|
||||
{
|
||||
$this->incident = $incident;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +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\Exceptions\Displayers;
|
||||
|
||||
use Exception;
|
||||
use GrahamCampbell\Exceptions\Displayers\DisplayerInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
|
||||
class RedirectDisplayer implements DisplayerInterface
|
||||
{
|
||||
/**
|
||||
* The request instance.
|
||||
*
|
||||
* @var \Illuminate\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Create a new redirect displayer instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*/
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error response associated with the given exception.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param string $id
|
||||
* @param int $code
|
||||
* @param string[] $headers
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function display(Exception $exception, $id, $code, array $headers)
|
||||
{
|
||||
return redirect()->guest('auth/login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the supported content type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function contentType()
|
||||
{
|
||||
return 'text/html';
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we display the exception?
|
||||
*
|
||||
* @param \Exception $original
|
||||
* @param \Exception $transformed
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDisplay(Exception $original, Exception $transformed)
|
||||
{
|
||||
$redirect = $transformed instanceof HttpExceptionInterface && $transformed->getStatusCode() === 401;
|
||||
|
||||
return $redirect && !$this->request->is('api*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we provide verbose information about the exception?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isVerbose()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +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\Exceptions\Filters;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ApiFilter
|
||||
{
|
||||
/**
|
||||
* The request instance.
|
||||
*
|
||||
* @var \Illuminate\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Create a new api filter instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*/
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter and return the displayers.
|
||||
*
|
||||
* @param \GrahamCampbell\Exceptions\Displayers\DisplayerInterface[] $displayers
|
||||
* @param \Exception $original
|
||||
* @param \Exception $transformed
|
||||
*
|
||||
* @return \GrahamCampbell\Exceptions\Displayers\DisplayerInterface[]
|
||||
*/
|
||||
public function filter(array $displayers, Exception $original, Exception $transformed)
|
||||
{
|
||||
if ($this->request->is('api*')) {
|
||||
foreach ($displayers as $index => $displayer) {
|
||||
if (!str_contains($displayer->contentType(), 'application/')) {
|
||||
unset($displayers[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($displayers);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +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\Exceptions;
|
||||
|
||||
use GrahamCampbell\Exceptions\ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of the exception types that should not be reported.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $dontReport = [
|
||||
NotFoundHttpException::class,
|
||||
];
|
||||
}
|
||||
@@ -1,41 +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\Exceptions\Transformers;
|
||||
|
||||
use Exception;
|
||||
use GrahamCampbell\Exceptions\Transformers\TransformerInterface;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* This is the model not found transformer class.
|
||||
*
|
||||
* @author Graham Campbell <graham@alt-three.com>
|
||||
*/
|
||||
class ModelNotFoundTransformer implements TransformerInterface
|
||||
{
|
||||
/**
|
||||
* Transform the provided exception.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
*
|
||||
* @return \Exception
|
||||
*/
|
||||
public function transform(Exception $exception)
|
||||
{
|
||||
if ($exception instanceof ModelNotFoundException) {
|
||||
$exception = new NotFoundHttpException('Resource not found');
|
||||
}
|
||||
|
||||
return $exception;
|
||||
}
|
||||
}
|
||||
@@ -1,89 +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\Handlers\Events;
|
||||
|
||||
use CachetHQ\Cachet\Events\IncidentHasReportedEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
use McCool\LaravelAutoPresenter\PresenterDecorator;
|
||||
|
||||
class SendIncidentEmailNotificationHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* The subscriber instance.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
protected $subscriber;
|
||||
|
||||
/**
|
||||
* The presenter instance.
|
||||
*
|
||||
* @var \McCool\LaravelAutoPresenter\PresenterDecorator
|
||||
*/
|
||||
protected $presenter;
|
||||
|
||||
/**
|
||||
* Create a new send incident email notification handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
* @param \McCool\LaravelAutoPresenter\PresenterDecorator $presenter
|
||||
*/
|
||||
public function __construct(MailQueue $mailer, Subscriber $subscriber, PresenterDecorator $presenter)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->presenter = $presenter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\IncidentHasReportedEvent $event
|
||||
*/
|
||||
public function handle(IncidentHasReportedEvent $event)
|
||||
{
|
||||
$data = $this->presenter->decorate($event->incident);
|
||||
|
||||
// Only send emails for public incidents.
|
||||
if ($event->incident->visible === 1) {
|
||||
foreach ($this->subscriber->all() as $subscriber) {
|
||||
$mail = [
|
||||
'email' => $subscriber->email,
|
||||
'subject' => 'New incident reported.',
|
||||
'status' => $data->humanStatus,
|
||||
'htmlContent' => $data->formattedMessage,
|
||||
'textContent' => $data->message,
|
||||
'token' => $subscriber->token,
|
||||
'unsubscribeLink' => route('unsubscribe', ['code' => $subscriber->verify_code]),
|
||||
'appUrl' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$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']);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +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\Handlers\Events;
|
||||
|
||||
use CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
use McCool\LaravelAutoPresenter\PresenterDecorator;
|
||||
|
||||
class SendMaintenanceEmailNotificationHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\MailQueue
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* The subscriber instance.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
protected $subscriber;
|
||||
|
||||
/**
|
||||
* The presenter instance.
|
||||
*
|
||||
* @var \McCool\LaravelAutoPresenter\PresenterDecorator
|
||||
*/
|
||||
protected $presenter;
|
||||
|
||||
/**
|
||||
* Create a new send maintenance email notification handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
* @param \McCool\LaravelAutoPresenter\PresenterDecorator $presenter
|
||||
*/
|
||||
public function __construct(MailQueue $mailer, Subscriber $subscriber, PresenterDecorator $presenter)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->presenter = $presenter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent $event
|
||||
*/
|
||||
public function handle(MaintenanceHasScheduledEvent $event)
|
||||
{
|
||||
$data = $this->presenter->decorate($event->incident);
|
||||
|
||||
foreach ($this->subscriber->all() as $subscriber) {
|
||||
$mail = [
|
||||
'email' => $subscriber->email,
|
||||
'subject' => 'Scheduled maintenance.',
|
||||
'status' => $data->humanStatus,
|
||||
'htmlContent' => $data->formattedMessage,
|
||||
'textContent' => $data->message,
|
||||
'token' => $subscriber->token,
|
||||
'unsubscribeLink' => route('unsubscribe', ['code' => $subscriber->verify_code]),
|
||||
'appUrl' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$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']);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +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\Handlers\Events;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
|
||||
class SendSubscriberVerificationEmailHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\MailQueue
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* Create a new send subscriber verification email handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
*/
|
||||
public function __construct(MailQueue $mailer)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\CustomerHasSubscribedEvent $event
|
||||
*/
|
||||
public function handle(CustomerHasSubscribedEvent $event)
|
||||
{
|
||||
$mail = [
|
||||
'email' => $event->subscriber->email,
|
||||
'subject' => 'Confirm your subscription.',
|
||||
'link' => route('subscribe-verify', ['code' => $event->subscriber->verify_code]),
|
||||
'appUrl' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$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']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,21 +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\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
abstract class AbstractController extends BaseController
|
||||
{
|
||||
use DispatchesJobs, ValidatesRequests;
|
||||
}
|
||||
@@ -1,104 +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\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class SubscriberController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the subscribers view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showSubscribers()
|
||||
{
|
||||
$subscribers = Subscriber::all();
|
||||
|
||||
return View::make('dashboard.subscribers.index')
|
||||
->with([
|
||||
'page_title' => trans('dashboard.subscribers.subscribers').' - '.trans('dashboard.dashboard'),
|
||||
'subscribers' => $subscribers,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the add subscriber view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showAddSubscriber()
|
||||
{
|
||||
return View::make('dashboard.subscribers.add')
|
||||
->with([
|
||||
'page_title' => trans('dashboard.subscribers.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'incidentTemplates' => Subscriber::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new subscriber.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function createSubscriberAction()
|
||||
{
|
||||
$email = Binput::get('email');
|
||||
|
||||
$subscriber = Subscriber::create([
|
||||
'email' => $email,
|
||||
]);
|
||||
|
||||
if (!$subscriber->isValid()) {
|
||||
return Redirect::back()
|
||||
->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.subscribers.add.failure')
|
||||
))
|
||||
->with('errors', $subscriber->getErrors());
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.subscribers.add.success')
|
||||
);
|
||||
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
|
||||
return Redirect::back()
|
||||
->with('success', $successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a subscriber.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function deleteSubscriberAction(Subscriber $subscriber)
|
||||
{
|
||||
$subscriber->delete();
|
||||
|
||||
return Redirect::back();
|
||||
}
|
||||
}
|
||||
@@ -1,204 +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\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController as BaseController;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use McCool\LaravelAutoPresenter\Facades\AutoPresenter;
|
||||
|
||||
abstract class AbstractApiController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The HTTP response headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* The HTTP response meta data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $meta = [];
|
||||
|
||||
/**
|
||||
* The HTTP response data.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $data = null;
|
||||
|
||||
/**
|
||||
* The HTTP response status code.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $statusCode = 200;
|
||||
|
||||
/**
|
||||
* Set the response headers.
|
||||
*
|
||||
* @param array $headers
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response meta data.
|
||||
*
|
||||
* @param array $meta
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setMetaData(array $meta)
|
||||
{
|
||||
$this->meta = $meta;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response meta data.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response status code.
|
||||
*
|
||||
* @param int $statusCode
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setStatusCode($statusCode)
|
||||
{
|
||||
$this->statusCode = $statusCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with an item response.
|
||||
*
|
||||
* @param mixed
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function item($item)
|
||||
{
|
||||
return $this->setData(AutoPresenter::decorate($item))->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with a collection response.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $collection
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function collection(Collection $collection)
|
||||
{
|
||||
return $this->setData(AutoPresenter::decorate($collection))->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with a pagination response.
|
||||
*
|
||||
* @param \Illuminate\Pagination\Paginator $paginator
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function paginator(Paginator $paginator, Request $request)
|
||||
{
|
||||
foreach ($request->query as $key => $value) {
|
||||
if ($key != 'page') {
|
||||
$paginator->addQuery($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$pagination = [
|
||||
'pagination' => [
|
||||
'total' => $paginator->total(),
|
||||
'count' => count($paginator->items()),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'total_pages' => $paginator->lastPage(),
|
||||
'links' => [
|
||||
'next_page' => $paginator->nextPageUrl(),
|
||||
'previous_page' => $paginator->previousPageUrl(),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$items = $paginator->getCollection();
|
||||
|
||||
if ($sortBy = $request->get('sort')) {
|
||||
$direction = $request->has('order') && $request->get('order') == 'desc';
|
||||
|
||||
$items = $items->sortBy($sortBy, SORT_REGULAR, $direction);
|
||||
}
|
||||
|
||||
return $this->setMetaData($pagination)->setData(AutoPresenter::decorate($items->values()->all()))->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with a no content response.
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function noContent()
|
||||
{
|
||||
return $this->setStatusCode(204)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the response.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function respond()
|
||||
{
|
||||
if (!empty($this->meta)) {
|
||||
$response['meta'] = $this->meta;
|
||||
}
|
||||
|
||||
$response['data'] = $this->data;
|
||||
|
||||
if ($this->data instanceof Arrayable) {
|
||||
$response['data'] = $this->data->toArray();
|
||||
}
|
||||
|
||||
return Response::json($response, $this->statusCode, $this->headers);
|
||||
}
|
||||
}
|
||||
@@ -1,132 +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\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\Tag;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class ComponentController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all components.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getComponents(Request $request)
|
||||
{
|
||||
$components = Component::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($components, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single component.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Component $component
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Component
|
||||
*/
|
||||
public function getComponent(Component $component)
|
||||
{
|
||||
return $this->item($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new component.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Component
|
||||
*/
|
||||
public function postComponents(Guard $auth)
|
||||
{
|
||||
$componentData = Binput::except('tags');
|
||||
|
||||
try {
|
||||
$component = Component::create($componentData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if (!$component->isValid()) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if (Binput::has('tags')) {
|
||||
// The component was added successfully, so now let's deal with the tags.
|
||||
$tags = preg_split('/ ?, ?/', Binput::get('tags'));
|
||||
|
||||
// For every tag, do we need to create it?
|
||||
$componentTags = array_map(function ($taggable) use ($component) {
|
||||
return Tag::firstOrCreate([
|
||||
'name' => $taggable,
|
||||
])->id;
|
||||
}, $tags);
|
||||
|
||||
$component->tags()->sync($componentTags);
|
||||
}
|
||||
|
||||
return $this->item($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing component.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Componet $component
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Component
|
||||
*/
|
||||
public function putComponent(Component $component)
|
||||
{
|
||||
$component->update(Binput::except('tags'));
|
||||
|
||||
if (!$component->isValid('updating')) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if (Binput::has('tags')) {
|
||||
$tags = preg_split('/ ?, ?/', Binput::get('tags'));
|
||||
|
||||
// For every tag, do we need to create it?
|
||||
$componentTags = array_map(function ($taggable) use ($component) {
|
||||
return Tag::firstOrCreate([
|
||||
'name' => $taggable,
|
||||
])->id;
|
||||
}, $tags);
|
||||
|
||||
$component->tags()->sync($componentTags);
|
||||
}
|
||||
|
||||
return $this->item($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing component.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Component $component
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteComponent(Component $component)
|
||||
{
|
||||
$component->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +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\Http\Controllers\Api;
|
||||
|
||||
class GeneralController extends AbstractApiController
|
||||
{
|
||||
public function ping()
|
||||
{
|
||||
return $this->item('Pong!');
|
||||
}
|
||||
}
|
||||
@@ -1,123 +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\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Events\IncidentHasReportedEvent;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class IncidentController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all incidents.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getIncidents(Request $request, Guard $auth)
|
||||
{
|
||||
$incidentVisiblity = $auth->check() ? 0 : 1;
|
||||
|
||||
$incidents = Incident::where('visible', '>=', $incidentVisiblity)
|
||||
->paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($incidents, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single incident.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Incident $incident
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public function getIncident(Incident $incident)
|
||||
{
|
||||
return $this->item($incident);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new incident.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public function postIncidents(Guard $auth)
|
||||
{
|
||||
$incidentData = Binput::all();
|
||||
|
||||
if (!array_has($incidentData, 'visible')) {
|
||||
$incidentData['visible'] = 1;
|
||||
}
|
||||
|
||||
try {
|
||||
$incident = Incident::create($incidentData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
$isEnabled = (bool) Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
$subscribersEnabled = $isEnabled && $mailAddress && $mailFrom;
|
||||
|
||||
if (array_get($incidentData, 'notify') && $subscribersEnabled) {
|
||||
event(new IncidentHasReportedEvent($incident));
|
||||
}
|
||||
|
||||
if ($incident->isValid()) {
|
||||
return $this->item($incident);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing incident.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Inicdent $incident
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public function putIncident(Incident $incident)
|
||||
{
|
||||
$incident->update(Binput::all());
|
||||
|
||||
if ($incident->isValid('updating')) {
|
||||
return $this->item($incident);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing incident.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Inicdent $incident
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteIncident(Incident $incident)
|
||||
{
|
||||
$incident->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
@@ -1,111 +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\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class MetricController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all metrics.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getMetrics(Request $request)
|
||||
{
|
||||
$metrics = Metric::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($metrics, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single metric.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Metric
|
||||
*/
|
||||
public function getMetric(Metric $metric)
|
||||
{
|
||||
return $this->item($metric);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all metric points.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getMetricPoints(Metric $metric)
|
||||
{
|
||||
return $this->collection($metric->points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new metric.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Metric
|
||||
*/
|
||||
public function postMetrics()
|
||||
{
|
||||
try {
|
||||
$metric = Metric::create(Binput::all());
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if ($metric->isValid()) {
|
||||
return $this->item($metric);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing metric.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Metric
|
||||
*/
|
||||
public function putMetric(Metric $metric)
|
||||
{
|
||||
$metric->update(Binput::all());
|
||||
|
||||
if ($metric->isValid('updating')) {
|
||||
return $this->item($metric);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing metric.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteMetric(Metric $metric)
|
||||
{
|
||||
$metric->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
@@ -1,98 +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\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use CachetHQ\Cachet\Models\MetricPoint;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
|
||||
class MetricPointController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get a single metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
* @param \CachetHQ\Cachet\Models\MetricPoint $metricPoint
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\MetricPoint
|
||||
*/
|
||||
public function getMetricPoints(Metric $metric, MetricPoint $metricPoint)
|
||||
{
|
||||
return $this->item($metricPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\MetricPoint
|
||||
*/
|
||||
public function postMetricPoints(Metric $metric)
|
||||
{
|
||||
$metricPointData = Binput::all();
|
||||
$metricPointData['metric_id'] = $metric->id;
|
||||
|
||||
if ($timestamp = array_pull($metricPointData, 'timestamp')) {
|
||||
$pointTimestamp = Carbon::createFromFormat('U', $timestamp);
|
||||
$metricPointData['created_at'] = $pointTimestamp->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
try {
|
||||
$metricPoint = MetricPoint::create($metricPointData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
return $this->item($metricPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
* @param \CachetHQ\Cachet\Models\MetircPoint $metricPoint
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\MetricPoint
|
||||
*/
|
||||
public function putMetricPoint(Metric $metric, MetricPoint $metricPoint)
|
||||
{
|
||||
$metricPointData = Binput::all();
|
||||
$metricPointData['metric_id'] = $metric->id;
|
||||
|
||||
if ($timestamp = array_pull($metricPointData, 'timestamp')) {
|
||||
$pointTimestamp = Carbon::createFromFormat('U', $timestamp);
|
||||
$metricPointData['created_at'] = $pointTimestamp->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$metricPoint->update($metricPointData);
|
||||
|
||||
return $this->item($metricPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
* @param \CachetHQ\Cachet\Models\MetricPoint $metricPoint
|
||||
*
|
||||
* @return \Dingo\Api\Http\Response
|
||||
*/
|
||||
public function deleteMetricPoint(Metric $metric, MetricPoint $metricPoint)
|
||||
{
|
||||
$metricPoint->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
@@ -1,77 +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\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class SubscriberController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all subscribers.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getSubscribers(Request $request)
|
||||
{
|
||||
$subscribers = Subscriber::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($subscribers, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subscriber.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
public function postSubscribers()
|
||||
{
|
||||
$subscriberData = Binput::except('verify');
|
||||
|
||||
try {
|
||||
$subscriber = Subscriber::create($subscriberData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if ($subscriber->isValid()) {
|
||||
// If we're auto-verifying the subscriber, don't bother with this event.
|
||||
if (!(Binput::get('verify'))) {
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
}
|
||||
|
||||
return $this->item($subscriber);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a subscriber.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteSubscriber(Subscriber $subscriber)
|
||||
{
|
||||
$subscriber->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
@@ -1,118 +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\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
class HomeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Returns the rendered Blade templates.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showIndex()
|
||||
{
|
||||
$today = Date::now();
|
||||
$startDate = Date::now();
|
||||
|
||||
// Check if we have another starting date
|
||||
if (Binput::has('start_date')) {
|
||||
try {
|
||||
// If date provided is valid
|
||||
$oldDate = Date::createFromFormat('Y-m-d', Binput::get('start_date'));
|
||||
|
||||
// If trying to get a future date fallback to today
|
||||
if ($today->gt($oldDate)) {
|
||||
$startDate = $oldDate;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Fallback to today
|
||||
}
|
||||
}
|
||||
|
||||
$metrics = null;
|
||||
|
||||
if ($displayMetrics = Setting::get('display_graphs')) {
|
||||
$metrics = Metric::where('display_chart', 1)->get();
|
||||
}
|
||||
|
||||
$daysToShow = Setting::get('app_incident_days') ?: 7;
|
||||
$incidentDays = range(0, $daysToShow - 1);
|
||||
$dateTimeZone = Setting::get('app_timezone');
|
||||
|
||||
$incidentVisiblity = Auth::check() ? 0 : 1;
|
||||
|
||||
$allIncidents = Incident::notScheduled()->where('visible', '>=', $incidentVisiblity)->whereBetween('created_at', [
|
||||
$startDate->copy()->subDays($daysToShow)->format('Y-m-d').' 00:00:00',
|
||||
$startDate->format('Y-m-d').' 23:59:59',
|
||||
])->orderBy('scheduled_at', 'desc')->orderBy('created_at', 'desc')->get()->groupBy(function (Incident $incident) use ($dateTimeZone) {
|
||||
// If it's scheduled, get the scheduled at date.
|
||||
if ($incident->is_scheduled) {
|
||||
return (new Date($incident->scheduled_at))
|
||||
->setTimezone($dateTimeZone)->toDateString();
|
||||
}
|
||||
|
||||
return (new Date($incident->created_at))
|
||||
->setTimezone($dateTimeZone)->toDateString();
|
||||
});
|
||||
|
||||
// Add in days that have no incidents
|
||||
foreach ($incidentDays as $i) {
|
||||
$date = (new Date($startDate))->setTimezone($dateTimeZone)->subDays($i);
|
||||
|
||||
if (!isset($allIncidents[$date->toDateString()])) {
|
||||
$allIncidents[$date->toDateString()] = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the array so it takes into account the added days
|
||||
$allIncidents = $allIncidents->sortBy(function ($value, $key) {
|
||||
return strtotime($key);
|
||||
}, SORT_REGULAR, true)->all();
|
||||
|
||||
// Scheduled maintenance code.
|
||||
$scheduledMaintenance = Incident::scheduled()->orderBy('scheduled_at')->get();
|
||||
|
||||
// Component & Component Group lists.
|
||||
$usedComponentGroups = Component::where('group_id', '>', 0)->groupBy('group_id')->lists('group_id');
|
||||
$componentGroups = ComponentGroup::whereIn('id', $usedComponentGroups)->orderBy('order')->get();
|
||||
$ungroupedComponents = Component::where('group_id', 0)->orderBy('order')->orderBy('created_at')->get();
|
||||
|
||||
$canPageBackward = Incident::notScheduled()->where('created_at', '<', $startDate->format('Y-m-d'))->count() != 0;
|
||||
|
||||
return View::make('index', [
|
||||
'componentGroups' => $componentGroups,
|
||||
'ungroupedComponents' => $ungroupedComponents,
|
||||
'displayMetrics' => $displayMetrics,
|
||||
'metrics' => $metrics,
|
||||
'allIncidents' => $allIncidents,
|
||||
'scheduledMaintenance' => $scheduledMaintenance,
|
||||
'aboutApp' => Markdown::convertToHtml(Setting::get('app_about')),
|
||||
'canPageForward' => (bool) $today->gt($startDate),
|
||||
'canPageBackward' => $canPageBackward,
|
||||
'previousDate' => $startDate->copy()->subDays($daysToShow)->toDateString(),
|
||||
'nextDate' => $startDate->copy()->addDays($daysToShow)->toDateString(),
|
||||
'page_title' => Setting::get('app_name'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +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\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use Illuminate\Support\Str;
|
||||
use Roumen\Feed\Facades\Feed;
|
||||
|
||||
class RssController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Generates an Atom feed of all incidents.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\ComponentGroup|null $group
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function feedAction(ComponentGroup $group = null)
|
||||
{
|
||||
$feed = Feed::make();
|
||||
$feed->title = Setting::get('app_name');
|
||||
$feed->lang = Setting::get('app_locale');
|
||||
$feed->description = trans('cachet.feed');
|
||||
$feed->link = Str::canonicalize(Setting::get('app_domain'));
|
||||
|
||||
$feed->setDateFormat('datetime');
|
||||
|
||||
if ($group->exists) {
|
||||
$group->components->map(function ($component) use ($feed) {
|
||||
$component->incidents()->visible()->orderBy('created_at', 'desc')->get()->map(function ($incident) use ($feed) {
|
||||
$this->feedAddItem($feed, $incident);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Incident::visible()->orderBy('created_at', 'desc')->get()->map(function ($incident) use ($feed) {
|
||||
$this->feedAddItem($feed, $incident);
|
||||
});
|
||||
}
|
||||
|
||||
return $feed->render('rss');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the feed.
|
||||
*
|
||||
* @param \Roumen\Feed\Facades\Feed $feed
|
||||
* @param \CachetHQ\Cachet\Models\Incident $incident
|
||||
*/
|
||||
private function feedAddItem(&$feed, $incident)
|
||||
{
|
||||
$feed->add(
|
||||
$incident->name,
|
||||
Setting::get('app_name'),
|
||||
Str::canonicalize(Setting::get('app_domain')).'#'.$incident->id,
|
||||
$incident->created_at->toRssString(),
|
||||
$incident->message
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,216 +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\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class SetupController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Array of cache drivers.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $cacheDrivers = [
|
||||
'apc' => 'APC(u)',
|
||||
'array' => 'Array',
|
||||
'file' => 'File',
|
||||
'database' => 'Database',
|
||||
'memcached' => 'Memcached',
|
||||
'redis' => 'Redis',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new setup controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->beforeFilter('csrf', ['only' => ['postCachet']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setup page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
// If we've copied the .env.example file, then we should try and reset it.
|
||||
if (getenv('APP_KEY') === 'SomeRandomString') {
|
||||
$this->keyGenerate();
|
||||
}
|
||||
|
||||
return View::make('setup')->with([
|
||||
'page_title' => trans('setup.setup'),
|
||||
'cacheDrivers' => $this->cacheDrivers,
|
||||
'appUrl' => Request::root(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles validation on step one of the setup form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postStep1()
|
||||
{
|
||||
$postData = Binput::all();
|
||||
|
||||
$v = Validator::make($postData, [
|
||||
'env.cache_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'env.session_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
]);
|
||||
|
||||
if ($v->passes()) {
|
||||
return Response::json(['status' => 1]);
|
||||
} else {
|
||||
return Response::json(['errors' => $v->messages()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles validation on step two of the setup form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postStep2()
|
||||
{
|
||||
$postData = Binput::all();
|
||||
|
||||
$v = Validator::make($postData, [
|
||||
'env.cache_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'env.session_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'settings.app_name' => 'required',
|
||||
'settings.app_domain' => 'required',
|
||||
'settings.app_timezone' => 'required',
|
||||
'settings.app_locale' => 'required',
|
||||
'settings.show_support' => 'boolean',
|
||||
]);
|
||||
|
||||
if ($v->passes()) {
|
||||
return Response::json(['status' => 1]);
|
||||
} else {
|
||||
return Response::json(['errors' => $v->messages()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the actual app setup, including user, settings and env.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
|
||||
*/
|
||||
public function postStep3()
|
||||
{
|
||||
$postData = Binput::all();
|
||||
|
||||
$v = Validator::make($postData, [
|
||||
'env.cache_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'env.session_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'settings.app_name' => 'required',
|
||||
'settings.app_domain' => 'required',
|
||||
'settings.app_timezone' => 'required',
|
||||
'settings.app_locale' => 'required',
|
||||
'settings.show_support' => 'boolean',
|
||||
'user.username' => ['required', 'regex:/\A(?!.*[:;]-\))[ -~]+\z/'],
|
||||
'user.email' => 'email|required',
|
||||
'user.password' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->passes()) {
|
||||
// Pull the user details out.
|
||||
$userDetails = array_pull($postData, 'user');
|
||||
|
||||
$user = User::create([
|
||||
'username' => $userDetails['username'],
|
||||
'email' => $userDetails['email'],
|
||||
'password' => $userDetails['password'],
|
||||
'level' => 1,
|
||||
]);
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
$settings = array_pull($postData, 'settings');
|
||||
|
||||
foreach ($settings as $settingName => $settingValue) {
|
||||
Setting::create([
|
||||
'name' => $settingName,
|
||||
'value' => $settingValue,
|
||||
]);
|
||||
}
|
||||
|
||||
$envData = array_pull($postData, 'env');
|
||||
|
||||
// Write the env to the .env file.
|
||||
foreach ($envData as $envKey => $envValue) {
|
||||
$this->writeEnv($envKey, $envValue);
|
||||
}
|
||||
|
||||
Session::flash('setup.done', true);
|
||||
|
||||
if (Request::ajax()) {
|
||||
return Response::json(['status' => 1]);
|
||||
}
|
||||
|
||||
return Redirect::to('dashboard');
|
||||
} else {
|
||||
if (Request::ajax()) {
|
||||
return Response::json(['errors' => $v->messages()], 400);
|
||||
}
|
||||
|
||||
return Redirect::back()->withInput()->with('errors', $v->messages());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to the .env file with given parameters.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function writeEnv($key, $value)
|
||||
{
|
||||
static $path = null;
|
||||
|
||||
if ($path === null || ($path !== null && file_exists($path))) {
|
||||
$path = base_path('.env');
|
||||
file_put_contents($path, str_replace(
|
||||
getenv(strtoupper($key)), $value, file_get_contents($path)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the app.key value.
|
||||
*/
|
||||
protected function keyGenerate()
|
||||
{
|
||||
$key = str_random(42);
|
||||
|
||||
$path = base_path('.env');
|
||||
|
||||
file_put_contents($path, str_replace(
|
||||
Config::get('app.key'), $key, file_get_contents($path)
|
||||
));
|
||||
|
||||
Config::set('app.key', $key);
|
||||
}
|
||||
}
|
||||
@@ -1,129 +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\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Carbon\Carbon;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class SubscribeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Show the subscribe by email page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showSubscribe()
|
||||
{
|
||||
return View::make('subscribe', [
|
||||
'page_title' => Setting::get('app_name'),
|
||||
'aboutApp' => Markdown::convertToHtml(Setting::get('app_about')),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the subscribe user.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function postSubscribe()
|
||||
{
|
||||
$subscriber = Subscriber::create(['email' => Binput::get('email')]);
|
||||
|
||||
if (!$subscriber->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('cachet.subscriber.email.failure')
|
||||
))
|
||||
->with('errors', $subscriber->getErrors());
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('cachet.subscriber.email.subscribed')
|
||||
);
|
||||
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
|
||||
return Redirect::route('status-page')->with('success', $successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the verify subscriber email.
|
||||
*
|
||||
* @param string $code
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function getVerify($code = null)
|
||||
{
|
||||
if (is_null($code)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||
|
||||
if (!$subscriber || $subscriber->verified()) {
|
||||
return Redirect::route('status-page');
|
||||
}
|
||||
|
||||
$subscriber->verified_at = Carbon::now();
|
||||
$subscriber->save();
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('cachet.subscriber.email.verified')
|
||||
);
|
||||
|
||||
return Redirect::route('status-page')->with('success', $successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the unsubscribe.
|
||||
*
|
||||
* @param string $code
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function getUnsubscribe($code = null)
|
||||
{
|
||||
if (is_null($code)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||
|
||||
if (!$subscriber || !$subscriber->verified()) {
|
||||
return Redirect::route('status-page');
|
||||
}
|
||||
|
||||
$subscriber->delete();
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('cachet.subscriber.email.unsuscribed')
|
||||
);
|
||||
|
||||
return Redirect::route('status-page')->with('success', $successMsg);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +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\Http;
|
||||
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
/**
|
||||
* The application's global HTTP middleware stack.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
'Fideloper\Proxy\TrustProxies',
|
||||
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
|
||||
'Illuminate\Cookie\Middleware\EncryptCookies',
|
||||
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
|
||||
'Illuminate\Session\Middleware\StartSession',
|
||||
'Illuminate\View\Middleware\ShareErrorsFromSession',
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth' => 'CachetHQ\Cachet\Http\Middleware\Authenticate',
|
||||
'auth.api' => 'CachetHQ\Cachet\Http\Middleware\ApiAuthenticate',
|
||||
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
|
||||
'guest' => 'CachetHQ\Cachet\Http\Middleware\RedirectIfAuthenticated',
|
||||
'csrf' => 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken',
|
||||
'admin' => 'CachetHQ\Cachet\Http\Middleware\Admin',
|
||||
'throttling' => 'GrahamCampbell\Throttle\Http\Middleware\ThrottleMiddleware',
|
||||
'app.isSetup' => 'CachetHQ\Cachet\Http\Middleware\AppIsSetup',
|
||||
'app.hasSetting' => 'CachetHQ\Cachet\Http\Middleware\HasSetting',
|
||||
'app.subscribers' => 'CachetHQ\Cachet\Http\Middleware\SubscribersConfigured',
|
||||
'accept' => 'CachetHQ\Cachet\Http\Middleware\Acceptable',
|
||||
];
|
||||
}
|
||||
@@ -1,36 +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\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
|
||||
|
||||
class Acceptable
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $type
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $type)
|
||||
{
|
||||
if (!$request->accepts($type)) {
|
||||
throw new NotAcceptableHttpException();
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class Admin
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new admin middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* We're verifying that the current user is logged in to Cachet and is an admin level.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$this->auth->check() || ($this->auth->check() && !$this->auth->user()->isAdmin)) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +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\Http\Middleware;
|
||||
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class ApiAuthenticate
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new api authenticate middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
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, Closure $next)
|
||||
{
|
||||
if ($this->auth->guest()) {
|
||||
if ($apiToken = $request->header('X-Cachet-Token')) {
|
||||
try {
|
||||
$this->auth->onceUsingId(User::findByApiToken($apiToken)->id);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
} elseif ($request->getUser()) {
|
||||
if ($this->auth->onceBasic() !== null) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class Authenticate
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new authenticate middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
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, Closure $next)
|
||||
{
|
||||
if ($this->auth->guest()) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +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\Http\Middleware;
|
||||
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
|
||||
class HasSetting
|
||||
{
|
||||
/**
|
||||
* Run the has setting middleware.
|
||||
*
|
||||
* We're verifying that the given setting exists in our database. If it
|
||||
* doesn't, then we're sending the user to the setup page so that they can
|
||||
* complete the installation of Cachet on their server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$settingName = $this->getSettingName($request);
|
||||
|
||||
try {
|
||||
$setting = Setting::where('name', $settingName)->first();
|
||||
if (!$setting || !$setting->value) {
|
||||
return Redirect::to('setup');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return Redirect::to('setup');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setting from the request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSettingName($request)
|
||||
{
|
||||
$actions = $request->route()->getAction();
|
||||
|
||||
return $actions['setting'];
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new redirect if authenticated middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
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, Closure $next)
|
||||
{
|
||||
if ($this->auth->check()) {
|
||||
return new RedirectResponse(route('dashboard'));
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +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\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
|
||||
class SubscribersConfigured
|
||||
{
|
||||
/**
|
||||
* We're verifying that subscribers is both enabled and configured.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!subscribers_enabled()) {
|
||||
return Redirect::route('status-page');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,224 +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\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class AdminRoutes
|
||||
{
|
||||
/**
|
||||
* Define the dashboard routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group([
|
||||
'middleware' => 'auth',
|
||||
'prefix' => 'dashboard',
|
||||
'namespace' => 'Admin',
|
||||
], function ($router) {
|
||||
// Dashboard
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard',
|
||||
'uses' => 'DashboardController@showDashboard',
|
||||
]);
|
||||
|
||||
// Components
|
||||
$router->group(['prefix' => 'components'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.components',
|
||||
'uses' => 'ComponentController@showComponents',
|
||||
]);
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.components.add',
|
||||
'uses' => 'ComponentController@showAddComponent',
|
||||
]);
|
||||
$router->post('add', 'ComponentController@createComponentAction');
|
||||
$router->get('groups', [
|
||||
'as' => 'dashboard.components.groups',
|
||||
'uses' => 'ComponentController@showComponentGroups',
|
||||
]);
|
||||
$router->get('groups/add', [
|
||||
'as' => 'dashboard.components.groups.add',
|
||||
'uses' => 'ComponentController@showAddComponentGroup',
|
||||
]);
|
||||
$router->get('groups/edit/{component_group}', [
|
||||
'as' => 'dashboard.components.groups.edit',
|
||||
'uses' => 'ComponentController@showEditComponentGroup',
|
||||
]);
|
||||
$router->post('groups/edit/{component_group}', 'ComponentController@updateComponentGroupAction');
|
||||
|
||||
$router->delete('groups/{component_group}/delete', 'ComponentController@deleteComponentGroupAction');
|
||||
$router->post('groups/add', 'ComponentController@postAddComponentGroup');
|
||||
$router->delete('{component}/delete', 'ComponentController@deleteComponentAction');
|
||||
$router->get('{component}/edit', 'ComponentController@showEditComponent');
|
||||
$router->post('{component}/edit', 'ComponentController@updateComponentAction');
|
||||
});
|
||||
|
||||
// Incidents
|
||||
$router->group(['prefix' => 'incidents'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.incidents',
|
||||
'uses' => 'IncidentController@showIncidents',
|
||||
]);
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.incidents.add',
|
||||
'uses' => 'IncidentController@showAddIncident',
|
||||
]);
|
||||
$router->post('add', 'IncidentController@createIncidentAction');
|
||||
$router->delete('{incident}/delete', 'IncidentController@deleteIncidentAction');
|
||||
$router->get('{incident}/edit', 'IncidentController@showEditIncidentAction');
|
||||
$router->post('{incident}/edit', 'IncidentController@editIncidentAction');
|
||||
});
|
||||
|
||||
// Scheduled Maintenance
|
||||
$router->group(['prefix' => 'schedule'], function ($router) {
|
||||
$router->get('/', ['as' => 'dashboard.schedule', 'uses' => 'ScheduleController@showIndex']);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.schedule.add',
|
||||
'uses' => 'ScheduleController@showAddSchedule',
|
||||
]);
|
||||
$router->post('add', 'ScheduleController@addScheduleAction');
|
||||
|
||||
$router->get('{incident}/edit', [
|
||||
'as' => 'dashboard.schedule.edit',
|
||||
'uses' => 'ScheduleController@showEditSchedule',
|
||||
]);
|
||||
$router->post('{incident}/edit', 'ScheduleController@editScheduleAction');
|
||||
|
||||
$router->delete('{incident}/delete', [
|
||||
'as' => 'dashboard.schedule.delete',
|
||||
'uses' => 'ScheduleController@deleteScheduleAction',
|
||||
]);
|
||||
});
|
||||
|
||||
// Incident Templates
|
||||
$router->group(['prefix' => 'templates'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.templates',
|
||||
'uses' => 'IncidentController@showTemplates',
|
||||
]);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.templates.add',
|
||||
'uses' => 'IncidentController@showAddIncidentTemplate',
|
||||
]);
|
||||
$router->post('add', 'IncidentController@createIncidentTemplateAction');
|
||||
|
||||
$router->get('{incident_template}/edit', 'IncidentController@showEditTemplateAction');
|
||||
$router->post('{incident_template}/edit', 'IncidentController@editTemplateAction');
|
||||
$router->delete('{incident_template}/delete', 'IncidentController@deleteTemplateAction');
|
||||
});
|
||||
|
||||
// Subscribers
|
||||
$router->group(['prefix' => 'subscribers'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.subscribers',
|
||||
'uses' => 'SubscriberController@showSubscribers',
|
||||
]);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.subscribers.add',
|
||||
'uses' => 'SubscriberController@showAddSubscriber',
|
||||
]);
|
||||
$router->post('add', 'SubscriberController@createSubscriberAction');
|
||||
|
||||
$router->delete('{subscriber}/delete', 'SubscriberController@deleteSubscriberAction');
|
||||
});
|
||||
|
||||
// Metrics
|
||||
$router->group(['prefix' => 'metrics'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.metrics',
|
||||
'uses' => 'MetricController@showMetrics',
|
||||
]);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.metrics.add',
|
||||
'uses' => 'MetricController@showAddMetric',
|
||||
]);
|
||||
$router->post('add', 'MetricController@createMetricAction');
|
||||
$router->delete('{metric}/delete', 'MetricController@deleteMetricAction');
|
||||
$router->get('{metric}/edit', 'MetricController@showEditMetricAction');
|
||||
$router->post('{metric}/edit', 'MetricController@editMetricAction');
|
||||
});
|
||||
|
||||
// Notifications
|
||||
$router->group(['prefix' => 'notifications'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.notifications',
|
||||
'uses' => 'DashboardController@showNotifications',
|
||||
]);
|
||||
});
|
||||
|
||||
// Team Members
|
||||
$router->group(['prefix' => 'team'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.team',
|
||||
'uses' => 'TeamController@showTeamView',
|
||||
]);
|
||||
|
||||
$router->group(['middleware' => 'admin'], function ($router) {
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.team.add',
|
||||
'uses' => 'TeamController@showAddTeamMemberView',
|
||||
]);
|
||||
$router->get('{user}', 'TeamController@showTeamMemberView');
|
||||
$router->post('add', 'TeamController@postAddUser');
|
||||
$router->post('{user}', 'TeamController@postUpdateUser');
|
||||
});
|
||||
});
|
||||
|
||||
// Settings
|
||||
$router->group(['prefix' => 'settings'], function ($router) {
|
||||
$router->get('setup', [
|
||||
'as' => 'dashboard.settings.setup',
|
||||
'uses' => 'SettingsController@showSetupView',
|
||||
]);
|
||||
$router->get('security', [
|
||||
'as' => 'dashboard.settings.security',
|
||||
'uses' => 'SettingsController@showSecurityView',
|
||||
]);
|
||||
$router->get('theme', [
|
||||
'as' => 'dashboard.settings.theme',
|
||||
'uses' => 'SettingsController@showThemeView',
|
||||
]);
|
||||
$router->get('stylesheet', [
|
||||
'as' => 'dashboard.settings.stylesheet',
|
||||
'uses' => 'SettingsController@showStylesheetView',
|
||||
]);
|
||||
$router->post('/', 'SettingsController@postSettings');
|
||||
});
|
||||
|
||||
// User Settings
|
||||
$router->group(['prefix' => 'user'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.user',
|
||||
'uses' => 'UserController@showUser',
|
||||
]);
|
||||
$router->post('/', 'UserController@postUser');
|
||||
$router->get('{user}/api/regen', 'UserController@regenerateApiKey');
|
||||
});
|
||||
|
||||
// Internal API.
|
||||
// This should only be used for making requests within the dashboard.
|
||||
$router->group(['prefix' => 'api'], function ($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');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,69 +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\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class ApiRoutes
|
||||
{
|
||||
/**
|
||||
* Define the api routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group([
|
||||
'namespace' => 'Api',
|
||||
'prefix' => 'api/v1',
|
||||
'middleware' => 'accept:application/json',
|
||||
], function ($router) {
|
||||
// General
|
||||
$router->get('ping', 'GeneralController@ping');
|
||||
|
||||
// Components
|
||||
$router->get('components', 'ComponentController@getComponents');
|
||||
$router->get('components/{component}', 'ComponentController@getComponent');
|
||||
|
||||
// Incidents
|
||||
$router->get('incidents', 'IncidentController@getIncidents');
|
||||
$router->get('incidents/{incident}', 'IncidentController@getIncident');
|
||||
|
||||
// Metrics
|
||||
$router->get('metrics', 'MetricController@getMetrics');
|
||||
$router->get('metrics/{metric}', 'MetricController@getMetric');
|
||||
$router->get('metrics/{metric}/points', 'MetricController@getMetricPoints');
|
||||
|
||||
// Api protected
|
||||
$router->group(['middleware' => 'auth.api'], function ($router) {
|
||||
$router->get('subscribers', 'SubscriberController@getSubscribers');
|
||||
|
||||
$router->post('components', 'ComponentController@postComponents');
|
||||
$router->post('incidents', 'IncidentController@postIncidents');
|
||||
$router->post('metrics', 'MetricController@postMetrics');
|
||||
$router->post('metrics/{metric}/points', 'MetricPointController@postMetricPoints');
|
||||
$router->post('subscribers', 'SubscriberController@postSubscribers');
|
||||
|
||||
$router->put('components/{component}', 'ComponentController@putComponent');
|
||||
$router->put('incidents/{incident}', 'IncidentController@putIncident');
|
||||
$router->put('metrics/{metric}', 'MetricController@putMetric');
|
||||
$router->put('metrics/{metric}/points/{metric_point}', 'MetricPointController@putMetricPoint');
|
||||
|
||||
$router->delete('components/{component}', 'ComponentController@deleteComponent');
|
||||
$router->delete('incidents/{incident}', 'IncidentController@deleteIncident');
|
||||
$router->delete('metrics/{metric}', 'MetricController@deleteMetric');
|
||||
$router->delete('metrics/{metric}/points/{metric_point}', 'MetricPointController@deleteMetricPoint');
|
||||
$router->delete('subscribers/{subscriber}', 'SubscriberController@deleteSubscriber');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,57 +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\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class AuthRoutes
|
||||
{
|
||||
/**
|
||||
* Define the auth routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group(['prefix' => 'auth'], function ($router) {
|
||||
$router->group(['middleware' => 'app.hasSetting', 'setting' => 'app_name'], function ($router) {
|
||||
// Login routes
|
||||
$router->get('login', [
|
||||
'middleware' => 'guest',
|
||||
'as' => 'login',
|
||||
'uses' => 'AuthController@showLogin',
|
||||
]);
|
||||
|
||||
$router->post('login', [
|
||||
'middleware' => ['guest', 'csrf', 'throttling:10,10'],
|
||||
'as' => 'login',
|
||||
'uses' => 'AuthController@postLogin',
|
||||
]);
|
||||
|
||||
// Two factor authorization
|
||||
$router->get('2fa', [
|
||||
'as' => 'two-factor',
|
||||
'uses' => 'AuthController@showTwoFactorAuth',
|
||||
]);
|
||||
|
||||
$router->post('2fa', 'AuthController@postTwoFactor');
|
||||
});
|
||||
|
||||
$router->group(['middleware' => 'auth'], function ($router) {
|
||||
$router->get('logout', [
|
||||
'as' => 'logout',
|
||||
'uses' => 'AuthController@logoutAction',
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,29 +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\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class SetupRoutes
|
||||
{
|
||||
/**
|
||||
* Define the setup routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group(['middleware' => 'app.isSetup'], function ($router) {
|
||||
$router->controller('setup', 'SetupController');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,36 +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\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class StatusPageRoutes
|
||||
{
|
||||
/**
|
||||
* Define the status page routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
// Prevent access until the app is setup.
|
||||
$router->group(['middleware' => 'app.hasSetting', 'setting' => 'app_name'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'status-page',
|
||||
'uses' => 'HomeController@showIndex',
|
||||
]);
|
||||
|
||||
$router->get('/atom/{component_group?}', 'AtomController@feedAction');
|
||||
$router->get('/rss/{component_group?}', 'RssController@feedAction');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,49 +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\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class SubscribeRoutes
|
||||
{
|
||||
/**
|
||||
* Define the subscribe routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group(['middleware' => 'app.hasSetting', 'setting' => 'app_name'], function ($router) {
|
||||
$router->group(['middleware' => 'app.subscribers'], function ($router) {
|
||||
$router->get('subscribe', [
|
||||
'as' => 'subscribe-page',
|
||||
'uses' => 'SubscribeController@showSubscribe',
|
||||
]);
|
||||
|
||||
$router->post('subscribe', [
|
||||
'as' => 'subscribe',
|
||||
'uses' => 'SubscribeController@postSubscribe',
|
||||
]);
|
||||
|
||||
$router->get('subscribe/verify/{code}', [
|
||||
'as' => 'subscribe-verify',
|
||||
'uses' => 'SubscribeController@getVerify',
|
||||
]);
|
||||
|
||||
$router->get('unsubscribe/{code}', [
|
||||
'as' => 'unsubscribe',
|
||||
'uses' => 'SubscribeController@getUnsubscribe',
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,69 +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.
|
||||
*/
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
if (!function_exists('set_active')) {
|
||||
|
||||
/**
|
||||
* Set active class if request is in path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $classes
|
||||
* @param string $active
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function set_active($path, array $classes = [], $active = 'active')
|
||||
{
|
||||
if (Request::is($path)) {
|
||||
$classes[] = $active;
|
||||
}
|
||||
|
||||
$class = e(implode(' ', $classes));
|
||||
|
||||
return empty($classes) ? '' : "class=\"{$class}\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('formatted_date')) {
|
||||
/**
|
||||
* Formats a date with the user timezone and the selected format.
|
||||
*
|
||||
* @param string $date
|
||||
*
|
||||
* @return \Jenssegers\Date\Date
|
||||
*/
|
||||
function formatted_date($date)
|
||||
{
|
||||
$dateFormat = Setting::get('date_format', 'jS F Y');
|
||||
|
||||
return (new Date($date))->format($dateFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('subscribers_enabled')) {
|
||||
/**
|
||||
* Is the subscriber functionality enabled and configured.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function subscribers_enabled()
|
||||
{
|
||||
$isEnabled = Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
|
||||
return $isEnabled && $mailAddress && $mailFrom;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +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\Models;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\MetricPointPresenter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class MetricPoint extends Model implements HasPresenter
|
||||
{
|
||||
use ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['metric_id', 'value', 'created_at'];
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'value' => 'numeric|required',
|
||||
];
|
||||
|
||||
/**
|
||||
* A metric point belongs to a metric unit.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function metric()
|
||||
{
|
||||
return $this->belongsTo(Metric::class, 'id', 'metric_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return MetricPointPresenter::class;
|
||||
}
|
||||
}
|
||||
@@ -1,99 +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\Models;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\SubscriberPresenter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Subscriber extends Model implements HasPresenter
|
||||
{
|
||||
use ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'email' => 'required|email|unique:subscribers',
|
||||
];
|
||||
|
||||
/**
|
||||
* The fillable properties.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['email'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['verified_at'];
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'email' => 'string',
|
||||
'verify_code' => 'string',
|
||||
];
|
||||
|
||||
/**
|
||||
* Overrides the models boot method.
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::creating(function ($user) {
|
||||
if (!$user->verify_code) {
|
||||
$user->verify_code = self::generateVerifyCode();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the subscriber is verified.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verified()
|
||||
{
|
||||
return !is_null($this->verified_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an new verify code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateVerifyCode()
|
||||
{
|
||||
return str_random(42);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return SubscriberPresenter::class;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +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 CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use McCool\LaravelAutoPresenter\BasePresenter as BaseLaravelAutoPresenter;
|
||||
|
||||
abstract class AbstractPresenter extends BaseLaravelAutoPresenter implements Arrayable
|
||||
{
|
||||
/**
|
||||
* The setting repository.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Config\Repository
|
||||
*/
|
||||
protected $setting;
|
||||
|
||||
/**
|
||||
* Create a incident presenter instance.
|
||||
*
|
||||
* @param object $resource
|
||||
*/
|
||||
public function __construct($resource)
|
||||
{
|
||||
parent::__construct($resource);
|
||||
|
||||
$this->setting = app('setting');
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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 CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class ComponentPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
'status_name' => $this->wrappedObject->humanStatus,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,196 +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 CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
class IncidentPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Renders the message from Markdown into HTML.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formattedMessage()
|
||||
{
|
||||
return Markdown::convertToHtml($this->wrappedObject->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Present diff for humans date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_diff()
|
||||
{
|
||||
return (new Date($this->wrappedObject->created_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->diffForHumans();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_formatted()
|
||||
{
|
||||
return ucfirst((new Date($this->wrappedObject->created_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->format($this->setting->get('incident_date_format', 'l jS F Y H:i:s')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the created_at time ready to be used by bootstrap-datetimepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_datetimepicker()
|
||||
{
|
||||
return $this->wrappedObject->created_at->setTimezone($this->setting->get('app_timezone'))->format('d/m/Y H:i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_iso()
|
||||
{
|
||||
return $this->wrappedObject->created_at->setTimezone($this->setting->get('app_timezone'))->toISO8601String();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->scheduled_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present diff for humans date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_diff()
|
||||
{
|
||||
return (new Date($this->wrappedObject->scheduled_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->diffForHumans();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formated date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_formatted()
|
||||
{
|
||||
return ucfirst((new Date($this->wrappedObject->scheduled_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->format($this->setting->get('incident_date_format', 'l jS F Y H:i:s')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_iso()
|
||||
{
|
||||
return $this->wrappedObject->scheduled_at->setTimezone($this->setting->get('app_timezone'))->toISO8601String();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the scheduled_at time ready to be used by bootstrap-datetimepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_datetimepicker()
|
||||
{
|
||||
return $this->wrappedObject->scheduled_at->setTimezone($this->setting->get('app_timezone'))->format('d/m/Y H:i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted timestamp for use within the timeline.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function timestamp_formatted()
|
||||
{
|
||||
if ($this->wrappedObject->is_scheduled) {
|
||||
return $this->scheduled_at_formatted;
|
||||
} else {
|
||||
return $this->created_at_formatted;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the iso timestamp for use within the timeline.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function timestamp_iso()
|
||||
{
|
||||
if ($this->wrappedObject->is_scheduled) {
|
||||
return $this->scheduled_at_iso;
|
||||
} else {
|
||||
return $this->created_at_iso;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Present the status with an icon.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function icon()
|
||||
{
|
||||
switch ($this->wrappedObject->status) {
|
||||
case 0: // Scheduled
|
||||
return 'icon ion-android-calendar';
|
||||
case 1: // Investigating
|
||||
return 'icon ion-flag';
|
||||
case 2: // Identified
|
||||
return 'icon ion-alert';
|
||||
case 3: // Watching
|
||||
return 'icon ion-eye';
|
||||
case 4: // Fixed
|
||||
return 'icon ion-checkmark';
|
||||
default: // Something actually broke, this shouldn't happen.
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'scheduled_at' => $this->created_at(),
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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 CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class MetricPointPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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 CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class MetricPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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 CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class SubscriberPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
'verified_at' => $this->verified_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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\Traits;
|
||||
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
trait TimestampsTrait
|
||||
{
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->created_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function updated_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->updated_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function deleted_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->deleted_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function verified_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->verified_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
}
|
||||
@@ -1,43 +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\Providers;
|
||||
|
||||
use Illuminate\Bus\Dispatcher;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*
|
||||
* @param \Illuminate\Bus\Dispatcher $dispatcher
|
||||
*/
|
||||
public function boot(Dispatcher $dispatcher)
|
||||
{
|
||||
$dispatcher->mapUsing(function ($command) {
|
||||
return Dispatcher::simpleMapping($command, 'CachetHQ\Cachet\Commands', 'CachetHQ\Cachet\Handlers\Commands');
|
||||
});
|
||||
|
||||
Str::macro('canonicalize', function ($url) {
|
||||
return preg_replace('/([^\/])$/', '$1/', $url);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->bind('Illuminate\Contracts\Auth\Registrar', 'CachetHQ\Cachet\Services\Registrar');
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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\Providers;
|
||||
|
||||
use CachetHQ\Cachet\Composers\AppComposer;
|
||||
use CachetHQ\Cachet\Composers\DashboardComposer;
|
||||
use CachetHQ\Cachet\Composers\IndexComposer;
|
||||
use CachetHQ\Cachet\Composers\LoggedUserComposer;
|
||||
use CachetHQ\Cachet\Composers\ThemeComposer;
|
||||
use CachetHQ\Cachet\Composers\TimezoneLocaleComposer;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ComposerServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\Factory $factory
|
||||
*/
|
||||
public function boot(Factory $factory)
|
||||
{
|
||||
$factory->composer('*', AppComposer::class);
|
||||
$factory->composer('*', LoggedUserComposer::class);
|
||||
$factory->composer(['index', 'subscribe'], IndexComposer::class);
|
||||
$factory->composer(['index', 'subscribe'], ThemeComposer::class);
|
||||
$factory->composer('dashboard.*', DashboardComposer::class);
|
||||
$factory->composer(['setup', 'dashboard.settings.app-setup'], TimezoneLocaleComposer::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -1,70 +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\Providers;
|
||||
|
||||
use CachetHQ\Cachet\Config\Repository;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Setting as SettingModel;
|
||||
use Exception;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ConfigServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$appDomain = $appLocale = null;
|
||||
|
||||
try {
|
||||
// Get app custom configuration.
|
||||
$appDomain = Setting::get('app_domain');
|
||||
$appLocale = Setting::get('app_locale');
|
||||
|
||||
// Setup Cors.
|
||||
$allowedOrigins = $this->app->config->get('cors.defaults.allowedOrigins');
|
||||
$allowedOrigins[] = Setting::get('app_domain');
|
||||
|
||||
// Add our allowed domains too.
|
||||
if ($allowedDomains = Setting::get('allowed_domains')) {
|
||||
$domains = explode(',', $allowedDomains);
|
||||
foreach ($domains as $domain) {
|
||||
$allowedOrigins[] = $domain;
|
||||
}
|
||||
} else {
|
||||
$allowedOrigins[] = env('APP_URL');
|
||||
}
|
||||
|
||||
$this->app->config->set('cors.paths.api/v1/*.allowedOrigins', $allowedOrigins);
|
||||
} catch (Exception $e) {
|
||||
// Don't throw any errors, we may not be setup yet.
|
||||
}
|
||||
|
||||
// Override default app values.
|
||||
$this->app->config->set('app.url', $appDomain ?: $this->app->config->get('app.url'));
|
||||
$this->app->config->set('app.locale', $appLocale ?: $this->app->config->get('app.locale'));
|
||||
|
||||
// Set custom lang.
|
||||
$this->app->translator->setLocale($appLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->bindShared('setting', function () {
|
||||
return new Repository(new SettingModel());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,34 +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\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The event handler mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $listen = [
|
||||
'CachetHQ\Cachet\Events\CustomerHasSubscribedEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\SendSubscriberVerificationEmailHandler',
|
||||
],
|
||||
'CachetHQ\Cachet\Events\IncidentHasReportedEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\SendIncidentEmailNotificationHandler',
|
||||
],
|
||||
'CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\SendMaintenanceEmailNotificationHandler',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -1,69 +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\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Routing\Router;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* This namespace is applied to the controller routes in your routes file.
|
||||
*
|
||||
* In addition, it is set as the URL generator's root namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'CachetHQ\Cachet\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Define the route model bindings, pattern filters, etc.
|
||||
*
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
*/
|
||||
public function boot(Router $router)
|
||||
{
|
||||
parent::boot($router);
|
||||
|
||||
$this->registerBindings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register model bindings.
|
||||
*/
|
||||
protected function registerBindings()
|
||||
{
|
||||
$this->app->router->model('component', 'CachetHQ\Cachet\Models\Component');
|
||||
$this->app->router->model('component_group', 'CachetHQ\Cachet\Models\ComponentGroup');
|
||||
$this->app->router->model('incident', 'CachetHQ\Cachet\Models\Incident');
|
||||
$this->app->router->model('incident_template', 'CachetHQ\Cachet\Models\IncidentTemplate');
|
||||
$this->app->router->model('metric', 'CachetHQ\Cachet\Models\Metric');
|
||||
$this->app->router->model('metric_point', 'CachetHQ\Cachet\Models\MetricPoint');
|
||||
$this->app->router->model('setting', 'CachetHQ\Cachet\Models\Setting');
|
||||
$this->app->router->model('subscriber', 'CachetHQ\Cachet\Models\Subscriber');
|
||||
$this->app->router->model('user', 'CachetHQ\Cachet\Models\User');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
*/
|
||||
public function map(Router $router)
|
||||
{
|
||||
$router->group(['namespace' => $this->namespace], function (Router $router) {
|
||||
foreach (glob(app_path('Http//Routes').'/*.php') as $file) {
|
||||
$this->app->make('CachetHQ\\Cachet\\Http\\Routes\\'.basename($file, '.php'))->map($router);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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\Services;
|
||||
|
||||
use CachetHQ\Cachet\User;
|
||||
use Illuminate\Contracts\Auth\Registrar as RegistrarContract;
|
||||
use Validator;
|
||||
|
||||
class Registrar implements RegistrarContract
|
||||
{
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
public function validator(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'name' => 'required|max:255',
|
||||
'email' => 'required|email|max:255|unique:users',
|
||||
'password' => 'required|confirmed|min:6',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
return User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => bcrypt($data['password']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
78
resources/assets/js/app.js → app/assets/js/app.js
Executable file → Normal file
78
resources/assets/js/app.js → app/assets/js/app.js
Executable file → Normal file
@@ -5,18 +5,12 @@ $(function() {
|
||||
if (! options.crossDomain) {
|
||||
token = $('meta[name="token"]').attr('content');
|
||||
if (token) {
|
||||
jqXHR.setRequestHeader('X-CSRF-Token', token);
|
||||
return jqXHR.setRequestHeader('X-CSRF-Token', token);
|
||||
}
|
||||
}
|
||||
|
||||
return jqXHR;
|
||||
});
|
||||
|
||||
$.ajaxSetup({
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
// xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
|
||||
},
|
||||
statusCode: {
|
||||
401: function () {
|
||||
window.location.href = '/';
|
||||
@@ -132,21 +126,6 @@ $(function() {
|
||||
}
|
||||
});
|
||||
|
||||
$('input[rel=datepicker-any]').datetimepicker({
|
||||
format: "DD/MM/YYYY HH:mm",
|
||||
sideBySide: true,
|
||||
icons: {
|
||||
time: 'ion-clock',
|
||||
date: 'ion-android-calendar',
|
||||
up: 'ion-ios-arrow-up',
|
||||
down: 'ion-ios-arrow-down',
|
||||
previous: 'ion-ios-arrow-left',
|
||||
next: 'ion-ios-arrow-right',
|
||||
today: 'ion-android-home',
|
||||
clear: 'ion-trash-a',
|
||||
}
|
||||
});
|
||||
|
||||
// Sortable components.
|
||||
var componentList = document.getElementById("component-list");
|
||||
if (componentList) {
|
||||
@@ -154,51 +133,21 @@ $(function() {
|
||||
group: "omega",
|
||||
handle: ".drag-handle",
|
||||
onUpdate: function() {
|
||||
var orderedComponentIds = $.map($('#component-list .striped-list-item'), function(elem) {
|
||||
return $(elem).data('component-id');
|
||||
// Loop each component, setting the order input to the new order.
|
||||
var $components = $('#component-list .striped-list-item');
|
||||
$.each($components, function(id) {
|
||||
// Order should start from 1 now.
|
||||
$(this).find('input[rel=order]').val(id + 1);
|
||||
});
|
||||
|
||||
// Now POST the form to the internal API.
|
||||
$.ajax({
|
||||
async: true,
|
||||
url: '/dashboard/api/components/order',
|
||||
type: 'POST',
|
||||
data: {
|
||||
ids: orderedComponentIds
|
||||
},
|
||||
data: $('form[name=componentList]').serializeObject(),
|
||||
success: function() {
|
||||
(new CachetHQ.Notifier()).notify('Component orders updated.', 'success');
|
||||
},
|
||||
error: function() {
|
||||
(new CachetHQ.Notifier()).notify('Component orders not updated.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Sortable Component Groups
|
||||
var componentGroupList = document.getElementById("component-group-list");
|
||||
if (componentGroupList) {
|
||||
new Sortable(componentGroupList, {
|
||||
group: "omega",
|
||||
handle: ".drag-handle",
|
||||
onUpdate: function() {
|
||||
var orderedComponentGroupsIds = $.map(
|
||||
$('#component-group-list .striped-list-item'),
|
||||
function(elem) {
|
||||
return $(elem).data('group-id');
|
||||
}
|
||||
);
|
||||
$.ajax({
|
||||
async: true,
|
||||
url: '/dashboard/api/components/groups/order',
|
||||
type: 'POST',
|
||||
data: {ids: orderedComponentGroupsIds},
|
||||
success: function() {
|
||||
(new CachetHQ.Notifier()).notify('Component groups order has been updated.', 'success');
|
||||
},
|
||||
error: function() {
|
||||
(new CachetHQ.Notifier()).notify('Component groups order could not be updated.', 'error');
|
||||
(new CachetHQ.Notifier()).notify('Components updated.', 'success');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -233,6 +182,7 @@ $(function() {
|
||||
if (slug) {
|
||||
$.ajax({
|
||||
async: true,
|
||||
dataType: 'json',
|
||||
data: {
|
||||
slug: slug
|
||||
},
|
||||
@@ -255,14 +205,6 @@ $(function() {
|
||||
$('input[name=remove_banner]').val('1');
|
||||
});
|
||||
|
||||
$('.group-name').on('click', function () {
|
||||
var $this = $(this);
|
||||
|
||||
$this.find('.group-toggle').toggleClass('ion-ios-minus-outline').toggleClass('ion-ios-plus-outline');
|
||||
|
||||
$this.next('.group-items').toggleClass('hide');
|
||||
});
|
||||
|
||||
// Setup wizard
|
||||
$('.wizard-next').on('click', function () {
|
||||
var $form = $('#setup-form'),
|
||||
0
resources/assets/sass/_errors.scss → app/assets/sass/_errors.scss
Executable file → Normal file
0
resources/assets/sass/_errors.scss → app/assets/sass/_errors.scss
Executable file → Normal file
0
resources/assets/sass/_helpers.scss → app/assets/sass/_helpers.scss
Executable file → Normal file
0
resources/assets/sass/_helpers.scss → app/assets/sass/_helpers.scss
Executable file → Normal file
0
resources/assets/sass/_palette.scss → app/assets/sass/_palette.scss
Executable file → Normal file
0
resources/assets/sass/_palette.scss → app/assets/sass/_palette.scss
Executable file → Normal file
132
resources/assets/sass/_status-page.scss → app/assets/sass/_status-page.scss
Executable file → Normal file
132
resources/assets/sass/_status-page.scss → app/assets/sass/_status-page.scss
Executable file → Normal file
@@ -1,5 +1,4 @@
|
||||
body.status-page {
|
||||
padding-top: 40px;
|
||||
font-family: $base-font-family;
|
||||
background-color: #F0F3F4;
|
||||
color: #333333;
|
||||
@@ -45,6 +44,8 @@ body.status-page {
|
||||
|
||||
.container {
|
||||
max-width: 960px;
|
||||
margin-bottom: 40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
@@ -64,8 +65,25 @@ body.status-page {
|
||||
}
|
||||
|
||||
.alert {
|
||||
border-radius: 0;
|
||||
font-size: 1.2em;
|
||||
font-weight: 600;
|
||||
&.alert-success {
|
||||
background-color: $cachet_green;
|
||||
border-color: $cachet_dark-green;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&.alert-info {
|
||||
background: $cachet_blue;
|
||||
border-color: $cachet_dark-blue;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
&.alert-danger {
|
||||
background: $cachet_red;
|
||||
border-color: $cachet_dark-red;
|
||||
color: #FFF;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline {
|
||||
@@ -121,8 +139,8 @@ body.status-page {
|
||||
position: relative;
|
||||
&.first {
|
||||
&:before {
|
||||
// height: 130%;
|
||||
top: -5px;
|
||||
height: 130%;
|
||||
top: -20px;
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
@@ -139,7 +157,7 @@ body.status-page {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 26px;
|
||||
top: -5px;
|
||||
top: 5px;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: #7266BA;
|
||||
@@ -216,30 +234,12 @@ body.status-page {
|
||||
}
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
strong {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
border-top: 1px solid #eee;
|
||||
p {
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
box-sizing: border-box;
|
||||
|
||||
&.emoji {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: middle;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
font-size: 1em;
|
||||
// font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,9 +252,9 @@ body.status-page {
|
||||
}
|
||||
|
||||
.list-group {
|
||||
// margin-bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
padding-left: 0;
|
||||
// border-radius: 0;
|
||||
border-radius: 0;
|
||||
|
||||
.list-group-item {
|
||||
border-radius: 0;
|
||||
@@ -285,87 +285,39 @@ body.status-page {
|
||||
top: 0.6em;
|
||||
bottom: 0.6em;
|
||||
}
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&.sub-component {
|
||||
&:before {
|
||||
@extend .ion;
|
||||
content: $ionicon-var-ios-plus-outline;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.break {
|
||||
padding: 1px;
|
||||
background-color: $cachet-base-medium;
|
||||
background-color: $cachet_gray_light;
|
||||
}
|
||||
}
|
||||
|
||||
&.components {
|
||||
@extend .panel;
|
||||
border-color: $cachet_gray_light;
|
||||
margin-bottom: 30px;
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.badge {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $cachet-base-dark !important;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
height: 60px;
|
||||
padding: 40px 0 60px 0;
|
||||
footer.footer {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
color: #777;
|
||||
text-align: center;
|
||||
border-top: 1px solid $cachet_gray_light;
|
||||
background-color: lighten($cachet_gray_light, 5%);
|
||||
color: $cachet-gray-darker;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
|
||||
.icons {
|
||||
a.icon-link {
|
||||
display: inline-block;
|
||||
min-width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 3px;
|
||||
background-color: $cachet-gray-darker;
|
||||
text-align: center;
|
||||
color: $cachet_gray_light;
|
||||
transition: all 0.15s;
|
||||
padding: 0 10px 0 10px;
|
||||
|
||||
&.rss {
|
||||
background-color: $cachet-orange;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
background-color: darken($cachet-gray-darker, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
text-align: left;
|
||||
|
||||
.icons {
|
||||
margin-top: 0;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Individual section styling.
|
||||
.section-timeline, .section-components, .section-metrics, .section-scheduled {
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
16
resources/assets/sass/app.scss → app/assets/sass/main.scss
Executable file → Normal file
16
resources/assets/sass/app.scss → app/assets/sass/main.scss
Executable file → Normal file
@@ -1,19 +1,12 @@
|
||||
@import "palette";
|
||||
|
||||
$ionicons-font-path: "../../../fonts" !default;
|
||||
@import "./vendor/bower_components/ionicons/scss/ionicons";
|
||||
@import "../bower_components/ionicons/scss/ionicons";
|
||||
|
||||
@import "modules/bootstrap";
|
||||
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
body {
|
||||
margin-bottom: 60px;
|
||||
padding-bottom: 60px;
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@import "helpers";
|
||||
@@ -22,9 +15,6 @@ body {
|
||||
@import "modules/tabs";
|
||||
@import "modules/forms";
|
||||
@import "modules/well";
|
||||
@import "modules/alerts";
|
||||
@import "modules/panels";
|
||||
@import "modules/btns";
|
||||
|
||||
// Styles for partials
|
||||
@import "partials/base";
|
||||
52
app/assets/sass/modules/_bootstrap.scss
Normal file
52
app/assets/sass/modules/_bootstrap.scss
Normal file
@@ -0,0 +1,52 @@
|
||||
// Bootstrap variable overrides and custom variables
|
||||
@import "variables";
|
||||
|
||||
// Core variables and mixins
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/variables";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/mixins";
|
||||
|
||||
// Reset and dependencies
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/normalize";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/print";
|
||||
|
||||
// Core CSS
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/scaffolding";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/type";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/code";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/grid";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tables";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/forms";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/buttons";
|
||||
|
||||
// Components
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/component-animations";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/dropdowns";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/button-groups";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/input-groups";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navs";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navbar";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pagination";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pager";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/labels";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/badges";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/jumbotron";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/thumbnails";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/alerts";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/progress-bars";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/media";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/list-group";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/panels";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/wells";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/close";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/modals";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tooltip";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/popovers";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/carousel";
|
||||
|
||||
// Utility classes
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/utilities";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-utilities";
|
||||
0
resources/assets/sass/modules/_forms.scss → app/assets/sass/modules/_forms.scss
Executable file → Normal file
0
resources/assets/sass/modules/_forms.scss → app/assets/sass/modules/_forms.scss
Executable file → Normal file
0
resources/assets/sass/modules/_tabs.scss → app/assets/sass/modules/_tabs.scss
Executable file → Normal file
0
resources/assets/sass/modules/_tabs.scss → app/assets/sass/modules/_tabs.scss
Executable file → Normal file
2
resources/assets/sass/modules/_variables.scss → app/assets/sass/modules/_variables.scss
Executable file → Normal file
2
resources/assets/sass/modules/_variables.scss → app/assets/sass/modules/_variables.scss
Executable file → Normal file
@@ -15,7 +15,7 @@ $tooltip-bg: #333 !default;
|
||||
$tooltip-opacity: .9 !default;
|
||||
$base-background-color: #f1f1f1;
|
||||
|
||||
$base-font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
|
||||
$base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
|
||||
$base-font-weight: 400;
|
||||
$base-letter-spacing: 0.08em;
|
||||
$base-font-size: 15px;
|
||||
0
resources/assets/sass/modules/_well.scss → app/assets/sass/modules/_well.scss
Executable file → Normal file
0
resources/assets/sass/modules/_well.scss → app/assets/sass/modules/_well.scss
Executable file → Normal file
0
resources/assets/sass/pages/_dashboard.scss → app/assets/sass/pages/_dashboard.scss
Executable file → Normal file
0
resources/assets/sass/pages/_dashboard.scss → app/assets/sass/pages/_dashboard.scss
Executable file → Normal file
18
app/assets/sass/pages/_login.scss
Normal file
18
app/assets/sass/pages/_login.scss
Normal file
@@ -0,0 +1,18 @@
|
||||
.login {
|
||||
padding-top: 90px;
|
||||
}
|
||||
|
||||
.login .logo {
|
||||
display: block;
|
||||
margin: 0 auto 30px;
|
||||
}
|
||||
|
||||
.login legend {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin: 0 0 30px 0;
|
||||
}
|
||||
2
resources/assets/sass/pages/_setup.scss → app/assets/sass/pages/_setup.scss
Executable file → Normal file
2
resources/assets/sass/pages/_setup.scss → app/assets/sass/pages/_setup.scss
Executable file → Normal file
@@ -10,7 +10,7 @@
|
||||
border-radius: 2px 2px 0 0;
|
||||
margin-bottom: 20px;
|
||||
.step {
|
||||
@extend .col-xs-3;
|
||||
@extend .col-xs-4;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
2
resources/assets/sass/partials/_base.scss → app/assets/sass/partials/_base.scss
Executable file → Normal file
2
resources/assets/sass/partials/_base.scss → app/assets/sass/partials/_base.scss
Executable file → Normal file
@@ -2,7 +2,7 @@ body.dashboard {
|
||||
font-family: $base-font-family;
|
||||
font-weight: $base-font-weight;
|
||||
font-size: $base-font-size;
|
||||
// letter-spacing: $base-letter-spacing;
|
||||
letter-spacing: $base-letter-spacing;
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
0
resources/assets/sass/partials/_content.scss → app/assets/sass/partials/_content.scss
Executable file → Normal file
0
resources/assets/sass/partials/_content.scss → app/assets/sass/partials/_content.scss
Executable file → Normal file
0
resources/assets/sass/partials/_modals.scss → app/assets/sass/partials/_modals.scss
Executable file → Normal file
0
resources/assets/sass/partials/_modals.scss → app/assets/sass/partials/_modals.scss
Executable file → Normal file
2
resources/assets/sass/partials/_navbar.scss → app/assets/sass/partials/_navbar.scss
Executable file → Normal file
2
resources/assets/sass/partials/_navbar.scss → app/assets/sass/partials/_navbar.scss
Executable file → Normal file
@@ -30,7 +30,7 @@ body.dashboard {
|
||||
letter-spacing: 0.04em;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
@media (min-width: $screen-sm-max) {
|
||||
@media #{$screen-sm-max} {
|
||||
span {
|
||||
padding-right: 10px;
|
||||
&:before {
|
||||
36
resources/assets/sass/partials/_sidebar.scss → app/assets/sass/partials/_sidebar.scss
Executable file → Normal file
36
resources/assets/sass/partials/_sidebar.scss → app/assets/sass/partials/_sidebar.scss
Executable file → Normal file
@@ -39,23 +39,16 @@ body.dashboard {
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
.username-wrapper {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
&.username {
|
||||
word-break: break-all;
|
||||
color: $sidebar-text-color;
|
||||
.profile {
|
||||
&.username {
|
||||
word-break: break-all;
|
||||
color: $sidebar-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.quick-add-incident {
|
||||
@extend .text-center;
|
||||
padding: 10px;
|
||||
i {
|
||||
@extend .visible-sm;
|
||||
}
|
||||
span {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
clear: both;
|
||||
@@ -111,14 +104,8 @@ body.dashboard {
|
||||
}
|
||||
}
|
||||
}
|
||||
& > ul > li > a {
|
||||
& > span {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-menu-sidebar {
|
||||
@extend .hidden-sm;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 230px;
|
||||
@@ -161,21 +148,34 @@ body.dashboard {
|
||||
.profile .avatar img {
|
||||
width: 40px;
|
||||
}
|
||||
.profile .username-wrapper {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
.quick-add-incident {
|
||||
.btn {
|
||||
padding: 3px 6px;
|
||||
}
|
||||
i {
|
||||
@extend .visible-sm;
|
||||
font-size: 20px;
|
||||
}
|
||||
span {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
}
|
||||
& > ul > li > a {
|
||||
text-align: center;
|
||||
& > i {
|
||||
font-size: 25px;
|
||||
}
|
||||
& > span {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-menu-sidebar {
|
||||
@extend .hidden-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0
resources/assets/sass/partials/_variables.scss → app/assets/sass/partials/_variables.scss
Executable file → Normal file
0
resources/assets/sass/partials/_variables.scss → app/assets/sass/partials/_variables.scss
Executable file → Normal file
0
resources/assets/sass/partials/_wrapper.scss → app/assets/sass/partials/_wrapper.scss
Executable file → Normal file
0
resources/assets/sass/partials/_wrapper.scss → app/assets/sass/partials/_wrapper.scss
Executable file → Normal file
2
resources/assets/sass/plugins/_animate.scss → app/assets/sass/plugins/_animate.scss
Executable file → Normal file
2
resources/assets/sass/plugins/_animate.scss → app/assets/sass/plugins/_animate.scss
Executable file → Normal file
@@ -1,4 +1,4 @@
|
||||
@import "./vendor/bower_components/animate-sass/animate";
|
||||
@import "../../bower_components/animate-sass/animate";
|
||||
|
||||
body {
|
||||
-webkit-backface-visibility: hidden; // Addresses a small issue in webkit: http://bit.ly/NEdoDq
|
||||
0
resources/assets/sass/plugins/_messenger.scss → app/assets/sass/plugins/_messenger.scss
Executable file → Normal file
0
resources/assets/sass/plugins/_messenger.scss → app/assets/sass/plugins/_messenger.scss
Executable file → Normal file
301
app/assets/sass/plugins/bootstrap-datetimepicker/bootstrap-datetimepicker.scss
vendored
Normal file
301
app/assets/sass/plugins/bootstrap-datetimepicker/bootstrap-datetimepicker.scss
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
// Import boostrap variables including default color palette and fonts
|
||||
@import "../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/_variables";
|
||||
|
||||
.bootstrap-datetimepicker-widget {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 250px;
|
||||
padding: 4px;
|
||||
margin-top: 1px;
|
||||
z-index: 99999 !important;
|
||||
border-radius: $border-radius-base;
|
||||
|
||||
&.timepicker-sbs {
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-bottom-color: rgba(0,0,0,.2);
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid white;
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.top {
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-top: 7px solid #ccc;
|
||||
border-top-color: rgba(0,0,0,.2);
|
||||
position: absolute;
|
||||
bottom: -7px;
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-top: 6px solid white;
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
left: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
& .dow {
|
||||
width: 14.2857%;
|
||||
}
|
||||
|
||||
&.pull-right {
|
||||
&:before {
|
||||
left: auto;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: auto;
|
||||
right: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
>ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a[data-action] {
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
a[data-action]:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.timepicker-hour, .timepicker-minute, .timepicker-second {
|
||||
width: 54px;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button[data-action] {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
table[data-hour-format="12"] .separator {
|
||||
width: 4px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.datepicker > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.picker-switch {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
text-align: center;
|
||||
border-radius: $border-radius-base;
|
||||
}
|
||||
|
||||
td {
|
||||
height: 54px;
|
||||
line-height: 54px;
|
||||
width: 54px;
|
||||
|
||||
&.cw {
|
||||
font-size: 10px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
color: $gray-light;
|
||||
}
|
||||
|
||||
&.day {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
&.day:hover,
|
||||
&.hour:hover,
|
||||
&.minute:hover,
|
||||
&.second:hover {
|
||||
background: $gray-lighter;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.old,
|
||||
&.new {
|
||||
color: $gray-light;
|
||||
}
|
||||
|
||||
&.today {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom: 7px solid $btn-primary-bg;
|
||||
border-top-color: rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&.active,
|
||||
&.active:hover {
|
||||
background-color: $btn-primary-bg;
|
||||
color: $btn-primary-color;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
|
||||
}
|
||||
|
||||
&.active.today:before {
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:hover {
|
||||
background: none;
|
||||
color: $gray-light;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
line-height: 54px;
|
||||
margin: 2px 1.5px;
|
||||
cursor: pointer;
|
||||
border-radius: $border-radius-base;
|
||||
|
||||
&:hover {
|
||||
background: $gray-lighter;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $btn-primary-bg;
|
||||
color: $btn-primary-color;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
|
||||
}
|
||||
|
||||
&.old {
|
||||
color: $gray-light;
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:hover {
|
||||
background: none;
|
||||
color: $gray-light;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
th {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 20px;
|
||||
|
||||
&.picker-switch {
|
||||
width: 145px;
|
||||
}
|
||||
|
||||
&.next,
|
||||
&.prev {
|
||||
font-size: $font-size-base * 1.5;
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:hover {
|
||||
background: none;
|
||||
color: $gray-light;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
thead tr:first-child th {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: $gray-lighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group {
|
||||
&.date {
|
||||
.input-group-addon span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget.left-oriented {
|
||||
&:before {
|
||||
left: auto;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: auto;
|
||||
right: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody > tr > td {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.bootstrap-datetimepicker-widget.timepicker-sbs {
|
||||
width: 283px;
|
||||
}
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
border: 0;
|
||||
}
|
||||
@@ -1,14 +1,5 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@@ -22,7 +13,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => env('APP_DEBUG', false),
|
||||
'debug' => getenv('APP_DEBUG') ?: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -35,7 +26,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
'url' => 'http://localhost',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -61,7 +52,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'locale' => env('APP_LOCALE', 'en'),
|
||||
'locale' => 'en',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -87,24 +78,9 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('APP_KEY', 'SomeRandomString'),
|
||||
'key' => 'kCifbUiHYswooAvSZBQjWZVY1S6aBdnD',
|
||||
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logging Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log settings for your application. Out of
|
||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Settings: "single", "daily", "syslog", "errorlog"
|
||||
|
|
||||
*/
|
||||
|
||||
'log' => env('LOGGING_MODE', 'daily'),
|
||||
'cipher' => MCRYPT_RIJNDAEL_128,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -124,23 +100,24 @@ return [
|
||||
*/
|
||||
'Illuminate\Foundation\Providers\ArtisanServiceProvider',
|
||||
'Illuminate\Auth\AuthServiceProvider',
|
||||
'Illuminate\Broadcasting\BroadcastServiceProvider',
|
||||
'Illuminate\Bus\BusServiceProvider',
|
||||
'Illuminate\Cache\CacheServiceProvider',
|
||||
'Illuminate\Session\CommandsServiceProvider',
|
||||
'Illuminate\Foundation\Providers\ConsoleSupportServiceProvider',
|
||||
'Illuminate\Routing\ControllerServiceProvider',
|
||||
'Illuminate\Cookie\CookieServiceProvider',
|
||||
'Illuminate\Database\DatabaseServiceProvider',
|
||||
'Illuminate\Encryption\EncryptionServiceProvider',
|
||||
'Illuminate\Filesystem\FilesystemServiceProvider',
|
||||
'Illuminate\Foundation\Providers\FoundationServiceProvider',
|
||||
'Illuminate\Hashing\HashServiceProvider',
|
||||
'Illuminate\Html\HtmlServiceProvider',
|
||||
'Illuminate\Log\LogServiceProvider',
|
||||
'Illuminate\Mail\MailServiceProvider',
|
||||
'Illuminate\Database\MigrationServiceProvider',
|
||||
'Illuminate\Pagination\PaginationServiceProvider',
|
||||
'Illuminate\Pipeline\PipelineServiceProvider',
|
||||
'Illuminate\Queue\QueueServiceProvider',
|
||||
'Illuminate\Redis\RedisServiceProvider',
|
||||
'Illuminate\Auth\Passwords\PasswordResetServiceProvider',
|
||||
'Illuminate\Auth\Reminders\ReminderServiceProvider',
|
||||
'Illuminate\Database\SeedServiceProvider',
|
||||
'Illuminate\Session\SessionServiceProvider',
|
||||
'Illuminate\Translation\TranslationServiceProvider',
|
||||
'Illuminate\Validation\ValidationServiceProvider',
|
||||
@@ -149,11 +126,9 @@ return [
|
||||
/*
|
||||
* Packages Service Providers...
|
||||
*/
|
||||
'AltThree\Emoji\EmojiServiceProvider',
|
||||
'Barryvdh\Cors\CorsServiceProvider',
|
||||
'Fideloper\Proxy\TrustedProxyServiceProvider',
|
||||
'Dingo\Api\Provider\ApiServiceProvider',
|
||||
'Fideloper\Proxy\ProxyServiceProvider',
|
||||
'GrahamCampbell\Binput\BinputServiceProvider',
|
||||
'GrahamCampbell\Exceptions\ExceptionsServiceProvider',
|
||||
'GrahamCampbell\Markdown\MarkdownServiceProvider',
|
||||
'GrahamCampbell\Security\SecurityServiceProvider',
|
||||
'GrahamCampbell\Throttle\ThrottleServiceProvider',
|
||||
@@ -161,19 +136,36 @@ return [
|
||||
'McCool\LaravelAutoPresenter\LaravelAutoPresenterServiceProvider',
|
||||
'PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider',
|
||||
'Roumen\Feed\FeedServiceProvider',
|
||||
'Thujohn\Rss\RssServiceProvider',
|
||||
|
||||
/*
|
||||
* Application Service Providers...
|
||||
*/
|
||||
'CachetHQ\Cachet\Providers\AppServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\ComposerServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\ConfigServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\AuthServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\ConsoleServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\EventServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\RouteServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\RepositoryServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\RoutingServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\ViewComposerServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\LoadConfigServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\SettingsServiceProvider',
|
||||
'CachetHQ\Cachet\Providers\SegmentApiServiceProvider',
|
||||
'CachetHQ\Segment\SegmentServiceProvider',
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Service Provider Manifest
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The service provider manifest is used by Laravel to lazy load service
|
||||
| providers which are not needed for each request, as well to keep a
|
||||
| list of all of the services. Here, you may set its storage spot.
|
||||
|
|
||||
*/
|
||||
|
||||
'manifest' => storage_path().'/meta',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Aliases
|
||||
@@ -187,41 +179,17 @@ return [
|
||||
|
||||
'aliases' => [
|
||||
|
||||
'App' => 'Illuminate\Support\Facades\App',
|
||||
'Artisan' => 'Illuminate\Support\Facades\Artisan',
|
||||
'Auth' => 'Illuminate\Support\Facades\Auth',
|
||||
'Blade' => 'Illuminate\Support\Facades\Blade',
|
||||
'Bus' => 'Illuminate\Support\Facades\Bus',
|
||||
'Cache' => 'Illuminate\Support\Facades\Cache',
|
||||
'Config' => 'Illuminate\Support\Facades\Config',
|
||||
'Cookie' => 'Illuminate\Support\Facades\Cookie',
|
||||
'Crypt' => 'Illuminate\Support\Facades\Crypt',
|
||||
'DB' => 'Illuminate\Support\Facades\DB',
|
||||
'Eloquent' => 'Illuminate\Database\Eloquent\Model',
|
||||
'Event' => 'Illuminate\Support\Facades\Event',
|
||||
'File' => 'Illuminate\Support\Facades\File',
|
||||
'Hash' => 'Illuminate\Support\Facades\Hash',
|
||||
'Input' => 'Illuminate\Support\Facades\Input',
|
||||
'Inspiring' => 'Illuminate\Foundation\Inspiring',
|
||||
'Lang' => 'Illuminate\Support\Facades\Lang',
|
||||
'Log' => 'Illuminate\Support\Facades\Log',
|
||||
'Mail' => 'Illuminate\Support\Facades\Mail',
|
||||
'Password' => 'Illuminate\Support\Facades\Password',
|
||||
'Queue' => 'Illuminate\Support\Facades\Queue',
|
||||
'Redirect' => 'Illuminate\Support\Facades\Redirect',
|
||||
'Redis' => 'Illuminate\Support\Facades\Redis',
|
||||
'Request' => 'Illuminate\Support\Facades\Request',
|
||||
'Response' => 'Illuminate\Support\Facades\Response',
|
||||
'Route' => 'Illuminate\Support\Facades\Route',
|
||||
'Schema' => 'Illuminate\Support\Facades\Schema',
|
||||
'Session' => 'Illuminate\Support\Facades\Session',
|
||||
'Storage' => 'Illuminate\Support\Facades\Storage',
|
||||
'URL' => 'Illuminate\Support\Facades\URL',
|
||||
'Validator' => 'Illuminate\Support\Facades\Validator',
|
||||
'View' => 'Illuminate\Support\Facades\View',
|
||||
|
||||
'Setting' => 'CachetHQ\Cachet\Facades\Setting',
|
||||
'Str' => 'Illuminate\Support\Str',
|
||||
'App' => 'Illuminate\Support\Facades\App',
|
||||
'Auth' => 'Illuminate\Support\Facades\Auth',
|
||||
'Form' => 'Illuminate\Support\Facades\Form',
|
||||
'Input' => 'Illuminate\Support\Facades\Input',
|
||||
'Redirect' => 'Illuminate\Support\Facades\Redirect',
|
||||
'Request' => 'Illuminate\Support\Facades\Request',
|
||||
'Response' => 'Illuminate\Support\Facades\Response',
|
||||
'Route' => 'Illuminate\Support\Facades\Route',
|
||||
'Session' => 'Illuminate\Support\Facades\Session',
|
||||
'Setting' => 'CachetHQ\Cachet\Facades\Setting',
|
||||
'Str' => 'Illuminate\Support\Str',
|
||||
|
||||
],
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@@ -54,23 +45,27 @@ return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Settings
|
||||
| Password Reminder Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may set the options for resetting passwords including the view
|
||||
| that is your password reset e-mail. You can also set the name of the
|
||||
| table that maintains all of the reset tokens for your application.
|
||||
| Here you may set the settings for password reminders, including a view
|
||||
| that should be used as your password reminder e-mail. You will also
|
||||
| be able to set the name of the table that holds the reset tokens.
|
||||
|
|
||||
| The expire time is the number of minutes that the reset token should be
|
||||
| The "expire" time is the number of minutes that the reminder should be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => [
|
||||
'email' => 'emails.password',
|
||||
'table' => 'password_resets',
|
||||
'reminder' => [
|
||||
|
||||
'email' => 'emails.auth.reminder',
|
||||
|
||||
'table' => 'password_reminders',
|
||||
|
||||
'expire' => 60,
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
89
app/config/cache.php
Normal file
89
app/config/cache.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache "driver" that will be used when
|
||||
| using the Caching library. Of course, you may use other drivers any
|
||||
| time you wish. This is the default when another is not specified.
|
||||
|
|
||||
| Supported: "file", "database", "apc", "memcached", "redis", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => getenv('CACHE_DRIVER') ?: 'apc',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| File Cache Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "file" cache driver, we need a location where the cache
|
||||
| files may be stored. A sensible default has been specified, but you
|
||||
| are free to change it to any other place on disk that you desire.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => storage_path().'/cache',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Cache Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" cache driver you may specify the connection
|
||||
| that should be used to store the cached items. When this option is
|
||||
| null the default database connection will be utilized for cache.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Cache Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" cache driver we need to know the table that
|
||||
| should be used to store the cached items. A default table name has
|
||||
| been provided but you're free to change it however you deem fit.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => 'cache',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Memcached Servers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Now you may specify an array of your Memcached servers that should be
|
||||
| used when utilizing the Memcached cache driver. All of the servers
|
||||
| should contain a value for "host", "port", and "weight" options.
|
||||
|
|
||||
*/
|
||||
|
||||
'memcached' => [
|
||||
|
||||
['host' => '127.0.0.1', 'port' => 11211, 'weight' => 100],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing a RAM based store such as APC or Memcached, there might
|
||||
| be other applications utilizing the same cache. So, we'll specify a
|
||||
| value to get prefixed to all our keys so we can avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => 'laravel',
|
||||
|
||||
];
|
||||
16
app/config/compile.php
Normal file
16
app/config/compile.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Additional Compiled Classes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify additional classes to include in the compiled file
|
||||
| generated by the `artisan optimize` command. These should be classes
|
||||
| that are included on basically every request into the application.
|
||||
|
|
||||
*/
|
||||
|
||||
];
|
||||
@@ -1,14 +1,5 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@@ -35,7 +26,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DB_DRIVER', 'sqlite'),
|
||||
'default' => getenv('DB_DRIVER') ?: 'sqlite',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -57,40 +48,39 @@ return [
|
||||
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'database' => env('DB_HOST', storage_path().'/database.sqlite'),
|
||||
'database' => app_path('database').'/'.getenv('DB_DATABASE') ?: null,
|
||||
'prefix' => '',
|
||||
],
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'host' => env('DB_HOST', null),
|
||||
'database' => env('DB_DATABASE', null),
|
||||
'username' => env('DB_USERNAME', null),
|
||||
'password' => env('DB_PASSWORD', null),
|
||||
'host' => getenv('DB_HOST') ?: null,
|
||||
'database' => getenv('DB_DATABASE') ?: null,
|
||||
'username' => getenv('DB_USERNAME') ?: null,
|
||||
'password' => getenv('DB_PASSWORD') ?: null,
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
'strict' => false,
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'host' => env('DB_HOST', null),
|
||||
'database' => env('DB_DATABASE', null),
|
||||
'username' => env('DB_USERNAME', null),
|
||||
'password' => env('DB_PASSWORD', null),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'schema' => 'public',
|
||||
'driver' => 'pgsql',
|
||||
'host' => getenv('DB_HOST') ?: null,
|
||||
'database' => getenv('DB_DATABASE') ?: null,
|
||||
'username' => getenv('DB_USERNAME') ?: null,
|
||||
'password' => getenv('DB_PASSWORD') ?: null,
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'schema' => 'public',
|
||||
],
|
||||
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
'host' => env('DB_HOST', null),
|
||||
'database' => env('DB_DATABASE', null),
|
||||
'username' => env('DB_USERNAME', null),
|
||||
'password' => env('DB_PASSWORD', null),
|
||||
'prefix' => '',
|
||||
'driver' => 'sqlsrv',
|
||||
'host' => getenv('DB_HOST') ?: null,
|
||||
'database' => getenv('DB_DATABASE') ?: null,
|
||||
'username' => getenv('DB_USERNAME') ?: null,
|
||||
'password' => getenv('DB_PASSWORD') ?: null,
|
||||
'prefix' => '',
|
||||
],
|
||||
|
||||
],
|
||||
@@ -124,9 +114,9 @@ return [
|
||||
'cluster' => false,
|
||||
|
||||
'default' => [
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'port' => env('REDIS_PORT', 6379),
|
||||
'database' => env('REDIS_DATABASE', 0),
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'database' => 0,
|
||||
],
|
||||
|
||||
],
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user