diff --git a/app/Components/Client/Text.php b/app/Components/Client/Text.php new file mode 100644 index 00000000..dc6fa065 --- /dev/null +++ b/app/Components/Client/Text.php @@ -0,0 +1,26 @@ +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', [ 'referral' => $aff->load('user:id,email'), - 'commissions' => $commissions ?? null, + 'commissions' => $aff->referral_logs()->with(['invitee:id,email', 'order.goods:id,name'])->paginate()->appends($request->except('page')), ]); } diff --git a/app/Http/Controllers/Admin/ArticleController.php b/app/Http/Controllers/Admin/ArticleController.php index daacfffd..29c14173 100644 --- a/app/Http/Controllers/Admin/ArticleController.php +++ b/app/Http/Controllers/Admin/ArticleController.php @@ -8,6 +8,7 @@ use App\Models\Article; use Exception; use Illuminate\Http\UploadedFile; use Log; +use Str; class ArticleController extends Controller { diff --git a/app/Http/Controllers/Admin/CertController.php b/app/Http/Controllers/Admin/CertController.php index 69589af2..ef75cf0b 100644 --- a/app/Http/Controllers/Admin/CertController.php +++ b/app/Http/Controllers/Admin/CertController.php @@ -13,7 +13,7 @@ class CertController extends Controller // 域名证书列表 public function index() { - $certs = NodeCertificate::orderBy('id')->paginate(15)->appends(request('page')); + $certs = NodeCertificate::orderBy('id')->paginate()->appends(request('page')); foreach ($certs as $cert) { if ($cert->pem) { $certInfo = openssl_x509_parse($cert->pem); @@ -63,14 +63,14 @@ class CertController extends Controller { try { if ($cert->delete()) { - return response()->json(['status' => 'success', 'message' => '操作成功']); + 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/CountryController.php b/app/Http/Controllers/Admin/Config/CountryController.php index bd76a681..e00b115d 100644 --- a/app/Http/Controllers/Admin/Config/CountryController.php +++ b/app/Http/Controllers/Admin/Config/CountryController.php @@ -4,67 +4,44 @@ namespace App\Http\Controllers\Admin\Config; use App\Http\Controllers\Controller; use App\Models\Country; -use App\Models\Node; use Exception; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; use Response; +use Validator; class CountryController extends Controller { // 添加国家/地区 - public function store(Request $request): JsonResponse + public function store(Request $request) { - $code = $request->input('code'); - $name = $request->input('name'); + $validator = Validator::make($request->all(), [ + 'code' => 'required|string|unique:country,code', + 'name' => 'required', + ]); - if (empty($code)) { - return Response::json(['status' => 'fail', 'message' => '国家/地区代码不能为空']); + if ($validator->fails()) { + return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); } - if (empty($name)) { - return Response::json(['status' => 'fail', 'message' => '国家/地区名称不能为空']); + if (Country::create($validator->validated())) { + return Response::json(['status' => 'success', 'message' => '生成成功']); } - $exists = Country::find($code); - if ($exists) { - return Response::json(['status' => 'fail', 'message' => '该国家/地区名称已存在,请勿重复添加']); - } - - $obj = new Country(); - $obj->code = $code; - $obj->name = $name; - - if ($obj->save()) { - return Response::json(['status' => 'success', 'message' => '提交成功']); - } - - return Response::json(['status' => 'fail', 'message' => '操作失败']); + return Response::json(['status' => 'fail', 'message' => '生成失败']); } // 编辑国家/地区 - public function update(Request $request, $code): JsonResponse + public function update(Request $request, Country $country) { - $name = $request->input('name'); + $validator = Validator::make($request->all(), ['name' => 'required']); - if (empty($name)) { - return Response::json(['status' => 'fail', 'message' => '国家/地区名称不能为空']); - } - - $country = Country::find($code); - if (! $country) { - return Response::json(['status' => 'fail', 'message' => '国家/地区不存在']); - } - - // 校验该国家/地区下是否存在关联节点 - if (Node::whereCountryCode($country->code)->exists()) { - return Response::json(['status' => 'fail', 'message' => '该国家/地区下存在关联节点,请先取消关联']); + if ($validator->fails()) { + return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); } try { - $country->name = $name; - if ($country->save()) { + if ($country->update($validator->validated())) { return Response::json(['status' => 'success', 'message' => '编辑成功']); } } catch (Exception $e) { @@ -77,15 +54,10 @@ class CountryController extends Controller } // 删除国家/地区 - public function destroy($code): ?JsonResponse + public function destroy(Country $country) { - $country = Country::find($code); - if (! $country) { - return Response::json(['status' => 'fail', 'message' => '国家/地区不存在']); - } - // 校验该国家/地区下是否存在关联节点 - if (Node::whereCountryCode($country->code)->exists()) { + if ($country->nodes()->exists()) { 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 63c42fb0..78bbe252 100644 --- a/app/Http/Controllers/Admin/Config/EmailFilterController.php +++ b/app/Http/Controllers/Admin/Config/EmailFilterController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers\Admin\Config; use App\Http\Controllers\Controller; use App\Models\EmailFilter; use Exception; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; use Response; @@ -16,13 +15,14 @@ class EmailFilterController extends Controller // 邮箱过滤列表 public function index() { - return view('admin.config.emailFilter', ['list' => EmailFilter::orderByDesc('id')->paginate()]); + return view('admin.config.emailFilter', ['filters' => EmailFilter::orderByDesc('id')->paginate()]); } // 添加邮箱后缀 - public function store(Request $request): JsonResponse + public function store(Request $request) { $validator = Validator::make($request->all(), [ + 'type' => 'required|numeric|between:1,2', 'words' => 'required|unique:email_filter', ]); @@ -31,11 +31,7 @@ class EmailFilterController extends Controller } try { - $obj = new EmailFilter(); - $obj->type = $request->input('type'); - $obj->words = strtolower($request->input('words')); - - if ($obj->save()) { + if (EmailFilter::create($validator->validated())) { return Response::json(['status' => 'success', 'message' => '添加成功']); } } catch (Exception $e) { @@ -48,11 +44,10 @@ class EmailFilterController extends Controller } // 删除邮箱后缀 - public function destroy($id): JsonResponse + public function destroy(EmailFilter $filter) { try { - $result = EmailFilter::whereId($id)->delete(); - if ($result) { + if ($filter->delete()) { return Response::json(['status' => 'success', 'message' => '删除成功']); } } catch (Exception $e) { diff --git a/app/Http/Controllers/Admin/Config/LabelController.php b/app/Http/Controllers/Admin/Config/LabelController.php index 6590088b..aed7af0d 100644 --- a/app/Http/Controllers/Admin/Config/LabelController.php +++ b/app/Http/Controllers/Admin/Config/LabelController.php @@ -5,21 +5,26 @@ namespace App\Http\Controllers\Admin\Config; use App\Http\Controllers\Controller; use App\Models\Label; use Exception; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; use Response; +use Validator; class LabelController extends Controller { // 添加标签 - public function store(Request $request): JsonResponse + public function store(Request $request) { - $label = new Label(); - $label->name = $request->input('name'); - $label->sort = $request->input('sort'); + $validator = Validator::make($request->all(), [ + 'name' => 'required|string|unique:label,name', + 'sort' => 'required|numeric', + ]); - if ($label->save()) { + if ($validator->fails()) { + return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); + } + + if (Label::create($validator->validated())) { return Response::json(['status' => 'success', 'message' => '添加成功']); } @@ -27,9 +32,18 @@ class LabelController extends Controller } // 编辑标签 - public function update(Request $request, Label $label): JsonResponse + public function update(Request $request, Label $label) { - if ($label->update(['name' => $request->input('name'), 'sort' => $request->input('sort')])) { + $validator = Validator::make($request->all(), [ + 'name' => 'required|string|unique:label,name,'.$label->id, + 'sort' => 'required|numeric', + ]); + + if ($validator->fails()) { + return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); + } + + if ($label->update($validator->validated())) { return Response::json(['status' => 'success', 'message' => '编辑成功']); } @@ -37,7 +51,7 @@ class LabelController extends Controller } // 删除标签 - public function destroy(Label $label): ?JsonResponse + public function destroy(Label $label) { try { $label->delete(); diff --git a/app/Http/Controllers/Admin/Config/LevelController.php b/app/Http/Controllers/Admin/Config/LevelController.php index ff6ab87b..c4aa2921 100644 --- a/app/Http/Controllers/Admin/Config/LevelController.php +++ b/app/Http/Controllers/Admin/Config/LevelController.php @@ -4,9 +4,7 @@ namespace App\Http\Controllers\Admin\Config; use App\Http\Controllers\Controller; use App\Models\Level; -use App\Models\User; use Exception; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; use Response; @@ -15,23 +13,18 @@ use Validator; class LevelController extends Controller { // 添加等级 - public function store(Request $request): JsonResponse + public function store(Request $request) { $validator = Validator::make($request->all(), [ 'level' => 'required|numeric|unique:level,level', - 'level_name' => 'required', + 'name' => 'required', ]); if ($validator->fails()) { return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); } - $obj = new Level(); - $obj->level = $request->input('level'); - $obj->name = $request->input('level_name'); - $obj->save(); - - if ($obj->id) { + if (Level::create($validator->validated())) { return Response::json(['status' => 'success', 'message' => '提交成功']); } @@ -39,48 +32,34 @@ class LevelController extends Controller } // 编辑等级 - public function update(Request $request, $id): JsonResponse + public function update(Request $request, Level $level) { - $level = $request->input('level'); - $validator = Validator::make($request->all(), [ - 'level' => 'required|numeric', - 'level_name' => 'required', + 'level' => 'required|numeric|unique:level,level,'.$level->id, + 'name' => 'required', ]); if ($validator->fails()) { return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); } - // 校验该等级下是否存在关联账号 - $levelCheck = Level::where('id', '<>', $id)->whereLevel($level)->exists(); - if ($levelCheck) { - return Response::json(['status' => 'fail', 'message' => '该等级已存在!']); + + if ($level->update($validator->validated())) { + return Response::json(['status' => 'success', 'message' => '操作成功']); } - // 校验该等级下是否存在关联账号 - $userCount = User::whereLevel($level)->count(); - if ($userCount) { - return Response::json(['status' => 'fail', 'message' => '该等级下存在关联账号,请先取消关联!']); - } - - Level::whereId($id)->update(['level' => $level, 'name' => $request->input('level_name')]); - - return Response::json(['status' => 'success', 'message' => '操作成功']); + return Response::json(['status' => 'fail', 'message' => '操作失败']); } // 删除等级 - public function destroy($id): JsonResponse + public function destroy(Level $level) { - $level = Level::find($id); - // 校验该等级下是否存在关联账号 - $userCount = User::whereLevel($level->level)->count(); - if ($userCount) { + if ($level->users()->exists()) { return Response::json(['status' => 'fail', 'message' => '该等级下存在关联账号,请先取消关联']); } try { - if (Level::whereId($id)->delete()) { + if ($level->delete()) { return Response::json(['status' => 'success', 'message' => '删除成功']); } } catch (Exception $e) { diff --git a/app/Http/Controllers/Admin/Config/SsConfigController.php b/app/Http/Controllers/Admin/Config/SsConfigController.php index e0541588..fb6e8d03 100644 --- a/app/Http/Controllers/Admin/Config/SsConfigController.php +++ b/app/Http/Controllers/Admin/Config/SsConfigController.php @@ -5,67 +5,49 @@ namespace App\Http\Controllers\Admin\Config; use App\Http\Controllers\Controller; use App\Models\SsConfig; use Exception; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; use Response; +use Validator; class SsConfigController extends Controller { // 添加SS配置 - public function store(Request $request): JsonResponse + public function store(Request $request) { - $name = $request->input('name'); - $type = $request->input('type', 1); // 类型:1-加密方式(method)、2-协议(protocol)、3-混淆(obfs) - $is_default = $request->input('is_default', 0); - $sort = $request->input('sort', 0); + $validator = Validator::make($request->all(), [ + 'name' => 'required|string|unique:ss_config,name', + 'type' => 'required|numeric|between:1,3', + ]); - if (empty($name)) { - return Response::json(['status' => 'fail', 'message' => '配置名称不能为空']); + if ($validator->fails()) { + return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); } - // 校验是否已存在 - $config = SsConfig::type($type)->whereName($name)->first(); - if ($config) { - return Response::json(['status' => 'fail', 'message' => '配置已经存在,请勿重复添加']); + if (SsConfig::create($validator->validated())) { + return Response::json(['status' => 'success', 'message' => '添加成功']); } - $ssConfig = new SsConfig(); - $ssConfig->name = $name; - $ssConfig->type = $type; - $ssConfig->is_default = $is_default; - $ssConfig->sort = $sort; - $ssConfig->save(); - - return Response::json(['status' => 'success', 'message' => '添加成功']); + return Response::json(['status' => 'fail', 'message' => '添加失败']); } // 设置SS默认配置 - public function update($id): JsonResponse + public function update(SsConfig $ss) { - if (empty($id)) { - return Response::json(['status' => 'fail', 'message' => '非法请求']); - } - - $config = SsConfig::find($id); - if (! $config) { - return Response::json(['status' => 'fail', 'message' => '配置不存在']); - } - // 去除该配置所属类型的默认值 - SsConfig::default()->type($config->type)->update(['is_default' => 0]); + SsConfig::default()->type($ss->type)->update(['is_default' => 0]); // 将该ID对应记录值置为默认值 - SsConfig::whereId($id)->update(['is_default' => 1]); + $ss->update(['is_default' => 1]); return Response::json(['status' => 'success', 'message' => '操作成功']); } // 删除SS配置 - public function destroy($id): JsonResponse + public function destroy(SsConfig $ss) { try { - if (SsConfig::whereId($id)->delete()) { + if ($ss->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 d63dc22b..8c67eaa7 100644 --- a/app/Http/Controllers/Admin/CouponController.php +++ b/app/Http/Controllers/Admin/CouponController.php @@ -15,11 +15,6 @@ use Redirect; use Response; use Str; -/** - * 优惠券控制器. - * - * Class CouponController - */ class CouponController extends Controller { // 优惠券列表 @@ -67,11 +62,10 @@ class CouponController extends Controller } $logo = 'upload/'.$fileName; } + $num = (int) $request->input('num'); + $data = $request->only(['name', 'type', 'usable_times', 'value', 'rule', 'start_time', 'end_time']); + $data['logo'] = $logo; 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++) { $data['sn'] = $num === 1 && $request->input('sn') ? $request->input('sn') : Str::random(8); Coupon::create($data); diff --git a/app/Http/Controllers/Admin/LogsController.php b/app/Http/Controllers/Admin/LogsController.php index c58fa991..7c64eebe 100644 --- a/app/Http/Controllers/Admin/LogsController.php +++ b/app/Http/Controllers/Admin/LogsController.php @@ -286,8 +286,9 @@ class LogsController extends Controller $nodeOnlineIPs = NodeOnlineIp::with('node:id,name')->where('created_at', '>=', strtotime('-10 minutes'))->latest()->distinct()->get(); foreach ($userList as $user) { + //Todo node_online_ip表 api可以用user_id // 最近5条在线IP记录,如果后端设置为60秒上报一次,则为10分钟内的在线IP - $user->onlineIPList = $nodeOnlineIPs->where('port', '==', $user->port)->chunk(5); + $user->onlineIPList = $nodeOnlineIPs->where('port', $user->port)->chunk(5); } return view('admin.logs.userOnlineIP', ['userList' => $userList]); diff --git a/app/Http/Controllers/Admin/MarketingController.php b/app/Http/Controllers/Admin/MarketingController.php index e6eeb091..46437b37 100644 --- a/app/Http/Controllers/Admin/MarketingController.php +++ b/app/Http/Controllers/Admin/MarketingController.php @@ -7,17 +7,11 @@ use App\Models\Marketing; use DB; use Exception; use Http; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; use Response; use RuntimeException; -/** - * 促销控制器. - * - * Class MarketingController - */ class MarketingController extends Controller { // 邮件群发消息列表 @@ -49,7 +43,7 @@ class MarketingController extends Controller } // 添加推送消息 - public function addPushMarketing(Request $request): ?JsonResponse + public function addPushMarketing(Request $request) { $title = $request->input('title'); $content = $request->input('content'); @@ -74,7 +68,7 @@ class MarketingController extends Controller throw new RuntimeException($message['message']); } - $this->addMarketing(2, $title, $content, 1); + $this->addMarketing(2, $title, $content); DB::commit(); diff --git a/app/Http/Controllers/Admin/NodeAuthController.php b/app/Http/Controllers/Admin/NodeAuthController.php index 60ec4590..b239a7b9 100644 --- a/app/Http/Controllers/Admin/NodeAuthController.php +++ b/app/Http/Controllers/Admin/NodeAuthController.php @@ -3,9 +3,11 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Models\Node; use App\Models\NodeAuth; use Exception; -use Illuminate\Http\Request; +use Response; +use Str; class NodeAuthController extends Controller { @@ -16,24 +18,16 @@ class NodeAuthController extends Controller } // 添加节点授权 - public function store(Request $request) + public function store() { - $nodeArray = Node::whereStatus(1)->orderBy('id')->pluck('id')->toArray(); - $authArray = NodeAuth::orderBy('node_id')->pluck('node_id')->toArray(); + $nodes = Node::whereStatus(1)->doesntHave('auth')->orderBy('id')->get(); - $arrayDifferent = array_diff($nodeArray, $authArray); - - if (empty($arrayDifferent)) { + if ($nodes->isEmpty()) { 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(); - } + $nodes->each(static function ($node) { + $node->auth()->create(['key' => Str::random(), 'secret' => Str::random(8)]); + }); return Response::json(['status' => 'success', 'message' => '生成成功']); } diff --git a/app/Http/Controllers/Admin/NodeController.php b/app/Http/Controllers/Admin/NodeController.php index b58841d7..d59055a2 100644 --- a/app/Http/Controllers/Admin/NodeController.php +++ b/app/Http/Controllers/Admin/NodeController.php @@ -68,12 +68,10 @@ class NodeController extends Controller // 添加节点 public function store(NodeRequest $request): JsonResponse { + $array = $request->validated(); + Arr::forget($array, ['labels']); try { - $array = $request->validated(); - Arr::forget($array, ['labels']); - $node = Node::create($array); - - if ($node) { + if ($node = Node::create($array)) { // 生成节点标签 if ($request->has('labels')) { $node->labels()->attach($request->input('labels')); diff --git a/app/Http/Controllers/Admin/RoleController.php b/app/Http/Controllers/Admin/RoleController.php index 48a634bc..7732126d 100644 --- a/app/Http/Controllers/Admin/RoleController.php +++ b/app/Http/Controllers/Admin/RoleController.php @@ -23,7 +23,7 @@ class RoleController extends Controller public function store(RoleRequest $request) { if ($role = Role::create($request->only(['name', 'description']))) { - $role->givePermissionTo($request->input('permissions') ?: []); + $role->givePermissionTo($request->input('permissions') ?? []); return redirect()->route('admin.role.edit', $role)->with('successMsg', '操作成功'); } diff --git a/app/Http/Controllers/Admin/ShopController.php b/app/Http/Controllers/Admin/ShopController.php index aab774c7..1821764b 100644 --- a/app/Http/Controllers/Admin/ShopController.php +++ b/app/Http/Controllers/Admin/ShopController.php @@ -48,25 +48,24 @@ class ShopController extends Controller // 添加商品 public function store(ShopStoreRequest $request): RedirectResponse { + $data = $request->validated(); + if (array_key_exists('traffic_unit', $data)) { + $data['traffic'] *= $data['traffic_unit']; + Arr::forget($data, 'traffic_unit'); + } + $data['is_hot'] = array_key_exists('is_hot', $data) ? 1 : 0; + $data['status'] = array_key_exists('status', $data) ? 1 : 0; + + // 商品LOGO + if ($request->hasFile('logo')) { + $path = $this->fileUpload($request->file('logo')); + if (is_string($path)) { + $data['logo'] = $path; + } else { + return $path; + } + } try { - $data = $request->validated(); - if (array_key_exists('traffic_unit', $data)) { - $data['traffic'] *= $data['traffic_unit']; - Arr::forget($data, 'traffic_unit'); - } - $data['is_hot'] = array_key_exists('is_hot', $data) ? 1 : 0; - $data['status'] = array_key_exists('status', $data) ? 1 : 0; - - // 商品LOGO - if ($request->hasFile('logo')) { - $path = $this->fileUpload($request->file('logo')); - if (is_string($path)) { - $data['logo'] = $path; - } else { - return $path; - } - } - if ($good = Goods::create($data)) { return Redirect::route('admin.goods.edit', $good)->with('successMsg', '添加成功'); } diff --git a/app/Http/Controllers/Admin/SystemController.php b/app/Http/Controllers/Admin/SystemController.php index c82d09e5..45040a56 100644 --- a/app/Http/Controllers/Admin/SystemController.php +++ b/app/Http/Controllers/Admin/SystemController.php @@ -44,7 +44,7 @@ class SystemController extends Controller } $file = $request->file('website_logo'); $ret = $file->move('uploads/logo', $file->getClientOriginalName()); - if ($ret && Config::find('website_logo')->update(['value' => 'uploads/logo/'.$file->getClientOriginalName()])) { + if ($ret && Config::findOrFail('website_logo')->update(['value' => 'uploads/logo/'.$file->getClientOriginalName()])) { return redirect()->route('admin.system.index', '#other')->with('successMsg', '更新成功'); } } diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index a234ca92..cec7281c 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -137,22 +137,22 @@ class UserController extends Controller // 添加账号 public function store(UserStoreRequest $request): JsonResponse { - try { - $data = $request->validated(); - Arr::forget($data, 'roles'); - $data['password'] = $data['password'] ?? Str::random(); - $data['port'] = $data['port'] ?? Helpers::getPort(); - $data['passwd'] = $data['passwd'] ?? Str::random(); - $data['vmess_id'] = $data['uuid'] ?? Str::uuid(); - Arr::forget($data, 'uuid'); - $data['transfer_enable'] *= GB; - $data['expired_at'] = $data['expired_at'] ?? date('Y-m-d', strtotime('+365 days')); - $data['remark'] = str_replace(['atob', 'eval'], '', $data['remark']); - $data['reg_ip'] = IP::getClientIp(); - $data['reset_time'] = $data['reset_time'] > date('Y-m-d') ? $data['reset_time'] : null; - $user = User::create($data); + $data = $request->validated(); + Arr::forget($data, 'roles'); + $data['password'] = $data['password'] ?? Str::random(); + $data['port'] = $data['port'] ?? Helpers::getPort(); + $data['passwd'] = $data['passwd'] ?? Str::random(); + $data['vmess_id'] = $data['uuid'] ?? Str::uuid(); + Arr::forget($data, 'uuid'); + $data['transfer_enable'] *= GB; + $data['expired_at'] = $data['expired_at'] ?? date('Y-m-d', strtotime('+365 days')); + $data['remark'] = str_replace(['atob', 'eval'], '', $data['remark']); + $data['reg_ip'] = IP::getClientIp(); + $data['reset_time'] = $data['reset_time'] > date('Y-m-d') ? $data['reset_time'] : null; + $user = User::create($data); - $roles = $request->input('roles'); + $roles = $request->input('roles'); + try { if ($roles && (Auth::getUser()->hasPermissionTo('give roles') || (in_array('Super Admin', $roles, true) && Auth::getUser()->hasRole('Super Admin')) || Auth::getUser()->hasRole('Super Admin'))) { $user->assignRole($roles); @@ -193,20 +193,19 @@ class UserController extends Controller // 编辑账号 public function update(UserUpdateRequest $request, User $user) { + $data = $request->validated(); + Arr::forget($data, 'roles'); + $data['passwd'] = $request->input('passwd') ?? Str::random(); + $data['vmess_id'] = $data['uuid'] ?? Str::uuid(); + Arr::forget($data, 'uuid'); + $data['transfer_enable'] *= GB; + $data['enable'] = $data['status'] < 0 ? 0 : $data['enable']; + $data['expired_at'] = $data['expired_at'] ?? date('Y-m-d', strtotime('+365 days')); + $data['remark'] = str_replace(['atob', 'eval'], '', $data['remark']); + + // 只有超级管理员才能赋予超级管理员 + $roles = $request->input('roles'); try { - $data = $request->validated(); - Arr::forget($data, 'roles'); - $data['passwd'] = $request->input('passwd') ?? Str::random(); - $data['vmess_id'] = $data['uuid'] ?? Str::uuid(); - Arr::forget($data, 'uuid'); - $data['transfer_enable'] *= GB; - $data['enable'] = $data['status'] < 0 ? 0 : $data['enable']; - $data['expired_at'] = $data['expired_at'] ?? date('Y-m-d', strtotime('+365 days')); - $data['remark'] = str_replace(['atob', 'eval'], '', $data['remark']); - - // 只有超级管理员才能赋予超级管理员 - $roles = $request->input('roles'); - if ($roles && (Auth::getUser()->hasPermissionTo('give roles') || (in_array('Super Admin', $roles, true) && Auth::getUser()->hasRole('Super Admin')) || Auth::getUser()->hasRole('Super Admin'))) { $user->syncRoles($roles); @@ -332,19 +331,8 @@ class UserController extends Controller public function exportProxyConfig(Request $request, User $user): JsonResponse { - $node = Node::find($request->input('id')); - if ($node->type === 1) { - if ($node->compatible) { - $proxyType = 'SS'; - } else { - $proxyType = 'SSR'; - } - } else { - $proxyType = 'V2Ray'; - } + $server = Node::findOrFail($request->input('id'))->config($user); // 提取节点信息 - $data = $this->getUserNodeInfo($user->id, $node->id, $request->input('type') !== 'text' ? 0 : 1); - - return Response::json(['status' => 'success', 'data' => $data, 'title' => $proxyType]); + return Response::json(['status' => 'success', 'data' => $this->getUserNodeInfo($server, $request->input('type') !== 'text'), 'title' => $server['type']]); } } diff --git a/app/Http/Controllers/Api/Client/V1Controller.php b/app/Http/Controllers/Api/Client/V1Controller.php index adab40e7..8a0359b6 100644 --- a/app/Http/Controllers/Api/Client/V1Controller.php +++ b/app/Http/Controllers/Api/Client/V1Controller.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api\Client; use App\Http\Controllers\Controller; use App\Models\Goods; +use App\Models\User; use Illuminate\Http\Request; use Validator; @@ -26,11 +27,11 @@ class V1Controller extends Controller return response()->json(['ret' => 0, 'msg' => $validator->errors()->all()], 422); } - if (! $token = auth()->attempt($validator->validated())) { - return response()->json(['ret' => 0, 'msg' => '登录信息错误'], 401); + if ($token = auth()->attempt($validator->validated())) { + return $this->createNewToken($token); } - return $this->createNewToken($token); + return response()->json(['ret' => 0, 'msg' => '登录信息错误'], 401); } protected function createNewToken($token) diff --git a/app/Http/Controllers/Api/WebApi/BaseController.php b/app/Http/Controllers/Api/WebApi/BaseController.php index 8a6f9398..707ccaa8 100644 --- a/app/Http/Controllers/Api/WebApi/BaseController.php +++ b/app/Http/Controllers/Api/WebApi/BaseController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api\WebApi; use App\Models\Node; +use App\Models\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Response; @@ -73,7 +74,7 @@ class BaseController $onlineCount = 0; foreach ($validator->validated() as $input) { // 处理节点在线IP数据 - $formattedData[] = ['user_id' => $input['uid'], 'ip' => $input['ip'], 'created_at' => time()]; + $formattedData[] = ['user_id' => $input['uid'], 'ip' => $input['ip'], 'port' => User::find($input['uid'])->port, 'created_at' => time()]; $onlineCount++; } diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php new file mode 100644 index 00000000..3b53e620 --- /dev/null +++ b/app/Http/Controllers/ClientController.php @@ -0,0 +1,225 @@ +quantumultX($user, $servers); + } + if (strpos($target, 'quantumult') !== false) { + return $this->quantumult($user, $servers); + } + if (strpos($target, 'clash') !== false) { + return $this->clash($servers); + } + if (strpos($target, 'surfboard') !== false) { + return $this->surfboard($user, $servers); + } + if (strpos($target, 'surge') !== false) { + return $this->surge($user, $servers); + } + if (strpos($target, 'shadowrocket') !== false) { + return $this->shadowrocket($user, $servers); + } +// if (strpos($target, 'shadowsocks') !== false) { +// exit($this->shaodowsocksSIP008($servers)); +// } + return $this->origin($servers); + } + + private function quantumultX(User $user, array $servers = []): string + { + $uri = ''; + if (sysConfig('is_custom_subscribe')) { + header("subscription-userinfo: upload={$user->u}; download={$user->d}; total={$user->transfer_enable}; expire={$user->expired_at}"); + } + foreach ($servers as $server) { + if ($server['type'] === 'shadowsocks') { + $uri .= QuantumultX::buildShadowsocks($server); + } + if ($server['type'] === 'shadowsocksr') { + $uri .= QuantumultX::buildShadowsocksr($server); + } + if ($server['type'] === 'v2ray') { + $uri .= QuantumultX::buildVmess($server); + } + if ($server['type'] === 'trojan') { + $uri .= QuantumultX::buildTrojan($server); + } + } + + return base64_encode($uri); + } + + private function quantumult(User $user, array $servers = []): string + { + if (sysConfig('is_custom_subscribe')) { + header("subscription-userinfo: upload={$user->u}; download={$user->d}; total={$user->transfer_enable}; expire={$user->expired_at}"); + } + + return $this->origin($servers); + } + + private function origin(array $servers = [], bool $encode = true): string + { + $uri = ''; + foreach ($servers as $server) { + if ($server['type'] === 'shadowsocks') { + $uri .= URLSchemes::buildShadowsocks($server); + } + if ($server['type'] === 'shadowsocksr') { + $uri .= URLSchemes::buildShadowsocksr($server); + } + if ($server['type'] === 'v2ray') { + $uri .= URLSchemes::buildVmess($server); + } + if ($server['type'] === 'trojan') { + $uri .= URLSchemes::buildTrojan($server); + } + } + + return $encode ? base64_encode($uri) : $uri; + } + + private function clash($servers) + { + $defaultConfig = base_path().'/resources/rules/default.clash.yaml'; + $customConfig = base_path().'/resources/rules/custom.clash.yaml'; + if (File::exists($customConfig)) { + $config = Yaml::parseFile($customConfig); + } else { + $config = Yaml::parseFile($defaultConfig); + } + + foreach ($servers as $server) { + if ($server['type'] === 'shadowsocks') { + $proxy[] = Clash::buildShadowsocks($server); + $proxies[] = $server['name']; + } + if ($server['type'] === 'shadowsocksr') { + $proxy[] = Clash::buildShadowsocksr($server); + $proxies[] = $server['name']; + } + if ($server['type'] === 'v2ray') { + $proxy[] = Clash::buildVmess($server); + $proxies[] = $server['name']; + } + if ($server['type'] === 'trojan') { + $proxy[] = Clash::buildTrojan($server); + $proxies[] = $server['name']; + } + } + + $config['proxies'] = array_merge($config['proxies'] ?: [], $proxy ?? []); + foreach ($config['proxy-groups'] as $k => $v) { + if (! is_array($config['proxy-groups'][$k]['proxies'])) { + continue; + } + $config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies ?? []); + } + + return str_replace('$app_name', sysConfig('website_name'), Yaml::dump($config)); + } + + private function surfboard(User $user, array $servers = []) + { + $proxies = ''; + $proxyGroup = ''; + + foreach ($servers as $server) { + if ($server['type'] === 'shadowsocks') { + $proxies .= Surfboard::buildShadowsocks($server); + $proxyGroup .= $server['name'].', '; + } + if ($server['type'] === 'v2ray') { + $proxies .= Surfboard::buildVmess($server); + $proxyGroup .= $server['name'].', '; + } + } + + $defaultConfig = base_path().'/resources/rules/default.surfboard.conf'; + $customConfig = base_path().'/resources/rules/custom.surfboard.conf'; + if (File::exists($customConfig)) { + $config = file_get_contents($customConfig); + } else { + $config = file_get_contents($defaultConfig); + } + + // Subscription link + $subsURL = route('sub', $user->subscribe->code); + + return str_replace(['$subs_link', '$proxies', '$proxy_group'], [$subsURL, $proxies, rtrim($proxyGroup, ', ')], $config); + } + + private function surge(User $user, array $servers = []) + { + $proxies = ''; + $proxyGroup = ''; + + foreach ($servers as $server) { + if ($server['type'] === 'shadowsocks') { + $proxies .= Surge::buildShadowsocks($server); + $proxyGroup .= $server['name'].', '; + } + if ($server['type'] === 'v2ray') { + $proxies .= Surge::buildVmess($server); + $proxyGroup .= $server['name'].', '; + } + if ($server['type'] === 'trojan') { + $proxies .= Surge::buildTrojan($server); + $proxyGroup .= $server['name'].', '; + } + } + + $defaultConfig = base_path().'/resources/rules/default.surge.conf'; + $customConfig = base_path().'/resources/rules/custom.surge.conf'; + if (File::exists($customConfig)) { + $config = file_get_contents($customConfig); + } else { + $config = file_get_contents($defaultConfig); + } + + // Subscription link + $subsURL = route('sub', $user->subscribe->code); + + return str_replace(['$subs_link', '$proxies', '$proxy_group'], [$subsURL, $proxies, rtrim($proxyGroup, ', ')], $config); + } + + private function shadowrocket(User $user, array $servers = []): string + { + //display remaining traffic and expire date + $uri = ''; + if (sysConfig('is_custom_subscribe')) { + $upload = flowAutoShow($user->u); + $download = flowAutoShow($user->d); + $totalTraffic = flowAutoShow($user->transfer_enable); + $uri = "STATUS=📤:{$upload}📥:{$download}⏳:{$totalTraffic}📅:{$user->expired_at}\r\n"; + } + $uri .= $this->origin($servers, false); + + return base64_encode($uri); + } + + private function shaodowsocksSIP008(array $servers = []): string + { + foreach ($servers as $server) { + if ($server['type'] === 'shadowsocks') { + $configs[] = URLSchemes::buildShadowsocksSIP008($server); + } + } + + return json_encode(['version' => 1, 'remark' => sysConfig('website_name'), 'servers' => $configs ?? []], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 5dc87b2d..bc831f6c 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,11 +2,10 @@ namespace App\Http\Controllers; -use App\Models\EmailFilter; -use App\Models\Node; +use App\Components\Client\Text; +use App\Components\Client\URLSchemes; use App\Models\NodeDailyDataFlow; use App\Models\NodeHourlyDataFlow; -use App\Models\User; use App\Models\UserDailyDataFlow; use App\Models\UserDataFlowLog; use App\Models\UserHourlyDataFlow; @@ -105,108 +104,26 @@ class Controller extends BaseController return ''; } - /** - * 节点信息. - * - * @param int $uid 用户ID - * @param int $nodeId 节点ID - * @param int $infoType 信息类型:0为链接,1为文字 - * - * @return string - */ - public function getUserNodeInfo(int $uid, int $nodeId, int $infoType): string + // 节点信息 + public function getUserNodeInfo(array $server, bool $is_url): ?string { - $user = User::find($uid); - $node = Node::find($nodeId); - $scheme = null; - $group = sysConfig('website_name'); // 分组名称 - $host = $node->is_relay ? $node->relay_server : ($node->server ?: $node->ip); - $data = null; - switch ($node->type) { - case 2: - // 生成v2ray scheme - if ($infoType !== 1) { - // 生成v2ray scheme - $data = $this->v2raySubUrl( - $node->name, - $host, - $node->v2_port, - $user->vmess_id, - $node->v2_alter_id, - $node->v2_net, - $node->v2_type, - $node->v2_host, - $node->v2_path, - $node->v2_tls ? 'tls' : '' - ); - } else { - $data = '服务器:'.$host.PHP_EOL.'IPv6:'.($node->ipv6 ?: '').PHP_EOL.'端口:'.$node->v2_port.PHP_EOL.'加密方式:'.$node->v2_method.PHP_EOL.'用户ID:'.$user->vmess_id.PHP_EOL.'额外ID:'.$node->v2_alter_id.PHP_EOL.'传输协议:'.$node->v2_net.PHP_EOL.'伪装类型:'.$node->v2_type.PHP_EOL.'伪装域名:'.($node->v2_host ?: '').PHP_EOL.'路径:'.($node->v2_path ?: '').PHP_EOL.'TLS:'.($node->v2_tls ? 'tls' : '').PHP_EOL; - } + switch ($server['type']) { + case'shadowsocks': + $data = $is_url ? URLSchemes::buildShadowsocks($server) : Text::buildShadowsocks($server); break; - case 3: - if ($infoType !== 1) { - $data = $this->trojanSubUrl($user->passwd, $host, $node->port, $node->name); - } else { - $data = '备注:'.$node->name.PHP_EOL.'服务器:'.$host.PHP_EOL.'密码:'.$user->passwd.PHP_EOL.'端口:'.$node->port.PHP_EOL; - } + case 'shadowsocksr': + $data = $is_url ? URLSchemes::buildShadowsocksr($server) : Text::buildShadowsocksr($server); break; - case 1: - case 4: - $protocol = $node->protocol; - $method = $node->method; - $obfs = $node->obfs; - if ($node->single) { - //单端口使用中转的端口 - $port = $node->is_relay ? $node->relay_port : $node->port; - $passwd = $node->passwd; - $protocol_param = $user->port.':'.$user->passwd; - } else { - $port = $user->port; - $passwd = $user->passwd; - $protocol_param = $node->protocol_param; - if ($node->type === 1) { - $protocol = $user->protocol; - $method = $user->method; - $obfs = $user->obfs; - } - } - - if ($infoType !== 1) { - // 生成ss/ssr scheme - $data = $node->compatible ? $this->ssSubUrl($host, $port, $method, $passwd, $group) : - $this->ssrSubUrl($host, $port, $protocol, $method, $obfs, $passwd, $node->obfs_param, $protocol_param, $node->name, $group, $node->is_udp); - } else { - // 生成文本配置信息 - $data = '服务器:'.$host.PHP_EOL.'IPv6:'.$node->ipv6.PHP_EOL.'服务器端口:'.$port.PHP_EOL.'密码:'.$passwd.PHP_EOL.'加密:'.$method.PHP_EOL.($node->compatible ? '' : '协议:'.$protocol.PHP_EOL.'协议参数:'.$protocol_param.PHP_EOL.'混淆:'.$obfs.PHP_EOL.'混淆参数:'.$node->obfs_param.PHP_EOL); - } + case 'v2ray': + $data = $is_url ? URLSchemes::buildVmess($server) : Text::buildVmess($server); + break; + case 'trojan': + $data = $is_url ? URLSchemes::buildTrojan($server) : Text::buildTrojan($server); break; default: } - return $data; - } - - public function v2raySubUrl($name, $host, $port, $uuid, $alter_id, $net, $type, $domain, $path, $tls): string - { - return 'vmess://'.base64url_encode(json_encode([ - 'v' => '2', 'ps' => $name, 'add' => $host, 'port' => $port, 'id' => $uuid, 'aid' => $alter_id, 'net' => $net, - 'type' => $type, 'host' => $domain, 'path' => $path, 'tls' => $tls ? 'tls' : '', - ], JSON_PRETTY_PRINT)); - } - - public function trojanSubUrl($password, $domain, $port, $remark): string - { - return 'trojan://'.urlencode($password).'@'.$domain.':'.$port.'#'.urlencode($remark); - } - - public function ssSubUrl($host, $port, $method, $passwd, $group): string - { - return 'ss://'.base64url_encode($method.':'.$passwd.'@'.$host.':'.$port).'#'.$group; - } - - public function ssrSubUrl($host, $port, $protocol, $method, $obfs, $passwd, $obfs_param, $protocol_param, $name, $group, $is_udp): string - { - return 'ssr://'.base64url_encode($host.':'.$port.':'.$protocol.':'.$method.':'.$obfs.':'.base64url_encode($passwd).'/?obfsparam='.base64url_encode($obfs_param).'&protoparam='.base64url_encode($protocol_param).'&remarks='.base64url_encode($name).'&group='.base64url_encode($group).'&udpport='.$is_udp.'&uot=0'); + return $data ?? null; } // 流量使用图表 diff --git a/app/Http/Controllers/User/SubscribeController.php b/app/Http/Controllers/User/SubscribeController.php index 47c3e230..1dd59537 100644 --- a/app/Http/Controllers/User/SubscribeController.php +++ b/app/Http/Controllers/User/SubscribeController.php @@ -2,23 +2,15 @@ namespace App\Http\Controllers\User; -use App\Components\Client\Clash; -use App\Components\Client\QuantumultX; -use App\Components\Client\Shadowrocket; -use App\Components\Client\Surfboard; -use App\Components\Client\Surge; -use App\Components\Client\URLSchemes; use App\Components\IP; +use App\Http\Controllers\ClientController; use App\Http\Controllers\Controller; -use App\Models\User; use App\Models\UserSubscribe; use App\Models\UserSubscribeLog; use Arr; -use File; use Illuminate\Http\Request; use Redirect; use Response; -use Symfony\Component\Yaml\Yaml; class SubscribeController extends Controller { @@ -31,7 +23,7 @@ class SubscribeController extends Controller return Redirect::route('login'); } $this->subType = $request->input('type'); - $target = strtolower($request->input('target') ?? (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '')); + $target = strtolower($request->input('target') ?? ($request->userAgent() ?? '')); // 检查订阅码是否有效 $subscribe = UserSubscribe::whereCode($code)->first(); @@ -104,34 +96,9 @@ class SubscribeController extends Controller $servers = array_slice($servers, 0, (int) sysConfig('subscribe_max')); } - if ($target) { - if (strpos($target, 'quantumult%20x') !== false) { - exit($this->quantumultX($user, $servers)); - } - if (strpos($target, 'quantumult') !== false) { - exit($this->quantumult($user, $servers)); - } - if (strpos($target, 'clash') !== false) { - exit($this->clash($servers)); - } - if (strpos($target, 'surfboard') !== false) { - exit($this->surfboard($user, $servers)); - } - if (strpos($target, 'surge') !== false) { - exit($this->surge($user, $servers)); - } - if (strpos($target, 'shadowrocket') !== false) { - exit($this->shadowrocket($user, $servers)); - } -// if (strpos($target, 'shadowsocks') !== false) { -// exit($this->shaodowsocksSIP008($servers)); -// } - } - exit($this->origin($servers)); + return (new ClientController)->config($target, $user, $servers); } - // TODO 通过Token获取订阅信息 - // 抛出错误的节点信息,用于兼容防止客户端订阅失败 private function failed($text) { @@ -171,218 +138,4 @@ class SubscribeController extends Controller $log->request_header = $headers; $log->save(); } - - private function quantumultX(User $user, array $servers = []): string - { - $uri = ''; - if (sysConfig('is_custom_subscribe')) { - header("subscription-userinfo: upload={$user->u}; download={$user->d}; total={$user->transfer_enable}; expire={$user->expired_at}"); - } - foreach ($servers as $server) { - if ($server['type'] === 'shadowsocks') { - $uri .= QuantumultX::buildShadowsocks($server); - } - if ($server['type'] === 'shadowsocksr') { - $uri .= QuantumultX::buildShadowsocksr($server); - } - if ($server['type'] === 'v2ray') { - $uri .= QuantumultX::buildVmess($server); - } - if ($server['type'] === 'trojan') { - $uri .= QuantumultX::buildTrojan($server); - } - } - - return base64_encode($uri); - } - - private function quantumult(User $user, array $servers = []): string - { - if (sysConfig('is_custom_subscribe')) { - header('subscription-userinfo: upload='.$user->u.'; download='.$user->d.';total='.$user->transfer_enable.'; expire='.strtotime($user->expired_at)); - } - - return $this->origin($servers); - } - - private function origin(array $servers = [], bool $encode = true): string - { - $uri = ''; - foreach ($servers as $server) { - if ($server['type'] === 'shadowsocks') { - $uri .= URLSchemes::buildShadowsocks($server); - } - if ($server['type'] === 'shadowsocksr') { - $uri .= URLSchemes::buildShadowsocksr($server); - } - if ($server['type'] === 'v2ray') { - $uri .= URLSchemes::buildVmess($server); - } - if ($server['type'] === 'trojan') { - $uri .= URLSchemes::buildTrojan($server); - } - } - - return $encode ? base64_encode($uri) : $uri; - } - - private function clash($servers) - { - $defaultConfig = base_path().'/resources/rules/default.clash.yaml'; - $customConfig = base_path().'/resources/rules/custom.clash.yaml'; - if (File::exists($customConfig)) { - $config = Yaml::parseFile($customConfig); - } else { - $config = Yaml::parseFile($defaultConfig); - } - $proxy = []; - $proxies = []; - - foreach ($servers as $server) { - if ($server['type'] === 'shadowsocks') { - $proxy[] = Clash::buildShadowsocks($server); - $proxies[] = $server['name']; - } - if ($server['type'] === 'shadowsocksr') { - $proxy[] = Clash::buildShadowsocksr($server); - $proxies[] = $server['name']; - } - if ($server['type'] === 'v2ray') { - $proxy[] = Clash::buildVmess($server); - $proxies[] = $server['name']; - } - if ($server['type'] === 'trojan') { - $proxy[] = Clash::buildTrojan($server); - $proxies[] = $server['name']; - } - } - - $config['proxies'] = array_merge($config['proxies'] ?: [], $proxy); - foreach ($config['proxy-groups'] as $k => $v) { - if (! is_array($config['proxy-groups'][$k]['proxies'])) { - continue; - } - $config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies); - } - $yaml = Yaml::dump($config); - $yaml = str_replace('$app_name', sysConfig('website_name'), $yaml); - - return $yaml; - } - - private function surfboard(User $user, array $servers = []) - { - $proxies = ''; - $proxyGroup = ''; - - foreach ($servers as $server) { - if ($server['type'] === 'shadowsocks') { - // [Proxy] - $proxies .= Surfboard::buildShadowsocks($server); - // [Proxy Group] - $proxyGroup .= $server['name'].', '; - } - if ($server['type'] === 'v2ray') { - // [Proxy] - $proxies .= Surfboard::buildVmess($server); - // [Proxy Group] - $proxyGroup .= $server['name'].', '; - } - } - - $defaultConfig = base_path().'/resources/rules/default.surfboard.conf'; - $customConfig = base_path().'/resources/rules/custom.surfboard.conf'; - if (File::exists($customConfig)) { - $config = file_get_contents("$customConfig"); - } else { - $config = file_get_contents("$defaultConfig"); - } - - // Subscription link - $subsURL = route('sub', $user->subscribe->code); - - $config = str_replace('$subs_link', $subsURL, $config); - $config = str_replace('$proxies', $proxies, $config); - $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config); - - return $config; - } - - private function surge(User $user, array $servers = []) - { - $proxies = ''; - $proxyGroup = ''; - - foreach ($servers as $server) { - if ($server['type'] === 'shadowsocks') { - // [Proxy] - $proxies .= Surge::buildShadowsocks($server); - // [Proxy Group] - $proxyGroup .= $server['name'].', '; - } - if ($server['type'] === 'v2ray') { - // [Proxy] - $proxies .= Surge::buildVmess($server); - // [Proxy Group] - $proxyGroup .= $server['name'].', '; - } - if ($server['type'] === 'trojan') { - // [Proxy] - $proxies .= Surge::buildTrojan($server); - // [Proxy Group] - $proxyGroup .= $server['name'].', '; - } - } - - $defaultConfig = base_path().'/resources/rules/default.surge.conf'; - $customConfig = base_path().'/resources/rules/custom.surge.conf'; - if (File::exists($customConfig)) { - $config = file_get_contents("$customConfig"); - } else { - $config = file_get_contents("$defaultConfig"); - } - - // Subscription link - $subsURL = route('sub', $user->subscribe->code); - - $config = str_replace('$subs_link', $subsURL, $config); - $config = str_replace('$proxies', $proxies, $config); - $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config); - - return $config; - } - - private function shadowrocket(User $user, array $servers = []): string - { - //display remaining traffic and expire date - $uri = ''; - if (sysConfig('is_custom_subscribe')) { - $upload = flowAutoShow($user->u); - $download = flowAutoShow($user->d); - $totalTraffic = flowAutoShow($user->transfer_enable); - $uri = "STATUS=📤:{$upload}📥:{$download}⏳:{$totalTraffic}📅:{$user->expired_at}\r\n"; - } - $uri .= $this->origin($servers, false); - - return base64_encode($uri); - } - - private function shaodowsocksSIP008(array $servers = []): string - { - $configs = []; - $subs = []; - $subs['servers'] = []; - - foreach ($servers as $server) { - if ($server['type'] === 'shadowsocks') { - $configs[] = URLSchemes::buildShadowsocksSIP008($server); - } - } - - $subs['version'] = 1; - $subs['remark'] = sysConfig('website_name'); - $subs['servers'] = array_merge($subs['servers'] ?: [], $configs); - - return json_encode($subs, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); - } } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index e2851fed..97c5ad59 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -110,18 +110,9 @@ class UserController extends Controller { $user = auth()->user(); if ($request->isMethod('POST')) { - $infoType = $request->input('type'); + $server = Node::findOrFail($request->input('id'))->config($user); // 提取节点信息 - $node = Node::find($request->input('id')); - // 生成节点信息 - if ($node->type === 1) { - $proxyType = $node->compatible ? 'SS' : 'SSR'; - } else { - $proxyType = 'V2Ray'; - } - $data = $this->getUserNodeInfo($user->id, $node->id, $infoType !== 'text' ? 0 : 1); - - return Response::json(['status' => 'success', 'data' => $data, 'title' => $proxyType]); + return Response::json(['status' => 'success', 'data' => $this->getUserNodeInfo($server, $request->input('type') !== 'text'), 'title' => $server['type']]); } // 获取当前用户可用节点 diff --git a/app/Models/Country.php b/app/Models/Country.php index 5a494a5f..39cca0cd 100644 --- a/app/Models/Country.php +++ b/app/Models/Country.php @@ -15,4 +15,9 @@ class Country extends Model protected $primaryKey = 'code'; protected $keyType = 'string'; protected $guarded = []; + + public function nodes() + { + return $this->hasMany(Node::class, 'country_code'); + } } diff --git a/app/Models/Level.php b/app/Models/Level.php index 6abe3aac..21193278 100644 --- a/app/Models/Level.php +++ b/app/Models/Level.php @@ -12,4 +12,9 @@ class Level extends Model public $timestamps = false; protected $table = 'level'; protected $guarded = []; + + public function users() + { + return $this->hasMany(User::class, 'level'); + } } diff --git a/app/Models/Node.php b/app/Models/Node.php index 2643511a..14f372fb 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -90,7 +90,7 @@ class Node extends Model ->get(); } - public function config($user) + public function config(User $user) { $config = [ 'id' => $this->id, diff --git a/app/Models/ReferralLog.php b/app/Models/ReferralLog.php index b196bfff..e9ab9b8c 100644 --- a/app/Models/ReferralLog.php +++ b/app/Models/ReferralLog.php @@ -38,16 +38,16 @@ class ReferralLog extends Model return $value / 100; } - public function setAmountAttribute($value): void - { - $this->attributes['amount'] = $value * 100; - } - public function getCommissionAttribute($value) { return $value / 100; } + public function setAmountAttribute($value): void + { + $this->attributes['amount'] = $value * 100; + } + public function setCommissionAttribute($value): void { $this->attributes['commission'] = $value * 100; diff --git a/config/version.php b/config/version.php index 7f840569..b14d8ab4 100644 --- a/config/version.php +++ b/config/version.php @@ -2,5 +2,5 @@ return [ 'name' => 'ProxyPanel', - 'number' => '2.6.a', + 'number' => '2.6.b', ]; diff --git a/resources/views/admin/config/config.blade.php b/resources/views/admin/config/config.blade.php index da2fd04c..c61338a4 100644 --- a/resources/views/admin/config/config.blade.php +++ b/resources/views/admin/config/config.blade.php @@ -392,7 +392,7 @@ $.ajax({ url: '{{route('admin.config.level.store')}}', method: 'POST', - data: {_token: '{{csrf_token()}}', level: level, level_name: level_name}, + data: {_token: '{{csrf_token()}}', level: level, name: level_name}, beforeSend: function() { $('#level_msg').show().html('正在添加'); }, @@ -426,7 +426,7 @@ data: { _token: '{{csrf_token()}}', level: $('#level_' + id).val(), - level_name: $('#level_name_' + id).val(), + name: $('#level_name_' + id).val(), }, dataType: 'json', success: function(ret) { diff --git a/resources/views/admin/config/emailFilter.blade.php b/resources/views/admin/config/emailFilter.blade.php index 43424c3e..9bbc67f4 100644 --- a/resources/views/admin/config/emailFilter.blade.php +++ b/resources/views/admin/config/emailFilter.blade.php @@ -27,14 +27,14 @@ - @foreach($list as $vo) + @foreach($filters as $filter) - {{$vo->id}} - {{$vo->type==1? '黑':'白'}} - {{$vo->words}} + {{$filter->id}} + {{$filter->type === 1? '黑':'白'}} + {{$filter->words}} @can('admin.config.filter.destroy') - @endcan @@ -47,11 +47,11 @@