Page MenuHomePhorge

D3409.1775372384.diff
No OneTemporary

Authored By
Unknown
Size
196 KB
Referenced Files
None
Subscribers
None

D3409.1775372384.diff

diff --git a/bin/quickstart.sh b/bin/quickstart.sh
--- a/bin/quickstart.sh
+++ b/bin/quickstart.sh
@@ -42,10 +42,10 @@
# Always reset .env with .env.example
cp src/.env.example src/.env
-if [ -f "src/.env.local" ]; then
+if [ -f "src/env.local" ]; then
# Ensure there's a line ending
echo "" >> src/.env
- cat src/.env.local >> src/.env
+ cat src/env.local >> src/.env
fi
docker pull docker.io/kolab/centos7:latest
@@ -97,9 +97,8 @@
./artisan db:ping --wait
php -dmemory_limit=512M ./artisan migrate:refresh --seed
./artisan data:import || :
-./artisan swoole:http stop >/dev/null 2>&1 || :
-SWOOLE_HTTP_DAEMONIZE=true ./artisan swoole:http start
+./artisan octane:stop >/dev/null 2>&1 || :
+nohup ./artisan octane:start --host=$(grep OCTANE_HTTP_HOST .env | tail -n1 | sed "s/OCTANE_HTTP_HOST=//") > octane.out &
./artisan horizon:terminate >/dev/null 2>&1 || :
-nohup ./artisan horizon >/dev/null 2>&1 &
+nohup ./artisan horizon > horizon.out &
popd
-
diff --git a/docker-compose.yml b/docker-compose.yml
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -189,7 +189,7 @@
build:
context: ./docker/swoole/
container_name: kolab-swoole
- image: apheleia/swoole:4.6.x
+ image: apheleia/swoole:4.8.x
worker:
build:
context: ./docker/worker/
diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile
--- a/docker/nginx/Dockerfile
+++ b/docker/nginx/Dockerfile
@@ -1,4 +1,4 @@
-FROM fedora:34
+FROM fedora:35
MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
diff --git a/docker/proxy/Dockerfile b/docker/proxy/Dockerfile
--- a/docker/proxy/Dockerfile
+++ b/docker/proxy/Dockerfile
@@ -1,4 +1,4 @@
-FROM fedora:31
+FROM fedora:35
MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
diff --git a/docker/swoole/Dockerfile b/docker/swoole/Dockerfile
--- a/docker/swoole/Dockerfile
+++ b/docker/swoole/Dockerfile
@@ -1,8 +1,8 @@
-FROM fedora:34
+FROM fedora:35
MAINTAINER Jeroen van Meeuwen <vanmeeuwen@apheleia-it.ch>
-ARG SWOOLE_VERSION=v4.6.7
+ARG SWOOLE_VERSION=v4.8.7
ENV HOME=/opt/app-root/src
LABEL io.k8s.description="Platform for serving PHP applications under Swoole" \
@@ -10,6 +10,7 @@
io.openshift.expose-services="8000:http" \
io.openshift.tags="builder,php,swoole"
+RUN dnf -y update
RUN dnf -y install \
composer \
diffutils \
diff --git a/docker/swoole/rootfs/usr/local/bin/run-container b/docker/swoole/rootfs/usr/local/bin/run-container
--- a/docker/swoole/rootfs/usr/local/bin/run-container
+++ b/docker/swoole/rootfs/usr/local/bin/run-container
@@ -36,7 +36,7 @@
env
- exec ./artisan swoole:http start
+ exec ./artisan octane:start
else
exec $@
fi
diff --git a/src/.env.example b/src/.env.example
--- a/src/.env.example
+++ b/src/.env.example
@@ -30,6 +30,8 @@
LOG_CHANNEL=stack
LOG_SLOW_REQUESTS=5
+LOG_DEPRECATIONS_CHANNEL=null
+LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_DATABASE=kolabdev
@@ -112,14 +114,7 @@
REDIS_PASSWORD=null
REDIS_PORT=6379
-SWOOLE_HOT_RELOAD_ENABLE=true
-SWOOLE_HTTP_ACCESS_LOG=true
-SWOOLE_HTTP_HOST=127.0.0.1
-SWOOLE_HTTP_PORT=8000
-SWOOLE_HTTP_REACTOR_NUM=1
-SWOOLE_HTTP_WEBSOCKET=true
-SWOOLE_HTTP_WORKER_NUM=1
-SWOOLE_OB_OUTPUT=true
+OCTANE_HTTP_HOST=127.0.0.1
PAYMENT_PROVIDER=
MOLLIE_KEY=
@@ -127,7 +122,7 @@
STRIPE_PUBLIC_KEY=
STRIPE_WEBHOOK_SECRET=
-MAIL_DRIVER=smtp
+MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
@@ -147,6 +142,7 @@
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
+AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
diff --git a/src/.gitattributes b/src/.gitattributes
--- a/src/.gitattributes
+++ b/src/.gitattributes
@@ -1,5 +1,9 @@
* text=auto
-*.css linguist-vendored
-*.scss linguist-vendored
-*.js linguist-vendored
+
+*.blade.php diff=html
+*.css diff=css
+*.html diff=html
+*.md diff=markdown
+*.php diff=php
+
CHANGELOG.md export-ignore
diff --git a/src/.styleci.yml b/src/.styleci.yml
--- a/src/.styleci.yml
+++ b/src/.styleci.yml
@@ -1,11 +1,10 @@
php:
preset: laravel
disabled:
- - unused_use
+ - no_unused_imports
finder:
not-name:
- index.php
- - server.php
js:
finder:
not-name:
diff --git a/src/app/Auth/LDAPUserProvider.php b/src/app/Auth/LDAPUserProvider.php
deleted file mode 100644
--- a/src/app/Auth/LDAPUserProvider.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-namespace App\Auth;
-
-use App\User;
-use Illuminate\Auth\EloquentUserProvider;
-use Illuminate\Support\Facades\Hash;
-use Illuminate\Contracts\Auth\Authenticatable;
-use Illuminate\Contracts\Auth\UserProvider;
-
-/**
- * A user provider that integrates an LDAP deployment.
- */
-class LDAPUserProvider extends EloquentUserProvider implements UserProvider
-{
- /**
- * Retrieve the user by its credentials (email).
- *
- * @param array $credentials An array containing the email and password.
- *
- * @return User|null
- */
- public function retrieveByCredentials(array $credentials)
- {
- $entries = User::where('email', \strtolower($credentials['email']))->get();
-
- $count = $entries->count();
-
- if ($count == 1) {
- return $entries->first();
- }
-
- if ($count > 1) {
- \Log::warning("Multiple entries for {$credentials['email']}");
- } else {
- \Log::warning("No entries for {$credentials['email']}");
- }
-
- return null;
- }
-
- /**
- * Validate the credentials for a user.
- *
- * @param Authenticatable $user The user.
- * @param array $credentials The credentials.
- *
- * @return bool
- */
- public function validateCredentials(Authenticatable $user, array $credentials): bool
- {
- return $user->validateCredentials($credentials['email'], $credentials['password']);
- }
-}
diff --git a/src/app/Auth/SecondFactor.php b/src/app/Auth/SecondFactor.php
--- a/src/app/Auth/SecondFactor.php
+++ b/src/app/Auth/SecondFactor.php
@@ -57,6 +57,7 @@
return;
}
}
+
throw new \Exception(\trans('validation.2fainvalid'));
}
diff --git a/src/app/AuthAttempt.php b/src/app/AuthAttempt.php
--- a/src/app/AuthAttempt.php
+++ b/src/app/AuthAttempt.php
@@ -2,10 +2,10 @@
namespace App;
-use Illuminate\Database\Eloquent\Model;
-use Iatstuti\Database\Support\NullableFields;
use App\Traits\UuidStrKeyTrait;
use Carbon\Carbon;
+use Dyrynda\Database\Support\NullableFields;
+use Illuminate\Database\Eloquent\Model;
/**
* The eloquent definition of an AuthAttempt.
@@ -27,10 +27,10 @@
private const STATUS_ACCEPTED = 'ACCEPTED';
private const STATUS_DENIED = 'DENIED';
- protected $nullable = [
- 'reason',
- ];
+ /** @var array<int, string> The attributes that can be not set */
+ protected $nullable = ['reason'];
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'ip',
'user_id',
@@ -40,6 +40,7 @@
'last_seen',
];
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
'expires_at' => 'datetime',
'last_seen' => 'datetime'
@@ -106,7 +107,7 @@
*/
public function notify(): bool
{
- return \App\CompanionApp::notifyUser($this->user_id, ['token' => $this->id]);
+ return CompanionApp::notifyUser($this->user_id, ['token' => $this->id]);
}
/**
@@ -154,12 +155,12 @@
*
* @return \App\AuthAttempt
*/
- public static function recordAuthAttempt(\App\User $user, $clientIP)
+ public static function recordAuthAttempt(User $user, $clientIP)
{
- $authAttempt = \App\AuthAttempt::where('ip', $clientIP)->where('user_id', $user->id)->first();
+ $authAttempt = AuthAttempt::where('ip', $clientIP)->where('user_id', $user->id)->first();
if (!$authAttempt) {
- $authAttempt = new \App\AuthAttempt();
+ $authAttempt = new AuthAttempt();
$authAttempt->ip = $clientIP;
$authAttempt->user_id = $user->id;
}
diff --git a/src/app/Backends/LDAP.php b/src/app/Backends/LDAP.php
--- a/src/app/Backends/LDAP.php
+++ b/src/app/Backends/LDAP.php
@@ -1356,7 +1356,7 @@
*/
private static function throwException($ldap, string $message): void
{
- if (empty(self::$ldap) && !empty($ldap)) {
+ if (empty(self::$ldap)) {
$ldap->close();
}
diff --git a/src/app/CompanionApp.php b/src/app/CompanionApp.php
--- a/src/app/CompanionApp.php
+++ b/src/app/CompanionApp.php
@@ -11,6 +11,7 @@
*/
class CompanionApp extends Model
{
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'name',
'user_id',
@@ -67,7 +68,7 @@
*/
public static function notifyUser($userId, $data): bool
{
- $notificationTokens = \App\CompanionApp::where('user_id', $userId)
+ $notificationTokens = CompanionApp::where('user_id', $userId)
->where('mfa_enabled', true)
->pluck('notification_token')
->all();
diff --git a/src/app/Console/Command.php b/src/app/Console/Command.php
--- a/src/app/Console/Command.php
+++ b/src/app/Console/Command.php
@@ -9,9 +9,9 @@
/**
* This needs to be here to be used.
*
- * @var null
+ * @var string
*/
- protected $commandPrefix = null;
+ protected $commandPrefix = '';
/**
* Annotate this command as being dangerous for any potential unintended consequences.
diff --git a/src/app/Console/Commands/Data/Import/LdifCommand.php b/src/app/Console/Commands/Data/Import/LdifCommand.php
--- a/src/app/Console/Commands/Data/Import/LdifCommand.php
+++ b/src/app/Console/Commands/Data/Import/LdifCommand.php
@@ -121,6 +121,7 @@
$lastAttr = null;
$insertFunc = function ($limit = 0) use (&$entry, &$inserts) {
+ // @phpstan-ignore-next-line
if (!empty($entry)) {
if ($entry = $this->parseLDAPEntry($entry)) {
$inserts[] = $entry;
diff --git a/src/app/Console/Kernel.php b/src/app/Console/Kernel.php
--- a/src/app/Console/Kernel.php
+++ b/src/app/Console/Kernel.php
@@ -8,15 +8,6 @@
class Kernel extends ConsoleKernel
{
/**
- * The Artisan commands provided by your application.
- *
- * @var array
- */
- protected $commands = [
- //
- ];
-
- /**
* Define the application's command schedule.
*
* @param Schedule $schedule The application's command schedule
diff --git a/src/app/Console/ObjectCommand.php b/src/app/Console/ObjectCommand.php
--- a/src/app/Console/ObjectCommand.php
+++ b/src/app/Console/ObjectCommand.php
@@ -13,7 +13,7 @@
*
* @var string
*/
- protected $commandPrefix = null;
+ protected $commandPrefix = '';
/**
* The object class that we are operating on, for example \App\User::class
diff --git a/src/app/Console/ObjectCreateCommand.php b/src/app/Console/ObjectCreateCommand.php
--- a/src/app/Console/ObjectCreateCommand.php
+++ b/src/app/Console/ObjectCreateCommand.php
@@ -61,7 +61,5 @@
} else {
$this->error("Object could not be created.");
}
-
- return $object;
}
}
diff --git a/src/app/Discount.php b/src/app/Discount.php
--- a/src/app/Discount.php
+++ b/src/app/Discount.php
@@ -26,17 +26,12 @@
'discount' => 'integer',
];
- protected $fillable = [
- 'active',
- 'code',
- 'description',
- 'discount',
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['active', 'code', 'description', 'discount'];
+
+ /** @var array<int, string> Translatable properties */
+ public $translatable = ['description'];
- /** @var array Translatable properties */
- public $translatable = [
- 'description',
- ];
/**
* Discount value mutator
@@ -67,6 +62,6 @@
*/
public function wallets()
{
- return $this->hasMany('App\Wallet');
+ return $this->hasMany(Wallet::class);
}
}
diff --git a/src/app/Domain.php b/src/app/Domain.php
--- a/src/app/Domain.php
+++ b/src/app/Domain.php
@@ -2,7 +2,6 @@
namespace App;
-use App\Wallet;
use App\Traits\BelongsToTenantTrait;
use App\Traits\DomainConfigTrait;
use App\Traits\EntitleableTrait;
@@ -56,12 +55,16 @@
public const HASH_TEXT = 2;
public const HASH_CNAME = 3;
- protected $fillable = [
- 'namespace',
- 'status',
- 'type'
+ /** @var array<string, string> The attributes that should be cast */
+ protected $casts = [
+ 'created_at' => 'datetime:Y-m-d H:i:s',
+ 'deleted_at' => 'datetime:Y-m-d H:i:s',
+ 'updated_at' => 'datetime:Y-m-d H:i:s',
];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['namespace', 'status', 'type'];
+
/**
* Assign a package to a domain. The domain should not belong to any existing entitlements.
*
@@ -97,8 +100,8 @@
public static function getPublicDomains(): array
{
return self::withEnvTenantContext()
- ->whereRaw(sprintf('(type & %s)', Domain::TYPE_PUBLIC))
- ->get(['namespace'])->pluck('namespace')->toArray();
+ ->where('type', '&', Domain::TYPE_PUBLIC)
+ ->pluck('namespace')->all();
}
/**
@@ -315,11 +318,11 @@
$suffixLen = strlen($suffix);
return !(
- \App\User::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
- || \App\UserAlias::whereRaw('substr(alias, ?) = ?', [-$suffixLen, $suffix])->exists()
- || \App\Group::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
- || \App\Resource::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
- || \App\SharedFolder::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
+ User::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
+ || UserAlias::whereRaw('substr(alias, ?) = ?', [-$suffixLen, $suffix])->exists()
+ || Group::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
+ || Resource::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
+ || SharedFolder::whereRaw('substr(email, ?) = ?', [-$suffixLen, $suffix])->exists()
);
}
@@ -370,7 +373,7 @@
return [];
}
- $mailboxSKU = \App\Sku::withObjectTenantContext($this)->where('title', 'mailbox')->first();
+ $mailboxSKU = Sku::withObjectTenantContext($this)->where('title', 'mailbox')->first();
if (!$mailboxSKU) {
\Log::error("No mailbox SKU available.");
@@ -378,7 +381,7 @@
}
return $wallet->entitlements()
- ->where('entitleable_type', \App\User::class)
+ ->where('entitleable_type', User::class)
->where('sku_id', $mailboxSKU->id)
->get()
->pluck('entitleable')
diff --git a/src/app/DomainSetting.php b/src/app/DomainSetting.php
--- a/src/app/DomainSetting.php
+++ b/src/app/DomainSetting.php
@@ -14,9 +14,8 @@
*/
class DomainSetting extends Model
{
- protected $fillable = [
- 'domain_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['domain_id', 'key', 'value'];
/**
* The domain to which this setting belongs.
@@ -26,7 +25,7 @@
public function domain()
{
return $this->belongsTo(
- '\App\Domain',
+ Domain::class,
'domain_id', /* local */
'id' /* remote */
);
diff --git a/src/app/Entitlement.php b/src/app/Entitlement.php
--- a/src/app/Entitlement.php
+++ b/src/app/Entitlement.php
@@ -2,9 +2,9 @@
namespace App;
+use App\Traits\UuidStrKeyTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
-use App\Traits\UuidStrKeyTrait;
/**
* The eloquent definition of an Entitlement.
@@ -29,11 +29,7 @@
use SoftDeletes;
use UuidStrKeyTrait;
- /**
- * The fillable columns for this Entitlement
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'sku_id',
'wallet_id',
@@ -44,6 +40,7 @@
'fee',
];
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
'cost' => 'integer',
'fee' => 'integer'
@@ -80,10 +77,10 @@
*/
public function createTransaction($type, $amount = null)
{
- $transaction = \App\Transaction::create(
+ $transaction = Transaction::create(
[
'object_id' => $this->id,
- 'object_type' => \App\Entitlement::class,
+ 'object_type' => Entitlement::class,
'type' => $type,
'amount' => $amount
]
@@ -110,7 +107,7 @@
*/
public function entitleableTitle(): ?string
{
- if ($this->entitleable instanceof \App\Domain) {
+ if ($this->entitleable instanceof Domain) {
return $this->entitleable->namespace;
}
@@ -151,7 +148,7 @@
*/
public function sku()
{
- return $this->belongsTo('App\Sku');
+ return $this->belongsTo(Sku::class);
}
/**
@@ -161,7 +158,7 @@
*/
public function wallet()
{
- return $this->belongsTo('App\Wallet');
+ return $this->belongsTo(Wallet::class);
}
/**
diff --git a/src/app/Exceptions/Handler.php b/src/app/Exceptions/Handler.php
--- a/src/app/Exceptions/Handler.php
+++ b/src/app/Exceptions/Handler.php
@@ -2,61 +2,37 @@
namespace App\Exceptions;
-use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Support\Facades\DB;
class Handler extends ExceptionHandler
{
- /**
- * A list of the exception types that are not reported.
- *
- * @var array
- */
+ /** @var string[] A list of the exception types that are not reported */
protected $dontReport = [
\Laravel\Passport\Exceptions\OAuthServerException::class,
\League\OAuth2\Server\Exception\OAuthServerException::class
];
- /**
- * A list of the inputs that are never flashed for validation exceptions.
- *
- * @var array
- */
+ /** @var string[] A list of the inputs that are never flashed for validation exceptions */
protected $dontFlash = [
+ 'current_password',
'password',
'password_confirmation',
];
- /**
- * Report or log an exception.
- *
- * @param \Exception $exception
- *
- * @return void
- */
- public function report(Exception $exception)
- {
- parent::report($exception);
- }
/**
- * Render an exception into an HTTP response.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Exception $exception
- *
- * @return \Symfony\Component\HttpFoundation\Response
+ * Register the exception handling callbacks for the application.
*/
- public function render($request, Exception $exception)
+ public function register()
{
- // Rollback uncommitted transactions
- while (DB::transactionLevel() > 0) {
- DB::rollBack();
- }
-
- return parent::render($request, $exception);
+ $this->reportable(function (\Throwable $e) {
+ // Rollback uncommitted transactions
+ while (DB::transactionLevel() > 0) {
+ DB::rollBack();
+ }
+ });
}
/**
diff --git a/src/app/Group.php b/src/app/Group.php
--- a/src/app/Group.php
+++ b/src/app/Group.php
@@ -9,7 +9,6 @@
use App\Traits\SettingsTrait;
use App\Traits\StatusPropertyTrait;
use App\Traits\UuidIntKeyTrait;
-use App\Wallet;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -45,6 +44,14 @@
// group has been created in LDAP
public const STATUS_LDAP_READY = 1 << 4;
+ /** @var array<string, string> The attributes that should be cast */
+ protected $casts = [
+ 'created_at' => 'datetime:Y-m-d H:i:s',
+ 'deleted_at' => 'datetime:Y-m-d H:i:s',
+ 'updated_at' => 'datetime:Y-m-d H:i:s',
+ ];
+
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'email',
'members',
diff --git a/src/app/GroupSetting.php b/src/app/GroupSetting.php
--- a/src/app/GroupSetting.php
+++ b/src/app/GroupSetting.php
@@ -14,9 +14,8 @@
*/
class GroupSetting extends Model
{
- protected $fillable = [
- 'group_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['group_id', 'key', 'value'];
/**
* The group to which this setting belongs.
@@ -25,6 +24,6 @@
*/
public function group()
{
- return $this->belongsTo(\App\Group::class, 'group_id', 'id');
+ return $this->belongsTo(Group::class, 'group_id', 'id');
}
}
diff --git a/src/app/Http/Controllers/API/PasswordResetController.php b/src/app/Http/Controllers/API/PasswordResetController.php
--- a/src/app/Http/Controllers/API/PasswordResetController.php
+++ b/src/app/Http/Controllers/API/PasswordResetController.php
@@ -16,10 +16,6 @@
*/
class PasswordResetController extends Controller
{
- /** @var \App\VerificationCode A verification code object */
- protected $code;
-
-
/**
* Sends password reset code to the user's external email
*
@@ -98,7 +94,7 @@
// For last-step remember the code object, so we can delete it
// with single SQL query (->delete()) instead of two (::destroy())
- $this->code = $code;
+ $request->code = $code;
return response()->json([
'status' => 'success',
@@ -121,7 +117,7 @@
return $v;
}
- $user = $this->code->user;
+ $user = $request->code->user;
// Validate the password
$v = Validator::make(
@@ -138,7 +134,7 @@
$user->save();
// Remove the verification code
- $this->code->delete();
+ $request->code->delete();
return AuthController::logonResponse($user, $request->password);
}
diff --git a/src/app/Http/Controllers/API/SignupController.php b/src/app/Http/Controllers/API/SignupController.php
--- a/src/app/Http/Controllers/API/SignupController.php
+++ b/src/app/Http/Controllers/API/SignupController.php
@@ -25,13 +25,6 @@
*/
class SignupController extends Controller
{
- /** @var ?\App\SignupCode A verification code object */
- protected $code;
-
- /** @var ?\App\Plan Signup plan object */
- protected $plan;
-
-
/**
* Returns plans definitions for signup.
*
@@ -177,7 +170,7 @@
// For signup last-step mode remember the code object, so we can delete it
// with single SQL query (->delete()) instead of two (::destroy())
- $this->code = $code;
+ $request->code = $code;
$has_domain = $this->getPlan()->hasDomain();
@@ -328,8 +321,8 @@
}
// Remove the verification code
- if ($this->code) {
- $this->code->delete();
+ if ($request->code) {
+ $request->code->delete();
}
DB::commit();
@@ -344,10 +337,12 @@
*/
protected function getPlan()
{
- if (!$this->plan) {
+ $request = request();
+
+ if (!$request->plan || !$request->plan instanceof Plan) {
// Get the plan if specified and exists...
- if ($this->code && $this->code->plan) {
- $plan = Plan::withEnvTenantContext()->where('title', $this->code->plan)->first();
+ if ($request->code && $request->code->plan) {
+ $plan = Plan::withEnvTenantContext()->where('title', $request->code->plan)->first();
}
// ...otherwise use the default plan
@@ -356,10 +351,10 @@
$plan = Plan::withEnvTenantContext()->where('title', 'individual')->first();
}
- $this->plan = $plan;
+ $request->plan = $plan;
}
- return $this->plan;
+ return $request->plan;
}
/**
diff --git a/src/app/Http/Controllers/API/V4/Admin/UsersController.php b/src/app/Http/Controllers/API/V4/Admin/UsersController.php
--- a/src/app/Http/Controllers/API/V4/Admin/UsersController.php
+++ b/src/app/Http/Controllers/API/V4/Admin/UsersController.php
@@ -215,6 +215,8 @@
}
$user->assignSku($sku);
+
+ /** @var \App\Entitlement $entitlement */
$entitlement = $user->entitlements()->where('sku_id', $sku->id)->first();
return response()->json([
diff --git a/src/app/Http/Controllers/API/V4/AuthAttemptsController.php b/src/app/Http/Controllers/API/V4/AuthAttemptsController.php
--- a/src/app/Http/Controllers/API/V4/AuthAttemptsController.php
+++ b/src/app/Http/Controllers/API/V4/AuthAttemptsController.php
@@ -9,7 +9,6 @@
class AuthAttemptsController extends Controller
{
-
/**
* Confirm the authentication attempt.
*
diff --git a/src/app/Http/Controllers/API/V4/WalletsController.php b/src/app/Http/Controllers/API/V4/WalletsController.php
--- a/src/app/Http/Controllers/API/V4/WalletsController.php
+++ b/src/app/Http/Controllers/API/V4/WalletsController.php
@@ -161,6 +161,7 @@
// Get sub-transactions for the specified transaction ID, first
// check access rights to the transaction's wallet
+ /** @var ?\App\Transaction $transaction */
$transaction = $wallet->transactions()->where('id', $transaction)->first();
if (!$transaction) {
diff --git a/src/app/Http/Kernel.php b/src/app/Http/Kernel.php
--- a/src/app/Http/Kernel.php
+++ b/src/app/Http/Kernel.php
@@ -11,12 +11,13 @@
*
* These middleware are run during every request to your application.
*
- * @var array
+ * @var array<int, class-string|string>
*/
protected $middleware = [
+ // \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\RequestLogger::class,
\App\Http\Middleware\TrustProxies::class,
- \App\Http\Middleware\CheckForMaintenanceMode::class,
+ \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
@@ -31,7 +32,7 @@
/**
* The application's route middleware groups.
*
- * @var array
+ * @var array<string, array<int, class-string|string>
*/
protected $middlewareGroups = [
'web' => [
@@ -45,8 +46,8 @@
],
'api' => [
- //'throttle:120,1',
- 'bindings',
+ // 'throttle:api',
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
@@ -55,13 +56,12 @@
*
* These middleware may be assigned to groups or used individually.
*
- * @var array
+ * @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'admin' => \App\Http\Middleware\AuthenticateAdmin::class,
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
- 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
@@ -72,25 +72,6 @@
];
/**
- * The priority-sorted list of middleware.
- *
- * This forces non-global middleware to always be in the given order.
- *
- * @var array
- */
- protected $middlewarePriority = [
- \Illuminate\Session\Middleware\StartSession::class,
- \Illuminate\View\Middleware\ShareErrorsFromSession::class,
- \App\Http\Middleware\AuthenticateAdmin::class,
- \App\Http\Middleware\AuthenticateReseller::class,
- \App\Http\Middleware\Authenticate::class,
- \Illuminate\Session\Middleware\AuthenticateSession::class,
- \Illuminate\Routing\Middleware\SubstituteBindings::class,
- \Illuminate\Auth\Middleware\Authorize::class,
- \App\Http\Middleware\ContentSecurityPolicy::class,
- ];
-
- /**
* Handle an incoming HTTP request.
*
* @param \Illuminate\Http\Request $request HTTP Request object
diff --git a/src/app/Http/Middleware/EncryptCookies.php b/src/app/Http/Middleware/EncryptCookies.php
--- a/src/app/Http/Middleware/EncryptCookies.php
+++ b/src/app/Http/Middleware/EncryptCookies.php
@@ -9,7 +9,7 @@
/**
* The names of the cookies that should not be encrypted.
*
- * @var array
+ * @var array<int, string>
*/
protected $except = [
//
diff --git a/src/app/Http/Middleware/CheckForMaintenanceMode.php b/src/app/Http/Middleware/PreventRequestsDuringMaintenance.php
rename from src/app/Http/Middleware/CheckForMaintenanceMode.php
rename to src/app/Http/Middleware/PreventRequestsDuringMaintenance.php
--- a/src/app/Http/Middleware/CheckForMaintenanceMode.php
+++ b/src/app/Http/Middleware/PreventRequestsDuringMaintenance.php
@@ -2,14 +2,14 @@
namespace App\Http\Middleware;
-use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
+use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
-class CheckForMaintenanceMode extends Middleware
+class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
- * @var array
+ * @var array<int, string>
*/
protected $except = [
//
diff --git a/src/app/Http/Middleware/RedirectIfAuthenticated.php b/src/app/Http/Middleware/RedirectIfAuthenticated.php
--- a/src/app/Http/Middleware/RedirectIfAuthenticated.php
+++ b/src/app/Http/Middleware/RedirectIfAuthenticated.php
@@ -3,6 +3,7 @@
namespace App\Http\Middleware;
use Closure;
+use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
@@ -12,14 +13,18 @@
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
- * @param string|null $guard
+ * @param string|null ...$guards
*
* @return mixed
*/
- public function handle($request, Closure $next, $guard = null)
+ public function handle(Request $request, Closure $next, ...$guards)
{
- if (Auth::guard($guard)->check()) {
- return redirect('/dashboard');
+ $guards = empty($guards) ? [null] : $guards;
+
+ foreach ($guards as $guard) {
+ if (Auth::guard($guard)->check()) {
+ return redirect('/dashboard');
+ }
}
return $next($request);
diff --git a/src/app/Http/Middleware/TrustHosts.php b/src/app/Http/Middleware/TrustHosts.php
new file mode 100644
--- /dev/null
+++ b/src/app/Http/Middleware/TrustHosts.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Http\Middleware\TrustHosts as Middleware;
+
+class TrustHosts extends Middleware
+{
+ /**
+ * Get the host patterns that should be trusted.
+ *
+ * @return array<int, string|null>
+ */
+ public function hosts()
+ {
+ return [
+ $this->allSubdomainsOfApplicationUrl(),
+ ];
+ }
+}
diff --git a/src/app/Http/Middleware/TrustProxies.php b/src/app/Http/Middleware/TrustProxies.php
--- a/src/app/Http/Middleware/TrustProxies.php
+++ b/src/app/Http/Middleware/TrustProxies.php
@@ -2,15 +2,15 @@
namespace App\Http\Middleware;
+use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
-use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
- * @var array|string
+ * @var array<int, string>|string|null
*/
protected $proxies = [
'10.0.0.0/8',
@@ -24,5 +24,9 @@
*
* @var int
*/
- protected $headers = Request::HEADER_X_FORWARDED_ALL;
+ protected $headers = Request::HEADER_X_FORWARDED_FOR |
+ Request::HEADER_X_FORWARDED_HOST |
+ Request::HEADER_X_FORWARDED_PORT |
+ Request::HEADER_X_FORWARDED_PROTO |
+ Request::HEADER_X_FORWARDED_AWS_ELB;
}
diff --git a/src/app/Http/Middleware/VerifyCsrfToken.php b/src/app/Http/Middleware/VerifyCsrfToken.php
--- a/src/app/Http/Middleware/VerifyCsrfToken.php
+++ b/src/app/Http/Middleware/VerifyCsrfToken.php
@@ -7,16 +7,9 @@
class VerifyCsrfToken extends Middleware
{
/**
- * Indicates whether the XSRF-TOKEN cookie should be set on the response.
- *
- * @var bool
- */
- protected $addHttpCookie = true;
-
- /**
* The URIs that should be excluded from CSRF verification.
*
- * @var array
+ * @var array<int, string>
*/
protected $except = [
//
diff --git a/src/app/IP4Net.php b/src/app/IP4Net.php
--- a/src/app/IP4Net.php
+++ b/src/app/IP4Net.php
@@ -9,6 +9,7 @@
{
protected $table = "ip4nets";
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'rir_name',
'net_number',
diff --git a/src/app/IP6Net.php b/src/app/IP6Net.php
--- a/src/app/IP6Net.php
+++ b/src/app/IP6Net.php
@@ -9,6 +9,7 @@
{
protected $table = "ip6nets";
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'rir_name',
'net_number',
diff --git a/src/app/Jobs/PaymentEmail.php b/src/app/Jobs/PaymentEmail.php
--- a/src/app/Jobs/PaymentEmail.php
+++ b/src/app/Jobs/PaymentEmail.php
@@ -22,7 +22,7 @@
public $tries = 2;
/** @var int The number of seconds to wait before retrying the job. */
- public $retryAfter = 10;
+ public $backoff = 10;
/** @var bool Delete the job if the wallet no longer exist. */
public $deleteWhenMissingModels = true;
@@ -30,7 +30,7 @@
/** @var \App\Payment A payment object */
protected $payment;
- /** @var \App\User A wallet controller */
+ /** @var ?\App\User A wallet controller */
protected $controller;
diff --git a/src/app/Jobs/PaymentMandateDisabledEmail.php b/src/app/Jobs/PaymentMandateDisabledEmail.php
--- a/src/app/Jobs/PaymentMandateDisabledEmail.php
+++ b/src/app/Jobs/PaymentMandateDisabledEmail.php
@@ -22,7 +22,7 @@
public $tries = 2;
/** @var int The number of seconds to wait before retrying the job. */
- public $retryAfter = 10;
+ public $backoff = 10;
/** @var bool Delete the job if the wallet no longer exist. */
public $deleteWhenMissingModels = true;
@@ -30,7 +30,7 @@
/** @var \App\Wallet A wallet object */
protected $wallet;
- /** @var \App\User A wallet controller */
+ /** @var ?\App\User A wallet controller */
protected $controller;
diff --git a/src/app/Jobs/SignupInvitationEmail.php b/src/app/Jobs/SignupInvitationEmail.php
--- a/src/app/Jobs/SignupInvitationEmail.php
+++ b/src/app/Jobs/SignupInvitationEmail.php
@@ -24,7 +24,7 @@
public $deleteWhenMissingModels = true;
/** @var int The number of seconds to wait before retrying the job. */
- public $retryAfter = 10;
+ public $backoff = 10;
/** @var SignupInvitation Signup invitation object */
protected $invitation;
diff --git a/src/app/Jobs/WalletCharge.php b/src/app/Jobs/WalletCharge.php
--- a/src/app/Jobs/WalletCharge.php
+++ b/src/app/Jobs/WalletCharge.php
@@ -21,7 +21,7 @@
protected $wallet;
/** @var int The number of seconds to wait before retrying the job. */
- public $retryAfter = 10;
+ public $backoff = 10;
/** @var int How many times retry the job if it fails. */
public $tries = 5;
diff --git a/src/app/Jobs/WalletCheck.php b/src/app/Jobs/WalletCheck.php
--- a/src/app/Jobs/WalletCheck.php
+++ b/src/app/Jobs/WalletCheck.php
@@ -30,7 +30,7 @@
public const THRESHOLD_INITIAL = 'initial';
/** @var int The number of seconds to wait before retrying the job. */
- public $retryAfter = 10;
+ public $backoff = 10;
/** @var int How many times retry the job if it fails. */
public $tries = 5;
diff --git a/src/app/Observers/OpenVidu/ConnectionObserver.php b/src/app/Observers/OpenVidu/ConnectionObserver.php
--- a/src/app/Observers/OpenVidu/ConnectionObserver.php
+++ b/src/app/Observers/OpenVidu/ConnectionObserver.php
@@ -34,7 +34,7 @@
foreach ($keys as $key => $type) {
$newState = $connection->metadata[$key] ?? null;
- $oldState = $this->getOriginal($connection, 'metadata')[$key] ?? null;
+ $oldState = $connection->getOriginal('metadata')[$key] ?? null;
if ($newState !== $oldState) {
$params[$key] = $type == 'bool' ? !empty($newState) : $newState;
@@ -47,25 +47,4 @@
$connection->room->signal('connectionUpdate', $params);
}
}
-
- /**
- * A wrapper to getOriginal() on an object
- *
- * @param \App\OpenVidu\Connection $connection The connection.
- * @param string $property The property name
- *
- * @return mixed
- */
- private function getOriginal($connection, $property)
- {
- $original = $connection->getOriginal($property);
-
- // The original value for a property is in a format stored in database
- // I.e. for 'metadata' it is a JSON string instead of an array
- if ($property == 'metadata') {
- $original = json_decode($original, true);
- }
-
- return $original;
- }
}
diff --git a/src/app/OpenVidu/Room.php b/src/app/OpenVidu/Room.php
--- a/src/app/OpenVidu/Room.php
+++ b/src/app/OpenVidu/Room.php
@@ -27,9 +27,9 @@
public const REQUEST_ACCEPTED = 'accepted';
public const REQUEST_DENIED = 'denied';
- private const OV_ROLE_MODERATOR = 'MODERATOR';
+ private const OV_ROLE_MODERATOR = 'MODERATOR'; // @phpstan-ignore-line
private const OV_ROLE_PUBLISHER = 'PUBLISHER';
- private const OV_ROLE_SUBSCRIBER = 'SUBSCRIBER';
+ private const OV_ROLE_SUBSCRIBER = 'SUBSCRIBER'; // @phpstan-ignore-line
protected $fillable = [
'user_id',
diff --git a/src/app/Package.php b/src/app/Package.php
--- a/src/app/Package.php
+++ b/src/app/Package.php
@@ -39,6 +39,7 @@
public $timestamps = false;
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'description',
'discount_rate',
@@ -46,7 +47,7 @@
'title',
];
- /** @var array Translatable properties */
+ /** @var array<int, string> Translatable properties */
public $translatable = [
'name',
'description',
@@ -83,7 +84,7 @@
public function isDomain(): bool
{
foreach ($this->skus as $sku) {
- if ($sku->handler_class::entitleableClass() == \App\Domain::class) {
+ if ($sku->handler_class::entitleableClass() == Domain::class) {
return true;
}
}
@@ -98,11 +99,8 @@
*/
public function skus()
{
- return $this->belongsToMany(
- 'App\Sku',
- 'package_skus'
- )->using('App\PackageSku')->withPivot(
- ['qty']
- );
+ return $this->belongsToMany(Sku::class, 'package_skus')
+ ->using(PackageSku::class)
+ ->withPivot(['qty']);
}
}
diff --git a/src/app/PackageSku.php b/src/app/PackageSku.php
--- a/src/app/PackageSku.php
+++ b/src/app/PackageSku.php
@@ -16,6 +16,7 @@
*/
class PackageSku extends Pivot
{
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'package_id',
'sku_id',
@@ -23,6 +24,7 @@
'qty'
];
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
'cost' => 'integer',
'qty' => 'integer'
@@ -71,7 +73,7 @@
*/
public function package()
{
- return $this->belongsTo('App\Package');
+ return $this->belongsTo(Package::class);
}
/**
@@ -81,6 +83,6 @@
*/
public function sku()
{
- return $this->belongsTo('App\Sku');
+ return $this->belongsTo(Sku::class);
}
}
diff --git a/src/app/Payment.php b/src/app/Payment.php
--- a/src/app/Payment.php
+++ b/src/app/Payment.php
@@ -20,10 +20,12 @@
public $incrementing = false;
protected $keyType = 'string';
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
'amount' => 'integer'
];
+ /** @var array<int,string> The attributes that are mass assignable */
protected $fillable = [
'id',
'wallet_id',
@@ -52,6 +54,6 @@
*/
public function wallet()
{
- return $this->belongsTo('\App\Wallet', 'wallet_id', 'id');
+ return $this->belongsTo(Wallet::class, 'wallet_id', 'id');
}
}
diff --git a/src/app/Plan.php b/src/app/Plan.php
--- a/src/app/Plan.php
+++ b/src/app/Plan.php
@@ -34,6 +34,7 @@
public $timestamps = false;
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'title',
'name',
@@ -47,14 +48,15 @@
'discount_rate',
];
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
- 'promo_from' => 'datetime',
- 'promo_to' => 'datetime',
+ 'promo_from' => 'datetime:Y-m-d H:i:s',
+ 'promo_to' => 'datetime:Y-m-d H:i:s',
'discount_qty' => 'integer',
'discount_rate' => 'integer'
];
- /** @var array Translatable properties */
+ /** @var array<int, string> Translatable properties */
public $translatable = [
'name',
'description',
@@ -87,18 +89,15 @@
*/
public function packages()
{
- return $this->belongsToMany(
- 'App\Package',
- 'plan_packages'
- )->using('App\PlanPackage')->withPivot(
- [
- 'qty',
- 'qty_min',
- 'qty_max',
- 'discount_qty',
- 'discount_rate'
- ]
- );
+ return $this->belongsToMany(Package::class, 'plan_packages')
+ ->using(PlanPackage::class)
+ ->withPivot([
+ 'qty',
+ 'qty_min',
+ 'qty_max',
+ 'discount_qty',
+ 'discount_rate'
+ ]);
}
/**
diff --git a/src/app/PlanPackage.php b/src/app/PlanPackage.php
--- a/src/app/PlanPackage.php
+++ b/src/app/PlanPackage.php
@@ -19,6 +19,7 @@
*/
class PlanPackage extends Pivot
{
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'plan_id',
'package_id',
@@ -29,6 +30,7 @@
'discount_rate'
];
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
'qty' => 'integer',
'qty_max' => 'integer',
@@ -62,7 +64,7 @@
*/
public function package()
{
- return $this->belongsTo('App\Package');
+ return $this->belongsTo(Package::class);
}
/**
@@ -72,6 +74,6 @@
*/
public function plan()
{
- return $this->belongsTo('App\Plan');
+ return $this->belongsTo(Plan::class);
}
}
diff --git a/src/app/Providers/AuthServiceProvider.php b/src/app/Providers/AuthServiceProvider.php
--- a/src/app/Providers/AuthServiceProvider.php
+++ b/src/app/Providers/AuthServiceProvider.php
@@ -2,9 +2,8 @@
namespace App\Providers;
-use App\Auth\LDAPUserProvider;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;
@@ -13,7 +12,7 @@
/**
* The policy mappings for the application.
*
- * @var array
+ * @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
@@ -28,13 +27,6 @@
{
$this->registerPolicies();
- Auth::provider(
- 'ldap',
- function ($app, array $config) {
- return new LDAPUserProvider($app['hash'], $config['model']);
- }
- );
-
// Hashes all secrets and thus makes them non-recoverable
/* Passport::hashClientSecrets(); */
// Only enable routes for access tokens
@@ -43,7 +35,7 @@
$router->forAccessTokens();
// Override the default route to avoid rate-limiting.
- \Route::post('/token', [
+ Route::post('/token', [
'uses' => 'AccessTokenController@issueToken',
'as' => 'passport.token',
]);
diff --git a/src/app/Providers/EventServiceProvider.php b/src/app/Providers/EventServiceProvider.php
--- a/src/app/Providers/EventServiceProvider.php
+++ b/src/app/Providers/EventServiceProvider.php
@@ -12,7 +12,7 @@
/**
* The event listener mappings for the application.
*
- * @var array
+ * @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
@@ -27,8 +27,16 @@
*/
public function boot()
{
- parent::boot();
-
//
}
+
+ /**
+ * Determine if events and listeners should be automatically discovered.
+ *
+ * @return bool
+ */
+ public function shouldDiscoverEvents()
+ {
+ return false;
+ }
}
diff --git a/src/app/Providers/PassportServiceProvider.php b/src/app/Providers/PassportServiceProvider.php
--- a/src/app/Providers/PassportServiceProvider.php
+++ b/src/app/Providers/PassportServiceProvider.php
@@ -10,7 +10,6 @@
class PassportServiceProvider extends \Laravel\Passport\PassportServiceProvider
{
-
/**
* Make the authorization service instance.
*
diff --git a/src/app/Providers/RouteServiceProvider.php b/src/app/Providers/RouteServiceProvider.php
--- a/src/app/Providers/RouteServiceProvider.php
+++ b/src/app/Providers/RouteServiceProvider.php
@@ -2,73 +2,43 @@
namespace App\Providers;
-use Illuminate\Support\Facades\Route;
+use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\RateLimiter;
+use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
- * This namespace is applied to your controller routes.
- *
- * In addition, it is set as the URL generator's root namespace.
- *
- * @var string
- */
- protected $namespace = 'App\Http\Controllers';
-
- /**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
- //
+ $this->configureRateLimiting();
- parent::boot();
- }
+ $this->routes(function () {
+ $prefix = \trim(\parse_url(\config('app.url'), PHP_URL_PATH), '/') . '/';
- /**
- * Define the routes for the application.
- *
- * @return void
- */
- public function map()
- {
- $this->mapApiRoutes();
-
- $this->mapWebRoutes();
+ Route::prefix($prefix . 'api')
+ ->group(base_path('routes/api.php'));
- //
+ Route::middleware('web')
+ ->group(base_path('routes/web.php'));
+ });
}
/**
- * Define the "web" routes for the application.
- *
- * These routes all receive session state, CSRF protection, etc.
- *
- * @return void
- */
- protected function mapWebRoutes()
- {
- Route::middleware('web')
- ->namespace($this->namespace)
- ->group(base_path('routes/web.php'));
- }
-
- /**
- * Define the "api" routes for the application.
- *
- * These routes are typically stateless.
+ * Configure the rate limiters for the application.
*
* @return void
*/
- protected function mapApiRoutes()
+ protected function configureRateLimiting()
{
- // Note: We removed the prefix from here, to have more control
- // over it in routes/api.php
- Route::middleware('api')
- ->namespace($this->namespace)
- ->group(base_path('routes/api.php'));
+ RateLimiter::for('api', function (Request $request) {
+ return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
+ });
}
}
diff --git a/src/app/Resource.php b/src/app/Resource.php
--- a/src/app/Resource.php
+++ b/src/app/Resource.php
@@ -9,7 +9,6 @@
use App\Traits\SettingsTrait;
use App\Traits\StatusPropertyTrait;
use App\Traits\UuidIntKeyTrait;
-use App\Wallet;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -49,9 +48,13 @@
// A template for the email attribute on a resource creation
public const EMAIL_TEMPLATE = 'resource-{id}@{domainName}';
- protected $fillable = [
- 'email',
- 'name',
- 'status',
+ /** @var array<string, string> The attributes that should be cast */
+ protected $casts = [
+ 'created_at' => 'datetime:Y-m-d H:i:s',
+ 'deleted_at' => 'datetime:Y-m-d H:i:s',
+ 'updated_at' => 'datetime:Y-m-d H:i:s',
];
+
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['email', 'name', 'status'];
}
diff --git a/src/app/ResourceSetting.php b/src/app/ResourceSetting.php
--- a/src/app/ResourceSetting.php
+++ b/src/app/ResourceSetting.php
@@ -14,9 +14,8 @@
*/
class ResourceSetting extends Model
{
- protected $fillable = [
- 'resource_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['resource_id', 'key', 'value'];
/**
* The resource to which this setting belongs.
@@ -25,6 +24,6 @@
*/
public function resource()
{
- return $this->belongsTo(\App\Resource::class, 'resource_id', 'id');
+ return $this->belongsTo(Resource::class, 'resource_id', 'id');
}
}
diff --git a/src/app/SharedFolder.php b/src/app/SharedFolder.php
--- a/src/app/SharedFolder.php
+++ b/src/app/SharedFolder.php
@@ -54,7 +54,14 @@
/** @const string A template for the email attribute on a folder creation */
public const EMAIL_TEMPLATE = '{type}-{id}@{domainName}';
- /** @var array Mass-assignable properties */
+ /** @var array<string, string> The attributes that should be cast */
+ protected $casts = [
+ 'created_at' => 'datetime:Y-m-d H:i:s',
+ 'deleted_at' => 'datetime:Y-m-d H:i:s',
+ 'updated_at' => 'datetime:Y-m-d H:i:s',
+ ];
+
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'email',
'name',
diff --git a/src/app/SharedFolderAlias.php b/src/app/SharedFolderAlias.php
--- a/src/app/SharedFolderAlias.php
+++ b/src/app/SharedFolderAlias.php
@@ -34,6 +34,6 @@
*/
public function sharedFolder()
{
- return $this->belongsTo('\App\SharedFolder', 'shared_folder_id', 'id');
+ return $this->belongsTo(SharedFolder::class, 'shared_folder_id', 'id');
}
}
diff --git a/src/app/SharedFolderSetting.php b/src/app/SharedFolderSetting.php
--- a/src/app/SharedFolderSetting.php
+++ b/src/app/SharedFolderSetting.php
@@ -14,9 +14,8 @@
*/
class SharedFolderSetting extends Model
{
- protected $fillable = [
- 'shared_folder_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['shared_folder_id', 'key', 'value'];
/**
* The folder to which this setting belongs.
@@ -25,6 +24,6 @@
*/
public function folder()
{
- return $this->belongsTo(\App\SharedFolder::class, 'shared_folder_id', 'id');
+ return $this->belongsTo(SharedFolder::class, 'shared_folder_id', 'id');
}
}
diff --git a/src/app/SignupCode.php b/src/app/SignupCode.php
--- a/src/app/SignupCode.php
+++ b/src/app/SignupCode.php
@@ -35,32 +35,16 @@
public const CODE_EXP_HOURS = 24;
- /**
- * The primary key associated with the table.
- *
- * @var string
- */
+ /** @var string The primary key associated with the table */
protected $primaryKey = 'code';
- /**
- * Indicates if the IDs are auto-incrementing.
- *
- * @var bool
- */
+ /** @var bool Indicates if the IDs are auto-incrementing */
public $incrementing = false;
- /**
- * The "type" of the auto-incrementing ID.
- *
- * @var string
- */
+ /** @var string The "type" of the auto-incrementing ID */
protected $keyType = 'string';
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'code',
'email',
@@ -72,14 +56,12 @@
'voucher'
];
- protected $casts = ['headers' => 'array'];
+ /** @var array<string, string> The attributes that should be cast */
+ protected $casts = [
+ 'expires_at' => 'datetime:Y-m-d H:i:s',
+ 'headers' => 'array'
+ ];
- /**
- * The attributes that should be mutated to dates.
- *
- * @var array
- */
- protected $dates = ['expires_at'];
/**
* Check if code is expired.
diff --git a/src/app/SignupInvitation.php b/src/app/SignupInvitation.php
--- a/src/app/SignupInvitation.php
+++ b/src/app/SignupInvitation.php
@@ -31,13 +31,10 @@
public const STATUS_COMPLETED = 1 << 3;
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = ['email'];
+
/**
* Returns whether this invitation process completed (user signed up)
*
@@ -85,6 +82,6 @@
*/
public function user()
{
- return $this->belongsTo('App\User', 'user_id', 'id');
+ return $this->belongsTo(User::class, 'user_id', 'id');
}
}
diff --git a/src/app/Sku.php b/src/app/Sku.php
--- a/src/app/Sku.php
+++ b/src/app/Sku.php
@@ -2,10 +2,10 @@
namespace App;
-use Illuminate\Database\Eloquent\Model;
-use Spatie\Translatable\HasTranslations;
use App\Traits\BelongsToTenantTrait;
use App\Traits\UuidStrKeyTrait;
+use Illuminate\Database\Eloquent\Model;
+use Spatie\Translatable\HasTranslations;
/**
* The eloquent definition of a Stock Keeping Unit (SKU).
@@ -28,10 +28,12 @@
use HasTranslations;
use UuidStrKeyTrait;
+ /** @var array<string, string> The attributes that should be cast */
protected $casts = [
'units_free' => 'integer'
];
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'active',
'cost',
@@ -45,7 +47,7 @@
'units_free',
];
- /** @var array Translatable properties */
+ /** @var array<int, string> Translatable properties */
public $translatable = [
'name',
'description',
@@ -58,7 +60,7 @@
*/
public function entitlements()
{
- return $this->hasMany('App\Entitlement');
+ return $this->hasMany(Entitlement::class);
}
/**
@@ -68,9 +70,8 @@
*/
public function packages()
{
- return $this->belongsToMany(
- 'App\Package',
- 'package_skus'
- )->using('App\PackageSku')->withPivot(['cost', 'qty']);
+ return $this->belongsToMany(Package::class, 'package_skus')
+ ->using(PackageSku::class)
+ ->withPivot(['cost', 'qty']);
}
}
diff --git a/src/app/Tenant.php b/src/app/Tenant.php
--- a/src/app/Tenant.php
+++ b/src/app/Tenant.php
@@ -15,10 +15,8 @@
{
use SettingsTrait;
- protected $fillable = [
- 'id',
- 'title',
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['id', 'title'];
/**
@@ -67,7 +65,7 @@
*/
public function discounts()
{
- return $this->hasMany('App\Discount');
+ return $this->hasMany(Discount::class);
}
/**
@@ -77,7 +75,7 @@
*/
public function signupInvitations()
{
- return $this->hasMany('App\SignupInvitation');
+ return $this->hasMany(SignupInvitation::class);
}
/*
@@ -87,7 +85,7 @@
*/
public function wallet(): ?Wallet
{
- $user = \App\User::where('role', 'reseller')->where('tenant_id', $this->id)->first();
+ $user = User::where('role', 'reseller')->where('tenant_id', $this->id)->first();
return $user ? $user->wallets->first() : null;
}
diff --git a/src/app/TenantSetting.php b/src/app/TenantSetting.php
--- a/src/app/TenantSetting.php
+++ b/src/app/TenantSetting.php
@@ -14,9 +14,8 @@
*/
class TenantSetting extends Model
{
- protected $fillable = [
- 'tenant_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['tenant_id', 'key', 'value'];
/**
* The tenant to which this setting belongs.
@@ -25,6 +24,6 @@
*/
public function tenant()
{
- return $this->belongsTo('\App\Tenant', 'tenant_id', 'id');
+ return $this->belongsTo(Tenant::class, 'tenant_id', 'id');
}
}
diff --git a/src/app/Traits/EmailPropertyTrait.php b/src/app/Traits/EmailPropertyTrait.php
--- a/src/app/Traits/EmailPropertyTrait.php
+++ b/src/app/Traits/EmailPropertyTrait.php
@@ -61,7 +61,7 @@
* @param string $email Email address
* @param bool $return_object Return model instance instead of a boolean
*
- * @return object|bool True or Model object if found, False otherwise
+ * @return static|bool True or Model object if found, False otherwise
*/
public static function emailExists(string $email, bool $return_object = false)
{
diff --git a/src/app/Transaction.php b/src/app/Transaction.php
--- a/src/app/Transaction.php
+++ b/src/app/Transaction.php
@@ -2,8 +2,6 @@
namespace App;
-use App\Entitlement;
-use App\Wallet;
use App\Traits\UuidStrKeyTrait;
use Illuminate\Database\Eloquent\Model;
@@ -34,27 +32,23 @@
public const WALLET_REFUND = 'refund';
public const WALLET_CHARGEBACK = 'chback';
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
// actor, if any
'user_email',
-
// entitlement, wallet
'object_id',
'object_type',
-
// entitlement: created, deleted, billed
// wallet: debit, credit, award, penalty
'type',
-
'amount',
-
'description',
-
// parent, for example wallet debit is parent for entitlements charged.
'transaction_id'
];
- /** @var array Casts properties as type */
+ /** @var array<string, string> Casts properties as type */
protected $casts = [
'amount' => 'integer',
];
diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -10,11 +10,11 @@
use App\Traits\UuidIntKeyTrait;
use App\Traits\SettingsTrait;
use App\Traits\StatusPropertyTrait;
+use Dyrynda\Database\Support\NullableFields;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Foundation\Auth\User as Authenticatable;
-use Iatstuti\Database\Support\NullableFields;
use Laravel\Passport\HasApiTokens;
use League\OAuth2\Server\Exception\OAuthServerException;
@@ -57,11 +57,7 @@
// user in "limited feature-set" state
public const STATUS_DEGRADED = 1 << 6;
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'id',
'email',
@@ -70,22 +66,26 @@
'status',
];
- /**
- * The attributes that should be hidden for arrays.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that should be hidden for arrays */
protected $hidden = [
'password',
'password_ldap',
'role'
];
+ /** @var array<int, string> The attributes that can be null */
protected $nullable = [
'password',
'password_ldap'
];
+ /** @var array<string, string> The attributes that should be cast */
+ protected $casts = [
+ 'created_at' => 'datetime:Y-m-d H:i:s',
+ 'deleted_at' => 'datetime:Y-m-d H:i:s',
+ 'updated_at' => 'datetime:Y-m-d H:i:s',
+ ];
+
/**
* Any wallets on which this user is a controller.
*
@@ -96,7 +96,7 @@
public function accounts()
{
return $this->belongsToMany(
- 'App\Wallet', // The foreign object definition
+ Wallet::class, // The foreign object definition
'user_accounts', // The table name
'user_id', // The local foreign key
'wallet_id' // The remote foreign key
@@ -274,8 +274,8 @@
$query->withEnvTenantContext();
}
- $query->whereRaw(sprintf('(domains.type & %s)', Domain::TYPE_PUBLIC))
- ->whereRaw(sprintf('(domains.status & %s)', Domain::STATUS_ACTIVE));
+ $query->where('domains.type', '&', Domain::TYPE_PUBLIC)
+ ->where('domains.status', '&', Domain::STATUS_ACTIVE);
});
}
@@ -337,7 +337,7 @@
return $user;
}
- $aliases = \App\UserAlias::where('alias', $email)->get();
+ $aliases = UserAlias::where('alias', $email)->get();
if (count($aliases) == 1) {
return $aliases->first()->user;
@@ -395,7 +395,7 @@
$name = trim($settings['first_name'] . ' ' . $settings['last_name']);
if (empty($name) && $fallback) {
- return trim(\trans('app.siteuser', ['site' => \App\Tenant::getConfig($this->tenant_id, 'app.name')]));
+ return trim(\trans('app.siteuser', ['site' => Tenant::getConfig($this->tenant_id, 'app.name')]));
}
return $name;
@@ -408,7 +408,7 @@
*/
public function passwords()
{
- return $this->hasMany('App\UserPassword');
+ return $this->hasMany(UserPassword::class);
}
/**
@@ -421,7 +421,7 @@
*/
public function resources($with_accounts = true)
{
- return $this->entitleables(\App\Resource::class, $with_accounts);
+ return $this->entitleables(Resource::class, $with_accounts);
}
/**
@@ -434,7 +434,7 @@
*/
public function sharedFolders($with_accounts = true)
{
- return $this->entitleables(\App\SharedFolder::class, $with_accounts);
+ return $this->entitleables(SharedFolder::class, $with_accounts);
}
public function senderPolicyFrameworkWhitelist($clientName)
@@ -512,7 +512,7 @@
*/
public function verificationcodes()
{
- return $this->hasMany('App\VerificationCode', 'user_id', 'id');
+ return $this->hasMany(VerificationCode::class, 'user_id', 'id');
}
/**
@@ -522,7 +522,7 @@
*/
public function wallets()
{
- return $this->hasMany('App\Wallet');
+ return $this->hasMany(Wallet::class);
}
/**
diff --git a/src/app/UserAlias.php b/src/app/UserAlias.php
--- a/src/app/UserAlias.php
+++ b/src/app/UserAlias.php
@@ -13,9 +13,8 @@
*/
class UserAlias extends Model
{
- protected $fillable = [
- 'user_id', 'alias'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['user_id', 'alias'];
/**
* Ensure the email address is appropriately cased.
@@ -34,6 +33,6 @@
*/
public function user()
{
- return $this->belongsTo('\App\User', 'user_id', 'id');
+ return $this->belongsTo(User::class, 'user_id', 'id');
}
}
diff --git a/src/app/UserPassword.php b/src/app/UserPassword.php
--- a/src/app/UserPassword.php
+++ b/src/app/UserPassword.php
@@ -16,13 +16,15 @@
/** @var bool Indicates if the model should be timestamped. */
public $timestamps = false;
- /** @var array The attributes that should be mutated to dates. */
- protected $dates = ['created_at'];
+ /** @var array<string, string> The attributes that should be cast. */
+ protected $casts = [
+ 'created_at' => 'datetime:Y-m-d H:i:s',
+ ];
- /** @var array The attributes that are mass assignable. */
+ /** @var array<int, string> The attributes that are mass assignable. */
protected $fillable = ['user_id', 'password'];
- /** @var array The attributes that should be hidden for arrays. */
+ /** @var array<int, string> The attributes that should be hidden for arrays. */
protected $hidden = ['password'];
/**
@@ -32,6 +34,6 @@
*/
public function user()
{
- return $this->belongsTo('\App\User', 'user_id', 'id');
+ return $this->belongsTo(User::class, 'user_id', 'id');
}
}
diff --git a/src/app/UserSetting.php b/src/app/UserSetting.php
--- a/src/app/UserSetting.php
+++ b/src/app/UserSetting.php
@@ -14,9 +14,8 @@
*/
class UserSetting extends Model
{
- protected $fillable = [
- 'user_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['user_id', 'key', 'value'];
/**
* The user to which this setting belongs.
@@ -25,6 +24,6 @@
*/
public function user()
{
- return $this->belongsTo('\App\User', 'user_id', 'id');
+ return $this->belongsTo(User::class, 'user_id', 'id');
}
}
diff --git a/src/app/VerificationCode.php b/src/app/VerificationCode.php
--- a/src/app/VerificationCode.php
+++ b/src/app/VerificationCode.php
@@ -26,49 +26,25 @@
// Code expires after so many hours
public const CODE_EXP_HOURS = 8;
- /**
- * The primary key associated with the table.
- *
- * @var string
- */
+ /** @var string The primary key associated with the table */
protected $primaryKey = 'code';
- /**
- * Indicates if the IDs are auto-incrementing.
- *
- * @var bool
- */
+ /** @var bool Indicates if the IDs are auto-incrementing */
public $incrementing = false;
- /**
- * The "type" of the auto-incrementing ID.
- *
- * @var string
- */
+ /** @var string The "type" of the auto-incrementing ID */
protected $keyType = 'string';
- /**
- * Indicates if the model should be timestamped.
- *
- * @var bool
- */
+ /** @var bool Indicates if the model should be timestamped */
public $timestamps = false;
- /**
- * Casts properties as type
- *
- * @var array
- */
+ /** @var array<string, string> Casts properties as type */
protected $casts = [
'active' => 'boolean',
'expires_at' => 'datetime',
];
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = ['user_id', 'code', 'short_code', 'mode', 'expires_at', 'active'];
@@ -102,6 +78,6 @@
*/
public function user()
{
- return $this->belongsTo('\App\User', 'user_id', 'id');
+ return $this->belongsTo(User::class, 'user_id', 'id');
}
}
diff --git a/src/app/Wallet.php b/src/app/Wallet.php
--- a/src/app/Wallet.php
+++ b/src/app/Wallet.php
@@ -2,11 +2,10 @@
namespace App;
-use App\User;
use App\Traits\SettingsTrait;
use App\Traits\UuidStrKeyTrait;
use Carbon\Carbon;
-use Iatstuti\Database\Support\NullableFields;
+use Dyrynda\Database\Support\NullableFields;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
@@ -30,39 +29,23 @@
public $timestamps = false;
- /**
- * The attributes' default values.
- *
- * @var array
- */
+ /** @var array The attributes' default values */
protected $attributes = [
'balance' => 0,
];
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that are mass assignable */
protected $fillable = [
'currency',
'description'
];
- /**
- * The attributes that can be not set.
- *
- * @var array
- */
+ /** @var array<int, string> The attributes that can be not set */
protected $nullable = [
'description',
];
- /**
- * The types of attributes to which its values will be cast
- *
- * @var array
- */
+ /** @var array<string, string> The types of attributes to which its values will be cast */
protected $casts = [
'balance' => 'integer',
];
@@ -160,7 +143,7 @@
}
$entitlementTransactions[] = $entitlement->createTransaction(
- \App\Transaction::ENTITLEMENT_BILLED,
+ Transaction::ENTITLEMENT_BILLED,
$cost
);
}
@@ -232,8 +215,8 @@
public function controllers()
{
return $this->belongsToMany(
- 'App\User', // The foreign object definition
- 'user_accounts', // The table name
+ User::class, // The foreign object definition
+ 'user_accounts', // The table name
'wallet_id', // The local foreign key
'user_id' // The remote foreign key
);
@@ -269,11 +252,11 @@
$this->save();
- \App\Transaction::create(
+ Transaction::create(
[
'object_id' => $this->id,
- 'object_type' => \App\Wallet::class,
- 'type' => \App\Transaction::WALLET_CREDIT,
+ 'object_type' => Wallet::class,
+ 'type' => Transaction::WALLET_CREDIT,
'amount' => $amount,
'description' => $description
]
@@ -301,18 +284,18 @@
$this->save();
- $transaction = \App\Transaction::create(
+ $transaction = Transaction::create(
[
'object_id' => $this->id,
- 'object_type' => \App\Wallet::class,
- 'type' => \App\Transaction::WALLET_DEBIT,
+ 'object_type' => Wallet::class,
+ 'type' => Transaction::WALLET_DEBIT,
'amount' => $amount * -1,
'description' => $description
]
);
if (!empty($eTIDs)) {
- \App\Transaction::whereIn('id', $eTIDs)->update(['transaction_id' => $transaction->id]);
+ Transaction::whereIn('id', $eTIDs)->update(['transaction_id' => $transaction->id]);
}
return $this;
@@ -325,7 +308,7 @@
*/
public function discount()
{
- return $this->belongsTo('App\Discount', 'discount_id', 'id');
+ return $this->belongsTo(Discount::class, 'discount_id', 'id');
}
/**
@@ -335,7 +318,7 @@
*/
public function entitlements()
{
- return $this->hasMany('App\Entitlement');
+ return $this->hasMany(Entitlement::class);
}
/**
@@ -396,7 +379,7 @@
*/
public function owner()
{
- return $this->belongsTo('App\User', 'user_id', 'id');
+ return $this->belongsTo(User::class, 'user_id', 'id');
}
/**
@@ -406,7 +389,7 @@
*/
public function payments()
{
- return $this->hasMany('App\Payment');
+ return $this->hasMany(Payment::class);
}
/**
@@ -430,10 +413,10 @@
*/
public function transactions()
{
- return \App\Transaction::where(
+ return Transaction::where(
[
'object_id' => $this->id,
- 'object_type' => \App\Wallet::class
+ 'object_type' => Wallet::class
]
);
}
@@ -492,7 +475,7 @@
// FIXME: Shouldn't we store also cost=0 transactions (to have the full history)?
$entitlementTransactions[] = $entitlement->createTransaction(
- \App\Transaction::ENTITLEMENT_BILLED,
+ Transaction::ENTITLEMENT_BILLED,
$cost
);
}
diff --git a/src/app/WalletSetting.php b/src/app/WalletSetting.php
--- a/src/app/WalletSetting.php
+++ b/src/app/WalletSetting.php
@@ -14,9 +14,8 @@
*/
class WalletSetting extends Model
{
- protected $fillable = [
- 'wallet_id', 'key', 'value'
- ];
+ /** @var array<int, string> The attributes that are mass assignable */
+ protected $fillable = ['wallet_id', 'key', 'value'];
/**
* The wallet to which this setting belongs.
@@ -25,6 +24,6 @@
*/
public function wallet()
{
- return $this->belongsTo('\App\Wallet', 'wallet_id', 'id');
+ return $this->belongsTo(Wallet::class, 'wallet_id', 'id');
}
}
diff --git a/src/composer.json b/src/composer.json
--- a/src/composer.json
+++ b/src/composer.json
@@ -1,7 +1,7 @@
{
- "name": "laravel/laravel",
+ "name": "kolab/kolab4",
"type": "project",
- "description": "The Laravel Framework.",
+ "description": "Kolab 4",
"keywords": [
"framework",
"laravel"
@@ -14,37 +14,33 @@
}
],
"require": {
- "php": "^7.3",
- "barryvdh/laravel-dompdf": "^0.8.6",
- "doctrine/dbal": "^2.13",
- "dyrynda/laravel-nullable-fields": "*",
- "fideloper/proxy": "^4.0",
- "guzzlehttp/guzzle": "^7.3",
+ "php": "^8.0",
+ "barryvdh/laravel-dompdf": "^1.0.0",
+ "doctrine/dbal": "^3.3.2",
+ "dyrynda/laravel-nullable-fields": "^4.2.0",
+ "guzzlehttp/guzzle": "^7.4.1",
"kolab/net_ldap3": "dev-master",
- "laravel/framework": "6.*",
- "laravel/horizon": "^3",
- "laravel/passport": "^9",
- "laravel/tinker": "^2.4",
- "mlocati/spf-lib": "^3.0",
- "mollie/laravel-mollie": "^2.9",
+ "laravel/framework": "^9.2",
+ "laravel/horizon": "^5.9",
+ "laravel/octane": "^1.2",
+ "laravel/passport": "^10.3",
+ "laravel/tinker": "^2.7",
+ "mlocati/spf-lib": "^3.1",
+ "mollie/laravel-mollie": "^2.19",
"moontoast/math": "^1.2",
- "morrislaptop/laravel-queue-clear": "^1.2",
"pear/crypt_gpg": "^1.6.6",
- "silviolleite/laravelpwa": "^2.0",
- "spatie/laravel-translatable": "^4.2",
- "spomky-labs/otphp": "~4.0.0",
- "stripe/stripe-php": "^7.29",
- "swooletw/laravel-swoole": "^2.6"
+ "predis/predis": "^1.1.10",
+ "spatie/laravel-translatable": "^5.2",
+ "spomky-labs/otphp": "~10.0.0",
+ "stripe/stripe-php": "^7.29"
},
"require-dev": {
- "beyondcode/laravel-er-diagram-generator": "^1.3",
- "code-lts/doctum": "^5.1",
- "kirschbaum-development/mail-intercept": "^0.2.4",
- "laravel/dusk": "~6.15.0",
- "nunomaduro/larastan": "^0.7",
- "phpstan/phpstan": "^0.12",
+ "code-lts/doctum": "^5.5.1",
+ "laravel/dusk": "~6.22.0",
+ "nunomaduro/larastan": "^2.0",
+ "phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^9",
- "squizlabs/php_codesniffer": "3.*"
+ "squizlabs/php_codesniffer": "^3.6"
},
"config": {
"optimize-autoloader": true,
@@ -77,6 +73,9 @@
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
+ "post-update-cmd": [
+ "@php artisan vendor:publish --tag=laravel-assets --ansi --force"
+ ],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
diff --git a/src/config/app.php b/src/config/app.php
--- a/src/config/app.php
+++ b/src/config/app.php
@@ -57,7 +57,7 @@
'public_url' => env('APP_PUBLIC_URL', env('APP_URL', 'http://localhost')),
- 'asset_url' => env('ASSET_URL', null),
+ 'asset_url' => env('ASSET_URL'),
'support_url' => env('SUPPORT_URL', null),
@@ -215,44 +215,9 @@
|
*/
- 'aliases' => [
- 'App' => Illuminate\Support\Facades\App::class,
- 'Arr' => Illuminate\Support\Arr::class,
- 'Artisan' => Illuminate\Support\Facades\Artisan::class,
- 'Auth' => Illuminate\Support\Facades\Auth::class,
- 'Blade' => Illuminate\Support\Facades\Blade::class,
- 'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
- 'Bus' => Illuminate\Support\Facades\Bus::class,
- 'Cache' => Illuminate\Support\Facades\Cache::class,
- 'Config' => Illuminate\Support\Facades\Config::class,
- 'Cookie' => Illuminate\Support\Facades\Cookie::class,
- 'Crypt' => Illuminate\Support\Facades\Crypt::class,
- 'DB' => Illuminate\Support\Facades\DB::class,
- 'Eloquent' => Illuminate\Database\Eloquent\Model::class,
- 'Event' => Illuminate\Support\Facades\Event::class,
- 'File' => Illuminate\Support\Facades\File::class,
- 'Gate' => Illuminate\Support\Facades\Gate::class,
- 'Hash' => Illuminate\Support\Facades\Hash::class,
- 'Lang' => Illuminate\Support\Facades\Lang::class,
- 'Log' => Illuminate\Support\Facades\Log::class,
- 'Mail' => Illuminate\Support\Facades\Mail::class,
- 'Notification' => Illuminate\Support\Facades\Notification::class,
- 'Password' => Illuminate\Support\Facades\Password::class,
+ 'aliases' => \Illuminate\Support\Facades\Facade::defaultAliases()->merge([
'PDF' => Barryvdh\DomPDF\Facade::class,
- 'Queue' => Illuminate\Support\Facades\Queue::class,
- 'Redirect' => Illuminate\Support\Facades\Redirect::class,
- 'Redis' => Illuminate\Support\Facades\Redis::class,
- 'Request' => Illuminate\Support\Facades\Request::class,
- 'Response' => Illuminate\Support\Facades\Response::class,
- 'Route' => Illuminate\Support\Facades\Route::class,
- 'Schema' => Illuminate\Support\Facades\Schema::class,
- 'Session' => Illuminate\Support\Facades\Session::class,
- 'Storage' => Illuminate\Support\Facades\Storage::class,
- 'Str' => Illuminate\Support\Str::class,
- 'URL' => Illuminate\Support\Facades\URL::class,
- 'Validator' => Illuminate\Support\Facades\Validator::class,
- 'View' => Illuminate\Support\Facades\View::class,
- ],
+ ])->toArray(),
'headers' => [
'csp' => env('APP_HEADER_CSP', ""),
diff --git a/src/config/auth.php b/src/config/auth.php
--- a/src/config/auth.php
+++ b/src/config/auth.php
@@ -66,7 +66,7 @@
'providers' => [
'users' => [
- 'driver' => 'ldap',
+ 'driver' => 'eloquent',
'model' => App\User::class,
],
diff --git a/src/config/broadcasting.php b/src/config/broadcasting.php
--- a/src/config/broadcasting.php
+++ b/src/config/broadcasting.php
@@ -11,7 +11,7 @@
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
- | Supported: "pusher", "redis", "log", "null"
+ | Supported: "pusher", "ably", "redis", "log", "null"
|
*/
@@ -39,6 +39,14 @@
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
+ 'client_options' => [
+ // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
+ ],
+ ],
+
+ 'ably' => [
+ 'driver' => 'ably',
+ 'key' => env('ABLY_KEY'),
],
'redis' => [
diff --git a/src/config/cache.php b/src/config/cache.php
--- a/src/config/cache.php
+++ b/src/config/cache.php
@@ -39,12 +39,14 @@
'array' => [
'driver' => 'array',
+ 'serialize' => false,
],
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
+ 'lock_connection' => null,
],
'file' => [
@@ -74,6 +76,7 @@
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
+ 'lock_connection' => 'default',
],
'dynamodb' => [
@@ -85,6 +88,10 @@
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
+ 'octane' => [
+ 'driver' => 'octane',
+ ],
+
],
/*
@@ -98,6 +105,6 @@
|
*/
- 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
+ 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'),
];
diff --git a/src/config/database.php b/src/config/database.php
--- a/src/config/database.php
+++ b/src/config/database.php
@@ -75,7 +75,7 @@
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
- 'schema' => 'public',
+ 'search_path' => 'public',
'sslmode' => 'prefer',
],
@@ -135,7 +135,7 @@
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
- 'password' => env('REDIS_PASSWORD', null),
+ 'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
@@ -143,7 +143,7 @@
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
- 'password' => env('REDIS_PASSWORD', null),
+ 'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
diff --git a/src/config/filesystems.php b/src/config/filesystems.php
--- a/src/config/filesystems.php
+++ b/src/config/filesystems.php
@@ -13,20 +13,7 @@
|
*/
- 'default' => env('FILESYSTEM_DRIVER', 'local'),
-
- /*
- |--------------------------------------------------------------------------
- | Default Cloud Filesystem Disk
- |--------------------------------------------------------------------------
- |
- | Many applications store files both locally and in the cloud. For this
- | reason, you may specify a default "cloud" driver here. This driver
- | will be bound as the Cloud disk implementation in the container.
- |
- */
-
- 'cloud' => env('FILESYSTEM_CLOUD', 's3'),
+ 'default' => env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
@@ -37,7 +24,7 @@
| may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options.
|
- | Supported Drivers: "local", "ftp", "sftp", "s3", "rackspace"
+ | Supported Drivers: "local", "ftp", "sftp", "s3"
|
*/
@@ -56,7 +43,7 @@
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
- 'url' => env('APP_URL').'/storage',
+ 'url' => env('APP_URL') . '/storage',
'visibility' => 'public',
],
@@ -67,8 +54,25 @@
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
+ 'endpoint' => env('AWS_ENDPOINT'),
+ 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
],
],
+ /*
+ |--------------------------------------------------------------------------
+ | Symbolic Links
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the symbolic links that will be created when the
+ | `storage:link` Artisan command is executed. The array keys should be
+ | the locations of the links and the values should be their targets.
+ |
+ */
+
+ 'links' => [
+ public_path('storage') => storage_path('app/public'),
+ ],
+
];
diff --git a/src/config/hashing.php b/src/config/hashing.php
--- a/src/config/hashing.php
+++ b/src/config/hashing.php
@@ -44,9 +44,9 @@
*/
'argon' => [
- 'memory' => 1024,
- 'threads' => 2,
- 'time' => 2,
+ 'memory' => 65536,
+ 'threads' => 1,
+ 'time' => 4,
],
];
diff --git a/src/config/horizon.php b/src/config/horizon.php
--- a/src/config/horizon.php
+++ b/src/config/horizon.php
@@ -147,7 +147,7 @@
'queue' => ['default'],
'balance' => 'auto',
'maxProcesses' => 1,
- 'minProcesses' => 0,
+ 'minProcesses' => 1,
'tries' => 1,
],
],
@@ -158,7 +158,7 @@
'queue' => ['default'],
'balance' => 'auto',
'maxProcesses' => 1,
- 'minProcesses' => 0,
+ 'minProcesses' => 1,
'tries' => 1,
],
],
diff --git a/src/config/logging.php b/src/config/logging.php
--- a/src/config/logging.php
+++ b/src/config/logging.php
@@ -1,5 +1,6 @@
<?php
+use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
@@ -20,6 +21,19 @@
/*
|--------------------------------------------------------------------------
+ | Deprecations Log Channel
+ |--------------------------------------------------------------------------
+ |
+ | This option controls the log channel that should be used to log warnings
+ | regarding deprecated PHP and library features. This allows you to get
+ | your application ready for upcoming major versions of dependencies.
+ |
+ */
+
+ 'deprecations' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
+
+ /*
+ |--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
@@ -43,13 +57,13 @@
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
- 'level' => 'debug',
+ 'level' => env('LOG_LEVEL', 'debug'),
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
- 'level' => 'debug',
+ 'level' => env('LOG_LEVEL', 'debug'),
'days' => 14,
],
@@ -58,21 +72,23 @@
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
- 'level' => 'critical',
+ 'level' => env('LOG_LEVEL', 'critical'),
],
'papertrail' => [
'driver' => 'monolog',
- 'level' => 'debug',
- 'handler' => SyslogUdpHandler::class,
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
+ 'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
],
],
'stderr' => [
'driver' => 'monolog',
+ 'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'),
'with' => [
@@ -82,15 +98,22 @@
'syslog' => [
'driver' => 'syslog',
- 'level' => 'debug',
+ 'level' => env('LOG_LEVEL', 'debug'),
],
'errorlog' => [
'driver' => 'errorlog',
- 'level' => 'debug',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ ],
+
+ 'null' => [
+ 'driver' => 'monolog',
+ 'handler' => NullHandler::class,
],
- ],
- 'slow_log' => (float) env('LOG_SLOW_REQUESTS', 5),
+ 'emergency' => [
+ 'path' => storage_path('logs/laravel.log'),
+ ],
+ ],
];
diff --git a/src/config/mail.php b/src/config/mail.php
--- a/src/config/mail.php
+++ b/src/config/mail.php
@@ -4,45 +4,80 @@
/*
|--------------------------------------------------------------------------
- | Mail Driver
+ | Default Mailer
|--------------------------------------------------------------------------
|
- | Laravel supports both SMTP and PHP's "mail" function as drivers for the
- | sending of e-mail. You may specify which one you're using throughout
- | your application here. By default, Laravel is setup for SMTP mail.
- |
- | Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses",
- | "sparkpost", "postmark", "log", "array"
+ | This option controls the default mailer that is used to send any email
+ | messages sent by your application. Alternative mailers may be setup
+ | and used as needed; however, this mailer will be used by default.
|
*/
- 'driver' => env('MAIL_DRIVER', 'smtp'),
+ 'default' => env('MAIL_MAILER', 'smtp'),
/*
|--------------------------------------------------------------------------
- | SMTP Host Address
+ | Mailer Configurations
|--------------------------------------------------------------------------
|
- | Here you may provide the host address of the SMTP server used by your
- | applications. A default option is provided that is compatible with
- | the Mailgun mail service which will provide reliable deliveries.
+ | Here you may configure all of the mailers used by your application plus
+ | their respective settings. Several examples have been configured for
+ | you and you are free to add your own as your application requires.
|
- */
-
- 'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
-
- /*
- |--------------------------------------------------------------------------
- | SMTP Host Port
- |--------------------------------------------------------------------------
+ | Laravel supports a variety of mail "transport" drivers to be used while
+ | sending an e-mail. You will specify which one you are using for your
+ | mailers below. You are free to add additional mailers as required.
|
- | This is the SMTP port used by your application to deliver e-mails to
- | users of the application. Like the host we have set this value to
- | stay compatible with the Mailgun e-mail application by default.
+ | Supported: "smtp", "sendmail", "mailgun", "ses",
+ | "postmark", "log", "array", "failover"
|
*/
- 'port' => env('MAIL_PORT', 587),
+ 'mailers' => [
+ 'smtp' => [
+ 'transport' => 'smtp',
+ 'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
+ 'port' => env('MAIL_PORT', 587),
+ 'encryption' => env('MAIL_ENCRYPTION', 'tls'),
+ 'username' => env('MAIL_USERNAME'),
+ 'password' => env('MAIL_PASSWORD'),
+ 'timeout' => null,
+ ],
+
+ 'ses' => [
+ 'transport' => 'ses',
+ ],
+
+ 'mailgun' => [
+ 'transport' => 'mailgun',
+ ],
+
+ 'postmark' => [
+ 'transport' => 'postmark',
+ ],
+
+ 'sendmail' => [
+ 'transport' => 'sendmail',
+ 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -t -i'),
+ ],
+
+ 'log' => [
+ 'transport' => 'log',
+ 'channel' => env('MAIL_LOG_CHANNEL'),
+ ],
+
+ 'array' => [
+ 'transport' => 'array',
+ ],
+
+ 'failover' => [
+ 'transport' => 'failover',
+ 'mailers' => [
+ 'smtp',
+ 'log',
+ ],
+ ],
+ ],
/*
|--------------------------------------------------------------------------
@@ -78,47 +113,6 @@
/*
|--------------------------------------------------------------------------
- | E-Mail Encryption Protocol
- |--------------------------------------------------------------------------
- |
- | Here you may specify the encryption protocol that should be used when
- | the application send e-mail messages. A sensible default using the
- | transport layer security protocol should provide great security.
- |
- */
-
- 'encryption' => env('MAIL_ENCRYPTION', 'tls'),
-
- /*
- |--------------------------------------------------------------------------
- | SMTP Server Username
- |--------------------------------------------------------------------------
- |
- | If your SMTP server requires a username for authentication, you should
- | set it here. This will get used to authenticate with your server on
- | connection. You may also set the "password" value below this one.
- |
- */
-
- 'username' => env('MAIL_USERNAME'),
-
- 'password' => env('MAIL_PASSWORD'),
-
- /*
- |--------------------------------------------------------------------------
- | Sendmail System Path
- |--------------------------------------------------------------------------
- |
- | When using the "sendmail" driver to send e-mails, we will need to know
- | the path to where Sendmail lives on this server. A default path has
- | been provided here, which will work well on most of your systems.
- |
- */
-
- 'sendmail' => '/usr/sbin/sendmail -bs',
-
- /*
- |--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
@@ -132,21 +126,8 @@
'theme' => 'default',
'paths' => [
- resource_path('views/emails'),
+ resource_path('views/vendor/mail'),
],
],
- /*
- |--------------------------------------------------------------------------
- | Log Channel
- |--------------------------------------------------------------------------
- |
- | If you are using the "log" driver, you may specify the logging channel
- | if you prefer to keep mail messages separate from other log entries
- | for simpler reading. Otherwise, the default channel will be used.
- |
- */
-
- 'log_channel' => env('MAIL_LOG_CHANNEL'),
-
];
diff --git a/src/config/octane.php b/src/config/octane.php
new file mode 100644
--- /dev/null
+++ b/src/config/octane.php
@@ -0,0 +1,246 @@
+<?php
+
+use Laravel\Octane\Contracts\OperationTerminated;
+use Laravel\Octane\Events\RequestHandled;
+use Laravel\Octane\Events\RequestReceived;
+use Laravel\Octane\Events\RequestTerminated;
+use Laravel\Octane\Events\TaskReceived;
+use Laravel\Octane\Events\TaskTerminated;
+use Laravel\Octane\Events\TickReceived;
+use Laravel\Octane\Events\TickTerminated;
+use Laravel\Octane\Events\WorkerErrorOccurred;
+use Laravel\Octane\Events\WorkerStarting;
+use Laravel\Octane\Events\WorkerStopping;
+use Laravel\Octane\Listeners\CollectGarbage;
+use Laravel\Octane\Listeners\DisconnectFromDatabases;
+use Laravel\Octane\Listeners\EnsureUploadedFilesAreValid;
+use Laravel\Octane\Listeners\EnsureUploadedFilesCanBeMoved;
+use Laravel\Octane\Listeners\FlushTemporaryContainerInstances;
+use Laravel\Octane\Listeners\FlushUploadedFiles;
+use Laravel\Octane\Listeners\ReportException;
+use Laravel\Octane\Listeners\StopWorkerIfNecessary;
+use Laravel\Octane\Octane;
+
+return [
+
+ /*
+ |--------------------------------------------------------------------------
+ | Octane Server
+ |--------------------------------------------------------------------------
+ |
+ | This value determines the default "server" that will be used by Octane
+ | when starting, restarting, or stopping your server via the CLI. You
+ | are free to change this to the supported server of your choosing.
+ |
+ | Supported: "roadrunner", "swoole"
+ |
+ */
+
+ 'server' => env('OCTANE_SERVER', 'swoole'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Force HTTPS
+ |--------------------------------------------------------------------------
+ |
+ | When this configuration value is set to "true", Octane will inform the
+ | framework that all absolute links must be generated using the HTTPS
+ | protocol. Otherwise your links may be generated using plain HTTP.
+ |
+ */
+
+ 'https' => env('OCTANE_HTTPS', true),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Octane Listeners
+ |--------------------------------------------------------------------------
+ |
+ | All of the event listeners for Octane's events are defined below. These
+ | listeners are responsible for resetting your application's state for
+ | the next request. You may even add your own listeners to the list.
+ |
+ */
+
+ 'listeners' => [
+ WorkerStarting::class => [
+ EnsureUploadedFilesAreValid::class,
+ EnsureUploadedFilesCanBeMoved::class,
+ ],
+
+ RequestReceived::class => [
+ ...Octane::prepareApplicationForNextOperation(),
+ ...Octane::prepareApplicationForNextRequest(),
+ //
+ ],
+
+ RequestHandled::class => [
+ //
+ ],
+
+ RequestTerminated::class => [
+ // FlushUploadedFiles::class,
+ ],
+
+ TaskReceived::class => [
+ ...Octane::prepareApplicationForNextOperation(),
+ //
+ ],
+
+ TaskTerminated::class => [
+ //
+ ],
+
+ TickReceived::class => [
+ ...Octane::prepareApplicationForNextOperation(),
+ //
+ ],
+
+ TickTerminated::class => [
+ //
+ ],
+
+ OperationTerminated::class => [
+ FlushTemporaryContainerInstances::class,
+ // DisconnectFromDatabases::class,
+ CollectGarbage::class,
+ ],
+
+ WorkerErrorOccurred::class => [
+ ReportException::class,
+ StopWorkerIfNecessary::class,
+ ],
+
+ WorkerStopping::class => [
+ //
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Warm / Flush Bindings
+ |--------------------------------------------------------------------------
+ |
+ | The bindings listed below will either be pre-warmed when a worker boots
+ | or they will be flushed before every new request. Flushing a binding
+ | will force the container to resolve that binding again when asked.
+ |
+ */
+
+ 'warm' => [
+ ...Octane::defaultServicesToWarm(),
+ ],
+
+ 'flush' => [
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Octane Cache Table
+ |--------------------------------------------------------------------------
+ |
+ | While using Swoole, you may leverage the Octane cache, which is powered
+ | by a Swoole table. You may set the maximum number of rows as well as
+ | the number of bytes per row using the configuration options below.
+ |
+ */
+
+ 'cache' => [
+ 'rows' => 1000,
+ 'bytes' => 10000,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Octane Swoole Tables
+ |--------------------------------------------------------------------------
+ |
+ | While using Swoole, you may define additional tables as required by the
+ | application. These tables can be used to store data that needs to be
+ | quickly accessed by other workers on the particular Swoole server.
+ |
+ */
+
+ 'tables' => [
+/*
+ 'example:1000' => [
+ 'name' => 'string:1000',
+ 'votes' => 'int',
+ ],
+*/
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | File Watching
+ |--------------------------------------------------------------------------
+ |
+ | The following list of files and directories will be watched when using
+ | the --watch option offered by Octane. If any of the directories and
+ | files are changed, Octane will automatically reload your workers.
+ |
+ */
+
+ 'watch' => [
+ 'app',
+ 'bootstrap',
+ 'config',
+ 'database',
+ 'public/**/*.php',
+ 'resources/**/*.php',
+ 'routes',
+ 'composer.lock',
+ '.env',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Garbage Collection Threshold
+ |--------------------------------------------------------------------------
+ |
+ | When executing long-lived PHP scripts such as Octane, memory can build
+ | up before being cleared by PHP. You can force Octane to run garbage
+ | collection if your application consumes this amount of megabytes.
+ |
+ */
+
+ 'garbage' => 64,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Maximum Execution Time
+ |--------------------------------------------------------------------------
+ |
+ | The following setting configures the maximum execution time for requests
+ | being handled by Octane. You may set this value to 0 to indicate that
+ | there isn't a specific time limit on Octane request execution time.
+ |
+ */
+
+ 'max_execution_time' => 30,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Swoole configuration
+ |--------------------------------------------------------------------------
+ |
+ | See Laravel\Octane\Command\StartSwooleCommand
+ */
+
+ 'swoole' => [
+ 'options' => [
+ 'log_file' => storage_path('logs/swoole_http.log'),
+ 'package_max_length' => 10 * 1024 * 1024,
+ 'enable_coroutine' => false,
+ //FIXME the daemonize option does not work
+ // 'daemonize' => env('OCTANE_DAEMONIZE', true),
+ //FIXME accessing app()->environment in here renders artisan disfunctional. I suppose it's too early.
+ //'log_level' => app()->environment('local') ? SWOOLE_LOG_INFO : SWOOLE_LOG_ERROR,
+ // 'reactor_num' => , // number of available cpus by default
+ 'send_yield' => true,
+ 'socket_buffer_size' => 10 * 1024 * 1024,
+ // 'task_worker_num' => // number of available cpus by default
+ // 'worker_num' => // number of available cpus by default
+ ],
+ ],
+];
diff --git a/src/config/queue.php b/src/config/queue.php
--- a/src/config/queue.php
+++ b/src/config/queue.php
@@ -39,6 +39,7 @@
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
+ 'after_commit' => false,
],
'beanstalkd' => [
@@ -47,6 +48,7 @@
'queue' => 'default',
'retry_after' => 90,
'block_for' => 0,
+ 'after_commit' => false,
],
'sqs' => [
@@ -54,8 +56,10 @@
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
- 'queue' => env('SQS_QUEUE', 'your-queue-name'),
+ 'queue' => env('SQS_QUEUE', 'default'),
+ 'suffix' => env('SQS_SUFFIX'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ 'after_commit' => false,
],
'redis' => [
@@ -64,6 +68,7 @@
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
+ 'after_commit' => false,
],
],
diff --git a/src/config/session.php b/src/config/session.php
--- a/src/config/session.php
+++ b/src/config/session.php
@@ -72,7 +72,7 @@
|
*/
- 'connection' => env('SESSION_CONNECTION', null),
+ 'connection' => env('SESSION_CONNECTION'),
/*
|--------------------------------------------------------------------------
@@ -92,13 +92,15 @@
| Session Cache Store
|--------------------------------------------------------------------------
|
- | When using the "apc", "memcached", or "dynamodb" session drivers you may
+ | While using one of the framework's cache driven session backends you may
| list a cache store that should be used for these sessions. This value
| must match with one of the application's configured cache "stores".
|
+ | Affects: "apc", "dynamodb", "memcached", "redis"
+ |
*/
- 'store' => env('SESSION_STORE', null),
+ 'store' => env('SESSION_STORE'),
/*
|--------------------------------------------------------------------------
@@ -124,10 +126,7 @@
|
*/
- 'cookie' => env(
- 'SESSION_COOKIE',
- Str::slug(env('APP_NAME', 'laravel'), '_') . '_session'
- ),
+ 'cookie' => env('SESSION_COOKIE', Str::slug(env('APP_NAME', 'laravel'), '_') . '_session'),
/*
|--------------------------------------------------------------------------
@@ -153,7 +152,7 @@
|
*/
- 'domain' => env('SESSION_DOMAIN', null),
+ 'domain' => env('SESSION_DOMAIN'),
/*
|--------------------------------------------------------------------------
@@ -162,11 +161,11 @@
|
| By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep
- | the cookie from being sent to you if it can not be done securely.
+ | the cookie from being sent to you when it can't be done securely.
|
*/
- 'secure' => env('SESSION_SECURE_COOKIE', false),
+ 'secure' => env('SESSION_SECURE_COOKIE'),
/*
|--------------------------------------------------------------------------
@@ -188,12 +187,12 @@
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
- | do not enable this as other CSRF protection services are in place.
+ | will set this value to "lax" since this is a secure default value.
|
- | Supported: "lax", "strict"
+ | Supported: "lax", "strict", "none", null
|
*/
- 'same_site' => null,
+ 'same_site' => 'lax',
];
diff --git a/src/config/swoole_http.php b/src/config/swoole_http.php
deleted file mode 100644
--- a/src/config/swoole_http.php
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-
-return [
- /*
- |--------------------------------------------------------------------------
- | HTTP server configurations.
- |--------------------------------------------------------------------------
- |
- | @see https://www.swoole.co.uk/docs/modules/swoole-server/configuration
- |
- */
- 'server' => [
- 'host' => env('SWOOLE_HTTP_HOST', '127.0.0.1'),
- 'port' => env('SWOOLE_HTTP_PORT', '1215'),
- 'public_path' => base_path('public'),
- // Determine if to use swoole to respond request for static files
- 'handle_static_files' => env('SWOOLE_HANDLE_STATIC', true),
- 'access_log' => env('SWOOLE_HTTP_ACCESS_LOG', false),
- // You must add --enable-openssl while compiling Swoole
- // Put `SWOOLE_SOCK_TCP | SWOOLE_SSL` if you want to enable SSL
- 'socket_type' => SWOOLE_SOCK_TCP,
- 'process_type' => SWOOLE_PROCESS,
- 'options' => [
- 'pid_file' => env('SWOOLE_HTTP_PID_FILE', base_path('storage/logs/swoole_http.pid')),
- 'log_file' => env('SWOOLE_HTTP_LOG_FILE', base_path('storage/logs/swoole_http.log')),
- 'daemonize' => env('SWOOLE_HTTP_DAEMONIZE', false),
- // Normally this value should be 1~4 times larger according to your cpu cores.
- 'reactor_num' => env('SWOOLE_HTTP_REACTOR_NUM', swoole_cpu_num()),
- 'worker_num' => env('SWOOLE_HTTP_WORKER_NUM', swoole_cpu_num()),
- 'task_worker_num' => env('SWOOLE_HTTP_TASK_WORKER_NUM', swoole_cpu_num()),
- // The data to receive can't be larger than buffer_output_size.
- 'package_max_length' => 20 * 1024 * 1024,
- // The data to send can't be larger than buffer_output_size.
- 'buffer_output_size' => 10 * 1024 * 1024,
- // Max buffer size for socket connections
- 'socket_buffer_size' => 128 * 1024 * 1024,
- // Worker will restart after processing this number of requests
- 'max_request' => 3000,
- // Enable coroutine send
- 'send_yield' => true,
- // You must add --enable-openssl while compiling Swoole
- 'ssl_cert_file' => null,
- 'ssl_key_file' => null,
- ],
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Enable to turn on websocket server.
- |--------------------------------------------------------------------------
- */
- 'websocket' => [
- 'enabled' => env('SWOOLE_HTTP_WEBSOCKET', false),
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Hot reload configuration
- |--------------------------------------------------------------------------
- */
- 'hot_reload' => [
- 'enabled' => env('SWOOLE_HOT_RELOAD_ENABLE', false),
- 'recursively' => env('SWOOLE_HOT_RELOAD_RECURSIVELY', true),
- 'directory' => env('SWOOLE_HOT_RELOAD_DIRECTORY', base_path()),
- 'log' => env('SWOOLE_HOT_RELOAD_LOG', true),
- 'filter' => env('SWOOLE_HOT_RELOAD_FILTER', '.php'),
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Console output will be transferred to response content if enabled.
- |--------------------------------------------------------------------------
- */
- 'ob_output' => env('SWOOLE_OB_OUTPUT', true),
-
- /*
- |--------------------------------------------------------------------------
- | Pre-resolved instances here will be resolved when sandbox created.
- |--------------------------------------------------------------------------
- */
- 'pre_resolved' => [
- 'view', 'files', 'session', 'session.store', 'routes',
- 'db', 'db.factory', 'cache', 'cache.store', 'config', 'cookie',
- 'encrypter', 'hash', 'router', 'translator', 'url', 'log',
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Instances here will be cleared on every request.
- |--------------------------------------------------------------------------
- */
- 'instances' => [
- 'auth', 'translator'
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Providers here will be registered on every request.
- |--------------------------------------------------------------------------
- */
- 'providers' => [
- Illuminate\Pagination\PaginationServiceProvider::class,
- App\Providers\AuthServiceProvider::class,
- //Without this passport will sort of work,
- //but PassportServiceProvider will not contain a valid app instance.
- App\Providers\PassportServiceProvider::class,
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Resetters for sandbox app.
- |--------------------------------------------------------------------------
- */
- 'resetters' => [
- SwooleTW\Http\Server\Resetters\ResetConfig::class,
- SwooleTW\Http\Server\Resetters\ResetSession::class,
- SwooleTW\Http\Server\Resetters\ResetCookie::class,
- SwooleTW\Http\Server\Resetters\ClearInstances::class,
- SwooleTW\Http\Server\Resetters\BindRequest::class,
- SwooleTW\Http\Server\Resetters\RebindKernelContainer::class,
- SwooleTW\Http\Server\Resetters\RebindRouterContainer::class,
- SwooleTW\Http\Server\Resetters\RebindViewContainer::class,
- SwooleTW\Http\Server\Resetters\ResetProviders::class,
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Define your swoole tables here.
- |
- | @see https://www.swoole.co.uk/docs/modules/swoole-table
- |--------------------------------------------------------------------------
- */
- 'tables' => [
- // 'table_name' => [
- // 'size' => 1024,
- // 'columns' => [
- // ['name' => 'column_name', 'type' => Table::TYPE_STRING, 'size' => 1024],
- // ]
- // ],
- ],
-];
diff --git a/src/config/swoole_websocket.php b/src/config/swoole_websocket.php
deleted file mode 100644
--- a/src/config/swoole_websocket.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-return [
- /*
- |--------------------------------------------------------------------------
- | Websocket handler for onOpen and onClose callback
- | Replace this handler if you want to customize your websocket handler
- |--------------------------------------------------------------------------
- */
- 'handler' => SwooleTW\Http\Websocket\SocketIO\WebsocketHandler::class,
-
- /*
- |--------------------------------------------------------------------------
- | Default frame parser
- | Replace it if you want to customize your websocket payload
- |--------------------------------------------------------------------------
- */
- 'parser' => SwooleTW\Http\Websocket\SocketIO\SocketIOParser::class,
-
- /*
- |--------------------------------------------------------------------------
- | Websocket route file path
- |--------------------------------------------------------------------------
- */
- 'route_file' => base_path('routes/websocket.php'),
-
- /*
- |--------------------------------------------------------------------------
- | Default middleware for on connect request
- |--------------------------------------------------------------------------
- */
- 'middleware' => [
- SwooleTW\Http\Websocket\Middleware\DecryptCookies::class,
- SwooleTW\Http\Websocket\Middleware\StartSession::class,
- SwooleTW\Http\Websocket\Middleware\Authenticate::class,
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Websocket handler for customized onHandShake callback
- |--------------------------------------------------------------------------
- */
- 'handshake' => [
- 'enabled' => false,
- 'handler' => SwooleTW\Http\Websocket\HandShakeHandler::class,
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Default websocket driver
- |--------------------------------------------------------------------------
- */
- 'default' => 'table',
-
- /*
- |--------------------------------------------------------------------------
- | Websocket client's heartbeat interval (ms)
- |--------------------------------------------------------------------------
- */
- 'ping_interval' => 25000,
-
- /*
- |--------------------------------------------------------------------------
- | Websocket client's heartbeat interval timeout (ms)
- |--------------------------------------------------------------------------
- */
- 'ping_timeout' => 60000,
-
- /*
- |--------------------------------------------------------------------------
- | Room drivers mapping
- |--------------------------------------------------------------------------
- */
- 'drivers' => [
- 'table' => SwooleTW\Http\Websocket\Rooms\TableRoom::class,
- 'redis' => SwooleTW\Http\Websocket\Rooms\RedisRoom::class,
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Room drivers settings
- |--------------------------------------------------------------------------
- */
- 'settings' => [
-
- 'table' => [
- 'room_rows' => 4096,
- 'room_size' => 2048,
- 'client_rows' => 8192,
- 'client_size' => 2048,
- ],
-
- 'redis' => [
- 'server' => [
- 'host' => env('REDIS_HOST', '127.0.0.1'),
- 'password' => env('REDIS_PASSWORD', null),
- 'port' => env('REDIS_PORT', 6379),
- 'database' => 0,
- 'persistent' => true,
- ],
- 'options' => [
- //
- ],
- 'prefix' => 'swoole:',
- ],
- ],
-];
diff --git a/src/include/Kolab2FA/Driver/HOTP.php b/src/include/Kolab2FA/Driver/HOTP.php
--- a/src/include/Kolab2FA/Driver/HOTP.php
+++ b/src/include/Kolab2FA/Driver/HOTP.php
@@ -58,12 +58,15 @@
);
// copy config options
- $this->backend = new \Kolab2FA\OTP\HOTP();
- $this->backend
- ->setDigits($this->config['digits'])
- ->setDigest($this->config['digest'])
- ->setIssuer($this->config['issuer'])
- ->setIssuerIncludedAsParameter(true);
+ $this->backend = \OTPHP\HOTP::create(
+ null,
+ 0,
+ $this->config['digest'],
+ $this->config['digits']
+ );
+
+ $this->backend->setIssuer($this->config['issuer']);
+ $this->backend->setIssuerIncludedAsParameter(true);
}
/**
@@ -73,7 +76,7 @@
{
// get my secret from the user storage
$secret = $this->get('secret');
- $counter = $this->get('counter');
+ $counter = (int) $this->get('counter');
if (!strlen($secret)) {
// LOG: "no secret set for user $this->username"
@@ -82,7 +85,10 @@
}
try {
- $this->backend->setLabel($this->username)->setSecret($secret)->setCounter(intval($this->get('counter')));
+ $this->backend->setLabel($this->username);
+ $this->backend->setSecret($secret);
+ $this->backend->setParameter('counter', $counter);
+
$pass = $this->backend->verify($code, $counter, $this->config['window']);
// store incremented counter value
@@ -114,7 +120,10 @@
// TODO: deny call if already active?
- $this->backend->setLabel($this->username)->setSecret($this->secret)->setCounter(intval($this->get('counter')));
+ $this->backend->setLabel($this->username);
+ $this->backend->setSecret($this->secret);
+ $this->backend->setParameter('counter', (int) $this->get('counter'));
+
return $this->backend->getProvisioningUri();
}
diff --git a/src/include/Kolab2FA/Driver/TOTP.php b/src/include/Kolab2FA/Driver/TOTP.php
--- a/src/include/Kolab2FA/Driver/TOTP.php
+++ b/src/include/Kolab2FA/Driver/TOTP.php
@@ -52,13 +52,15 @@
);
// copy config options
- $this->backend = new \Kolab2FA\OTP\TOTP();
- $this->backend
- ->setDigits($this->config['digits'])
- ->setInterval($this->config['interval'])
- ->setDigest($this->config['digest'])
- ->setIssuer($this->config['issuer'])
- ->setIssuerIncludedAsParameter(true);
+ $this->backend = \OTPHP\TOTP::create(
+ null,
+ $this->config['interval'],
+ $this->config['digest'],
+ $this->config['digits']
+ );
+
+ $this->backend->setIssuer($this->config['issuer']);
+ $this->backend->setIssuerIncludedAsParameter(true);
}
/**
@@ -75,14 +77,11 @@
return false;
}
- $this->backend->setLabel($this->username)->setSecret($secret);
+ $this->backend->setLabel($this->username);
+ $this->backend->setParameter('secret', $secret);
- // PHP gets a string, but we're comparing integers.
- $code = (int)$code;
-//$code = (string) $code;
- // Pass a window to indicate the maximum timeslip between client (mobile
- // device) and server.
- $pass = $this->backend->verify($code, $timestamp, 150);
+ // Pass a window to indicate the maximum timeslip between client (device) and server.
+ $pass = $this->backend->verify((string) $code, $timestamp, 150);
// try all codes from $timestamp till now
if (!$pass && $timestamp) {
@@ -109,7 +108,8 @@
return;
}
- $this->backend->setLabel($this->username)->setSecret($secret);
+ $this->backend->setLabel($this->username);
+ $this->backend->setParameter('secret', $secret);
return $this->backend->at(time());
}
@@ -130,8 +130,9 @@
// TODO: deny call if already active?
- $this->backend->setLabel($this->username)->setSecret($this->secret);
+ $this->backend->setLabel($this->username);
+ $this->backend->setParameter('secret', $secret);
+
return $this->backend->getProvisioningUri();
}
-
}
diff --git a/src/include/Kolab2FA/OTP/HOTP.php b/src/include/Kolab2FA/OTP/HOTP.php
deleted file mode 100644
--- a/src/include/Kolab2FA/OTP/HOTP.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * Kolab HOTP implementation based on Spomky-Labs/otphp
- *
- * This basically follows the exmaple implementation from
- * https://github.com/Spomky-Labs/otphp/tree/master/examples
- *
- * @author Thomas Bruederli <bruederli@kolabsys.com>
- *
- * Copyright (C) 2015, Kolab Systems AG <contact@kolabsys.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-namespace Kolab2FA\OTP;
-
-use OTPHP\HOTP as Base;
-
-class HOTP extends Base
-{
- use OTP;
- protected $counter = 0;
-
- public function setCounter($counter)
- {
- if (!is_integer($counter) || $counter < 0) {
- throw new \Exception('Counter must be at least 0.');
- }
- $this->counter = $counter;
-
- return $this;
- }
-
- public function getCounter()
- {
- return $this->counter;
- }
-
- public function updateCounter($counter)
- {
- $this->counter = $counter;
-
- return $this;
- }
-}
diff --git a/src/include/Kolab2FA/OTP/OTP.php b/src/include/Kolab2FA/OTP/OTP.php
deleted file mode 100644
--- a/src/include/Kolab2FA/OTP/OTP.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-
-/**
- * Kolab OTP trait based on Spomky-Labs/otphp
- *
- * This basically follows the exmaple implementation from
- * https://github.com/Spomky-Labs/otphp/tree/master/examples
- *
- * @author Thomas Bruederli <bruederli@kolabsys.com>
- *
- * Copyright (C) 2015, Kolab Systems AG <contact@kolabsys.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-namespace Kolab2FA\OTP;
-
-trait OTP
-{
- protected $secret = null;
- protected $issuer = null;
- protected $issuer_included_as_parameter = false;
- protected $label = null;
- protected $digest = 'sha1';
- protected $digits = 6;
-
- public function setSecret($secret)
- {
- $this->secret = $secret;
-
- return $this;
- }
-
- public function getSecret()
- {
- return $this->secret;
- }
-
- public function setLabel($label)
- {
- if ($this->hasSemicolon($label)) {
- throw new \Exception('Label must not contain a semi-colon.');
- }
- $this->label = $label;
-
- return $this;
- }
-
- public function getLabel()
- {
- return $this->label;
- }
-
- public function setIssuer($issuer)
- {
- if ($this->hasSemicolon($issuer)) {
- throw new \Exception('Issuer must not contain a semi-colon.');
- }
- $this->issuer = $issuer;
-
- return $this;
- }
-
- public function getIssuer()
- {
- return $this->issuer;
- }
-
- public function isIssuerIncludedAsParameter()
- {
- return $this->issuer_included_as_parameter;
- }
-
- public function setIssuerIncludedAsParameter($issuer_included_as_parameter)
- {
- $this->issuer_included_as_parameter = $issuer_included_as_parameter;
-
- return $this;
- }
-
- public function setDigits($digits)
- {
- if (!is_numeric($digits) || $digits < 1) {
- throw new \Exception('Digits must be at least 1.');
- }
- $this->digits = $digits;
-
- return $this;
- }
-
- public function getDigits()
- {
- return $this->digits;
- }
-
- public function setDigest($digest)
- {
- if (!in_array($digest, array('md5', 'sha1', 'sha256', 'sha512'))) {
- throw new \Exception("'$digest' digest is not supported.");
- }
- $this->digest = $digest;
-
- return $this;
- }
-
- public function getDigest()
- {
- return $this->digest;
- }
-
- private function hasSemicolon($value)
- {
- $semicolons = array(':', '%3A', '%3a');
- foreach ($semicolons as $semicolon) {
- if (false !== strpos($value, $semicolon)) {
- return true;
- }
- }
-
- return false;
- }
-}
diff --git a/src/include/Kolab2FA/OTP/TOTP.php b/src/include/Kolab2FA/OTP/TOTP.php
deleted file mode 100644
--- a/src/include/Kolab2FA/OTP/TOTP.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-/**
- * Kolab TOTP implementation based on Spomky-Labs/otphp
- *
- * This basically follows the exmaple implementation from
- * https://github.com/Spomky-Labs/otphp/tree/master/examples
- *
- * @author Thomas Bruederli <bruederli@kolabsys.com>
- *
- * Copyright (C) 2015, Kolab Systems AG <contact@kolabsys.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-namespace Kolab2FA\OTP;
-
-use OTPHP\TOTP as Base;
-
-class TOTP extends Base
-{
- use OTP;
- protected $interval = 30;
-
- public function setInterval($interval)
- {
- if (!is_integer($interval) || $interval < 1) {
- throw new \Exception('Interval must be at least 1.');
- }
- $this->interval = $interval;
-
- return $this;
- }
-
- public function getInterval()
- {
- return $this->interval;
- }
-}
diff --git a/src/phpstan.neon b/src/phpstan.neon
--- a/src/phpstan.neon
+++ b/src/phpstan.neon
@@ -8,7 +8,6 @@
- '#Call to an undefined [a-zA-Z0-9<>\\ ]+::withObjectTenantContext\(\)#'
- '#Call to an undefined [a-zA-Z0-9<>\\ ]+::withSubjectTenantContext\(\)#'
- '#Call to an undefined method Tests\\Browser::#'
- - '#Call to an undefined method Illuminate\\Support\\Fluent::references\(\)#'
level: 4
parallel:
processTimeout: 300.0
@@ -17,4 +16,5 @@
- config/
- database/
- resources/
+ - routes/
- tests/
diff --git a/src/phpunit.xml b/src/phpunit.xml
--- a/src/phpunit.xml
+++ b/src/phpunit.xml
@@ -37,7 +37,7 @@
<server name="APP_ENV" value="testing"/>
<server name="APP_DEBUG" value="true"/>
<server name="BCRYPT_ROUNDS" value="4"/>
- <server name="MAIL_DRIVER" value="array"/>
+ <server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="SWOOLE_HTTP_ACCESS_LOG" value="false"/>
diff --git a/src/public/index.php b/src/public/index.php
--- a/src/public/index.php
+++ b/src/public/index.php
@@ -1,14 +1,14 @@
<?php
-/**
- * Laravel - A PHP Framework For Web Artisans
- *
- * @package Laravel
- * @author Taylor Otwell <taylor@laravel.com>
- */
+use Illuminate\Contracts\Http\Kernel;
+use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
+if (file_exists($maintenance = __DIR__ . '/../storage/framework/maintenance.php')) {
+ require $maintenance;
+}
+
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
@@ -21,7 +21,7 @@
|
*/
-require __DIR__.'/../vendor/autoload.php';
+require __DIR__ . '/../vendor/autoload.php';
/*
|--------------------------------------------------------------------------
@@ -35,7 +35,7 @@
|
*/
-$app = require_once __DIR__.'/../bootstrap/app.php';
+$app = require_once __DIR__ . '/../bootstrap/app.php';
/*
|--------------------------------------------------------------------------
@@ -49,10 +49,10 @@
|
*/
-$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
+$kernel = $app->make(Kernel::class);
$response = $kernel->handle(
- $request = Illuminate\Http\Request::capture()
+ $request = Request::capture()
);
$response->send();
diff --git a/src/resources/lang/en/auth.php b/src/resources/lang/en/auth.php
--- a/src/resources/lang/en/auth.php
+++ b/src/resources/lang/en/auth.php
@@ -14,6 +14,7 @@
*/
'failed' => 'Invalid username or password.',
+ 'password' => 'The provided password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
'logoutsuccess' => 'Successfully logged out.',
diff --git a/src/resources/lang/en/validation.php b/src/resources/lang/en/validation.php
--- a/src/resources/lang/en/validation.php
+++ b/src/resources/lang/en/validation.php
@@ -14,12 +14,13 @@
*/
'accepted' => 'The :attribute must be accepted.',
+ 'accepted_if' => 'The :attribute must be accepted when :other is :value.',
'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.',
+ 'alpha' => 'The :attribute must only contain letters.',
+ 'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.',
+ 'alpha_num' => 'The :attribute must 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.',
@@ -31,9 +32,12 @@
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
+ 'current_password' => 'The password is incorrect.',
'date' => 'The :attribute is not a valid date.',
'date_equals' => 'The :attribute must be a date equal to :date.',
'date_format' => 'The :attribute does not match the format :format.',
+ 'declined' => 'The :attribute must be declined.',
+ 'declined_if' => 'The :attribute must be declined when :other is :value.',
'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.',
@@ -41,6 +45,7 @@
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'The :attribute must be a valid email address.',
'ends_with' => 'The :attribute must end with one of the following: :values',
+ 'enum' => 'The selected :attribute is invalid.',
'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.',
@@ -82,6 +87,7 @@
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
+ 'mac_address' => 'The :attribute must be a valid MAC address.',
'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [
@@ -90,12 +96,18 @@
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
+ 'multiple_of' => 'The :attribute must be a multiple of :value.',
'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.',
+ 'prohibited' => 'The :attribute field is prohibited.',
+ 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
+ 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
+ 'prohibits' => 'The :attribute field prohibits :other from being present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
+ 'required_array_keys' => 'The :attribute field must contain entries for: :values.',
'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.',
@@ -111,10 +123,10 @@
],
'starts_with' => 'The :attribute must start with one of the following: :values',
'string' => 'The :attribute must be a string.',
- 'timezone' => 'The :attribute must be a valid zone.',
+ 'timezone' => 'The :attribute must be a valid timezone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
- 'url' => 'The :attribute format is invalid.',
+ 'url' => 'The :attribute must be a valid URL.',
'uuid' => 'The :attribute must be a valid UUID.',
'2fareq' => 'Second factor code is required.',
diff --git a/src/routes/api.php b/src/routes/api.php
--- a/src/routes/api.php
+++ b/src/routes/api.php
@@ -1,6 +1,8 @@
<?php
+use App\Http\Controllers\API;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
@@ -13,23 +15,21 @@
|
*/
-$prefix = \trim(\parse_url(\config('app.url'), PHP_URL_PATH), '/') . '/';
-
Route::group(
[
'middleware' => 'api',
- 'prefix' => $prefix . 'api/auth'
+ 'prefix' => 'auth'
],
- function ($router) {
- Route::post('login', 'API\AuthController@login');
+ function () {
+ Route::post('login', [API\AuthController::class, 'login']);
Route::group(
['middleware' => 'auth:api'],
- function ($router) {
- Route::get('info', 'API\AuthController@info');
- Route::post('info', 'API\AuthController@info');
- Route::post('logout', 'API\AuthController@logout');
- Route::post('refresh', 'API\AuthController@refresh');
+ function () {
+ Route::get('info', [API\AuthController::class, 'info']);
+ Route::post('info', [API\AuthController::class, 'info']);
+ Route::post('logout', [API\AuthController::class, 'logout']);
+ Route::post('refresh', [API\AuthController::class, 'refresh']);
}
);
}
@@ -39,131 +39,115 @@
[
'domain' => \config('app.website_domain'),
'middleware' => 'api',
- 'prefix' => $prefix . 'api/auth'
- ],
- function ($router) {
- Route::post('password-policy/check', 'API\PasswordPolicyController@check');
-
- Route::post('password-reset/init', 'API\PasswordResetController@init');
- Route::post('password-reset/verify', 'API\PasswordResetController@verify');
- Route::post('password-reset', 'API\PasswordResetController@reset');
-
- Route::post('signup/init', 'API\SignupController@init');
- Route::get('signup/invitations/{id}', 'API\SignupController@invitation');
- Route::get('signup/plans', 'API\SignupController@plans');
- Route::post('signup/verify', 'API\SignupController@verify');
- Route::post('signup', 'API\SignupController@signup');
- }
-);
-
-Route::group(
- [
- 'domain' => \config('app.website_domain'),
- 'middleware' => 'auth:api',
- 'prefix' => $prefix . 'api/v4'
+ 'prefix' => 'auth'
],
function () {
- Route::post('companion/register', 'API\V4\CompanionAppsController@register');
-
- Route::post('auth-attempts/{id}/confirm', 'API\V4\AuthAttemptsController@confirm');
- Route::post('auth-attempts/{id}/deny', 'API\V4\AuthAttemptsController@deny');
- Route::get('auth-attempts/{id}/details', 'API\V4\AuthAttemptsController@details');
- Route::get('auth-attempts', 'API\V4\AuthAttemptsController@index');
-
- Route::apiResource('domains', 'API\V4\DomainsController');
- Route::get('domains/{id}/confirm', 'API\V4\DomainsController@confirm');
- Route::get('domains/{id}/skus', 'API\V4\SkusController@domainSkus');
- Route::get('domains/{id}/status', 'API\V4\DomainsController@status');
- Route::post('domains/{id}/config', 'API\V4\DomainsController@setConfig');
-
- Route::apiResource('groups', 'API\V4\GroupsController');
- Route::get('groups/{id}/status', 'API\V4\GroupsController@status');
- Route::post('groups/{id}/config', 'API\V4\GroupsController@setConfig');
-
- Route::apiResource('packages', 'API\V4\PackagesController');
-
- Route::apiResource('resources', 'API\V4\ResourcesController');
- Route::get('resources/{id}/status', 'API\V4\ResourcesController@status');
- Route::post('resources/{id}/config', 'API\V4\ResourcesController@setConfig');
-
- Route::apiResource('shared-folders', 'API\V4\SharedFoldersController');
- Route::get('shared-folders/{id}/status', 'API\V4\SharedFoldersController@status');
- Route::post('shared-folders/{id}/config', 'API\V4\SharedFoldersController@setConfig');
-
- Route::apiResource('skus', 'API\V4\SkusController');
-
- Route::apiResource('users', 'API\V4\UsersController');
- Route::post('users/{id}/config', 'API\V4\UsersController@setConfig');
- Route::get('users/{id}/skus', 'API\V4\SkusController@userSkus');
- Route::get('users/{id}/status', 'API\V4\UsersController@status');
-
- Route::apiResource('wallets', 'API\V4\WalletsController');
- Route::get('wallets/{id}/transactions', 'API\V4\WalletsController@transactions');
- Route::get('wallets/{id}/receipts', 'API\V4\WalletsController@receipts');
- Route::get('wallets/{id}/receipts/{receipt}', 'API\V4\WalletsController@receiptDownload');
-
- Route::get('password-policy', 'API\PasswordPolicyController@index');
- Route::post('password-reset/code', 'API\PasswordResetController@codeCreate');
- Route::delete('password-reset/code/{id}', 'API\PasswordResetController@codeDelete');
-
- Route::post('payments', 'API\V4\PaymentsController@store');
- //Route::delete('payments', 'API\V4\PaymentsController@cancel');
- Route::get('payments/mandate', 'API\V4\PaymentsController@mandate');
- Route::post('payments/mandate', 'API\V4\PaymentsController@mandateCreate');
- Route::put('payments/mandate', 'API\V4\PaymentsController@mandateUpdate');
- Route::delete('payments/mandate', 'API\V4\PaymentsController@mandateDelete');
- Route::get('payments/methods', 'API\V4\PaymentsController@paymentMethods');
- Route::get('payments/pending', 'API\V4\PaymentsController@payments');
- Route::get('payments/has-pending', 'API\V4\PaymentsController@hasPayments');
-
- Route::get('openvidu/rooms', 'API\V4\OpenViduController@index');
- Route::post('openvidu/rooms/{id}/close', 'API\V4\OpenViduController@closeRoom');
- Route::post('openvidu/rooms/{id}/config', 'API\V4\OpenViduController@setRoomConfig');
+ Route::post('password-policy/check', [API\PasswordPolicyController::class, 'check']);
- // FIXME: I'm not sure about this one, should we use DELETE request maybe?
- Route::post('openvidu/rooms/{id}/connections/{conn}/dismiss', 'API\V4\OpenViduController@dismissConnection');
- Route::put('openvidu/rooms/{id}/connections/{conn}', 'API\V4\OpenViduController@updateConnection');
- Route::post('openvidu/rooms/{id}/request/{reqid}/accept', 'API\V4\OpenViduController@acceptJoinRequest');
- Route::post('openvidu/rooms/{id}/request/{reqid}/deny', 'API\V4\OpenViduController@denyJoinRequest');
+ Route::post('password-reset/init', [API\PasswordResetController::class, 'init']);
+ Route::post('password-reset/verify', [API\PasswordResetController::class, 'verify']);
+ Route::post('password-reset', [API\PasswordResetController::class, 'reset']);
+
+ Route::post('signup/init', [API\SignupController::class, 'init']);
+ Route::get('signup/invitations/{id}', [API\SignupController::class, 'invitation']);
+ Route::get('signup/plans', [API\SignupController::class, 'plans']);
+ Route::post('signup/verify', [API\SignupController::class, 'verify']);
+ Route::post('signup', [API\SignupController::class, 'signup']);
}
);
-// Note: In Laravel 7.x we could just use withoutMiddleware() instead of a separate group
Route::group(
[
'domain' => \config('app.website_domain'),
- 'prefix' => $prefix . 'api/v4'
+ 'middleware' => 'auth:api',
+ 'prefix' => 'v4'
],
function () {
- Route::post('openvidu/rooms/{id}', 'API\V4\OpenViduController@joinRoom');
- Route::post('openvidu/rooms/{id}/connections', 'API\V4\OpenViduController@createConnection');
+ Route::post('companion/register', [API\V4\CompanionAppsController::class, 'register']);
+
+ Route::post('auth-attempts/{id}/confirm', [API\V4\AuthAttemptsController::class, 'confirm']);
+ Route::post('auth-attempts/{id}/deny', [API\V4\AuthAttemptsController::class, 'deny']);
+ Route::get('auth-attempts/{id}/details', [API\V4\AuthAttemptsController::class, 'details']);
+ Route::get('auth-attempts', [API\V4\AuthAttemptsController::class, 'index']);
+
+ Route::apiResource('domains', API\V4\DomainsController::class);
+ Route::get('domains/{id}/confirm', [API\V4\DomainsController::class, 'confirm']);
+ Route::get('domains/{id}/skus', [API\V4\SkusController::class, 'domainSkus']);
+ Route::get('domains/{id}/status', [API\V4\DomainsController::class, 'status']);
+ Route::post('domains/{id}/config', [API\V4\DomainsController::class, 'setConfig']);
+
+ Route::apiResource('groups', API\V4\GroupsController::class);
+ Route::get('groups/{id}/status', [API\V4\GroupsController::class, 'status']);
+ Route::post('groups/{id}/config', [API\V4\GroupsController::class, 'setConfig']);
+
+ Route::apiResource('packages', API\V4\PackagesController::class);
+
+ Route::apiResource('resources', API\V4\ResourcesController::class);
+ Route::get('resources/{id}/status', [API\V4\ResourcesController::class, 'status']);
+ Route::post('resources/{id}/config', [API\V4\ResourcesController::class, 'setConfig']);
+
+ Route::apiResource('shared-folders', API\V4\SharedFoldersController::class);
+ Route::get('shared-folders/{id}/status', [API\V4\SharedFoldersController::class, 'status']);
+ Route::post('shared-folders/{id}/config', [API\V4\SharedFoldersController::class, 'setConfig']);
+
+ Route::apiResource('skus', API\V4\SkusController::class);
+
+ Route::apiResource('users', API\V4\UsersController::class);
+ Route::post('users/{id}/config', [API\V4\UsersController::class, 'setConfig']);
+ Route::get('users/{id}/skus', [API\V4\SkusController::class, 'userSkus']);
+ Route::get('users/{id}/status', [API\V4\UsersController::class, 'status']);
+
+ Route::apiResource('wallets', API\V4\WalletsController::class);
+ Route::get('wallets/{id}/transactions', [API\V4\WalletsController::class, 'transactions']);
+ Route::get('wallets/{id}/receipts', [API\V4\WalletsController::class, 'receipts']);
+ Route::get('wallets/{id}/receipts/{receipt}', [API\V4\WalletsController::class, 'receiptDownload']);
+
+ Route::get('password-policy', [API\PasswordPolicyController::class, 'index']);
+ Route::post('password-reset/code', [API\PasswordResetController::class, 'codeCreate']);
+ Route::delete('password-reset/code/{id}', [API\PasswordResetController::class, 'codeDelete']);
+
+ Route::post('payments', [API\V4\PaymentsController::class, 'store']);
+ //Route::delete('payments', [API\V4\PaymentsController::class, 'cancel']);
+ Route::get('payments/mandate', [API\V4\PaymentsController::class, 'mandate']);
+ Route::post('payments/mandate', [API\V4\PaymentsController::class, 'mandateCreate']);
+ Route::put('payments/mandate', [API\V4\PaymentsController::class, 'mandateUpdate']);
+ Route::delete('payments/mandate', [API\V4\PaymentsController::class, 'mandateDelete']);
+ Route::get('payments/methods', [API\V4\PaymentsController::class, 'paymentMethods']);
+ Route::get('payments/pending', [API\V4\PaymentsController::class, 'payments']);
+ Route::get('payments/has-pending', [API\V4\PaymentsController::class, 'hasPayments']);
+
+ Route::get('openvidu/rooms', [API\V4\OpenViduController::class, 'index']);
+ Route::post('openvidu/rooms/{id}/close', [API\V4\OpenViduController::class, 'closeRoom']);
+ Route::post('openvidu/rooms/{id}/config', [API\V4\OpenViduController::class, 'setRoomConfig']);
+
+ Route::post('openvidu/rooms/{id}', [API\V4\OpenViduController::class, 'joinRoom'])
+ ->withoutMiddleware(['auth:api']);
+ Route::post('openvidu/rooms/{id}/connections', [API\V4\OpenViduController::class, 'createConnection'])
+ ->withoutMiddleware(['auth:api']);
// FIXME: I'm not sure about this one, should we use DELETE request maybe?
- Route::post('openvidu/rooms/{id}/connections/{conn}/dismiss', 'API\V4\OpenViduController@dismissConnection');
- Route::put('openvidu/rooms/{id}/connections/{conn}', 'API\V4\OpenViduController@updateConnection');
- Route::post('openvidu/rooms/{id}/request/{reqid}/accept', 'API\V4\OpenViduController@acceptJoinRequest');
- Route::post('openvidu/rooms/{id}/request/{reqid}/deny', 'API\V4\OpenViduController@denyJoinRequest');
- }
-);
-
-Route::group(
- [
- 'domain' => \config('app.website_domain'),
- 'middleware' => 'api',
- 'prefix' => $prefix . 'api/v4'
- ],
- function ($router) {
- Route::post('support/request', 'API\V4\SupportController@request');
+ Route::post('openvidu/rooms/{id}/connections/{conn}/dismiss', [API\V4\OpenViduController::class, 'dismissConnection'])
+ ->withoutMiddleware(['auth:api']);
+ Route::put('openvidu/rooms/{id}/connections/{conn}', [API\V4\OpenViduController::class, 'updateConnection'])
+ ->withoutMiddleware(['auth:api']);
+ Route::post('openvidu/rooms/{id}/request/{reqid}/accept', [API\V4\OpenViduController::class, 'acceptJoinRequest'])
+ ->withoutMiddleware(['auth:api']);
+ Route::post('openvidu/rooms/{id}/request/{reqid}/deny', [API\V4\OpenViduController::class, 'denyJoinRequest'])
+ ->withoutMiddleware(['auth:api']);
+
+ Route::post('support/request', [API\V4\SupportController::class, 'request'])
+ ->withoutMiddleware(['auth:api'])
+ ->middleware(['api']);
}
);
Route::group(
[
'domain' => \config('app.website_domain'),
- 'prefix' => $prefix . 'api/webhooks'
+ 'prefix' => 'webhooks'
],
function () {
- Route::post('payment/{provider}', 'API\V4\PaymentsController@webhook');
- Route::post('meet/openvidu', 'API\V4\OpenViduController@webhook');
+ Route::post('payment/{provider}', [API\V4\PaymentsController::class, 'webhook']);
+ Route::post('meet/openvidu', [API\V4\OpenViduController::class, 'webhook']);
}
);
@@ -171,14 +155,14 @@
Route::group(
[
'domain' => 'services.' . \config('app.website_domain'),
- 'prefix' => $prefix . 'api/webhooks'
+ 'prefix' => 'webhooks'
],
function () {
- Route::get('nginx', 'API\V4\NGINXController@authenticate');
- Route::get('nginx-httpauth', 'API\V4\NGINXController@httpauth');
- Route::post('policy/greylist', 'API\V4\PolicyController@greylist');
- Route::post('policy/ratelimit', 'API\V4\PolicyController@ratelimit');
- Route::post('policy/spf', 'API\V4\PolicyController@senderPolicyFramework');
+ Route::get('nginx', [API\V4\NGINXController::class, 'authenticate']);
+ Route::get('nginx-httpauth', [API\V4\NGINXController::class, 'httpauth']);
+ Route::post('policy/greylist', [API\V4\PolicyController::class, 'greylist']);
+ Route::post('policy/ratelimit', [API\V4\PolicyController::class, 'ratelimit']);
+ Route::post('policy/spf', [API\V4\PolicyController::class, 'senderPolicyFramework']);
}
);
}
@@ -188,33 +172,35 @@
[
'domain' => 'admin.' . \config('app.website_domain'),
'middleware' => ['auth:api', 'admin'],
- 'prefix' => $prefix . 'api/v4',
+ 'prefix' => 'v4',
],
function () {
- Route::apiResource('domains', 'API\V4\Admin\DomainsController');
- Route::get('domains/{id}/skus', 'API\V4\Admin\SkusController@domainSkus');
- Route::post('domains/{id}/suspend', 'API\V4\Admin\DomainsController@suspend');
- Route::post('domains/{id}/unsuspend', 'API\V4\Admin\DomainsController@unsuspend');
-
- Route::apiResource('groups', 'API\V4\Admin\GroupsController');
- Route::post('groups/{id}/suspend', 'API\V4\Admin\GroupsController@suspend');
- Route::post('groups/{id}/unsuspend', 'API\V4\Admin\GroupsController@unsuspend');
-
- Route::apiResource('resources', 'API\V4\Admin\ResourcesController');
- Route::apiResource('shared-folders', 'API\V4\Admin\SharedFoldersController');
- Route::apiResource('skus', 'API\V4\Admin\SkusController');
- Route::apiResource('users', 'API\V4\Admin\UsersController');
- Route::get('users/{id}/discounts', 'API\V4\Reseller\DiscountsController@userDiscounts');
- Route::post('users/{id}/reset2FA', 'API\V4\Admin\UsersController@reset2FA');
- Route::get('users/{id}/skus', 'API\V4\Admin\SkusController@userSkus');
- Route::post('users/{id}/skus/{sku}', 'API\V4\Admin\UsersController@setSku');
- Route::post('users/{id}/suspend', 'API\V4\Admin\UsersController@suspend');
- Route::post('users/{id}/unsuspend', 'API\V4\Admin\UsersController@unsuspend');
- Route::apiResource('wallets', 'API\V4\Admin\WalletsController');
- Route::post('wallets/{id}/one-off', 'API\V4\Admin\WalletsController@oneOff');
- Route::get('wallets/{id}/transactions', 'API\V4\Admin\WalletsController@transactions');
-
- Route::get('stats/chart/{chart}', 'API\V4\Admin\StatsController@chart');
+ Route::apiResource('domains', API\V4\Admin\DomainsController::class);
+ Route::get('domains/{id}/skus', [API\V4\Admin\SkusController::class, 'domainSkus']);
+ Route::post('domains/{id}/suspend', [API\V4\Admin\DomainsController::class, 'suspend']);
+ Route::post('domains/{id}/unsuspend', [API\V4\Admin\DomainsController::class, 'unsuspend']);
+
+ Route::apiResource('groups', API\V4\Admin\GroupsController::class);
+ Route::post('groups/{id}/suspend', [API\V4\Admin\GroupsController::class, 'suspend']);
+ Route::post('groups/{id}/unsuspend', [API\V4\Admin\GroupsController::class, 'unsuspend']);
+
+ Route::apiResource('resources', API\V4\Admin\ResourcesController::class);
+ Route::apiResource('shared-folders', API\V4\Admin\SharedFoldersController::class);
+ Route::apiResource('skus', API\V4\Admin\SkusController::class);
+
+ Route::apiResource('users', API\V4\Admin\UsersController::class);
+ Route::get('users/{id}/discounts', [API\V4\Reseller\DiscountsController::class, 'userDiscounts']);
+ Route::post('users/{id}/reset2FA', [API\V4\Admin\UsersController::class, 'reset2FA']);
+ Route::get('users/{id}/skus', [API\V4\Admin\SkusController::class, 'userSkus']);
+ Route::post('users/{id}/skus/{sku}', [API\V4\Admin\UsersController::class, 'setSku']);
+ Route::post('users/{id}/suspend', [API\V4\Admin\UsersController::class, 'suspend']);
+ Route::post('users/{id}/unsuspend', [API\V4\Admin\UsersController::class, 'unsuspend']);
+
+ Route::apiResource('wallets', API\V4\Admin\WalletsController::class);
+ Route::post('wallets/{id}/one-off', [API\V4\Admin\WalletsController::class, 'oneOff']);
+ Route::get('wallets/{id}/transactions', [API\V4\Admin\WalletsController::class, 'transactions']);
+
+ Route::get('stats/chart/{chart}', [API\V4\Admin\StatsController::class, 'chart']);
}
);
}
@@ -224,47 +210,49 @@
[
'domain' => 'reseller.' . \config('app.website_domain'),
'middleware' => ['auth:api', 'reseller'],
- 'prefix' => $prefix . 'api/v4',
+ 'prefix' => 'v4',
],
function () {
- Route::apiResource('domains', 'API\V4\Reseller\DomainsController');
- Route::get('domains/{id}/skus', 'API\V4\Reseller\SkusController@domainSkus');
- Route::post('domains/{id}/suspend', 'API\V4\Reseller\DomainsController@suspend');
- Route::post('domains/{id}/unsuspend', 'API\V4\Reseller\DomainsController@unsuspend');
-
- Route::apiResource('groups', 'API\V4\Reseller\GroupsController');
- Route::post('groups/{id}/suspend', 'API\V4\Reseller\GroupsController@suspend');
- Route::post('groups/{id}/unsuspend', 'API\V4\Reseller\GroupsController@unsuspend');
-
- Route::apiResource('invitations', 'API\V4\Reseller\InvitationsController');
- Route::post('invitations/{id}/resend', 'API\V4\Reseller\InvitationsController@resend');
-
- Route::post('payments', 'API\V4\Reseller\PaymentsController@store');
- Route::get('payments/mandate', 'API\V4\Reseller\PaymentsController@mandate');
- Route::post('payments/mandate', 'API\V4\Reseller\PaymentsController@mandateCreate');
- Route::put('payments/mandate', 'API\V4\Reseller\PaymentsController@mandateUpdate');
- Route::delete('payments/mandate', 'API\V4\Reseller\PaymentsController@mandateDelete');
- Route::get('payments/methods', 'API\V4\Reseller\PaymentsController@paymentMethods');
- Route::get('payments/pending', 'API\V4\Reseller\PaymentsController@payments');
- Route::get('payments/has-pending', 'API\V4\Reseller\PaymentsController@hasPayments');
-
- Route::apiResource('resources', 'API\V4\Reseller\ResourcesController');
- Route::apiResource('shared-folders', 'API\V4\Reseller\SharedFoldersController');
- Route::apiResource('skus', 'API\V4\Reseller\SkusController');
- Route::apiResource('users', 'API\V4\Reseller\UsersController');
- Route::get('users/{id}/discounts', 'API\V4\Reseller\DiscountsController@userDiscounts');
- Route::post('users/{id}/reset2FA', 'API\V4\Reseller\UsersController@reset2FA');
- Route::get('users/{id}/skus', 'API\V4\Reseller\SkusController@userSkus');
- Route::post('users/{id}/skus/{sku}', 'API\V4\Admin\UsersController@setSku');
- Route::post('users/{id}/suspend', 'API\V4\Reseller\UsersController@suspend');
- Route::post('users/{id}/unsuspend', 'API\V4\Reseller\UsersController@unsuspend');
- Route::apiResource('wallets', 'API\V4\Reseller\WalletsController');
- Route::post('wallets/{id}/one-off', 'API\V4\Reseller\WalletsController@oneOff');
- Route::get('wallets/{id}/receipts', 'API\V4\Reseller\WalletsController@receipts');
- Route::get('wallets/{id}/receipts/{receipt}', 'API\V4\Reseller\WalletsController@receiptDownload');
- Route::get('wallets/{id}/transactions', 'API\V4\Reseller\WalletsController@transactions');
-
- Route::get('stats/chart/{chart}', 'API\V4\Reseller\StatsController@chart');
+ Route::apiResource('domains', API\V4\Reseller\DomainsController::class);
+ Route::get('domains/{id}/skus', [API\V4\Reseller\SkusController::class, 'domainSkus']);
+ Route::post('domains/{id}/suspend', [API\V4\Reseller\DomainsController::class, 'suspend']);
+ Route::post('domains/{id}/unsuspend', [API\V4\Reseller\DomainsController::class, 'unsuspend']);
+
+ Route::apiResource('groups', API\V4\Reseller\GroupsController::class);
+ Route::post('groups/{id}/suspend', [API\V4\Reseller\GroupsController::class, 'suspend']);
+ Route::post('groups/{id}/unsuspend', [API\V4\Reseller\GroupsController::class, 'unsuspend']);
+
+ Route::apiResource('invitations', API\V4\Reseller\InvitationsController::class);
+ Route::post('invitations/{id}/resend', [API\V4\Reseller\InvitationsController::class, 'resend']);
+
+ Route::post('payments', [API\V4\Reseller\PaymentsController::class, 'store']);
+ Route::get('payments/mandate', [API\V4\Reseller\PaymentsController::class, 'mandate']);
+ Route::post('payments/mandate', [API\V4\Reseller\PaymentsController::class, 'mandateCreate']);
+ Route::put('payments/mandate', [API\V4\Reseller\PaymentsController::class, 'mandateUpdate']);
+ Route::delete('payments/mandate', [API\V4\Reseller\PaymentsController::class, 'mandateDelete']);
+ Route::get('payments/methods', [API\V4\Reseller\PaymentsController::class, 'paymentMethods']);
+ Route::get('payments/pending', [API\V4\Reseller\PaymentsController::class, 'payments']);
+ Route::get('payments/has-pending', [API\V4\Reseller\PaymentsController::class, 'hasPayments']);
+
+ Route::apiResource('resources', API\V4\Reseller\ResourcesController::class);
+ Route::apiResource('shared-folders', API\V4\Reseller\SharedFoldersController::class);
+ Route::apiResource('skus', API\V4\Reseller\SkusController::class);
+
+ Route::apiResource('users', API\V4\Reseller\UsersController::class);
+ Route::get('users/{id}/discounts', [API\V4\Reseller\DiscountsController::class, 'userDiscounts']);
+ Route::post('users/{id}/reset2FA', [API\V4\Reseller\UsersController::class, 'reset2FA']);
+ Route::get('users/{id}/skus', [API\V4\Reseller\SkusController::class, 'userSkus']);
+ Route::post('users/{id}/skus/{sku}', [API\V4\Admin\UsersController::class, 'setSku']);
+ Route::post('users/{id}/suspend', [API\V4\Reseller\UsersController::class, 'suspend']);
+ Route::post('users/{id}/unsuspend', [API\V4\Reseller\UsersController::class, 'unsuspend']);
+
+ Route::apiResource('wallets', API\V4\Reseller\WalletsController::class);
+ Route::post('wallets/{id}/one-off', [API\V4\Reseller\WalletsController::class, 'oneOff']);
+ Route::get('wallets/{id}/receipts', [API\V4\Reseller\WalletsController::class, 'receipts']);
+ Route::get('wallets/{id}/receipts/{receipt}', [API\V4\Reseller\WalletsController::class, 'receiptDownload']);
+ Route::get('wallets/{id}/transactions', [API\V4\Reseller\WalletsController::class, 'transactions']);
+
+ Route::get('stats/chart/{chart}', [API\V4\Reseller\StatsController::class, 'chart']);
}
);
}
diff --git a/src/routes/channels.php b/src/routes/channels.php
--- a/src/routes/channels.php
+++ b/src/routes/channels.php
@@ -1,5 +1,7 @@
<?php
+use Illuminate\Support\Facades\Broadcast;
+
/*
|--------------------------------------------------------------------------
| Broadcast Channels
diff --git a/src/routes/console.php b/src/routes/console.php
--- a/src/routes/console.php
+++ b/src/routes/console.php
@@ -1,6 +1,7 @@
<?php
use Illuminate\Foundation\Inspiring;
+use Illuminate\Support\Facades\Artisan;
/*
|--------------------------------------------------------------------------
@@ -14,5 +15,5 @@
*/
Artisan::command('inspire', function () {
- $this->comment(Inspiring::quote());
+ $this->comment(Inspiring::quote()); // @phpstan-ignore-line
})->describe('Display an inspiring quote');
diff --git a/src/routes/web.php b/src/routes/web.php
--- a/src/routes/web.php
+++ b/src/routes/web.php
@@ -1,5 +1,8 @@
<?php
+use App\Http\Controllers;
+use Illuminate\Support\Facades\Route;
+
// We can handle every URL with the default action because
// we have client-side router (including 404 error handler).
// This way we don't have to define any "deep link" routes here.
@@ -8,16 +11,16 @@
//'domain' => \config('app.website_domain'),
],
function () {
- Route::get('content/page/{page}', 'ContentController@pageContent')
+ Route::get('content/page/{page}', Controllers\ContentController::class . '@pageContent')
->where('page', '(.*)');
- Route::get('content/faq/{page}', 'ContentController@faqContent')
+ Route::get('content/faq/{page}', Controllers\ContentController::class . '@faqContent')
->where('page', '(.*)');
Route::fallback(
function () {
// Return 404 for requests to the API end-points that do not exist
if (strpos(request()->path(), 'api/') === 0) {
- return \App\Http\Controllers\Controller::errorResponse(404);
+ return Controllers\Controller::errorResponse(404);
}
$env = \App\Utils::uiEnv();
diff --git a/src/routes/websocket.php b/src/routes/websocket.php
deleted file mode 100644
--- a/src/routes/websocket.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-use Illuminate\Http\Request;
-use SwooleTW\Http\Websocket\Facades\Websocket;
-
-/*
-|--------------------------------------------------------------------------
-| Websocket Routes
-|--------------------------------------------------------------------------
-|
-| Here is where you can register websocket events for your application.
-|
-*/
-
-Websocket::on(
- 'connect',
- function ($websocket, Request $request) {
- return;
- }
-);
-
-Websocket::on(
- 'open',
- function ($websocket, Request $request) {
- return;
- }
-);
-
-Websocket::on(
- 'disconnect',
- function ($websocket) {
- return;
- }
-);
-
-//Websocket::on('message', 'App\Http\Controllers\WebsocketController@message');
-//Websocket::on('ping', 'App\Http\Controllers\WebsocketController@ping');
diff --git a/src/storage/framework/.gitignore b/src/storage/framework/.gitignore
--- a/src/storage/framework/.gitignore
+++ b/src/storage/framework/.gitignore
@@ -1,8 +1,9 @@
+compiled.php
config.php
+down
+events.scanned.php
+maintenance.php
routes.php
+routes.scanned.php
schedule-*
-compiled.php
services.json
-events.scanned.php
-routes.scanned.php
-down
diff --git a/src/tests/Browser/DomainTest.php b/src/tests/Browser/DomainTest.php
--- a/src/tests/Browser/DomainTest.php
+++ b/src/tests/Browser/DomainTest.php
@@ -47,6 +47,17 @@
}
/**
+ * Test domains list page (unauthenticated)
+ */
+ public function testDomainListUnauth(): void
+ {
+ // Test that the page requires authentication
+ $this->browse(function ($browser) {
+ $browser->visit('/domains')->on(new Home());
+ });
+ }
+
+ /**
* Test domain info page (non-existing domain id)
*/
public function testDomainInfo404(): void
@@ -164,19 +175,6 @@
}
/**
- * Test domains list page (unauthenticated)
- */
- public function testDomainListUnauth(): void
- {
- // Test that the page requires authentication
- $this->browse(function ($browser) {
- $browser->visit('/logout')
- ->visit('/domains')
- ->on(new Home());
- });
- }
-
- /**
* Test domains list page
*
* @depends testDomainListUnauth
@@ -245,7 +243,7 @@
$this->browse(function ($browser) {
$browser->visit('/login')
->on(new Home())
- ->submitLogon('john@kolab.org', 'simple123')
+ ->submitLogon('john@kolab.org', 'simple123', true)
->visit('/domains')
->on(new DomainList())
->assertSeeIn('.card-title button.btn-success', 'Create domain')
diff --git a/src/tests/Browser/ErrorTest.php b/src/tests/Browser/ErrorTest.php
--- a/src/tests/Browser/ErrorTest.php
+++ b/src/tests/Browser/ErrorTest.php
@@ -7,7 +7,6 @@
class ErrorTest extends TestCaseDusk
{
-
/**
* Test error 404 page on unknown route
*
diff --git a/src/tests/Browser/SharedFolderTest.php b/src/tests/Browser/SharedFolderTest.php
--- a/src/tests/Browser/SharedFolderTest.php
+++ b/src/tests/Browser/SharedFolderTest.php
@@ -239,7 +239,7 @@
// Test creation/updating a mail folder with mail aliases
$this->browse(function (Browser $browser) {
$browser->on(new SharedFolderList())
- ->click('button.create-folder')
+ ->click('button.shared-folder-new')
->on(new SharedFolderInfo())
->type('#name', 'Test Folder2')
->with(new ListInput('#aliases'), function (Browser $browser) {
diff --git a/src/tests/Feature/Auth/SecondFactorTest.php b/src/tests/Feature/Auth/SecondFactorTest.php
--- a/src/tests/Feature/Auth/SecondFactorTest.php
+++ b/src/tests/Feature/Auth/SecondFactorTest.php
@@ -10,7 +10,9 @@
class SecondFactorTest extends TestCase
{
-
+ /**
+ * {@inheritDoc}
+ */
public function setUp(): void
{
parent::setUp();
@@ -18,6 +20,9 @@
$this->deleteTestUser('entitlement-test@kolabnow.com');
}
+ /**
+ * {@inheritDoc}
+ */
public function tearDown(): void
{
$this->deleteTestUser('entitlement-test@kolabnow.com');
diff --git a/src/tests/Feature/AuthAttemptTest.php b/src/tests/Feature/AuthAttemptTest.php
--- a/src/tests/Feature/AuthAttemptTest.php
+++ b/src/tests/Feature/AuthAttemptTest.php
@@ -7,7 +7,9 @@
class AuthAttemptTest extends TestCase
{
-
+ /**
+ * {@inheritDoc}
+ */
public function setUp(): void
{
parent::setUp();
@@ -15,6 +17,9 @@
$this->deleteTestUser('jane@kolabnow.com');
}
+ /**
+ * {@inheritDoc}
+ */
public function tearDown(): void
{
$this->deleteTestUser('jane@kolabnow.com');
diff --git a/src/tests/Feature/Console/Data/Import/LdifTest.php b/src/tests/Feature/Console/Data/Import/LdifTest.php
--- a/src/tests/Feature/Console/Data/Import/LdifTest.php
+++ b/src/tests/Feature/Console/Data/Import/LdifTest.php
@@ -92,6 +92,7 @@
// Users
$this->assertSame(2, $owner->users(false)->count());
+ /** @var \App\User $user */
$user = $owner->users(false)->where('email', 'user@kolab3.com')->first();
// User settings
@@ -112,6 +113,7 @@
]);
// Domains
+ /** @var \App\Domain[] $domains */
$domains = $owner->domains(false, false)->orderBy('namespace')->get();
$this->assertCount(2, $domains);
@@ -124,6 +126,7 @@
$this->assertEntitlements($domains[1], ['domain-hosting']);
// Shared folders
+ /** @var \App\SharedFolder[] $folders */
$folders = $owner->sharedFolders(false)->orderBy('email')->get();
$this->assertCount(2, $folders);
@@ -144,6 +147,7 @@
);
// Groups
+ /** @var \App\Group[] $groups */
$groups = $owner->groups(false)->orderBy('email')->get();
$this->assertCount(1, $groups);
@@ -153,6 +157,7 @@
$this->assertSame('["sender@gmail.com","-"]', $groups[0]->getSetting('sender_policy'));
// Resources
+ /** @var \App\Resource[] $resources */
$resources = $owner->resources(false)->orderBy('email')->get();
$this->assertCount(1, $resources);
diff --git a/src/tests/Feature/Console/Scalpel/TenantSetting/CreateCommandTest.php b/src/tests/Feature/Console/Scalpel/TenantSetting/CreateCommandTest.php
--- a/src/tests/Feature/Console/Scalpel/TenantSetting/CreateCommandTest.php
+++ b/src/tests/Feature/Console/Scalpel/TenantSetting/CreateCommandTest.php
@@ -38,7 +38,7 @@
$setting = $tenant->settings()->where('key', 'test')->first();
- $this->assertSame('init', $setting->fresh()->value);
+ $this->assertSame('init', $setting->value);
$this->assertSame('init', $tenant->fresh()->getSetting('test'));
}
}
diff --git a/src/tests/Feature/Console/Scalpel/WalletSetting/CreateCommandTest.php b/src/tests/Feature/Console/Scalpel/WalletSetting/CreateCommandTest.php
--- a/src/tests/Feature/Console/Scalpel/WalletSetting/CreateCommandTest.php
+++ b/src/tests/Feature/Console/Scalpel/WalletSetting/CreateCommandTest.php
@@ -17,7 +17,7 @@
$setting = $wallet->settings()->where('key', 'test')->first();
- $this->assertSame('init', $setting->fresh()->value);
+ $this->assertSame('init', $setting->value);
$this->assertSame('init', $wallet->fresh()->getSetting('test'));
}
}
diff --git a/src/tests/Feature/Controller/SupportTest.php b/src/tests/Feature/Controller/SupportTest.php
--- a/src/tests/Feature/Controller/SupportTest.php
+++ b/src/tests/Feature/Controller/SupportTest.php
@@ -47,7 +47,7 @@
$this->assertCount(1, $json['errors']);
$this->assertSame(['The email must be a valid email address.'], $json['errors']['email']);
- $this->assertCount(0, $this->app->make('swift.transport')->driver()->messages());
+ $this->assertCount(0, $this->getSentMessages());
// Valid input
$post = [
@@ -66,17 +66,44 @@
$this->assertSame('success', $json['status']);
$this->assertSame('Support request submitted successfully.', $json['message']);
- $emails = $this->app->make('swift.transport')->driver()->messages();
+ $emails = $this->getSentMessages();
- $expected_body = "ID: 1234567\nName: Username\nWorking email address: test@test.com\n"
+ $this->assertCount(1, $emails);
+
+ $to = $emails[0]->getTo();
+ $from = $emails[0]->getFrom();
+ $replyTo = $emails[0]->getReplyTo();
+ $expectedBody = "ID: 1234567\nName: Username\nWorking email address: test@test.com\n"
. "Subject: Test summary\n\nTest body";
- $this->assertCount(1, $emails);
+ $this->assertCount(1, $to);
+ $this->assertCount(1, $from);
+ $this->assertCount(1, $replyTo);
$this->assertSame('Test summary', $emails[0]->getSubject());
- $this->assertSame(['test@test.com' => 'Username'], $emails[0]->getFrom());
- $this->assertSame(['test@test.com' => 'Username'], $emails[0]->getReplyTo());
- $this->assertNull($emails[0]->getCc());
- $this->assertSame([$support_email => null], $emails[0]->getTo());
- $this->assertSame($expected_body, trim($emails[0]->getBody()));
+ $this->assertSame('test@test.com', $from[0]->getAddress());
+ $this->assertSame('Username', $from[0]->getName());
+ $this->assertSame('test@test.com', $replyTo[0]->getAddress());
+ $this->assertSame('Username', $replyTo[0]->getName());
+ $this->assertSame([], $emails[0]->getCc());
+ $this->assertSame($support_email, $to[0]->getAddress());
+ $this->assertSame('', $to[0]->getName());
+ $this->assertSame($expectedBody, trim($emails[0]->getTextBody()));
+ $this->assertSame('', trim($emails[0]->getHtmlBody()));
+ }
+
+ /**
+ * Get all messages that have been sent
+ *
+ * @return \Symfony\Component\Mime\Email[]
+ */
+ protected function getSentMessages(): array
+ {
+ $transport = $this->app->make('mail.manager')->mailer()->getSymfonyTransport();
+
+ return $this->getObjectProperty($transport, 'messages')
+ ->map(function (\Symfony\Component\Mailer\SentMessage $item) {
+ return $item->getOriginalMessage();
+ })
+ ->all();
}
}
diff --git a/src/tests/Feature/Controller/UsersTest.php b/src/tests/Feature/Controller/UsersTest.php
--- a/src/tests/Feature/Controller/UsersTest.php
+++ b/src/tests/Feature/Controller/UsersTest.php
@@ -736,6 +736,7 @@
$this->assertSame('John2', $user->getSetting('first_name'));
$this->assertSame('Doe2', $user->getSetting('last_name'));
$this->assertSame('TestOrg', $user->getSetting('organization'));
+ /** @var \App\UserAlias[] $aliases */
$aliases = $user->aliases()->orderBy('alias')->get();
$this->assertCount(2, $aliases);
$this->assertSame('deleted@kolab.org', $aliases[0]->alias);
diff --git a/src/tests/Feature/Jobs/PasswordResetEmailTest.php b/src/tests/Feature/Jobs/PasswordResetEmailTest.php
--- a/src/tests/Feature/Jobs/PasswordResetEmailTest.php
+++ b/src/tests/Feature/Jobs/PasswordResetEmailTest.php
@@ -11,8 +11,6 @@
class PasswordResetEmailTest extends TestCase
{
- private $code;
-
/**
* {@inheritDoc}
*
diff --git a/src/tests/Feature/SkuTest.php b/src/tests/Feature/SkuTest.php
--- a/src/tests/Feature/SkuTest.php
+++ b/src/tests/Feature/SkuTest.php
@@ -11,7 +11,9 @@
class SkuTest extends TestCase
{
-
+ /**
+ * {@inheritDoc}
+ */
public function setUp(): void
{
parent::setUp();
@@ -19,6 +21,9 @@
$this->deleteTestUser('jane@kolabnow.com');
}
+ /**
+ * {@inheritDoc}
+ */
public function tearDown(): void
{
$this->deleteTestUser('jane@kolabnow.com');
diff --git a/src/tests/Feature/Stories/GreylistTest.php b/src/tests/Feature/Stories/GreylistTest.php
--- a/src/tests/Feature/Stories/GreylistTest.php
+++ b/src/tests/Feature/Stories/GreylistTest.php
@@ -14,7 +14,6 @@
class GreylistTest extends TestCase
{
private $clientAddress;
- private $requests = [];
private $net;
public function setUp(): void
diff --git a/src/tests/Feature/TenantTest.php b/src/tests/Feature/TenantTest.php
--- a/src/tests/Feature/TenantTest.php
+++ b/src/tests/Feature/TenantTest.php
@@ -8,7 +8,6 @@
class TenantTest extends TestCase
{
-
/**
* {@inheritDoc}
*/
diff --git a/src/tests/MailInterceptTrait.php b/src/tests/MailInterceptTrait.php
deleted file mode 100644
--- a/src/tests/MailInterceptTrait.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-
-namespace Tests;
-
-use Illuminate\Mail\Mailable;
-use Illuminate\Support\Facades\Mail;
-use KirschbaumDevelopment\MailIntercept\WithMailInterceptor;
-
-trait MailInterceptTrait
-{
- use WithMailInterceptor;
-
- /**
- * Extract content of a email message.
- *
- * @param \Illuminate\Mail\Mailable $mail Mailable object
- *
- * @return array Parsed message data:
- * - 'plain': Plain text body
- * - 'html: HTML body
- * - 'message': Swift_Message object
- */
- protected function fakeMail(Mailable $mail): array
- {
- $this->interceptMail();
-
- Mail::send($mail);
-
- $message = $this->interceptedMail()->last();
-
- // SwiftMailer does not have methods to get the bodies, we'll parse the message
- list($plain, $html) = $this->extractMailBody($message->toString());
-
- return [
- 'plain' => $plain,
- 'html' => $html,
- 'message' => $message,
- ];
- }
-
- /**
- * Simple message parser to extract plain and html body
- *
- * @param string $message Email message as string
- *
- * @return array Plain text and HTML body
- */
- protected function extractMailBody(string $message): array
- {
- // Note that we're not supporting every message format, we only
- // support what Laravel/SwiftMailer produces
- // TODO: It may stop working if we start using attachments
- $plain = '';
- $html = '';
-
- if (preg_match('/[\s\t]boundary="([^"]+)"/', $message, $matches)) {
- // multipart message assume plain and html parts
- $split = preg_split('/--' . preg_quote($matches[1]) . '/', $message);
-
- list($plain_head, $plain) = explode("\r\n\r\n", $split[1], 2);
- list($html_head, $html) = explode("\r\n\r\n", $split[2], 2);
-
- if (strpos($plain_head, 'Content-Transfer-Encoding: quoted-printable') !== false) {
- $plain = quoted_printable_decode($plain);
- }
-
- if (strpos($html_head, 'Content-Transfer-Encoding: quoted-printable') !== false) {
- $html = quoted_printable_decode($html);
- }
- } else {
- list($header, $html) = explode("\r\n\r\n", $message, 2);
- if (strpos($header, 'Content-Transfer-Encoding: quoted-printable') !== false) {
- $html = quoted_printable_decode($html);
- }
- }
-
- return [$plain, $html];
- }
-}
diff --git a/src/tests/TestCaseTrait.php b/src/tests/TestCaseTrait.php
--- a/src/tests/TestCaseTrait.php
+++ b/src/tests/TestCaseTrait.php
@@ -495,7 +495,7 @@
*
* @return mixed Method return.
*/
- protected function invokeMethod($object, $methodName, array $parameters = array())
+ protected function invokeMethod($object, $methodName, array $parameters = [])
{
$reflection = new \ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
@@ -504,6 +504,29 @@
return $method->invokeArgs($object, $parameters);
}
+ /**
+ * Extract content of an email message.
+ *
+ * @param \Illuminate\Mail\Mailable $mail Mailable object
+ *
+ * @return array Parsed message data:
+ * - 'plain': Plain text body
+ * - 'html: HTML body
+ * - 'subject': Mail subject
+ */
+ protected function renderMail(\Illuminate\Mail\Mailable $mail): array
+ {
+ $mail->build(); // @phpstan-ignore-line
+
+ $result = $this->invokeMethod($mail, 'renderForAssertions');
+
+ return [
+ 'plain' => $result[1],
+ 'html' => $result[0],
+ 'subject' => $mail->subject,
+ ];
+ }
+
protected function setUpTest()
{
$this->userPassword = \App\Utils::generatePassphrase();
diff --git a/src/tests/Unit/Mail/DegradedAccountReminderTest.php b/src/tests/Unit/Mail/DegradedAccountReminderTest.php
--- a/src/tests/Unit/Mail/DegradedAccountReminderTest.php
+++ b/src/tests/Unit/Mail/DegradedAccountReminderTest.php
@@ -5,13 +5,10 @@
use App\Mail\DegradedAccountReminder;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class DegradedAccountReminderTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -20,7 +17,7 @@
$user = $this->getTestUser('ned@kolab.org');
$wallet = $user->wallets->first();
- $mail = $this->fakeMail(new DegradedAccountReminder($wallet, $user));
+ $mail = $this->renderMail(new DegradedAccountReminder($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -29,7 +26,7 @@
$dashboardLink = sprintf('<a href="%s">%s</a>', $dashboardUrl, $dashboardUrl);
$appName = $user->tenant->title;
- $this->assertMailSubject("$appName Reminder: Your account is free", $mail['message']);
+ $this->assertSame("$appName Reminder: Your account is free", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/NegativeBalanceBeforeDeleteTest.php b/src/tests/Unit/Mail/NegativeBalanceBeforeDeleteTest.php
--- a/src/tests/Unit/Mail/NegativeBalanceBeforeDeleteTest.php
+++ b/src/tests/Unit/Mail/NegativeBalanceBeforeDeleteTest.php
@@ -6,13 +6,10 @@
use App\Mail\NegativeBalanceBeforeDelete;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class NegativeBalanceBeforeDeleteTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* {@inheritDoc}
*/
@@ -49,7 +46,7 @@
'app.support_url' => 'https://kolab.org/support',
]);
- $mail = $this->fakeMail(new NegativeBalanceBeforeDelete($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalanceBeforeDelete($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -60,7 +57,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = $user->tenant->title;
- $this->assertMailSubject("$appName Final Warning", $mail['message']);
+ $this->assertSame("$appName Final Warning", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
@@ -93,7 +90,7 @@
'app.public_url' => 'https://test.org',
]);
- $mail = $this->fakeMail(new NegativeBalanceBeforeDelete($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalanceBeforeDelete($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -103,7 +100,7 @@
$supportUrl = 'https://test.org/support';
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
- $this->assertMailSubject("{$tenant->title} Final Warning", $mail['message']);
+ $this->assertSame("{$tenant->title} Final Warning", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/NegativeBalanceDegradedTest.php b/src/tests/Unit/Mail/NegativeBalanceDegradedTest.php
--- a/src/tests/Unit/Mail/NegativeBalanceDegradedTest.php
+++ b/src/tests/Unit/Mail/NegativeBalanceDegradedTest.php
@@ -6,13 +6,10 @@
use App\Mail\NegativeBalanceDegraded;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class NegativeBalanceDegradedTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -27,7 +24,7 @@
'app.support_url' => 'https://kolab.org/support',
]);
- $mail = $this->fakeMail(new NegativeBalanceDegraded($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalanceDegraded($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -38,7 +35,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = $user->tenant->title;
- $this->assertMailSubject("$appName Account Degraded", $mail['message']);
+ $this->assertSame("$appName Account Degraded", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/NegativeBalanceReminderDegradeTest.php b/src/tests/Unit/Mail/NegativeBalanceReminderDegradeTest.php
--- a/src/tests/Unit/Mail/NegativeBalanceReminderDegradeTest.php
+++ b/src/tests/Unit/Mail/NegativeBalanceReminderDegradeTest.php
@@ -6,13 +6,10 @@
use App\Mail\NegativeBalanceReminderDegrade;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class NegativeBalanceReminderDegradeTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -29,7 +26,7 @@
'app.support_url' => 'https://kolab.org/support',
]);
- $mail = $this->fakeMail(new NegativeBalanceReminderDegrade($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalanceReminderDegrade($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -40,7 +37,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = $user->tenant->title;
- $this->assertMailSubject("$appName Payment Reminder", $mail['message']);
+ $this->assertSame("$appName Payment Reminder", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/NegativeBalanceReminderTest.php b/src/tests/Unit/Mail/NegativeBalanceReminderTest.php
--- a/src/tests/Unit/Mail/NegativeBalanceReminderTest.php
+++ b/src/tests/Unit/Mail/NegativeBalanceReminderTest.php
@@ -6,13 +6,10 @@
use App\Mail\NegativeBalanceReminder;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class NegativeBalanceReminderTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -29,7 +26,7 @@
'app.support_url' => 'https://kolab.org/support',
]);
- $mail = $this->fakeMail(new NegativeBalanceReminder($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalanceReminder($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -40,7 +37,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = $user->tenant->title;
- $this->assertMailSubject("$appName Payment Reminder", $mail['message']);
+ $this->assertSame("$appName Payment Reminder", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/NegativeBalanceSuspendedTest.php b/src/tests/Unit/Mail/NegativeBalanceSuspendedTest.php
--- a/src/tests/Unit/Mail/NegativeBalanceSuspendedTest.php
+++ b/src/tests/Unit/Mail/NegativeBalanceSuspendedTest.php
@@ -6,13 +6,10 @@
use App\Mail\NegativeBalanceSuspended;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class NegativeBalanceSuspendedTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -29,7 +26,7 @@
'app.support_url' => 'https://kolab.org/support',
]);
- $mail = $this->fakeMail(new NegativeBalanceSuspended($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalanceSuspended($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -40,7 +37,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = $user->tenant->title;
- $this->assertMailSubject("$appName Account Suspended", $mail['message']);
+ $this->assertSame("$appName Account Suspended", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/NegativeBalanceTest.php b/src/tests/Unit/Mail/NegativeBalanceTest.php
--- a/src/tests/Unit/Mail/NegativeBalanceTest.php
+++ b/src/tests/Unit/Mail/NegativeBalanceTest.php
@@ -5,13 +5,10 @@
use App\Mail\NegativeBalance;
use App\User;
use App\Wallet;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class NegativeBalanceTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -24,7 +21,7 @@
'app.support_url' => 'https://kolab.org/support',
]);
- $mail = $this->fakeMail(new NegativeBalance($wallet, $user));
+ $mail = $this->renderMail(new NegativeBalance($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -35,7 +32,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = \config('app.name');
- $this->assertMailSubject("$appName Payment Required", $mail['message']);
+ $this->assertSame("$appName Payment Required", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/PasswordResetTest.php b/src/tests/Unit/Mail/PasswordResetTest.php
--- a/src/tests/Unit/Mail/PasswordResetTest.php
+++ b/src/tests/Unit/Mail/PasswordResetTest.php
@@ -6,13 +6,10 @@
use App\User;
use App\Utils;
use App\VerificationCode;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class PasswordResetTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -29,7 +26,7 @@
'name' => 'User Name',
]);
- $mail = $this->fakeMail(new PasswordReset($code));
+ $mail = $this->renderMail(new PasswordReset($code));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -38,7 +35,7 @@
$link = "<a href=\"$url\">$url</a>";
$appName = \config('app.name');
- $this->assertMailSubject("$appName Password Reset", $mail['message']);
+ $this->assertSame("$appName Password Reset", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $link) > 0);
diff --git a/src/tests/Unit/Mail/PaymentFailureTest.php b/src/tests/Unit/Mail/PaymentFailureTest.php
--- a/src/tests/Unit/Mail/PaymentFailureTest.php
+++ b/src/tests/Unit/Mail/PaymentFailureTest.php
@@ -5,13 +5,10 @@
use App\Mail\PaymentFailure;
use App\Payment;
use App\User;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class PaymentFailureTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -23,7 +20,7 @@
\config(['app.support_url' => 'https://kolab.org/support']);
- $mail = $this->fakeMail(new PaymentFailure($payment, $user));
+ $mail = $this->renderMail(new PaymentFailure($payment, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -34,7 +31,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = \config('app.name');
- $this->assertMailSubject("$appName Payment Failed", $mail['message']);
+ $this->assertSame("$appName Payment Failed", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/PaymentMandateDisabledTest.php b/src/tests/Unit/Mail/PaymentMandateDisabledTest.php
--- a/src/tests/Unit/Mail/PaymentMandateDisabledTest.php
+++ b/src/tests/Unit/Mail/PaymentMandateDisabledTest.php
@@ -5,13 +5,10 @@
use App\Mail\PaymentMandateDisabled;
use App\Wallet;
use App\User;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class PaymentMandateDisabledTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -22,7 +19,7 @@
\config(['app.support_url' => 'https://kolab.org/support']);
- $mail = $this->fakeMail(new PaymentMandateDisabled($wallet, $user));
+ $mail = $this->renderMail(new PaymentMandateDisabled($wallet, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -33,7 +30,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = \config('app.name');
- $this->assertMailSubject("$appName Auto-payment Problem", $mail['message']);
+ $this->assertSame("$appName Auto-payment Problem", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/PaymentSuccessTest.php b/src/tests/Unit/Mail/PaymentSuccessTest.php
--- a/src/tests/Unit/Mail/PaymentSuccessTest.php
+++ b/src/tests/Unit/Mail/PaymentSuccessTest.php
@@ -5,13 +5,10 @@
use App\Mail\PaymentSuccess;
use App\Payment;
use App\User;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class PaymentSuccessTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -23,7 +20,7 @@
\config(['app.support_url' => 'https://kolab.org/support']);
- $mail = $this->fakeMail(new PaymentSuccess($payment, $user));
+ $mail = $this->renderMail(new PaymentSuccess($payment, $user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -34,7 +31,7 @@
$supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
$appName = \config('app.name');
- $this->assertMailSubject("$appName Payment Succeeded", $mail['message']);
+ $this->assertSame("$appName Payment Succeeded", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);
diff --git a/src/tests/Unit/Mail/SignupInvitationTest.php b/src/tests/Unit/Mail/SignupInvitationTest.php
--- a/src/tests/Unit/Mail/SignupInvitationTest.php
+++ b/src/tests/Unit/Mail/SignupInvitationTest.php
@@ -5,13 +5,10 @@
use App\Mail\SignupInvitation;
use App\SignupInvitation as SI;
use App\Utils;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class SignupInvitationTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -22,7 +19,7 @@
'email' => 'test@email',
]);
- $mail = $this->fakeMail(new SignupInvitation($invitation));
+ $mail = $this->renderMail(new SignupInvitation($invitation));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -31,7 +28,7 @@
$link = "<a href=\"$url\">$url</a>";
$appName = \config('app.name');
- $this->assertMailSubject("$appName Invitation", $mail['message']);
+ $this->assertSame("$appName Invitation", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $link) > 0);
diff --git a/src/tests/Unit/Mail/SignupVerificationTest.php b/src/tests/Unit/Mail/SignupVerificationTest.php
--- a/src/tests/Unit/Mail/SignupVerificationTest.php
+++ b/src/tests/Unit/Mail/SignupVerificationTest.php
@@ -5,13 +5,10 @@
use App\Mail\SignupVerification;
use App\SignupCode;
use App\Utils;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class SignupVerificationTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -25,7 +22,7 @@
'last_name' => 'Last',
]);
- $mail = $this->fakeMail(new SignupVerification($code));
+ $mail = $this->renderMail(new SignupVerification($code));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -34,7 +31,7 @@
$link = "<a href=\"$url\">$url</a>";
$appName = \config('app.name');
- $this->assertMailSubject("$appName Registration", $mail['message']);
+ $this->assertSame("$appName Registration", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $link) > 0);
diff --git a/src/tests/Unit/Mail/SuspendedDebtorTest.php b/src/tests/Unit/Mail/SuspendedDebtorTest.php
--- a/src/tests/Unit/Mail/SuspendedDebtorTest.php
+++ b/src/tests/Unit/Mail/SuspendedDebtorTest.php
@@ -4,13 +4,10 @@
use App\Mail\SuspendedDebtor;
use App\User;
-use Tests\MailInterceptTrait;
use Tests\TestCase;
class SuspendedDebtorTest extends TestCase
{
- use MailInterceptTrait;
-
/**
* Test email content
*/
@@ -24,7 +21,7 @@
'app.kb.account_delete' => 'https://kb.kolab.org/account-delete',
]);
- $mail = $this->fakeMail(new SuspendedDebtor($user));
+ $mail = $this->renderMail(new SuspendedDebtor($user));
$html = $mail['html'];
$plain = $mail['plain'];
@@ -39,7 +36,7 @@
$moreLink = sprintf('<a href="%s">here</a>', $moreUrl);
$appName = \config('app.name');
- $this->assertMailSubject("$appName Account Suspended", $mail['message']);
+ $this->assertSame("$appName Account Suspended", $mail['subject']);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $user->name(true)) > 0);

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 5, 6:59 AM (10 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18832697
Default Alt Text
D3409.1775372384.diff (196 KB)

Event Timeline