feat: 修复退出登录登录信息未失效
This commit is contained in:
@@ -17,11 +17,17 @@ export class AuthController {
|
||||
|
||||
@Post('/login')
|
||||
async login(ctx: Context) {
|
||||
if (!ctx.session.isNew) {
|
||||
if (ctx.session.user) {
|
||||
return ctx.session.user;
|
||||
}
|
||||
const { code } = ctx.request.body as LoginRequestBody;
|
||||
const { access_token } = await gitea.getToken(code);
|
||||
const { access_token, refresh_token, expires_in } =
|
||||
await gitea.getToken(code);
|
||||
const giteaAuth = {
|
||||
access_token,
|
||||
refresh_token,
|
||||
expires_at: Date.now() + expires_in * 1000,
|
||||
};
|
||||
const giteaUser = await gitea.getUserInfo(access_token);
|
||||
log.debug(this.TAG, 'gitea user: %o', giteaUser);
|
||||
const exist = await prisma.user.findFirst({
|
||||
@@ -61,9 +67,15 @@ export class AuthController {
|
||||
log.debug(this.TAG, '更新用户信息成功 %o', updatedUser);
|
||||
ctx.session.user = updatedUser;
|
||||
}
|
||||
ctx.session.gitea = giteaAuth;
|
||||
return ctx.session.user;
|
||||
}
|
||||
|
||||
@Get('logout')
|
||||
async logout(ctx: Context) {
|
||||
ctx.session.user = null;
|
||||
}
|
||||
|
||||
@Get('info')
|
||||
async info(ctx: Context) {
|
||||
return ctx.session?.user;
|
||||
|
||||
@@ -10,11 +10,10 @@ export class Authorization implements Middleware {
|
||||
|
||||
apply(app: Koa) {
|
||||
app.use(async (ctx: Koa.Context, next: Koa.Next) => {
|
||||
console.log('ctx.path', ctx.path)
|
||||
if (this.ignoreAuth.includes(ctx.path)) {
|
||||
return next();
|
||||
}
|
||||
if (ctx.session.isNew) {
|
||||
if (ctx.session.user == null) {
|
||||
ctx.throw(401, 'Unauthorized');
|
||||
}
|
||||
await next();
|
||||
|
||||
Binary file not shown.
@@ -10,6 +10,7 @@ import { useState } from 'react';
|
||||
import Logo from '@assets/images/logo.svg?react';
|
||||
import { Link, Outlet } from 'react-router';
|
||||
import { useGlobalStore } from '../../stores/global';
|
||||
import { loginService } from '@pages/login/service';
|
||||
|
||||
function Home() {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
@@ -56,18 +57,20 @@ function Home() {
|
||||
<Layout.Header className="h-14 border-b-gray-100 border-b-[1px]">
|
||||
<div className="flex items-center justify-end px-4 h-full">
|
||||
<Dropdown
|
||||
trigger={'click'}
|
||||
droplist={
|
||||
<Menu className="px-3">
|
||||
<Menu.Item key="1">
|
||||
<Menu.Item key="1" onClick={loginService.logout}>
|
||||
<IconExport />
|
||||
<span className="ml-2">退出登录</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<div className="p-2 rounded-xl cursor-pointer flex items-center hover:bg-[rgba(0,0,0,0.03)]">
|
||||
<Avatar size={28}>
|
||||
<div className="p-2 rounded-xl cursor-pointer flex items-center hover:bg-gray-100">
|
||||
<Avatar
|
||||
size={28}
|
||||
className="border-gray-300 border-[1px] border-solid"
|
||||
>
|
||||
<img
|
||||
alt="avatar"
|
||||
src={globalStore.user?.avatar_url.replace('https', 'http')}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { net } from '@shared';
|
||||
import type { AuthURLResponse } from './types';
|
||||
import type { AuthURLResponse, AuthLoginResponse } from './types';
|
||||
import type { NavigateFunction } from 'react-router';
|
||||
import { Notification } from '@arco-design/web-react';
|
||||
import { Message, Notification } from '@arco-design/web-react';
|
||||
import { useGlobalStore } from '../../stores/global';
|
||||
|
||||
class LoginService {
|
||||
async getAuthUrl() {
|
||||
@@ -18,7 +19,7 @@ class LoginService {
|
||||
}
|
||||
|
||||
async login(authCode: string, navigate: NavigateFunction) {
|
||||
const { data, code } = await net.request<AuthURLResponse>({
|
||||
const { data, code } = await net.request<AuthLoginResponse>({
|
||||
method: 'POST',
|
||||
url: '/api/auth/login',
|
||||
data: {
|
||||
@@ -26,14 +27,25 @@ class LoginService {
|
||||
},
|
||||
});
|
||||
if (code === 0) {
|
||||
localStorage.setItem('user', JSON.stringify(data));
|
||||
useGlobalStore.getState().setUser(data);
|
||||
navigate('/');
|
||||
Notification.success({
|
||||
title: '提示',
|
||||
content: '登录成功'
|
||||
content: '登录成功',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async logout() {
|
||||
const { code } = await net.request<AuthURLResponse>({
|
||||
method: 'GET',
|
||||
url: '/api/auth/logout',
|
||||
});
|
||||
if (code === 0) {
|
||||
Message.success('登出成功');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const loginService = new LoginService();
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
import type { APIResponse } from '@shared';
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
username: string;
|
||||
email: string;
|
||||
avatar_url: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export type AuthURLResponse = APIResponse<{
|
||||
url: string;
|
||||
}>
|
||||
}>;
|
||||
|
||||
export type AuthLoginResponse = APIResponse<User>;
|
||||
|
||||
@@ -11,11 +11,13 @@ interface User {
|
||||
|
||||
interface GlobalStore {
|
||||
user: User | null;
|
||||
setUser: (user: User) => void;
|
||||
refreshUser: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useGlobalStore = create<GlobalStore>((set) => ({
|
||||
user: null,
|
||||
setUser: (user: User) => set({ user }),
|
||||
async refreshUser() {
|
||||
const { data } = await net.request<APIResponse<User>>({
|
||||
method: 'GET',
|
||||
|
||||
Reference in New Issue
Block a user