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