## 1. ECS RAM 角色改为自动探测 原先要用户去阿里云控制台查「实例 RAM 角色名」再手填,纯属多余 —— 机器自己知道答案。 新增 fb_oss_detect_instance_role():读元数据 GET /latest/meta-data/ram/security-credentials/(末尾带斜杠)拿到角色名列表。 - 兼容单行 / 多行 / JSON 数组三种返回 - 未配置角色时 fb_oss_instance_creds() 自动探测,不再报「未配置」 - 后台改成只读展示「已绑定:xxx」,手填入口收进「高级」折叠里 - 保存时留空 = 自动探测后写入,不存空值 - 探测失败给出可操作原因(没绑角色 / 不在 ECS 上 / 元数据被禁用) ## 2. 邮件配置界面(原先完全缺失) lib/mailer.php 有完整 SMTP 实现,但后台一个输入框都没有, 只能改 config.php —— 用户装完根本找不到地方配。 根因有两层: - fb_setting_keys() 白名单里没有任何 smtp.* / notify.* 键, 就算加了表单,fb_set_setting() 也会把值全部丢弃 - 设置页只有「站点信息」「附件存储」两个区块 补上:白名单 15 个键 + 后台「邮件通知」区块 - SMTP 服务器/端口/加密方式(SSL/STARTTLS/不加密) - 登录账号/密码(留空不修改,避免每次重填) - 发件地址/显示名、超时、SSL 校验 - 通知规则:回复通知、每次回复都通知、新反馈通知管理员、发信冷却 - 「发送测试邮件」按钮,AJAX 发完就地显示成功或失败原因, 不用保存再靠猜 ## 3. 每个软件一个主题色 需求:从短链接进不同软件,颜色不同,一眼区分。 - software 表加 color 字段(幂等迁移) - 全站配色靠 --brand / --brand-600 / --brand-soft 三个变量, 按软件覆写这三个即可,不用为每个软件写一套 CSS - fb_color_variants() 由主色推出深一档(×0.85)与浅一档(往白混 88%) - 未配色的软件按 id 从 8 色调色板取默认色,保证同站不撞色 - 后台:颜色选择器(原生取色 + 8 个预设 + 用默认) - 前台:index / new / thread 都按当前软件注入主题色, meta theme-color 也跟着变 验证:三功能专项 30/30;新旧回归全过 (全新安装 33/33、老基线 25/25、附件 22/22、安装向导 60/60、约束检查 20/20)
This commit is contained in:
+45
@@ -136,9 +136,54 @@ function fb_oss_metadata_token() {
|
||||
return trim((string)$body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动探测本 ECS 实例绑定的 RAM 角色名。
|
||||
*
|
||||
* 元数据接口 GET /latest/meta-data/ram/security-credentials/(末尾带斜杠)
|
||||
* 返回的是「角色名列表」,每行一个。绝大多数实例只绑一个角色。
|
||||
* 所以用户完全不需要知道角色叫什么 —— 我们去问机器就行。
|
||||
*
|
||||
* @return array [bool $ok, string $role|string $err]
|
||||
*/
|
||||
function fb_oss_detect_instance_role() {
|
||||
$url = fb_oss_metadata_base() . '/latest/meta-data/ram/security-credentials/';
|
||||
$headers = [];
|
||||
$tok = fb_oss_metadata_token();
|
||||
if ($tok !== '') { $headers[] = 'X-aliyun-ECS-Metadata-Token: ' . $tok; }
|
||||
|
||||
list($st, , $body) = fb_http('GET', $url, [
|
||||
'timeout' => 3, 'noproxy' => true, 'headers' => $headers,
|
||||
]);
|
||||
if ($st < 200 || $st >= 300) {
|
||||
return [false, '读不到 ECS 元数据(HTTP ' . $st . ')。不在 ECS 上,或元数据服务被禁用。'];
|
||||
}
|
||||
$txt = trim((string)$body);
|
||||
if ($txt === '') {
|
||||
return [false, '这台 ECS 实例没有绑定任何 RAM 角色。请在阿里云控制台给实例绑定一个角色,再回来点「自动探测」。'];
|
||||
}
|
||||
// 可能是多行(多角色)或 JSON 数组,两种都兼容
|
||||
$names = [];
|
||||
$j = json_decode($txt, true);
|
||||
if (is_array($j)) {
|
||||
foreach ($j as $v) { if (is_string($v) && trim($v) !== '') { $names[] = trim($v); } }
|
||||
} else {
|
||||
foreach (preg_split('/\r?\n/', $txt) as $line) {
|
||||
$line = trim($line);
|
||||
if ($line !== '') { $names[] = $line; }
|
||||
}
|
||||
}
|
||||
if (!$names) { return [false, '元数据返回内容无法识别为角色名。']; }
|
||||
return [true, $names[0]]; // 多角色时取第一个,后台会提示可手改
|
||||
}
|
||||
|
||||
/** 从 ECS 元数据读取实例 RAM 角色凭证 @return array [bool, array|string] */
|
||||
function fb_oss_instance_creds() {
|
||||
$role = trim((string)fb_oss_cfg('instance_role', ''));
|
||||
// 没填就自动探测一次,免得用户还要去控制台查角色名
|
||||
if ($role === '') {
|
||||
list($ok, $r) = fb_oss_detect_instance_role();
|
||||
if ($ok) { $role = (string)$r; }
|
||||
}
|
||||
if ($role === '') { return [false, '未配置 oss.instance_role']; }
|
||||
|
||||
$url = fb_oss_metadata_base() . '/latest/meta-data/ram/security-credentials/' . rawurlencode($role);
|
||||
|
||||
Reference in New Issue
Block a user