feat(users): govern profiles and access

Normalize fixed profile fields, profile actions, and the five-column capability matrix for comments, uploads, and downloads.
This commit is contained in:
2026-08-13 00:24:54 +08:00
parent 0b06b2c7df
commit 8241570ca2
67 changed files with 780 additions and 1127 deletions
+6 -1
View File
@@ -17,7 +17,12 @@ trait AuthReader {
/** 是否要求注册用户才能评论 */
public static function comment_requires_registration(): bool {
return !empty(self::get_value('comment_require_login', false)) && self::comment_enabled();
if (!self::comment_enabled()) {
return true;
}
$user_id = get_current_user_id();
return !class_exists(Capabilities::class) || !Capabilities::user_can('comment_add', $user_id);
}
/** 是否允许注册 */
+16 -18
View File
@@ -12,7 +12,7 @@ class Capabilities {
/**
* Capability definitions registry.
*
* @return array<string, array{label:string, roles?:string[], exclude_roles?:string[], default?:array<string,mixed>}>
* @return array<string, array{label:string, exclude_roles?:string[], default?:array<string,mixed>}>
*/
public static function cap_definitions(): array {
return [
@@ -20,16 +20,11 @@ class Capabilities {
'balance_transfer' => ['label' => __('余额转账给其他用户', 'aksrt'), 'exclude_roles' => ['all']],
'points_transfer' => ['label' => __('积分转账给其他用户', 'aksrt'), 'exclude_roles' => ['all']],
'balance_withdraw' => ['label' => __('余额提现', 'aksrt'), 'exclude_roles' => ['all']],
'set_user_ban' => ['label' => __('设置用户封禁状态', 'aksrt'), 'roles' => ['cat_moderator'], 'default' => ['cat_moderator' => true]],
'medal_manually_set' => ['label' => __('为用户授予徽章', 'aksrt'), 'roles' => ['cat_moderator'], 'default' => ['cat_moderator' => true]],
'new_post_add' => ['label' => __('发布新文章', 'aksrt'), 'default' => ['logged' => true]],
'new_post_audit_no' => ['label' => __('投稿无需审核直接发布', 'aksrt'), 'exclude_roles' => ['all']],
'new_post_audit_no_manual' => ['label' => __('无需人工审核直接发布', 'aksrt'), 'exclude_roles' => ['all']],
'new_post_upload_img' => ['label' => __('投稿允许上传图片', 'aksrt'), 'exclude_roles' => ['all']],
'new_post_upload_video' => ['label' => __('投稿允许上传视频', 'aksrt'), 'exclude_roles' => ['all']],
'new_post_iframe_video' => ['label' => __('投稿允许插入 iframe 视频', 'aksrt'), 'exclude_roles' => ['all'], 'default' => ['logged' => true]],
'new_post_upload_file' => ['label' => __('投稿允许上传文件', 'aksrt'), 'exclude_roles' => ['all']],
'new_post_hide' => ['label' => __('投稿允许发布隐藏内容', 'aksrt'), 'default' => ['logged' => true]],
'new_post_image_cover' => ['label' => __('发帖允许设置图片封面', 'aksrt'), 'exclude_roles' => ['all']],
'new_post_slide_cover' => ['label' => __('允许设置幻灯片封面', 'aksrt'), 'exclude_roles' => ['all']],
@@ -40,18 +35,26 @@ class Capabilities {
'new_post_delete' => ['label' => __('删除自己发布的投稿', 'aksrt'), 'exclude_roles' => ['all']],
'comment_view' => ['label' => __('查看评论', 'aksrt'), 'default' => ['all' => true]],
'comment_add' => ['label' => __('发表评论', 'aksrt'), 'default' => ['logged' => true]],
'comment_edit' => ['label' => __('修改自己发布的评论', 'aksrt'), 'exclude_roles' => ['all'], 'default' => ['logged' => true]],
'comment_delete' => ['label' => __('删除自己发布的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_audit_no' => ['label' => __('评论无需审核直接发布', 'aksrt'), 'exclude_roles' => ['all']],
'comment_audit_no_manual' => ['label' => __('评论无需人工审核', 'aksrt'), 'exclude_roles' => ['all']],
'comment_set_topping_my_post' => ['label' => __('置顶自己文章下的评论', 'aksrt'), 'exclude_roles' => ['all'], 'default' => ['moderator' => true, 'plate_author' => true, 'cat_moderator' => true]],
'comment_set_topping_other' => ['label' => __('置顶管理帖子下的评论', 'aksrt'), 'roles' => ['moderator', 'plate_author', 'cat_moderator'], 'default' => ['cat_moderator' => true]],
'comment_set_topping_my_post' => ['label' => __('置顶自己文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_set_topping_other' => ['label' => __('置顶其他文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_edit_my_post' => ['label' => __('修改自己文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_edit_other' => ['label' => __('修改管理帖子下的评论', 'aksrt'), 'roles' => ['moderator', 'plate_author', 'cat_moderator'], 'default' => ['cat_moderator' => true]],
'comment_audit_my_post' => ['label' => __('审核自己文章下的评论', 'aksrt'), 'exclude_roles' => ['all'], 'default' => ['moderator' => true, 'plate_author' => true, 'cat_moderator' => true]],
'comment_audit_other' => ['label' => __('审核管理帖子下的评论', 'aksrt'), 'roles' => ['moderator', 'plate_author', 'cat_moderator'], 'default' => ['moderator' => true, 'plate_author' => true, 'cat_moderator' => true]],
'comment_edit_other' => ['label' => __('修改其他文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_audit_my_post' => ['label' => __('审核自己文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_audit_other' => ['label' => __('审核其他文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_delete_my_post' => ['label' => __('删除自己文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'comment_delete_other' => ['label' => __('删除管理帖子下的评论', 'aksrt'), 'roles' => ['moderator', 'plate_author', 'cat_moderator'], 'default' => ['cat_moderator' => true]],
'comment_delete_other' => ['label' => __('删除其他文章下的评论', 'aksrt'), 'exclude_roles' => ['all']],
'upload_avatar' => ['label' => __('上传头像', 'aksrt'), 'default' => ['logged' => true]],
'upload_profile_background' => ['label' => __('上传用户资料卡背景图', 'aksrt'), 'default' => ['logged' => true]],
'upload_submit_image' => ['label' => __('投稿图片上传', 'aksrt'), 'exclude_roles' => ['all']],
'upload_comment_image' => ['label' => __('评论图片上传', 'aksrt'), 'exclude_roles' => ['all']],
'upload_resource_attachment'=> ['label' => __('资源附件上传', 'aksrt'), 'exclude_roles' => ['all']],
'resource_download' => ['label' => __('资源下载', 'aksrt'), 'default' => ['logged' => true]],
];
}
@@ -59,7 +62,7 @@ class Capabilities {
* All role columns in the capability matrix.
*/
public static function cap_role_columns(): array {
return ['all', 'logged', 'level', 'vip', 'auth', 'moderator', 'plate_author', 'cat_moderator'];
return ['all', 'logged', 'level', 'vip', 'auth'];
}
/**
@@ -77,14 +80,9 @@ class Capabilities {
foreach ($defs as $cap_id => $def) {
$defaults = $def['default'] ?? [];
$excludes = $def['exclude_roles'] ?? [];
$only_roles = $def['roles'] ?? null;
$row = [];
foreach ($cols as $col) {
if ($only_roles !== null && !in_array($col, $only_roles, true) && !in_array($col, ['all', 'logged', 'level', 'vip', 'auth'], true)) {
$row[$col] = false;
continue;
}
if (in_array($col, $excludes, true)) {
$row[$col] = false;
continue;
+1 -3
View File
@@ -121,9 +121,7 @@ trait CreditsPaymentGroups {
* Unified paid-content and download policy settings.
*
* @return array{
* download_login:bool,
* download_credit:bool,
* download_captcha:bool,
* default_cost:int,
* paid_post_types:string[],
* vip_free_download:bool,
@@ -194,7 +192,7 @@ trait CreditsPaymentGroups {
/**
* 获取订单设置
*
* @return array{prefix:string,expiry:int,show_user:bool,show_paycount:bool,no_logged_in:bool,cookie_day:int,no_logged_remind:bool,wait_float:bool,order_max_minutes:int,mark:string,box_position:string,free_logged_show:bool,show_ip:bool,show_device:bool,show_order_no:bool,show_create_time:bool,show_pay_time:bool,status_texts:array,service:array}
* @return array{prefix:string,expiry:int,show_user:bool,show_paycount:bool,no_logged_in:bool,cookie_day:int,no_logged_remind:bool,wait_float:bool,order_max_minutes:int,mark:string,box_position:string,show_ip:bool,show_device:bool,show_order_no:bool,show_create_time:bool,show_pay_time:bool,status_texts:array,service:array}
*/
public static function get_order_settings(): array {
return PaymentRuntime::get_order_settings();
-2
View File
@@ -137,9 +137,7 @@ class HomeCms {
public static function get_cms_features(): array {
$defaults = [
'resource_cpt_enabled' => true,
'download_login' => true,
'download_credit' => true,
'download_captcha' => false,
'search_include_resource' => true,
];
$s = Settings::get_all();
-4
View File
@@ -27,9 +27,7 @@ class PaymentRuntime {
}
return [
'download_login' => !empty($features['download_login']),
'download_credit' => !empty($features['download_credit']) && Settings::credits_enabled(),
'download_captcha' => !empty($features['download_captcha']),
'default_cost' => Settings::download_default_cost(),
'paid_post_types' => self::parse_slug_list((string) ($settings['payment_paid_post_types'] ?? 'post'), ['post']),
'vip_free_download' => !empty($settings['payment_vip_free_download']),
@@ -37,7 +35,6 @@ class PaymentRuntime {
'catalog_note' => $catalog_note,
'manual_delivery_note' => $manual_note !== '' ? $manual_note : __('付费或人工确认内容请在订单备注中记录交付方式。', 'aksrt'),
'no_logged_in' => !isset($settings['pay_no_logged_in']) || !empty($settings['pay_no_logged_in']),
'free_logged_show' => !empty($settings['pay_free_logged_show']),
'down_alone_page' => !empty($settings['payment_down_alone_page']),
'display' => [
'mark' => sanitize_text_field((string) ($settings['pay_mark'] ?? '付费')),
@@ -375,7 +372,6 @@ class PaymentRuntime {
'order_max_minutes' => $max_minutes,
'mark' => sanitize_text_field((string) ($s['pay_mark'] ?? '付费')),
'box_position' => $box_position,
'free_logged_show' => !empty($s['pay_free_logged_show']),
'show_ip' => !empty($s['payment_show_ip']),
'show_device' => !empty($s['payment_show_device']),
'show_order_no' => !isset($s['payment_show_order_no']) || !empty($s['payment_show_order_no']),
+1 -2
View File
@@ -461,14 +461,13 @@ class PostDisplay {
'per_page' => max(5, min(100, (int) ($settings['comment_per_page'] ?? 20))),
'nested_depth' => max(1, min(10, (int) ($settings['comment_nested_depth'] ?? 3))),
'require_login' => Settings::comment_requires_registration(),
'allow_reply' => !isset($settings['comment_allow_reply']) || !empty($settings['comment_allow_reply']),
'avatar_size' => max(24, min(96, (int) ($settings['comment_avatar_size'] ?? 48))),
'empty_text' => $empty_text !== '' ? $empty_text : __('暂无评论,来做第一个评论的人吧~', 'aksrt'),
'toolbar' => [
'smilie' => !isset($settings['comment_smilie']) || !empty($settings['comment_smilie']),
'code' => !isset($settings['comment_code']) || !empty($settings['comment_code']),
'image' => !isset($settings['comment_img']) || !empty($settings['comment_img']),
'upload_img' => !empty($settings['comment_upload_img']),
'upload_img' => function_exists('aksrt_user_can') && aksrt_user_can('upload_comment_image', get_current_user_id()),
],
'like_enabled' => !isset($settings['comment_like_s']) || !empty($settings['comment_like_s']),
'author_tag' => !isset($settings['comment_author_tag']) || !empty($settings['comment_author_tag']),
+2 -2
View File
@@ -573,7 +573,7 @@ class Settings {
/**
* Private user-center display settings.
*
* @return array{tabs:string[],avatar_upload:bool,cover_upload:bool,social_links:bool}
* @return array{tabs:string[]}
*/
public static function get_user_center_settings(): array {
return UserRuntime::get_user_center_settings();
@@ -705,7 +705,7 @@ class Settings {
/**
* Comment display and behavior settings.
*
* @return array{order:string,pagination_mode:string,nested_depth:int,require_login:bool,allow_reply:bool,avatar_size:int,empty_text:string}
* @return array{order:string,pagination_mode:string,nested_depth:int,require_login:bool,avatar_size:int,empty_text:string}
*/
public static function get_comment_display_settings(): array {
return PostDisplay::get_comment_display_settings();
+1 -4
View File
@@ -80,7 +80,7 @@ class UserRuntime {
/**
* Private user-center display settings.
*
* @return array{tabs:string[],avatar_upload:bool,cover_upload:bool,social_links:bool}
* @return array{tabs:string[]}
*/
public static function get_user_center_settings(): array {
$settings = Settings::get_all();
@@ -133,9 +133,6 @@ class UserRuntime {
return [
'tabs' => $normalized_tabs,
'avatar_upload' => !isset($settings['allow_avatar_upload']) || !empty($settings['allow_avatar_upload']),
'cover_upload' => !isset($settings['user_cover_upload']) || !empty($settings['user_cover_upload']),
'social_links' => !isset($settings['user_social_links']) || !empty($settings['user_social_links']),
];
}