diff --git a/scripts/generate-schema.mjs b/scripts/generate-schema.mjs
index 4381bbf..edc8972 100644
--- a/scripts/generate-schema.mjs
+++ b/scripts/generate-schema.mjs
@@ -14,9 +14,7 @@ export async function generateApiSchema(openapiUrl, outputFilePath, pathToPretti
const request = new Request(openapiUrl)
const response = await fetch(request)
const json = await response.text()
- const ast = await openapiTS(json, {
- pathParamsAsTypes: true,
- })
+ const ast = await openapiTS(json, {})
const prettierConfig = await resolveConfig(pathToPrettierRc, {
useCache: true,
})
diff --git a/src/App.tsx b/src/App.tsx
index 74cc867..6f04dca 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -10,6 +10,7 @@ import LogoutPage from './app/auth/pages/LogoutPage.tsx'
import UnauthorizedHandler from './app/auth/components/UnauthorizedHandler.tsx'
import AdminPage from './app/admin/pages/AdminPage.tsx'
import SignupCodesManagementPage from './app/admin/pages/subpages/SignupCodesManagementPage.tsx'
+import RefreshUser from './app/auth/components/RefreshUser.tsx'
function App() {
const postService = new PostsService()
@@ -19,22 +20,24 @@ function App() {
return (
-
- }
- />
- } />
- } />
- } />
- } />
- }>
+
+
}
+ path={'/'}
+ element={}
/>
-
-
+ } />
+ } />
+ } />
+ } />
+ }>
+ }
+ />
+
+
+
)
diff --git a/src/app/api/schema.ts b/src/app/api/schema.ts
index 32d4ad8..f476eb0 100644
--- a/src/app/api/schema.ts
+++ b/src/app/api/schema.ts
@@ -87,8 +87,7 @@ export interface paths {
requestBody: {
content: {
'multipart/form-data': {
- /** Format: binary */
- file?: string
+ file?: components['schemas']['IFormFile']
}
}
}
@@ -112,7 +111,7 @@ export interface paths {
patch?: never
trace?: never
}
- [path: `/media/${string}`]: {
+ '/media/{id}': {
parameters: {
query?: never
header?: never
@@ -266,6 +265,45 @@ export interface paths {
patch?: 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': {
parameters: {
query?: never
@@ -362,6 +400,8 @@ export interface components {
/** Format: uuid */
next: string | null
}
+ /** Format: binary */
+ IFormFile: string
ListSignupCodesResult: {
signupCodes: components['schemas']['SignupCodeDto'][]
}
@@ -397,6 +437,12 @@ export interface components {
/** Format: int32 */
height: number | null
}
+ RefreshUserResult: {
+ /** Format: uuid */
+ userId: string
+ username: string
+ isSuperUser: boolean
+ }
RegisterRequest: {
username: string
password: string
diff --git a/src/app/auth/authService.ts b/src/app/auth/authService.ts
index a5733d6..293c242 100644
--- a/src/app/auth/authService.ts
+++ b/src/app/auth/authService.ts
@@ -63,4 +63,35 @@ export class AuthService {
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
+ }
}
diff --git a/src/app/auth/components/RefreshUser.tsx b/src/app/auth/components/RefreshUser.tsx
new file mode 100644
index 0000000..34dd268
--- /dev/null
+++ b/src/app/auth/components/RefreshUser.tsx
@@ -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) {
+ 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}>
+}
diff --git a/src/app/messageBus/messageTypes.ts b/src/app/messageBus/messageTypes.ts
index 8d15f6c..080964e 100644
--- a/src/app/messageBus/messageTypes.ts
+++ b/src/app/messageBus/messageTypes.ts
@@ -5,4 +5,6 @@ export interface MessageTypes {
'auth:registered': User
'auth:logged-out': null
'auth:unauthorized': null
+ 'auth:user-refreshed': User
+ 'auth:user-refresh-failed': null
}