Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117896068
D3409.1775372384.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
196 KB
Referenced Files
None
Subscribers
None
D3409.1775372384.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D3409: Laravel v9
Attached
Detach File
Event Timeline