CalciumIon 1 год назад
Родитель
Сommit
7db703374c

+ 10 - 1
controller/github.go

@@ -142,8 +142,13 @@ func GitHubOAuth(c *gin.Context) {
 			user.Email = githubUser.Email
 			user.Email = githubUser.Email
 			user.Role = common.RoleCommonUser
 			user.Role = common.RoleCommonUser
 			user.Status = common.UserStatusEnabled
 			user.Status = common.UserStatusEnabled
+			affCode := session.Get("aff")
+			inviterId := 0
+			if affCode != nil {
+				inviterId, _ = model.GetUserIdByAffCode(affCode.(string))
+			}
 
 
-			if err := user.Insert(0); err != nil {
+			if err := user.Insert(inviterId); err != nil {
 				c.JSON(http.StatusOK, gin.H{
 				c.JSON(http.StatusOK, gin.H{
 					"success": false,
 					"success": false,
 					"message": err.Error(),
 					"message": err.Error(),
@@ -227,6 +232,10 @@ func GitHubBind(c *gin.Context) {
 func GenerateOAuthCode(c *gin.Context) {
 func GenerateOAuthCode(c *gin.Context) {
 	session := sessions.Default(c)
 	session := sessions.Default(c)
 	state := common.GetRandomString(12)
 	state := common.GetRandomString(12)
+	affCode := c.Query("aff")
+	if affCode != "" {
+		session.Set("aff", affCode)
+	}
 	session.Set("oauth_state", state)
 	session.Set("oauth_state", state)
 	err := session.Save()
 	err := session.Save()
 	if err != nil {
 	if err != nil {

+ 7 - 1
controller/linuxdo.go

@@ -237,7 +237,13 @@ func LinuxdoOAuth(c *gin.Context) {
 			user.Role = common.RoleCommonUser
 			user.Role = common.RoleCommonUser
 			user.Status = common.UserStatusEnabled
 			user.Status = common.UserStatusEnabled
 
 
-			if err := user.Insert(0); err != nil {
+			affCode := session.Get("aff")
+			inviterId := 0
+			if affCode != nil {
+				inviterId, _ = model.GetUserIdByAffCode(affCode.(string))
+			}
+
+			if err := user.Insert(inviterId); err != nil {
 				c.JSON(http.StatusOK, gin.H{
 				c.JSON(http.StatusOK, gin.H{
 					"success": false,
 					"success": false,
 					"message": err.Error(),
 					"message": err.Error(),

+ 7 - 1
web/src/components/LoginForm.js

@@ -44,8 +44,15 @@ const LoginForm = () => {
   const [turnstileToken, setTurnstileToken] = useState('');
   const [turnstileToken, setTurnstileToken] = useState('');
   let navigate = useNavigate();
   let navigate = useNavigate();
   const [status, setStatus] = useState({});
   const [status, setStatus] = useState({});
+  const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false);
+
   const logo = getLogo();
   const logo = getLogo();
 
 
+  let affCode = new URLSearchParams(window.location.search).get('aff');
+  if (affCode) {
+    localStorage.setItem('aff', affCode);
+  }
+
   useEffect(() => {
   useEffect(() => {
     if (searchParams.get('expired')) {
     if (searchParams.get('expired')) {
       showError('未登录或登录已过期,请重新登录!');
       showError('未登录或登录已过期,请重新登录!');
@@ -61,7 +68,6 @@ const LoginForm = () => {
     }
     }
   }, []);
   }, []);
 
 
-  const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false);
 
 
   const onWeChatLoginClicked = () => {
   const onWeChatLoginClicked = () => {
     setShowWeChatLoginModal(true);
     setShowWeChatLoginModal(true);

+ 157 - 8
web/src/components/RegisterForm.js

@@ -1,10 +1,16 @@
 import React, { useEffect, useState } from 'react';
 import React, { useEffect, useState } from 'react';
 import { Link, useNavigate } from 'react-router-dom';
 import { Link, useNavigate } from 'react-router-dom';
-import { API, getLogo, showError, showInfo, showSuccess } from '../helpers';
+import { API, getLogo, showError, showInfo, showSuccess, updateAPI } from '../helpers';
 import Turnstile from 'react-turnstile';
 import Turnstile from 'react-turnstile';
-import { Button, Card, Form, Layout } from '@douyinfe/semi-ui';
+import { Button, Card, Divider, Form, Icon, Layout, Modal } from '@douyinfe/semi-ui';
 import Title from '@douyinfe/semi-ui/lib/es/typography/title';
 import Title from '@douyinfe/semi-ui/lib/es/typography/title';
 import Text from '@douyinfe/semi-ui/lib/es/typography/text';
 import Text from '@douyinfe/semi-ui/lib/es/typography/text';
+import { IconGithubLogo } from '@douyinfe/semi-icons';
+import { onGitHubOAuthClicked, onLinuxDOOAuthClicked } from './utils.js';
+import LinuxDoIcon from './LinuxDoIcon.js';
+import WeChatIcon from './WeChatIcon.js';
+import TelegramLoginButton from 'react-telegram-login/src';
+import { setUserData } from '../helpers/data.js';
 
 
 const RegisterForm = () => {
 const RegisterForm = () => {
   const [inputs, setInputs] = useState({
   const [inputs, setInputs] = useState({
@@ -20,7 +26,11 @@ const RegisterForm = () => {
   const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
   const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
   const [turnstileToken, setTurnstileToken] = useState('');
   const [turnstileToken, setTurnstileToken] = useState('');
   const [loading, setLoading] = useState(false);
   const [loading, setLoading] = useState(false);
+  const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false);
+  const [status, setStatus] = useState({});
+  let navigate = useNavigate();
   const logo = getLogo();
   const logo = getLogo();
+
   let affCode = new URLSearchParams(window.location.search).get('aff');
   let affCode = new URLSearchParams(window.location.search).get('aff');
   if (affCode) {
   if (affCode) {
     localStorage.setItem('aff', affCode);
     localStorage.setItem('aff', affCode);
@@ -30,6 +40,7 @@ const RegisterForm = () => {
     let status = localStorage.getItem('status');
     let status = localStorage.getItem('status');
     if (status) {
     if (status) {
       status = JSON.parse(status);
       status = JSON.parse(status);
+      setStatus(status);
       setShowEmailVerification(status.email_verification);
       setShowEmailVerification(status.email_verification);
       if (status.turnstile_check) {
       if (status.turnstile_check) {
         setTurnstileEnabled(true);
         setTurnstileEnabled(true);
@@ -38,7 +49,32 @@ const RegisterForm = () => {
     }
     }
   });
   });
 
 
-  let navigate = useNavigate();
+
+  const onWeChatLoginClicked = () => {
+    setShowWeChatLoginModal(true);
+  };
+
+  const onSubmitWeChatVerificationCode = async () => {
+    if (turnstileEnabled && turnstileToken === '') {
+      showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
+      return;
+    }
+    const res = await API.get(
+      `/api/oauth/wechat?code=${inputs.wechat_verification_code}`,
+    );
+    const { success, message, data } = res.data;
+    if (success) {
+      userDispatch({ type: 'login', payload: data });
+      localStorage.setItem('user', JSON.stringify(data));
+      setUserData(data);
+      updateAPI();
+      navigate('/');
+      showSuccess('登录成功!');
+      setShowWeChatLoginModal(false);
+    } else {
+      showError(message);
+    }
+  };
 
 
   function handleChange(name, value) {
   function handleChange(name, value) {
     setInputs((inputs) => ({ ...inputs, [name]: value }));
     setInputs((inputs) => ({ ...inputs, [name]: value }));
@@ -189,14 +225,127 @@ const RegisterForm = () => {
                     </Link>
                     </Link>
                   </Text>
                   </Text>
                 </div>
                 </div>
+                {status.github_oauth ||
+                status.wechat_login ||
+                status.telegram_oauth ||
+                status.linuxdo_oauth ? (
+                  <>
+                    <Divider margin='12px' align='center'>
+                      第三方登录
+                    </Divider>
+                    <div
+                      style={{
+                        display: 'flex',
+                        justifyContent: 'center',
+                        marginTop: 20,
+                      }}
+                    >
+                      {status.github_oauth ? (
+                        <Button
+                          type='primary'
+                          icon={<IconGithubLogo />}
+                          onClick={() =>
+                            onGitHubOAuthClicked(status.github_client_id)
+                          }
+                        />
+                      ) : (
+                        <></>
+                      )}
+                      {status.linuxdo_oauth ? (
+                        <Button
+                          icon={<LinuxDoIcon />}
+                          onClick={() =>
+                            onLinuxDOOAuthClicked(status.linuxdo_client_id)
+                          }
+                        />
+                      ) : (
+                        <></>
+                      )}
+                      {status.wechat_login ? (
+                        <Button
+                          type='primary'
+                          style={{ color: 'rgba(var(--semi-green-5), 1)' }}
+                          icon={<Icon svg={<WeChatIcon />} />}
+                          onClick={onWeChatLoginClicked}
+                        />
+                      ) : (
+                        <></>
+                      )}
+                    </div>
+                    {status.telegram_oauth ? (
+                      <>
+                        <div
+                          style={{
+                            display: 'flex',
+                            justifyContent: 'center',
+                            marginTop: 5,
+                          }}
+                        >
+                          <TelegramLoginButton
+                            dataOnauth={onTelegramLoginClicked}
+                            botName={status.telegram_bot_name}
+                          />
+                        </div>
+                      </>
+                    ) : (
+                      <></>
+                    )}
+                  </>
+                ) : (
+                  <></>
+                )}
               </Card>
               </Card>
+              <Modal
+                title='微信扫码登录'
+                visible={showWeChatLoginModal}
+                maskClosable={true}
+                onOk={onSubmitWeChatVerificationCode}
+                onCancel={() => setShowWeChatLoginModal(false)}
+                okText={'登录'}
+                size={'small'}
+                centered={true}
+              >
+                <div
+                  style={{
+                    display: 'flex',
+                    alignItem: 'center',
+                    flexDirection: 'column',
+                  }}
+                >
+                  <img src={status.wechat_qrcode} />
+                </div>
+                <div style={{ textAlign: 'center' }}>
+                  <p>
+                    微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
+                  </p>
+                </div>
+                <Form size='large'>
+                  <Form.Input
+                    field={'wechat_verification_code'}
+                    placeholder='验证码'
+                    label={'验证码'}
+                    value={inputs.wechat_verification_code}
+                    onChange={(value) =>
+                      handleChange('wechat_verification_code', value)
+                    }
+                  />
+                </Form>
+              </Modal>
               {turnstileEnabled ? (
               {turnstileEnabled ? (
-                <Turnstile
-                  sitekey={turnstileSiteKey}
-                  onVerify={(token) => {
-                    setTurnstileToken(token);
+                <div
+                  style={{
+                    display: 'flex',
+                    justifyContent: 'center',
+                    marginTop: 20,
                   }}
                   }}
-                />
+                >
+                  <Turnstile
+                    sitekey={turnstileSiteKey}
+                    onVerify={(token) => {
+                      setTurnstileToken(token);
+                    }}
+                  />
+                </div>
               ) : (
               ) : (
                 <></>
                 <></>
               )}
               )}

+ 6 - 1
web/src/components/utils.js

@@ -1,7 +1,12 @@
 import { API, showError } from '../helpers';
 import { API, showError } from '../helpers';
 
 
 export async function getOAuthState() {
 export async function getOAuthState() {
-  const res = await API.get('/api/oauth/state');
+  let path = '/api/oauth/state';
+  let affCode = new URLSearchParams(window.location.search).get('aff');
+  if (affCode) {
+    path += `?aff=${affCode}`;
+  }
+  const res = await API.get(path);
   const { success, message, data } = res.data;
   const { success, message, data } = res.data;
   if (success) {
   if (success) {
     return data;
     return data;