import React, {useEffect, useState} from 'react'; import {Button, Divider, Form, Grid, Header, Modal, Message} from 'semantic-ui-react'; import {API, removeTrailingSlash, showError, verifyJSON} from '../helpers'; const SystemSetting = () => { let [inputs, setInputs] = useState({ PasswordLoginEnabled: '', PasswordRegisterEnabled: '', EmailVerificationEnabled: '', GitHubOAuthEnabled: '', GitHubClientId: '', GitHubClientSecret: '', Notice: '', SMTPServer: '', SMTPPort: '', SMTPAccount: '', SMTPFrom: '', SMTPToken: '', ServerAddress: '', EpayId: '', EpayKey: '', Price: 7.3, MinTopUp: 1, TopupGroupRatio: '', PayAddress: '', CustomCallbackAddress: '', Footer: '', WeChatAuthEnabled: '', WeChatServerAddress: '', WeChatServerToken: '', WeChatAccountQRCodeImageURL: '', TurnstileCheckEnabled: '', TurnstileSiteKey: '', TurnstileSecretKey: '', RegisterEnabled: '', EmailDomainRestrictionEnabled: '', EmailDomainWhitelist: '' }); const [originInputs, setOriginInputs] = useState({}); let [loading, setLoading] = useState(false); const [EmailDomainWhitelist, setEmailDomainWhitelist] = useState([]); const [restrictedDomainInput, setRestrictedDomainInput] = useState(''); const [showPasswordWarningModal, setShowPasswordWarningModal] = useState(false); 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(); }, []); const updateOption = async (key, value) => { setLoading(true); switch (key) { case 'PasswordLoginEnabled': case 'PasswordRegisterEnabled': case 'EmailVerificationEnabled': case 'GitHubOAuthEnabled': case 'WeChatAuthEnabled': case 'TurnstileCheckEnabled': case 'EmailDomainRestrictionEnabled': 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 === 'ServerAddress' || 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' ) { setInputs((inputs) => ({...inputs, [name]: value})); } else { await updateOption(name, value); } }; const submitServerAddress = async () => { let ServerAddress = removeTrailingSlash(inputs.ServerAddress); await updateOption('ServerAddress', ServerAddress); }; 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 !== '') { 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 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 (
通用设置
更新服务器地址
支付设置(当前仅支持易支付接口,默认使用上方服务器地址作为回调地址!)
更新支付设置
配置登录注册
{ 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 设置
配置 Turnstile 用以支持用户校验, 点击此处 管理你的 Turnstile Sites,推荐选择 Invisible Widget Type
保存 Turnstile 设置
); }; export default SystemSetting;