import React, { useEffect, useState } from 'react'; import { Button, Divider, Form, Grid, Header, Modal, Message } from 'semantic-ui-react'; import { API, removeTrailingSlash, showError } from '../helpers'; const SystemSetting = () => { let [inputs, setInputs] = useState({ PasswordLoginEnabled: '', PasswordRegisterEnabled: '', EmailVerificationEnabled: '', GitHubOAuthEnabled: '', GitHubClientId: '', GitHubClientSecret: '', LarkClientId: '', LarkClientSecret: '', Notice: '', SMTPServer: '', SMTPPort: '', SMTPAccount: '', SMTPFrom: '', SMTPToken: '', ServerAddress: '', Footer: '', WeChatAuthEnabled: '', WeChatServerAddress: '', WeChatServerToken: '', WeChatAccountQRCodeImageURL: '', MessagePusherAddress: '', MessagePusherToken: '', 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) => { 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(','); } 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 === 'GitHubClientId' || name === 'GitHubClientSecret' || name === 'LarkClientId' || name === 'LarkClientSecret' || name === 'WeChatServerAddress' || name === 'WeChatServerToken' || name === 'WeChatAccountQRCodeImageURL' || name === 'TurnstileSiteKey' || name === 'TurnstileSecretKey' || name === 'EmailDomainWhitelist' ) { setInputs((inputs) => ({ ...inputs, [name]: value })); } else { await updateOption(name, value); } }; const submitServerAddress = async () => { let ServerAddress = removeTrailingSlash(inputs.ServerAddress); await updateOption('ServerAddress', ServerAddress); }; 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 submitMessagePusher = async () => { if (originInputs['MessagePusherAddress'] !== inputs.MessagePusherAddress) { await updateOption( 'MessagePusherAddress', removeTrailingSlash(inputs.MessagePusherAddress) ); } if ( originInputs['MessagePusherToken'] !== inputs.MessagePusherToken && inputs.MessagePusherToken !== '' ) { await updateOption('MessagePusherToken', inputs.MessagePusherToken); } }; 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 submitLarkOAuth = async () => { if (originInputs['LarkClientId'] !== inputs.LarkClientId) { await updateOption('LarkClientId', inputs.LarkClientId); } if ( originInputs['LarkClientSecret'] !== inputs.LarkClientSecret && inputs.LarkClientSecret !== '' ) { await updateOption('LarkClientSecret', inputs.LarkClientSecret); } }; 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 (
General Settings
Update Server Address
Configure Login/Registration
{ showPasswordWarningModal && setShowPasswordWarningModal(false)} size={'tiny'} style={{ maxWidth: '450px' }} > 警告

Canceling password login will cause all users (including administrators) who have not bound other login methods to be unable to log in via password, confirm cancel?

}
配置邮箱域名白名单 用以防止恶意Users利用临时邮箱批量Sign up
{ submitNewRestrictedDomain(); }}>填入 } onKeyDown={(e) => { if (e.key === 'Enter') { submitNewRestrictedDomain(); } }} autoComplete='new-password' placeholder='Enter新的允许的邮箱域名' value={restrictedDomainInput} onChange={(e, { value }) => { setRestrictedDomainInput(value); }} /> 保存邮箱域名白名单Settings
Configure SMTP To support the system email sending
Save SMTP Settings
Configure GitHub OAuth App To support login & registration via GitHub, Click here Manage your GitHub OAuth App
Fill in the Homepage URL {inputs.ServerAddress} ,Fill in the Authorization callback URL{' '} {`${inputs.ServerAddress}/oauth/github`} Save GitHub OAuth Settings
配置飞书授权Log in 用以支持通过飞书进行Log inSign up, Click here Management你的飞书应用
主页链接填 {inputs.ServerAddress} ,重定向 URL 填{' '} {`${inputs.ServerAddress}/oauth/lark`} 保存飞书 OAuth Settings
Configure WeChat Server To support login & registration via WeChat, Click here Learn about WeChat Server
Save WeChat Server Settings
配置 Message Pusher 用以推送报警信息, Click here 了解 Message Pusher
保存 Message Pusher Settings
Configure Turnstile To support user verification, Click here Manage your Turnstile Sites, recommend selecting Invisible Widget Type
Save Turnstile Settings
); }; export default SystemSetting;