diff --git a/.gitea/workflows/Laravel.yaml b/.gitea/workflows/Laravel.yaml new file mode 100644 index 0000000..1640e63 --- /dev/null +++ b/.gitea/workflows/Laravel.yaml @@ -0,0 +1,47 @@ +name: Tests + +on: + push: + branches: + - master + - '*.x' + pull_request: + schedule: + - cron: '0 0 * * *' + +permissions: + contents: read + +jobs: + tests: + runs-on: centos + + strategy: + fail-fast: true + matrix: + php: [8.1, 8.2] + + name: PHP + + steps: + - name: 检查代码 + uses: actions/checkout@v3 + + - name: 配置PHP + uses: XiaoLFeng/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite + coverage: none + + - name: 安装PHP Composer依赖 + run: composer install --prefer-dist --no-interaction --no-progress + + - name: 复制配置文件 + run: cp .env.example .env + + - name: 生成应用程序密钥 + run: php artisan key:generate + +# - name: Execute tests +# run: /phpunit diff --git a/app/Http/Controllers/Function/Link.php b/app/Http/Controllers/Function/Link.php index fba3798..ee85a7d 100644 --- a/app/Http/Controllers/Function/Link.php +++ b/app/Http/Controllers/Function/Link.php @@ -13,16 +13,19 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request as HttpRequest; use Illuminate\Mail\Message; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Facades\Request; use Illuminate\Support\Facades\Response; use Illuminate\Support\Facades\Validator; class Link extends Controller { protected array $data; + private array $sendEmail; public function __construct() { @@ -30,7 +33,13 @@ public function __construct() $this->data = $data->data; } - public function apiCustomAdd(Request $request): JsonResponse + /** + * 添加友链API + * + * @param HttpRequest $request 获取HTTP中 Request 数据 + * @return JsonResponse 返回JSON数据 + */ + public function apiCustomAdd(HttpRequest $request): JsonResponse { /** @var array $returnData Json的 return 返回值 */ /** @var Validator $dataCheck 数据判断 */ @@ -48,7 +57,7 @@ public function apiCustomAdd(Request $request): JsonResponse 'userRss' => 'string|regex:#[a-zA-z]+://[^\s]*#', 'userLocation' => 'required|int', 'userSelColor' => 'required|int', - 'userRemark' => 'required|string', + 'userRemark' => 'string', ]); // 检查发现错误 @@ -134,7 +143,13 @@ public function apiCustomAdd(Request $request): JsonResponse return Response::json($returnData, $returnData['code']); } - public function apiCustomSearch(Request $request): JsonResponse + /** + * 搜索友链数据 + * + * @param HttpRequest $request 获取HTTP中 Request 数据 + * @return JsonResponse 返回JSON数据 + */ + public function apiCustomSearch(HttpRequest $request): JsonResponse { /** @var array $returnData Json的 return 返回值 */ if (!empty($request->location_search)) { @@ -143,8 +158,8 @@ public function apiCustomSearch(Request $request): JsonResponse ->where([ ['blogName', 'LIKE', '%' . $request->location_search . '%', 'or'], ['blogUrl', 'LIKE', '%' . $request->location_search . '%', 'or'], - ['blogOwnEmail', 'LIKE', '%' . $request->location_search . '%', 'or']]) - ->select('blogName','blogUrl','blogDescription','blogIcon') + ['blogOwnEmail', '=', $request->location_search, 'or']]) + ->select('id', 'blogName', 'blogUrl', 'blogDescription', 'blogIcon') ->orderBy('id') ->get() ->toArray(); @@ -170,7 +185,7 @@ public function apiCustomSearch(Request $request): JsonResponse if ($request->searchType == 'blogName') { $resultData = DB::table('blog_link') ->where([['blogName', 'LIKE', '%' . $request->location_search . '%']]) - ->select('blogName','blogUrl','blogDescription','blogIcon') + ->select('id', 'blogName', 'blogUrl', 'blogDescription', 'blogIcon') ->orderBy('id') ->get() ->toArray(); @@ -195,7 +210,7 @@ public function apiCustomSearch(Request $request): JsonResponse } elseif ($request->searchType == 'blogUrl') { $resultData = DB::table('blog_link') ->where([['blogUrl', 'LIKE', '%' . $request->location_search . '%']]) - ->select('blogName','blogUrl','blogDescription','blogIcon') + ->select('id', 'blogName', 'blogUrl', 'blogDescription', 'blogIcon') ->orderBy('id') ->get() ->toArray(); @@ -236,10 +251,190 @@ public function apiCustomSearch(Request $request): JsonResponse ], ]; } - return Response::json($returnData,$returnData['code']); + return Response::json($returnData, $returnData['code']); } - protected function viewLink(Request $request): Factory|View|Application + /** + * 检查数据验证是否正确 + * + * @param HttpRequest $request 获取HTTP中 Request 数据 + * @return JsonResponse 返回JSON数据 + */ + public function apiCustomBlogCheck(HttpRequest $request): JsonResponse + { + /** @var array $returnData Json的 return 返回值 */ + // 验证数据 + $resultBlog = DB::table('blog_link') + ->select('id', 'blogOwnEmail') + ->find((int)$request->id); + if (!empty($resultBlog->id)) { + // 检查输入博客是否对应 + if (!empty($resultBlog->blogOwnEmail)) { + if (strcmp($resultBlog->blogOwnEmail, $request->email) == 0) { + // 生成验证码(筛查内容) + $resultVerifyCode = DB::table('code') + ->where([ + ['email', '=', $resultBlog->blogOwnEmail], + ['type', '=', 'CODE-CUSTOM-CHECK'], + ['time', '>', time()]]) + ->get() + ->toArray(); + // 不存在验证码,生成验证码并存入数据库中 + if (empty($resultVerifyCode[0]->id)) { + // 生成6位数验证码 + $verifyCode = null; + for ($i = 0; $i < 6; $i++) + $verifyCode .= rand(0, 9); + + // 存入数据库 + DB::table('code') + ->insert([ + 'email' => $resultBlog->blogOwnEmail, + 'code' => $verifyCode, + 'type' => 'CODE-CUSTOM-CHECK', + 'sendTime' => time(), + 'time' => time()+900, + ]); + // 数据整理 + $this->sendEmail = [ + 'userEmail' => $resultBlog->blogOwnEmail, + 'verifyCode' => $verifyCode, + 'sendTime' => time(), + ]; + $this->apiCustomBlogCheckSendEmail(); + $returnData = [ + 'output' => 'Success', + 'code' => 200, + 'data' => [ + 'message' => '发送成功', + ], + ]; + } else { + // 存在验证码,检查验证码是否需要重新发送 + $data = DB::table('code') + ->where([ + ['email','=',$resultBlog->blogOwnEmail], + ['type','=','CODE-CUSTOM-CHECK'], + ['time','>',time()]]) + ->get() + ->toArray(); + $this->sendEmail = [ + 'userEmail' => $data[0]->email, + 'verifyCode' => $data[0]->code, + 'sendTime' => time(), + ]; + if ($resultVerifyCode[0]->sendTime < time()-60) { + // 发送验证码 + DB::table('code') + ->where([ + ['email','=',$resultBlog->blogOwnEmail], + ['type','=','CODE-CUSTOM-CHECK'], + ['time','>',time()]]) + ->update(['sendTime' => time()]); + $this->apiCustomBlogCheckSendEmail(); + $returnData = [ + 'output' => 'Success', + 'code' => 200, + 'data' => [ + 'message' => '重新发送成功', + ], + ]; + } else { + // 避免重复发送 + $returnData = [ + 'output' => 'SendingTimeTooFast', + 'code' => 403, + 'data' => [ + 'message' => '邮件重新发送时间过快', + 'data' => [ + 'time' => 60 - (time() - $resultVerifyCode[0]->sendTime), + ], + ], + ]; + } + } + } else { + $returnData = [ + 'output' => 'EmailMismatch', + 'code' => 403, + 'data' => [ + 'message' => '邮箱与对应ID不匹配', + ], + ]; + } + } else { + $returnData = [ + 'output' => 'NoEmail', + 'code' => 403, + 'data' => [ + 'message' => '对应ID没有绑定邮箱,请联系管理员', + ], + ]; + } + } else { + $returnData = [ + 'output' => 'NoBlog', + 'code' => 403, + 'data' => [ + 'message' => '没有ID对应博客', + ], + ]; + } + return Response::json($returnData, $returnData['code']); + } + + /** + * 站长认证邮件发送模板 + * + * @param array $data + * @return void + */ + private function apiCustomBlogCheckSendEmail(): void + { + // 验证通过发送邮件 + Mail::send('mail.link-custom-check', $this->sendEmail, function (Message $mail) { + $mail->from(env('MAIL_USERNAME'), env('APP_NAME')); + $mail->to($this->sendEmail['userEmail']); + $mail->subject(env('APP_NAME') . '-验证码(友链自助修改)'); + }); + } + + public function viewEditFriend($friendId): Application|Factory|View|RedirectResponse + { + // 检查内容是否为空 + if (!empty($friendId)) { + $this->data['webSubTitle'] = '修改友链'; + + // 检查这个ID是否存在 + $resultBlog = DB::table('blog_link') + ->find($friendId); + if (!empty($resultBlog->id)) { + // 检查是否存在Cookie作为已验证 + if (Request::hasCookie('friend_edit')) { + // 检查COOKIE与所验证ID是否匹配 + if (password_verify($friendId, Request::cookie('friend_edit'))) { + return view('function.edit-friend', $this->data); + } else { + response()->withCookie(cookie('friend_edit', null, time() - 1)); + return Response::redirectTo(route('function.edit-search')); + } + } else { + // 验证页面 + // 加密用户邮箱 + $this->data['blog'] = $resultBlog; + return view('function.edit-check', $this->data); + } + } else { + // 不存在这一个ID用户 + return Response::redirectTo(route('function.edit-search')); + } + } else { + // ID为空的时候就返回数据 + return Response::redirectTo(route('function.edit-search')); + } + } + + protected function viewLink(HttpRequest $request): Factory|View|Application { $this->data['webSubTitle'] = '友链'; $this->GetFriendsLink($this->data); @@ -266,16 +461,28 @@ protected function viewMakeFriend(): Factory|View|Application return view('function.make-friend', $this->data); } - protected function viewEditFriend(): Factory|View|Application - { - $this->data['webSubTitle'] = '修改友链'; - - return view('function.edit-friend', $this->data); - } - protected function viewSearchFriends(): Factory|View|Application { $this->data['webSubTitle'] = '查询列表'; return view('function.edit-search', $this->data); } + + protected function viewSearchFriend($friendId): Factory|View|Application|RedirectResponse + { + $this->data['webSubTitle'] = '查询列表'; + if (!empty($friendId)) { + // 检查 friendId 是否存在 + $resultBlog = DB::table('blog_link') + ->select('id','blogOwnEmail') + ->find($friendId); + if (!empty($resultBlog->id)) { + $this->data['blog'] = $resultBlog; + return view('function.edit-check', $this->data); + } else { + return Response::redirectTo(route('function.edit-search')); + } + } else { + return Response::redirectTo(route('function.edit-search')); + } + } } diff --git a/database/migrations/2023_06_28_054011_create_code_table.php b/database/migrations/2023_06_28_054011_create_code_table.php new file mode 100644 index 0000000..5b4c5d1 --- /dev/null +++ b/database/migrations/2023_06_28_054011_create_code_table.php @@ -0,0 +1,46 @@ +id() + ->comment('自动ID'); + $table->string('email',100) + ->comment('邮箱'); + $table->string('code',64) + ->comment('验证码内容'); + $table->string('type',40) + ->comment('类型(例如:CODE-CUSTOM-CHECK)'); + $table->integer('sendTime') + ->comment('发送时间'); + $table->integer('time') + ->comment('存储结束时间戳'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('code'); + } +} diff --git a/phpunit.xml b/phpunit.xml index e4386c4..039e811 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -24,14 +24,14 @@ - - - - - - - - - + + + + + + + + + diff --git a/resources/views/console/friends-link/edit.blade.php b/resources/views/console/friends-link/edit.blade.php index 071f348..20a5b82 100644 --- a/resources/views/console/friends-link/edit.blade.php +++ b/resources/views/console/friends-link/edit.blade.php @@ -172,7 +172,7 @@ class="w-16 h-16 p-1 rounded-full ring-2 ring-gray-300 dark:ring-gray-500 me-2 s + + + + + + +
+
+
+

+ 在上方进行友链检索

+

+ 选择内容输入博客名字、博客地址查询博客信息执行修改

+
+
+
+
+ + @include('modules.footer') + + + + + + + + +{!! $webFooter !!} + diff --git a/resources/views/function/make-friend.blade.php b/resources/views/function/make-friend.blade.php index 8d80588..1a6ecc4 100644 --- a/resources/views/function/make-friend.blade.php +++ b/resources/views/function/make-friend.blade.php @@ -296,8 +296,10 @@ function ajax() { dataType: "json", success: function (returnData) { if (returnData.output === "Success") { - Toast.toggle('友链申请成功',''); - location.href = '{{ route('home') }}' + Toast.toggle('友链申请成功,即将跳转',''); + setTimeout(function () { + location.href = '{{ route('function.link') }}'; + },3000); } else { Toast('未知错误',''); } diff --git a/resources/views/mail/link-custom-add.blade.php b/resources/views/mail/link-custom-add.blade.php index e52d01a..8a7982b 100644 --- a/resources/views/mail/link-custom-add.blade.php +++ b/resources/views/mail/link-custom-add.blade.php @@ -7,7 +7,7 @@ - + diff --git a/resources/views/mail/link-custom-check.blade.php b/resources/views/mail/link-custom-check.blade.php new file mode 100644 index 0000000..273202b --- /dev/null +++ b/resources/views/mail/link-custom-check.blade.php @@ -0,0 +1,54 @@ + + + + + Mail + + +
$G_TitleName{{ env('APP_NAME') }}
@@ -26,7 +26,8 @@ 您好 {{ $userBlog }} 的站长:{{ $userEmail }}
您在本博客({{ env('APP_NAME') }})申请了友链
-
+ 邮件为通知您您已成功申请友链,需等待站长进行审核,我们将在审核完毕后再次发送邮件通知您 +
请在确认一次您的信息是否正确:
  • 博主邮箱:{{ $userEmail }}
  • @@ -34,8 +35,8 @@
  • 贵站地址:{{ $userUrl }}
  • 图片地址:{{ $userIcon }}
  • 贵站介绍:{{ $userDescription }}
  • -
  • 备注内容:{{ $userRemark }}
  • -
  • RSS地址:{{ $userRSS }}
  • + @if(!empty($userRemark))
  • 备注内容:{{ $userRemark }}
  • @endif + @if(!empty($checkRssJudge))
  • RSS地址:{{ $userRSS }}
  • @endif
+ + + + + + + + + +
{{ env('APP_NAME') }}
+ + + + + + + + + + +
+ 时间: {{ date('Y-m-d H:i',$sendTime) }} +
+ Dear. {{ $userEmail }} +
+ 您在本博客({{ env('APP_NAME') }})正在进行 友链自助修改 操作。 +
+ 您的验证码为:{{ $verifyCode }} 验证码15分钟有效
+
+ 若您未在本站进行对应操作,请勿外泄验证码,忽略本邮件即可!谢谢您对本站的支持
+ 验证UU码:CODE-CUSTOM-CHECK +
+
+ + + + +
+ © 2022 - {{ date('Y') }}. {{ env('APP_NAME') }} All Rights Reserved.
+ 本邮件为自动发出,请勿直接回复 +
+
+ + + + diff --git a/resources/views/modules/navbar.blade.php b/resources/views/modules/navbar.blade.php index 826ad9d..c35bfab 100644 --- a/resources/views/modules/navbar.blade.php +++ b/resources/views/modules/navbar.blade.php @@ -80,7 +80,7 @@ class="fixed hidden inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6
Your Company -