first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
<?php
namespace Common\Core\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class EnableDebugIfLoggedInAsAdmin
{
public function handle(Request $request, Closure $next)
{
if ($this->loggedInAsAdmin()) {
config(['app.debug' => true]);
}
return $next($request);
}
protected function loggedInAsAdmin(): bool
{
return Auth::user() && Auth::user()->hasPermission('admin');
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Common\Core\Middleware;
use Closure;
use Common\Settings\Settings;
use Illuminate\Auth\Middleware\EnsureEmailIsVerified as LaravelMiddleware;
class EnsureEmailIsVerified extends LaravelMiddleware
{
public function handle($request, Closure $next, $redirectToRoute = null)
{
// bail if user is not logged in, it will be handled by policies
// also bail if email verification is disabled from settings page
if (
!$request->user() ||
!app(Settings::class)->get('require_email_confirmation')
) {
return $next($request);
}
return parent::handle($request, $next, $redirectToRoute);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Common\Core\Middleware;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful as LaravelMiddleware;
class EnsureFrontendRequestsAreStateful extends LaravelMiddleware
{
public static function fromFrontend($request): bool
{
$domain =
$request->headers->get('referer') ?:
$request->headers->get('origin');
if (is_null($domain)) {
return false;
}
// make sure api calls from api docs page are not considered stateful to avoid 419 errors on POST requests
if (Str::contains($domain, '/api-docs')) {
return false;
}
$domain = parse_url($domain, PHP_URL_HOST);
$domain = Str::replaceFirst('www.', '', $domain);
$domain = Str::endsWith($domain, '/') ? $domain : "{$domain}/";
$stateful = [
...array_filter(config('sanctum.stateful', [])),
parse_url(config('app.url'), PHP_URL_HOST),
];
return Str::is(
Collection::make($stateful)
->map(
fn($uri) => Str::replaceFirst('www.', '', trim($uri)) .
'/*',
)
->all(),
$domain,
);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Common\Core\Middleware;
use Auth;
use Closure;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Request;
class IsAdmin
{
public function handle(Request $request, Closure $next)
{
if ( ! Auth::check()) {
throw new AuthenticationException();
}
if ( ! Auth::user()->hasPermission('admin')) {
throw new AuthorizationException();
}
return $next($request);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Common\Core\Middleware;
use Closure;
use Illuminate\Http\Request;
class JsonMiddleware
{
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
//$request->headers->set('Content-Type', 'application/json');
return $next($request);
}
}

View File

@@ -0,0 +1,92 @@
<?php namespace Common\Core\Middleware;
use Closure;
use Common\Core\Controllers\HomeController;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class PrerenderIfCrawler
{
protected array $crawlerUserAgents = [
'Yahoo! Slurp',
'bingbot',
'yandex',
'baiduspider',
'facebookexternalhit',
'twitterbot',
'rogerbot',
'linkedinbot',
'embedly',
'quora link preview',
'showyoubot',
'outbrain',
'pinterest/0.',
'slackbot',
'vkShare',
'W3C_Validator',
'redditbot',
'Applebot',
'WhatsApp',
'flipboard',
'tumblr',
'bitlybot',
'SkypeUriPreview',
'nuzzel',
'Discordbot',
'Qwantify',
'pinterestbot',
'Bitrix link preview',
'XING-contenttabreceiver',
'developers.google.com/+/web/snippet',
];
public function handle(
Request $request,
Closure $next,
string $routeName = null
) {
if ($this->shouldPrerender($request)) {
define('SHOULD_PRERENDER', true);
// Always fallback to client routes if not prerendering
// otherwise prerender routes will override client side routing
} elseif ($routeName !== 'homepage') {
return app(HomeController::class)->show();
}
return $next($request);
}
protected function shouldPrerender(Request $request): bool
{
$userAgent = strtolower($request->server->get('HTTP_USER_AGENT'));
$bufferAgent = $request->server->get('X-BUFFERBOT');
$shouldPrerender = false;
if (!$userAgent) {
return false;
}
if (!$request->isMethod('GET')) {
return false;
}
// prerender if _escaped_fragment_ is in the query string
if ($request->query->has('_escaped_fragment_')) {
$shouldPrerender = true;
}
// prerender if a crawler is detected
foreach ($this->crawlerUserAgents as $crawlerUserAgent) {
if (Str::contains($userAgent, strtolower($crawlerUserAgent))) {
$shouldPrerender = true;
}
}
if ($bufferAgent) {
$shouldPrerender = true;
}
return $shouldPrerender;
}
}

View File

@@ -0,0 +1,177 @@
<?php namespace Common\Core\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
class RestrictDemoSiteFunctionality
{
public function handle(Request $request, Closure $next)
{
if (
Auth::user() &&
Auth::user()->email === 'Ic0OdCIodqz8q1r@demo.com'
) {
return $next($request);
}
$uri = str_replace(
['secure/', 'api/v1/'],
'',
$request->route()->uri(),
);
if ($this->shouldForbidRequest($request, $uri)) {
abort(403, "You can't do that on demo site.");
}
if ($uri === 'settings') {
return $this->manglePrivateSettings($next($request));
}
if ($uri === 'users' || $uri === 'billing/subscriptions') {
return $this->mangleUserEmails($next($request));
}
if (
($uri === 'billing/stripe/cards/add' ||
$uri === 'billing/subscriptions/paypal/agreement/create') &&
(Auth::user() && Auth::user()->email === 'admin@admin.com')
) {
abort(403, "Demo admin account can't subscribe to plans.");
}
return $next($request);
}
/**
* Check if specified request should be forbidden on demo site.
*/
private function shouldForbidRequest(Request $request, string $uri): bool
{
$method = $request->method();
foreach (config('common.demo-blocked-routes') as $route) {
if (
$method === $route['method'] &&
trim($uri) === trim($route['name'])
) {
$originMatches = true;
$paramsMatch = true;
//block this request only if it originated from specified origin, for example: admin area
if (isset($route['origin'])) {
$originMatches = Str::contains(
$request->server('HTTP_REFERER'),
$route['origin'],
);
}
if (isset($route['params'])) {
$paramsMatch =
collect($route['params'])->first(function (
$param,
$key
) use ($request) {
$routeParam = $request->route($key);
if (is_array($param)) {
return in_array($routeParam, $param);
} else {
return $routeParam == $param;
}
}) !== null;
}
return $originMatches && $paramsMatch;
}
}
return false;
}
/**
* Mangle settings values, so they are not visible on demo site.
*/
private function manglePrivateSettings(Response $response): Response
{
$serverKeys = [
'google_id',
'google_secret',
'twitter_id',
'twitter_secret',
'facebook_id',
'facebook_secret',
'spotify_id',
'spotify_secret',
'lastfm_api_key',
'soundcloud_api_key',
'sentry_dns',
'mailgun_secret',
'sentry_dsn',
'paypal_client_id',
'pusher_key',
'pusher_secret',
'paypal_secret',
'stripe_key',
'stripe_secret',
'mail_password',
'tmdb_api_key',
'storage_digitalocean_key',
'storage_digitalocean_secret',
'stripe_webhook_secret',
'openai_api_key',
];
$clientKeys = [
'youtube_api_key',
'logging.sentry_public',
'analytics.google_id',
'builder.google_fonts_api_key',
'recaptcha.site_key',
'recaptcha.secret_key',
];
$settings = json_decode($response->getContent(), true);
foreach ($serverKeys as $key) {
if (isset($settings['server'][$key])) {
$settings['server'][$key] = Str::random(30);
}
}
foreach ($clientKeys as $key) {
if (isset($settings['client'][$key])) {
$settings['client'][$key] = Str::random(30);
}
}
$response->setContent(json_encode($settings));
return $response;
}
/**
* Mangle settings values, so they are not visible on demo site.
*/
private function mangleUserEmails(Response $response): Response
{
$pagination = json_decode($response->getContent(), true);
$pagination['data'] = array_map(function ($item) {
if (isset($item['email'])) {
$item['email'] = 'hidden@demo.com';
} elseif (isset($item['user']['email'])) {
$item['user']['email'] = 'hidden@demo.com';
}
return $item;
}, Arr::get($pagination, 'data', []));
$response->setContent(json_encode($pagination));
return $response;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Common\Core\Middleware;
use Closure;
use Common\Localizations\Localization;
use Common\Localizations\UserLocaleController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Negotiation\LanguageNegotiator;
class SetAppLocale
{
public function handle(Request $request, Closure $next)
{
if (settings('i18n.enable')) {
// 1. Check if current user has manually selected a specific language
$langCode =
$request->get('lang') ??
($request->user()->language ??
Cookie::get(UserLocaleController::COOKIE_NAME));
$defaultLocale = settings('locale.default', 'auto');
// 2. if admin manually selected a specific default locale, use that
if (!$langCode && $defaultLocale && $defaultLocale !== 'auto') {
$langCode = $defaultLocale;
}
// 3. Try to use language based on browser settings
if (!$langCode && ($header = $request->header('Accept-Language'))) {
$languages = Localization::pluck('language');
if ($languages->isNotEmpty()) {
$bestLanguage = (new LanguageNegotiator())->getBest(
$header,
$languages->toArray(),
);
$langCode = $bestLanguage?->getBasePart();
}
}
if ($langCode) {
app()->setLocale($langCode);
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Common\Core\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Sentry\State\Scope;
use function Sentry\configureScope;
class SetSentryUserMiddleware
{
public function handle(Request $request, Closure $next)
{
if ($user = Auth::user()) {
configureScope(function (Scope $scope) use ($user) {
$scope->setUser(['email' => $user->email, 'id' => $user->id]);
});
}
return $next($request);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Common\Core\Middleware;
use Closure;
use Illuminate\Http\Request;
class SimulateSlowConnectionMiddleware
{
public function handle(Request $request, Closure $next)
{
if ($speed = config('common.site.simulated_connection')) {
if ($speed === 'medium') {
// 200ms
usleep(200000);
} elseif ($speed === 'slow') {
// 1s
sleep(1);
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Common\Core\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*/
protected $proxies = '*';
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
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;
}