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,238 @@
<?php
namespace App\Providers;
use App\Helpers\DBHelper;
use Laravel\Cashier\Cashier;
use Laravel\Passport\Passport;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\View;
use App\Notifications\EmailMessaging;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Validation\Rules\Password;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Auth\Notifications\VerifyEmail;
use Werk365\EtagConditionals\EtagConditionals;
use Illuminate\Auth\Notifications\ResetPassword;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (App::runningInConsole()) {
Command::macro('exec', function (string $message, string $commandline) {
// @codeCoverageIgnoreStart
/** @var \Illuminate\Console\Command */
$command = $this;
\App\Console\Commands\Helpers\Command::exec($command, $message, $commandline);
// @codeCoverageIgnoreEnd
});
Command::macro('artisan', function (string $message, string $commandline, array $arguments = []) {
/** @var \Illuminate\Console\Command */
$command = $this;
\App\Console\Commands\Helpers\Command::artisan($command, $message, $commandline, $arguments);
});
}
View::composer(
'partials.components.currency-select', 'App\Http\ViewComposers\CurrencySelectViewComposer'
);
View::composer(
'partials.components.date-select', 'App\Http\ViewComposers\DateSelectViewComposer'
);
View::composer(
'partials.check', 'App\Http\ViewComposers\InstanceViewComposer'
);
Password::defaults(function () {
if (! $this->app->environment('production')) {
return Password::min(6);
}
$rules = Password::min(config('app.password_min'));
$config = explode(',', config('app.password_rules'));
if (in_array('mixedCase', $config)) {
$rules = $rules->mixedCase();
}
if (in_array('letters', $config)) {
$rules = $rules->letters();
}
if (in_array('numbers', $config)) {
$rules = $rules->numbers();
}
if (in_array('symbols', $config)) {
$rules = $rules->symbols();
}
if (in_array('uncompromised', $config)) {
$rules = $rules->uncompromised();
}
return $rules;
});
if (config('database.use_utf8mb4')
&& DBHelper::connection()->getDriverName() == 'mysql'
&& ! DBHelper::testVersion('5.7.7')) {
Schema::defaultStringLength(191);
}
Cashier::useCustomerModel(\App\Models\Account\Account::class);
VerifyEmail::toMailUsing(function ($user, $verificationUrl) {
return EmailMessaging::verifyEmailMail($user, $verificationUrl);
});
ResetPassword::toMailUsing(function ($user, $token) {
return EmailMessaging::resetPasswordMail($user, $token);
});
Paginator::defaultView('vendor.pagination.default');
RateLimiter::for('GPSCoordinate', function () {
return [
Limit::perMinute(60),
Limit::perDay(5000),
];
});
EtagConditionals::etagGenerateUsing(function (\Illuminate\Http\Request $request, \Symfony\Component\HttpFoundation\Response $response) {
$url = $request->getRequestUri();
return Cache::rememberForever('etag.'.$url, function () use ($url) {
return sha1($url);
});
});
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Passport::ignoreMigrations();
Cashier::ignoreMigrations();
Cashier::formatCurrencyUsing(function ($amount, $currency) {
$currency = \App\Models\Settings\Currency::where('iso', strtoupper($currency ?? config('cashier.currency')))->first();
return \App\Helpers\MoneyHelper::format($amount, $currency);
});
}
/**
* All of the container singletons that should be registered.
*
* @var array
*/
public $singletons = [
\App\Services\Account\Activity\Activity\AttachContactToActivity::class => \App\Services\Account\Activity\Activity\AttachContactToActivity::class,
\App\Services\Account\Activity\Activity\CreateActivity::class => \App\Services\Account\Activity\Activity\CreateActivity::class,
\App\Services\Account\Activity\Activity\DestroyActivity::class => \App\Services\Account\Activity\Activity\DestroyActivity::class,
\App\Services\Account\Activity\Activity\UpdateActivity::class => \App\Services\Account\Activity\Activity\UpdateActivity::class,
\App\Services\Account\Activity\ActivityStatisticService::class => \App\Services\Account\Activity\ActivityStatisticService::class,
\App\Services\Account\Activity\ActivityTypeCategory\CreateActivityTypeCategory::class => \App\Services\Account\Activity\ActivityTypeCategory\CreateActivityTypeCategory::class,
\App\Services\Account\Activity\ActivityTypeCategory\DestroyActivityTypeCategory::class => \App\Services\Account\Activity\ActivityTypeCategory\DestroyActivityTypeCategory::class,
\App\Services\Account\Activity\ActivityTypeCategory\UpdateActivityTypeCategory::class => \App\Services\Account\Activity\ActivityTypeCategory\UpdateActivityTypeCategory::class,
\App\Services\Account\Activity\ActivityType\CreateActivityType::class => \App\Services\Account\Activity\ActivityType\CreateActivityType::class,
\App\Services\Account\Activity\ActivityType\DestroyActivityType::class => \App\Services\Account\Activity\ActivityType\DestroyActivityType::class,
\App\Services\Account\Activity\ActivityType\UpdateActivityType::class => \App\Services\Account\Activity\ActivityType\UpdateActivityType::class,
\App\Services\Account\Company\CreateCompany::class => \App\Services\Account\Company\CreateCompany::class,
\App\Services\Account\Company\DestroyCompany::class => \App\Services\Account\Company\DestroyCompany::class,
\App\Services\Account\Company\UpdateCompany::class => \App\Services\Account\Company\UpdateCompany::class,
\App\Services\Account\Settings\DestroyAllDocuments::class => \App\Services\Account\Settings\DestroyAllDocuments::class,
\App\Services\Account\Gender\CreateGender::class => \App\Services\Account\Gender\CreateGender::class,
\App\Services\Account\Gender\DestroyGender::class => \App\Services\Account\Gender\DestroyGender::class,
\App\Services\Account\Gender\UpdateGender::class => \App\Services\Account\Gender\UpdateGender::class,
\App\Services\Account\Photo\DestroyPhoto::class => \App\Services\Account\Photo\DestroyPhoto::class,
\App\Services\Account\Photo\UploadPhoto::class => \App\Services\Account\Photo\UploadPhoto::class,
\App\Services\Account\Place\CreatePlace::class => \App\Services\Account\Place\CreatePlace::class,
\App\Services\Account\Place\DestroyPlace::class => \App\Services\Account\Place\DestroyPlace::class,
\App\Services\Account\Place\UpdatePlace::class => \App\Services\Account\Place\UpdatePlace::class,
\App\Services\User\CreateUser::class => \App\Services\User\CreateUser::class,
\App\Services\Auth\Population\PopulateContactFieldTypesTable::class => \App\Services\Auth\Population\PopulateContactFieldTypesTable::class,
\App\Services\Auth\Population\PopulateLifeEventsTable::class => \App\Services\Auth\Population\PopulateLifeEventsTable::class,
\App\Services\Auth\Population\PopulateModulesTable::class => \App\Services\Auth\Population\PopulateModulesTable::class,
\App\Services\Contact\Avatar\GenerateDefaultAvatar::class => \App\Services\Contact\Avatar\GenerateDefaultAvatar::class,
\App\Services\Contact\Avatar\GetAdorableAvatarURL::class => \App\Services\Contact\Avatar\GetAdorableAvatarURL::class,
\App\Services\Contact\Avatar\GetAvatarsFromInternet::class => \App\Services\Contact\Avatar\GetAvatarsFromInternet::class,
\App\Services\Contact\Avatar\GetGravatar::class => \App\Services\Contact\Avatar\GetGravatar::class,
\App\Services\Contact\Avatar\GetGravatarURL::class => \App\Services\Contact\Avatar\GetGravatarURL::class,
\App\Services\Contact\Avatar\UpdateAvatar::class => \App\Services\Contact\Avatar\UpdateAvatar::class,
\App\Services\Contact\Address\CreateAddress::class => \App\Services\Contact\Address\CreateAddress::class,
\App\Services\Contact\Address\DestroyAddress::class => \App\Services\Contact\Address\DestroyAddress::class,
\App\Services\Contact\Address\UpdateAddress::class => \App\Services\Contact\Address\UpdateAddress::class,
\App\Services\Contact\Call\CreateCall::class => \App\Services\Contact\Call\CreateCall::class,
\App\Services\Contact\Call\DestroyCall::class => \App\Services\Contact\Call\DestroyCall::class,
\App\Services\Contact\Call\UpdateCall::class => \App\Services\Contact\Call\UpdateCall::class,
\App\Services\Contact\Contact\CreateContact::class => \App\Services\Contact\Contact\CreateContact::class,
\App\Services\Contact\Contact\DeleteMeContact::class => \App\Services\Contact\Contact\DeleteMeContact::class,
\App\Services\Contact\Contact\DestroyContact::class => \App\Services\Contact\Contact\DestroyContact::class,
\App\Services\Contact\Contact\SetMeContact::class => \App\Services\Contact\Contact\SetMeContact::class,
\App\Services\Contact\Contact\UpdateBirthdayInformation::class => \App\Services\Contact\Contact\UpdateBirthdayInformation::class,
\App\Services\Contact\Contact\UpdateContact::class => \App\Services\Contact\Contact\UpdateContact::class,
\App\Services\Contact\Contact\UpdateContactFoodPreferences::class => \App\Services\Contact\Contact\UpdateContactFoodPreferences::class,
\App\Services\Contact\Contact\UpdateContactIntroduction::class => \App\Services\Contact\Contact\UpdateContactIntroduction::class,
\App\Services\Contact\Contact\UpdateWorkInformation::class => \App\Services\Contact\Contact\UpdateWorkInformation::class,
\App\Services\Contact\Contact\UpdateDeceasedInformation::class => \App\Services\Contact\Contact\UpdateDeceasedInformation::class,
\App\Services\Contact\Conversation\AddMessageToConversation::class => \App\Services\Contact\Conversation\AddMessageToConversation::class,
\App\Services\Contact\Conversation\CreateConversation::class => \App\Services\Contact\Conversation\CreateConversation::class,
\App\Services\Contact\Conversation\DestroyConversation::class => \App\Services\Contact\Conversation\DestroyConversation::class,
\App\Services\Contact\Conversation\DestroyMessage::class => \App\Services\Contact\Conversation\DestroyMessage::class,
\App\Services\Contact\Conversation\UpdateConversation::class => \App\Services\Contact\Conversation\UpdateConversation::class,
\App\Services\Contact\Conversation\UpdateMessage::class => \App\Services\Contact\Conversation\UpdateMessage::class,
\App\Services\Contact\Document\DestroyDocument::class => \App\Services\Contact\Document\DestroyDocument::class,
\App\Services\Contact\Document\UploadDocument::class => \App\Services\Contact\Document\UploadDocument::class,
\App\Services\Contact\Gift\AssociatePhotoToGift::class => \App\Services\Contact\Gift\AssociatePhotoToGift::class,
\App\Services\Contact\Gift\CreateGift::class => \App\Services\Contact\Gift\CreateGift::class,
\App\Services\Contact\Gift\DestroyGift::class => \App\Services\Contact\Gift\DestroyGift::class,
\App\Services\Contact\Gift\UpdateGift::class => \App\Services\Contact\Gift\UpdateGift::class,
\App\Services\Contact\Label\UpdateAddressLabels::class => \App\Services\Contact\Label\UpdateAddressLabels::class,
\App\Services\Contact\Label\UpdateContactFieldLabels::class => \App\Services\Contact\Label\UpdateContactFieldLabels::class,
\App\Services\Contact\LifeEvent\CreateLifeEvent::class => \App\Services\Contact\LifeEvent\CreateLifeEvent::class,
\App\Services\Contact\LifeEvent\DestroyLifeEvent::class => \App\Services\Contact\LifeEvent\DestroyLifeEvent::class,
\App\Services\Contact\LifeEvent\UpdateLifeEvent::class => \App\Services\Contact\LifeEvent\UpdateLifeEvent::class,
\App\Services\Contact\Occupation\CreateOccupation::class => \App\Services\Contact\Occupation\CreateOccupation::class,
\App\Services\Contact\Occupation\DestroyOccupation::class => \App\Services\Contact\Occupation\DestroyOccupation::class,
\App\Services\Contact\Occupation\UpdateOccupation::class => \App\Services\Contact\Occupation\UpdateOccupation::class,
\App\Services\Contact\Relationship\CreateRelationship::class => \App\Services\Contact\Relationship\CreateRelationship::class,
\App\Services\Contact\Relationship\DestroyRelationship::class => \App\Services\Contact\Relationship\DestroyRelationship::class,
\App\Services\Contact\Relationship\UpdateRelationship::class => \App\Services\Contact\Relationship\UpdateRelationship::class,
\App\Services\Contact\Reminder\CreateReminder::class => \App\Services\Contact\Reminder\CreateReminder::class,
\App\Services\Contact\Reminder\DestroyReminder::class => \App\Services\Contact\Reminder\DestroyReminder::class,
\App\Services\Contact\Reminder\UpdateReminder::class => \App\Services\Contact\Reminder\UpdateReminder::class,
\App\Services\Contact\Tag\AssociateTag::class => \App\Services\Contact\Tag\AssociateTag::class,
\App\Services\Contact\Tag\CreateTag::class => \App\Services\Contact\Tag\CreateTag::class,
\App\Services\Contact\Tag\DestroyTag::class => \App\Services\Contact\Tag\DestroyTag::class,
\App\Services\Contact\Tag\DetachTag::class => \App\Services\Contact\Tag\DetachTag::class,
\App\Services\Contact\Tag\UpdateTag::class => \App\Services\Contact\Tag\UpdateTag::class,
\App\Services\Instance\IdHasher::class => \App\Services\Instance\IdHasher::class,
\App\Services\Instance\Geolocalization\GetGPSCoordinate::class => \App\Services\Instance\Geolocalization\GetGPSCoordinate::class,
\App\Services\Instance\Weather\GetWeatherInformation::class => \App\Services\Instance\Weather\GetWeatherInformation::class,
\App\Services\Task\CreateTask::class => \App\Services\Task\CreateTask::class,
\App\Services\Task\DestroyTask::class => \App\Services\Task\DestroyTask::class,
\App\Services\Task\UpdateTask::class => \App\Services\Task\UpdateTask::class,
\App\Services\User\EmailChange::class => \App\Services\User\EmailChange::class,
\App\Services\VCalendar\ExportTask::class => \App\Services\VCalendar\ExportTask::class,
\App\Services\VCalendar\ExportVCalendar::class => \App\Services\VCalendar\ExportVCalendar::class,
\App\Services\VCalendar\ImportTask::class => \App\Services\VCalendar\ImportTask::class,
\App\Services\VCard\ExportVCard::class => \App\Services\VCard\ExportVCard::class,
\App\Services\VCard\ImportVCard::class => \App\Services\VCard\ImportVCard::class,
\App\Services\Account\Settings\SqlExportAccount::class => \App\Services\Account\Settings\SqlExportAccount::class,
\App\Services\Account\Settings\ResetAccount::class => \App\Services\Account\Settings\ResetAccount::class,
\App\Services\Account\Settings\DestroyAccount::class => \App\Services\Account\Settings\DestroyAccount::class,
\App\Services\Instance\AuditLog\LogAccountAction::class => \App\Services\Instance\AuditLog\LogAccountAction::class,
\App\Services\User\UpdateViewPreference::class => \App\Services\User\UpdateViewPreference::class,
\App\Services\User\AcceptPolicy::class => \App\Services\User\AcceptPolicy::class,
];
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Laravel\Passport\Passport;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot(Request $request)
{
$this->registerPolicies();
Passport::ignoreCsrfToken(in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']));
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes();
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace App\Providers;
use Illuminate\Support\Arr;
use LaravelSabre\LaravelSabre;
use Sabre\CalDAV\CalendarRoot;
use Sabre\CalDAV\ICSExportPlugin;
use Sabre\CardDAV\VCFExportPlugin;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Sabre\DAVACL\Plugin as AclPlugin;
use Sabre\DAVACL\PrincipalCollection;
use Illuminate\Support\ServiceProvider;
use Sabre\CalDAV\Plugin as CalDAVPlugin;
use Sabre\DAV\Auth\Plugin as AuthPlugin;
use Sabre\DAV\Sync\Plugin as SyncPlugin;
use App\Http\Controllers\DAV\DAVRedirect;
use Sabre\CardDAV\Plugin as CardDAVPlugin;
use App\Http\Controllers\DAV\Auth\AuthBackend;
use Sabre\DAV\Browser\Plugin as BrowserPlugin;
use App\Http\Controllers\DAV\DAVACL\PrincipalBackend;
use App\Http\Controllers\DAV\Backend\CalDAV\CalDAVBackend;
use App\Http\Controllers\DAV\Backend\CardDAV\CardDAVBackend;
use App\Http\Controllers\DAV\Backend\CardDAV\AddressBookRoot;
class DAVServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
LaravelSabre::nodes(function () {
return $this->nodes();
});
LaravelSabre::plugins(function () {
return $this->plugins();
});
LaravelSabre::auth(function (\Illuminate\Http\Request $request): bool {
if (! $request->user()) {
return false;
}
if ($request->user()->admin ||
config('laravelsabre.users') == null) {
return true;
}
$users = explode(',', config('laravelsabre.users'));
$filtered = Arr::where($users, function ($value, $key) use ($request) {
return $value === $request->user()->email;
});
return count($filtered) > 0;
});
}
/**
* List of nodes for DAV Collection.
*/
private function nodes(): array
{
$user = Auth::user();
// Initiate custom backends for link between Sabre and Monica
$principalBackend = app(PrincipalBackend::class)->init($user); // User rights
$carddavBackend = app(CardDAVBackend::class)->init($user); // Contacts
$caldavBackend = app(CalDAVBackend::class)->init($user); // Calendar
return [
new PrincipalCollection($principalBackend),
new AddressBookRoot($principalBackend, $carddavBackend),
new CalendarRoot($principalBackend, $caldavBackend),
];
}
/**
* List of Sabre plugins.
*/
private function plugins()
{
// Authentication backend
$authBackend = new AuthBackend();
yield new AuthPlugin($authBackend);
// CardDAV plugin
yield new CardDAVPlugin();
yield new VCFExportPlugin();
// CalDAV plugin
yield new CalDAVPlugin();
yield new ICSExportPlugin();
// Sync Plugin - rfc6578
yield new SyncPlugin();
// ACL plugnin
$aclPlugin = new AclPlugin();
$aclPlugin->allowUnauthenticatedAccess = false;
$aclPlugin->hideNodesFromListings = true;
yield $aclPlugin;
// In local environment add browser plugin
if (App::environment('local')) {
yield new BrowserPlugin(false);
} else {
yield new DAVRedirect();
}
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array<string,array<int,string>>
*/
protected $listen = [
\Illuminate\Auth\Events\Registered::class => [
\Illuminate\Auth\Listeners\SendEmailVerificationNotification::class,
],
\Illuminate\Auth\Events\PasswordReset::class => [
\App\Listeners\LogoutUserDevices::class,
],
];
/**
* The subscriber classes to register.
*
* @var array
*/
protected $subscribe = [
\App\Listeners\LoginListener::class,
];
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Providers;
use App\Helpers\CollectionHelper;
use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;
class MacroServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (! Collection::hasMacro('sortByCollator')) {
Collection::macro('sortByCollator', function ($callback, $options = \Collator::SORT_STRING, $descending = false) {
/** @var Collection */
$collect = $this;
return CollectionHelper::sortByCollator($collect, $callback, $options, $descending);
});
}
if (! Collection::hasMacro('groupByItemsProperty')) {
Collection::macro('groupByItemsProperty', function ($property) {
/** @var Collection */
$collect = $this;
return CollectionHelper::groupByItemsProperty($collect, $property);
});
}
if (! Collection::hasMacro('mapUuid')) {
Collection::macro('mapUuid', function () {
/** @var Collection */
$collect = $this;
return $collect->map(function ($item) {
return $item->uuid;
})->toArray();
});
}
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace App\Providers;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Helpers\RequestHelper;
use App\Models\Contact\Contact;
use Illuminate\Http\JsonResponse;
use App\Services\Instance\IdHasher;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
use App\Exceptions\WrongIdException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Config;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
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()
{
parent::boot();
if (Config::get('app.force_url')) {
URL::forceRootUrl(Str::of(config('app.url'))->ltrim('/'));
}
if (App::environment('production')) {
URL::forceScheme('https');
}
$this->configureRateLimiting();
Route::bind('contact', function ($value) {
// In case the user is logged out
if (! Auth::check()) {
redirect()->route('loginRedirect')->send();
return;
}
try {
$id = app(IdHasher::class)->decodeId($value);
return Contact::where('account_id', auth()->user()->account_id)
->findOrFail($id);
} catch (WrongIdException $ex) {
redirect()->route('people.missing')->send();
} catch (ModelNotFoundException $ex) {
redirect()->route('people.missing')->send();
}
});
Route::model('otherContact', Contact::class);
}
/**
* Define the routes for the application.
*/
public function map(): void
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace.'\Api')
->group(base_path('routes/api.php'));
Route::prefix('oauth')
->namespace($this->namespace.'\Api')
->group(base_path('routes/oauth.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/special.php'));
}
/**
* Configure the rate limiters for the application.
*
* @return void
*/
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(config('monica.rate_limit_api'))
->by(optional($request->user())->id ?: RequestHelper::ip())
->response(function (Request $request, array $headers) {
$message = [
'error' => [
'message' => config('api.error_codes.34'),
'error_code' => 34,
],
];
return new JsonResponse($message, 429, $headers);
});
});
RateLimiter::for('oauth', function (Request $request) {
return Limit::perMinute(config('monica.rate_limit_oauth'))->by($request->input('email') ?: RequestHelper::ip());
});
}
}