import React, { useEffect, useState } from 'react'; import { Button, Divider, Form, Grid, Header, Message, Modal, } from 'semantic-ui-react'; import { API, removeTrailingSlash, showError, verifyJSON } from '../helpers'; import { useTheme } from '../context/Theme'; const SystemSetting = () => { let [inputs, setInputs] = useState({ PasswordLoginEnabled: '', PasswordRegisterEnabled: '', EmailVerificationEnabled: '', GitHubOAuthEnabled: '', GitHubClientId: '', GitHubClientSecret: '', Notice: '', SMTPServer: '', SMTPPort: '', SMTPAccount: '', SMTPFrom: '', SMTPToken: '', ServerAddress: '', WorkerUrl: '', WorkerValidKey: '', EpayId: '', EpayKey: '', Price: 7.3, MinTopUp: 1, TopupGroupRatio: '', PayAddress: '', CustomCallbackAddress: '', Footer: '', WeChatAuthEnabled: '', WeChatServerAddress: '', WeChatServerToken: '', WeChatAccountQRCodeImageURL: '', TurnstileCheckEnabled: '', TurnstileSiteKey: '', TurnstileSecretKey: '', RegisterEnabled: '', EmailDomainRestrictionEnabled: '', EmailAliasRestrictionEnabled: '', SMTPSSLEnabled: '', EmailDomainWhitelist: [], // telegram login TelegramOAuthEnabled: '', TelegramBotToken: '', TelegramBotName: '', }); const [originInputs, setOriginInputs] = useState({}); let [loading, setLoading] = useState(false); const [EmailDomainWhitelist, setEmailDomainWhitelist] = useState([]); const [restrictedDomainInput, setRestrictedDomainInput] = useState(''); const [showPasswordWarningModal, setShowPasswordWarningModal] = useState(false); const theme = useTheme(); const isDark = theme === 'dark'; const getOptions = async () => { const res = await API.get('/api/option/'); const { success, message, data } = res.data; if (success) { let newInputs = {}; data.forEach((item) => { if (item.key === 'TopupGroupRatio') { item.value = JSON.stringify(JSON.parse(item.value), null, 2); } newInputs[item.key] = item.value; }); setInputs({ ...newInputs, EmailDomainWhitelist: newInputs.EmailDomainWhitelist.split(','), }); setOriginInputs(newInputs); setEmailDomainWhitelist( newInputs.EmailDomainWhitelist.split(',').map((item) => { return { key: item, text: item, value: item }; }), ); } else { showError(message); } }; useEffect(() => { getOptions().then(); }, []); useEffect(() => {}, [inputs.EmailDomainWhitelist]); const updateOption = async (key, value) => { setLoading(true); switch (key) { case 'PasswordLoginEnabled': case 'PasswordRegisterEnabled': case 'EmailVerificationEnabled': case 'GitHubOAuthEnabled': case 'WeChatAuthEnabled': case 'TelegramOAuthEnabled': case 'TurnstileCheckEnabled': case 'EmailDomainRestrictionEnabled': case 'EmailAliasRestrictionEnabled': case 'SMTPSSLEnabled': case 'RegisterEnabled': value = inputs[key] === 'true' ? 'false' : 'true'; break; default: break; } const res = await API.put('/api/option/', { key, value, }); const { success, message } = res.data; if (success) { if (key === 'EmailDomainWhitelist') { value = value.split(','); } if (key === 'Price') { value = parseFloat(value); } setInputs((inputs) => ({ ...inputs, [key]: value, })); } else { showError(message); } setLoading(false); }; const handleInputChange = async (e, { name, value }) => { if (name === 'PasswordLoginEnabled' && inputs[name] === 'true') { // block disabling password login setShowPasswordWarningModal(true); return; } if ( name === 'Notice' || (name.startsWith('SMTP') && name !== 'SMTPSSLEnabled') || name === 'ServerAddress' || name === 'WorkerUrl' || name === 'WorkerValidKey' || name === 'EpayId' || name === 'EpayKey' || name === 'Price' || name === 'PayAddress' || name === 'GitHubClientId' || name === 'GitHubClientSecret' || name === 'WeChatServerAddress' || name === 'WeChatServerToken' || name === 'WeChatAccountQRCodeImageURL' || name === 'TurnstileSiteKey' || name === 'TurnstileSecretKey' || name === 'EmailDomainWhitelist' || name === 'TopupGroupRatio' || name === 'TelegramBotToken' || name === 'TelegramBotName' ) { setInputs((inputs) => ({ ...inputs, [name]: value })); } else { await updateOption(name, value); } }; const submitServerAddress = async () => { let ServerAddress = removeTrailingSlash(inputs.ServerAddress); await updateOption('ServerAddress', ServerAddress); }; const submitWorker = async () => { let WorkerUrl = removeTrailingSlash(inputs.WorkerUrl); await updateOption('WorkerUrl', WorkerUrl); if (inputs.WorkerValidKey !== '') { await updateOption('WorkerValidKey', inputs.WorkerValidKey); } } const submitPayAddress = async () => { if (inputs.ServerAddress === '') { showError('请先填写服务器地址'); return; } if (originInputs['TopupGroupRatio'] !== inputs.TopupGroupRatio) { if (!verifyJSON(inputs.TopupGroupRatio)) { showError('充值分组倍率不是合法的 JSON 字符串'); return; } await updateOption('TopupGroupRatio', inputs.TopupGroupRatio); } let PayAddress = removeTrailingSlash(inputs.PayAddress); await updateOption('PayAddress', PayAddress); if (inputs.EpayId !== '') { await updateOption('EpayId', inputs.EpayId); } if (inputs.EpayKey !== undefined && inputs.EpayKey !== '') { await updateOption('EpayKey', inputs.EpayKey); } await updateOption('Price', '' + inputs.Price); }; const submitSMTP = async () => { if (originInputs['SMTPServer'] !== inputs.SMTPServer) { await updateOption('SMTPServer', inputs.SMTPServer); } if (originInputs['SMTPAccount'] !== inputs.SMTPAccount) { await updateOption('SMTPAccount', inputs.SMTPAccount); } if (originInputs['SMTPFrom'] !== inputs.SMTPFrom) { await updateOption('SMTPFrom', inputs.SMTPFrom); } if ( originInputs['SMTPPort'] !== inputs.SMTPPort && inputs.SMTPPort !== '' ) { await updateOption('SMTPPort', inputs.SMTPPort); } if ( originInputs['SMTPToken'] !== inputs.SMTPToken && inputs.SMTPToken !== '' ) { await updateOption('SMTPToken', inputs.SMTPToken); } }; const submitEmailDomainWhitelist = async () => { if ( originInputs['EmailDomainWhitelist'] !== inputs.EmailDomainWhitelist.join(',') && inputs.SMTPToken !== '' ) { await updateOption( 'EmailDomainWhitelist', inputs.EmailDomainWhitelist.join(','), ); } }; const submitWeChat = async () => { if (originInputs['WeChatServerAddress'] !== inputs.WeChatServerAddress) { await updateOption( 'WeChatServerAddress', removeTrailingSlash(inputs.WeChatServerAddress), ); } if ( originInputs['WeChatAccountQRCodeImageURL'] !== inputs.WeChatAccountQRCodeImageURL ) { await updateOption( 'WeChatAccountQRCodeImageURL', inputs.WeChatAccountQRCodeImageURL, ); } if ( originInputs['WeChatServerToken'] !== inputs.WeChatServerToken && inputs.WeChatServerToken !== '' ) { await updateOption('WeChatServerToken', inputs.WeChatServerToken); } }; const submitGitHubOAuth = async () => { if (originInputs['GitHubClientId'] !== inputs.GitHubClientId) { await updateOption('GitHubClientId', inputs.GitHubClientId); } if ( originInputs['GitHubClientSecret'] !== inputs.GitHubClientSecret && inputs.GitHubClientSecret !== '' ) { await updateOption('GitHubClientSecret', inputs.GitHubClientSecret); } }; const submitTelegramSettings = async () => { // await updateOption('TelegramOAuthEnabled', inputs.TelegramOAuthEnabled); await updateOption('TelegramBotToken', inputs.TelegramBotToken); await updateOption('TelegramBotName', inputs.TelegramBotName); }; const submitTurnstile = async () => { if (originInputs['TurnstileSiteKey'] !== inputs.TurnstileSiteKey) { await updateOption('TurnstileSiteKey', inputs.TurnstileSiteKey); } if ( originInputs['TurnstileSecretKey'] !== inputs.TurnstileSecretKey && inputs.TurnstileSecretKey !== '' ) { await updateOption('TurnstileSecretKey', inputs.TurnstileSecretKey); } }; const submitNewRestrictedDomain = () => { const localDomainList = inputs.EmailDomainWhitelist; if ( restrictedDomainInput !== '' && !localDomainList.includes(restrictedDomainInput) ) { setRestrictedDomainInput(''); setInputs({ ...inputs, EmailDomainWhitelist: [...localDomainList, restrictedDomainInput], }); setEmailDomainWhitelist([ ...EmailDomainWhitelist, { key: restrictedDomainInput, text: restrictedDomainInput, value: restrictedDomainInput, }, ]); } }; return (
通用设置
更新服务器地址
代理设置(支持 new-api-worker
更新Worker设置
支付设置(当前仅支持易支付接口,默认使用上方服务器地址作为回调地址!)
更新支付设置
配置登录注册
{showPasswordWarningModal && ( setShowPasswordWarningModal(false)} size={'tiny'} style={{ maxWidth: '450px' }} > 警告

取消密码登录将导致所有未绑定其他登录方式的用户(包括管理员)无法通过密码登录,确认取消?

)}
配置邮箱域名白名单 用以防止恶意用户利用临时邮箱批量注册
{ submitNewRestrictedDomain(); }} > 填入 } onKeyDown={(e) => { if (e.key === 'Enter') { submitNewRestrictedDomain(); } }} autoComplete='new-password' placeholder='输入新的允许的邮箱域名' value={restrictedDomainInput} onChange={(e, { value }) => { setRestrictedDomainInput(value); }} /> 保存邮箱域名白名单设置
配置 SMTP 用以支持系统的邮件发送
保存 SMTP 设置
配置 GitHub OAuth App 用以支持通过 GitHub 进行登录注册, 点击此处 管理你的 GitHub OAuth App
Homepage URL 填 {inputs.ServerAddress} ,Authorization callback URL 填{' '} {`${inputs.ServerAddress}/oauth/github`} 保存 GitHub OAuth 设置
配置 WeChat Server 用以支持通过微信进行登录注册, 点击此处 了解 WeChat Server
保存 WeChat Server 设置
配置 Telegram 登录
保存 Telegram 登录设置
配置 Turnstile 用以支持用户校验, 点击此处 管理你的 Turnstile Sites,推荐选择 Invisible Widget Type
保存 Turnstile 设置
); }; export default SystemSetting;