Skip to content

Commit 315b06d

Browse files
authored
Merge branch 'cedar2025:master' into master
2 parents 2d8ed35 + 95e8e7b commit 315b06d

File tree

14 files changed

+151
-38
lines changed

14 files changed

+151
-38
lines changed

app/Http/Controllers/V1/Server/UniProxyController.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public function config(Request $request)
9595
$host = $node->host;
9696

9797
$baseConfig = [
98+
'protocol' => $nodeType,
99+
'listen_ip' => '0.0.0.0',
98100
'server_port' => (int) $serverPort,
99101
'network' => data_get($protocolSettings, 'network'),
100102
'networkSettings' => data_get($protocolSettings, 'network_settings') ?: null,
@@ -132,6 +134,7 @@ public function config(Request $request)
132134
}
133135
],
134136
'hysteria' => [
137+
...$baseConfig,
135138
'server_port' => (int) $serverPort,
136139
'version' => (int) $protocolSettings['version'],
137140
'host' => $host,
@@ -148,6 +151,7 @@ public function config(Request $request)
148151
}
149152
],
150153
'tuic' => [
154+
...$baseConfig,
151155
'version' => (int) $protocolSettings['version'],
152156
'server_port' => (int) $serverPort,
153157
'server_name' => $protocolSettings['tls']['server_name'],
@@ -157,24 +161,29 @@ public function config(Request $request)
157161
'heartbeat' => "3s",
158162
],
159163
'anytls' => [
164+
...$baseConfig,
160165
'server_port' => (int) $serverPort,
161166
'server_name' => $protocolSettings['tls']['server_name'],
162167
'padding_scheme' => $protocolSettings['padding_scheme'],
163168
],
164169
'socks' => [
170+
...$baseConfig,
165171
'server_port' => (int) $serverPort,
166172
],
167173
'naive' => [
174+
...$baseConfig,
168175
'server_port' => (int) $serverPort,
169176
'tls' => (int) $protocolSettings['tls'],
170177
'tls_settings' => $protocolSettings['tls_settings']
171178
],
172179
'http' => [
180+
...$baseConfig,
173181
'server_port' => (int) $serverPort,
174182
'tls' => (int) $protocolSettings['tls'],
175183
'tls_settings' => $protocolSettings['tls_settings']
176184
],
177185
'mieru' => [
186+
...$baseConfig,
178187
'server_port' => (string) $serverPort,
179188
'protocol' => (int) $protocolSettings['protocol'],
180189
],

app/Http/Middleware/Server.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ class Server
1414
public function handle(Request $request, Closure $next, ?string $nodeType = null)
1515
{
1616
$this->validateRequest($request);
17-
17+
$nodeType = $request->input('node_type', $nodeType);
18+
$normalizedNodeType = ServerModel::normalizeType($nodeType);
1819
$serverInfo = ServerService::getServer(
1920
$request->input('node_id'),
20-
$request->input('node_type') ?? $nodeType
21+
$normalizedNodeType
2122
);
2223
if (!$serverInfo) {
2324
throw new ApiException('Server does not exist');
@@ -43,6 +44,9 @@ function ($attribute, $value, $fail) {
4344
'node_type' => [
4445
'nullable',
4546
function ($attribute, $value, $fail) use ($request) {
47+
if ($value === "v2node") {
48+
$value = null;
49+
}
4650
if (!ServerModel::isValidType($value)) {
4751
$fail("Invalid node type specified");
4852
return;

app/Http/Routes/V2/ServerRoute.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
namespace App\Http\Routes\V2;
3+
4+
use App\Http\Controllers\V1\Server\ShadowsocksTidalabController;
5+
use App\Http\Controllers\V1\Server\TrojanTidalabController;
6+
use App\Http\Controllers\V1\Server\UniProxyController;
7+
use Illuminate\Contracts\Routing\Registrar;
8+
9+
class ServerRoute
10+
{
11+
public function map(Registrar $router)
12+
{
13+
14+
$router->group([
15+
'prefix' => 'server',
16+
'middleware' => 'server'
17+
], function ($route) {
18+
$route->get('config', [UniProxyController::class, 'config']);
19+
$route->get('user', [UniProxyController::class, 'user']);
20+
$route->post('push', [UniProxyController::class, 'push']);
21+
$route->post('alive', [UniProxyController::class, 'alive']);
22+
$route->get('alivelist', [UniProxyController::class, 'alivelist']);
23+
$route->post('status', [UniProxyController::class, 'status']);
24+
});
25+
}
26+
}

app/Models/Server.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,14 +317,14 @@ public function generateServerPassword(User $user): string
317317
return "{$serverKey}:{$userKey}";
318318
}
319319

320-
public static function normalizeType(string $type): string
320+
public static function normalizeType(?string $type): string | null
321321
{
322-
return strtolower(self::TYPE_ALIASES[$type] ?? $type);
322+
return $type ? strtolower(self::TYPE_ALIASES[$type] ?? $type) : null;
323323
}
324-
325-
public static function isValidType(string $type): bool
324+
325+
public static function isValidType(?string $type): bool
326326
{
327-
return in_array(self::normalizeType($type), self::VALID_TYPES, true);
327+
return $type ? in_array(self::normalizeType($type), self::VALID_TYPES, true) : true;
328328
}
329329

330330
public function getAvailableStatusAttribute(): int

app/Services/Plugin/AbstractPlugin.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
namespace App\Services\Plugin;
44

5-
use Illuminate\Support\Facades\View;
6-
use Illuminate\Support\Facades\Route;
75
use Illuminate\Support\Facades\File;
86
use Illuminate\Support\Str;
97
use Symfony\Component\HttpFoundation\Response;

app/Services/Plugin/PluginManager.php

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class PluginManager
1717
protected string $pluginPath;
1818
protected array $loadedPlugins = [];
1919
protected bool $pluginsInitialized = false;
20+
protected array $configTypesCache = [];
2021

2122
public function __construct()
2223
{
@@ -319,7 +320,9 @@ public function enable(string $pluginCode): bool
319320
->first();
320321

321322
if ($dbPlugin && !empty($dbPlugin->config)) {
322-
$plugin->setConfig(json_decode($dbPlugin->config, true));
323+
$values = json_decode($dbPlugin->config, true) ?: [];
324+
$values = $this->castConfigValuesByType($pluginCode, $values);
325+
$plugin->setConfig($values);
323326
}
324327

325328
// 注册服务提供者
@@ -453,13 +456,15 @@ public function update(string $pluginCode): bool
453456
$this->runMigrations($pluginCode);
454457

455458
$plugin = $this->loadPlugin($pluginCode);
456-
if ($plugin) {
457-
if (!empty($dbPlugin->config)) {
458-
$plugin->setConfig(json_decode($dbPlugin->config, true));
459-
}
459+
if ($plugin) {
460+
if (!empty($dbPlugin->config)) {
461+
$values = json_decode($dbPlugin->config, true) ?: [];
462+
$values = $this->castConfigValuesByType($pluginCode, $values);
463+
$plugin->setConfig($values);
464+
}
460465

461-
$plugin->update($oldVersion, $newVersion);
462-
}
466+
$plugin->update($oldVersion, $newVersion);
467+
}
463468

464469
$dbPlugin->update([
465470
'version' => $newVersion,
@@ -567,7 +572,9 @@ public function initializeEnabledPlugins(): void
567572
}
568573

569574
if (!empty($dbPlugin->config)) {
570-
$pluginInstance->setConfig(json_decode($dbPlugin->config, true));
575+
$values = json_decode($dbPlugin->config, true) ?: [];
576+
$values = $this->castConfigValuesByType($pluginCode, $values);
577+
$pluginInstance->setConfig($values);
571578
}
572579

573580
$this->registerServiceProvider($pluginCode);
@@ -603,7 +610,9 @@ public function registerPluginSchedules(Schedule $schedule): void
603610
return;
604611
}
605612
if (!empty($dbPlugin->config)) {
606-
$pluginInstance->setConfig(json_decode($dbPlugin->config, true));
613+
$values = json_decode($dbPlugin->config, true) ?: [];
614+
$values = $this->castConfigValuesByType($dbPlugin->code, $values);
615+
$pluginInstance->setConfig($values);
607616
}
608617
$pluginInstance->schedule($schedule);
609618

@@ -669,4 +678,50 @@ public static function installDefaultPlugins(): void
669678
}
670679
}
671680
}
681+
682+
/**
683+
* 根据 config.json 的类型信息对配置值进行类型转换(仅处理 type=json 键)。
684+
*/
685+
protected function castConfigValuesByType(string $pluginCode, array $values): array
686+
{
687+
$types = $this->getConfigTypes($pluginCode);
688+
foreach ($values as $key => $value) {
689+
$type = $types[$key] ?? null;
690+
691+
if ($type === 'json') {
692+
if (is_array($value)) {
693+
continue;
694+
}
695+
696+
if (is_string($value) && $value !== '') {
697+
$decoded = json_decode($value, true);
698+
if (json_last_error() === JSON_ERROR_NONE) {
699+
$values[$key] = $decoded;
700+
}
701+
}
702+
}
703+
}
704+
return $values;
705+
}
706+
707+
/**
708+
* 读取并缓存插件 config.json 中的键类型映射。
709+
*/
710+
protected function getConfigTypes(string $pluginCode): array
711+
{
712+
if (isset($this->configTypesCache[$pluginCode])) {
713+
return $this->configTypesCache[$pluginCode];
714+
}
715+
$types = [];
716+
$configFile = $this->getPluginPath($pluginCode) . '/config.json';
717+
if (File::exists($configFile)) {
718+
$config = json_decode(File::get($configFile), true);
719+
$fields = $config['config'] ?? [];
720+
foreach ($fields as $key => $meta) {
721+
$types[$key] = is_array($meta) ? ($meta['type'] ?? 'string') : 'string';
722+
}
723+
}
724+
$this->configTypesCache[$pluginCode] = $types;
725+
return $types;
726+
}
672727
}

app/Services/ServerService.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,12 @@ public static function getRoutes(array $routeIds)
9898
* @param string $serverType
9999
* @return Server|null
100100
*/
101-
public static function getServer($serverId, $serverType)
101+
public static function getServer($serverId, ?string $serverType)
102102
{
103103
return Server::query()
104-
->where('type', Server::normalizeType($serverType))
104+
->when($serverType, function ($query) use ($serverType) {
105+
$query->where('type', Server::normalizeType($serverType));
106+
})
105107
->where(function ($query) use ($serverId) {
106108
$query->where('code', $serverId)
107109
->orWhere('id', $serverId);

app/Services/ThemeService.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ public function upload(UploadedFile $file): bool
159159
$this->cleanupThemeFiles($config['name']);
160160
File::deleteDirectory($targetPath);
161161
File::copyDirectory($sourcePath, $targetPath);
162-
$this->initConfig($config['name']);
162+
// 更新主题时保留用户配置
163+
$this->initConfig($config['name'], true);
163164
return true;
164165
} else {
165166
throw new Exception('Theme exists and not a newer version');
@@ -397,8 +398,11 @@ public function refreshCurrentTheme(): bool
397398

398399
/**
399400
* Initialize theme config
401+
*
402+
* @param string $theme 主题名称
403+
* @param bool $preserveExisting 是否保留现有配置(更新主题时使用)
400404
*/
401-
private function initConfig(string $theme): void
405+
private function initConfig(string $theme, bool $preserveExisting = false): void
402406
{
403407
$config = $this->readConfigFile($theme);
404408
if (!$config) {
@@ -408,6 +412,13 @@ private function initConfig(string $theme): void
408412
$defaults = collect($config['configs'] ?? [])
409413
->mapWithKeys(fn($col) => [$col['field_name'] => $col['default_value'] ?? ''])
410414
->toArray();
411-
admin_setting([self::SETTING_PREFIX . $theme => $defaults]);
415+
416+
if ($preserveExisting) {
417+
$existingConfig = admin_setting(self::SETTING_PREFIX . $theme) ?? [];
418+
$mergedConfig = array_merge($defaults, $existingConfig);
419+
admin_setting([self::SETTING_PREFIX . $theme => $mergedConfig]);
420+
} else {
421+
admin_setting([self::SETTING_PREFIX . $theme => $defaults]);
422+
}
412423
}
413424
}

plugins/Telegram/Plugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public function sendTicketNotify(Ticket $ticket): void
9393

9494
if ($plan) {
9595
$TGmessage .= "📦 套餐: `{$plan->name}`\n";
96-
$TGmessage .= "📊 流量: `{$remaining_traffic}G / {$transfer_enable}G` (已用/总计)\n";
96+
$TGmessage .= "📊 流量: `{$remaining_traffic}G / {$transfer_enable}G` (剩余/总计)\n";
9797
$TGmessage .= "⬆️⬇️ 已用: `{$u}G / {$d}G`\n";
9898
$TGmessage .= "⏰ 到期: `{$expired_at}`\n";
9999
} else {

public/assets/admin/assets/index.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)