feat(api): implement chestny-znak web app with True API integration

- Fastify backend with auth (CryptoPro CAdES-BES), KM check, UPD parsing
- React frontend with auth page, code check, XML upload, results table
- Client-side signing via crypto-pro 2.3.0 (browser plugin)
- Token caching with auto-refresh, retry with exponential backoff
- Input validation schemas, file size limits, global 401 interceptor
- Docker compose with backend + frontend (nginx) services
This commit is contained in:
kislovdm
2026-07-08 16:53:35 +03:00
parent d2819ff03c
commit 70eac33c8c
19 changed files with 501 additions and 240 deletions
+20 -4
View File
@@ -1,6 +1,17 @@
import type { FastifyInstance } from 'fastify'
import { getAuthKey, signIn } from '../services/auth-service.js'
import { getTokenTTL, hasToken } from '../services/token-cache.js'
import { getAuthKey, signIn, clearToken, isAuthenticated } from '../services/auth-service.js'
import { getTokenTTL } from '../services/token-cache.js'
const signInSchema = {
body: {
type: 'object',
required: ['uuid', 'data'],
properties: {
uuid: { type: 'string' },
data: { type: 'string' },
},
},
}
export async function authRoutes(app: FastifyInstance): Promise<void> {
app.get('/auth/key', async () => {
@@ -8,18 +19,23 @@ export async function authRoutes(app: FastifyInstance): Promise<void> {
return { uuid: authKey.uuid, data: authKey.data }
})
app.post<{ Body: { uuid: string; data: string } }>('/auth/signin', async (request) => {
app.post<{ Body: { uuid: string; data: string } }>('/auth/simpleSignIn', { schema: signInSchema }, async (request) => {
const { uuid, data } = request.body
const result = await signIn({ uuid, data })
return result
})
app.get('/auth/status', async () => {
const authenticated = hasToken()
const authenticated = isAuthenticated()
const ttl = getTokenTTL()
return {
authenticated,
tokenExpiresAt: ttl ? new Date(ttl).toISOString() : null,
}
})
app.post('/auth/logout', async () => {
clearToken()
return { success: true }
})
}