完善工单/节点/系统设置的请求合规检测

This commit is contained in:
兔姬桑
2020-12-30 02:32:10 +08:00
parent eed3c80fb6
commit 2bedbd6b59
11 changed files with 134 additions and 93 deletions

View File

@@ -14,6 +14,7 @@ use App\Models\NodeCertificate;
use App\Models\NodePing;
use App\Models\RuleGroup;
use App\Services\NodeService;
use Arr;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -68,7 +69,9 @@ class NodeController extends Controller
public function store(NodeRequest $request): JsonResponse
{
try {
$node = Node::create($request->except('_token', 'labels'));
$array = $request->validated();
Arr::forget($array, ['labels']);
$node = Node::create($array);
if ($node) {
// 生成节点标签
@@ -104,10 +107,12 @@ class NodeController extends Controller
public function update(NodeRequest $request, Node $node): JsonResponse
{
try {
// 更新节点标签
$node->labels()->sync($request->input('labels'));
$array = $request->validated();
Arr::forget($array, ['labels']);
if ($node->update($array)) {
// 更新节点标签
$node->labels()->sync($request->input('labels'));
if ($node->update($request->except('_token', 'labels'))) {
return Response::json(['status' => 'success', 'message' => '编辑成功']);
}
} catch (Exception $e) {
@@ -182,9 +187,7 @@ class NodeController extends Controller
// Ping节点延迟
public function pingNode(Node $node): JsonResponse
{
$result = NetworkDetection::ping($node->is_ddns ? $node->server : $node->ip);
if ($result) {
if ($result = NetworkDetection::ping($node->is_ddns ? $node->server : $node->ip)) {
return Response::json([
'status' => 'success',
'message' => [

View File

@@ -4,11 +4,11 @@ namespace App\Http\Controllers\Admin;
use App\Components\PushNotification;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\SystemRequest;
use App\Models\Config;
use App\Models\Label;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Response;
class SystemController extends Controller
@@ -20,7 +20,7 @@ class SystemController extends Controller
}
// 设置系统扩展信息,例如客服、统计代码
public function setExtend(Request $request): RedirectResponse
public function setExtend(SystemRequest $request): RedirectResponse
{
if ($request->hasFile('website_home_logo')) {
$validator = validator()->make($request->all(), ['website_home_logo' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048']);
@@ -53,29 +53,18 @@ class SystemController extends Controller
}
// 设置某个配置项
public function setConfig(Request $request): JsonResponse
public function setConfig(SystemRequest $request): JsonResponse
{
$name = $request->input('name');
$value = $request->input('value');
if (! $name) {
return Response::json(['status' => 'fail', 'message' => '设置失败:请求参数异常']);
}
// 屏蔽异常配置
if (! in_array($name, Config::pluck('name')->toArray(), true)) {
return Response::json(['status' => 'fail', 'message' => '设置失败:配置不存在']);
}
// 如果开启用户邮件重置密码,则先设置网站名称和网址
if ($value !== '0' && in_array($name, ['is_reset_password', 'is_activate_account', 'expire_warning', 'traffic_warning'], true)) {
$config = Config::find('website_name');
if (! $config->value) {
if (! Config::find('website_url')->value) {
return Response::json(['status' => 'fail', 'message' => '设置失败:启用该配置需要先设置【网站名称】']);
}
$config = Config::find('website_url');
if (! $config->value) {
if (! Config::find('website_url')->value) {
return Response::json(['status' => 'fail', 'message' => '设置失败:启用该配置需要先设置【网站地址】']);
}
}
@@ -146,9 +135,11 @@ class SystemController extends Controller
}
// 更新配置
Config::find($name)->update(['value' => $value]);
if (Config::findOrFail($name)->update(['value' => $value])) {
return Response::json(['status' => 'success', 'message' => '修改成功']);
}
return Response::json(['status' => 'success', 'message' => '操作成功']);
return Response::json(['status' => 'fail', 'message' => '修改失败']);
}
// 推送通知测试

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin;
use App\Components\Helpers;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\TicketRequest;
use App\Mail\closeTicket;
use App\Mail\replyTicket;
use App\Models\Ticket;
@@ -37,34 +38,16 @@ class TicketController extends Controller
}
// 创建工单
public function store(Request $request)
public function store(TicketRequest $request)
{
$id = $request->input('id');
$email = $request->input('email');
$title = $request->input('title');
$content = $request->input('content');
$user = User::find($id) ?: User::whereEmail($email)->first();
if (! $user) {
return Response::json(['status' => 'fail', 'message' => '用户不存在']);
}
$data = $request->validated();
$user = User::find($data['id']) ?: User::whereEmail($data['email'])->first();
if ($user === Auth::user()) {
return Response::json(['status' => 'fail', 'message' => '不能对自己发起工单']);
}
if (empty($title) || empty($content)) {
return Response::json(['status' => 'fail', 'message' => '请输入标题和内容']);
}
$obj = new Ticket();
$obj->user_id = $user->id;
$obj->admin_id = Auth::id();
$obj->title = $title;
$obj->content = $content;
if ($obj->save()) {
if (Ticket::create(['user_id' => $user->id, 'admin_id' => auth()->id(), 'title' => $data['title'], 'content' => $data['content']])) {
return Response::json(['status' => 'success', 'message' => '工单创建成功']);
}

View File

@@ -9,38 +9,47 @@ class NodeRequest extends FormRequest
public function rules(): array
{
return [
'type' => 'required|between:1,3',
'name' => 'required',
'country_code' => 'required',
'is_ddns' => 'required|boolean',
'name' => 'required|string',
'server' => 'required_if:is_ddns,1|nullable|ends_with:'.implode(',', config('domains')),
'push_port' => 'numeric|between:0,65535',
'traffic_rate' => 'required|numeric|min:0',
'level' => 'required|numeric|between:0,255',
'speed_limit' => 'required|numeric|min:0',
'client_limit' => 'required|numeric|min:0',
'port' => 'nullable|numeric|between:0,65535',
'ip' => 'ipv4|required_if:is_ddns,0|nullable',
'ipv6' => 'nullable|ipv6',
'relay_server' => 'required_if:is_relay,1',
'relay_port' => 'required_if:is_relay,1|numeric|between:0,65535',
'method' => 'required_if:type,1',
'protocol' => 'required_if:type,1',
'obfs' => 'required_if:type,1',
'is_subscribe' => 'boolean',
'is_ddns' => 'boolean',
'is_relay' => 'boolean',
'is_udp' => 'boolean',
'detection_type' => 'between:0,3',
'compatible' => 'boolean',
'single' => 'boolean',
'push_port' => 'numeric|between:0,65535',
'traffic_rate' => 'required|numeric|min:0',
'level' => 'required|numeric|exists:level,level',
'rule_group_id' => 'nullable|exists:rule_group,id',
'speed_limit' => 'required|numeric|min:0',
'client_limit' => 'required|numeric|min:0',
'labels' => 'nullable|exists:label,id',
'country_code' => 'required|exists:country,code',
'description' => 'nullable|string',
'sort' => 'required|numeric|between:0,255',
'status' => 'boolean',
'is_udp' => 'required|boolean',
'status' => 'required|boolean',
'type' => 'required|numeric|between:1,4',
'method' => 'required_if:type,1,4|exists:ss_config,name',
'protocol' => 'required_if:type,1,4|exists:ss_config,name',
'protocol_param' => 'nullable|string',
'obfs' => 'required_if:type,1,4|exists:ss_config,name',
'obfs_param' => 'nullable|string',
'compatible' => 'required|boolean',
'is_subscribe' => 'required|boolean',
'detection_type' => 'required|numeric|between:0,3',
'single' => 'required|boolean',
'port' => 'required_if:single,1|numeric|between:1,65535|nullable',
'passwd' => 'required_if:single,1|string|nullable',
'v2_alter_id' => 'required_if:type,2|numeric|between:0,65535',
'v2_port' => 'required_if:type,2|numeric|between:0,65535',
'v2_method' => 'required_if:type,2',
'v2_net' => 'required_if:type,2',
'v2_type' => 'required_if:type,2',
'v2_tls' => 'boolean',
'v2_host' => 'string|nullable',
'v2_path' => 'string|nullable',
'v2_tls' => 'required_if:type,2|boolean',
'tls_provider' => 'json|nullable',
'is_relay' => 'required|boolean',
'relay_server' => 'required_if:is_relay,1',
'relay_port' => 'required_if:is_relay,1|numeric|between:1,65535',
];
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
class SystemRequest extends FormRequest
{
public function rules()
{
return [
'name' => 'required|string|exists:config,name',
'value' => 'nullable',
];
}
public function messages()
{
return [
'name.exists' => '设置项目不存在于数据库',
];
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
class TicketRequest extends FormRequest
{
public function rules()
{
return [
'id' => 'required_without:email|exists:user,id|numeric|nullable',
'email' => 'required_without:id|exists:user,email||nullable',
'title' => 'required|string',
'content' => 'required|string',
];
}
}

View File

@@ -107,7 +107,6 @@
<label for="country_code" class="col-md-3 col-form-label"> 国家/地区 </label>
<select data-plugin="selectpicker" data-style="btn-outline btn-primary"
class="col-md-5 form-control" name="country_code" id="country_code">
<option value="un" selected hidden>请选择</option>
@foreach($countries as $country)
<option value="{{$country->code}}">{{$country->code}} - {{$country->name}}</option>
@endforeach

View File

@@ -150,14 +150,6 @@
@can('admin.rule.store')
// 添加规则
function addRule() {
$.post("{{route('admin.rule.store')}}", {}, function(ret) {
$('#add').modal('hide');
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: 'POST',
url: "{{route('admin.rule.store')}}",

View File

@@ -177,18 +177,36 @@
confirmButtonText: '{{trans('home.ticket_confirm')}}',
}).then((result) => {
if (result.value) {
$.post('{{route('admin.ticket.store')}}', {
_token: '{{csrf_token()}}',
id: id,
email: email,
title: title,
content: content,
}, 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: 'POST',
url: "{{route('admin.ticket.store')}}",
data: {
_token: '{{csrf_token()}}',
id: id,
email: email,
title: title,
content: content,
},
dataType: 'json',
success: function(ret) {
$('#add_ticket_modal').modal('hide');
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) {
$('#add_ticket_modal').modal('hide');
let str = '';
const errors = data.responseJSON;
if ($.isEmptyObject(errors) === false) {
$.each(errors.errors, function(index, value) {
str += '<li>' + value + '</li>';
});
swal.fire({title: '提示', html: str, icon: 'error', confirmButtonText: '{{trans('home.ticket_confirm')}}'});
}
},
});
}
});

View File

@@ -1,4 +1,9 @@
<div class="chat @if(($ticket->admin_id && $ticket->admin_id !== $user->id) ||($ticket->user_id && $ticket->user_id !== $user->id)) chat-left @endif">
<div class="chat
@if (isset($ticket->admin_id) && $ticket->admin_id !== $user->id)
chat-left
@elseif(isset($ticket->user_id) && !isset($ticket->admin_id) && $ticket->user_id !== $user->id)
chat-left
@endif">
<div class="chat-avatar">
<p class="avatar" data-toggle="tooltip" href="#" data-placement="right" title="" data-original-title="{{($ticket->admin ?? $ticket->user)->email}}">
<x-avatar :user="$ticket->admin ?? $ticket->user"/>

View File

@@ -175,7 +175,7 @@
<footer class="site-footer">
<div class="site-footer-legal">
Copyright ©2017 - 2020 <a href="https://github.com/ProxyPanel/ProxyPanel" target="_blank">{{config('version.name')}}</a>
🚀 版本: {{config('version.number')}}
🚀 版本: <code> {{config('version.number')}} </code>
</div>
<div class="site-footer-right">
<a href="{{sysConfig('website_url')}}" target="_blank">{{sysConfig('website_name')}}</a> 🈺运营