refresh user
This commit is contained in:
parent
57e56dc33d
commit
17c9885ccc
6 changed files with 127 additions and 20 deletions
|
@ -14,9 +14,7 @@ export async function generateApiSchema(openapiUrl, outputFilePath, pathToPretti
|
||||||
const request = new Request(openapiUrl)
|
const request = new Request(openapiUrl)
|
||||||
const response = await fetch(request)
|
const response = await fetch(request)
|
||||||
const json = await response.text()
|
const json = await response.text()
|
||||||
const ast = await openapiTS(json, {
|
const ast = await openapiTS(json, {})
|
||||||
pathParamsAsTypes: true,
|
|
||||||
})
|
|
||||||
const prettierConfig = await resolveConfig(pathToPrettierRc, {
|
const prettierConfig = await resolveConfig(pathToPrettierRc, {
|
||||||
useCache: true,
|
useCache: true,
|
||||||
})
|
})
|
||||||
|
|
31
src/App.tsx
31
src/App.tsx
|
@ -10,6 +10,7 @@ import LogoutPage from './app/auth/pages/LogoutPage.tsx'
|
||||||
import UnauthorizedHandler from './app/auth/components/UnauthorizedHandler.tsx'
|
import UnauthorizedHandler from './app/auth/components/UnauthorizedHandler.tsx'
|
||||||
import AdminPage from './app/admin/pages/AdminPage.tsx'
|
import AdminPage from './app/admin/pages/AdminPage.tsx'
|
||||||
import SignupCodesManagementPage from './app/admin/pages/subpages/SignupCodesManagementPage.tsx'
|
import SignupCodesManagementPage from './app/admin/pages/subpages/SignupCodesManagementPage.tsx'
|
||||||
|
import RefreshUser from './app/auth/components/RefreshUser.tsx'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const postService = new PostsService()
|
const postService = new PostsService()
|
||||||
|
@ -19,22 +20,24 @@ function App() {
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<UnauthorizedHandler>
|
<UnauthorizedHandler>
|
||||||
<Routes>
|
<RefreshUser authService={authService}>
|
||||||
<Route
|
<Routes>
|
||||||
path={'/'}
|
|
||||||
element={<HomePage postsService={postService} mediaService={mediaService} />}
|
|
||||||
/>
|
|
||||||
<Route path="/u/:username" element={<AuthorPage postsService={postService} />} />
|
|
||||||
<Route path="/login" element={<LoginPage authService={authService} />} />
|
|
||||||
<Route path="/logout" element={<LogoutPage authService={authService} />} />
|
|
||||||
<Route path="/signup/:code?" element={<SignupPage authService={authService} />} />
|
|
||||||
<Route path={'/admin'} element={<AdminPage />}>
|
|
||||||
<Route
|
<Route
|
||||||
path={'codes'}
|
path={'/'}
|
||||||
element={<SignupCodesManagementPage authService={authService} />}
|
element={<HomePage postsService={postService} mediaService={mediaService} />}
|
||||||
/>
|
/>
|
||||||
</Route>
|
<Route path="/u/:username" element={<AuthorPage postsService={postService} />} />
|
||||||
</Routes>
|
<Route path="/login" element={<LoginPage authService={authService} />} />
|
||||||
|
<Route path="/logout" element={<LogoutPage authService={authService} />} />
|
||||||
|
<Route path="/signup/:code?" element={<SignupPage authService={authService} />} />
|
||||||
|
<Route path={'/admin'} element={<AdminPage />}>
|
||||||
|
<Route
|
||||||
|
path={'codes'}
|
||||||
|
element={<SignupCodesManagementPage authService={authService} />}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
</RefreshUser>
|
||||||
</UnauthorizedHandler>
|
</UnauthorizedHandler>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)
|
)
|
||||||
|
|
|
@ -87,8 +87,7 @@ export interface paths {
|
||||||
requestBody: {
|
requestBody: {
|
||||||
content: {
|
content: {
|
||||||
'multipart/form-data': {
|
'multipart/form-data': {
|
||||||
/** Format: binary */
|
file?: components['schemas']['IFormFile']
|
||||||
file?: string
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +111,7 @@ export interface paths {
|
||||||
patch?: never
|
patch?: never
|
||||||
trace?: never
|
trace?: never
|
||||||
}
|
}
|
||||||
[path: `/media/${string}`]: {
|
'/media/{id}': {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: never
|
query?: never
|
||||||
header?: never
|
header?: never
|
||||||
|
@ -266,6 +265,45 @@ export interface paths {
|
||||||
patch?: never
|
patch?: never
|
||||||
trace?: never
|
trace?: never
|
||||||
}
|
}
|
||||||
|
'/auth/user/{userId}': {
|
||||||
|
parameters: {
|
||||||
|
query?: never
|
||||||
|
header?: never
|
||||||
|
path?: never
|
||||||
|
cookie?: never
|
||||||
|
}
|
||||||
|
get: {
|
||||||
|
parameters: {
|
||||||
|
query?: never
|
||||||
|
header?: never
|
||||||
|
path: {
|
||||||
|
userId: string
|
||||||
|
}
|
||||||
|
cookie?: never
|
||||||
|
}
|
||||||
|
requestBody?: never
|
||||||
|
responses: {
|
||||||
|
/** @description OK */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown
|
||||||
|
}
|
||||||
|
content: {
|
||||||
|
'text/plain': components['schemas']['RefreshUserResult']
|
||||||
|
'application/json': components['schemas']['RefreshUserResult']
|
||||||
|
'text/json': components['schemas']['RefreshUserResult']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
put?: never
|
||||||
|
post?: never
|
||||||
|
delete?: never
|
||||||
|
options?: never
|
||||||
|
head?: never
|
||||||
|
patch?: never
|
||||||
|
trace?: never
|
||||||
|
}
|
||||||
'/auth/signup-codes': {
|
'/auth/signup-codes': {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: never
|
query?: never
|
||||||
|
@ -362,6 +400,8 @@ export interface components {
|
||||||
/** Format: uuid */
|
/** Format: uuid */
|
||||||
next: string | null
|
next: string | null
|
||||||
}
|
}
|
||||||
|
/** Format: binary */
|
||||||
|
IFormFile: string
|
||||||
ListSignupCodesResult: {
|
ListSignupCodesResult: {
|
||||||
signupCodes: components['schemas']['SignupCodeDto'][]
|
signupCodes: components['schemas']['SignupCodeDto'][]
|
||||||
}
|
}
|
||||||
|
@ -397,6 +437,12 @@ export interface components {
|
||||||
/** Format: int32 */
|
/** Format: int32 */
|
||||||
height: number | null
|
height: number | null
|
||||||
}
|
}
|
||||||
|
RefreshUserResult: {
|
||||||
|
/** Format: uuid */
|
||||||
|
userId: string
|
||||||
|
username: string
|
||||||
|
isSuperUser: boolean
|
||||||
|
}
|
||||||
RegisterRequest: {
|
RegisterRequest: {
|
||||||
username: string
|
username: string
|
||||||
password: string
|
password: string
|
||||||
|
|
|
@ -63,4 +63,35 @@ export class AuthService {
|
||||||
|
|
||||||
return res.data.signupCodes.map(SignupCode.fromDto)
|
return res.data.signupCodes.map(SignupCode.fromDto)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async refreshUser(userId: string) {
|
||||||
|
if (this.getCookie('hasSession') !== 'true') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await client.GET(`/auth/user/{userId}`, {
|
||||||
|
params: {
|
||||||
|
path: { userId },
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!res.data) {
|
||||||
|
dispatchMessage('auth:user-refresh-failed', null)
|
||||||
|
} else {
|
||||||
|
dispatchMessage('auth:user-refreshed', { ...res.data })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getCookie(cookieName: string): string | undefined {
|
||||||
|
const cookie = document.cookie
|
||||||
|
.split('; ')
|
||||||
|
.map((c) => {
|
||||||
|
const [name, value] = c.split('=')
|
||||||
|
return { name, value }
|
||||||
|
})
|
||||||
|
.find((c) => c.name === cookieName)
|
||||||
|
|
||||||
|
return cookie?.value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
27
src/app/auth/components/RefreshUser.tsx
Normal file
27
src/app/auth/components/RefreshUser.tsx
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { PropsWithChildren, useEffect, useRef } from 'react'
|
||||||
|
import { AuthService } from '../authService.ts'
|
||||||
|
import { useUser } from '../../user/userStore.ts'
|
||||||
|
|
||||||
|
interface RefreshUserProps {
|
||||||
|
authService: AuthService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RefreshUser({
|
||||||
|
authService,
|
||||||
|
children,
|
||||||
|
}: PropsWithChildren<RefreshUserProps>) {
|
||||||
|
const { user } = useUser()
|
||||||
|
const didRefresh = useRef(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timeoutId = setTimeout(async () => {
|
||||||
|
if (didRefresh.current) return
|
||||||
|
if (user == null) return
|
||||||
|
didRefresh.current = true
|
||||||
|
await authService.refreshUser(user.userId)
|
||||||
|
})
|
||||||
|
return () => clearTimeout(timeoutId)
|
||||||
|
}, [authService, user])
|
||||||
|
|
||||||
|
return <>{children}</>
|
||||||
|
}
|
|
@ -5,4 +5,6 @@ export interface MessageTypes {
|
||||||
'auth:registered': User
|
'auth:registered': User
|
||||||
'auth:logged-out': null
|
'auth:logged-out': null
|
||||||
'auth:unauthorized': null
|
'auth:unauthorized': null
|
||||||
|
'auth:user-refreshed': User
|
||||||
|
'auth:user-refresh-failed': null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue