feat(auth): Refactor mobile authentication config to support whitelist functionality

This commit is contained in:
web@ppanel 2025-02-14 22:13:50 +07:00
parent 5bac933fbc
commit c761ec7538
12 changed files with 92 additions and 49 deletions

View File

@ -24,9 +24,8 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
auth: { auth: {
mobile: { mobile: {
enable: false, enable: false,
limit: 0, enable_whitelist: false,
interval: 0, whitelist: [],
expire_time: 0,
}, },
email: { email: {
enable: false, enable: false,
@ -36,10 +35,6 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
}, },
register: { register: {
stop_register: false, stop_register: false,
enable_trial: false,
trial_subscribe: 0,
trial_time: 0,
trial_time_unit: '',
enable_ip_register_limit: false, enable_ip_register_limit: false,
ip_register_limit: 0, ip_register_limit: 0,
ip_register_limit_duration: 0, ip_register_limit_duration: 0,

View File

@ -1,5 +1,5 @@
// @ts-ignore // @ts-ignore
// API 更新时间: // API 更新时间:
// API 唯一标识: // API 唯一标识:
import * as announcement from './announcement'; import * as announcement from './announcement';

View File

@ -68,7 +68,7 @@ declare namespace API {
type AuthConfig = { type AuthConfig = {
mobile: MobileAuthenticateConfig; mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig; email: EmailAuthticateConfig;
register: RegisterConfig; register: PubilcRegisterConfig;
}; };
type AuthMethodConfig = { type AuthMethodConfig = {
@ -768,9 +768,8 @@ declare namespace API {
type MobileAuthenticateConfig = { type MobileAuthenticateConfig = {
enable: boolean; enable: boolean;
limit: number; enable_whitelist: boolean;
interval: number; whitelist: string[];
expire_time: number;
}; };
type NodeConfig = { type NodeConfig = {
@ -876,6 +875,17 @@ declare namespace API {
list: PlatformInfo[]; list: PlatformInfo[];
}; };
type PubilcRegisterConfig = {
stop_register: boolean;
enable_ip_register_limit: boolean;
ip_register_limit: number;
ip_register_limit_duration: number;
};
type PubilcVerifyCodeConfig = {
verify_code_interval: number;
};
type RegisterConfig = { type RegisterConfig = {
stop_register: boolean; stop_register: boolean;
enable_trial: boolean; enable_trial: boolean;

View File

@ -1,5 +1,5 @@
// @ts-ignore // @ts-ignore
// API 更新时间: // API 更新时间:
// API 唯一标识: // API 唯一标识:
import * as auth from './auth'; import * as auth from './auth';

View File

@ -66,7 +66,7 @@ declare namespace API {
type AuthConfig = { type AuthConfig = {
mobile: MobileAuthenticateConfig; mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig; email: EmailAuthticateConfig;
register: RegisterConfig; register: PubilcRegisterConfig;
}; };
type AuthMethodConfig = { type AuthMethodConfig = {
@ -152,7 +152,7 @@ declare namespace API {
invite: InviteConfig; invite: InviteConfig;
currency: CurrencyConfig; currency: CurrencyConfig;
subscribe: SubscribeConfig; subscribe: SubscribeConfig;
verify_code: VerifyCodeConfig; verify_code: PubilcVerifyCodeConfig;
oauth_methods: string[]; oauth_methods: string[];
}; };
@ -208,9 +208,8 @@ declare namespace API {
type MobileAuthenticateConfig = { type MobileAuthenticateConfig = {
enable: boolean; enable: boolean;
limit: number; enable_whitelist: boolean;
interval: number; whitelist: string[];
expire_time: number;
}; };
type NodeConfig = { type NodeConfig = {
@ -310,6 +309,17 @@ declare namespace API {
enable: boolean; enable: boolean;
}; };
type PubilcRegisterConfig = {
stop_register: boolean;
enable_ip_register_limit: boolean;
ip_register_limit: number;
ip_register_limit_duration: number;
};
type PubilcVerifyCodeConfig = {
verify_code_interval: number;
};
type RegisterConfig = { type RegisterConfig = {
stop_register: boolean; stop_register: boolean;
enable_trial: boolean; enable_trial: boolean;

View File

@ -31,6 +31,8 @@ function MobileBindDialog({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const t = useTranslations('profile.thirdParty'); const t = useTranslations('profile.thirdParty');
const { common } = useGlobalStore();
const { enable_whitelist, whitelist } = common.auth.mobile;
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const formSchema = z.object({ const formSchema = z.object({
@ -88,6 +90,7 @@ function MobileBindDialog({
className='w-32 rounded-r-none border-r-0' className='w-32 rounded-r-none border-r-0'
placeholder='Area code...' placeholder='Area code...'
value={field.value} value={field.value}
whitelist={enable_whitelist ? whitelist : []}
onChange={(value) => { onChange={(value) => {
if (value.phone) { if (value.phone) {
form.setValue(field.name, value.phone); form.setValue(field.name, value.phone);

View File

@ -29,6 +29,7 @@ export default function RegisterForm({
const t = useTranslations('auth.register'); const t = useTranslations('auth.register');
const { common } = useGlobalStore(); const { common } = useGlobalStore();
const { verify, auth, invite } = common; const { verify, auth, invite } = common;
const { enable_whitelist, whitelist } = auth.mobile;
const formSchema = z const formSchema = z
.object({ .object({
@ -87,6 +88,7 @@ export default function RegisterForm({
className='w-32 rounded-r-none border-r-0' className='w-32 rounded-r-none border-r-0'
placeholder='Area code...' placeholder='Area code...'
value={field.value} value={field.value}
whitelist={enable_whitelist ? whitelist : []}
onChange={(value) => { onChange={(value) => {
if (value.phone) { if (value.phone) {
form.setValue('telephone_area_code', value.phone); form.setValue('telephone_area_code', value.phone);

View File

@ -30,9 +30,8 @@ export const useGlobalStore = create<GlobalStore>((set, get) => ({
auth: { auth: {
mobile: { mobile: {
enable: false, enable: false,
limit: 0, enable_whitelist: false,
interval: 0, whitelist: [],
expire_time: 0,
}, },
email: { email: {
enable: false, enable: false,
@ -42,10 +41,6 @@ export const useGlobalStore = create<GlobalStore>((set, get) => ({
}, },
register: { register: {
stop_register: false, stop_register: false,
enable_trial: false,
trial_subscribe: 0,
trial_time: 0,
trial_time_unit: '',
enable_ip_register_limit: false, enable_ip_register_limit: false,
ip_register_limit: 0, ip_register_limit: 0,
ip_register_limit_duration: 0, ip_register_limit_duration: 0,

View File

@ -1,5 +1,5 @@
// @ts-ignore // @ts-ignore
// API 更新时间: // API 更新时间:
// API 唯一标识: // API 唯一标识:
import * as auth from './auth'; import * as auth from './auth';

View File

@ -66,7 +66,7 @@ declare namespace API {
type AuthConfig = { type AuthConfig = {
mobile: MobileAuthenticateConfig; mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig; email: EmailAuthticateConfig;
register: RegisterConfig; register: PubilcRegisterConfig;
}; };
type AuthMethodConfig = { type AuthMethodConfig = {
@ -152,7 +152,7 @@ declare namespace API {
invite: InviteConfig; invite: InviteConfig;
currency: CurrencyConfig; currency: CurrencyConfig;
subscribe: SubscribeConfig; subscribe: SubscribeConfig;
verify_code: VerifyCodeConfig; verify_code: PubilcVerifyCodeConfig;
oauth_methods: string[]; oauth_methods: string[];
}; };
@ -208,9 +208,8 @@ declare namespace API {
type MobileAuthenticateConfig = { type MobileAuthenticateConfig = {
enable: boolean; enable: boolean;
limit: number; enable_whitelist: boolean;
interval: number; whitelist: string[];
expire_time: number;
}; };
type NodeConfig = { type NodeConfig = {
@ -310,6 +309,17 @@ declare namespace API {
enable: boolean; enable: boolean;
}; };
type PubilcRegisterConfig = {
stop_register: boolean;
enable_ip_register_limit: boolean;
ip_register_limit: number;
ip_register_limit_duration: number;
};
type PubilcVerifyCodeConfig = {
verify_code_interval: number;
};
type RegisterConfig = { type RegisterConfig = {
stop_register: boolean; stop_register: boolean;
enable_trial: boolean; enable_trial: boolean;

View File

@ -60,7 +60,7 @@ declare namespace API {
type AuthConfig = { type AuthConfig = {
mobile: MobileAuthenticateConfig; mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig; email: EmailAuthticateConfig;
register: RegisterConfig; register: PubilcRegisterConfig;
}; };
type AuthMethodConfig = { type AuthMethodConfig = {
@ -264,9 +264,8 @@ declare namespace API {
type MobileAuthenticateConfig = { type MobileAuthenticateConfig = {
enable: boolean; enable: boolean;
limit: number; enable_whitelist: boolean;
interval: number; whitelist: string[];
expire_time: number;
}; };
type NodeConfig = { type NodeConfig = {
@ -372,6 +371,17 @@ declare namespace API {
deduction_amount: number; deduction_amount: number;
}; };
type PubilcRegisterConfig = {
stop_register: boolean;
enable_ip_register_limit: boolean;
ip_register_limit: number;
ip_register_limit_duration: number;
};
type PubilcVerifyCodeConfig = {
verify_code_interval: number;
};
type PurchaseOrderRequest = { type PurchaseOrderRequest = {
subscribe_id: number; subscribe_id: number;
quantity: number; quantity: number;

View File

@ -22,21 +22,27 @@ interface AreaCodeSelectProps {
className?: string; className?: string;
placeholder?: string; placeholder?: string;
simple?: boolean; simple?: boolean;
whitelist?: string[];
} }
const items = countries const filterItems = (whitelist?: string[]) => {
.filter((item) => !!item.phone) const baseItems = countries
.map((item) => { .filter((item) => !!item.phone)
const phones = item.phone!.split(','); .map((item) => {
if (phones.length > 1) { const phones = item.phone!.split(',');
return [...phones].map((phone) => ({ if (phones.length > 1) {
...item, return [...phones].map((phone) => ({
phone, ...item,
})); phone,
} }));
return item; }
}) return item;
.flat(); })
.flat();
if (!whitelist?.length) return baseItems;
return baseItems.filter((item) => whitelist.includes(item.phone!));
};
export const AreaCodeSelect = ({ export const AreaCodeSelect = ({
value, value,
@ -44,16 +50,18 @@ export const AreaCodeSelect = ({
className, className,
placeholder = 'Select Area Code', placeholder = 'Select Area Code',
simple = false, simple = false,
whitelist,
}: AreaCodeSelectProps) => { }: AreaCodeSelectProps) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [selectedItem, setSelectedItem] = useState<ICountry | undefined>(); const [selectedItem, setSelectedItem] = useState<ICountry | undefined>();
const items = filterItems(whitelist);
useEffect(() => { useEffect(() => {
if (value !== selectedItem?.phone) { if (value !== selectedItem?.phone) {
const found = items.find((item) => item.phone === value); const found = items.find((item) => item.phone === value);
setSelectedItem(found); setSelectedItem(found);
} }
}, [selectedItem?.phone, value]); }, [selectedItem?.phone, value, items]);
return ( return (
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>