refactor: replace custom CRM with Monica fork
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s

This commit is contained in:
Kroonk
2026-05-22 16:19:55 +02:00
parent 38cc4c09ca
commit a213a1dba0
2215 changed files with 242567 additions and 6015 deletions

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('loginRedirect');
}
return '';
}
}

View File

@@ -0,0 +1,149 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Models\User\User;
use Illuminate\Http\Request;
use Illuminate\Auth\AuthManager;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
/**
* Authenticate user with Basic Authentication, with Passport token on password field.
*
* Examples:
* curl -u "email@example.com:$TOKEN" -X PROPFIND https://localhost/dav/
* curl -u ":$TOKEN" -X PROPFIND https://localhost/dav/
*/
class AuthenticateWithTokenOnBasicAuth
{
/**
* The guard factory instance.
*
* @var AuthManager
*
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param AuthManager $auth
* @return void
*/
public function __construct(AuthManager $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$this->authenticate($request);
return $next($request);
}
/**
* Handle authentication.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
private function authenticate($request)
{
if ($this->auth->guard()->check()) {
return;
}
if (! $this->basicAuth($request)) {
$this->failedBasicResponse();
}
}
/**
* Try Bearer authentication, with token in 'password' field on basic auth.
*
* @param \Illuminate\Http\Request $request
*/
private function basicAuth(Request $request)
{
if (! $this->assertToken($request)) {
return false;
}
$user = $this->authUser($request);
// match User header if present
if ($user && (! $request->getUser() || $request->getUser() === $user->email)) {
$this->auth->guard()->setUser($user);
return true;
}
return false;
}
/**
* Authenticate user.
*
* @param \Illuminate\Http\Request $request
* @return User|null
*/
private function authUser(Request $request): ?User
{
$headerUser = $request->getUser();
$user = null;
try {
// Remove User from header request as Laravel auth will not authenticate using Bearer token
$request->headers->set('PHP_AUTH_USER', '');
/** @var \Illuminate\Auth\RequestGuard */
$guard = $this->auth->guard('api');
/** @var ?User */
$user = $guard->setRequest($request)
->user();
} finally {
$request->headers->set('PHP_AUTH_USER', $headerUser);
}
return $user;
}
/**
* Assert Bearer token is present.
* If not using 'password' field on basic auth as Bearer token.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
private function assertToken(Request $request): bool
{
if (! $request->bearerToken()) {
$password = $request->getPassword();
$request->headers->set('Authorization', 'Bearer '.$password);
}
return true;
}
/**
* Get the response for basic authentication.
*
* @return void
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*/
protected function failedBasicResponse()
{
throw new UnauthorizedHttpException('Basic', 'Invalid credentials.');
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Helpers\AccountHelper;
use Illuminate\Support\Facades\Auth;
class CheckAccountLimitations
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check() && AccountHelper::hasLimitations(auth()->user()->account)) {
abort(402);
}
return $next($request);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Helpers\ComplianceHelper;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
class CheckCompliance
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->isMethod('post')) {
return $next($request);
}
if (Route::currentRouteName() == 'compliance') {
return $next($request);
}
if (Auth::check() && ! ComplianceHelper::isCompliantWithCurrentTerm(auth()->user())) {
return redirect()->route('compliance');
}
return $next($request);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Helpers\LocaleHelper;
use Illuminate\Support\Facades\App;
class CheckLocale
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$locale = $request->query('lang');
if (empty($locale)) {
$locale = LocaleHelper::getLocale();
}
App::setLocale($locale);
return $next($request);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Http\Middleware;
use Closure;
use PharIo\Version\Version;
use App\Models\Instance\Instance;
class CheckVersion
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (($version = config('monica.app_version')) !== '') {
$instance = Instance::first();
$appVersion = new Version($version);
$latestVersion = new Version($instance->latest_version ?? '0.0.0');
$currentVersion = new Version($instance->current_version ?? '0.0.0');
if ($latestVersion == $appVersion && $currentVersion != $latestVersion) {
// The instance has been updated to the latest version. We reset
// the ping data.
$instance->current_version = $instance->latest_version;
$instance->latest_release_notes = null;
$instance->number_of_versions_since_current_version = null;
$instance->save();
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int,string>
*/
protected $except = [
//
];
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Middleware\EnsureEmailIsVerified as Middleware;
class EnsureEmailIsVerified extends Middleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle($request, Closure $next, $redirectToRoute = null)
{
if (config('monica.signup_double_optin')) {
return parent::handle($request, $next, $redirectToRoute);
}
return $next($request);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int,string>
*/
protected $except = [
//
];
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect()->route('dashboard.index');
}
return $next($request);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Sentry\State\Scope;
use App\Helpers\RequestHelper;
class SentryContext
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (app()->bound('sentry') && config('monica.sentry_support')) {
// Add user context
if (auth()->check()) {
\Sentry\configureScope(function (Scope $scope): void {
$user = auth()->user();
$scope->setUser([
'id' => $user->id,
'email' => $user->email,
'username' => $user->name,
]);
$scope->setExtra('isSubscribed', $user->account->isSubscribed());
});
} else {
\Sentry\configureScope(function (Scope $scope): void {
$scope->setUser([
'id' => null,
'ip_address' => RequestHelper::ip(),
]);
});
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int,string>
*/
protected $except = [
'password',
'password_confirmation',
];
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Http\Middleware;
use Monicahq\Cloudflare\Http\Middleware\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* Get the trusted proxies.
*
* @return array|string|null
*/
protected function proxies()
{
return config('app.trust_proxies') ?? $this->proxies;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
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<int,string>
*/
protected $except = [
'stripe/*',
];
}