diff --git a/app/Console/Commands/AutoClearLog.php b/app/Console/Commands/AutoClearLog.php index 24b1cfc0..c0d6a160 100644 --- a/app/Console/Commands/AutoClearLog.php +++ b/app/Console/Commands/AutoClearLog.php @@ -5,8 +5,11 @@ namespace App\Console\Commands; use App\Models\NodeDailyDataFlow; use App\Models\NodeHeartBeat; use App\Models\NodeHourlyDataFlow; +use App\Models\NodeOnlineIp; use App\Models\NodeOnlineLog; -use App\Models\NodeOnlineUserIp; +use App\Models\NotificationLog; +use App\Models\Payment; +use App\Models\RuleLog; use App\Models\UserBanedLog; use App\Models\UserDailyDataFlow; use App\Models\UserDataFlowLog; @@ -41,17 +44,32 @@ class AutoClearLog extends Command private function clearLog(): void { try { + // 清除节点每天流量数据日志 + NodeDailyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-2 month')))->delete(); + + // 清除节点每小时流量数据日志 + NodeHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete(); + + // 清理通知日志 + NotificationLog::where('updated_at', '<=', date('Y-m-d H:i:s', strtotime('-1 month')))->delete(); + // 清除节点负载信息日志 NodeHeartBeat::where('log_time', '<=', strtotime('-30 minutes'))->delete(); // 清除节点在线用户数日志 NodeOnlineLog::where('log_time', '<=', strtotime('-1 hour'))->delete(); - // 清除用户流量日志 - UserDataFlowLog::where('log_time', '<=', strtotime('-3 days'))->delete(); + // 清理在线支付日志 + Payment::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-1 year')))->delete(); - // 清除用户每时各流量数据日志 - UserHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete(); + // 清理审计触发日志 + RuleLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete(); + + // 清除用户连接IP + NodeOnlineIp::where('created_at', '<=', strtotime('-1 week'))->delete(); + + // 清除用户封禁日志 + UserBanedLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete(); // 清除用户各节点 / 节点总计的每天流量数据日志 UserDailyDataFlow::where('node_id', '<>', null) @@ -59,23 +77,17 @@ class AutoClearLog extends Command ->orWhere('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month'))) ->delete(); - // 清除节点每小时流量数据日志 - NodeHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete(); - - // 清除节点每天流量数据日志 - NodeDailyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-2 month')))->delete(); - - // 清除用户封禁日志 - UserBanedLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete(); - - // 清除用户连接IP - NodeOnlineUserIp::where('created_at', '<=', strtotime('-1 month'))->delete(); + // 清除用户每时各流量数据日志 + UserHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete(); // 清除用户登陆日志 - UserLoginLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete(); + UserLoginLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete(); // 清除用户订阅记录 - // 清除用户订阅记录 + // 清理用户订阅请求日志 UserSubscribeLog::where('request_time', '<=', date('Y-m-d H:i:s', strtotime('-1 month')))->delete(); + + // 清除用户流量日志 + UserDataFlowLog::where('log_time', '<=', strtotime('-3 days'))->delete(); } catch (Exception $e) { Log::error('【清理日志】错误: '.$e->getMessage()); } diff --git a/app/Console/Commands/AutoJob.php b/app/Console/Commands/AutoJob.php index ef6e76c9..480418d9 100644 --- a/app/Console/Commands/AutoJob.php +++ b/app/Console/Commands/AutoJob.php @@ -80,11 +80,7 @@ class AutoJob extends Command VerifyCode::recentUnused()->update(['status' => 2]); // 优惠券到期 / 用尽的 自动置无效 - Coupon::whereStatus(0) - ->where('end_time', '<=', time()) - ->orWhereIn('type', [1, 2]) - ->whereUsableTimes(0) - ->update(['status' => 2]); + Coupon::withTrashed()->whereStatus(0)->where('end_time', '<=', time())->orWhereIn('type', [1, 2])->whereUsableTimes(0)->update(['status' => 2]); // 邀请码到期自动置无效 Invite::whereStatus(0)->where('dateline', '<=', date('Y-m-d H:i:s'))->update(['status' => 2]); diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 480f0acf..1997a3c6 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -9,6 +9,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\Request; use Illuminate\Session\TokenMismatchException; +use Illuminate\Validation\ValidationException; use Log; use ReflectionException; use Response; @@ -25,6 +26,7 @@ class Handler extends ExceptionHandler */ protected $dontReport = [ HttpException::class, + ValidationException::class, ]; /** diff --git a/app/Http/Controllers/Admin/AffiliateController.php b/app/Http/Controllers/Admin/AffiliateController.php index a3767123..c14633bf 100644 --- a/app/Http/Controllers/Admin/AffiliateController.php +++ b/app/Http/Controllers/Admin/AffiliateController.php @@ -5,15 +5,8 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\ReferralApply; use App\Models\ReferralLog; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Response; -/** - * 推广控制器. - * - * Class AffiliateController - */ class AffiliateController extends Controller { // 提现申请列表 @@ -33,44 +26,38 @@ class AffiliateController extends Controller $query->whereStatus($status); } - $view['applyList'] = $query->latest()->paginate(15)->appends($request->except('page')); - - return view('admin.aff.index', $view); + return view('admin.aff.index', ['applyList' => $query->latest()->paginate(15)->appends($request->except('page'))]); } // 提现申请详情 - public function detail(Request $request, $id) + public function detail(Request $request, ReferralApply $aff) { - $view['basic'] = ReferralApply::with('user:id,email')->find($id); - $view['commissions'] = []; - if ($view['basic'] && $view['basic']->link_logs) { - $view['commissions'] = ReferralLog::with(['invitee:id,email', 'order.goods:id,name']) - ->whereIn('id', $view['basic']->link_logs) + if ($aff->link_logs) { + $commissions = ReferralLog::with(['invitee:id,email', 'order.goods:id,name']) + ->whereIn('id', $aff->link_logs) ->paginate(15) ->appends($request->except('page')); } - return view('admin.aff.detail', $view); + return view('admin.aff.detail', [ + 'referral' => $aff->load('user:id,email'), + 'commissions' => $commissions ?? null, + ]); } // 设置提现申请状态 - public function setStatus(Request $request): JsonResponse + public function setStatus(Request $request, ReferralApply $aff) { - $id = $request->input('id'); - $status = (int) $request->input('status'); + $status = (int) $request->validate(['status' => 'required|numeric|between:-1,2']); - $ret = ReferralApply::whereId($id)->update(['status' => $status]); - if ($ret) { + if ($aff->update(['status' => $status])) { // 审核申请的时候将关联的 - $referralApply = ReferralApply::findOrFail($id); - if ($referralApply && $status === 1) { - ReferralLog::whereIn('id', $referralApply->link_logs)->update(['status' => 1]); - } elseif ($referralApply && $status === 2) { - ReferralLog::whereIn('id', $referralApply->link_logs)->update(['status' => 2]); + if ($status === 1 || $status === 2) { + $aff->referral_logs()->update(['status' => $status]); } } - return Response::json(['status' => 'success', 'message' => '操作成功']); + return response()->json(['status' => 'success', 'message' => '操作成功']); } // 用户返利流水记录 @@ -98,8 +85,6 @@ class AffiliateController extends Controller $query->whereStatus($status); } - $view['list'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.aff.rebate', $view); + return view('admin.aff.rebate', ['referralLogs' => $query->paginate(15)->appends($request->except('page'))]); } } diff --git a/app/Http/Controllers/Admin/ArticleController.php b/app/Http/Controllers/Admin/ArticleController.php index c1849e31..daacfffd 100644 --- a/app/Http/Controllers/Admin/ArticleController.php +++ b/app/Http/Controllers/Admin/ArticleController.php @@ -6,22 +6,15 @@ use App\Http\Controllers\Controller; use App\Http\Requests\Admin\ArticleRequest; use App\Models\Article; use Exception; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\RedirectResponse; -use Illuminate\Http\Request; use Illuminate\Http\UploadedFile; use Log; -use Redirect; -use Response; class ArticleController extends Controller { // 文章列表 - public function index(Request $request) + public function index() { - $view['articles'] = Article::orderByDesc('sort')->paginate(15)->appends($request->except('page')); - - return view('admin.article.index', $view); + return view('admin.article.index', ['articles' => Article::orderByDesc('sort')->paginate(15)->appends(request('page'))]); } // 添加文章页面 @@ -33,9 +26,9 @@ class ArticleController extends Controller // 添加文章 public function store(ArticleRequest $request) { - $data = $request->except('_method', '_token'); + $data = $request->validated(); // LOGO - if ($request->input('type') !== '4' && $request->hasFile('logo')) { + if ($data['type'] !== '4' && $request->hasFile('logo')) { $path = $this->fileUpload($request->file('logo')); if (is_string($path)) { $data['logo'] = $path; @@ -44,50 +37,44 @@ class ArticleController extends Controller } } - $article = Article::create($data); - if ($article->id) { - return Redirect::route('admin.article.edit', $article->id)->with('successMsg', '添加成功'); + if ($article = Article::create($data)) { + return redirect(route('admin.article.edit', $article))->with('successMsg', '添加成功'); } - return Redirect::back()->withInput()->withErrors('添加失败'); + return redirect()->back()->withInput()->withErrors('添加失败'); } // 图片上传 public function fileUpload(UploadedFile $file) { $fileName = Str::random(8).time().'.'.$file->getClientOriginalExtension(); - $path = $file->storeAs('public', $fileName); - if (! $path) { - return Redirect::back()->withInput()->withErrors('Logo存储失败'); + if (! $file->storeAs('public', $fileName)) { + return redirect()->back()->withInput()->withErrors('Logo存储失败'); } return 'upload/'.$fileName; } // 文章页面 - public function show($id) + public function show(Article $article) { - $view['article'] = Article::find($id); - - return view('admin.article.show', $view); + return view('admin.article.show', compact('article')); } // 编辑文章页面 - public function edit($id) + public function edit(Article $article) { - $view['article'] = Article::find($id); - - return view('admin.article.edit', $view); + return view('admin.article.edit', compact('article')); } // 编辑文章 - public function update(ArticleRequest $request, $id): RedirectResponse + public function update(ArticleRequest $request, Article $article) { - $data = $request->except('_method', '_token'); + $data = $request->validated(); $data['logo'] = $data['logo'] ?? null; // LOGO - if ($request->input('type') != 4 && $request->hasFile('logo')) { + if ($data['type'] !== '4' && $request->hasFile('logo')) { $path = $this->fileUpload($request->file('logo')); if (is_string($path)) { $data['logo'] = $path; @@ -96,26 +83,24 @@ class ArticleController extends Controller } } - if (Article::find($id)->update($data)) { - return Redirect::back()->with('successMsg', '编辑成功'); + if ($article->update($data)) { + return redirect()->back()->with('successMsg', '编辑成功'); } - return Redirect::back()->withErrors('编辑失败'); + return redirect()->back()->withInput()->withErrors('编辑失败'); } // 删除文章 - public function destroy($id): JsonResponse + public function destroy(Article $article) { try { - Article::find($id)->delete(); + $article->delete(); } catch (Exception $e) { Log::error('删除文章失败:'.$e->getMessage()); - return Response::json( - ['status' => 'fail', 'message' => '删除失败:'.$e->getMessage()] - ); + return response()->json(['status' => 'fail', 'message' => '删除失败:'.$e->getMessage()]); } - return Response::json(['status' => 'success', 'message' => '删除成功']); + return response()->json(['status' => 'success', 'message' => '删除成功']); } } diff --git a/app/Http/Controllers/Admin/CertController.php b/app/Http/Controllers/Admin/CertController.php index f4123d05..69589af2 100644 --- a/app/Http/Controllers/Admin/CertController.php +++ b/app/Http/Controllers/Admin/CertController.php @@ -3,32 +3,29 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\CertRequest; use App\Models\NodeCertificate; use Exception; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; use Log; -use Response; class CertController extends Controller { // 域名证书列表 - public function index(Request $request) + public function index() { - $DvList = NodeCertificate::orderBy('id')->paginate(15)->appends($request->except('page')); - foreach ($DvList as $Dv) { - if ($Dv->pem) { - $DvInfo = openssl_x509_parse($Dv->pem); - if ($DvInfo) { - $Dv->issuer = $DvInfo['issuer']['O'] ?? null; - $Dv->from = date('Y-m-d', $DvInfo['validFrom_time_t']) ?: null; - $Dv->to = date('Y-m-d', $DvInfo['validTo_time_t']) ?: null; + $certs = NodeCertificate::orderBy('id')->paginate(15)->appends(request('page')); + foreach ($certs as $cert) { + if ($cert->pem) { + $certInfo = openssl_x509_parse($cert->pem); + if ($certInfo) { + $cert->issuer = $certInfo['issuer']['O'] ?? null; + $cert->from = date('Y-m-d', $certInfo['validFrom_time_t']) ?: null; + $cert->to = date('Y-m-d', $certInfo['validTo_time_t']) ?: null; } } } - $view['list'] = $DvList; - return view('admin.node.cert.index', $view); + return view('admin.node.cert.index', ['certs' => $certs]); } public function create() @@ -37,52 +34,43 @@ class CertController extends Controller } // 添加域名证书 - public function store(Request $request): JsonResponse + public function store(CertRequest $request) { - $cert = new NodeCertificate(); - $cert->domain = $request->input('domain'); - $cert->key = str_replace(["\r", "\n"], '', $request->input('key')); - $cert->pem = str_replace(["\r", "\n"], '', $request->input('pem')); - $cert->save(); - - if ($cert->id) { - return Response::json(['status' => 'success', 'message' => '生成成功']); + if ($cert = NodeCertificate::create($request->validated())) { + return redirect(route('admin.node.cert.update', $cert))->with('successMsg', '生成成功'); } - return Response::json(['status' => 'fail', 'message' => '生成失败']); + return redirect()->back()->withInput()->withErrors('生成失败'); } // 编辑域名证书 - public function edit($id) + public function edit(NodeCertificate $cert) { - $view['Dv'] = NodeCertificate::find($id); - - return view('admin.node.cert.info', $view); + return view('admin.node.cert.info', compact('cert')); } - public function update(Request $request, $id): JsonResponse + public function update(CertRequest $request, NodeCertificate $cert) { - $Dv = NodeCertificate::findOrFail($id); - if ($Dv->update(['domain' => $request->input('domain'), 'key' => $request->input('key'), 'pem' => $request->input('pem')])) { - return Response::json(['status' => 'success', 'message' => '修改成功']); + if ($cert->update($request->validated())) { + return redirect()->back()->with('successMsg', '修改成功'); } - return Response::json(['status' => 'fail', 'message' => '修改失败']); + return redirect()->back()->withInput()->withErrors('修改失败'); } // 删除域名证书 - public function destroy($id): JsonResponse + public function destroy(NodeCertificate $cert) { try { - if (NodeCertificate::whereId($id)->delete()) { - return Response::json(['status' => 'success', 'message' => '操作成功']); + if ($cert->delete()) { + return response()->json(['status' => 'success', 'message' => '操作成功']); } } catch (Exception $e) { Log::error('删除域名证书失败:'.$e->getMessage()); - return Response::json(['status' => 'fail', 'message' => '删除域名证书失败:'.$e->getMessage()]); + return response()->json(['status' => 'fail', 'message' => '删除域名证书错误:'.$e->getMessage()]); } - return Response::json(['status' => 'fail', 'message' => '删除域名证书失败']); + return response()->json(['status' => 'fail', 'message' => '删除域名证书失败']); } } diff --git a/app/Http/Controllers/Admin/Config/EmailFilterController.php b/app/Http/Controllers/Admin/Config/EmailFilterController.php index 9a662057..63c42fb0 100644 --- a/app/Http/Controllers/Admin/Config/EmailFilterController.php +++ b/app/Http/Controllers/Admin/Config/EmailFilterController.php @@ -16,9 +16,7 @@ class EmailFilterController extends Controller // 邮箱过滤列表 public function index() { - $view['list'] = EmailFilter::orderByDesc('id')->paginate(15); - - return view('admin.config.emailFilter', $view); + return view('admin.config.emailFilter', ['list' => EmailFilter::orderByDesc('id')->paginate()]); } // 添加邮箱后缀 diff --git a/app/Http/Controllers/Admin/Config/LabelController.php b/app/Http/Controllers/Admin/Config/LabelController.php index c5f000de..6590088b 100644 --- a/app/Http/Controllers/Admin/Config/LabelController.php +++ b/app/Http/Controllers/Admin/Config/LabelController.php @@ -4,7 +4,6 @@ namespace App\Http\Controllers\Admin\Config; use App\Http\Controllers\Controller; use App\Models\Label; -use App\Models\NodeLabel; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -28,9 +27,9 @@ class LabelController extends Controller } // 编辑标签 - public function update(Request $request, $id): JsonResponse + public function update(Request $request, Label $label): JsonResponse { - if (Label::whereId($id)->update(['name' => $request->input('name'), 'sort' => $request->input('sort')])) { + if ($label->update(['name' => $request->input('name'), 'sort' => $request->input('sort')])) { return Response::json(['status' => 'success', 'message' => '编辑成功']); } @@ -38,10 +37,10 @@ class LabelController extends Controller } // 删除标签 - public function destroy($id): ?JsonResponse + public function destroy(Label $label): ?JsonResponse { try { - Label::whereId($id)->delete(); + $label->delete(); return Response::json(['status' => 'success', 'message' => '删除成功']); } catch (Exception $e) { diff --git a/app/Http/Controllers/Admin/CouponController.php b/app/Http/Controllers/Admin/CouponController.php index 764b76d4..d63dc22b 100644 --- a/app/Http/Controllers/Admin/CouponController.php +++ b/app/Http/Controllers/Admin/CouponController.php @@ -43,9 +43,7 @@ class CouponController extends Controller $query->whereStatus($status); } - $view['couponList'] = $query->latest()->paginate(15)->appends($request->except('page')); - - return view('admin.coupon.index', $view); + return view('admin.coupon.index', ['couponList' => $query->latest()->paginate(15)->appends($request->except('page'))]); } // 添加优惠券页面 @@ -71,19 +69,12 @@ class CouponController extends Controller } try { $num = (int) $request->input('num'); + $data = $request->only(['name', 'type', 'usable_times', 'value', 'rule', 'start_time', 'end_time']); + $data['logo'] = $logo; for ($i = 0; $i < $num; $i++) { - $obj = new Coupon(); - $obj->name = $request->input('name'); - $obj->logo = $logo; - $obj->sn = $num === 1 && $request->input('sn') ? $request->input('sn') : Str::random(8); - $obj->type = $request->input('type'); - $obj->usable_times = $request->input('usable_times'); - $obj->value = $request->input('value'); - $obj->rule = $request->input('rule'); - $obj->start_time = strtotime($request->input('start_time')); - $obj->end_time = strtotime($request->input('end_time')); - $obj->save(); + $data['sn'] = $num === 1 && $request->input('sn') ? $request->input('sn') : Str::random(8); + Coupon::create($data); } return Redirect::route('admin.coupon.index')->with('successMsg', '生成成功'); @@ -95,10 +86,10 @@ class CouponController extends Controller } // 删除优惠券 - public function destroy($id): JsonResponse + public function destroy(Coupon $coupon): JsonResponse { try { - if (Coupon::find($id)->delete()) { + if ($coupon->delete()) { return Response::json(['status' => 'success', 'message' => '删除成功']); } } catch (Exception $e) { @@ -132,7 +123,7 @@ class CouponController extends Controller $sheet->setTitle('抵用券'); $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '金额(元)', '使用限制(元)'], null); foreach ($voucherList as $k => $vo) { - $dateRange = date('Y-m-d', $vo->start_time).' ~ '.date('Y-m-d', $vo->end_time); + $dateRange = $vo->start_time.' ~ '.$vo->end_time; $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->rule], null, 'A'.($k + 2)); } @@ -143,7 +134,7 @@ class CouponController extends Controller $sheet->setTitle('折扣券'); $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '折扣(折)', '使用限制(元)'], null); foreach ($discountCouponList as $k => $vo) { - $dateRange = date('Y-m-d', $vo->start_time).' ~ '.date('Y-m-d', $vo->end_time); + $dateRange = $vo->start_time.' ~ '.$vo->end_time; $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->rule], null, 'A'.($k + 2)); } @@ -154,7 +145,7 @@ class CouponController extends Controller $sheet->setTitle('充值券'); $sheet->fromArray(['名称', '有效期', '券码', '金额(元)'], null); foreach ($refillList as $k => $vo) { - $dateRange = date('Y-m-d', $vo->start_time).' ~ '.date('Y-m-d', $vo->end_time); + $dateRange = $vo->start_time.' ~ '.$vo->end_time; $sheet->fromArray([$vo->name, $dateRange, $vo->sn, $vo->value], null, 'A'.($k + 2)); } diff --git a/app/Http/Controllers/Admin/LogsController.php b/app/Http/Controllers/Admin/LogsController.php index b5d2047e..c58fa991 100644 --- a/app/Http/Controllers/Admin/LogsController.php +++ b/app/Http/Controllers/Admin/LogsController.php @@ -5,7 +5,7 @@ namespace App\Http\Controllers\Admin; use App\Components\IP; use App\Http\Controllers\Controller; use App\Models\Node; -use App\Models\NodeOnlineUserIp; +use App\Models\NodeOnlineIp; use App\Models\NotificationLog; use App\Models\Order; use App\Models\PaymentCallback; @@ -15,7 +15,6 @@ use App\Models\UserCreditLog; use App\Models\UserDataFlowLog; use App\Models\UserDataModifyLog; use Illuminate\Http\Request; -use Redirect; class LogsController extends Controller { @@ -78,9 +77,7 @@ class LogsController extends Controller $query->orderByDesc('id'); } - $view['orderList'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.logs.order', $view); + return view('admin.logs.order', ['orders' => $query->paginate(15)->appends($request->except('page'))]); } // 流量日志 @@ -123,20 +120,18 @@ class LogsController extends Controller $query->where('log_time', '<=', strtotime($endTime)); } - // 已使用流量 - $view['totalTraffic'] = flowAutoShow($query->sum('u') + $query->sum('d')); - - $list = $query->latest('log_time')->paginate(20)->appends($request->except('page')); - foreach ($list as $vo) { - $vo->u = flowAutoShow($vo->u); - $vo->d = flowAutoShow($vo->d); - $vo->log_time = date('Y-m-d H:i:s', $vo->log_time); + $dataFlowLogs = $query->latest('log_time')->paginate(20)->appends($request->except('page')); + foreach ($dataFlowLogs as $log) { + $log->u = flowAutoShow($log->u); + $log->d = flowAutoShow($log->d); + $log->log_time = date('Y-m-d H:i:s', $log->log_time); } - $view['list'] = $list; - $view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->latest()->get(); - - return view('admin.logs.traffic', $view); + return view('admin.logs.traffic', [ + 'totalTraffic' => flowAutoShow($query->sum('u') + $query->sum('d')), // 已使用流量 + 'dataFlowLogs' => $dataFlowLogs, + 'nodes' => Node::whereStatus(1)->orderByDesc('sort')->latest()->get(), + ]); } // 邮件发送日志列表 @@ -155,9 +150,7 @@ class LogsController extends Controller $query->whereType($type); } - $view['list'] = $query->latest()->paginate(15)->appends($request->except('page')); - - return view('admin.logs.notification', $view); + return view('admin.logs.notification', ['notificationLogs' => $query->latest()->paginate(15)->appends($request->except('page'))]); } // 在线IP监控(实时) @@ -168,7 +161,7 @@ class LogsController extends Controller $port = $request->input('port'); $nodeId = $request->input('nodeId'); - $query = NodeOnlineUserIp::with(['node:id,name', 'user:id,email'])->where('created_at', '>=', strtotime('-2 minutes')); + $query = NodeOnlineIp::with(['node:id,name', 'user:id,email'])->where('created_at', '>=', strtotime('-2 minutes')); if (isset($ip)) { $query->whereIp($ip); @@ -209,10 +202,10 @@ class LogsController extends Controller $log->ipInfo = implode(' ', $ipInfo); } - $view['list'] = $onlineIPLogs; - $view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->latest()->get(); - - return view('admin.logs.onlineIPMonitor', $view); + return view('admin.logs.onlineIPMonitor', [ + 'onlineIPLogs' => $onlineIPLogs, + 'nodes' => Node::whereStatus(1)->orderByDesc('sort')->latest()->get(), + ]); } // 用户余额变动记录 @@ -228,9 +221,7 @@ class LogsController extends Controller }); } - $view['list'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.logs.userCreditHistory', $view); + return view('admin.logs.userCreditHistory', ['userCreditLogs' => $query->paginate(15)->appends($request->except('page'))]); } // 用户封禁记录 @@ -246,9 +237,7 @@ class LogsController extends Controller }); } - $view['list'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.logs.userBanHistory', $view); + return view('admin.logs.userBanHistory', ['userBanLogs' => $query->paginate(15)->appends($request->except('page'))]); } // 用户流量变动记录 @@ -264,9 +253,7 @@ class LogsController extends Controller }); } - $view['list'] = $query->latest()->paginate(15)->appends($request->except('page')); - - return view('admin.logs.userTraffic', $view); + return view('admin.logs.userTraffic', ['userTrafficLogs' => $query->latest()->paginate(15)->appends($request->except('page'))]); } // 用户在线IP记录 @@ -297,34 +284,19 @@ class LogsController extends Controller $userList = $query->paginate(15)->appends($request->except('page')); - $nodeOnlineIPs = NodeOnlineUserIp::with('node:id,name')->where('created_at', '>=', strtotime('-10 minutes'))->latest()->distinct(); - // Todo 优化查询 + $nodeOnlineIPs = NodeOnlineIp::with('node:id,name')->where('created_at', '>=', strtotime('-10 minutes'))->latest()->distinct()->get(); foreach ($userList as $user) { // 最近5条在线IP记录,如果后端设置为60秒上报一次,则为10分钟内的在线IP - $user->onlineIPList = $nodeOnlineIPs->wherePort($user->port)->limit(5)->get(); + $user->onlineIPList = $nodeOnlineIPs->where('port', '==', $user->port)->chunk(5); } - $view['userList'] = $userList; - - return view('admin.logs.userOnlineIP', $view); + return view('admin.logs.userOnlineIP', ['userList' => $userList]); } // 用户流量监控 - public function userTrafficMonitor($id) + public function userTrafficMonitor(User $user) { - if (empty($id)) { - return Redirect::back(); - } - - $user = User::find($id); - if (empty($user)) { - return Redirect::back(); - } - - $view['email'] = $user->email; - $view = array_merge($view, $this->dataFlowChart($user->id)); - - return view('admin.logs.userMonitor', $view); + return view('admin.logs.userMonitor', array_merge(['email' => $user->email], $this->dataFlowChart($user->id))); } // 回调日志 @@ -338,8 +310,6 @@ class LogsController extends Controller $query->whereStatus($status); } - $view['list'] = $query->latest()->paginate(10)->appends($request->except('page')); - - return view('admin.logs.callback', $view); + return view('admin.logs.callback', ['callbackLogs' => $query->latest()->paginate(10)->appends($request->except('page'))]); } } diff --git a/app/Http/Controllers/Admin/MarketingController.php b/app/Http/Controllers/Admin/MarketingController.php index 6a7557fb..e6eeb091 100644 --- a/app/Http/Controllers/Admin/MarketingController.php +++ b/app/Http/Controllers/Admin/MarketingController.php @@ -31,9 +31,7 @@ class MarketingController extends Controller $query->whereStatus($status); } - $view['list'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.marketing.emailList', $view); + return view('admin.marketing.emailList', ['emails' => $query->paginate(15)->appends($request->except('page'))]); } // 消息通道群发列表 @@ -47,9 +45,7 @@ class MarketingController extends Controller $query->whereStatus($status); } - $view['list'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.marketing.pushList', $view); + return view('admin.marketing.pushList', ['pushes' => $query->paginate(15)->appends($request->except('page'))]); } // 添加推送消息 diff --git a/app/Http/Controllers/Admin/NodeAuthController.php b/app/Http/Controllers/Admin/NodeAuthController.php new file mode 100644 index 00000000..60ec4590 --- /dev/null +++ b/app/Http/Controllers/Admin/NodeAuthController.php @@ -0,0 +1,62 @@ + NodeAuth::orderBy('node_id')->paginate()->appends(request('page'))]); + } + + // 添加节点授权 + public function store(Request $request) + { + $nodeArray = Node::whereStatus(1)->orderBy('id')->pluck('id')->toArray(); + $authArray = NodeAuth::orderBy('node_id')->pluck('node_id')->toArray(); + + $arrayDifferent = array_diff($nodeArray, $authArray); + + if (empty($arrayDifferent)) { + return Response::json(['status' => 'success', 'message' => '没有需要生成授权的节点']); + } + + foreach ($arrayDifferent as $nodeId) { + $obj = new NodeAuth(); + $obj->node_id = $nodeId; + $obj->key = Str::random(); + $obj->secret = Str::random(8); + $obj->save(); + } + + return Response::json(['status' => 'success', 'message' => '生成成功']); + } + + // 重置节点授权 + public function update(NodeAuth $auth) + { + if ($auth->update(['key' => Str::random(), 'secret' => Str::random(8)])) { + return Response::json(['status' => 'success', 'message' => '操作成功']); + } + + return Response::json(['status' => 'fail', 'message' => '操作失败']); + } + + // 删除节点授权 + public function destroy(NodeAuth $auth) + { + try { + $auth->delete(); + } catch (Exception $e) { + return Response::json(['status' => 'fail', 'message' => '错误:'.var_export($e, true)]); + } + + return Response::json(['status' => 'success', 'message' => '操作成功']); + } +} diff --git a/app/Http/Controllers/Admin/NodeController.php b/app/Http/Controllers/Admin/NodeController.php index b2d4e5b8..b49daf8d 100644 --- a/app/Http/Controllers/Admin/NodeController.php +++ b/app/Http/Controllers/Admin/NodeController.php @@ -10,18 +10,15 @@ use App\Models\Country; use App\Models\Label; use App\Models\Level; use App\Models\Node; -use App\Models\NodeAuth; use App\Models\NodeCertificate; use App\Models\NodePing; +use App\Models\RuleGroup; use App\Services\NodeService; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; -use Redirect; use Response; -use Session; -use Str; class NodeController extends Controller { @@ -52,19 +49,18 @@ class NodeController extends Controller $node->uptime = empty($node_info) ? 0 : seconds2time($node_info->uptime); } - $view['nodeList'] = $nodeList; - - return view('admin.node.index', $view); + return view('admin.node.index', ['nodeList' => $nodeList]); } // 添加节点页面 public function create() { return view('admin.node.info', [ - 'countryList' => Country::orderBy('code')->get(), - 'levelList' => Level::orderBy('level')->get(), - 'labelList' => Label::orderByDesc('sort')->orderBy('id')->get(), - 'dvList' => NodeCertificate::orderBy('id')->get(), + 'countries' => Country::orderBy('code')->get(), + 'levels' => Level::orderBy('level')->get(), + 'ruleGroups' => RuleGroup::orderBy('id')->get(), + 'labels' => Label::orderByDesc('sort')->orderBy('id')->get(), + 'certs' => NodeCertificate::orderBy('id')->get(), ]); } @@ -76,8 +72,8 @@ class NodeController extends Controller if ($node) { // 生成节点标签 - if ($request->exists('labels')) { - (new NodeService())->makeLabels($node->id, $request->input('labels')); + if ($request->has('labels')) { + $node->labels()->attach($request->input('labels')); } return Response::json(['status' => 'success', 'message' => '添加成功']); @@ -92,27 +88,24 @@ class NodeController extends Controller } // 编辑节点页面 - public function edit($id) + public function edit(Node $node) { return view('admin.node.info', [ - 'node' => Node::with('labels')->find($id), - 'countryList' => Country::orderBy('code')->get(), - 'levelList' => Level::orderBy('level')->get(), - 'labelList' => Label::orderByDesc('sort')->orderBy('id')->get(), - 'dvList' => NodeCertificate::orderBy('id')->get(), + 'node' => $node, + 'countries' => Country::orderBy('code')->get(), + 'levels' => Level::orderBy('level')->get(), + 'ruleGroups' => RuleGroup::orderBy('id')->get(), + 'labels' => Label::orderByDesc('sort')->orderBy('id')->get(), + 'certs' => NodeCertificate::orderBy('id')->get(), ]); } // 编辑节点 - public function update(NodeRequest $request, $id): JsonResponse + public function update(NodeRequest $request, Node $node): JsonResponse { - $node = Node::find($id); - try { - // 生成节点标签 - if ($request->exists('labels')) { - (new NodeService())->makeLabels($node->id, $request->input('labels')); - } + // 更新节点标签 + $node->labels()->sync($request->input('labels')); if ($node->update($request->except('_token', 'labels'))) { return Response::json(['status' => 'success', 'message' => '编辑成功']); @@ -127,10 +120,8 @@ class NodeController extends Controller } // 删除节点 - public function destroy($id): JsonResponse + public function destroy(Node $node): JsonResponse { - $node = Node::findOrFail($id); - try { if ($node->delete()) { return Response::json(['status' => 'success', 'message' => '删除成功']); @@ -145,9 +136,8 @@ class NodeController extends Controller } // 节点信息验证 - public function checkNode($id): JsonResponse + public function checkNode(Node $node): JsonResponse { - $node = Node::find($id); // 使用DDNS的node先获取ipv4地址 if ($node->is_ddns) { $ip = gethostbyname($node->server); @@ -174,9 +164,9 @@ class NodeController extends Controller } // 重载节点 - public function reload($id): JsonResponse + public function reload(Node $node): JsonResponse { - if (reloadNode::dispatchNow(Node::whereId($id)->get())) { + if (reloadNode::dispatchNow($node)) { return Response::json(['status' => 'success', 'message' => '重载成功!']); } @@ -184,27 +174,14 @@ class NodeController extends Controller } // 节点流量监控 - public function nodeMonitor($id) + public function nodeMonitor(Node $node) { - $node = Node::find($id); - if (! $node) { - Session::flash('errorMsg', '节点不存在,请重试'); - - return Redirect::back(); - } - - $view['nodeName'] = $node->name; - $view['nodeServer'] = $node->server; - $view = array_merge($view, $this->DataFlowChart($node->id, true)); - - return view('admin.node.monitor', $view); + return view('admin.node.monitor', array_merge(['nodeName' => $node->name, 'nodeServer' => $node->server], $this->DataFlowChart($node->id, true))); } // Ping节点延迟 - public function pingNode($id): JsonResponse + public function pingNode(Node $node): JsonResponse { - $node = Node::findOrFail($id); - $result = NetworkDetection::ping($node->is_ddns ? $node->server : $node->ip); if ($result) { @@ -225,69 +202,15 @@ class NodeController extends Controller // Ping节点延迟日志 public function pingLog(Request $request) { - $node_id = $request->input('nodeId'); + $node_id = $request->input('id'); $query = NodePing::query(); if (isset($node_id)) { $query->whereNodeId($node_id); } - $view['nodeList'] = Node::orderBy('id')->get(); - $view['pingLogs'] = $query->latest()->paginate(15)->appends($request->except('page')); - - return view('admin.node.ping', $view); - } - - // 节点授权列表 - public function authList(Request $request) - { - $view['list'] = NodeAuth::orderBy('node_id')->paginate(15)->appends($request->except('page')); - - return view('admin.node.auth', $view); - } - - // 添加节点授权 - public function addAuth(): JsonResponse - { - $nodeArray = Node::whereStatus(1)->orderBy('id')->pluck('id')->toArray(); - $authArray = NodeAuth::orderBy('node_id')->pluck('node_id')->toArray(); - - $arrayDifferent = array_diff($nodeArray, $authArray); - - if (empty($arrayDifferent)) { - return Response::json(['status' => 'success', 'message' => '没有需要生成授权的节点']); - } - - foreach ($arrayDifferent as $nodeId) { - $obj = new NodeAuth(); - $obj->node_id = $nodeId; - $obj->key = Str::random(); - $obj->secret = Str::random(8); - $obj->save(); - } - - return Response::json(['status' => 'success', 'message' => '生成成功']); - } - - // 删除节点授权 - public function delAuth($id): JsonResponse - { - try { - NodeAuth::whereId($id)->delete(); - } catch (Exception $e) { - return Response::json(['status' => 'fail', 'message' => '错误:'.var_export($e, true)]); - } - - return Response::json(['status' => 'success', 'message' => '操作成功']); - } - - // 重置节点授权 - public function refreshAuth($id): JsonResponse - { - $ret = NodeAuth::find($id)->update(['key' => Str::random(), 'secret' => Str::random(8)]); - if ($ret) { - return Response::json(['status' => 'success', 'message' => '操作成功']); - } - - return Response::json(['status' => 'fail', 'message' => '操作失败']); + return view('admin.node.ping', [ + 'nodeList' => Node::orderBy('id')->get(), + 'pingLogs' => $query->latest()->paginate(15)->appends($request->except('page')), + ]); } } diff --git a/app/Http/Controllers/Admin/PermissionController.php b/app/Http/Controllers/Admin/PermissionController.php index 09356e57..516e6d79 100644 --- a/app/Http/Controllers/Admin/PermissionController.php +++ b/app/Http/Controllers/Admin/PermissionController.php @@ -3,17 +3,15 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; -use Illuminate\Http\Request; -use Illuminate\Http\Response; +use App\Http\Requests\Admin\PermissionRequest; +use Exception; use Spatie\Permission\Models\Permission; class PermissionController extends Controller { public function index() { - $permissions = Permission::query()->paginate(15); - - return view('admin.permission.index', compact('permissions')); + return view('admin.permission.index', ['permissions' => Permission::query()->paginate(15)]); } public function create() @@ -21,17 +19,9 @@ class PermissionController extends Controller return view('admin.permission.info'); } - public function store(Request $request) + public function store(PermissionRequest $request) { - $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']); - - if ($validator->fails()) { - return redirect()->back()->withInput()->withErrors($validator->errors()); - } - - $permission = Permission::create($request->all()); - - if ($permission) { + if ($permission = Permission::create($request->validated())) { return redirect()->route('admin.permission.edit', $permission)->with('successMsg', '操作成功'); } @@ -43,15 +33,9 @@ class PermissionController extends Controller return view('admin.permission.info', compact('permission')); } - public function update(Request $request, Permission $permission) + public function update(PermissionRequest $request, Permission $permission) { - $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']); - - if ($validator->fails()) { - return redirect()->back()->withInput()->withErrors($validator->errors()); - } - - if ($permission->update($request->all())) { + if ($permission->update($request->validated())) { return redirect()->back()->with('successMsg', '操作成功'); } @@ -63,9 +47,9 @@ class PermissionController extends Controller try { $permission->delete(); } catch (Exception $e) { - return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); + return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); } - return Response::json(['status' => 'success', 'message' => '清理成功']); + return response()->json(['status' => 'success', 'message' => '清理成功']); } } diff --git a/app/Http/Controllers/Admin/RoleController.php b/app/Http/Controllers/Admin/RoleController.php index 74ec310f..48a634bc 100644 --- a/app/Http/Controllers/Admin/RoleController.php +++ b/app/Http/Controllers/Admin/RoleController.php @@ -3,8 +3,8 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; -use Illuminate\Http\Request; -use Illuminate\Http\Response; +use App\Http\Requests\Admin\RoleRequest; +use Exception; use Spatie\Permission\Models\Permission; use Spatie\Permission\Models\Role; @@ -12,29 +12,19 @@ class RoleController extends Controller { public function index() { - $roles = Role::with('permissions')->paginate(15); - - return view('admin.role.index', compact('roles')); + return view('admin.role.index', ['roles' => Role::with('permissions')->paginate(15)]); } public function create() { - $permissions = Permission::all()->pluck('description', 'name'); - - return view('admin.role.info', compact('permissions')); + return view('admin.role.info', ['permissions' => Permission::all()->pluck('description', 'name')]); } - public function store(Request $request) + public function store(RoleRequest $request) { - $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']); + if ($role = Role::create($request->only(['name', 'description']))) { + $role->givePermissionTo($request->input('permissions') ?: []); - if ($validator->fails()) { - return redirect()->back()->withInput()->withErrors($validator->errors()); - } - - $role = Role::create($request->except('permissions')); - $permissions = $request->input('permissions') ?: []; - if ($role->givePermissionTo($permissions)) { return redirect()->route('admin.role.edit', $role)->with('successMsg', '操作成功'); } @@ -43,27 +33,21 @@ class RoleController extends Controller public function edit(Role $role) { - $role->load('permissions'); - $permissions = Permission::all()->pluck('description', 'name'); - - return view('admin.role.info', compact('role', 'permissions')); + return view('admin.role.info', [ + 'role' => $role->load('permissions'), + 'permissions' => Permission::all()->pluck('description', 'name'), + ]); } - public function update(Request $request, Role $role) + public function update(RoleRequest $request, Role $role) { - $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']); - - if ($validator->fails()) { - return redirect()->back()->withInput()->withErrors($validator->errors()); - } - if ($role->name === 'Super Admin') { return redirect()->back()->withInput()->withErrors('请勿修改超级管理员'); } - $role->update($request->except('permissions')); - $permissions = $request->input('permissions') ?: []; - if ($role->syncPermissions($permissions)) { + if ($role->update($request->only(['name', 'description']))) { + $role->syncPermissions($request->input('permissions') ?: []); + return redirect()->back()->with('successMsg', '操作成功'); } @@ -74,13 +58,13 @@ class RoleController extends Controller { try { if ($role->name === 'Super Admin') { - return Response::json(['status' => 'fail', 'message' => '请勿删除超级管理员']); + return response()->json(['status' => 'fail', 'message' => '请勿删除超级管理员']); } $role->delete(); } catch (Exception $e) { - return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); + return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); } - return Response::json(['status' => 'success', 'message' => '清理成功']); + return response()->json(['status' => 'success', 'message' => '清理成功']); } } diff --git a/app/Http/Controllers/Admin/RuleController.php b/app/Http/Controllers/Admin/RuleController.php index 930b3f1d..3b4c327a 100644 --- a/app/Http/Controllers/Admin/RuleController.php +++ b/app/Http/Controllers/Admin/RuleController.php @@ -3,15 +3,14 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\RuleRequest; use App\Models\Node; use App\Models\Rule; -use App\Models\RuleGroup; use App\Models\RuleLog; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Response; -use Validator; class RuleController extends Controller { @@ -25,31 +24,13 @@ class RuleController extends Controller $query->whereType($type); } - $view['rules'] = $query->paginate(15)->appends($request->except('page')); - - return view('admin.rule.index', $view); + return view('admin.rule.index', ['rules' => $query->paginate(15)->appends($request->except('page'))]); } // 添加审计规则 - public function store(Request $request): JsonResponse + public function store(RuleRequest $request): JsonResponse { - $validator = Validator::make($request->all(), [ - 'type' => 'required|between:1,4', - 'name' => 'required', - 'pattern' => 'required', - ]); - - if ($validator->fails()) { - return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); - } - - $rule = new Rule(); - $rule->type = $request->input('type'); - $rule->name = $request->input('name'); - $rule->pattern = $request->input('pattern'); - $rule->save(); - - if ($rule->id) { + if (Rule::create($request->validated())) { return Response::json(['status' => 'success', 'message' => '提交成功']); } @@ -57,9 +38,9 @@ class RuleController extends Controller } // 编辑审计规则 - public function update(Request $request, $id): JsonResponse + public function update(RuleRequest $request, Rule $rule): JsonResponse { - if (Rule::find($id)->update(['name' => $request->input('rule_name'), 'pattern' => $request->input('rule_pattern')])) { + if ($rule->update($request->validated())) { return Response::json(['status' => 'success', 'message' => '操作成功']); } @@ -67,18 +48,10 @@ class RuleController extends Controller } // 删除审计规则 - public function destroy($id): JsonResponse + public function destroy(Rule $rule): JsonResponse { try { - Rule::whereId($id)->delete(); - - foreach (RuleGroup::all() as $ruleGroup) { - $rules = $ruleGroup->rules; - if ($rules && in_array($id, $rules, true)) { - $ruleGroup->rules = array_merge(array_diff($rules, [$id])); - $ruleGroup->save(); - } - } + $rule->delete(); } catch (Exception $e) { return Response::json(['status' => 'fail', 'message' => '操作失败, '.$e->getMessage()]); } @@ -110,11 +83,11 @@ class RuleController extends Controller $query->whereRuleId($ruleId); } - $view['nodeList'] = Node::all(); - $view['ruleList'] = Rule::all(); - $view['ruleLogs'] = $query->latest()->paginate(15)->appends($request->except('page')); - - return view('admin.rule.log', $view); + return view('admin.rule.log', [ + 'nodes' => Node::all(), + 'rules' => Rule::all(), + 'ruleLogs' => $query->latest()->paginate(15)->appends($request->except('page')), + ]); } // 清除所有审计触发日志 @@ -125,8 +98,8 @@ class RuleController extends Controller } catch (Exception $e) { return Response::json(['status' => 'fail', 'message' => '清理失败, '.$e->getMessage()]); } - $result = RuleLog::doesntExist(); - if ($ret || $result) { + + if ($ret || RuleLog::doesntExist()) { return Response::json(['status' => 'success', 'message' => '清理成功']); } diff --git a/app/Http/Controllers/Admin/RuleGroupController.php b/app/Http/Controllers/Admin/RuleGroupController.php index c9f0ef7c..1555969d 100644 --- a/app/Http/Controllers/Admin/RuleGroupController.php +++ b/app/Http/Controllers/Admin/RuleGroupController.php @@ -3,146 +3,67 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; -use App\Models\Node; +use App\Http\Requests\Admin\RuleGroupRequest; use App\Models\Rule; use App\Models\RuleGroup; -use App\Models\RuleGroupNode; use Exception; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\RedirectResponse; -use Illuminate\Http\Request; -use Redirect; -use Response; -use Validator; class RuleGroupController extends Controller { // 审计规则分组列表 - public function index(Request $request) + public function index() { - $view['ruleGroupList'] = RuleGroup::paginate(15)->appends($request->except('page')); - - return view('admin.rule.group.index', $view); + return view('admin.rule.group.index', ['ruleGroups' => RuleGroup::paginate(15)->appends(request('page'))]); } // 添加审计规则分组页面 public function create() { - $view['ruleList'] = Rule::all(); - - return view('admin.rule.group.info', $view); + return view('admin.rule.group.info', ['rules' => Rule::all()]); } // 添加审计规则分组 - public function store(Request $request): RedirectResponse + public function store(RuleGroupRequest $request) { - $validator = Validator::make($request->all(), [ - 'name' => 'required', - 'type' => 'required|boolean', - 'rules' => 'required', - ]); + if ($group = RuleGroup::create($request->only('name', 'type'))) { + $group->rules()->attach($request->input('rules')); - if ($validator->fails()) { - return Redirect::back()->withInput()->withErrors($validator->errors()); + return redirect(route('admin.rule.group.edit', $group))->with('successMsg', '操作成功'); } - $obj = new RuleGroup(); - $obj->name = $request->input('name'); - $obj->type = (int) $request->input('type'); - $obj->rules = $request->input('rules'); - $obj->save(); - - if ($obj->id) { - return Redirect::back()->with('successMsg', '操作成功'); - } - - return Redirect::back()->withInput()->withErrors('操作失败'); + return redirect()->back()->withInput()->withErrors('操作失败'); } // 编辑审计规则分组页面 - public function edit($id) + public function edit(RuleGroup $group) { - $view['ruleGroup'] = RuleGroup::find($id); - $view['ruleList'] = Rule::all(); - - return view('admin.rule.group.info', $view); + return view('admin.rule.group.info', [ + 'ruleGroup' => $group, + 'rules' => Rule::all(), + ]); } // 编辑审计规则分组 - public function update(Request $request, $id): RedirectResponse + public function update(RuleGroupRequest $request, RuleGroup $group) { - $validator = Validator::make($request->all(), [ - 'name' => 'required', - 'type' => 'required|boolean', - ]); - if ($validator->fails()) { - return Redirect::back()->withInput()->withErrors($validator->errors()); + if ($group->update($request->only(['name', 'type']))) { + $group->rules()->sync($request->input('rules')); + + return redirect()->back()->with('successMsg', '操作成功'); } - $ret = RuleGroup::find($id)->update([ - 'name' => $request->input('name'), - 'type' => $request->input('type'), - 'rules' => $request->input('rules'), - ]); - - if ($ret) { - return Redirect::back()->with('successMsg', '操作成功'); - } - - return Redirect::back()->withInput()->withErrors('操作失败'); + return redirect()->back()->withInput()->withErrors('操作失败'); } // 删除审计规则分组 - public function destroy($id): JsonResponse + public function destroy(RuleGroup $group) { try { - RuleGroup::whereId($id)->delete(); + $group->delete(); } catch (Exception $e) { - return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); + return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); } - return Response::json(['status' => 'success', 'message' => '清理成功']); - } - - // 规则分组关联节点 - public function assignNode($id) - { - $view['ruleGroup'] = RuleGroup::find($id); - $view['nodeList'] = Node::all(); - - return view('admin.rule.group.assign', $view); - } - - // 规则分组关联节点 - public function assign(Request $request, $id) - { - $nodes = $request->input('nodes'); - $ruleGroup = RuleGroup::findOrFail($id); - - try { - if ($ruleGroup->nodes === $nodes) { - return Redirect::back()->with('successMsg', '检测为未修改,无变动!'); - } - RuleGroupNode::whereRuleGroupId($id)->delete(); - if ($nodes) { - $ruleGroup->nodes = $nodes; - if (! $ruleGroup->save()) { - return Redirect::back()->withErrors('更新错误!'); - } - - foreach ($nodes as $nodeId) { - $obj = new RuleGroupNode(); - $obj->rule_group_id = $id; - $obj->node_id = $nodeId; - $obj->save(); - } - } else { - RuleGroup::find($id)->update(['nodes' => null]); - } - } catch (Exception $e) { - return Redirect::back()->withInput()->withErrors($e->getMessage()); - } - - return Redirect::back()->with('successMsg', '操作成功'); + return response()->json(['status' => 'success', 'message' => '清理成功']); } } diff --git a/app/Http/Controllers/Admin/ShopController.php b/app/Http/Controllers/Admin/ShopController.php index d6d6d914..ca16001f 100644 --- a/app/Http/Controllers/Admin/ShopController.php +++ b/app/Http/Controllers/Admin/ShopController.php @@ -17,11 +17,6 @@ use Redirect; use Response; use Str; -/** - * 商店控制器. - * - * Class ShopController - */ class ShopController extends Controller { // 商品列表 @@ -40,17 +35,13 @@ class ShopController extends Controller $query->whereStatus($status); } - $view['goodsList'] = $query->orderByDesc('status')->paginate(10)->appends($request->except('page')); - - return view('admin.shop.index', $view); + return view('admin.shop.index', ['goodsList' => $query->orderByDesc('status')->paginate(10)->appends($request->except('page'))]); } // 添加商品页面 public function create() { - $view['levelList'] = Level::orderBy('level')->get(); - - return view('admin.shop.info', $view); + return view('admin.shop.info', ['levels' => Level::orderBy('level')->get()]); } // 添加商品 @@ -71,10 +62,9 @@ class ShopController extends Controller return $path; } } - $good = Goods::create($data); - if ($good) { - return Redirect::route('admin.goods.edit', $good->id)->with('successMsg', '添加成功'); + if ($good = Goods::create($data)) { + return Redirect::route('admin.goods.edit', $good)->with('successMsg', '添加成功'); } } catch (Exception $e) { Log::error('添加商品信息异常:'.$e->getMessage()); @@ -99,18 +89,17 @@ class ShopController extends Controller } // 编辑商品页面 - public function edit($id) + public function edit(Goods $good) { - $view['goods'] = Goods::find($id); - $view['levelList'] = Level::orderBy('level')->get(); - - return view('admin.shop.info', $view); + return view('admin.shop.info', [ + 'good' => $good, + 'levels' => Level::orderBy('level')->get(), + ]); } // 编辑商品 - public function update(ShopUpdateRequest $request, $id) + public function update(ShopUpdateRequest $request, Goods $good) { - $goods = Goods::findOrFail($id); $data = $request->except('_token', '_method', 'logo'); // 商品LOGO if ($request->hasFile('logo')) { @@ -126,7 +115,7 @@ class ShopController extends Controller $data['is_hot'] = $request->input('is_hot') ? 1 : 0; $data['status'] = $request->input('status') ? 1 : 0; - if ($goods->update($data)) { + if ($good->update($data)) { return Redirect::back()->with('successMsg', '编辑成功'); } } catch (Exception $e) { @@ -139,10 +128,10 @@ class ShopController extends Controller } // 删除商品 - public function destroy($id): JsonResponse + public function destroy(Goods $good): JsonResponse { try { - if (Goods::find($id)->delete()) { + if ($good->delete()) { return Response::json(['status' => 'success', 'message' => '删除成功']); } } catch (Exception $e) { diff --git a/app/Http/Controllers/Admin/SubscribeController.php b/app/Http/Controllers/Admin/SubscribeController.php index 93ba0d6d..122b6d08 100644 --- a/app/Http/Controllers/Admin/SubscribeController.php +++ b/app/Http/Controllers/Admin/SubscribeController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\UserSubscribe; use App\Models\UserSubscribeLog; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Response; @@ -39,13 +38,11 @@ class SubscribeController extends Controller $query->whereStatus($status); } - $view['subscribeList'] = $query->latest()->paginate(20)->appends($request->except('page')); - - return view('admin.subscribe.index', $view); + return view('admin.subscribe.index', ['subscribeList' => $query->latest()->paginate(20)->appends($request->except('page'))]); } //订阅记录 - public function subscribeLog(Request $request, $id) + public function subscribeLog($id) { $query = UserSubscribeLog::with('user:email'); @@ -53,19 +50,12 @@ class SubscribeController extends Controller $query->whereUserSubscribeId($id); } - $view['subscribeLog'] = $query->latest()->paginate(20)->appends($request->except('page')); - - return view('admin.subscribe.log', $view); + return view('admin.subscribe.log', ['subscribeLog' => $query->latest()->paginate(20)->appends(\request('page'))]); } // 设置用户的订阅的状态 - public function setSubscribeStatus(Request $request, $id): JsonResponse + public function setSubscribeStatus(UserSubscribe $subscribe) { - if (empty($id)) { - return Response::json(['status' => 'fail', 'message' => '操作异常']); - } - $subscribe = UserSubscribe::find($id); - if ($subscribe->status) { $subscribe->update(['status' => 0, 'ban_time' => time(), 'ban_desc' => '后台手动封禁']); } else { diff --git a/app/Http/Controllers/Admin/SystemController.php b/app/Http/Controllers/Admin/SystemController.php index 1ad373b9..9a85e73b 100644 --- a/app/Http/Controllers/Admin/SystemController.php +++ b/app/Http/Controllers/Admin/SystemController.php @@ -16,10 +16,7 @@ class SystemController extends Controller // 系统设置 public function index() { - $view = Config::pluck('value', 'name')->toArray(); - $view['labelList'] = Label::orderByDesc('sort')->orderBy('id')->get(); - - return view('admin.config.system', $view); + return view('admin.config.system', array_merge(['labelList' => Label::orderByDesc('sort')->orderBy('id')->get()], Config::pluck('value', 'name')->toArray())); } // 设置系统扩展信息,例如客服、统计代码 diff --git a/app/Http/Controllers/Admin/TicketController.php b/app/Http/Controllers/Admin/TicketController.php index d3ba249f..a7387b6e 100644 --- a/app/Http/Controllers/Admin/TicketController.php +++ b/app/Http/Controllers/Admin/TicketController.php @@ -3,12 +3,10 @@ namespace App\Http\Controllers\Admin; use App\Components\Helpers; -use App\Components\PushNotification; use App\Http\Controllers\Controller; use App\Mail\closeTicket; use App\Mail\replyTicket; use App\Models\Ticket; -use App\Models\TicketReply; use App\Models\User; use Auth; use Illuminate\Http\Request; @@ -27,7 +25,7 @@ class TicketController extends Controller { $email = $request->input('email'); - $query = Ticket::whereAdminId(Auth::id())->orwhere('admin_id', null); + $query = Ticket::whereAdminId(Auth::id())->orwhere('admin_id'); if (isset($email)) { $query->whereHas('user', static function ($q) use ($email) { @@ -35,9 +33,7 @@ class TicketController extends Controller }); } - $view['ticketList'] = $query->latest()->paginate(10)->appends($request->except('page')); - - return view('admin.ticket.index', $view); + return view('admin.ticket.index', ['ticketList' => $query->latest()->paginate(10)->appends($request->except('page'))]); } // 创建工单 @@ -76,28 +72,22 @@ class TicketController extends Controller } // 回复 - public function edit($id) + public function edit(Ticket $ticket) { - $view['ticket'] = Ticket::find($id); - $view['replyList'] = TicketReply::whereTicketId($id)->oldest()->get(); - - return view('admin.ticket.reply', $view); + return view('admin.ticket.reply', [ + 'ticket' => $ticket, + 'replyList' => $ticket->reply()->oldest()->get(), + ]); } // 回复工单 - public function update(Request $request, $id) + public function update(Request $request, Ticket $ticket) { $content = substr(str_replace(['atob', 'eval'], '', clean($request->input('content'))), 0, 300); - $obj = new TicketReply(); - $obj->ticket_id = $id; - $obj->admin_id = Auth::id(); - $obj->content = $content; - - if ($obj->save()) { + if ($ticket->reply()->create(['admin_id' => Auth::id(), 'content' => $content])) { // 将工单置为已回复 - $ticket = Ticket::with('user')->find($id); - Ticket::whereId($id)->update(['status' => 1]); + $ticket->update(['status' => 1]); $title = '工单回复提醒'; $content = '标题:'.$ticket->title.'
管理员回复:'.$content; @@ -113,10 +103,8 @@ class TicketController extends Controller } // 关闭工单 - public function destroy($id) + public function destroy(Ticket $ticket) { - $ticket = Ticket::with('user')->find($id); - if (! $ticket->close()) { return Response::json(['status' => 'fail', 'message' => '关闭失败']); } diff --git a/app/Http/Controllers/Admin/ToolsController.php b/app/Http/Controllers/Admin/ToolsController.php index 46a09631..8c97a47c 100644 --- a/app/Http/Controllers/Admin/ToolsController.php +++ b/app/Http/Controllers/Admin/ToolsController.php @@ -197,10 +197,7 @@ class ToolsController extends Controller } $logs = $this->tail($file, 10000); - if (false === $logs) { - $view['urlList'] = []; - } else { - $url = []; + if (false !== $logs) { foreach ($logs as $log) { if (str_contains($log, 'TCP connecting')) { continue; @@ -220,10 +217,8 @@ class ToolsController extends Controller } } } - - $view['urlList'] = array_unique($url); } - return view('admin.tools.analysis', $view); + return view('admin.tools.analysis', ['urlList' => array_unique($url ?? [])]); } } diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index 8290e58b..b00f6c3f 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -9,16 +9,15 @@ use App\Http\Requests\Admin\UserStoreRequest; use App\Http\Requests\Admin\UserUpdateRequest; use App\Models\Level; use App\Models\Node; +use App\Models\Order; use App\Models\User; use App\Models\UserGroup; use App\Models\UserHourlyDataFlow; use Auth; -use DB; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; -use Redirect; use Response; use Session; use Spatie\Permission\Models\Role; @@ -96,10 +95,16 @@ class UserController extends Controller } // 不活跃用户 - if ($request->input('unActive')) { + if ($request->has('unActive')) { $query->whereBetween('t', [1, strtotime('-'.sysConfig('expire_days').' days')])->whereEnable(1); } + // 不活跃用户 + if ($request->has('paying')) { + $payingUser = Order::whereStatus(2)->where('goods_id', '<>', 0)->whereIsExpire(0)->where('amount', '>', 0)->pluck('user_id')->unique(); + $query->whereIn('id', $payingUser); + } + // 1小时内流量异常用户 if ($flowAbnormal) { $query->whereIn('id', (new UserHourlyDataFlow)->trafficAbnormal()); @@ -119,14 +124,12 @@ class UserController extends Controller $roles = Role::all()->pluck('description', 'name'); } elseif (Auth::getUser()->hasPermissionTo('give roles')) { $roles = Auth::getUser()->roles(); - } else { - $roles = []; } return view('admin.user.info', [ 'levels' => Level::orderBy('level')->get(), 'userGroups' => UserGroup::orderBy('id')->get(), - 'roles' => $roles, + 'roles' => $roles ?? [], ]); } @@ -173,15 +176,13 @@ class UserController extends Controller $roles = Role::all()->pluck('description', 'name'); } elseif (Auth::getUser()->hasPermissionTo('give roles')) { $roles = Auth::getUser()->roles(); - } else { - $roles = []; } return view('admin.user.info', [ 'user' => $user->load('inviter:id,email'), 'levels' => Level::orderBy('level')->get(), 'userGroups' => UserGroup::orderBy('id')->get(), - 'roles' => $roles, + 'roles' => $roles ?? [], ]); } @@ -256,38 +257,26 @@ class UserController extends Controller } // 批量生成账号 - public function batchAddUsers(Request $request) + public function batchAddUsers() { + $preset = ['transfer_enable' => 1024 * GB, 'expired_at' => date('Y-m-d', strtotime('+365 days'))]; + try { - DB::beginTransaction(); - - for ($i = 0; $i < $request->input('amount', 1); $i++) { - $uid = Helpers::addUser(Str::random(8).'@auto.generate', Str::random(), 1024 * GB, 365); - - if ($uid) { - // 写入用户流量变动记录 - Helpers::addUserTrafficModifyLog($uid, null, 0, 1024 * GB, '后台批量生成用户'); - } + for ($i = 0; $i < (int) request('amount', 1); $i++) { + $user = factory(User::class)->create($preset); + // 写入用户流量变动记录 + Helpers::addUserTrafficModifyLog($user->id, null, 0, 1024 * GB, '后台批量生成用户'); } - DB::commit(); - return Response::json(['status' => 'success', 'message' => '批量生成账号成功']); } catch (Exception $e) { - DB::rollBack(); - return Response::json(['status' => 'fail', 'message' => '批量生成账号失败:'.$e->getMessage()]); } } // 转换成某个用户的身份 - public function switchToUser(Request $request): JsonResponse + public function switchToUser(User $user): JsonResponse { - $user = User::find($request->input('user_id')); - if (! $user) { - return Response::json(['status' => 'fail', 'message' => '用户不存在']); - } - // 存储当前管理员ID,并将当前登录信息改成要切换的用户的身份信息 Session::put('admin', Auth::id()); Session::put('user', $user->id); @@ -296,10 +285,10 @@ class UserController extends Controller } // 重置用户流量 - public function resetTraffic(Request $request): JsonResponse + public function resetTraffic(User $user): JsonResponse { try { - User::find($request->input('id'))->update(['u' => 0, 'd' => 0]); + $user->update(['u' => 0, 'd' => 0]); } catch (Exception $e) { Log::error('流量重置失败:'.$e->getMessage()); @@ -310,19 +299,17 @@ class UserController extends Controller } // 操作用户余额 - public function handleUserCredit(Request $request): JsonResponse + public function handleUserCredit(Request $request, User $user): JsonResponse { - $userId = $request->input('user_id'); - $amount = $request->input('amount'); + $amount = (int) $request->input('amount'); - if (empty($userId) || empty($amount)) { + if (empty($amount)) { return Response::json(['status' => 'fail', 'message' => '充值异常']); } - $user = User::find($userId); // 加减余额 if ($user->updateCredit($amount)) { - Helpers::addUserCreditLog($userId, null, $user->credit, $user->credit + $amount, $amount, '后台手动充值'); // 写入余额变动日志 + Helpers::addUserCreditLog($user->id, null, $user->credit, $user->credit + $amount, $amount, '后台手动充值'); // 写入余额变动日志 return Response::json(['status' => 'success', 'message' => '充值成功']); } @@ -331,19 +318,15 @@ class UserController extends Controller } // 导出配置信息 - public function export(Request $request, User $user) + public function export(User $user) { - if ($user === null) { - return Redirect::back(); - } - - $view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->orderBy('id')->paginate(15)->appends($request->except('page')); - $view['user'] = $user; - - return view('admin.user.export', $view); + return view('admin.user.export', [ + 'user' => $user, + 'nodeList' => Node::whereStatus(1)->orderByDesc('sort')->orderBy('id')->paginate(15)->appends(\request('page')), + ]); } - public function exportProxyConfig(Request $request, $uid): JsonResponse + public function exportProxyConfig(Request $request, User $user): JsonResponse { $node = Node::find($request->input('id')); if ($node->type === 1) { @@ -356,7 +339,7 @@ class UserController extends Controller $proxyType = 'V2Ray'; } - $data = $this->getUserNodeInfo($uid, $node->id, $request->input('type') !== 'text' ? 0 : 1); + $data = $this->getUserNodeInfo($user->id, $node->id, $request->input('type') !== 'text' ? 0 : 1); return Response::json(['status' => 'success', 'data' => $data, 'title' => $proxyType]); } diff --git a/app/Http/Controllers/Admin/UserGroupController.php b/app/Http/Controllers/Admin/UserGroupController.php index 5202acca..c883cc3d 100644 --- a/app/Http/Controllers/Admin/UserGroupController.php +++ b/app/Http/Controllers/Admin/UserGroupController.php @@ -3,92 +3,71 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\UserGroupRequest; use App\Models\Node; -use App\Models\User; use App\Models\UserGroup; use Exception; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\RedirectResponse; -use Illuminate\Http\Request; -use Redirect; -use Response; -use Validator; class UserGroupController extends Controller { - public function index(Request $request) + public function index() { - $view['list'] = UserGroup::paginate(15)->appends($request->except('page')); - - return view('admin.user.group.index', $view); + return view('admin.user.group.index', ['groups' => UserGroup::paginate(15)->appends(request('page'))]); } // 添加用户分组页面 public function create() { - $nodes = Node::whereStatus(1)->pluck('name', 'id'); - - return view('admin.user.group.info', compact('nodes')); + return view('admin.user.group.info', ['nodes' => Node::whereStatus(1)->pluck('name', 'id')]); } // 添加用户分组 - public function store(Request $request): RedirectResponse + public function store(UserGroupRequest $request) { - $validator = Validator::make($request->all(), ['name' => 'required']); + if ($userGroup = UserGroup::create($request->only(['name']))) { + $userGroup->nodes()->attach($request->input('nodes')); - if ($validator->fails()) { - return Redirect::back()->withInput()->withErrors($validator->errors()); + return redirect(route('admin.user.group.edit', $userGroup))->with('successMsg', '操作成功'); } - $userGroup = UserGroup::create(['name' => $request->input('name'), 'nodes' => $request->input('nodes')]); - - if ($userGroup) { - return Redirect::route('admin.user.group.edit', $userGroup)->with('successMsg', '操作成功'); - } - - return Redirect::back()->withInput()->withErrors('操作失败'); + return redirect()->back()->withInput()->withErrors('操作失败'); } // 编辑用户分组页面 public function edit(UserGroup $group) { - $nodes = Node::whereStatus(1)->pluck('name', 'id'); - - return view('admin.user.group.info', compact('group', 'nodes')); + return view('admin.user.group.info', [ + 'group' => $group, + 'nodes' => Node::whereStatus(1)->pluck('name', 'id'), + ]); } // 编辑用户分组 - public function update(Request $request, UserGroup $group) + public function update(UserGroupRequest $request, UserGroup $group) { - $validator = Validator::make($request->all(), ['name' => 'required']); + if ($group->update($request->only(['name']))) { + $group->nodes()->sync($request->input('nodes')); - if ($validator->fails()) { - return Redirect::back()->withInput()->withErrors($validator->errors()); + return redirect()->back()->with('successMsg', '操作成功'); } - $group->name = $request->input('name'); - $group->nodes = $request->input('nodes'); - if ($group->save()) { - return Redirect::back()->with('successMsg', '操作成功'); - } - - return Redirect::back()->withInput()->withErrors('操作失败'); + return redirect()->back()->withInput()->withErrors('操作失败'); } // 删除用户分组 - public function destroy(UserGroup $group): JsonResponse + public function destroy(UserGroup $group) { // 校验该分组下是否存在关联账号 - if (User::whereGroupId($group->id)->count()) { - return Response::json(['status' => 'fail', 'message' => '该分组下存在关联账号,请先取消关联!']); + if ($group->users->isNotEmpty()) { + return response()->json(['status' => 'fail', 'message' => '该分组下存在关联账号,请先取消关联!']); } try { $group->delete(); } catch (Exception $e) { - return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); + return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]); } - return Response::json(['status' => 'success', 'message' => '清理成功']); + return response()->json(['status' => 'success', 'message' => '清理成功']); } } diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 27fee618..32b1dfbe 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -2,7 +2,6 @@ namespace App\Http\Controllers; -use App\Components\Helpers; use App\Models\Country; use App\Models\Invite; use App\Models\Label; @@ -15,68 +14,56 @@ use App\Models\ReferralLog; use App\Models\SsConfig; use App\Models\User; use App\Models\UserHourlyDataFlow; -use Auth; -use Hash; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; use Log; use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; -use Redirect; use Response; use Str; -/** - * 管理员控制器. - * - * Class AdminController - */ class AdminController extends Controller { public function index() { $past = strtotime('-'.sysConfig('expire_days').' days'); - $view['expireDays'] = sysConfig('expire_days'); - $view['totalUserCount'] = User::count(); // 总用户数 - $view['todayRegister'] = User::whereDate('created_at', date('Y-m-d'))->count(); // 今日注册用户 - $view['enableUserCount'] = User::whereEnable(1)->count(); // 有效用户数 - $view['activeUserCount'] = User::where('t', '>=', $past)->count(); // 活跃用户数 - $view['unActiveUserCount'] = User::whereEnable(1)->whereBetween('t', [1, $past])->count(); // 不活跃用户数 - $view['onlineUserCount'] = User::where('t', '>=', strtotime('-10 minutes'))->count(); // 10分钟内在线用户数 - $view['expireWarningUserCount'] = User::whereBetween('expired_at', [date('Y-m-d'), date('Y-m-d', strtotime('+'.sysConfig('expire_days').' days'))])->count(); // 临近过期用户数 - $view['largeTrafficUserCount'] = User::whereRaw('(u + d)/transfer_enable >= 0.9')->where('status', '<>', -1)->count(); // 流量使用超过90%的用户 - $view['flowAbnormalUserCount'] = count((new UserHourlyDataFlow)->trafficAbnormal()); // 1小时内流量异常用户 - $view['nodeCount'] = Node::count(); - $view['unnormalNodeCount'] = Node::whereStatus(0)->count(); - $view['flowCount'] = flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d', strtotime('-30 days')))->sum('total')); - $view['todayFlowCount'] = flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d'))->sum('total')); - $view['totalFlowCount'] = flowAutoShow(NodeDailyDataFlow::sum('total')); - $view['totalCredit'] = User::where('credit', '<>', 0)->sum('credit') / 100; - $view['totalWaitRefAmount'] = ReferralLog::whereIn('status', [0, 1])->sum('commission') / 100; - $view['todayWaitRefAmount'] = ReferralLog::whereIn('status', [0, 1])->whereDate('created_at', date('Y-m-d'))->sum('commission') / 100; - $view['totalRefAmount'] = ReferralApply::whereStatus(2)->sum('amount') / 100; - $view['totalOrder'] = Order::count(); - $view['todayOrder'] = Order::whereDate('created_at', date('Y-m-d'))->count(); - $view['totalOnlinePayOrder'] = Order::where('pay_type', '<>', 0)->count(); - $view['todayOnlinePayOrder'] = Order::where('pay_type', '<>', 0)->whereDate('created_at', date('Y-m-d'))->count(); - $view['totalSuccessOrder'] = Order::whereStatus(2)->count(); - $view['todaySuccessOrder'] = Order::whereStatus(2)->whereDate('created_at', date('Y-m-d'))->count(); - - return view('admin.index', $view); + return view('admin.index', [ + 'expireDays' => sysConfig('expire_days'), + 'totalUserCount' => User::count(), // 总用户数 + 'todayRegister' => User::whereDate('created_at', date('Y-m-d'))->count(), // 今日注册用户 + 'enableUserCount' => User::whereEnable(1)->count(), // 有效用户数 + 'activeUserCount' => User::where('t', '>=', $past)->count(), // 活跃用户数, + 'payingUserCount' => Order::whereStatus(2)->where('goods_id', '<>', 0)->whereIsExpire(0)->where('amount', '>', 0)->pluck('user_id')->unique()->count(), // 付费用户数 + 'unActiveUserCount' => User::whereEnable(1)->whereBetween('t', [1, $past])->count(), // 不活跃用户数 + 'onlineUserCount' => User::where('t', '>=', strtotime('-10 minutes'))->count(), // 10分钟内在线用户数 + 'expireWarningUserCount' => User::whereBetween('expired_at', [date('Y-m-d'), date('Y-m-d', strtotime('+'.sysConfig('expire_days').' days'))])->count(), // 临近过期用户数 + 'largeTrafficUserCount' => User::whereRaw('(u + d)/transfer_enable >= 0.9')->where('status', '<>', -1)->count(), // 流量使用超过90%的用户 + 'flowAbnormalUserCount' => count((new UserHourlyDataFlow)->trafficAbnormal()), // 1小时内流量异常用户 + 'nodeCount' => Node::count(), + 'unnormalNodeCount' => Node::whereStatus(0)->count(), + 'flowCount' => flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d', strtotime('-30 days')))->sum('total')), + 'todayFlowCount' => flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d'))->sum('total')), + 'totalFlowCount' => flowAutoShow(NodeDailyDataFlow::sum('total')), + 'totalCredit' => User::where('credit', '<>', 0)->sum('credit') / 100, + 'totalWaitRefAmount' => ReferralLog::whereIn('status', [0, 1])->sum('commission') / 100, + 'todayWaitRefAmount' => ReferralLog::whereIn('status', [0, 1])->whereDate('created_at', date('Y-m-d'))->sum('commission') / 100, + 'totalRefAmount' => ReferralApply::whereStatus(2)->sum('amount') / 100, + 'totalOrder' => Order::count(), + 'todayOrder' => Order::whereDate('created_at', date('Y-m-d'))->count(), + 'totalOnlinePayOrder' => Order::where('pay_type', '<>', 0)->count(), + 'todayOnlinePayOrder' => Order::where('pay_type', '<>', 0)->whereDate('created_at', date('Y-m-d'))->count(), + 'totalSuccessOrder' => Order::whereStatus(2)->count(), + 'todaySuccessOrder' => Order::whereStatus(2)->whereDate('created_at', date('Y-m-d'))->count(), + ]); } // 邀请码列表 - public function inviteList(Request $request) + public function inviteList() { - $view['inviteList'] = Invite::with(['invitee:id,email', 'inviter:id,email']) - ->orderBy('status') - ->orderByDesc('id') - ->paginate(15) - ->appends($request->except('page')); - - return view('admin.inviteList', $view); + return view('admin.inviteList', [ + 'inviteList' => Invite::with(['invitee:id,email', 'inviter:id,email'])->orderBy('status')->orderByDesc('id')->paginate(15)->appends(request('page')), + ]); } // 生成邀请码 @@ -128,13 +115,13 @@ class AdminController extends Controller public function config() { - $view['methodList'] = SsConfig::type(1)->get(); - $view['protocolList'] = SsConfig::type(2)->get(); - $view['obfsList'] = SsConfig::type(3)->get(); - $view['countryList'] = Country::all(); - $view['levelList'] = Level::all(); - $view['labelList'] = Label::with('nodes')->get(); - - return view('admin.config.config', $view); + return view('admin.config.config', [ + 'methods' => SsConfig::type(1)->get(), + 'protocols' => SsConfig::type(2)->get(), + 'obfsList' => SsConfig::type(3)->get(), + 'countries' => Country::all(), + 'levels' => Level::all(), + 'labels' => Label::with('nodes')->get(), + ]); } } diff --git a/app/Http/Controllers/Api/Client/V1Controller.php b/app/Http/Controllers/Api/Client/V1Controller.php index 34125298..2431a2d0 100644 --- a/app/Http/Controllers/Api/Client/V1Controller.php +++ b/app/Http/Controllers/Api/Client/V1Controller.php @@ -84,7 +84,7 @@ class V1Controller extends Controller public function nodeList(int $id = null) { $user = auth()->user(); - $nodes = $user->userAccessNodes()->get(); + $nodes = $user->nodes()->get(); if (isset($id)) { $node = $nodes->where('id', $id)->first(); diff --git a/app/Http/Controllers/Api/WebApi/BaseController.php b/app/Http/Controllers/Api/WebApi/BaseController.php index 02e252e4..13646c41 100644 --- a/app/Http/Controllers/Api/WebApi/BaseController.php +++ b/app/Http/Controllers/Api/WebApi/BaseController.php @@ -5,11 +5,8 @@ namespace App\Http\Controllers\Api\WebApi; use App\Components\Helpers; use App\Models\Node; use App\Models\NodeHeartBeat; +use App\Models\NodeOnlineIp; use App\Models\NodeOnlineLog; -use App\Models\NodeOnlineUserIp; -use App\Models\Rule; -use App\Models\RuleGroup; -use App\Models\RuleGroupNode; use App\Models\RuleLog; use App\Models\User; use App\Models\UserDataFlowLog; @@ -74,7 +71,7 @@ class BaseController return $this->returnData('上报节点在线用户IP信息失败,请检查字段'); } - $obj = new NodeOnlineUserIp(); + $obj = new NodeOnlineIp(); $obj->node_id = $id; $obj->user_id = $input['uid']; $obj->ip = $input['ip']; @@ -137,27 +134,21 @@ class BaseController } // 获取节点的审计规则 - public function getNodeRule($id): JsonResponse + public function getNodeRule(Node $node): JsonResponse { - $nodeRule = RuleGroupNode::whereNodeId($id)->first(); $data = []; //节点未设置任何审计规则 - if ($nodeRule) { - $ruleGroup = RuleGroup::find($nodeRule->rule_group_id); - if ($ruleGroup && $ruleGroup->rules) { - foreach ($ruleGroup->rules as $ruleId) { - $rule = Rule::find($ruleId); - if ($rule) { - $data[] = [ - 'id' => $rule->id, - 'type' => $rule->type_api_label, - 'pattern' => $rule->pattern, - ]; - } - } - - return $this->returnData('获取节点审计规则成功', 'success', 200, ['mode' => $ruleGroup->type ? 'reject' : 'allow', 'rules' => $data]); + if ($node->rule_group_id) { + $ruleGroup = $node->ruleGroup; + foreach ($ruleGroup->rules as $rule) { + $data[] = [ + 'id' => $rule->id, + 'type' => $rule->type_api_label, + 'pattern' => $rule->pattern, + ]; } + + return $this->returnData('获取节点审计规则成功', 'success', 200, ['mode' => $ruleGroup->type ? 'reject' : 'allow', 'rules' => $data]); } //放行 @@ -173,9 +164,8 @@ class BaseController $obj->node_id = $id; $obj->rule_id = $request->input('rule_id'); $obj->reason = $request->input('reason'); - $obj->save(); - if ($obj->id) { + if ($obj->save()) { return $this->returnData('上报用户触发审计规则日志成功', 'success', 200); } } diff --git a/app/Http/Controllers/Api/WebApi/TrojanController.php b/app/Http/Controllers/Api/WebApi/TrojanController.php index 03c0056a..cbd5e3a5 100644 --- a/app/Http/Controllers/Api/WebApi/TrojanController.php +++ b/app/Http/Controllers/Api/WebApi/TrojanController.php @@ -8,10 +8,8 @@ use Illuminate\Http\JsonResponse; class TrojanController extends BaseController { // 获取节点信息 - public function getNodeInfo($id): JsonResponse + public function getNodeInfo(Node $node): JsonResponse { - $node = Node::find($id); - return $this->returnData('获取节点信息成功', 'success', 200, [ 'id' => $node->id, 'is_udp' => $node->is_udp ? true : false, @@ -26,12 +24,9 @@ class TrojanController extends BaseController } // 获取节点可用的用户列表 - public function getUserList($id): JsonResponse + public function getUserList(Node $node): JsonResponse { - $users = Node::find($id)->node_access_users; - $data = []; - - foreach ($users as $user) { + foreach ($node->users() as $user) { $data[] = [ 'uid' => $user->id, 'password' => $user->passwd, @@ -39,6 +34,6 @@ class TrojanController extends BaseController ]; } - return $this->returnData('获取用户列表成功', 'success', 200, $data, ['updateTime' => time()]); + return $this->returnData('获取用户列表成功', 'success', 200, $data ?? [], ['updateTime' => time()]); } } diff --git a/app/Http/Controllers/Api/WebApi/V2RayController.php b/app/Http/Controllers/Api/WebApi/V2RayController.php index 43ae8e5a..e8c6a68c 100644 --- a/app/Http/Controllers/Api/WebApi/V2RayController.php +++ b/app/Http/Controllers/Api/WebApi/V2RayController.php @@ -5,15 +5,13 @@ namespace App\Http\Controllers\Api\WebApi; use App\Models\Node; use App\Models\NodeCertificate; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; class V2RayController extends BaseController { // 获取节点信息 - public function getNodeInfo($id): JsonResponse + public function getNodeInfo(Node $node): JsonResponse { - $node = Node::find($id); - $nodeDv = NodeCertificate::whereDomain($node->v2_host)->first(); + $cert = NodeCertificate::whereDomain($node->v2_host)->first(); $tlsProvider = $node->tls_provider ?: sysConfig('v2ray_tls_provider'); if (! $tlsProvider) { $tlsProvider = null; @@ -27,8 +25,8 @@ class V2RayController extends BaseController 'push_port' => $node->push_port, 'redirect_url' => (string) sysConfig('redirect_url'), 'secret' => $node->auth->secret, - 'key' => $nodeDv->key ?? '', - 'pem' => $nodeDv->pem ?? '', + 'key' => $cert->key ?? '', + 'pem' => $cert->pem ?? '', 'v2_license' => (string) sysConfig('v2ray_license'), 'v2_alter_id' => $node->v2_alter_id, 'v2_port' => $node->v2_port, @@ -43,12 +41,9 @@ class V2RayController extends BaseController } // 获取节点可用的用户列表 - public function getUserList($id): JsonResponse + public function getUserList(Node $node): JsonResponse { - $users = Node::find($id)->node_access_users; - $data = []; - - foreach ($users as $user) { + foreach ($node->users() as $user) { $data[] = [ 'uid' => $user->id, 'vmess_uid' => $user->vmess_id, @@ -56,29 +51,15 @@ class V2RayController extends BaseController ]; } - return $this->returnData('获取用户列表成功', 'success', 200, $data, ['updateTime' => time()]); + return $this->returnData('获取用户列表成功', 'success', 200, $data ?? [], ['updateTime' => time()]); } // 上报节点伪装域名证书信息 - public function addCertificate(Request $request, $id): JsonResponse + public function addCertificate(Node $node): JsonResponse { - $key = $request->input('key'); - $pem = $request->input('pem'); - - if ($request->has(['key', 'pem'])) { - $node = Node::find($id); - $Dv = NodeCertificate::whereDomain($node->v2_host)->first(); - if ($Dv) { - $ret = NodeCertificate::whereId($Dv->id)->update(['key' => $key, 'pem' => $pem]); - } else { - $ret = new NodeCertificate(); - $ret->domain = $node->server; - $ret->key = $request->input('key'); - $ret->pem = $request->input('pem'); - $ret->save(); - } - - if ($ret) { + if (request()->has(['key', 'pem'])) { + $cert = NodeCertificate::whereDomain($node->v2_host)->firstOrCreate(['domain' => $node->server]); + if ($cert && $cert->update(['key' => request('key'), 'pem' => request('pem')])) { return $this->returnData('上报节点伪装域名证书成功', 'success', 200); } } diff --git a/app/Http/Controllers/Api/WebApi/VNetController.php b/app/Http/Controllers/Api/WebApi/VNetController.php index 809bd273..0d877760 100644 --- a/app/Http/Controllers/Api/WebApi/VNetController.php +++ b/app/Http/Controllers/Api/WebApi/VNetController.php @@ -8,10 +8,8 @@ use Illuminate\Http\JsonResponse; class VNetController extends BaseController { // 获取节点信息 - public function getNodeInfo($id): JsonResponse + public function getNodeInfo(Node $node): JsonResponse { - $node = Node::find($id); - return $this->returnData('获取节点信息成功', 'success', 200, [ 'id' => $node->id, 'method' => $node->method, @@ -31,13 +29,9 @@ class VNetController extends BaseController } // 获取节点可用的用户列表 - public function getUserList($id): JsonResponse + public function getUserList(Node $node): JsonResponse { - $node = Node::find($id); - $users = $node->node_access_users; - $data = []; - - foreach ($users as $user) { + foreach ($node->users() as $user) { $data[] = [ 'uid' => $user->id, 'port' => $user->port, @@ -51,7 +45,7 @@ class VNetController extends BaseController ]; } - if ($data) { + if (isset($data)) { return $this->returnData('获取用户列表成功', 'success', 200, $data, ['updateTime' => time()]); } diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 23c51559..824cfa2d 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -51,10 +51,6 @@ class AuthController extends Controller return Redirect::back()->withInput()->withErrors($validator->errors()); } - $email = $request->input('email'); - $password = $request->input('password'); - $remember = $request->input('remember'); - // 是否校验验证码 $captcha = $this->check_captcha($request); if ($captcha !== false) { @@ -62,7 +58,7 @@ class AuthController extends Controller } // 验证账号并创建会话 - if (! Auth::attempt(['email' => $email, 'password' => $password], $remember)) { + if (! Auth::attempt($validator->validated(), $request->input('remember'))) { return Redirect::back()->withInput()->withErrors(trans('auth.login_error')); } $user = Auth::getUser(); @@ -81,23 +77,17 @@ class AuthController extends Controller if ($user->status === 0 && sysConfig('is_activate_account')) { Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话 - return Redirect::back()->withInput()->withErrors(trans('auth.active_tip').'【'.trans('auth.active_account').'】'); + return Redirect::back()->withInput()->withErrors(trans('auth.active_tip').'【'.trans('auth.active_account').'】'); } // 写入登录日志 $this->addUserLoginLog($user->id, IP::getClientIp()); // 更新登录信息 - Auth::getUser()->update(['last_login' => time()]); - - // 根据权限跳转 - if ($user->hasPermissionTo('admin.index')) { - return Redirect::route('admin.index'); - } - - return Redirect::route('home'); + $user->update(['last_login' => time()]); } + // 根据权限跳转 if (Auth::check()) { if (Auth::getUser()->hasPermissionTo('admin.index')) { return Redirect::route('admin.index'); @@ -110,7 +100,7 @@ class AuthController extends Controller } // 校验验证码 - private function check_captcha($request) + private function check_captcha(Request $request) { switch (sysConfig('is_captcha')) { case 1: // 默认图形验证码 @@ -298,14 +288,14 @@ class AuthController extends Controller $transfer_enable = MB * ((int) sysConfig('default_traffic') + ($inviter_id ? (int) sysConfig('referral_traffic') : 0)); // 创建新用户 - $uid = Helpers::addUser($email, $password, $transfer_enable, sysConfig('default_days'), $inviter_id); + $user = factory(User::class)->create([ + 'username' => $username, 'email' => $email, 'password' => $password, 'transfer_enable' => $transfer_enable, 'inviter_id' => $inviter_id, + ]); // 注册失败,抛出异常 - if (! $uid) { + if (! $user) { return Redirect::back()->withInput()->withErrors(trans('auth.register_fail')); } - // 更新昵称 - User::find($uid)->update(['username' => $username]); // 注册次数+1 if (Cache::has($cacheKey)) { @@ -316,16 +306,16 @@ class AuthController extends Controller // 更新邀请码 if ($affArr['code_id'] && sysConfig('is_invite_register')) { - Invite::find($affArr['code_id'])->update(['invitee_id' => $uid, 'status' => 1]); + Invite::find($affArr['code_id'])->update(['invitee_id' => $user->id, 'status' => 1]); } // 清除邀请人Cookie Cookie::unqueue('register_aff'); // 注册后发送激活码 - if (sysConfig('is_activate_account') == 2) { + if ((int) sysConfig('is_activate_account') === 2) { // 生成激活账号的地址 - $token = $this->addVerifyUrl($uid, $email); + $token = $this->addVerifyUrl($user->id, $email); $activeUserUrl = route('activeAccount', $token); $logId = Helpers::addNotificationLog('注册激活', '请求地址:'.$activeUserUrl, 1, $email); @@ -341,8 +331,8 @@ class AuthController extends Controller } } - if (sysConfig('is_activate_account') == 1) { - User::find($uid)->update(['status' => 1]); + if ((int) sysConfig('is_activate_account') === 1) { + $user->update(['status' => 1]); } Session::flash('successMsg', trans('auth.register_success')); @@ -351,10 +341,9 @@ class AuthController extends Controller return Redirect::route('login')->withInput(); } - $view['emailList'] = sysConfig('is_email_filtering') != 2 ? false : EmailFilter::whereType(2)->get(); Session::put('register_token', Str::random()); - return view('auth.register', $view); + return view('auth.register', ['emailList' => (int) sysConfig('is_email_filtering') !== 2 ? false : EmailFilter::whereType(2)->get()]); } //邮箱检查 @@ -562,10 +551,7 @@ class AuthController extends Controller $verify->save(); } - // 重新获取一遍verify - $view['verify'] = Verify::type(1)->whereToken($token)->first(); - - return view('auth.reset', $view); + return view('auth.reset', ['verify' => Verify::type(1)->whereToken($token)->first()]); // 重新获取一遍verify } // 激活账号页 @@ -744,13 +730,11 @@ class AuthController extends Controller // 公开的邀请码列表 public function free() { - $view['inviteList'] = Invite::whereInviterId(null)->whereStatus(0)->paginate(); - - return view('auth.free', $view); + return view('auth.free', ['inviteList' => Invite::whereInviterId(null)->whereStatus(0)->paginate()]); } // 切换语言 - public function switchLang($locale): RedirectResponse + public function switchLang(string $locale): RedirectResponse { Session::put('locale', $locale); diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index a8fa4a15..54f90f9c 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -95,7 +95,6 @@ class PaymentController extends Controller $pay_type = $request->input('pay_type'); $amount = 0; - $goods = Goods::find($goods_id); // 充值余额 if ($credit) { if (! is_numeric($credit) || $credit <= 0) { @@ -104,6 +103,7 @@ class PaymentController extends Controller $amount = $credit; // 购买服务 } elseif ($goods_id && self::$method) { + $goods = Goods::find($goods_id); if (! $goods || ! $goods->status) { return Response::json(['status' => 'fail', 'message' => '订单创建失败:商品已下架']); } @@ -140,7 +140,7 @@ class PaymentController extends Controller } } - // 使用优惠券 TODO 代码整合至 CouponService + // 使用优惠券 if ($coupon_sn) { $coupon = Coupon::whereStatus(0)->whereIn('type', [1, 2])->whereSn($coupon_sn)->first(); if (! $coupon) { @@ -162,31 +162,29 @@ class PaymentController extends Controller } } - $orderSn = date('ymdHis').random_int(100000, 999999); - // 生成订单 try { - $order = new Order(); - $order->order_sn = $orderSn; - $order->user_id = Auth::id(); - $order->goods_id = $credit ? 0 : $goods_id; - $order->coupon_id = $coupon->id ?? 0; - $order->origin_amount = $credit ?: $goods->price; - $order->amount = $amount; - $order->pay_type = $pay_type; - $order->pay_way = self::$method; - $order->save(); + $newOrder = Order::create([ + 'order_sn' => date('ymdHis').random_int(100000, 999999), + 'user_id' => auth()->id(), + 'goods_id' => $credit ? null : $goods_id, + 'coupon_id' => $coupon->id ?? null, + 'origin_amount' => $credit ?: $goods->price ?? 0, + 'amount'=>$amount, + 'pay_type'=>$pay_type, + 'pay_way'=>self::$method, + ]); // 使用优惠券,减少可使用次数 if (! empty($coupon)) { if ($coupon->usable_times > 0) { - Coupon::whereId($coupon->id)->decrement('usable_times', 1); + $coupon->decrement('usable_times', 1); } - Helpers::addCouponLog('订单支付使用', $coupon->id, $goods_id, $order->id); + Helpers::addCouponLog('订单支付使用', $coupon->id, $goods_id, $newOrder->id); } - $request->merge(['id' => $order->id, 'type' => $pay_type, 'amount' => $amount]); + $request->merge(['id' => $newOrder->id, 'type' => $pay_type, 'amount' => $amount]); // 生成支付单 return self::getClient()->purchase($request); @@ -197,15 +195,10 @@ class PaymentController extends Controller return Response::json(['status' => 'fail', 'message' => '订单创建失败']); } - public function close(Request $request): JsonResponse + public function close(Order $order): JsonResponse { - $order = Order::find($request->input('id')); - if ($order) { - if (! $order->update(['status' => -1])) { - return Response::json(['status' => 'fail', 'message' => '关闭订单失败']); - } - } else { - return Response::json(['status' => 'fail', 'message' => '未找到订单']); + if (! $order->update(['status' => -1])) { + return Response::json(['status' => 'fail', 'message' => '关闭订单失败']); } return Response::json(['status' => 'success', 'message' => '关闭订单成功']); @@ -215,13 +208,14 @@ class PaymentController extends Controller public function detail($trade_no) { $payment = Payment::uid()->with(['order', 'order.goods'])->whereTradeNo($trade_no)->firstOrFail(); - $view['payment'] = $payment; $goods = $payment->order->goods; - $view['name'] = $goods->name ?? '余额充值'; - $view['days'] = $goods->days ?? 0; - $view['pay_type'] = $payment->order->pay_type_label ?: 0; - $view['pay_type_icon'] = $payment->order->pay_type_icon; - return view('user.payment', $view); + return view('user.payment', [ + 'payment' => $payment, + 'name' => $goods->name ?? '余额充值', + 'days' => $goods->days ?? 0, + 'pay_type' => $payment->order->pay_type_label ?: 0, + 'pay_type_icon' => $payment->order->pay_type_icon, + ]); } } diff --git a/app/Http/Controllers/User/AffiliateController.php b/app/Http/Controllers/User/AffiliateController.php index 5809c58a..7a61bc85 100644 --- a/app/Http/Controllers/User/AffiliateController.php +++ b/app/Http/Controllers/User/AffiliateController.php @@ -18,17 +18,18 @@ class AffiliateController extends Controller if (ReferralLog::uid()->doesntExist() && Order::uid()->whereStatus(2)->doesntExist()) { return Response::view('auth.error', ['message' => '本功能对非付费用户禁用!请 返 回'], 402); } - $view['referral_traffic'] = flowAutoShow(sysConfig('referral_traffic') * MB); - $view['referral_percent'] = sysConfig('referral_percent'); - $view['referral_money'] = sysConfig('referral_money'); - $view['totalAmount'] = ReferralLog::uid()->sum('commission') / 100; - $view['canAmount'] = ReferralLog::uid()->whereStatus(0)->sum('commission') / 100; - $view['aff_link'] = route('register', ['aff' => Auth::id()]); - $view['referralLogList'] = ReferralLog::uid()->with('invitee:id,email')->latest()->paginate(10, ['*'], 'log_page'); - $view['referralApplyList'] = ReferralApply::uid()->latest()->paginate(10, ['*'], 'apply_page'); - $view['referralUserList'] = Auth::getUser()->invitees()->select(['email', 'created_at'])->latest()->paginate(10, ['*'], 'user_page'); - return view('user.referral', $view); + return view('user.referral', [ + 'referral_traffic' => flowAutoShow(sysConfig('referral_traffic') * MB), + 'referral_percent' => sysConfig('referral_percent'), + 'referral_money' => sysConfig('referral_money'), + 'totalAmount' => ReferralLog::uid()->sum('commission') / 100, + 'canAmount' => ReferralLog::uid()->whereStatus(0)->sum('commission') / 100, + 'aff_link' => route('register', ['aff' => Auth::id()]), + 'referralLogList' => ReferralLog::uid()->with('invitee:id,email')->latest()->paginate(10, ['*'], 'log_page'), + 'referralApplyList' => ReferralApply::uid()->latest()->paginate(10, ['*'], 'apply_page'), + 'referralUserList' => Auth::getUser()->invitees()->select(['email', 'created_at'])->latest()->paginate(10, ['*'], 'user_page'), + ]); } // 申请提现 diff --git a/app/Http/Controllers/User/SubscribeController.php b/app/Http/Controllers/User/SubscribeController.php index 2b859db4..7b5c1b54 100644 --- a/app/Http/Controllers/User/SubscribeController.php +++ b/app/Http/Controllers/User/SubscribeController.php @@ -77,7 +77,7 @@ class SubscribeController extends Controller $this->subscribeLog($subscribe->id, IP::getClientIp(), $request->headers); // 获取这个账号可用节点 - $query = $user->whereIsSubscribe(1)->userAccessNodes(); + $query = $user->whereIsSubscribe(1)->nodes(); if ($this->subType === 1) { $query = $query->whereIn('type', [1, 4]); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 52094dfb..426982e0 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -16,9 +16,6 @@ use App\Models\NodePing; use App\Models\Order; use App\Models\Ticket; use App\Models\TicketReply; -use App\Models\UserLoginLog; -use App\Models\UserSubscribe; -use Auth; use Cache; use DB; use Exception; @@ -34,38 +31,22 @@ use Session; use Str; use Validator; -/** - * 用户控制器. - * - * Class UserController - */ class UserController extends Controller { public function index() { + // 用户转换 if (Session::has('user')) { - Auth::loginUsingId(Session::get('user')); + auth()->loginUsingId(Session::get('user')); Session::forget('user'); } - $user = Auth::getUser(); + $user = auth()->user(); $totalTransfer = $user->transfer_enable; $usedTransfer = $user->usedTraffic(); $unusedTraffic = $totalTransfer - $usedTransfer > 0 ? $totalTransfer - $usedTransfer : 0; $expireTime = $user->expired_at; - $view['remainDays'] = $expireTime < date('Y-m-d') ? -1 : Helpers::daysToNow($expireTime); - $view['resetDays'] = $user->reset_time ? Helpers::daysToNow($user->reset_time) : 0; - $view['unusedTraffic'] = flowAutoShow($unusedTraffic); - $view['expireTime'] = $expireTime; - $view['banedTime'] = $user->ban_time ?: 0; - $view['unusedPercent'] = $totalTransfer > 0 ? round($unusedTraffic / $totalTransfer, 2) * 100 : 0; - $view['announcements'] = Article::type(2)->take(5)->latest()->Paginate(1); // 公告 - //流量异常判断 - $view['isTrafficWarning'] = $user->isTrafficWarning(); - //付费用户判断 - $view['paying_user'] = $user->activePayingUser(); - $view['userLoginLog'] = UserLoginLog::whereUserId($user->id)->latest()->first(); // 近期登录日志 - $nodes = $user->userAccessNodes()->get(); + $nodes = $user->nodes()->get(); $subType = []; if ($nodes->whereIn('type', [1, 4])->isNotEmpty()) { $subType[] = 'ss'; @@ -77,18 +58,27 @@ class UserController extends Controller $subType[] = 'trojan'; } - $view['subscribe_status'] = $user->subscribe->status; - $view['subType'] = $subType; - $view['subUrl'] = route('sub', $user->subscribe->code); - $view = array_merge($view, $this->dataFlowChart($user->id)); - - return view('user.index', $view); + return view('user.index', array_merge([ + 'remainDays' => $expireTime < date('Y-m-d') ? -1 : Helpers::daysToNow($expireTime), + 'resetDays' => $user->reset_time ? Helpers::daysToNow($user->reset_time) : 0, + 'unusedTraffic' => flowAutoShow($unusedTraffic), + 'expireTime' => $expireTime, + 'banedTime' => $user->ban_time ?: 0, + 'unusedPercent' => $totalTransfer > 0 ? round($unusedTraffic / $totalTransfer, 2) * 100 : 0, + 'announcements' => Article::type(2)->take(5)->latest()->Paginate(1), // 公告 + 'isTrafficWarning' => $user->isTrafficWarning(), // 流量异常判断 + 'paying_user' => $user->activePayingUser(), // 付费用户判断 + 'userLoginLog' => $user->loginLogs()->latest()->first(), // 近期登录日志 + 'subscribe_status' => $user->subscribe->status, + 'subType' => $subType, + 'subUrl' => route('sub', $user->subscribe->code), + ], $this->dataFlowChart($user->id))); } // 签到 public function checkIn(): JsonResponse { - $user = Auth::getUser(); + $user = auth()->user(); // 系统开启登录加积分功能才可以签到 if (! sysConfig('is_checkin')) { return Response::json(['status' => 'fail', 'message' => '系统未开启签到功能']); @@ -118,7 +108,7 @@ class UserController extends Controller // 节点列表 public function nodeList(Request $request) { - $user = Auth::getUser(); + $user = auth()->user(); if ($request->isMethod('POST')) { $infoType = $request->input('type'); @@ -135,9 +125,7 @@ class UserController extends Controller } // 获取当前用户可用节点 - $nodeList = $user->userAccessNodes()->with(['labels', 'level_table'])->get(); - - $view['nodesGeo'] = $nodeList->pluck('name', 'geo')->toArray(); + $nodeList = $user->nodes()->with(['labels', 'level_table'])->get(); $onlineNode = NodeHeartBeat::recently()->distinct()->pluck('node_id')->toArray(); $pingNodeLogs = NodePing::whereMonth('created_at', date('m'))->get(['node_id', 'ct', 'cu', 'cm', 'hk']); foreach ($nodeList as $node) { @@ -150,23 +138,23 @@ class UserController extends Controller // 节点在线状态 $node->offline = ! in_array($node->id, $onlineNode, true); } - $view['nodeList'] = $nodeList ?? []; - return view('user.nodeList', $view); + return view('user.nodeList', [ + 'nodesGeo' => $nodeList->pluck('name', 'geo')->toArray(), + 'nodeList' => $nodeList, + ]); } // 公告详情 - public function article(Request $request) + public function article(Article $article) { - $view['info'] = Article::findOrFail($request->input('id')); - - return view('user.article', $view); + return view('user.article', compact($article)); } // 修改个人资料 public function profile(Request $request) { - $user = Auth::getUser(); + $user = auth()->user(); if ($request->isMethod('POST')) { $old_password = $request->input('old_password'); $new_password = $request->input('new_password'); @@ -224,30 +212,26 @@ class UserController extends Controller // 商品列表 public function services(Request $request) { - $user = Auth::getUser(); + $user = auth()->user(); // 余额充值商品,只取10个 - $view['chargeGoodsList'] = Goods::type(3)->whereStatus(1)->orderBy('price')->limit(10)->get(); - $view['goodsList'] = Goods::whereStatus(1) - ->where('type', '<=', '2') - ->orderByDesc('type') - ->orderByDesc('sort') - ->paginate(10) - ->appends($request->except('page')); $renewOrder = Order::userActivePlan($user->id)->first(); $renewPrice = $renewOrder->goods ?? 0; - $view['renewTraffic'] = $renewPrice->renew ?? 0; // 有重置日时按照重置日为标准,否者就以过期日为标准 $dataPlusDays = $user->reset_time ?? $user->expired_at; - $view['dataPlusDays'] = $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0; - return view('user.services', $view); + return view('user.services', [ + 'chargeGoodsList' => Goods::type(3)->whereStatus(1)->orderBy('price')->limit(10)->get(), + 'goodsList' => Goods::whereStatus(1)->where('type', '<=', '2')->orderByDesc('type')->orderByDesc('sort')->paginate(10)->appends($request->except('page')), + 'renewTraffic' => $renewPrice->renew ?? 0, + 'dataPlusDays' => $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0, + ]); } //重置流量 public function resetUserTraffic(): ?JsonResponse { - $user = Auth::getUser(); - $order = Order::userActivePlan()->first(); + $user = auth()->user(); + $order = Order::userActivePlan()->firstOrFail(); $renewCost = $order->goods->renew; if ($user->credit < $renewCost) { return Response::json(['status' => 'fail', 'message' => '余额不足,请充值余额']); @@ -268,26 +252,22 @@ class UserController extends Controller public function ticketList(Request $request) { return view('user.ticketList', [ - 'tickets' => Auth::user()->tickets()->latest()->paginate(10)->appends($request->except('page')), + 'tickets' => auth()->user()->tickets()->latest()->paginate(10)->appends($request->except('page')), ]); } // 订单 public function invoices(Request $request) { - $view['orderList'] = Auth::user()->orders() - ->with(['goods', 'payment']) - ->orderByDesc('id') - ->paginate(10) - ->appends($request->except('page')); - $view['prepaidPlan'] = Order::userPrepay()->exists(); - - return view('user.invoices', $view); + return view('user.invoices', [ + 'orderList' => auth()->user()->orders()->with(['goods', 'payment'])->orderByDesc('id')->paginate(10)->appends($request->except('page')), + 'prepaidPlan' => Order::userPrepay()->exists(), + ]); } public function closePlan(): JsonResponse { - $activePlan = Order::userActivePlan()->first(); + $activePlan = Order::userActivePlan()->firstOrFail(); $activePlan->is_expire = 1; if ($activePlan->save()) { @@ -305,15 +285,13 @@ class UserController extends Controller // 订单明细 public function invoiceDetail($sn) { - $view['order'] = Order::uid()->whereOrderSn($sn)->with(['goods', 'coupon', 'payment'])->firstOrFail(); - - return view('user.invoiceDetail', $view); + return view('user.invoiceDetail', ['order' => Order::uid()->whereOrderSn($sn)->with(['goods', 'coupon', 'payment'])->firstOrFail()]); } // 添加工单 public function createTicket(Request $request): ?JsonResponse { - $user = Auth::getUser(); + $user = auth()->user(); $title = $request->input('title'); $content = clean($request->input('content')); $content = str_replace(['atob', 'eval'], '', $content); @@ -367,7 +345,7 @@ class UserController extends Controller $obj = new TicketReply(); $obj->ticket_id = $id; - $obj->user_id = Auth::id(); + $obj->user_id = auth()->user()->id; $obj->content = $content; if ($obj->save()) { @@ -392,10 +370,10 @@ class UserController extends Controller return Response::json(['status' => 'fail', 'message' => '回复失败']); } - $view['ticket'] = $ticket; - $view['replyList'] = TicketReply::whereTicketId($id)->with('user')->oldest()->get(); - - return view('user.replyTicket', $view); + return view('user.replyTicket', [ + 'ticket' => $ticket, + 'replyList' => $ticket->reply()->with('user')->oldest()->get(), + ]); } // 关闭工单 @@ -423,18 +401,18 @@ class UserController extends Controller ); } - $view['num'] = Auth::getUser()->invite_num; // 还可以生成的邀请码数量 - $view['inviteList'] = Invite::uid()->with(['invitee', 'inviter'])->paginate(10); // 邀请码列表 - $view['referral_traffic'] = flowAutoShow(sysConfig('referral_traffic') * MB); - $view['referral_percent'] = sysConfig('referral_percent'); - - return view('user.invite', $view); + return view('user.invite', [ + 'num' => auth()->user()->invite_num, // 还可以生成的邀请码数量 + 'inviteList' => Invite::uid()->with(['invitee', 'inviter'])->paginate(10), // 邀请码列表 + 'referral_traffic' => flowAutoShow(sysConfig('referral_traffic') * MB), + 'referral_percent' => sysConfig('referral_percent'), + ]); } // 生成邀请码 public function makeInvite(): JsonResponse { - $user = Auth::getUser(); + $user = auth()->user(); if ($user->invite_num <= 0) { return Response::json(['status' => 'fail', 'message' => '生成失败:已无邀请码生成名额']); } @@ -483,7 +461,7 @@ class UserController extends Controller return Response::json(['status' => 'fail', 'title' => '抱歉', 'message' => '优惠券已失效!']); } - if ($coupon->start_time > time()) { + if ($coupon->start_time > date('Y-m-d H:i:s')) { return Response::json(['status' => 'fail', 'title' => '优惠券尚未生效', 'message' => '请等待活动正式开启']); } @@ -501,20 +479,17 @@ class UserController extends Controller } // 购买服务 - public function buy($goods_id) + public function buy(Goods $good) { - $user = Auth::getUser(); - $goods = Goods::whereId($goods_id)->whereStatus(1)->first(); - if (empty($goods)) { - return Redirect::route('shop'); - } + $user = auth()->user(); // 有重置日时按照重置日为标准,否者就以过期日为标准 $dataPlusDays = $user->reset_time ?? $user->expired_at; - $view['dataPlusDays'] = $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0; - $view['activePlan'] = Order::userActivePlan()->exists(); - $view['goods'] = $goods; - return view('user.buy', $view); + return view('user.buy', [ + 'dataPlusDays' => $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0, + 'activePlan' => Order::userActivePlan()->exists(), + 'goods' => $good, + ]); } // 帮助中心 @@ -533,25 +508,22 @@ class UserController extends Controller $data[] = 'trojan'; } - $view['sub'] = $data; - - //付费用户判断 - $view['paying_user'] = Auth::user()->activePayingUser(); - //客户端安装 - $view['Shadowrocket_install'] = 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Shadowrocket.plist'; - $view['Quantumult_install'] = 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Quantumult.plist'; - // 订阅连接 - $subscribe = UserSubscribe::whereUserId(Auth::id())->firstOrFail(); - $view['subscribe_status'] = $subscribe->status; + $subscribe = auth()->user()->subscribe; $subscribe_link = route('sub', $subscribe->code); - $view['link'] = $subscribe_link; - $view['subscribe_link'] = 'sub://'.base64url_encode($subscribe_link); - $view['Shadowrocket_link'] = 'shadowrocket://add/sub://'.base64url_encode($subscribe_link).'?remarks='.(sysConfig('website_name').'-'.sysConfig('website_url')); - $view['Shadowrocket_linkQrcode'] = 'sub://'.base64url_encode($subscribe_link).'#'.base64url_encode(sysConfig('website_name')); - $view['Quantumult_linkOut'] = 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Pro.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf'); - $view['Quantumult_linkIn'] = 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/BacktoCN.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf'); - return view('user.help', $view); + return view('user.help', [ + 'sub' => $data, + 'paying_user' => auth()->user()->activePayingUser(), // 付费用户判断 + 'Shadowrocket_install' => 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Shadowrocket.plist', // 客户端安装 + 'Quantumult_install' => 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Quantumult.plist', // 客户端安装 + 'subscribe_status' => $subscribe->status, // 订阅连接 + 'link' => $subscribe_link, + 'subscribe_link' => 'sub://'.base64url_encode($subscribe_link), + 'Shadowrocket_link' => 'shadowrocket://add/sub://'.base64url_encode($subscribe_link).'?remarks='.(sysConfig('website_name').'-'.sysConfig('website_url')), + 'Shadowrocket_linkQrcode' => 'sub://'.base64url_encode($subscribe_link).'#'.base64url_encode(sysConfig('website_name')), + 'Quantumult_linkOut' => 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Pro.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf'), + 'Quantumult_linkIn' => 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/BacktoCN.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf'), + ]); } // 更换订阅地址 @@ -561,10 +533,10 @@ class UserController extends Controller DB::beginTransaction(); // 更换订阅码 - Auth::getUser()->subscribe->update(['code' => Helpers::makeSubscribeCode()]); + auth()->user()->subscribe->update(['code' => Helpers::makeSubscribeCode()]); // 更换连接信息 - Auth::getUser()->update(['passwd' => Str::random(), 'vmess_id' => Str::uuid()]); + auth()->user()->update(['passwd' => Str::random(), 'vmess_id' => Str::uuid()]); DB::commit(); @@ -586,7 +558,7 @@ class UserController extends Controller } // 管理员信息重新写入user - $user = Auth::loginUsingId(Session::get('admin')); + $user = auth()->loginUsingId(Session::get('admin')); Session::forget('admin'); if ($user) { return Response::json(['status' => 'success', 'message' => '身份切换成功']); @@ -615,14 +587,14 @@ class UserController extends Controller try { DB::beginTransaction(); // 写入日志 - $user = Auth::getUser(); + $user = auth()->user(); Helpers::addUserCreditLog($user->id, null, $user->credit, $user->credit + $coupon->value, $coupon->value, '用户手动充值 - [充值券:'.$request->input('coupon_sn').']'); // 余额充值 $user->updateCredit($coupon->value); // 更改卡券状态 - Coupon::find($coupon->id)->update(['status' => 1]); + $coupon->update(['status' => 1]); // 写入卡券日志 Helpers::addCouponLog('账户余额充值使用', $coupon->id); diff --git a/app/Http/Requests/Admin/ArticleRequest.php b/app/Http/Requests/Admin/ArticleRequest.php index 8fcd53f8..2acb1553 100644 --- a/app/Http/Requests/Admin/ArticleRequest.php +++ b/app/Http/Requests/Admin/ArticleRequest.php @@ -9,12 +9,12 @@ class ArticleRequest extends FormRequest public function rules(): array { return [ - 'title' => 'required', - 'type' => 'required|numeric', - 'summary' => 'nullable', - 'logo' => 'nullable|exclude_if:type,4|image', - 'content' => 'required', + 'type' => 'required|numeric|between:1,4', + 'title' => 'required|string', + 'summary' => 'string|nullable', 'sort' => 'required_if:type,1|numeric', + 'logo' => 'nullable|exclude_if:type,4|image', + 'content' => 'required|string', ]; } } diff --git a/app/Http/Requests/Admin/CertRequest.php b/app/Http/Requests/Admin/CertRequest.php new file mode 100644 index 00000000..69abdf9d --- /dev/null +++ b/app/Http/Requests/Admin/CertRequest.php @@ -0,0 +1,17 @@ + 'required|string', + 'key' => 'string|nullable', + 'pem' => 'string|nullable', + ]; + } +} diff --git a/app/Http/Requests/Admin/CouponRequest.php b/app/Http/Requests/Admin/CouponRequest.php index 11ab8c0e..1c6decad 100644 --- a/app/Http/Requests/Admin/CouponRequest.php +++ b/app/Http/Requests/Admin/CouponRequest.php @@ -9,13 +9,14 @@ class CouponRequest extends FormRequest public function rules(): array { return [ - 'name' => 'required', + 'name' => 'required|string', 'sn' => 'unique:coupon', 'logo' => 'nullable|image', - 'type' => 'required|integer|between:1,3', - 'usable_times' => 'integer|nullable', - 'num' => 'required|integer|min:1', + 'type' => 'required|numeric|between:1,3', + 'usable_times' => 'numeric|nullable', 'value' => 'required|numeric|min:0', + 'rule' => 'required_unless:type,3', + 'num' => 'required|numeric|min:1', 'start_time' => 'required|date|before_or_equal:end_time', 'end_time' => 'required|date|after_or_equal:start_time', ]; diff --git a/app/Http/Requests/Admin/PermissionRequest.php b/app/Http/Requests/Admin/PermissionRequest.php new file mode 100644 index 00000000..a9bef815 --- /dev/null +++ b/app/Http/Requests/Admin/PermissionRequest.php @@ -0,0 +1,16 @@ + 'required|string', + 'description' => 'required|string', + ]; + } +} diff --git a/app/Http/Requests/Admin/RbacRequest.php b/app/Http/Requests/Admin/RbacRequest.php new file mode 100644 index 00000000..b10d6d56 --- /dev/null +++ b/app/Http/Requests/Admin/RbacRequest.php @@ -0,0 +1,16 @@ + 'required|string', + 'description' => 'required|string', + ]; + } +} diff --git a/app/Http/Requests/Admin/RoleRequest.php b/app/Http/Requests/Admin/RoleRequest.php new file mode 100644 index 00000000..129abe6e --- /dev/null +++ b/app/Http/Requests/Admin/RoleRequest.php @@ -0,0 +1,17 @@ + 'required|string', + 'description' => 'required|string', + 'permissions' => 'exists:permissions,name', + ]; + } +} diff --git a/app/Http/Requests/Admin/RuleGroupRequest.php b/app/Http/Requests/Admin/RuleGroupRequest.php new file mode 100644 index 00000000..cca8acbf --- /dev/null +++ b/app/Http/Requests/Admin/RuleGroupRequest.php @@ -0,0 +1,17 @@ + 'required|string', + 'type' => 'required|boolean', + 'rules' => 'exists:rule,id', + ]; + } +} diff --git a/app/Http/Requests/Admin/RuleRequest.php b/app/Http/Requests/Admin/RuleRequest.php new file mode 100644 index 00000000..a56914e3 --- /dev/null +++ b/app/Http/Requests/Admin/RuleRequest.php @@ -0,0 +1,17 @@ + 'required|numeric|between:1,4', + 'name' => 'required|string', + 'pattern' => 'required|string', + ]; + } +} diff --git a/app/Http/Requests/Admin/UserGroupRequest.php b/app/Http/Requests/Admin/UserGroupRequest.php new file mode 100644 index 00000000..459b0d8b --- /dev/null +++ b/app/Http/Requests/Admin/UserGroupRequest.php @@ -0,0 +1,16 @@ + 'required|string', + 'nodes' => 'exists:node,id', + ]; + } +} diff --git a/app/Models/Coupon.php b/app/Models/Coupon.php index 1c89463a..6737d29e 100644 --- a/app/Models/Coupon.php +++ b/app/Models/Coupon.php @@ -13,12 +13,23 @@ class Coupon extends Model use SoftDeletes; protected $table = 'coupon'; + protected $casts = ['start_time' => 'date:Y-m-d', 'end_time' => 'date:Y-m-d']; protected $dates = ['deleted_at']; - protected $fillable = ['usable_times', 'status']; + protected $guarded = []; // 筛选类型 public function scopeType($query, $type) { return $query->whereType($type); } + + public function setStartTimeAttribute($value) + { + return $this->attributes['start_time'] = strtotime($value); + } + + public function setEndTimeAttribute($value) + { + return $this->attributes['end_time'] = strtotime($value); + } } diff --git a/app/Models/Label.php b/app/Models/Label.php index d9a3a74e..4ee06539 100644 --- a/app/Models/Label.php +++ b/app/Models/Label.php @@ -14,8 +14,8 @@ class Label extends Model protected $table = 'label'; protected $guarded = ['id']; - public function nodes(): HasMany + public function nodes() { - return $this->hasMany(NodeLabel::class); + return $this->belongsToMany(Node::class); } } diff --git a/app/Models/Node.php b/app/Models/Node.php index 73342873..25995aa1 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -3,6 +3,8 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; @@ -11,12 +13,12 @@ use Illuminate\Database\Eloquent\Relations\HasOne; */ class Node extends Model { - protected $table = 'ss_node'; - protected $guarded = ['id', 'created_at']; + protected $table = 'node'; + protected $guarded = []; - public function labels(): HasMany + public function labels() { - return $this->hasMany(NodeLabel::class); + return $this->belongsToMany(Label::class); } public function heartBeats(): HasMany @@ -44,14 +46,14 @@ class Node extends Model return $this->hasMany(NodeHourlyDataFlow::class); } - public function rules(): hasMany + public function ruleGroup(): BelongsTo { - return $this->hasMany(NodeRule::class); + return $this->belongsTo(RuleGroup::class); } - public function ruleGroup(): hasOne + public function userGroups(): BelongsToMany { - return $this->hasOne(RuleGroupNode::class); + return $this->belongsToMany(UserGroup::class); } public function auth(): HasOne @@ -64,14 +66,10 @@ class Node extends Model return $this->hasOne(Level::class, 'level', 'level'); } - public function scopeUserAllowNodes($query, $user_group_id, $user_level) + public function users() { - $userGroup = UserGroup::find($user_group_id); - if ($userGroup) { - $query->whereIn('id', $userGroup->nodes); - } - - return $query->whereStatus(1)->where('level', '<=', $user_level ?: 0); + return User::activeUser()->whereIn('user_group_id', $this->userGroups->pluck('id')->toArray())->orwhereNull('user_group_id')->where('level', '>=', + $this->attributes['level'])->get(); } public function config($user) @@ -149,11 +147,6 @@ class Node extends Model return $this->attributes['speed_limit'] = $value * Mbps; } - public function getNodeAccessUsersAttribute() - { - return User::nodeAllowUsers($this->attributes['id'], $this->attributes['level'])->get(); - } - public function getTypeLabelAttribute(): string { switch ($this->attributes['type']) { diff --git a/app/Models/NodeHeartBeat.php b/app/Models/NodeHeartBeat.php index bae00e16..b8b405b1 100644 --- a/app/Models/NodeHeartBeat.php +++ b/app/Models/NodeHeartBeat.php @@ -7,10 +7,10 @@ use Illuminate\Database\Eloquent\Model; /** * 节点负载信息. */ -class NodeHeartBeat extends Model +class NodeHeartbeat extends Model { public $timestamps = false; - protected $table = 'ss_node_info'; + protected $table = 'node_heartbeat'; public function scopeRecently($query) { diff --git a/app/Models/NodeLabel.php b/app/Models/NodeLabel.php deleted file mode 100644 index fc50be91..00000000 --- a/app/Models/NodeLabel.php +++ /dev/null @@ -1,25 +0,0 @@ -belongsTo(Node::class); - } - - public function label(): BelongsTo - { - return $this->belongsTo(Label::class); - } -} diff --git a/app/Models/NodeOnlineUserIp.php b/app/Models/NodeOnlineIp.php similarity index 84% rename from app/Models/NodeOnlineUserIp.php rename to app/Models/NodeOnlineIp.php index 697d7100..0e323032 100644 --- a/app/Models/NodeOnlineUserIp.php +++ b/app/Models/NodeOnlineIp.php @@ -8,10 +8,10 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * 节点在线用户IP信息. */ -class NodeOnlineUserIp extends Model +class NodeOnlineIp extends Model { public $timestamps = false; - protected $table = 'ss_node_ip'; + protected $table = 'node_online_ip'; public function node(): BelongsTo { diff --git a/app/Models/NodeOnlineLog.php b/app/Models/NodeOnlineLog.php index a547738d..7f895251 100644 --- a/app/Models/NodeOnlineLog.php +++ b/app/Models/NodeOnlineLog.php @@ -10,5 +10,5 @@ use Illuminate\Database\Eloquent\Model; class NodeOnlineLog extends Model { public $timestamps = false; - protected $table = 'ss_node_online_log'; + protected $table = 'node_online_log'; } diff --git a/app/Models/NodeRule.php b/app/Models/NodeRule.php deleted file mode 100644 index d2ad0b5f..00000000 --- a/app/Models/NodeRule.php +++ /dev/null @@ -1,13 +0,0 @@ -active()->with('goods')->whereHas('goods', static function ($list) { - $list->whereType(2); + return $query->active()->with('goods')->whereHas('goods', static function ($query) { + $query->whereType(2); }); } public function scopeActivePackage($query) { - return $query->active()->with('goods')->whereHas('goods', static function ($list) { - $list->whereType(1); + return $query->active()->with('goods')->whereHas('goods', static function ($query) { + $query->whereType(1); }); } diff --git a/app/Models/ReferralApply.php b/app/Models/ReferralApply.php index 1d4038c7..a8e73382 100644 --- a/app/Models/ReferralApply.php +++ b/app/Models/ReferralApply.php @@ -24,6 +24,11 @@ class ReferralApply extends Model return $this->belongsTo(User::class); } + public function referral_logs() + { + return ReferralLog::whereIn('id', $this->link_logs); + } + public function getBeforeAttribute($value) { return $value / 100; diff --git a/app/Models/Rule.php b/app/Models/Rule.php index 4a1dfa11..d45a0023 100644 --- a/app/Models/Rule.php +++ b/app/Models/Rule.php @@ -56,4 +56,9 @@ class Rule extends Model return $type_api_label; } + + public function rule_groups() + { + return $this->belongsToMany(RuleGroup::class); + } } diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php index 8a83bbf0..046ce0d0 100644 --- a/app/Models/RuleGroup.php +++ b/app/Models/RuleGroup.php @@ -10,8 +10,7 @@ use Illuminate\Database\Eloquent\Model; class RuleGroup extends Model { protected $table = 'rule_group'; - protected $casts = ['rules' => 'array', 'nodes' => 'array']; - protected $guarded = ['id']; + protected $guarded = []; public function getTypeLabelAttribute(): string { @@ -23,4 +22,9 @@ class RuleGroup extends Model return $type_label; } + + public function rules() + { + return $this->belongsToMany(Rule::class); + } } diff --git a/app/Models/RuleGroupNode.php b/app/Models/RuleGroupNode.php deleted file mode 100644 index afff9235..00000000 --- a/app/Models/RuleGroupNode.php +++ /dev/null @@ -1,13 +0,0 @@ -BelongsTo(User::class); + return $this->belongsTo(User::class); + } + + public function reply(): HasMany + { + return $this->hasMany(TicketReply::class); } public function close(): bool diff --git a/app/Models/User.php b/app/Models/User.php index dd4b1e00..1f2d88b3 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -22,7 +22,7 @@ class User extends Authenticatable implements JWTSubject protected $table = 'user'; protected $casts = ['expired_at' => 'date:Y-m-d', 'reset_time' => 'date:Y-m-d', 'ban_time' => 'date:Y-m-d']; protected $dates = ['expired_at', 'reset_time']; - protected $guarded = ['id']; + protected $guarded = []; public function usedTrafficPercentage() { @@ -63,7 +63,7 @@ class User extends Authenticatable implements JWTSubject public function onlineIpLogs(): HasMany { - return $this->hasMany(NodeOnlineUserIp::class); + return $this->hasMany(NodeOnlineIp::class); } public function payments(): HasMany @@ -151,11 +151,6 @@ class User extends Authenticatable implements JWTSubject return $this->hasMany(Verify::class); } - public function group(): BelongsTo - { - return $this->belongsTo(UserGroup::class); - } - public function inviter(): BelongsTo { return $this->belongsTo(__CLASS__); @@ -221,24 +216,20 @@ class User extends Authenticatable implements JWTSubject return $query->where('status', '<>', -1)->whereEnable(1); } - public function scopeNodeAllowUsers($query, $node_id, $node_level) + public function nodes() { - $groups = [0]; - if ($node_id) { - foreach (UserGroup::all() as $userGroup) { - $nodes = $userGroup->nodes; - if ($nodes && in_array($node_id, $nodes)) { - $groups[] = $userGroup->id; - } - } + if ($this->attributes['user_group_id']) { + $query = $this->group->nodes(); + } else { + $query = Node::query(); } - return $query->activeUser()->whereIn('group_id', $groups)->where('level', '>=', $node_level); + return $query->whereStatus(1)->where('level', '<=', $this->attributes['level'] ?? 0); } - public function scopeUserAccessNodes() + public function group(): BelongsTo { - return Node::userAllowNodes($this->attributes['group_id'] ?? 0, $this->attributes['level'] ?? 0); + return $this->belongsTo(UserGroup::class); } public function getIsAvailableAttribute(): bool diff --git a/app/Models/UserGroup.php b/app/Models/UserGroup.php index 3acc9ce9..185f66d0 100644 --- a/app/Models/UserGroup.php +++ b/app/Models/UserGroup.php @@ -11,6 +11,15 @@ class UserGroup extends Model { public $timestamps = false; protected $table = 'user_group'; - protected $casts = ['nodes' => 'array']; - protected $guarded = ['id']; + protected $guarded = []; + + public function users() + { + return $this->hasMany(User::class); + } + + public function nodes() + { + return $this->belongsToMany(Node::class); + } } diff --git a/app/Models/UserSubscribe.php b/app/Models/UserSubscribe.php index 9d22c317..ad85664a 100644 --- a/app/Models/UserSubscribe.php +++ b/app/Models/UserSubscribe.php @@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class UserSubscribe extends Model { protected $table = 'user_subscribe'; - protected $guarded = ['id', 'user_id']; + protected $guarded = []; public function scopeUid($query) { diff --git a/app/Observers/RuleGroupObserver.php b/app/Observers/RuleGroupObserver.php deleted file mode 100644 index 4f85e186..00000000 --- a/app/Observers/RuleGroupObserver.php +++ /dev/null @@ -1,34 +0,0 @@ -getChanges(); - if ($ruleGroup->nodes && Arr::hasAny($changes, ['type', 'rules'])) { - $nodes = Node::whereType(4)->whereIn('id', $ruleGroup->nodes)->get(); - if ($nodes->isNotEmpty()) { - reloadNode::dispatch($nodes); - } - } elseif ($ruleGroup->rules && Arr::exists($changes, 'nodes')) { - $arrayDiff = array_merge( - array_diff($ruleGroup->nodes ?? [], $ruleGroup->getOriginal('nodes') ?? []), - array_diff($ruleGroup->getOriginal('nodes') ?? [], $ruleGroup->nodes ?? []) - ); - - if ($arrayDiff) { - $nodes = Node::whereType(4)->whereIn('id', $arrayDiff)->get(); - if ($nodes->isNotEmpty()) { - reloadNode::dispatch($nodes); - } - } - } - } -} diff --git a/app/Observers/UserObserver.php b/app/Observers/UserObserver.php index 74a5a04c..5c103b1d 100644 --- a/app/Observers/UserObserver.php +++ b/app/Observers/UserObserver.php @@ -19,7 +19,7 @@ class UserObserver $subscribe->code = Helpers::makeSubscribeCode(); $subscribe->save(); - $allowNodes = $user->userAccessNodes()->whereType(4)->pluck('id'); + $allowNodes = $user->nodes()->whereType(4)->pluck('id'); if ($allowNodes) { addUser::dispatch($user->id, $allowNodes); } @@ -28,7 +28,7 @@ class UserObserver public function updated(User $user): void { $changes = $user->getChanges(); - $allowNodes = $user->userAccessNodes()->whereType(4)->get(); + $allowNodes = $user->nodes()->whereType(4)->get(); if ($allowNodes->isNotEmpty() && Arr::hasAny($changes, ['level', 'group_id', 'port', 'passwd', 'speed_limit', 'enable'])) { editUser::dispatch($user, $allowNodes); } @@ -36,7 +36,7 @@ class UserObserver public function deleted(User $user): void { - $allowNodes = $user->userAccessNodes()->whereType(4)->get(); + $allowNodes = $user->nodes()->whereType(4)->get(); if ($allowNodes->isNotEmpty()) { delUser::dispatch($user->id, $allowNodes); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index f517d543..eaa2fa95 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,7 +5,6 @@ namespace App\Providers; use App\Models\Config; use App\Models\Node; use App\Models\Order; -use App\Models\RuleGroup; use App\Models\User; use App\Models\UserGroup; use App\Observers\ConfigObserver; @@ -51,7 +50,6 @@ class AppServiceProvider extends ServiceProvider Config::observe(ConfigObserver::class); Node::observe(NodeObserver::class); Order::observe(OrderObserver::class); - RuleGroup::observe(RuleGroupObserver::class); UserGroup::observe(UserGroupObserver::class); User::observe(UserObserver::class); } diff --git a/app/Services/NodeService.php b/app/Services/NodeService.php index ae17d4fd..ec5ef58e 100644 --- a/app/Services/NodeService.php +++ b/app/Services/NodeService.php @@ -4,7 +4,6 @@ namespace App\Services; use App\Components\IP; use App\Models\Node; -use App\Models\NodeLabel; class NodeService { @@ -26,20 +25,4 @@ class NodeService return $result; } - - // 生成节点标签 - public function makeLabels($nodeId, $labels): void - { - // 先删除所有该节点的标签 - NodeLabel::whereNodeId($nodeId)->delete(); - - if (! empty($labels) && is_array($labels)) { - foreach ($labels as $label) { - $nodeLabel = new NodeLabel(); - $nodeLabel->node_id = $nodeId; - $nodeLabel->label_id = $label; - $nodeLabel->save(); - } - } - } } diff --git a/composer.lock b/composer.lock index cbcd2775..973d6ab3 100644 --- a/composer.lock +++ b/composer.lock @@ -1687,16 +1687,16 @@ }, { "name": "laravel/framework", - "version": "v7.30.0", + "version": "v7.30.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "629c36a0fe87b66d8dccd3c82927950d0f59d3f9" + "reference": "e73855b18dcfc645c36d2474f437e4e73dd3c11d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/629c36a0fe87b66d8dccd3c82927950d0f59d3f9", - "reference": "629c36a0fe87b66d8dccd3c82927950d0f59d3f9", + "url": "https://api.github.com/repos/laravel/framework/zipball/e73855b18dcfc645c36d2474f437e4e73dd3c11d", + "reference": "e73855b18dcfc645c36d2474f437e4e73dd3c11d", "shasum": "" }, "require": { @@ -1845,7 +1845,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2020-12-01T15:01:25+00:00" + "time": "2020-12-22T17:00:45+00:00" }, { "name": "laravel/tinker", @@ -2595,16 +2595,16 @@ }, { "name": "mews/captcha", - "version": "3.2.3", + "version": "3.2.4", "source": { "type": "git", "url": "https://github.com/mewebstudio/captcha.git", - "reference": "b5549a90110ec6c32a93073aba3ea9ade288c6f7" + "reference": "616d006be6f53e87b93f6dc0f298fb29ca0b7d6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mewebstudio/captcha/zipball/b5549a90110ec6c32a93073aba3ea9ade288c6f7", - "reference": "b5549a90110ec6c32a93073aba3ea9ade288c6f7", + "url": "https://api.github.com/repos/mewebstudio/captcha/zipball/616d006be6f53e87b93f6dc0f298fb29ca0b7d6c", + "reference": "616d006be6f53e87b93f6dc0f298fb29ca0b7d6c", "shasum": "" }, "require": { @@ -2662,9 +2662,9 @@ ], "support": { "issues": "https://github.com/mewebstudio/captcha/issues", - "source": "https://github.com/mewebstudio/captcha/tree/3.2.3" + "source": "https://github.com/mewebstudio/captcha/tree/3.2.4" }, - "time": "2020-11-03T19:44:37+00:00" + "time": "2020-12-14T12:34:10+00:00" }, { "name": "mews/purifier", @@ -2805,16 +2805,16 @@ }, { "name": "monolog/monolog", - "version": "2.1.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f9eee5cec93dfb313a38b6b288741e84e53f02d5" + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f9eee5cec93dfb313a38b6b288741e84e53f02d5", - "reference": "f9eee5cec93dfb313a38b6b288741e84e53f02d5", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084", + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084", "shasum": "" }, "require": { @@ -2827,16 +2827,17 @@ "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^6.0", + "elasticsearch/elasticsearch": "^7", "graylog2/gelf-php": "^1.4.2", + "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", - "php-parallel-lint/php-parallel-lint": "^1.0", "phpspec/prophecy": "^1.6.1", + "phpstan/phpstan": "^0.12.59", "phpunit/phpunit": "^8.5", "predis/predis": "^1.1", "rollbar/rollbar": "^1.3", - "ruflin/elastica": ">=0.90 <3.0", + "ruflin/elastica": ">=0.90 <7.0.1", "swiftmailer/swiftmailer": "^5.3|^6.0" }, "suggest": { @@ -2856,7 +2857,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -2872,11 +2873,11 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ "log", "logging", @@ -2884,7 +2885,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.1.1" + "source": "https://github.com/Seldaek/monolog/tree/2.2.0" }, "funding": [ { @@ -2896,7 +2897,7 @@ "type": "tidelift" } ], - "time": "2020-07-23T08:41:23+00:00" + "time": "2020-12-14T13:15:25+00:00" }, { "name": "myclabs/php-enum", @@ -3027,16 +3028,16 @@ }, { "name": "nesbot/carbon", - "version": "2.42.0", + "version": "2.43.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "d0463779663437392fe42ff339ebc0213bd55498" + "reference": "d32c57d8389113742f4a88725a170236470012e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d0463779663437392fe42ff339ebc0213bd55498", - "reference": "d0463779663437392fe42ff339ebc0213bd55498", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d32c57d8389113742f4a88725a170236470012e2", + "reference": "d32c57d8389113742f4a88725a170236470012e2", "shasum": "" }, "require": { @@ -3116,20 +3117,20 @@ "type": "tidelift" } ], - "time": "2020-11-28T14:25:28+00:00" + "time": "2020-12-17T20:55:32+00:00" }, { "name": "nikic/php-parser", - "version": "v4.10.3", + "version": "v4.10.4", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984" + "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984", - "reference": "dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", "shasum": "" }, "require": { @@ -3170,9 +3171,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.3" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" }, - "time": "2020-12-03T17:45:45+00:00" + "time": "2020-12-20T10:01:03+00:00" }, { "name": "opis/closure", @@ -4521,16 +4522,16 @@ }, { "name": "symfony/console", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3e0564fb08d44a98bd5f1960204c958e57bd586b" + "reference": "47c02526c532fb381374dab26df05e7313978976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3e0564fb08d44a98bd5f1960204c958e57bd586b", - "reference": "3e0564fb08d44a98bd5f1960204c958e57bd586b", + "url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976", + "reference": "47c02526c532fb381374dab26df05e7313978976", "shasum": "" }, "require": { @@ -4598,7 +4599,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.0" + "source": "https://github.com/symfony/console/tree/v5.2.1" }, "funding": [ { @@ -4614,20 +4615,20 @@ "type": "tidelift" } ], - "time": "2020-11-28T11:24:18+00:00" + "time": "2020-12-18T08:03:05+00:00" }, { "name": "symfony/css-selector", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "b8d8eb06b0942e84a69e7acebc3e9c1e6e6e7256" + "reference": "f789e7ead4c79e04ca9a6d6162fc629c89bd8054" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/b8d8eb06b0942e84a69e7acebc3e9c1e6e6e7256", - "reference": "b8d8eb06b0942e84a69e7acebc3e9c1e6e6e7256", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/f789e7ead4c79e04ca9a6d6162fc629c89bd8054", + "reference": "f789e7ead4c79e04ca9a6d6162fc629c89bd8054", "shasum": "" }, "require": { @@ -4663,7 +4664,7 @@ "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.2.0" + "source": "https://github.com/symfony/css-selector/tree/v5.2.1" }, "funding": [ { @@ -4679,7 +4680,7 @@ "type": "tidelift" } ], - "time": "2020-10-28T21:31:18+00:00" + "time": "2020-12-08T17:02:38+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4750,16 +4751,16 @@ }, { "name": "symfony/error-handler", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "289008c5be039e39908d33ae0a8ac99be1210bba" + "reference": "59b190ce16ddf32771a22087b60f6dafd3407147" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/289008c5be039e39908d33ae0a8ac99be1210bba", - "reference": "289008c5be039e39908d33ae0a8ac99be1210bba", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/59b190ce16ddf32771a22087b60f6dafd3407147", + "reference": "59b190ce16ddf32771a22087b60f6dafd3407147", "shasum": "" }, "require": { @@ -4799,7 +4800,7 @@ "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.2.0" + "source": "https://github.com/symfony/error-handler/tree/v5.2.1" }, "funding": [ { @@ -4815,20 +4816,20 @@ "type": "tidelift" } ], - "time": "2020-10-28T21:46:03+00:00" + "time": "2020-12-09T18:54:12+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "aa13a09811e6d2ad43f8fb336bebdb7691d85d3c" + "reference": "1c93f7a1dff592c252574c79a8635a8a80856042" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/aa13a09811e6d2ad43f8fb336bebdb7691d85d3c", - "reference": "aa13a09811e6d2ad43f8fb336bebdb7691d85d3c", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1c93f7a1dff592c252574c79a8635a8a80856042", + "reference": "1c93f7a1dff592c252574c79a8635a8a80856042", "shasum": "" }, "require": { @@ -4884,7 +4885,7 @@ "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.1" }, "funding": [ { @@ -4900,7 +4901,7 @@ "type": "tidelift" } ], - "time": "2020-11-01T16:14:45+00:00" + "time": "2020-12-18T08:03:05+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4983,16 +4984,16 @@ }, { "name": "symfony/finder", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fd8305521692f27eae3263895d1ef1571c71a78d" + "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fd8305521692f27eae3263895d1ef1571c71a78d", - "reference": "fd8305521692f27eae3263895d1ef1571c71a78d", + "url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba", + "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba", "shasum": "" }, "require": { @@ -5024,7 +5025,7 @@ "description": "Symfony Finder Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.0" + "source": "https://github.com/symfony/finder/tree/v5.2.1" }, "funding": [ { @@ -5040,7 +5041,7 @@ "type": "tidelift" } ], - "time": "2020-11-18T09:42:36+00:00" + "time": "2020-12-08T17:02:38+00:00" }, { "name": "symfony/http-client-contracts", @@ -5123,16 +5124,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e4576271ee99123aa59a40564c7b5405f0ebd1e6" + "reference": "a1f6218b29897ab52acba58cfa905b83625bef8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e4576271ee99123aa59a40564c7b5405f0ebd1e6", - "reference": "e4576271ee99123aa59a40564c7b5405f0ebd1e6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a1f6218b29897ab52acba58cfa905b83625bef8d", + "reference": "a1f6218b29897ab52acba58cfa905b83625bef8d", "shasum": "" }, "require": { @@ -5176,7 +5177,7 @@ "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.2.0" + "source": "https://github.com/symfony/http-foundation/tree/v5.2.1" }, "funding": [ { @@ -5192,20 +5193,20 @@ "type": "tidelift" } ], - "time": "2020-11-27T06:13:25+00:00" + "time": "2020-12-18T10:00:10+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "38907e5ccb2d9d371191a946734afc83c7a03160" + "reference": "1feb619286d819180f7b8bc0dc44f516d9c62647" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/38907e5ccb2d9d371191a946734afc83c7a03160", - "reference": "38907e5ccb2d9d371191a946734afc83c7a03160", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1feb619286d819180f7b8bc0dc44f516d9c62647", + "reference": "1feb619286d819180f7b8bc0dc44f516d9c62647", "shasum": "" }, "require": { @@ -5288,7 +5289,7 @@ "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.2.0" + "source": "https://github.com/symfony/http-kernel/tree/v5.2.1" }, "funding": [ { @@ -5304,20 +5305,20 @@ "type": "tidelift" } ], - "time": "2020-11-30T05:54:18+00:00" + "time": "2020-12-18T13:49:39+00:00" }, { "name": "symfony/mime", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "05f667e8fa029568964fd3bec6bc17765b853cc5" + "reference": "de97005aef7426ba008c46ba840fc301df577ada" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/05f667e8fa029568964fd3bec6bc17765b853cc5", - "reference": "05f667e8fa029568964fd3bec6bc17765b853cc5", + "url": "https://api.github.com/repos/symfony/mime/zipball/de97005aef7426ba008c46ba840fc301df577ada", + "reference": "de97005aef7426ba008c46ba840fc301df577ada", "shasum": "" }, "require": { @@ -5368,7 +5369,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.2.0" + "source": "https://github.com/symfony/mime/tree/v5.2.1" }, "funding": [ { @@ -5384,7 +5385,7 @@ "type": "tidelift" } ], - "time": "2020-10-30T14:55:39+00:00" + "time": "2020-12-09T18:54:12+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6185,16 +6186,16 @@ }, { "name": "symfony/process", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "240e74140d4d956265048f3025c0aecbbc302d54" + "reference": "bd8815b8b6705298beaa384f04fabd459c10bedd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/240e74140d4d956265048f3025c0aecbbc302d54", - "reference": "240e74140d4d956265048f3025c0aecbbc302d54", + "url": "https://api.github.com/repos/symfony/process/zipball/bd8815b8b6705298beaa384f04fabd459c10bedd", + "reference": "bd8815b8b6705298beaa384f04fabd459c10bedd", "shasum": "" }, "require": { @@ -6227,7 +6228,7 @@ "description": "Symfony Process Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.2.0" + "source": "https://github.com/symfony/process/tree/v5.2.1" }, "funding": [ { @@ -6243,20 +6244,20 @@ "type": "tidelift" } ], - "time": "2020-11-02T15:47:15+00:00" + "time": "2020-12-08T17:03:37+00:00" }, { "name": "symfony/routing", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "130ac5175ad2fd417978baebd8062e2e6b2bc28b" + "reference": "934ac2720dcc878a47a45c986b483a7ee7193620" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/130ac5175ad2fd417978baebd8062e2e6b2bc28b", - "reference": "130ac5175ad2fd417978baebd8062e2e6b2bc28b", + "url": "https://api.github.com/repos/symfony/routing/zipball/934ac2720dcc878a47a45c986b483a7ee7193620", + "reference": "934ac2720dcc878a47a45c986b483a7ee7193620", "shasum": "" }, "require": { @@ -6317,7 +6318,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.2.0" + "source": "https://github.com/symfony/routing/tree/v5.2.1" }, "funding": [ { @@ -6333,7 +6334,7 @@ "type": "tidelift" } ], - "time": "2020-11-27T00:39:34+00:00" + "time": "2020-12-08T17:03:37+00:00" }, { "name": "symfony/service-contracts", @@ -6416,16 +6417,16 @@ }, { "name": "symfony/string", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "40e975edadd4e32cd16f3753b3bad65d9ac48242" + "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/40e975edadd4e32cd16f3753b3bad65d9ac48242", - "reference": "40e975edadd4e32cd16f3753b3bad65d9ac48242", + "url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed", + "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed", "shasum": "" }, "require": { @@ -6479,7 +6480,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.0" + "source": "https://github.com/symfony/string/tree/v5.2.1" }, "funding": [ { @@ -6495,20 +6496,20 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:08:07+00:00" + "time": "2020-12-05T07:33:16+00:00" }, { "name": "symfony/translation", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "52f486a707510884450df461b5a6429dd7a67379" + "reference": "a04209ba0d1391c828e5b2373181dac63c52ee70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/52f486a707510884450df461b5a6429dd7a67379", - "reference": "52f486a707510884450df461b5a6429dd7a67379", + "url": "https://api.github.com/repos/symfony/translation/zipball/a04209ba0d1391c828e5b2373181dac63c52ee70", + "reference": "a04209ba0d1391c828e5b2373181dac63c52ee70", "shasum": "" }, "require": { @@ -6572,7 +6573,7 @@ "description": "Symfony Translation Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.2.0" + "source": "https://github.com/symfony/translation/tree/v5.2.1" }, "funding": [ { @@ -6588,7 +6589,7 @@ "type": "tidelift" } ], - "time": "2020-11-28T11:24:18+00:00" + "time": "2020-12-08T17:03:37+00:00" }, { "name": "symfony/translation-contracts", @@ -6670,16 +6671,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "173a79c462b1c81e1fa26129f71e41333d846b26" + "reference": "13e7e882eaa55863faa7c4ad7c60f12f1a8b5089" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/173a79c462b1c81e1fa26129f71e41333d846b26", - "reference": "173a79c462b1c81e1fa26129f71e41333d846b26", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/13e7e882eaa55863faa7c4ad7c60f12f1a8b5089", + "reference": "13e7e882eaa55863faa7c4ad7c60f12f1a8b5089", "shasum": "" }, "require": { @@ -6738,7 +6739,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.2.0" + "source": "https://github.com/symfony/var-dumper/tree/v5.2.1" }, "funding": [ { @@ -6754,20 +6755,20 @@ "type": "tidelift" } ], - "time": "2020-11-27T00:39:34+00:00" + "time": "2020-12-16T17:02:19+00:00" }, { "name": "symfony/yaml", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "bb73619b2ae5121bbbcd9f191dfd53ded17ae598" + "reference": "290ea5e03b8cf9b42c783163123f54441fb06939" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/bb73619b2ae5121bbbcd9f191dfd53ded17ae598", - "reference": "bb73619b2ae5121bbbcd9f191dfd53ded17ae598", + "url": "https://api.github.com/repos/symfony/yaml/zipball/290ea5e03b8cf9b42c783163123f54441fb06939", + "reference": "290ea5e03b8cf9b42c783163123f54441fb06939", "shasum": "" }, "require": { @@ -6813,7 +6814,7 @@ "description": "Symfony Yaml Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.2.0" + "source": "https://github.com/symfony/yaml/tree/v5.2.1" }, "funding": [ { @@ -6829,7 +6830,7 @@ "type": "tidelift" } ], - "time": "2020-11-28T10:57:20+00:00" + "time": "2020-12-08T17:02:38+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -7547,16 +7548,16 @@ }, { "name": "andrey-helldar/support", - "version": "v1.26.0", + "version": "v1.30.2", "source": { "type": "git", "url": "https://github.com/andrey-helldar/support.git", - "reference": "608895d7324d44167a97a88ebec766e99dee92c7" + "reference": "e463d3c5ed4302ab04001a04d3264fc78acac858" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/andrey-helldar/support/zipball/608895d7324d44167a97a88ebec766e99dee92c7", - "reference": "608895d7324d44167a97a88ebec766e99dee92c7", + "url": "https://api.github.com/repos/andrey-helldar/support/zipball/e463d3c5ed4302ab04001a04d3264fc78acac858", + "reference": "e463d3c5ed4302ab04001a04d3264fc78acac858", "shasum": "" }, "require": { @@ -7585,7 +7586,7 @@ }, "autoload": { "psr-4": { - "Helldar\\Support\\": "src/" + "Helldar\\Support\\": "src" }, "files": [ "src/helpers/digit.php", @@ -7627,7 +7628,7 @@ "type": "custom" } ], - "time": "2020-11-30T12:10:47+00:00" + "time": "2020-12-25T21:28:47+00:00" }, { "name": "arcanedev/laravel-lang", @@ -8611,16 +8612,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.12.0", + "version": "v1.13.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "9aa6c9e289860951e6b4d010c7a841802d015cd8" + "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/9aa6c9e289860951e6b4d010c7a841802d015cd8", - "reference": "9aa6c9e289860951e6b4d010c7a841802d015cd8", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ab3f5364d01f2c2c16113442fb987d26e4004913", + "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913", "shasum": "" }, "require": { @@ -8657,9 +8658,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.12.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.13.0" }, - "time": "2020-11-23T09:33:08+00:00" + "time": "2020-12-18T16:50:48+00:00" }, { "name": "filp/whoops", @@ -9252,6 +9253,127 @@ ], "time": "2020-10-29T15:12:23+00:00" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c", + "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^1|^2|^3|^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2020-12-06T15:14:20+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.19", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/446fc9faa5c2a9ddf65eb7121c0af7e857295241", + "reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T10:06:57+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.1", @@ -9314,16 +9436,16 @@ }, { "name": "phar-io/version", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae" + "reference": "e4782611070e50613683d2b9a57730e9a3ba5451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/726c026815142e4f8677b7cb7f2249c9ffb7ecae", - "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae", + "url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451", + "reference": "e4782611070e50613683d2b9a57730e9a3ba5451", "shasum": "" }, "require": { @@ -9359,9 +9481,9 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.0.3" + "source": "https://github.com/phar-io/version/tree/3.0.4" }, - "time": "2020-11-30T09:21:21+00:00" + "time": "2020-12-13T23:18:30+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -9523,26 +9645,26 @@ }, { "name": "phpseclib/bcmath_compat", - "version": "1.0.5", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpseclib/bcmath_compat.git", - "reference": "89cbb63742a32730b7187773a60b6b12b9db4479" + "reference": "fd896dfceffc13d8cf45d2ee3470777a70026f3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/bcmath_compat/zipball/89cbb63742a32730b7187773a60b6b12b9db4479", - "reference": "89cbb63742a32730b7187773a60b6b12b9db4479", + "url": "https://api.github.com/repos/phpseclib/bcmath_compat/zipball/fd896dfceffc13d8cf45d2ee3470777a70026f3c", + "reference": "fd896dfceffc13d8cf45d2ee3470777a70026f3c", "shasum": "" }, "require": { - "phpseclib/phpseclib": ">=2.0.19" + "phpseclib/phpseclib": "^3.0" }, "provide": { - "ext-bcmath": "7.3.5" + "ext-bcmath": "8.0.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4", "squizlabs/php_codesniffer": "^3.0" }, "suggest": { @@ -9581,28 +9703,30 @@ "issues": "https://github.com/phpseclib/bcmath_compat/issues", "source": "https://github.com/phpseclib/bcmath_compat" }, - "time": "2020-04-26T16:34:33+00:00" + "time": "2020-12-22T16:38:51+00:00" }, { "name": "phpseclib/phpseclib", - "version": "2.0.29", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "497856a8d997f640b4a516062f84228a772a48a8" + "reference": "7a9418e4e02a3da7950b6b85c30e694d68daf995" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/497856a8d997f640b4a516062f84228a772a48a8", - "reference": "497856a8d997f640b4a516062f84228a772a48a8", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7a9418e4e02a3da7950b6b85c30e694d68daf995", + "reference": "7a9418e4e02a3da7950b6b85c30e694d68daf995", "shasum": "" }, "require": { - "php": ">=5.3.3" + "paragonie/constant_time_encoding": "^1|^2", + "paragonie/random_compat": "^1.4|^2.0", + "php": ">=5.6.1" }, "require-dev": { "phing/phing": "~2.7", - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "phpunit/phpunit": "^5.7|^6.0|^9.4", "squizlabs/php_codesniffer": "~2.0" }, "suggest": { @@ -9617,7 +9741,7 @@ "phpseclib/bootstrap.php" ], "psr-4": { - "phpseclib\\": "phpseclib/" + "phpseclib3\\": "phpseclib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -9674,7 +9798,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.2" }, "funding": [ { @@ -9690,20 +9814,20 @@ "type": "tidelift" } ], - "time": "2020-09-08T04:24:43+00:00" + "time": "2020-12-23T16:39:00+00:00" }, { "name": "phpspec/prophecy", - "version": "1.12.1", + "version": "1.12.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" + "reference": "245710e971a030f42e08f4912863805570f23d39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/245710e971a030f42e08f4912863805570f23d39", + "reference": "245710e971a030f42e08f4912863805570f23d39", "shasum": "" }, "require": { @@ -9715,7 +9839,7 @@ }, "require-dev": { "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0 <9.3" + "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { @@ -9755,9 +9879,9 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.12.1" + "source": "https://github.com/phpspec/prophecy/tree/1.12.2" }, - "time": "2020-09-29T09:10:42+00:00" + "time": "2020-12-19T10:15:11+00:00" }, { "name": "phpunit/php-code-coverage", @@ -11307,16 +11431,16 @@ }, { "name": "symfony/debug", - "version": "v4.4.17", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "65fe7b49868378319b82da3035fb30801b931c47" + "reference": "5dfc7825f3bfe9bb74b23d8b8ce0e0894e32b544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/65fe7b49868378319b82da3035fb30801b931c47", - "reference": "65fe7b49868378319b82da3035fb30801b931c47", + "url": "https://api.github.com/repos/symfony/debug/zipball/5dfc7825f3bfe9bb74b23d8b8ce0e0894e32b544", + "reference": "5dfc7825f3bfe9bb74b23d8b8ce0e0894e32b544", "shasum": "" }, "require": { @@ -11356,7 +11480,7 @@ "description": "Symfony Debug Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.17" + "source": "https://github.com/symfony/debug/tree/v4.4.18" }, "funding": [ { @@ -11372,20 +11496,20 @@ "type": "tidelift" } ], - "time": "2020-10-28T20:42:29+00:00" + "time": "2020-12-10T16:34:26+00:00" }, { "name": "symfony/filesystem", - "version": "v5.2.0", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "bb92ba7f38b037e531908590a858a04d85c0e238" + "reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/bb92ba7f38b037e531908590a858a04d85c0e238", - "reference": "bb92ba7f38b037e531908590a858a04d85c0e238", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/fa8f8cab6b65e2d99a118e082935344c5ba8c60d", + "reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d", "shasum": "" }, "require": { @@ -11418,7 +11542,7 @@ "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.2.0" + "source": "https://github.com/symfony/filesystem/tree/v5.2.1" }, "funding": [ { @@ -11434,7 +11558,7 @@ "type": "tidelift" } ], - "time": "2020-11-12T09:58:18+00:00" + "time": "2020-11-30T17:05:38+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/version.php b/config/version.php index 5ff19d4b..7f840569 100644 --- a/config/version.php +++ b/config/version.php @@ -2,5 +2,5 @@ return [ 'name' => 'ProxyPanel', - 'number' => '2.5.x', + 'number' => '2.6.a', ]; diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 5f6dcf19..08faf1fc 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -1,16 +1,23 @@ define(User::class, function (Faker $faker) { return [ 'username' => $faker->name, 'email' => $faker->unique()->safeEmail, 'password' => Hash::make(Str::random()), + 'port' => Helpers::getPort(), 'passwd' => Str::random(), 'vmess_id' => $faker->uuid, + 'method' => Helpers::getDefaultMethod(), + 'protocol' => Helpers::getDefaultProtocol(), + 'obfs' => Helpers::getDefaultObfs(), + 'transfer_enable' => (int) sysConfig('default_traffic') * MB, + 'expired_at' => date('Y-m-d', strtotime('+'.sysConfig('default_days').' days')), ]; }); diff --git a/database/migrations/2020_12_24_074739_table_improvement.php b/database/migrations/2020_12_24_074739_table_improvement.php new file mode 100644 index 00000000..31a831cf --- /dev/null +++ b/database/migrations/2020_12_24_074739_table_improvement.php @@ -0,0 +1,192 @@ +unique('level'); + }); + + Schema::table('node_certificate', function (Blueprint $table) { + $table->unique('domain'); + }); + + Schema::table('ss_node', function (Blueprint $table) { + $table->unsignedInteger('rule_group_id')->nullable()->comment('从属规则分组ID')->after('level'); + $table->foreign('rule_group_id')->references('id')->on('rule_group')->nullOnDelete(); + $table->rename('node'); + }); + + Schema::table('ss_node_info', function (Blueprint $table) { + $table->unsignedInteger('node_id')->comment('节点ID')->change(); + $table->rename('node_heartbeat'); + }); + + Schema::table('ss_node_ip', function (Blueprint $table) { + $table->rename('node_online_ip'); + }); + NodeOnlineIp::whereNodeId(0)->update(['node_id' => null]); + NodeOnlineIp::whereUserId(0)->update(['user_id' => null]); + Schema::table('node_online_ip', function (Blueprint $table) { + $table->unsignedInteger('node_id')->comment('节点ID')->change(); + $table->unsignedInteger('user_id')->default(null)->nullable()->change(); + }); + + Schema::table('ss_node_online_log', function (Blueprint $table) { + $table->rename('node_online_log'); + }); + + Schema::table('node_label', function (Blueprint $table) { + $table->unsignedInteger('node_id')->comment('节点ID')->change(); + $table->unsignedInteger('label_id')->comment('标签ID')->change(); + $table->unique(['node_id', 'label_id']); + $table->rename('label_node'); + }); + + Schema::table('node_ping', function (Blueprint $table) { + $table->unsignedInteger('node_id')->comment('对应节点ID')->change(); + }); + + Order::whereGoodsId(0)->update(['goods_id' => null]); + Order::whereCouponId(0)->orWhereNotIn('coupon_id', Coupon::withTrashed()->pluck('id')->toArray())->update(['coupon_id' => null]); + Schema::table('order', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('购买者ID')->change(); + $table->foreign('goods_id')->references('id')->on('goods')->nullOnDelete(); + $table->foreign('coupon_id')->references('id')->on('coupon')->nullOnDelete(); + }); + + Schema::create('node_user_group', function (Blueprint $table) { + $table->increments('id'); + $table->unsignedInteger('node_id')->comment('节点ID'); + $table->unsignedInteger('user_group_id')->comment('从属用户分组ID'); + + $table->unique(['user_group_id', 'node_id']); + $table->foreign('node_id')->references('id')->on('node')->cascadeOnDelete(); + $table->foreign('user_group_id')->references('id')->on('user_group')->cascadeOnDelete(); + }); + + Schema::table('payment', function (Blueprint $table) { + $table->foreign('order_id')->references('id')->on('order')->cascadeOnDelete(); + }); + + Schema::table('referral_apply', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('申请者ID')->change(); + }); + + Schema::table('rule_log', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('触发者ID')->change(); + }); + + Schema::create('rule_rule_group', function (Blueprint $table) { + $table->increments('id'); + $table->unsignedInteger('rule_id')->comment('规则ID'); + $table->unsignedInteger('rule_group_id')->comment('从属规则分组ID'); + + $table->unique(['rule_group_id', 'rule_id']); + $table->foreign('rule_id')->references('id')->on('rule')->cascadeOnDelete(); + $table->foreign('rule_group_id')->references('id')->on('rule_group')->cascadeOnDelete(); + }); + + Schema::table('ticket', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('ticket_reply', function (Blueprint $table) { + $table->unsignedInteger('ticket_id')->comment('工单ID')->change(); + }); + + Schema::table('user', function (Blueprint $table) { + $table->unsignedInteger('group_id')->nullable()->default(null)->comment('所属分组')->change(); + }); + User::whereGroupId(0)->update(['group_id' => null]); + Schema::table('user', function (Blueprint $table) { + $table->renameColumn('group_id', 'user_group_id'); + $table->foreign('user_group_id')->references('id')->on('user_group')->nullOnDelete(); + }); + + Schema::table('user_baned_log', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_credit_log', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_daily_data_flow', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_data_modify_log', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_hourly_data_flow', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_login_log', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_subscribe', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + }); + + Schema::table('user_traffic_log', function (Blueprint $table) { + $table->unsignedInteger('user_id')->comment('用户ID')->change(); + $table->unsignedInteger('node_id')->comment('节点ID')->change(); + }); + // ----- 结束 数据库表关系优化 ----- + + // ----- 开始 数据转化 & 弃用数据 ----- + foreach (RuleGroup::all() as $group) { + $group->rules()->attach(json_decode($group->rules, true)); + foreach (json_decode($group->nodes, true) as $id) { + $node = Node::find($id); + if ($node) { + $node->update(['rule_group_id' => $group->id]); + } + } + } + + foreach (UserGroup::all() as $group) { + $group->nodes()->attach(json_decode($group->nodes, true)); + } + + Schema::table('rule_group', function (Blueprint $table) { + $table->dropColumn('nodes'); + $table->dropColumn('rules'); + }); + + Schema::table('user_group', function (Blueprint $table) { + $table->dropColumn('nodes'); + }); + + Schema::table('node_rule', function (Blueprint $table) { + $table->drop(); + }); + + Schema::table('rule_group_node', function (Blueprint $table) { + $table->drop(); + }); + // ----- 结束 数据转化 & 弃用数据 ----- + } + + public function down() + { + // 不可逆 + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 237dfc5d..a0a2fd34 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -1,5 +1,6 @@ call(UserSeeder::class); + if (User::doesntExist()) { + $this->call(PresetSeeder::class); + } } } diff --git a/database/migrations/2020_08_21_150711_preset_data.php b/database/seeds/PresetSeeder.php similarity index 72% rename from database/migrations/2020_08_21_150711_preset_data.php rename to database/seeds/PresetSeeder.php index ed8db159..8cc81929 100644 --- a/database/migrations/2020_08_21_150711_preset_data.php +++ b/database/seeds/PresetSeeder.php @@ -8,73 +8,18 @@ use App\Models\Level; use App\Models\Rule; use App\Models\SsConfig; use App\Models\User; -use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Seeder; -class PresetData extends Migration +class PresetSeeder extends Seeder { /** - * Run the migrations. + * Run the database seeds. * * @return void */ - public function up() + public function run() { - // 生成初始管理账号 - User::create([ - 'username' => '管理员', - 'email' => 'test@test.com', - 'password' => '123456', - 'port' => 10000, - 'passwd' => Str::random(), - 'vmess_id' => Str::uuid(), - 'is_admin' => 1, - ]); - - // 生成最初的等级 - Level::insert(['level' => 0, 'name' => 'Free']); - for ($i = 1; $i < 8; $i++) { - Level::insert(['level' => $i, 'name' => 'VIP-'.$i]); - } - - // ss系列 加密方式 - SsConfig::insert(['name' => 'none', 'type' => 1, 'is_default' => 1]); - SsConfig::insert(['name' => 'rc4-md5']); - SsConfig::insert(['name' => 'aes-128-cfb']); - SsConfig::insert(['name' => 'aes-192-cfb']); - SsConfig::insert(['name' => 'aes-256-cfb']); - SsConfig::insert(['name' => 'aes-128-ctr']); - SsConfig::insert(['name' => 'aes-192-ctr']); - SsConfig::insert(['name' => 'aes-256-ctr']); - SsConfig::insert(['name' => 'aes-128-gcm']); - SsConfig::insert(['name' => 'aes-192-gcm']); - SsConfig::insert(['name' => 'aes-256-gcm']); - SsConfig::insert(['name' => 'bf-cfb']); - SsConfig::insert(['name' => 'cast5-cfb']); - SsConfig::insert(['name' => 'des-cfb']); - SsConfig::insert(['name' => 'salsa20']); - SsConfig::insert(['name' => 'chacha20']); - SsConfig::insert(['name' => 'chacha20-ietf']); - SsConfig::insert(['name' => 'chacha20-ietf-poly1305']); - - // ss系列 协议 - SsConfig::insert(['name' => 'origin', 'type' => 2, 'is_default' => 1]); - SsConfig::insert(['name' => 'auth_sha1_v4', 'type' => 2]); - SsConfig::insert(['name' => 'auth_aes128_md5', 'type' => 2]); - SsConfig::insert(['name' => 'auth_aes128_sha1', 'type' => 2]); - SsConfig::insert(['name' => 'auth_chain_a', 'type' => 2]); - SsConfig::insert(['name' => 'auth_chain_b', 'type' => 2]); - SsConfig::insert(['name' => 'auth_chain_c', 'type' => 2]); - SsConfig::insert(['name' => 'auth_chain_d', 'type' => 2]); - SsConfig::insert(['name' => 'auth_chain_e', 'type' => 2]); - SsConfig::insert(['name' => 'auth_chain_f', 'type' => 2]); - - // ss系列 混淆 - SsConfig::insert(['name' => 'plain', 'type' => 3, 'is_default' => 1]); - SsConfig::insert(['name' => 'http_simple', 'type' => 3]); - SsConfig::insert(['name' => 'http_post', 'type' => 3]); - SsConfig::insert(['name' => 'tls1.2_ticket_auth', 'type' => 3]); - SsConfig::insert(['name' => 'tls1.2_ticket_fastauth', 'type' => 3]); - + // 系统参数 $configList = [ 'is_rand_port', 'is_user_rand_port', @@ -198,49 +143,94 @@ class PresetData extends Migration } $presetDates = [ - 'invite_num' => 3, - 'is_register' => 1, - 'is_invite_register' => 2, - 'website_name' => 'ProxyPanel', - 'is_reset_password' => 1, - 'reset_password_times' => 3, - 'website_url' => 'https://demo.proxypanel.ml', - 'active_times' => 3, - 'is_checkin' => 1, - 'min_rand_traffic' => 10, - 'max_rand_traffic' => 500, - 'traffic_limit_time' => 1440, - 'referral_traffic' => 1024, - 'referral_percent' => 0.2, - 'referral_money' => 100, - 'referral_status' => 1, - 'default_traffic' => 1024, + 'invite_num' => 3, + 'is_register' => 1, + 'is_invite_register' => 2, + 'website_name' => 'ProxyPanel', + 'is_reset_password' => 1, + 'reset_password_times' => 3, + 'website_url' => 'https://demo.proxypanel.ml', + 'active_times' => 3, + 'is_checkin' => 1, + 'min_rand_traffic' => 10, + 'max_rand_traffic' => 500, + 'traffic_limit_time' => 1440, + 'referral_traffic' => 1024, + 'referral_percent' => 0.2, + 'referral_money' => 100, + 'referral_status' => 1, + 'default_traffic' => 1024, 'traffic_warning_percent' => 80, - 'expire_days' => 15, - 'reset_traffic' => 1, - 'default_days' => 7, - 'subscribe_max' => 3, - 'min_port' => 10000, - 'max_port' => 65535, - 'is_traffic_ban' => 1, - 'traffic_ban_value' => 10, - 'traffic_ban_time' => 60, - 'is_clear_log' => 1, - 'is_subscribe_ban' => 1, - 'subscribe_ban_times' => 20, - 'auto_release_port' => 1, - 'register_ip_limit' => 5, - 'detection_check_times' => 3, - 'alipay_transport' => 'http', - 'alipay_currency' => 'USD', - 'user_invite_days' => 7, - 'admin_invite_days' => 7, + 'expire_days' => 15, + 'reset_traffic' => 1, + 'default_days' => 7, + 'subscribe_max' => 3, + 'min_port' => 10000, + 'max_port' => 65535, + 'is_traffic_ban' => 1, + 'traffic_ban_value' => 10, + 'traffic_ban_time' => 60, + 'is_clear_log' => 1, + 'is_subscribe_ban' => 1, + 'subscribe_ban_times' => 20, + 'auto_release_port' => 1, + 'register_ip_limit' => 5, + 'detection_check_times' => 3, + 'alipay_transport' => 'http', + 'alipay_currency' => 'USD', + 'user_invite_days' => 7, + 'admin_invite_days' => 7, ]; foreach ($presetDates as $key => $value) { Config::find($key)->update(['value' => $value]); } + // 生成最初的等级 + Level::insert(['level' => 0, 'name' => 'Free']); + for ($i = 1; $i < 8; $i++) { + Level::insert(['level' => $i, 'name' => 'VIP-'.$i]); + } + + // ss系列 加密方式 + SsConfig::insert(['name' => 'none', 'type' => 1, 'is_default' => 1]); + SsConfig::insert(['name' => 'rc4-md5']); + SsConfig::insert(['name' => 'aes-128-cfb']); + SsConfig::insert(['name' => 'aes-192-cfb']); + SsConfig::insert(['name' => 'aes-256-cfb']); + SsConfig::insert(['name' => 'aes-128-ctr']); + SsConfig::insert(['name' => 'aes-192-ctr']); + SsConfig::insert(['name' => 'aes-256-ctr']); + SsConfig::insert(['name' => 'aes-128-gcm']); + SsConfig::insert(['name' => 'aes-192-gcm']); + SsConfig::insert(['name' => 'aes-256-gcm']); + SsConfig::insert(['name' => 'bf-cfb']); + SsConfig::insert(['name' => 'cast5-cfb']); + SsConfig::insert(['name' => 'des-cfb']); + SsConfig::insert(['name' => 'salsa20']); + SsConfig::insert(['name' => 'chacha20']); + SsConfig::insert(['name' => 'chacha20-ietf']); + SsConfig::insert(['name' => 'chacha20-ietf-poly1305']); + + // ss系列 协议 + SsConfig::insert(['name' => 'origin', 'type' => 2, 'is_default' => 1]); + SsConfig::insert(['name' => 'auth_sha1_v4', 'type' => 2]); + SsConfig::insert(['name' => 'auth_aes128_md5', 'type' => 2]); + SsConfig::insert(['name' => 'auth_aes128_sha1', 'type' => 2]); + SsConfig::insert(['name' => 'auth_chain_a', 'type' => 2]); + SsConfig::insert(['name' => 'auth_chain_b', 'type' => 2]); + SsConfig::insert(['name' => 'auth_chain_c', 'type' => 2]); + SsConfig::insert(['name' => 'auth_chain_d', 'type' => 2]); + SsConfig::insert(['name' => 'auth_chain_e', 'type' => 2]); + SsConfig::insert(['name' => 'auth_chain_f', 'type' => 2]); + + // ss系列 混淆 + SsConfig::insert(['name' => 'plain', 'type' => 3, 'is_default' => 1]); + SsConfig::insert(['name' => 'http_simple', 'type' => 3]); + SsConfig::insert(['name' => 'http_post', 'type' => 3]); + SsConfig::insert(['name' => 'tls1.2_ticket_auth', 'type' => 3]); + SsConfig::insert(['name' => 'tls1.2_ticket_fastauth', 'type' => 3]); + // 节点用标签 $labelList = [ 'Netflix', @@ -499,39 +489,32 @@ class PresetData extends Migration // 审核规则 $ruleList = [ - '360' => '(.*.||)(^360|0360|1360|3600|360safe|^so|qhimg|qhmsg|^yunpan|qihoo|qhcdn|qhupdate|360totalsecurity|360shouji|qihucdn|360kan|secmp).(cn|com|net)', - '腾讯管家' => '(.guanjia.qq.com|qqpcmgr|QQPCMGR)', - '金山毒霸' => '(.*.||)(rising|kingsoft|duba|xindubawukong|jinshanduba).(com|net|org)', - '暗网相关' => '(.*.||)(netvigator|torproject).(cn|com|net|org)', - '百度定位' => '(api|ps|sv|offnavi|newvector|ulog.imap|newloc|tracknavi)(.map|).(baidu|n.shifen).com', - '法轮功类' => '(.*.||)(dafahao|minghui|dongtaiwang|dajiyuan|falundata|shenyun|tuidang|epochweekly|epochtimes|ntdtv|falundafa|wujieliulan|zhengjian).(org|com|net)', - 'BT扩展名' => '(torrent|.torrent|peer_id=|info_hash|get_peers|find_node|BitTorrent|announce_peer|announce.php?passkey=)', - '邮件滥发' => '((^.*@)(guerrillamail|guerrillamailblock|sharklasers|grr|pokemail|spam4|bccto|chacuo|027168).(info|biz|com|de|net|org|me|la)|Subject|HELO|SMTP)', - '迅雷下载' => '(.?)(xunlei|sandai|Thunder|XLLiveUD)(.)', - '大陆应用' => '(.*.||)(baidu|qq|163|189|10000|10010|10086|sohu|sogoucdn|sogou|uc|58|taobao|qpic|bilibili|hdslb|acgvideo|sina|douban|doubanio|xiaohongshu|sinaimg|weibo|xiaomi|youzanyun|meituan|dianping|biliapi|huawei|pinduoduo|cnzz).(org|com|net|cn)', - '大陆银行' => '(.*.||)(icbc|ccb|boc|bankcomm|abchina|cmbchina|psbc|cebbank|cmbc|pingan|spdb|citicbank|cib|hxb|bankofbeijing|hsbank|tccb|4001961200|bosc|hkbchina|njcb|nbcb|lj-bank|bjrcb|jsbchina|gzcb|cqcbank|czbank|hzbank|srcb|cbhb|cqrcb|grcbank|qdccb|bocd|hrbcb|jlbank|bankofdl|qlbchina|dongguanbank|cscb|hebbank|drcbank|zzbank|bsb|xmccb|hljrcc|jxnxs|gsrcu|fjnx|sxnxs|gx966888|gx966888|zj96596|hnnxs|ahrcu|shanxinj|hainanbank|scrcu|gdrcu|hbxh|ynrcc|lnrcc|nmgnxs|hebnx|jlnls|js96008|hnnx|sdnxs).(org|com|net|cn)', - '台湾银行' => '(.*.||)(firstbank|bot|cotabank|megabank|tcb-bank|landbank|hncb|bankchb|tbb|ktb|tcbbank|scsb|bop|sunnybank|kgibank|fubon|ctbcbank|cathaybk|eximbank|bok|ubot|feib|yuantabank|sinopac|esunbank|taishinbank|jihsunbank|entiebank|hwataibank|csc|skbank).(org|com|net|tw)', + '360' => '(.*.||)(^360|0360|1360|3600|360safe|^so|qhimg|qhmsg|^yunpan|qihoo|qhcdn|qhupdate|360totalsecurity|360shouji|qihucdn|360kan|secmp).(cn|com|net)', + '腾讯管家' => '(.guanjia.qq.com|qqpcmgr|QQPCMGR)', + '金山毒霸' => '(.*.||)(rising|kingsoft|duba|xindubawukong|jinshanduba).(com|net|org)', + '暗网相关' => '(.*.||)(netvigator|torproject).(cn|com|net|org)', + '百度定位' => '(api|ps|sv|offnavi|newvector|ulog.imap|newloc|tracknavi)(.map|).(baidu|n.shifen).com', + '法轮功类' => '(.*.||)(dafahao|minghui|dongtaiwang|dajiyuan|falundata|shenyun|tuidang|epochweekly|epochtimes|ntdtv|falundafa|wujieliulan|zhengjian).(org|com|net)', + 'BT扩展名' => '(torrent|.torrent|peer_id=|info_hash|get_peers|find_node|BitTorrent|announce_peer|announce.php?passkey=)', + '邮件滥发' => '((^.*@)(guerrillamail|guerrillamailblock|sharklasers|grr|pokemail|spam4|bccto|chacuo|027168).(info|biz|com|de|net|org|me|la)|Subject|HELO|SMTP)', + '迅雷下载' => '(.?)(xunlei|sandai|Thunder|XLLiveUD)(.)', + '大陆应用' => '(.*.||)(baidu|qq|163|189|10000|10010|10086|sohu|sogoucdn|sogou|uc|58|taobao|qpic|bilibili|hdslb|acgvideo|sina|douban|doubanio|xiaohongshu|sinaimg|weibo|xiaomi|youzanyun|meituan|dianping|biliapi|huawei|pinduoduo|cnzz).(org|com|net|cn)', + '大陆银行' => '(.*.||)(icbc|ccb|boc|bankcomm|abchina|cmbchina|psbc|cebbank|cmbc|pingan|spdb|citicbank|cib|hxb|bankofbeijing|hsbank|tccb|4001961200|bosc|hkbchina|njcb|nbcb|lj-bank|bjrcb|jsbchina|gzcb|cqcbank|czbank|hzbank|srcb|cbhb|cqrcb|grcbank|qdccb|bocd|hrbcb|jlbank|bankofdl|qlbchina|dongguanbank|cscb|hebbank|drcbank|zzbank|bsb|xmccb|hljrcc|jxnxs|gsrcu|fjnx|sxnxs|gx966888|gx966888|zj96596|hnnxs|ahrcu|shanxinj|hainanbank|scrcu|gdrcu|hbxh|ynrcc|lnrcc|nmgnxs|hebnx|jlnls|js96008|hnnx|sdnxs).(org|com|net|cn)', + '台湾银行' => '(.*.||)(firstbank|bot|cotabank|megabank|tcb-bank|landbank|hncb|bankchb|tbb|ktb|tcbbank|scsb|bop|sunnybank|kgibank|fubon|ctbcbank|cathaybk|eximbank|bok|ubot|feib|yuantabank|sinopac|esunbank|taishinbank|jihsunbank|entiebank|hwataibank|csc|skbank).(org|com|net|tw)', '大陆第三方支付' => '(.*.||)(alipay|baifubao|yeepay|99bill|95516|51credit|cmpay|tenpay|lakala|jdpay).(org|com|net|cn)', - '台湾特供' => '(.*.||)(visa|mycard|mastercard|gov|gash|beanfun|bank|line).(org|com|net|cn|tw|jp|kr)', - '涉政治类' => '(.*.||)(shenzhoufilm|secretchina|renminbao|aboluowang|mhradio|guangming|zhengwunet|soundofhope|yuanming|zhuichaguoji|fgmtv|xinsheng|shenyunperformingarts|epochweekly|tuidang|shenyun|falundata|bannedbook|pincong|rfi|mingjingnews|boxun|rfa|scmp|ogate|voachinese).(org|com|net|rocks|fr)', - '流媒体' => '(.*.||)(youtube|googlevideo|hulu|netflix|nflxvideo|akamai|nflximg|hbo|mtv|bbc|tvb).(org|club|com|net|tv)', - '测速类' => '(.*.||)(fast|speedtest).(org|com|net|cn)', - '外汇交易类' => '(.*.||)(metatrader4|metatrader5|mql5).(org|com|net)', + '台湾特供' => '(.*.||)(visa|mycard|mastercard|gov|gash|beanfun|bank|line).(org|com|net|cn|tw|jp|kr)', + '涉政治类' => '(.*.||)(shenzhoufilm|secretchina|renminbao|aboluowang|mhradio|guangming|zhengwunet|soundofhope|yuanming|zhuichaguoji|fgmtv|xinsheng|shenyunperformingarts|epochweekly|tuidang|shenyun|falundata|bannedbook|pincong|rfi|mingjingnews|boxun|rfa|scmp|ogate|voachinese).(org|com|net|rocks|fr)', + '流媒体' => '(.*.||)(youtube|googlevideo|hulu|netflix|nflxvideo|akamai|nflximg|hbo|mtv|bbc|tvb).(org|club|com|net|tv)', + '测速类' => '(.*.||)(fast|speedtest).(org|com|net|cn)', + '外汇交易类' => '(.*.||)(metatrader4|metatrader5|mql5).(org|com|net)', ]; foreach ($ruleList as $name => $pattern) { Rule::insert(['type' => 1, 'name' => $name, 'pattern' => $pattern]); } - } - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - echo 'plz run php artisan migrate:fresh'.PHP_EOL; - echo '请运行 php artisan migrate:fresh'.PHP_EOL; + // 生成初始管理账号 + $user = factory(User::class)->create(['username' => '管理员', 'email' => 'test@test.com', 'password' => '123456']); + $user->assignRole('Super Admin'); } } diff --git a/public/downloads/convert.json b/public/downloads/convert.json deleted file mode 100644 index e69de29b..00000000 diff --git a/resources/views/admin/aff/detail.blade.php b/resources/views/admin/aff/detail.blade.php index 0897498e..7aa30f51 100644 --- a/resources/views/admin/aff/detail.blade.php +++ b/resources/views/admin/aff/detail.blade.php @@ -8,9 +8,9 @@

提现申请详情

- @if($basic->status === -1) + @if($referral->status === -1) 已驳回 - @elseif($basic->status === 2) + @elseif($referral->status === 2) 已打款 @endif 返 回 @@ -22,7 +22,7 @@ - 申请单ID:{{$basic->id}} | 申请人:{{$basic->user->email}} | 申请提现金额:¥{{$basic->amount}} | 申请时间:{{$basic->created_at}} + 申请单ID:{{$referral->id}} | 申请人:{{$referral->user->email}} | 申请提现金额:¥{{$referral->amount}} | 申请时间:{{$referral->created_at}} diff --git a/resources/views/admin/aff/index.blade.php b/resources/views/admin/aff/index.blade.php index 19a99ab5..265f4136 100644 --- a/resources/views/admin/aff/index.blade.php +++ b/resources/views/admin/aff/index.blade.php @@ -136,12 +136,31 @@ @can('admin.aff.setStatus') // 更改状态 function setStatus(id, status) { - $.post('{{route('admin.aff.setStatus')}}', {_token: '{{csrf_token()}}', id: id, status: status}, function(ret) { - if (ret.status === 'success') { - swal.fire({title: ret.message, icon: 'success', timer: 1000, showConfirmButton: false}).then(() => window.location.reload()); - } else { - swal.fire({title: ret.message, icon: 'error'}).then(() => window.location.reload()); - } + $.ajax({ + method: 'PUT', + url: '{{route('admin.aff.setStatus','')}}/' + id, + data: { + _token: '{{csrf_token()}}', + status: status, + }, + dataType: 'json', + success: function(ret) { + if (ret.status === 'success') { + swal.fire({title: ret.message, icon: 'success', timer: 1000, showConfirmButton: false}).then(() => window.location.reload()); + } else { + swal.fire({title: ret.message, icon: 'error'}).then(() => window.location.reload()); + } + }, + error: function(data) { + let str = ''; + const errors = data.responseJSON; + if ($.isEmptyObject(errors) === false) { + $.each(errors.errors, function(index, value) { + str += '
  • ' + value + '
  • '; + }); + swal.fire({title: '提示', html: str, icon: 'error', confirmButtonText: '{{trans('home.ticket_confirm')}}'}); + } + }, }); } @endcan diff --git a/resources/views/admin/aff/rebate.blade.php b/resources/views/admin/aff/rebate.blade.php index 7fd0a178..4276e91a 100644 --- a/resources/views/admin/aff/rebate.blade.php +++ b/resources/views/admin/aff/rebate.blade.php @@ -44,32 +44,32 @@ - @foreach($list as $vo) + @foreach($referralLogs as $referralLog) - {{$vo->id}} + {{$referralLog->id}} - @if(empty($vo->invitee)) + @if(empty($referralLog->invitee)) 【账号已删除】 @else - {{$vo->invitee->email}} + {{$referralLog->invitee->email}} @endif - @if(empty($vo->inviter)) + @if(empty($referralLog->inviter)) 【账号已删除】 @else - {{$vo->inviter->email}} + {{$referralLog->inviter->email}} @endif - {{$vo->order_id}} - {{$vo->amount}} - {{$vo->commission}} - {{$vo->created_at}} - {{$vo->updated_at}} + {{$referralLog->order_id}} + {{$referralLog->amount}} + {{$referralLog->commission}} + {{$referralLog->created_at}} + {{$referralLog->updated_at}} - @if ($vo->status === 1) + @if ($referralLog->status === 1) 申请中 - @elseif($vo->status === 2) + @elseif($referralLog->status === 2) 已提现 @else 未提现 @@ -83,11 +83,11 @@ +
    diff --git a/resources/views/admin/logs/callback.blade.php b/resources/views/admin/logs/callback.blade.php index 568f2bc8..200ab4eb 100644 --- a/resources/views/admin/logs/callback.blade.php +++ b/resources/views/admin/logs/callback.blade.php @@ -55,21 +55,21 @@ - @foreach($list as $vo) + @foreach($callbackLogs as $log) - {{$vo->id}} - {{$vo->type_label}} - {{$vo->trade_no}} + {{$log->id}} + {{$log->type_label}} + {{$log->trade_no}} @can('admin.order') - {{$vo->out_trade_no}} + {{$log->out_trade_no}} @else - {{$vo->out_trade_no}} + {{$log->out_trade_no}} @endcan - {{$vo->amount}}元 - {!! $vo->trade_status_label !!} - {{$vo->created_at}} + {{$log->amount}}元 + {!! $log->trade_status_label !!} + {{$log->created_at}} @endforeach @@ -78,11 +78,11 @@