feat: able to delete account by self (#294)
* feat: support account deletion * chore: update style --------- Co-authored-by: JustSong <songquanpeng@foxmail.com>
This commit is contained in:
parent
9b4d1964d4
commit
2fcd6852e0
@ -3,12 +3,13 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"one-api/common"
|
"one-api/common"
|
||||||
"one-api/model"
|
"one-api/model"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/sessions"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoginRequest struct {
|
type LoginRequest struct {
|
||||||
@ -477,6 +478,16 @@ func DeleteUser(c *gin.Context) {
|
|||||||
|
|
||||||
func DeleteSelf(c *gin.Context) {
|
func DeleteSelf(c *gin.Context) {
|
||||||
id := c.GetInt("id")
|
id := c.GetInt("id")
|
||||||
|
user, _ := model.GetUserById(id, false)
|
||||||
|
|
||||||
|
if user.Role == common.RoleRootUser {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"message": "不能删除超级管理员账户",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := model.DeleteUserById(id)
|
err := model.DeleteUserById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
@ -36,7 +36,7 @@ func SetApiRouter(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
selfRoute.GET("/self", controller.GetSelf)
|
selfRoute.GET("/self", controller.GetSelf)
|
||||||
selfRoute.PUT("/self", controller.UpdateSelf)
|
selfRoute.PUT("/self", controller.UpdateSelf)
|
||||||
selfRoute.DELETE("/self", controller.DeleteSelf)
|
selfRoute.DELETE("/self", middleware.TurnstileCheck(), controller.DeleteSelf)
|
||||||
selfRoute.GET("/token", controller.GenerateAccessToken)
|
selfRoute.GET("/token", controller.GenerateAccessToken)
|
||||||
selfRoute.GET("/aff", controller.GetAffCode)
|
selfRoute.GET("/aff", controller.GetAffCode)
|
||||||
selfRoute.POST("/topup", controller.TopUp)
|
selfRoute.POST("/topup", controller.TopUp)
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { Button, Divider, Form, Header, Image, Message, Modal } from 'semantic-ui-react';
|
import { Button, Divider, Form, Header, Image, Message, Modal } from 'semantic-ui-react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
|
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
|
||||||
import Turnstile from 'react-turnstile';
|
import Turnstile from 'react-turnstile';
|
||||||
|
import { UserContext } from '../context/User';
|
||||||
|
|
||||||
const PersonalSetting = () => {
|
const PersonalSetting = () => {
|
||||||
|
const [userState, userDispatch] = useContext(UserContext);
|
||||||
|
let navigate = useNavigate();
|
||||||
|
|
||||||
const [inputs, setInputs] = useState({
|
const [inputs, setInputs] = useState({
|
||||||
wechat_verification_code: '',
|
wechat_verification_code: '',
|
||||||
email_verification_code: '',
|
email_verification_code: '',
|
||||||
email: '',
|
email: '',
|
||||||
|
self_account_deletion_confirmation: ''
|
||||||
});
|
});
|
||||||
const [status, setStatus] = useState({});
|
const [status, setStatus] = useState({});
|
||||||
const [showWeChatBindModal, setShowWeChatBindModal] = useState(false);
|
const [showWeChatBindModal, setShowWeChatBindModal] = useState(false);
|
||||||
const [showEmailBindModal, setShowEmailBindModal] = useState(false);
|
const [showEmailBindModal, setShowEmailBindModal] = useState(false);
|
||||||
|
const [showAccountDeleteModal, setShowAccountDeleteModal] = useState(false);
|
||||||
const [turnstileEnabled, setTurnstileEnabled] = useState(false);
|
const [turnstileEnabled, setTurnstileEnabled] = useState(false);
|
||||||
const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
|
const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
|
||||||
const [turnstileToken, setTurnstileToken] = useState('');
|
const [turnstileToken, setTurnstileToken] = useState('');
|
||||||
@ -72,6 +78,26 @@ const PersonalSetting = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deleteAccount = async () => {
|
||||||
|
if (inputs.self_account_deletion_confirmation !== userState.user.username) {
|
||||||
|
showError('请输入你的账户名以确认删除!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await API.delete('/api/user/self');
|
||||||
|
const { success, message } = res.data;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
showSuccess('账户已删除!');
|
||||||
|
await API.get('/api/user/logout');
|
||||||
|
userDispatch({ type: 'logout' });
|
||||||
|
localStorage.removeItem('user');
|
||||||
|
navigate('/login');
|
||||||
|
} else {
|
||||||
|
showError(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const bindWeChat = async () => {
|
const bindWeChat = async () => {
|
||||||
if (inputs.wechat_verification_code === '') return;
|
if (inputs.wechat_verification_code === '') return;
|
||||||
const res = await API.get(
|
const res = await API.get(
|
||||||
@ -139,6 +165,9 @@ const PersonalSetting = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button onClick={generateAccessToken}>生成系统访问令牌</Button>
|
<Button onClick={generateAccessToken}>生成系统访问令牌</Button>
|
||||||
<Button onClick={getAffLink}>复制邀请链接</Button>
|
<Button onClick={getAffLink}>复制邀请链接</Button>
|
||||||
|
<Button onClick={() => {
|
||||||
|
setShowAccountDeleteModal(true);
|
||||||
|
}}>删除个人账户</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>账号绑定</Header>
|
<Header as='h3'>账号绑定</Header>
|
||||||
{
|
{
|
||||||
@ -246,6 +275,47 @@ const PersonalSetting = () => {
|
|||||||
</Modal.Description>
|
</Modal.Description>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal
|
||||||
|
onClose={() => setShowAccountDeleteModal(false)}
|
||||||
|
onOpen={() => setShowAccountDeleteModal(true)}
|
||||||
|
open={showAccountDeleteModal}
|
||||||
|
size={'tiny'}
|
||||||
|
style={{ maxWidth: '450px' }}
|
||||||
|
>
|
||||||
|
<Modal.Header>确认删除自己的帐户</Modal.Header>
|
||||||
|
<Modal.Content>
|
||||||
|
<Modal.Description>
|
||||||
|
<Form size='large'>
|
||||||
|
<Form.Input
|
||||||
|
fluid
|
||||||
|
placeholder={`输入你的账户名 ${userState.user.username} 以确认删除`}
|
||||||
|
name='self_account_deletion_confirmation'
|
||||||
|
value={inputs.self_account_deletion_confirmation}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
{turnstileEnabled ? (
|
||||||
|
<Turnstile
|
||||||
|
sitekey={turnstileSiteKey}
|
||||||
|
onVerify={(token) => {
|
||||||
|
setTurnstileToken(token);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
color='red'
|
||||||
|
fluid
|
||||||
|
size='large'
|
||||||
|
onClick={deleteAccount}
|
||||||
|
loading={loading}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
</Modal.Description>
|
||||||
|
</Modal.Content>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user