This commit is contained in:
longdayi 2024-09-10 11:23:02 +08:00
parent 5630af88ba
commit 6e95554e0c
10 changed files with 65 additions and 63 deletions

View File

@ -10,9 +10,14 @@ import { AuthModule } from './auth/auth.module';
import { ScheduleModule } from '@nestjs/schedule';
import { ConfigService } from '@nestjs/config';
import { TasksModule } from './tasks/tasks.module';
import { JwtModule } from '@nestjs/jwt';
import { env } from './env';
@Module({
imports: [ScheduleModule.forRoot(), TrpcModule, RedisModule, QueueModule, TransformModule, AuthModule, TasksModule],
imports: [ScheduleModule.forRoot(), JwtModule.register({
global: true,
secret: env.JWT_SECRET
}), TrpcModule, RedisModule, QueueModule, TransformModule, AuthModule, TasksModule],
providers: [RedisService, SocketGateway, ConfigService],
})
export class AppModule { }

View File

@ -12,8 +12,6 @@ export class AuthController {
@Get("user-profile")
async getUserProfile(@Req() request: Request) {
const user: JwtPayload = (request as any).user
console.log(user)
// console.log(request)
return this.authService.getUserProfile(user)
}
@Post('login')

View File

@ -15,7 +15,7 @@ export class AuthGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
console.log(token)
if (!token) {
throw new UnauthorizedException();
}
@ -26,7 +26,7 @@ export class AuthGuard implements CanActivate {
secret: env.JWT_SECRET
}
);
// 💡 We're assigning the payload to the request object here
// so that we can access it in our route handlers
request['user'] = payload;
@ -36,7 +36,7 @@ export class AuthGuard implements CanActivate {
return true;
}
private extractTokenFromHeader(request: Request): string | undefined {
extractTokenFromHeader(request: Request): string | undefined {
const [type, token] = request.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined;
}

View File

@ -9,11 +9,6 @@ import { DepartmentService } from '@server/models/department/department.service'
@Module({
providers: [AuthService, StaffService, RoleMapService, DepartmentService],
imports: [JwtModule.register({
global: true,
secret: env.JWT_SECRET,
signOptions: { expiresIn: '60s' },
}),],
controllers: [AuthController],
exports: [AuthService]
})

View File

@ -1,18 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TrpcService } from './trpc.service';
describe('TrpcService', () => {
let service: TrpcService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TrpcService],
}).compile();
service = module.get<TrpcService>(TrpcService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { initTRPC, TRPCError } from '@trpc/server';
import superjson from 'superjson-cjs';
import * as trpcExpress from '@trpc/server/adapters/express';
@ -9,7 +9,7 @@ import { JwtService } from '@nestjs/jwt';
type Context = Awaited<ReturnType<TrpcService['createContext']>>;
@Injectable()
export class TrpcService {
constructor(private readonly jwtService: JwtService) { }
async createContext({
req,
res,
@ -17,10 +17,11 @@ export class TrpcService {
const token = req.headers.authorization?.split(' ')[1];
let tokenData: JwtPayload | undefined = undefined;
let staff: Staff | undefined = undefined;
console.log(token)
if (token) {
try {
// Verify JWT token and extract tokenData
tokenData = await this.jwtService.verifyAsync(token, { secret: env.JWT_SECRET }) as JwtPayload;
const jwtService = new JwtService()
tokenData = await jwtService.verifyAsync(token, { secret: env.JWT_SECRET }) as JwtPayload;
if (tokenData) {
// Fetch staff details from the database using tokenData.id
staff = await db.staff.findUnique({ where: { id: tokenData.sub } });
@ -35,7 +36,7 @@ export class TrpcService {
}
return {
staff,
staff
};
};
trpc = initTRPC.context<Context>().create({

View File

@ -6,13 +6,16 @@ import QueryProvider from './providers/query-provider'
import { router } from './routes';
import { AuthProvider } from './providers/auth-provider';
import ThemeProvider from './providers/theme-provider';
import { App as AntdApp } from 'antd';
function App() {
return (
<AuthProvider>
<QueryProvider>
<ThemeProvider>
<RouterProvider router={router}></RouterProvider>
<AntdApp>
<RouterProvider router={router}></RouterProvider>
</AntdApp>
</ThemeProvider>
</QueryProvider>
</AuthProvider>

View File

@ -8,29 +8,28 @@ import SineWave from '../components/presentation/animation/sine-wave';
const LoginPage: React.FC = () => {
const [showLogin, setShowLogin] = useState(true);
const [registerLoading, setRegisterLoading] = useState(false);
const { login, isAuthenticated } = useAuth();
const { login, isAuthenticated, signup } = useAuth();
const loginFormRef = useRef<any>(null);
const registerFormRef = useRef<any>(null);
const location = useLocation();
const navigate = useNavigate()
const navigate = useNavigate();
const onFinishLogin = async (values: any) => {
try {
const { username, password } = values;
await login(username, password);
message.success('登录成功!');
} catch (err) {
message.warning('用户名或密码错误!');
message.error('用户名或密码错误!');
console.error(err);
}
};
const onFinishRegister = async (values: any) => {
setRegisterLoading(true);
const { username, password, phoneNumber } = values;
try {
// await wp.RegisterUser().create({
// ...values,
// custom_data: { org_unit: values.org_unit },
// });
await signup(username, password, phoneNumber);
message.success('注册成功!');
setShowLogin(true);
loginFormRef.current.submit();
@ -51,13 +50,10 @@ const LoginPage: React.FC = () => {
return (
<div className="flex justify-center items-center h-screen w-full bg-layout">
<div className="flex items-center transition-all overflow-hidden bg-container rounded-xl" style={{ width: 800, height: 600, padding: 0 }}>
<div className="flex items-center transition-all overflow-hidden bg-container rounded-xl " style={{ width: 800, height: 600 }}>
<div className="flex-1 py-10 px-10">
{showLogin ? (
<>
<Link to="/" className="text-gray-400 text-sm hover:text-primary hover:cursor-pointer">
</Link>
<div className="text-center text-2xl text-primary select-none">
<span className="px-2"></span>
</div>
@ -77,33 +73,28 @@ const LoginPage: React.FC = () => {
</Form>
</>
) : (
<>
<div
onClick={() => setShowLogin(true)}
className="text-sm text-gray-400 hover:cursor-pointer hover:text-primary"
>
</div>
<div >
<div className="text-center text-2xl text-primary"></div>
<Form requiredMark="optional" ref={registerFormRef} onFinish={onFinishRegister} layout="vertical" size="large">
<Form.Item name="username" label="用户名" rules={[
{ required: true, message: '请输入用户名' },
{ min: 3, max: 15, message: '用户名长度在 3 到 15 个字符' }
]}>
<Input placeholder="输入用户名" />
<Input />
</Form.Item>
<Form.Item name="deptId" label="单位" rules={[{ required: true, message: '请选择单位' }]}>
<DepartmentSelect />
<Form.Item name="phoneNumber" label="手机号" rules={[
{ required: false },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号' }
]}>
<Input />
</Form.Item>
<Form.Item name="password" label="密码" rules={[
{ required: true, message: '请输入密码' },
{ min: 6, message: '密码长度不能小于 6 位' }
]}>
<Input.Password placeholder="输入密码" />
<Input.Password />
</Form.Item>
<Form.Item name="repeatPass" label="确认密码" dependencies={['password']} hasFeedback rules={[
{ required: true, message: '请再次输入密码' },
({ getFieldValue }) => ({
@ -115,7 +106,7 @@ const LoginPage: React.FC = () => {
}
})
]}>
<Input.Password placeholder="确认密码" />
<Input.Password />
</Form.Item>
<div className="flex items-center justify-center">
@ -124,7 +115,7 @@ const LoginPage: React.FC = () => {
</Button>
</div>
</Form>
</>
</div>
)}
</div>
<div className={`transition-all h-full flex-1 text-white p-10 flex items-center justify-center bg-primary`}>

View File

@ -1,3 +1,6 @@
import { useAuth } from "@web/src/providers/auth-provider"
export default function MainPage() {
return <>hello,world</>
const { user } = useAuth()
return <>hello,{user?.username}</>
}

View File

@ -10,6 +10,7 @@ interface AuthContextProps {
user: UserProfile | null;
login: (username: string, password: string) => Promise<void>;
logout: () => Promise<void>;
signup: (username: string, password: string, phoneNumber?: string) => Promise<void>;
refreshAccessToken: () => Promise<void>;
initializeAuth: () => void;
startTokenRefreshInterval: () => void;
@ -102,6 +103,28 @@ export function AuthProvider({ children }: AuthProviderProps) {
}
};
const signup = async (username: string, password: string, phoneNumber?: string): Promise<void> => {
try {
setIsLoading(true);
const response = await apiClient.post(`/auth/signup`, { username, password, phoneNumber });
// const { access_token, refresh_token, access_token_expires_at, refresh_token_expires_at } = response.data;
// localStorage.setItem('access_token', access_token);
// localStorage.setItem('refresh_token', refresh_token);
// localStorage.setItem('access_token_expires_at', access_token_expires_at);
// localStorage.setItem('refresh_token_expires_at', refresh_token_expires_at);
// setAccessToken(access_token);
// setRefreshToken(refresh_token);
// setIsAuthenticated(true);
// startTokenRefreshInterval();
// fetchUserProfile();
} catch (err) {
console.error("Signup failed", err);
throw new Error("Signup failed");
} finally {
setIsLoading(false);
}
};
const logout = async (): Promise<void> => {
try {
setIsLoading(true);
@ -154,6 +177,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
user,
login,
logout,
signup,
refreshAccessToken,
initializeAuth,
startTokenRefreshInterval,