AppServiceProvider.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace App\Providers;
  3. use App\Services\PaliSeriesesService;
  4. use App\Services\RomanizeService;
  5. use App\Services\UserService;
  6. use App\Tools\QueryBuilderMacro;
  7. use App\View\Composers\BlogViewComposer;
  8. use Carbon\CarbonImmutable;
  9. use Godruoyi\Snowflake\LaravelSequenceResolver;
  10. use Godruoyi\Snowflake\Snowflake;
  11. use Illuminate\Cache\RateLimiting\Limit;
  12. use Illuminate\Database\Query\Builder as QueryBuilder;
  13. use Illuminate\Http\Request;
  14. use Illuminate\Support\Facades\Date;
  15. use Illuminate\Support\Facades\DB;
  16. use Illuminate\Support\Facades\RateLimiter;
  17. use Illuminate\Support\Facades\View;
  18. use Illuminate\Support\ServiceProvider;
  19. use Illuminate\Validation\Rules\Password;
  20. class AppServiceProvider extends ServiceProvider
  21. {
  22. /**
  23. * Register any application services.
  24. */
  25. public function register(): void
  26. {
  27. /*
  28. |--------------------------------------------------------------------------
  29. | Snowflake ID Generator
  30. |--------------------------------------------------------------------------
  31. */
  32. $this->app->singleton('snowflake', function () {
  33. return (new Snowflake(
  34. config('mint.snowflake.data_center_id'),
  35. config('mint.snowflake.worker_id')
  36. ))
  37. ->setStartTimeStamp(
  38. strtotime(config('mint.snowflake.start')) * 1000
  39. )
  40. ->setSequenceResolver(
  41. new LaravelSequenceResolver(
  42. $this->app->get('cache')->store()
  43. )
  44. );
  45. });
  46. /*
  47. |--------------------------------------------------------------------------
  48. | Romanize Service
  49. |--------------------------------------------------------------------------
  50. */
  51. $this->app->singleton(RomanizeService::class);
  52. /*
  53. |--------------------------------------------------------------------------
  54. | Pali Serieses Service
  55. |--------------------------------------------------------------------------
  56. */
  57. $this->app->singleton(PaliSeriesesService::class);
  58. /*
  59. |--------------------------------------------------------------------------
  60. | User Service
  61. |--------------------------------------------------------------------------
  62. |
  63. | 必须是 singleton:它在请求内维护一张 uuid => 摘要的身份映射,同一个用户
  64. | 在一次请求里被解析多次时只查一次库、只签一次头像 URL。每次 make 新实例
  65. | 那张映射就永远是空的。
  66. |
  67. */
  68. $this->app->singleton(UserService::class);
  69. }
  70. /**
  71. * Bootstrap any application services.
  72. */
  73. public function boot(): void
  74. {
  75. /*
  76. |--------------------------------------------------------------------------
  77. | Laravel 13 Default Production Behaviors
  78. |--------------------------------------------------------------------------
  79. */
  80. $this->configureDefaults();
  81. /*
  82. |--------------------------------------------------------------------------
  83. | Custom Query Builder Macros
  84. |--------------------------------------------------------------------------
  85. */
  86. QueryBuilder::mixin(
  87. $this->app->make(QueryBuilderMacro::class)
  88. );
  89. /*
  90. |--------------------------------------------------------------------------
  91. | View Composers
  92. |--------------------------------------------------------------------------
  93. */
  94. View::composer('blog.*', BlogViewComposer::class);
  95. View::composer('layouts.blog', BlogViewComposer::class);
  96. /*
  97. |--------------------------------------------------------------------------
  98. | Rate Limiters
  99. |--------------------------------------------------------------------------
  100. |
  101. | 找回密码会往外发邮件:按 IP 限住撞库式的批量请求,按邮箱限住对同一个人的
  102. | 邮件轰炸。设新密码的请求不带 email,只按 IP 计。
  103. |
  104. */
  105. RateLimiter::for('password-resets', fn (Request $request): array => array_filter([
  106. Limit::perMinute(10)->by('ip:'.$request->ip()),
  107. $request->filled('email')
  108. ? Limit::perHour(5)->by('email:'.mb_strtolower((string) $request->input('email')))
  109. : null,
  110. ]));
  111. }
  112. /**
  113. * Configure default behaviors for production-ready applications.
  114. */
  115. protected function configureDefaults(): void
  116. {
  117. /*
  118. |--------------------------------------------------------------------------
  119. | Use Immutable Dates
  120. |--------------------------------------------------------------------------
  121. */
  122. Date::use(CarbonImmutable::class);
  123. /*
  124. |--------------------------------------------------------------------------
  125. | Prevent destructive DB commands in production
  126. |--------------------------------------------------------------------------
  127. */
  128. DB::prohibitDestructiveCommands(
  129. app()->isProduction(),
  130. );
  131. /*
  132. |--------------------------------------------------------------------------
  133. | Strong password defaults in production
  134. |--------------------------------------------------------------------------
  135. */
  136. Password::defaults(
  137. fn (): ?Password => app()->isProduction()
  138. ? Password::min(12)
  139. ->mixedCase()
  140. ->letters()
  141. ->numbers()
  142. ->symbols()
  143. ->uncompromised()
  144. : null,
  145. );
  146. }
  147. }