Files
lgp-admin-plus-api/app/Service/common/oss/OssRuntimeConfigService.php
2026-08-19 08:16:49 +08:00

142 lines
4.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Service\common\oss;
use App\BaseApp\BaseService;
use App\Models\oss\OssConfigModel;
use App\Service\common\FieldEncryptService;
use App\Service\SystemConfigService;
use Exception;
/**
* OSS 运行时配置:解析当前启用的存储配置并解密密钥,供上传工厂使用
*/
class OssRuntimeConfigService extends BaseService
{
public const CFG_ACTIVE_ID = 'oss_active_config_id';
public function __construct()
{
// 上传链路可能在无登录上下文触发,不强制鉴权
$this->isAuth = false;
parent::__construct();
}
/**
* 获取当前启用的明文配置
* 为什么要解密:上传客户端需要明文 access/secret库内仅存 AES 密文
*
* @return array{
* id:int,driver:string,name:string,access_key:string,secret_key:string,
* endpoint:string,region:string,bucket:string,domain:string,
* path_prefix:string,extra_json:mixed
* }
*/
public function getActiveConfig(): array
{
$sys = SystemConfigService::getInstance();
$activeId = (int) $sys->getValue(self::CFG_ACTIVE_ID, '0');
$row = null;
if ($activeId > 0) {
$row = OssConfigModel::where('id', $activeId)
->where('deleted_at', 0)
->where('status', 1)
->first();
}
if (!$row) {
// 回落 is_active 标记,避免仅写了表未写 system_config 时上传失败
$row = OssConfigModel::where('is_active', 1)
->where('deleted_at', 0)
->where('status', 1)
->orderByDesc('id')
->first();
}
if (!$row) {
// 最终回落本地默认行或内存默认
$row = OssConfigModel::where('driver', 'local')
->where('deleted_at', 0)
->where('status', 1)
->orderByDesc('is_active')
->orderBy('id')
->first();
}
if (!$row) {
return [
'id' => 0,
'driver' => 'local',
'name' => '本地存储',
'access_key' => '',
'secret_key' => '',
'endpoint' => '',
'region' => '',
'bucket' => '',
'domain' => '',
'path_prefix' => 'uploads',
'extra_json' => null,
];
}
return $this->formatConfig($row);
}
/**
* 按 ID 获取明文配置
*
* 素材库要对指定 bucket 做列举与删除,不能只认「当前启用」那一份:
* 换过存储之后老素材仍然躺在旧配置的 bucket 里,回收时必须拿旧配置去删。
* 也因此这里不校验 status —— 配置被禁用不代表里面的对象不用管了。
*
* @throws Exception
*/
public function getConfigById(int $id): array
{
$row = OssConfigModel::where('id', $id)->where('deleted_at', 0)->first();
if (!$row) {
$this->utils->notFound('存储配置不存在');
}
return $this->formatConfig($row);
}
/**
* 库行转明文配置数组
*/
private function formatConfig(OssConfigModel $row): array
{
$enc = FieldEncryptService::getInstance();
$extra = $row->extra_json;
if (is_string($extra) && $extra !== '') {
$decoded = json_decode($extra, true);
$extra = is_array($decoded) ? $decoded : $extra;
}
return [
'id' => (int) $row->id,
'driver' => (string) $row->driver,
'name' => (string) $row->name,
'access_key' => $this->decryptSecret($enc, (string) ($row->access_key ?? ''), 'AccessKey'),
'secret_key' => $this->decryptSecret($enc, (string) ($row->secret_key ?? ''), 'SecretKey'),
'endpoint' => (string) ($row->endpoint ?? ''),
'region' => (string) ($row->region ?? ''),
'bucket' => (string) ($row->bucket ?? ''),
'domain' => (string) ($row->domain ?? ''),
'path_prefix' => (string) ($row->path_prefix ?? ''),
'extra_json' => $extra,
];
}
/**
* 解密库内密钥;密文在但解不开时必须说清楚,不能静默变空串
*
* 以前 silentFail=true解密失败后驱动只看到空 AccessKey
* 素材拉取就会报「七牛云配置不完整」,运营以为没填,其实是 ENCRYPT_KEY 对不上。
*/
private function decryptSecret(FieldEncryptService $enc, string $raw, string $label): string
{
$plain = $enc->decryptFromStorage($raw, true);
if ($raw !== '' && $plain === '' && $enc->isEncrypted($raw)) {
$this->utils->errorThrow(
'存储配置的' . $label . '解密失败,请到「系统配置 → 存储」重新填写密钥后保存'
);
}
return $plain;
}
}