diff --git a/.env.example b/.env.example
index 365288c..8264e86 100644
--- a/.env.example
+++ b/.env.example
@@ -22,9 +22,9 @@ DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
+QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
-QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 7e2563a..043cad6 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -29,8 +29,6 @@ class Handler extends ExceptionHandler
/**
* Report or log an exception.
*
- * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
- *
* @param \Exception $exception
* @return void
*/
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
index 0c6b5c0..787111e 100644
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -48,9 +48,9 @@ class RegisterController extends Controller {
protected function validator(array $data)
{
return Validator::make($data, [
- 'name' => 'required|string|max:255',
- 'email' => 'required|string|email|max:255|unique:users',
- 'password' => 'required|string|min:6|confirmed',
+ 'name' => ['required', 'string', 'max:255'],
+ 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
+ 'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
}
diff --git a/app/Http/Controllers/Auth/VerificationController.php b/app/Http/Controllers/Auth/VerificationController.php
new file mode 100644
index 0000000..23a43a8
--- /dev/null
+++ b/app/Http/Controllers/Auth/VerificationController.php
@@ -0,0 +1,41 @@
+middleware('auth');
+ $this->middleware('signed')->only('verify');
+ $this->middleware('throttle:6,1')->only('verify', 'resend');
+ }
+}
diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php
new file mode 100644
index 0000000..a4be5c5
--- /dev/null
+++ b/app/Http/Middleware/Authenticate.php
@@ -0,0 +1,21 @@
+expectsJson()) {
+ return route('login');
+ }
+ }
+}
diff --git a/app/Http/Middleware/CheckForMaintenanceMode.php b/app/Http/Middleware/CheckForMaintenanceMode.php
new file mode 100644
index 0000000..35b9824
--- /dev/null
+++ b/app/Http/Middleware/CheckForMaintenanceMode.php
@@ -0,0 +1,17 @@
+ [
- 'App\Listeners\EventListener',
+ Registered::class => [
+ SendEmailVerificationNotification::class,
],
];
diff --git a/bootstrap/app.php b/bootstrap/app.php
index f2801ad..c65a860 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -12,7 +12,7 @@
*/
$app = new Illuminate\Foundation\Application(
- realpath(__DIR__.'/../')
+ dirname(__DIR__)
);
/*
diff --git a/config/database.php b/config/database.php
index cab5d06..a4d20dd 100644
--- a/config/database.php
+++ b/config/database.php
@@ -37,6 +37,7 @@ return [
'driver' => 'sqlite',
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
+ 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
'mysql' => [
@@ -50,6 +51,7 @@ return [
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
+ 'prefix_indexes' => true,
'strict' => true,
'engine' => null,
],
@@ -63,6 +65,7 @@ return [
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
+ 'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
],
@@ -76,6 +79,7 @@ return [
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
+ 'prefix_indexes' => true,
],
],
@@ -112,7 +116,14 @@ return [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
- 'database' => 0,
+ 'database' => env('REDIS_DB', 0),
+ ],
+
+ 'cache' => [
+ 'host' => env('REDIS_HOST', '127.0.0.1'),
+ 'password' => env('REDIS_PASSWORD', null),
+ 'port' => env('REDIS_PORT', 6379),
+ 'database' => env('REDIS_CACHE_DB', 1),
],
],
diff --git a/config/hashing.php b/config/hashing.php
index f929cf0..8425770 100644
--- a/config/hashing.php
+++ b/config/hashing.php
@@ -11,10 +11,42 @@ return [
| passwords for your application. By default, the bcrypt algorithm is
| used; however, you remain free to modify this option if you wish.
|
- | Supported: "bcrypt", "argon"
+ | Supported: "bcrypt", "argon", "argon2id"
|
*/
'driver' => 'bcrypt',
+ /*
+ |--------------------------------------------------------------------------
+ | Bcrypt Options
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the configuration options that should be used when
+ | passwords are hashed using the Bcrypt algorithm. This will allow you
+ | to control the amount of time it takes to hash the given password.
+ |
+ */
+
+ 'bcrypt' => [
+ 'rounds' => env('BCRYPT_ROUNDS', 10),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Argon Options
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the configuration options that should be used when
+ | passwords are hashed using the Argon algorithm. These will allow you
+ | to control the amount of time it takes to hash the given password.
+ |
+ */
+
+ 'argon' => [
+ 'memory' => 1024,
+ 'threads' => 2,
+ 'time' => 2,
+ ],
+
];
diff --git a/config/logging.php b/config/logging.php
index 902efaf..506f2f3 100644
--- a/config/logging.php
+++ b/config/logging.php
@@ -1,5 +1,8 @@
[
'stack' => [
'driver' => 'stack',
- 'channels' => ['single'],
+ 'channels' => ['daily'],
],
'single' => [
@@ -45,7 +49,7 @@ return [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
- 'days' => 7,
+ 'days' => 14,
],
'slack' => [
@@ -56,6 +60,24 @@ return [
'level' => 'critical',
],
+ 'papertrail' => [
+ 'driver' => 'monolog',
+ 'level' => 'debug',
+ 'handler' => SyslogUdpHandler::class,
+ 'handler_with' => [
+ 'host' => env('PAPERTRAIL_URL'),
+ 'port' => env('PAPERTRAIL_PORT'),
+ ],
+ ],
+
+ 'stderr' => [
+ 'driver' => 'monolog',
+ 'handler' => StreamHandler::class,
+ 'with' => [
+ 'stream' => 'php://stderr',
+ ],
+ ],
+
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
diff --git a/config/queue.php b/config/queue.php
index 87b1b1b..c1430b4 100644
--- a/config/queue.php
+++ b/config/queue.php
@@ -4,18 +4,16 @@ return [
/*
|--------------------------------------------------------------------------
- | Default Queue Driver
+ | Default Queue Connection Name
|--------------------------------------------------------------------------
|
| Laravel's queue API supports an assortment of back-ends via a single
| API, giving you convenient access to each back-end using the same
- | syntax for each one. Here you may set the default queue driver.
- |
- | Supported: "sync", "database", "beanstalkd", "sqs", "redis", "null"
+ | syntax for every one. Here you may define a default connection.
|
*/
- 'default' => env('QUEUE_DRIVER', 'sync'),
+ 'default' => env('QUEUE_CONNECTION', 'sync'),
/*
|--------------------------------------------------------------------------
@@ -26,6 +24,8 @@ return [
| is used by your application. A default configuration has been added
| for each back-end shipped with Laravel. You are free to add more.
|
+ | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
+ |
*/
'connections' => [
@@ -60,7 +60,7 @@ return [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
- 'queue' => 'default',
+ 'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
diff --git a/config/services.php b/config/services.php
index 4460f0e..bb4d2ec 100644
--- a/config/services.php
+++ b/config/services.php
@@ -17,12 +17,13 @@ return [
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
+ 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
],
'ses' => [
'key' => env('SES_KEY'),
'secret' => env('SES_SECRET'),
- 'region' => 'us-east-1',
+ 'region' => env('SES_REGION', 'us-east-1'),
],
'sparkpost' => [
@@ -33,6 +34,10 @@ return [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
+ 'webhook' => [
+ 'secret' => env('STRIPE_WEBHOOK_SECRET'),
+ 'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
+ ],
],
];
diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php
index facf233..ec15e58 100644
--- a/database/factories/UserFactory.php
+++ b/database/factories/UserFactory.php
@@ -17,6 +17,7 @@ $factory->define(App\User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
+ 'email_verified_at' => now(),
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
'remember_token' => str_random(10),
];
diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php
index 99386f7..afe3e77 100644
--- a/database/seeds/DatabaseSeeder.php
+++ b/database/seeds/DatabaseSeeder.php
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder
{
/**
- * Run the database seeds.
+ * Seed the application's database.
*
* @return void
*/
diff --git a/phpunit.xml b/phpunit.xml
index bb9c4a7..9566b67 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -9,13 +9,13 @@
processIsolation="false"
stopOnFailure="false">
-
- ./tests/Feature
-
-
./tests/Unit
+
+
+ ./tests/Feature
+
@@ -24,8 +24,10 @@
+
+
+
-
diff --git a/public/svg/403.svg b/public/svg/403.svg
new file mode 100644
index 0000000..682aa98
--- /dev/null
+++ b/public/svg/403.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/svg/404.svg b/public/svg/404.svg
new file mode 100644
index 0000000..b6cd6f2
--- /dev/null
+++ b/public/svg/404.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/svg/500.svg b/public/svg/500.svg
new file mode 100644
index 0000000..9927e8d
--- /dev/null
+++ b/public/svg/500.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/svg/503.svg b/public/svg/503.svg
new file mode 100644
index 0000000..6ad1093
--- /dev/null
+++ b/public/svg/503.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php
index edc036d..35e5e88 100644
--- a/resources/lang/en/validation.php
+++ b/resources/lang/en/validation.php
@@ -13,80 +13,106 @@ return [
|
*/
- 'accepted' => 'The :attribute must be accepted.',
- 'active_url' => 'The :attribute is not a valid URL.',
- 'after' => 'The :attribute must be a date after :date.',
- 'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
- 'alpha' => 'The :attribute may only contain letters.',
- 'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
- 'alpha_num' => 'The :attribute may only contain letters and numbers.',
- 'array' => 'The :attribute must be an array.',
- 'before' => 'The :attribute must be a date before :date.',
- 'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
- 'between' => [
+ 'accepted' => 'The :attribute must be accepted.',
+ 'active_url' => 'The :attribute is not a valid URL.',
+ 'after' => 'The :attribute must be a date after :date.',
+ 'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
+ 'alpha' => 'The :attribute may only contain letters.',
+ 'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
+ 'alpha_num' => 'The :attribute may only contain letters and numbers.',
+ 'array' => 'The :attribute must be an array.',
+ 'before' => 'The :attribute must be a date before :date.',
+ 'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
+ 'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
- 'file' => 'The :attribute must be between :min and :max kilobytes.',
- 'string' => 'The :attribute must be between :min and :max characters.',
- 'array' => 'The :attribute must have between :min and :max items.',
+ 'file' => 'The :attribute must be between :min and :max kilobytes.',
+ 'string' => 'The :attribute must be between :min and :max characters.',
+ 'array' => 'The :attribute must have between :min and :max items.',
],
- 'boolean' => 'The :attribute field must be true or false.',
- 'confirmed' => 'The :attribute confirmation does not match.',
- 'date' => 'The :attribute is not a valid date.',
- 'date_format' => 'The :attribute does not match the format :format.',
- 'different' => 'The :attribute and :other must be different.',
- 'digits' => 'The :attribute must be :digits digits.',
- 'digits_between' => 'The :attribute must be between :min and :max digits.',
- 'dimensions' => 'The :attribute has invalid image dimensions.',
- 'distinct' => 'The :attribute field has a duplicate value.',
- 'email' => 'The :attribute must be a valid email address.',
- 'exists' => 'The selected :attribute is invalid.',
- 'file' => 'The :attribute must be a file.',
- 'filled' => 'The :attribute field must have a value.',
- 'image' => 'The :attribute must be an image.',
- 'in' => 'The selected :attribute is invalid.',
- 'in_array' => 'The :attribute field does not exist in :other.',
- 'integer' => 'The :attribute must be an integer.',
- 'ip' => 'The :attribute must be a valid IP address.',
- 'ipv4' => 'The :attribute must be a valid IPv4 address.',
- 'ipv6' => 'The :attribute must be a valid IPv6 address.',
- 'json' => 'The :attribute must be a valid JSON string.',
- 'max' => [
+ 'boolean' => 'The :attribute field must be true or false.',
+ 'confirmed' => 'The :attribute confirmation does not match.',
+ 'date' => 'The :attribute is not a valid date.',
+ 'date_format' => 'The :attribute does not match the format :format.',
+ 'different' => 'The :attribute and :other must be different.',
+ 'digits' => 'The :attribute must be :digits digits.',
+ 'digits_between' => 'The :attribute must be between :min and :max digits.',
+ 'dimensions' => 'The :attribute has invalid image dimensions.',
+ 'distinct' => 'The :attribute field has a duplicate value.',
+ 'email' => 'The :attribute must be a valid email address.',
+ 'exists' => 'The selected :attribute is invalid.',
+ 'file' => 'The :attribute must be a file.',
+ 'filled' => 'The :attribute field must have a value.',
+ 'gt' => [
+ 'numeric' => 'The :attribute must be greater than :value.',
+ 'file' => 'The :attribute must be greater than :value kilobytes.',
+ 'string' => 'The :attribute must be greater than :value characters.',
+ 'array' => 'The :attribute must have more than :value items.',
+ ],
+ 'gte' => [
+ 'numeric' => 'The :attribute must be greater than or equal :value.',
+ 'file' => 'The :attribute must be greater than or equal :value kilobytes.',
+ 'string' => 'The :attribute must be greater than or equal :value characters.',
+ 'array' => 'The :attribute must have :value items or more.',
+ ],
+ 'image' => 'The :attribute must be an image.',
+ 'in' => 'The selected :attribute is invalid.',
+ 'in_array' => 'The :attribute field does not exist in :other.',
+ 'integer' => 'The :attribute must be an integer.',
+ 'ip' => 'The :attribute must be a valid IP address.',
+ 'ipv4' => 'The :attribute must be a valid IPv4 address.',
+ 'ipv6' => 'The :attribute must be a valid IPv6 address.',
+ 'json' => 'The :attribute must be a valid JSON string.',
+ 'lt' => [
+ 'numeric' => 'The :attribute must be less than :value.',
+ 'file' => 'The :attribute must be less than :value kilobytes.',
+ 'string' => 'The :attribute must be less than :value characters.',
+ 'array' => 'The :attribute must have less than :value items.',
+ ],
+ 'lte' => [
+ 'numeric' => 'The :attribute must be less than or equal :value.',
+ 'file' => 'The :attribute must be less than or equal :value kilobytes.',
+ 'string' => 'The :attribute must be less than or equal :value characters.',
+ 'array' => 'The :attribute must not have more than :value items.',
+ ],
+ 'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
- 'file' => 'The :attribute may not be greater than :max kilobytes.',
- 'string' => 'The :attribute may not be greater than :max characters.',
- 'array' => 'The :attribute may not have more than :max items.',
+ 'file' => 'The :attribute may not be greater than :max kilobytes.',
+ 'string' => 'The :attribute may not be greater than :max characters.',
+ 'array' => 'The :attribute may not have more than :max items.',
],
- 'mimes' => 'The :attribute must be a file of type: :values.',
- 'mimetypes' => 'The :attribute must be a file of type: :values.',
- 'min' => [
+ 'mimes' => 'The :attribute must be a file of type: :values.',
+ 'mimetypes' => 'The :attribute must be a file of type: :values.',
+ 'min' => [
'numeric' => 'The :attribute must be at least :min.',
- 'file' => 'The :attribute must be at least :min kilobytes.',
- 'string' => 'The :attribute must be at least :min characters.',
- 'array' => 'The :attribute must have at least :min items.',
+ 'file' => 'The :attribute must be at least :min kilobytes.',
+ 'string' => 'The :attribute must be at least :min characters.',
+ 'array' => 'The :attribute must have at least :min items.',
],
- 'not_in' => 'The selected :attribute is invalid.',
- 'numeric' => 'The :attribute must be a number.',
- 'present' => 'The :attribute field must be present.',
- 'regex' => 'The :attribute format is invalid.',
- 'required' => 'The :attribute field is required.',
- 'required_if' => 'The :attribute field is required when :other is :value.',
- 'required_unless' => 'The :attribute field is required unless :other is in :values.',
- 'required_with' => 'The :attribute field is required when :values is present.',
- 'required_with_all' => 'The :attribute field is required when :values is present.',
- 'required_without' => 'The :attribute field is required when :values is not present.',
+ 'not_in' => 'The selected :attribute is invalid.',
+ 'not_regex' => 'The :attribute format is invalid.',
+ 'numeric' => 'The :attribute must be a number.',
+ 'present' => 'The :attribute field must be present.',
+ 'regex' => 'The :attribute format is invalid.',
+ 'required' => 'The :attribute field is required.',
+ 'required_if' => 'The :attribute field is required when :other is :value.',
+ 'required_unless' => 'The :attribute field is required unless :other is in :values.',
+ 'required_with' => 'The :attribute field is required when :values is present.',
+ 'required_with_all' => 'The :attribute field is required when :values are present.',
+ 'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
- 'same' => 'The :attribute and :other must match.',
- 'size' => [
+ 'same' => 'The :attribute and :other must match.',
+ 'size' => [
'numeric' => 'The :attribute must be :size.',
- 'file' => 'The :attribute must be :size kilobytes.',
- 'string' => 'The :attribute must be :size characters.',
- 'array' => 'The :attribute must contain :size items.',
+ 'file' => 'The :attribute must be :size kilobytes.',
+ 'string' => 'The :attribute must be :size characters.',
+ 'array' => 'The :attribute must contain :size items.',
],
- 'string' => 'The :attribute must be a string.',
- 'timezone' => 'The :attribute must be a valid zone.',
- 'unique' => 'The :attribute has already been taken.',
- 'uploaded' => 'The :attribute failed to upload.',
- 'url' => 'The :attribute format is invalid.',
+ 'string' => 'The :attribute must be a string.',
+ 'timezone' => 'The :attribute must be a valid zone.',
+ 'unique' => 'The :attribute has already been taken.',
+ 'uploaded' => 'The :attribute failed to upload.',
+ 'url' => 'The :attribute format is invalid.',
+ 'uuid' => 'The :attribute must be a valid UUID.',
/*
|--------------------------------------------------------------------------
@@ -110,9 +136,9 @@ return [
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
- | The following language lines are used to swap attribute place-holders
- | with something more reader friendly such as E-Mail Address instead
- | of "email". This simply helps us make messages a little cleaner.
+ | The following language lines are used to swap our attribute placeholder
+ | with something more reader friendly such as "E-Mail Address" instead
+ | of "email". This simply helps us make our message more expressive.
|
*/
diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore
index d6b7ef3..01e4a6c 100644
--- a/storage/framework/cache/.gitignore
+++ b/storage/framework/cache/.gitignore
@@ -1,2 +1,3 @@
*
+!data/
!.gitignore
diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/framework/cache/data/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php
index ff133fb..547152f 100644
--- a/tests/CreatesApplication.php
+++ b/tests/CreatesApplication.php
@@ -2,7 +2,6 @@
namespace Tests;
-use Illuminate\Support\Facades\Hash;
use Illuminate\Contracts\Console\Kernel;
trait CreatesApplication
@@ -18,8 +17,6 @@ trait CreatesApplication
$app->make(Kernel::class)->bootstrap();
- Hash::driver('bcrypt')->setRounds(4);
-
return $app;
}
}