Files
core/scripts/check-graphql-server.js

179 lines
5.3 KiB
JavaScript
Raw Normal View History

[0.9.29] - 2025-09-26 ### 🚨 CRITICAL Security Fixes - **🔒 Open Redirect Protection**: Добавлена строгая валидация redirect_uri против whitelist доменов - **🔒 Rate Limiting**: Защита OAuth endpoints от брутфорса (10 попыток за 5 минут на IP) - **🔒 Logout Endpoint**: Критически важный endpoint для безопасного отзыва httpOnly cookies - **🔒 Provider Validation**: Усиленная валидация OAuth провайдеров с логированием атак - **🚨 GlitchTip Alerts**: Автоматические алерты безопасности в GlitchTip при критических событиях ### 🛡️ Security Modules - **auth/oauth_security.py**: Модуль безопасности OAuth с валидацией и rate limiting + GlitchTip алерты - **auth/logout.py**: Безопасный logout с поддержкой JSON API и browser redirect - **tests/test_oauth_security.py**: Комплексные тесты безопасности (11 тестов) - **tests/test_oauth_glitchtip_alerts.py**: Тесты интеграции с GlitchTip (8 тестов) ### 🔧 OAuth Improvements - **Minimal Flow**: Упрощен до минимума - только httpOnly cookie, нет JWT в URL - **Simple Logic**: Нет error параметра = успех, максимальная простота - **DRY Refactoring**: Устранено дублирование кода в logout и валидации ### 🎯 OAuth Endpoints - **Старт**: `v3.dscrs.site/oauth/{provider}` - с rate limiting и валидацией - **Callback**: `v3.dscrs.site/oauth/{provider}/callback` - безопасный redirect_uri - **Logout**: `v3.dscrs.site/auth/logout` - отзыв httpOnly cookies - **Финализация**: `testing.discours.io/oauth?redirect_url=...` - минимальная схема ### 📊 Security Test Coverage - ✅ Open redirect attack prevention - ✅ Rate limiting protection - ✅ Provider validation - ✅ Safe fallback mechanisms - ✅ Cookie security (httpOnly + Secure + SameSite) - ✅ GlitchTip integration (8 тестов алертов) ### 📝 Documentation - Создан `docs/oauth-minimal-flow.md` - полное описание минимального flow - Обновлена документация OAuth в `docs/auth/oauth.md` - Добавлены security best practices
2025-09-26 21:03:45 +03:00
#!/usr/bin/env node
/**
* 🔍 Проверка доступности GraphQL сервера для Code Generator
*
* Проверяет доступность v3.dscrs.site/graphql и переключается на локальные схемы
* если сервер недоступен (например, в CI окружении Vercel/Netlify)
*/
import { readFileSync, writeFileSync, existsSync } from 'fs'
import { join } from 'path'
const GRAPHQL_URL = 'https://v3.dscrs.site/graphql'
const TIMEOUT = 10000 // 10 секунд
/**
* Проверяет доступность GraphQL сервера
*/
async function checkGraphQLServer() {
try {
console.log('🔍 Проверяем доступность GraphQL сервера...')
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT)
const response = await fetch(GRAPHQL_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'GraphQL-Codegen-Check/1.0'
},
body: JSON.stringify({
query: '{ __typename }'
}),
signal: controller.signal
})
clearTimeout(timeoutId)
if (response.ok) {
console.log('✅ GraphQL сервер доступен')
return true
} else {
console.log(`⚠️ GraphQL сервер вернул статус: ${response.status}`)
return false
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('⏰ Таймаут подключения к GraphQL серверу')
} else {
console.log(`❌ Ошибка подключения к GraphQL серверу: ${error.message}`)
}
return false
}
}
/**
* Создает fallback конфигурацию с локальными схемами
*/
function createFallbackConfig() {
console.log('🔄 Создаем fallback конфигурацию с локальными схемами...')
const fallbackConfig = `import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
overwrite: true,
// 🚨 FALLBACK: Используем локальные схемы вместо удаленного сервера
schema: ['schema/*.graphql'],
documents: ['panel/graphql/queries/**/*.ts', 'panel/**/*.{ts,tsx}', '!panel/graphql/generated/**'],
generates: {
'./panel/graphql/generated/introspection.json': {
plugins: ['introspection'],
config: {
minify: true
}
},
'./panel/graphql/generated/schema.graphql': {
plugins: ['schema-ast'],
config: {
includeDirectives: false
}
},
'./panel/graphql/generated/': {
preset: 'client',
plugins: [],
presetConfig: {
gqlTagName: 'gql',
fragmentMasking: false
},
config: {
scalars: {
DateTime: 'string',
JSON: 'Record<string, any>'
},
skipTypename: false,
useTypeImports: true,
dedupeOperationSuffix: true,
dedupeFragments: true,
avoidOptionals: false,
enumsAsTypes: false
}
}
},
config: {
skipTypename: false,
useTypeImports: true,
dedupeOperationSuffix: true,
dedupeFragments: true,
avoidOptionals: false,
enumsAsTypes: false
}
}
export default config`
writeFileSync('codegen.fallback.ts', fallbackConfig)
console.log('✅ Fallback конфигурация создана: codegen.fallback.ts')
}
/**
* Проверяет наличие локальных схем
*/
function checkLocalSchemas() {
const schemaFiles = [
'schema/admin.graphql',
'schema/enum.graphql',
'schema/input.graphql',
'schema/mutation.graphql',
'schema/query.graphql',
'schema/type.graphql'
]
const missingFiles = schemaFiles.filter(file => !existsSync(file))
if (missingFiles.length > 0) {
console.log('❌ Отсутствуют локальные схемы:')
missingFiles.forEach(file => console.log(` - ${file}`))
return false
}
console.log('✅ Все локальные схемы найдены')
return true
}
/**
* Основная функция
*/
async function main() {
const isCI = process.env.CI === 'true' || process.env.VERCEL || process.env.NETLIFY
if (isCI) {
console.log('🏗️ CI окружение обнаружено, используем локальные схемы')
}
const serverAvailable = await checkGraphQLServer()
if (!serverAvailable || isCI) {
if (!checkLocalSchemas()) {
console.log('❌ Локальные схемы недоступны, сборка невозможна')
process.exit(1)
}
createFallbackConfig()
// Обновляем package.json для использования fallback конфигурации
const packageJson = JSON.parse(readFileSync('package.json', 'utf8'))
packageJson.scripts.codegen = 'graphql-codegen --config codegen.fallback.ts'
writeFileSync('package.json', JSON.stringify(packageJson, null, 2))
console.log('🔄 package.json обновлен для использования fallback конфигурации')
} else {
console.log('✅ Используем удаленный GraphQL сервер')
}
}
main().catch(error => {
console.error('💥 Критическая ошибка:', error)
process.exit(1)
})