Files
core/scripts/check-graphql-server.js
Untone 05c188df62
Some checks failed
Deploy on push / deploy (push) Failing after 39s
[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

179 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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)
})