refresh user

This commit is contained in:
john 2025-05-19 09:23:15 +02:00
parent 57e56dc33d
commit 17c9885ccc
6 changed files with 127 additions and 20 deletions

View file

@ -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,
}) })

View file

@ -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>
) )

View file

@ -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

View file

@ -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
}
} }

View 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}</>
}

View file

@ -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
} }