AuthController.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Components\Helpers;
  4. use App\Components\IP;
  5. use App\Http\Requests\Auth\RegisterRequest;
  6. use App\Mail\activeUser;
  7. use App\Mail\resetPassword;
  8. use App\Mail\sendVerifyCode;
  9. use App\Models\EmailFilter;
  10. use App\Models\Invite;
  11. use App\Models\User;
  12. use App\Models\UserLoginLog;
  13. use App\Models\Verify;
  14. use App\Models\VerifyCode;
  15. use Auth;
  16. use Cache;
  17. use Captcha;
  18. use Cookie;
  19. use Hash;
  20. use Illuminate\Http\RedirectResponse;
  21. use Illuminate\Http\Request;
  22. use Log;
  23. use Mail;
  24. use Redirect;
  25. use Response;
  26. use Session;
  27. use Str;
  28. use Validator;
  29. /**
  30. * 认证控制器.
  31. *
  32. * Class AuthController
  33. */
  34. class AuthController extends Controller
  35. {
  36. // 登录
  37. public function showLoginForm()
  38. {
  39. // 根据权限跳转
  40. if (Auth::check()) {
  41. if (Auth::getUser()->can('admin.index')) {
  42. return Redirect::route('admin.index');
  43. }
  44. return Redirect::route('home');
  45. }
  46. return view('auth.login');
  47. }
  48. public function login(Request $request)
  49. {
  50. $validator = Validator::make($request->all(), ['email' => 'required|email', 'password' => 'required']);
  51. if ($validator->fails()) {
  52. return Redirect::back()->withInput()->withErrors($validator->errors());
  53. }
  54. // 是否校验验证码
  55. $captcha = $this->check_captcha($request);
  56. if ($captcha !== false) {
  57. return $captcha;
  58. }
  59. // 验证账号并创建会话
  60. if (! Auth::attempt($validator->validated(), $request->input('remember'))) {
  61. return Redirect::back()->withInput()->withErrors(trans('auth.error.login_failed'));
  62. }
  63. $user = Auth::getUser();
  64. if (! $user) {
  65. return Redirect::back()->withInput()->withErrors(trans('auth.error.login_error'));
  66. }
  67. if ($request->routeIs('admin.login.post') && $user->cannot('admin.index')) {
  68. // 管理页面登录
  69. // 非权限者清场
  70. Auth::logout();
  71. return Redirect::route('login');
  72. }
  73. // 校验普通用户账号状态
  74. if ($user->status === -1) {
  75. Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话
  76. return Redirect::back()->withInput()->withErrors(trans('auth.error.account_baned'));
  77. }
  78. if ($user->status === 0 && sysConfig('is_activate_account')) {
  79. Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话
  80. return Redirect::back()->withInput()->withErrors(trans('auth.active.promotion.0').'<a href="'.route('active').'?email='.$user->email.
  81. '" target="_blank">👉【'.trans('common.active_item', ['attribute' => trans('common.account')]).'】👈</span></a><br>'.trans('auth.active.promotion.1'));
  82. }
  83. // 写入登录日志
  84. $this->addUserLoginLog($user->id, IP::getClientIp());
  85. // 更新登录信息
  86. $user->update(['last_login' => time()]);
  87. return redirect()->back();
  88. }
  89. // 校验验证码
  90. private function check_captcha(Request $request)
  91. {
  92. switch (sysConfig('is_captcha')) {
  93. case 1: // 默认图形验证码
  94. if (! Captcha::check($request->input('captcha'))) {
  95. return Redirect::back()->withInput()->withErrors(trans('auth.captcha.error.failed'));
  96. }
  97. break;
  98. case 2: // Geetest
  99. $validator = Validator::make($request->all(), [
  100. 'geetest_challenge' => 'required|geetest',
  101. ]);
  102. if ($validator->fails()) {
  103. return Redirect::back()->withInput()->withErrors(trans('auth.captcha.error.failed'));
  104. }
  105. break;
  106. case 3: // Google reCAPTCHA
  107. $validator = Validator::make($request->all(), [
  108. 'g-recaptcha-response' => 'required|NoCaptcha',
  109. ]);
  110. if ($validator->fails()) {
  111. return Redirect::back()->withInput()->withErrors(trans('auth.captcha.error.failed'));
  112. }
  113. break;
  114. case 4: // hCaptcha
  115. $validator = Validator::make($request->all(), [
  116. 'h-captcha-response' => 'required|HCaptcha',
  117. ]);
  118. if ($validator->fails()) {
  119. return Redirect::back()->withInput()->withErrors(trans('auth.captcha.error.failed'));
  120. }
  121. break;
  122. default: // 不启用验证码
  123. break;
  124. }
  125. return false;
  126. }
  127. /**
  128. * 添加用户登录日志.
  129. *
  130. * @param int $userId 用户ID
  131. * @param string $ip IP地址
  132. */
  133. private function addUserLoginLog(int $userId, string $ip): void
  134. {
  135. $ipLocation = IP::getIPInfo($ip);
  136. if (empty($ipLocation) || empty($ipLocation['country'])) {
  137. Log::warning(trans('error.get_ip').':'.$ip);
  138. }
  139. $log = new UserLoginLog();
  140. $log->user_id = $userId;
  141. $log->ip = $ip;
  142. $log->country = $ipLocation['country'] ?? '';
  143. $log->province = $ipLocation['province'] ?? '';
  144. $log->city = $ipLocation['city'] ?? '';
  145. $log->county = $ipLocation['county'] ?? '';
  146. $log->isp = $ipLocation['isp'] ?? ($ipLocation['organization'] ?? '');
  147. $log->area = $ipLocation['area'] ?? '';
  148. $log->save();
  149. }
  150. // 退出
  151. public function logout(): RedirectResponse
  152. {
  153. Auth::logout();
  154. return Redirect::route('login');
  155. }
  156. public function showRegistrationForm()
  157. {
  158. Session::put('register_token', Str::random());
  159. return view('auth.register', ['emailList' => (int) sysConfig('is_email_filtering') !== 2 ? false : EmailFilter::whereType(2)->get()]);
  160. }
  161. // 注册
  162. public function register(RegisterRequest $request)
  163. {
  164. $cacheKey = 'register_times_'.md5(IP::getClientIp()); // 注册限制缓存key
  165. $validator = Validator::make($request->all(), [
  166. 'username' => 'required',
  167. 'email' => 'required|email|unique:user',
  168. 'password' => 'required|min:6|confirmed',
  169. 'term' => 'accepted',
  170. ]);
  171. if ($validator->fails()) {
  172. return Redirect::back()->withInput()->withErrors($validator->errors());
  173. }
  174. $data = $request->validated();
  175. $register_token = $request->input('register_token');
  176. $code = $request->input('code');
  177. $verify_code = $request->input('verify_code');
  178. $aff = (int) $request->input('aff');
  179. // 防止重复提交
  180. if ($register_token !== Session::get('register_token')) {
  181. return Redirect::back()->withInput()->withErrors(trans('auth.error.repeat_request'));
  182. }
  183. Session::forget('register_token');
  184. // 是否开启注册
  185. if (! sysConfig('is_register')) {
  186. return Redirect::back()->withErrors(trans('auth.register.error.disable'));
  187. }
  188. // 校验域名邮箱黑白名单
  189. if (sysConfig('is_email_filtering')) {
  190. $result = $this->emailChecker($data['email'], 1);
  191. if ($result !== false) {
  192. return $result;
  193. }
  194. }
  195. // 如果需要邀请注册
  196. if (sysConfig('is_invite_register')) {
  197. // 校验邀请码合法性
  198. if ($code) {
  199. if (Invite::whereCode($code)->whereStatus(0)->doesntExist()) {
  200. return Redirect::back()->withInput($request->except('code'))->withErrors(trans('auth.invite.error.unavailable'));
  201. }
  202. } elseif ((int) sysConfig('is_invite_register') === 2) { // 必须使用邀请码
  203. return Redirect::back()->withInput()->withErrors(trans('validation.required', ['attribute' => trans('auth.invite.attribute')]));
  204. }
  205. }
  206. // 注册前发送激活码
  207. if ((int) sysConfig('is_activate_account') === 1) {
  208. if (! $verify_code) {
  209. return Redirect::back()->withInput($request->except('verify_code'))->withErrors(trans('auth.captcha.required'));
  210. }
  211. $verifyCode = VerifyCode::whereAddress($data['email'])->whereCode($verify_code)->whereStatus(0)->first();
  212. if (! $verifyCode) {
  213. return Redirect::back()->withInput($request->except('verify_code'))->withErrors(trans('auth.captcha.error.timeout'));
  214. }
  215. $verifyCode->status = 1;
  216. $verifyCode->save();
  217. }
  218. // 是否校验验证码
  219. $captcha = $this->check_captcha($request);
  220. if ($captcha !== false) {
  221. return $captcha;
  222. }
  223. // 24小时内同IP注册限制
  224. if (sysConfig('register_ip_limit') && Cache::has($cacheKey)) {
  225. $registerTimes = Cache::get($cacheKey);
  226. if ($registerTimes >= sysConfig('register_ip_limit')) {
  227. return Redirect::back()->withInput($request->except('code'))->withErrors(trans('auth.register.error.throttle'));
  228. }
  229. }
  230. // 获取可用端口 TODO: 修改判断&提示
  231. $port = Helpers::getPort();
  232. if ($port > sysConfig('max_port')) {
  233. return Redirect::back()->withInput()->withErrors(trans('auth.register.error.disable'));
  234. }
  235. // 获取aff
  236. $affArr = $this->getAff($code, $aff);
  237. $inviter_id = $affArr['inviter_id'];
  238. $transfer_enable = MB * ((int) sysConfig('default_traffic') + ($inviter_id ? (int) sysConfig('referral_traffic') : 0));
  239. // 创建新用户
  240. $user = Helpers::addUser($data['email'], $data['password'], $transfer_enable, sysConfig('default_days'), $inviter_id, $data['username']);
  241. // 注册失败,抛出异常
  242. if (! $user) {
  243. return Redirect::back()->withInput()->withErrors(trans('auth.register.failed'));
  244. }
  245. // 注册次数+1
  246. if (Cache::has($cacheKey)) {
  247. Cache::increment($cacheKey);
  248. } else {
  249. Cache::put($cacheKey, 1, Day); // 24小时
  250. }
  251. // 更新邀请码
  252. if ($affArr['code_id'] && sysConfig('is_invite_register')) {
  253. $invite = Invite::find($affArr['code_id']);
  254. if ($invite) {
  255. $invite->update(['invitee_id' => $user->id, 'status' => 1]);
  256. }
  257. }
  258. // 清除邀请人Cookie
  259. Cookie::unqueue('register_aff');
  260. // 注册后发送激活码
  261. if ((int) sysConfig('is_activate_account') === 2) {
  262. // 生成激活账号的地址
  263. $token = $this->addVerifyUrl($user->id, $user->email);
  264. $activeUserUrl = route('activeAccount', $token);
  265. $logId = Helpers::addNotificationLog(trans('common.active_item', ['attribute' => trans('auth.register.attribute')]),
  266. trans('common.request_url').':'.$activeUserUrl, 1, $user->email);
  267. Mail::to($user->email)->send(new activeUser($logId, $activeUserUrl));
  268. Session::flash('successMsg', trans('auth.active.sent'));
  269. } else {
  270. // 则直接给推荐人加流量
  271. if ($inviter_id) {
  272. $referralUser = User::find($inviter_id);
  273. if ($referralUser && $referralUser->expired_at >= date('Y-m-d')) {
  274. $referralUser->incrementData(sysConfig('referral_traffic') * MB);
  275. }
  276. }
  277. if ((int) sysConfig('is_activate_account') === 1) {
  278. $user->update(['status' => 1]);
  279. }
  280. Session::flash('successMsg', trans('auth.register.success'));
  281. }
  282. return Redirect::route('login')->withInput();
  283. }
  284. //邮箱检查
  285. private function emailChecker($email, $returnType = 0)
  286. {
  287. $emailFilterList = EmailFilter::whereType(sysConfig('is_email_filtering'))->pluck('words')->toArray();
  288. $emailSuffix = explode('@', $email); // 提取邮箱后缀
  289. switch (sysConfig('is_email_filtering')) {
  290. // 黑名单
  291. case 1:
  292. if (in_array(strtolower($emailSuffix[1]), $emailFilterList, true)) {
  293. if ($returnType) {
  294. return Redirect::back()->withErrors(trans('auth.email.error.banned'));
  295. }
  296. return Response::json(['status' => 'fail', 'message' => trans('auth.email.error.banned')]);
  297. }
  298. break;
  299. //白名单
  300. case 2:
  301. if (! in_array(strtolower($emailSuffix[1]), $emailFilterList, true)) {
  302. if ($returnType) {
  303. return Redirect::back()->withErrors(trans('auth.email.error.invalid'));
  304. }
  305. return Response::json(['status' => 'fail', 'message' => trans('auth.email.error.invalid')]);
  306. }
  307. break;
  308. default:
  309. if ($returnType) {
  310. return Redirect::back()->withErrors(trans('auth.email.error.invalid'));
  311. }
  312. return Response::json(['status' => 'fail', 'message' => trans('auth.email.error.invalid')]);
  313. }
  314. return false;
  315. }
  316. /**
  317. * 获取AFF.
  318. *
  319. * @param string|null $code 邀请码
  320. * @param int|null $aff URL中的aff参数
  321. *
  322. * @return array
  323. */
  324. private function getAff($code = null, $aff = null): array
  325. {
  326. $data = ['inviter_id' => null, 'code_id' => 0]; // 邀请人ID 与 邀请码ID
  327. // 有邀请码先用邀请码,用谁的邀请码就给谁返利
  328. if ($code) {
  329. $inviteCode = Invite::whereCode($code)->whereStatus(0)->first();
  330. if ($inviteCode) {
  331. $data['inviter_id'] = $inviteCode->inviter_id;
  332. $data['code_id'] = $inviteCode->id;
  333. }
  334. }
  335. // 没有用邀请码或者邀请码是管理员生成的,则检查cookie或者url链接
  336. if (! $data['inviter_id']) {
  337. // 检查一下cookie里有没有aff
  338. $cookieAff = \Request::hasCookie('register_aff');
  339. if ($cookieAff) {
  340. $data['inviter_id'] = User::find($cookieAff) ? $cookieAff : null;
  341. } elseif ($aff) { // 如果cookie里没有aff,就再检查一下请求的url里有没有aff,因为有些人的浏览器会禁用了cookie,比如chrome开了隐私模式
  342. $data['inviter_id'] = User::find($aff) ? $aff : null;
  343. }
  344. }
  345. return $data;
  346. }
  347. // 生成申请的请求地址
  348. private function addVerifyUrl($uid, $email)
  349. {
  350. $token = md5(sysConfig('website_name').$email.microtime());
  351. $verify = new Verify();
  352. $verify->user_id = $uid;
  353. $verify->token = $token;
  354. $verify->save();
  355. return $token;
  356. }
  357. // 重设密码页
  358. public function resetPassword(Request $request)
  359. {
  360. if ($request->isMethod('POST')) {
  361. // 校验请求
  362. $validator = Validator::make($request->all(), [
  363. 'email' => 'required|email|exists:user,email',
  364. ]);
  365. if ($validator->fails()) {
  366. return Redirect::back()->withInput()->withErrors($validator->errors());
  367. }
  368. $email = $request->input('email');
  369. // 是否开启重设密码
  370. if (! sysConfig('is_reset_password')) {
  371. return Redirect::back()->withErrors(trans('auth.password.reset.error.disabled', ['email' => sysConfig('webmaster_email')]));
  372. }
  373. // 查找账号
  374. $user = User::whereEmail($email)->first();
  375. // 24小时内重设密码次数限制
  376. $resetTimes = 0;
  377. if (Cache::has('resetPassword_'.md5($email))) {
  378. $resetTimes = Cache::get('resetPassword_'.md5($email));
  379. if ($resetTimes >= sysConfig('reset_password_times')) {
  380. return Redirect::back()->withErrors(trans('auth.password.reset.error.throttle', ['time' => sysConfig('reset_password_times')]));
  381. }
  382. }
  383. // 生成取回密码的地址
  384. $token = $this->addVerifyUrl($user->id, $email);
  385. // 发送邮件
  386. $resetPasswordUrl = route('resettingPasswd', $token);
  387. $logId = Helpers::addNotificationLog(trans('auth.password.reset.attribute'), trans('common.request_url').':'.$resetPasswordUrl, 1, $email);
  388. Mail::to($email)->send(new resetPassword($logId, $resetPasswordUrl));
  389. Cache::put('resetPassword_'.md5($email), $resetTimes + 1, Day);
  390. return Redirect::back()->with('successMsg', trans('auth.password.reset.sent'));
  391. }
  392. return view('auth.resetPassword');
  393. }
  394. // 重设密码
  395. public function reset(Request $request, $token)
  396. {
  397. if (! $token) {
  398. return Redirect::route('login');
  399. }
  400. if ($request->isMethod('POST')) {
  401. $validator = Validator::make($request->all(), [
  402. 'password' => 'required|min:6|confirmed',
  403. ]);
  404. if ($validator->fails()) {
  405. return Redirect::back()->withInput()->withErrors($validator->errors());
  406. }
  407. $password = $request->input('password');
  408. // 校验账号
  409. $verify = Verify::type(1)->whereToken($token)->firstOrFail();
  410. $user = $verify->user;
  411. if (! $verify) {
  412. return Redirect::route('login');
  413. }
  414. if ($user->status === -1) {
  415. return Redirect::back()->withErrors(trans('auth.error.account_baned'));
  416. }
  417. if ($verify->status === 1) {
  418. return Redirect::back()->withErrors(trans('auth.error.url_timeout'));
  419. }
  420. if (Hash::check($password, $verify->user->password)) {
  421. return Redirect::back()->withErrors(trans('auth.password.reset.error.same'));
  422. }
  423. // 更新密码
  424. if (! $user->update(['password' => $password])) {
  425. return Redirect::back()->withErrors(trans('auth.password.reset.error.failed'));
  426. }
  427. // 置为已使用
  428. $verify->status = 1;
  429. $verify->save();
  430. return Redirect::route('login')->with('successMsg', trans('auth.password.reset.success'));
  431. }
  432. $verify = Verify::type(1)->whereToken($token)->first();
  433. if (! $verify) {
  434. return Redirect::route('login');
  435. }
  436. if (time() - strtotime($verify->created_at) >= 1800) {
  437. // 置为已失效
  438. $verify->status = 2;
  439. $verify->save();
  440. }
  441. return view('auth.reset', ['verify' => Verify::type(1)->whereToken($token)->first()]); // 重新获取一遍verify
  442. }
  443. // 激活账号页
  444. public function activeUser(Request $request)
  445. {
  446. if ($request->isMethod('POST')) {
  447. $validator = Validator::make($request->all(), ['email' => 'required|email|exists:user,email']);
  448. if ($validator->fails()) {
  449. return Redirect::back()->withInput()->withErrors($validator->errors());
  450. }
  451. $email = $request->input('email');
  452. // 是否开启账号激活
  453. if (! sysConfig('is_activate_account')) {
  454. return Redirect::back()->withInput()->withErrors(trans('auth.active.error.disable'));
  455. }
  456. // 查找账号
  457. $user = User::whereEmail($email)->firstOrFail();
  458. if ($user->status === -1) {
  459. return Redirect::back()->withErrors(trans('auth.error.account_baned'));
  460. }
  461. if ($user->status === 1) {
  462. return Redirect::back()->withErrors(trans('auth.active.error.activated'));
  463. }
  464. // 24小时内激活次数限制
  465. $activeTimes = 0;
  466. if (Cache::has('activeUser_'.md5($email))) {
  467. $activeTimes = Cache::get('activeUser_'.md5($email));
  468. if ($activeTimes >= sysConfig('active_times')) {
  469. return Redirect::back()->withErrors(trans('auth.active.error.throttle', ['email' => sysConfig('webmaster_email')]));
  470. }
  471. }
  472. // 生成激活账号的地址
  473. $token = $this->addVerifyUrl($user->id, $email);
  474. // 发送邮件
  475. $activeUserUrl = route('activeAccount', $token);
  476. $logId = Helpers::addNotificationLog(trans('common.active_item', ['attribute' => trans('common.account')]), trans('common.request_url').':'.$activeUserUrl, 1, $email);
  477. Mail::to($email)->send(new activeUser($logId, $activeUserUrl));
  478. Cache::put('activeUser_'.md5($email), $activeTimes + 1, Day);
  479. return Redirect::back()->with('successMsg', trans('auth.active.sent'));
  480. }
  481. return view('auth.activeUser');
  482. }
  483. // 激活账号
  484. public function active($token)
  485. {
  486. if (! $token) {
  487. return Redirect::route('login');
  488. }
  489. $verify = Verify::type(1)->with('user')->whereToken($token)->firstOrFail();
  490. $user = $verify->user;
  491. if (! $verify) {
  492. return Redirect::route('login');
  493. }
  494. if (empty($user) || $verify->status > 0) {
  495. Session::flash('errorMsg', trans('auth.error.url_timeout'));
  496. return view('auth.active');
  497. }
  498. if ($user->status === 1) {
  499. Session::flash('errorMsg', trans('auth.active.error.activated'));
  500. return view('auth.active');
  501. }
  502. if (time() - strtotime($verify->created_at) >= 1800) {
  503. Session::flash('errorMsg', trans('auth.error.url_timeout'));
  504. // 置为已失效
  505. $verify->status = 2;
  506. $verify->save();
  507. return view('auth.active');
  508. }
  509. // 更新账号状态
  510. if (! $user->update(['status' => 1])) {
  511. Session::flash('errorMsg', trans('common.active_item', ['attribute' => trans('common.failed')]));
  512. return Redirect::back();
  513. }
  514. // 置为已使用
  515. $verify->status = 1;
  516. $verify->save();
  517. // 账号激活后给邀请人送流量
  518. $inviter = $user->inviter;
  519. if ($inviter) {
  520. $inviter->incrementData(sysConfig('referral_traffic') * MB);
  521. }
  522. Session::flash('successMsg', trans('common.active_item', ['attribute' => trans('common.success')]));
  523. return view('auth.active');
  524. }
  525. // 发送注册验证码
  526. public function sendCode(Request $request)
  527. {
  528. $validator = Validator::make($request->all(), ['email' => 'required|email|unique:user,email']);
  529. $email = $request->input('email');
  530. if ($validator->fails()) {
  531. return Response::json(['status' => 'fail', 'message' => $validator->getMessageBag()->first()]);
  532. }
  533. $ip = IP::getClientIP();
  534. // 校验域名邮箱黑白名单
  535. if (sysConfig('is_email_filtering')) {
  536. $result = $this->emailChecker($email);
  537. if ($result !== false) {
  538. return $result;
  539. }
  540. }
  541. // 是否开启注册发送验证码
  542. if ((int) sysConfig('is_activate_account') !== 1) {
  543. return Response::json(['status' => 'fail', 'message' => trans('auth.active.error.disable')]);
  544. }
  545. // 防刷机制
  546. if (Cache::has('send_verify_code_'.md5($ip))) {
  547. return Response::json(['status' => 'fail', 'message' => trans('auth.register.error.throttle')]);
  548. }
  549. // 发送邮件
  550. $code = Str::random(6);
  551. $logId = Helpers::addNotificationLog(trans('auth.register.code'), trans('auth.captcha.attribute').':'.$code, 1, $email);
  552. Mail::to($email)->send(new sendVerifyCode($logId, $code));
  553. VerifyCode::create(['address' => $email, 'code' => $code]); // 生成注册验证码
  554. Cache::put('send_verify_code_'.md5($ip), $ip, Minute);
  555. return Response::json(['status' => 'success', 'message' => trans('auth.captcha.sent')]);
  556. }
  557. // 公开的邀请码列表
  558. public function free()
  559. {
  560. return view('auth.free', ['inviteList' => Invite::whereInviterId(null)->whereStatus(0)->paginate()]);
  561. }
  562. // 切换语言
  563. public function switchLang(string $locale): RedirectResponse
  564. {
  565. Session::put('locale', $locale);
  566. return Redirect::back();
  567. }
  568. }