mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-09-06 07:57:04 +08:00
feat: add role-based address limit configuration (#741)
- Add RoleAddressConfig component in admin panel - Implement role_address_config API endpoints (GET/POST) - Add getMaxAddressCount function with validation chain - Priority: role config > global settings - Support editable table with clearable input - Add extensible RoleConfig type for future fields - Use context for current user, query DB for target user - Optimize state management (remove redundant roleConfigsMap) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { Context } from 'hono';
|
||||
|
||||
import { CONSTANTS } from '../constants';
|
||||
import { getJsonSetting, saveSetting, checkUserPassword, getDomains, getUserRoles } from '../utils';
|
||||
import { UserSettings, GeoData, UserInfo } from "../models";
|
||||
import { UserSettings, GeoData, UserInfo, RoleAddressConfig } from "../models";
|
||||
import { handleListQuery } from '../common'
|
||||
import UserBindAddressModule from '../user_api/bind_address';
|
||||
import i18n from '../i18n';
|
||||
@@ -166,4 +166,14 @@ export default {
|
||||
results: results,
|
||||
});
|
||||
},
|
||||
getRoleAddressConfig: async (c: Context<HonoCustomType>) => {
|
||||
const value = await getJsonSetting<RoleAddressConfig>(c, CONSTANTS.ROLE_ADDRESS_CONFIG_KEY);
|
||||
const configs = value || {};
|
||||
return c.json({ configs });
|
||||
},
|
||||
saveRoleAddressConfig: async (c: Context<HonoCustomType>) => {
|
||||
const { configs } = await c.req.json<{ configs: RoleAddressConfig }>();
|
||||
await saveSetting(c, CONSTANTS.ROLE_ADDRESS_CONFIG_KEY, JSON.stringify(configs));
|
||||
return c.json({ success: true });
|
||||
},
|
||||
}
|
||||
|
||||
@@ -344,6 +344,8 @@ api.post('/admin/users', admin_user_api.createUser)
|
||||
api.post('/admin/users/:user_id/reset_password', admin_user_api.resetPassword)
|
||||
api.get('/admin/user_roles', async (c) => c.json(getUserRoles(c)))
|
||||
api.post('/admin/user_roles', admin_user_api.updateUserRoles)
|
||||
api.get('/admin/role_address_config', admin_user_api.getRoleAddressConfig)
|
||||
api.post('/admin/role_address_config', admin_user_api.saveRoleAddressConfig)
|
||||
api.get('/admin/users/bind_address/:user_id', admin_user_api.getBindedAddresses)
|
||||
api.post('/admin/users/bind_address', admin_user_api.bindAddress)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export const CONSTANTS = {
|
||||
VERIFIED_ADDRESS_LIST_KEY: 'verified_address_list',
|
||||
NO_LIMIT_SEND_ADDRESS_LIST_KEY: 'no_limit_send_address_list',
|
||||
EMAIL_RULE_SETTINGS_KEY: 'email_rule_settings',
|
||||
ROLE_ADDRESS_CONFIG_KEY: 'role_address_config',
|
||||
|
||||
// KV
|
||||
TG_KV_PREFIX: "temp-mail-telegram",
|
||||
|
||||
@@ -154,3 +154,10 @@ export type EmailRuleSettings = {
|
||||
blockReceiveUnknowAddressEmail: boolean;
|
||||
emailForwardingList: SubdomainForwardAddressList[]
|
||||
}
|
||||
|
||||
export type RoleConfig = {
|
||||
maxAddressCount?: number;
|
||||
// future configs can be added here
|
||||
}
|
||||
|
||||
export type RoleAddressConfig = Record<string, RoleConfig>;
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
import { Context } from 'hono';
|
||||
import { Jwt } from 'hono/utils/jwt'
|
||||
|
||||
import { UserSettings } from "../models";
|
||||
import { UserSettings, RoleAddressConfig } from "../models";
|
||||
import { getJsonSetting } from "../utils"
|
||||
import { CONSTANTS } from "../constants";
|
||||
import { unbindTelegramByAddress } from '../telegram_api/common';
|
||||
import i18n from '../i18n';
|
||||
import { updateAddressUpdatedAt } from '../common';
|
||||
import { updateAddressUpdatedAt, commonGetUserRole } from '../common';
|
||||
|
||||
const getMaxAddressCount = async (
|
||||
c: Context<HonoCustomType>,
|
||||
userRole: string | null | undefined,
|
||||
settings: UserSettings
|
||||
): Promise<number> => {
|
||||
if (!userRole) return settings.maxAddressCount;
|
||||
const roleConfigs = await getJsonSetting<RoleAddressConfig>(c, CONSTANTS.ROLE_ADDRESS_CONFIG_KEY);
|
||||
if (!roleConfigs) return settings.maxAddressCount;
|
||||
const roleMaxCount = roleConfigs[userRole]?.maxAddressCount;
|
||||
if (typeof roleMaxCount !== 'number') return settings.maxAddressCount;
|
||||
if (roleMaxCount <= 0) return settings.maxAddressCount;
|
||||
return roleMaxCount;
|
||||
};
|
||||
|
||||
const UserBindAddressModule = {
|
||||
bind: async (c: Context<HonoCustomType>) => {
|
||||
@@ -43,11 +57,15 @@ const UserBindAddressModule = {
|
||||
// check if binded address count
|
||||
const value = await getJsonSetting(c, CONSTANTS.USER_SETTINGS_KEY);
|
||||
const settings = new UserSettings(value);
|
||||
if (settings.maxAddressCount > 0) {
|
||||
// get user role
|
||||
const userRole = c.get("userRolePayload");
|
||||
// check role-based max address count first, fallback to global settings
|
||||
const maxAddressCount = await getMaxAddressCount(c, userRole, settings);
|
||||
if (maxAddressCount > 0) {
|
||||
const { count } = await c.env.DB.prepare(
|
||||
`SELECT COUNT(*) as count FROM users_address where user_id = ?`
|
||||
).bind(user_id).first<{ count: number }>() || { count: 0 };
|
||||
if (count >= settings.maxAddressCount) {
|
||||
if (count >= maxAddressCount) {
|
||||
return c.text("Max address count reached", 400)
|
||||
}
|
||||
}
|
||||
@@ -194,18 +212,22 @@ const UserBindAddressModule = {
|
||||
// check if target user exists
|
||||
const target_user_id = await c.env.DB.prepare(
|
||||
`SELECT id FROM users where user_email = ?`
|
||||
).bind(target_user_email).first("id");
|
||||
).bind(target_user_email).first<number>("id");
|
||||
if (!target_user_id) {
|
||||
return c.text("Target user not found", 400)
|
||||
}
|
||||
// check target user binded address count
|
||||
const value = await getJsonSetting(c, CONSTANTS.USER_SETTINGS_KEY);
|
||||
const settings = new UserSettings(value);
|
||||
if (settings.maxAddressCount > 0) {
|
||||
// get target user role
|
||||
const userRoleObj = await commonGetUserRole(c, target_user_id);
|
||||
// check role-based max address count first, fallback to global settings
|
||||
const maxAddressCount = await getMaxAddressCount(c, userRoleObj?.role, settings);
|
||||
if (maxAddressCount > 0) {
|
||||
const { count } = await c.env.DB.prepare(
|
||||
`SELECT COUNT(*) as count FROM users_address where user_id = ?`
|
||||
).bind(target_user_id).first<{ count: number }>() || { count: 0 };
|
||||
if (count >= settings.maxAddressCount) {
|
||||
if (count >= maxAddressCount) {
|
||||
return c.text("Target User Max address count reached", 400)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user