96 lines
3.1 KiB
Markdown
96 lines
3.1 KiB
Markdown
|
|
`API/users.ts`
|
|||
|
|
```ts
|
|||
|
|
|
|||
|
|
export async function login(data: TokenObtainPair): Promise<JwtTokenResponse | null>
|
|||
|
|
|
|||
|
|
export async function refreshToken(data: TokenRefresh): Promise<JwtTokenResponse | null>
|
|||
|
|
|
|||
|
|
export async function verifyToken(data: TokenVerify): Promise<boolean>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`utils/users/UserProvider.tsx`
|
|||
|
|
```tsx
|
|||
|
|
export function UserProvider({ children }: { children: ReactNode }) {
|
|||
|
|
const [user, setUser] = useState<Account | undefined>(() => {
|
|||
|
|
const storedUser = localStorage.getItem('user');
|
|||
|
|
return storedUser ? JSON.parse(storedUser) : undefined;
|
|||
|
|
});
|
|||
|
|
const [tokens, setTokens] = useState<JwtTokenResponse | undefined>(() => {
|
|||
|
|
const storedTokens = localStorage.getItem('tokens');
|
|||
|
|
return storedTokens ? JSON.parse(storedTokens) : undefined;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (tokens?.access) {
|
|||
|
|
localStorage.setItem('tokens', JSON.stringify(tokens));
|
|||
|
|
} else {
|
|||
|
|
localStorage.removeItem('tokens');
|
|||
|
|
}
|
|||
|
|
}, [tokens]);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (user) {
|
|||
|
|
localStorage.setItem('user', JSON.stringify(user));
|
|||
|
|
} else {
|
|||
|
|
localStorage.removeItem('user');
|
|||
|
|
}
|
|||
|
|
}, [user]);
|
|||
|
|
|
|||
|
|
const handleLogin = async (credentials: TokenObtainPair) => {
|
|||
|
|
const tokens = await apiLogin(credentials);
|
|||
|
|
if (tokens) {
|
|||
|
|
setTokens(tokens);
|
|||
|
|
// Здесь можно добавить запрос для получения данных пользователя
|
|||
|
|
setUser({ id: 1, login: credentials.login, is_staff: false, is_active: true } as Account); // TODO
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleLogout = () => {
|
|||
|
|
setUser(undefined);
|
|||
|
|
setTokens(undefined);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const validateToken = async () => {
|
|||
|
|
if (tokens?.access) {
|
|||
|
|
const isValid = await verifyToken({ token: tokens.access });
|
|||
|
|
if (!isValid && tokens.refresh) {
|
|||
|
|
const newTokens = await refreshToken({ refresh: tokens.refresh });
|
|||
|
|
if (newTokens) {
|
|||
|
|
setTokens(newTokens);
|
|||
|
|
} else {
|
|||
|
|
handleLogout();
|
|||
|
|
}
|
|||
|
|
} else if (!isValid) {
|
|||
|
|
handleLogout();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
validateToken().then();
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<UserContext.Provider value={{ user, login: handleLogin, logout: handleLogout }}>
|
|||
|
|
{children}
|
|||
|
|
</UserContext.Provider>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
|
|||
|
|
В частности обрати внимание на эту функцию
|
|||
|
|
```ts
|
|||
|
|
const handleLogin = async (credentials: TokenObtainPair) => {
|
|||
|
|
const tokens = await apiLogin(credentials);
|
|||
|
|
if (tokens) {
|
|||
|
|
setTokens(tokens);
|
|||
|
|
// Здесь можно добавить запрос для получения данных пользователя
|
|||
|
|
setUser({ id: 1, login: credentials.login, is_staff: false, is_active: true } as Account); // TODO
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Воспользуйся эндпоинтами /users/auth/users/me/ для получения id текущего пользователя
|
|||
|
|
|