stuff
This commit is contained in:
parent
341a78774f
commit
83b776c00e
9 changed files with 156 additions and 17 deletions
|
|
@ -54,11 +54,12 @@ class PackDtoConverter {
|
|||
tip: available
|
||||
? null
|
||||
: canOpenForAdVal
|
||||
? TextPackTip(
|
||||
'📺',
|
||||
? AssetPackTip(
|
||||
'asset:icons/ad.webp',
|
||||
position: PackTipPosition.bottomRight,
|
||||
)
|
||||
: TextPackTip('🔒'),
|
||||
: AssetPackTip('asset:icons/lock.webp',
|
||||
position: PackTipPosition.bottomRight,),
|
||||
version: model.version,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,44 @@ server {
|
|||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# Static files - no rate limiting (VSCode loads many files simultaneously)
|
||||
location ~ ^/(static|out|node_modules|_next)/ {
|
||||
# No rate limiting for static files
|
||||
proxy_pass http://127.0.0.1:8443;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Cache static files
|
||||
proxy_cache_valid 200 1h;
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
|
||||
# Timeout settings
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
# Static file extensions - no rate limiting
|
||||
location ~ \.(js|css|woff|woff2|ttf|eot|png|jpg|jpeg|gif|svg|ico|webp|map|json)$ {
|
||||
# No rate limiting for static file extensions
|
||||
proxy_pass http://127.0.0.1:8443;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Cache static files
|
||||
proxy_cache_valid 200 1h;
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
|
||||
# Timeout settings
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
# Special rate limiting for login attempts
|
||||
location /login {
|
||||
# Strict rate limiting for login
|
||||
|
|
@ -62,9 +100,10 @@ server {
|
|||
}
|
||||
|
||||
# Proxy to code-server running on port 8443
|
||||
# Increased rate limit for API and dynamic content
|
||||
location / {
|
||||
# Apply rate limiting
|
||||
limit_req zone=vscode_general burst=10 nodelay;
|
||||
# Increased rate limiting (200 requests per minute with burst of 50)
|
||||
limit_req zone=vscode_general burst=50 nodelay;
|
||||
limit_req_status 429;
|
||||
|
||||
proxy_pass http://127.0.0.1:8443;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ class _AppInitializerState extends State<_AppInitializer> {
|
|||
log('Auto-login successful, creating UserScope', name: 'App');
|
||||
// Create UserScope only for authenticated users
|
||||
widget.appScope.userScopeHolder.scope!.userStateManager.setUser(user);
|
||||
// Notify router about auth change
|
||||
widget.appScope.userScopeHolder.notifyAuthChanged();
|
||||
log('UserScope created and user set', name: 'App');
|
||||
} else {
|
||||
log('No saved session, starting as guest without UserScope', name: 'App');
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yx_scope/yx_scope.dart';
|
||||
|
||||
import 'user_scope.dart';
|
||||
|
|
@ -8,11 +9,49 @@ import 'user_scope_container.dart';
|
|||
/// Управляет жизненным циклом UserScope
|
||||
class UserScopeHolder extends BaseChildScopeHolder<UserScope,
|
||||
UserScopeContainer, UserScopeParent> {
|
||||
UserScopeHolder(super.parent);
|
||||
UserScopeHolder(super.parent) : _authNotifier = ValueNotifier<bool>(false) {
|
||||
// Подписываемся на изменения состояния scope
|
||||
listen((scope) {
|
||||
_updateAuthNotifier();
|
||||
}, emitImmediately: true);
|
||||
}
|
||||
|
||||
final ValueNotifier<bool> _authNotifier;
|
||||
|
||||
/// Notifier для отслеживания изменений состояния авторизации
|
||||
///
|
||||
/// Используется для обновления роутера при изменении авторизации
|
||||
ValueNotifier<bool> get authNotifier => _authNotifier;
|
||||
|
||||
@override
|
||||
UserScopeContainer createContainer(UserScopeParent parent) {
|
||||
return UserScopeContainer(parent: parent);
|
||||
}
|
||||
|
||||
void _updateAuthNotifier() {
|
||||
final isAuth = isAuthenticated;
|
||||
if (_authNotifier.value != isAuth) {
|
||||
_authNotifier.value = isAuth;
|
||||
}
|
||||
}
|
||||
|
||||
/// Проверяет, авторизован ли пользователь
|
||||
///
|
||||
/// Возвращает true, если UserScope существует и пользователь авторизован
|
||||
bool get isAuthenticated {
|
||||
final userScope = scope;
|
||||
if (userScope == null) {
|
||||
return false;
|
||||
}
|
||||
return userScope.userStateManager.isAuthenticated;
|
||||
}
|
||||
|
||||
/// Уведомляет о изменении состояния авторизации
|
||||
///
|
||||
/// Вызывается после изменения состояния пользователя (логин/логаут)
|
||||
/// для немедленного обновления роутера
|
||||
void notifyAuthChanged() {
|
||||
_updateAuthNotifier();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ class _AuthPageState extends State<AuthPage> {
|
|||
// Notify that UserScope has changed
|
||||
appScope.notifyUserScopeChanged();
|
||||
|
||||
// Notify router about auth change
|
||||
appScope.userScopeHolder.notifyAuthChanged();
|
||||
|
||||
// Navigate to home
|
||||
router.go('/home');
|
||||
} else {
|
||||
|
|
@ -156,6 +159,9 @@ class _AuthPageState extends State<AuthPage> {
|
|||
// Notify that UserScope has changed
|
||||
appScope.notifyUserScopeChanged();
|
||||
|
||||
// Notify router about auth change
|
||||
appScope.userScopeHolder.notifyAuthChanged();
|
||||
|
||||
// Navigate to home
|
||||
router.go('/home');
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -46,13 +46,24 @@ class _ProfilePageState extends State<ProfilePage> {
|
|||
|
||||
if (!mounted) return;
|
||||
|
||||
// UserScope will be automatically disposed when the holder is destroyed
|
||||
// Update user state to guest
|
||||
final userScope = appScope.userScopeHolder.scope;
|
||||
if (userScope != null) {
|
||||
userScope.userStateManager.logout();
|
||||
}
|
||||
|
||||
// Notify that UserScope has changed
|
||||
appScope.notifyUserScopeChanged();
|
||||
|
||||
// Notify router about auth change
|
||||
appScope.userScopeHolder.notifyAuthChanged();
|
||||
|
||||
log('User logged out successfully', name: 'ProfilePage');
|
||||
|
||||
// Navigate to auth page
|
||||
final router = GoRouter.of(context);
|
||||
router.go('/auth');
|
||||
|
||||
// Show success message
|
||||
messenger.showSnackBar(
|
||||
const SnackBar(content: Text('Logged out successfully')),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,30 @@ GoRouter createAppRouter({
|
|||
}) {
|
||||
return GoRouter(
|
||||
initialLocation: '/home',
|
||||
refreshListenable: userScopeHolder.authNotifier,
|
||||
redirect: (context, state) {
|
||||
final isAuthenticated = userScopeHolder.isAuthenticated;
|
||||
final location = state.uri.path;
|
||||
|
||||
// Если пользователь не авторизован
|
||||
if (!isAuthenticated) {
|
||||
// Разрешаем доступ только к странице авторизации
|
||||
if (location == '/auth') {
|
||||
return null; // Разрешить доступ
|
||||
}
|
||||
// Перенаправляем на страницу авторизации
|
||||
return '/auth';
|
||||
}
|
||||
|
||||
// Если пользователь авторизован и пытается зайти на /auth
|
||||
if (location == '/auth') {
|
||||
// Перенаправляем на главную страницу
|
||||
return '/home';
|
||||
}
|
||||
|
||||
// Разрешаем доступ к остальным страницам
|
||||
return null;
|
||||
},
|
||||
routes: [
|
||||
// Главный Shell с Bottom Navigation
|
||||
ShellRoute(
|
||||
|
|
|
|||
|
|
@ -102,9 +102,8 @@ dev_dependencies:
|
|||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# assets:
|
||||
# - assets/images/
|
||||
# - assets/icons/
|
||||
assets:
|
||||
- icons/
|
||||
|
||||
fonts:
|
||||
- family: Nunito
|
||||
|
|
|
|||
|
|
@ -68,11 +68,12 @@ Deployed proper nginx configuration for vscode.mnemo-cards.online:
|
|||
Created the following scripts in `tools/deploy/`:
|
||||
|
||||
1. **fix-vscode-server.sh** - Diagnoses and fixes code-server installation and configuration
|
||||
2. **check-nginx.sh** - Checks nginx status and reloads configuration
|
||||
3. **deploy-vscode-nginx.sh** - Deploys VSCode nginx configuration to server
|
||||
4. **fix-nginx-duplicates.sh** - Removes duplicate nginx configurations
|
||||
5. **test-vscode-from-server.sh** - Tests VSCode connectivity from server
|
||||
6. **test-vscode-final.sh** - Final tests of both URLs
|
||||
2. **fix-vscode-rate-limit.sh** - Fixes 429 errors by updating rate limits in nginx.conf
|
||||
3. **check-nginx.sh** - Checks nginx status and reloads configuration
|
||||
4. **deploy-vscode-nginx.sh** - Deploys VSCode nginx configuration to server
|
||||
5. **fix-nginx-duplicates.sh** - Removes duplicate nginx configurations
|
||||
6. **test-vscode-from-server.sh** - Tests VSCode connectivity from server
|
||||
7. **test-vscode-final.sh** - Final tests of both URLs
|
||||
|
||||
## How to Use
|
||||
|
||||
|
|
@ -143,6 +144,13 @@ nginx -t # Test configuration
|
|||
2. Check nginx error logs: `tail -f /var/log/nginx/error.log`
|
||||
3. Verify proxy_pass uses 127.0.0.1:8443 (not localhost)
|
||||
|
||||
### 429 Too Many Requests
|
||||
If you get `429 (Too Many Requests)` errors when loading VSCode:
|
||||
1. Run the fix script: `./fix-vscode-rate-limit.sh`
|
||||
2. Redeploy nginx config: `./deploy-vscode-nginx.sh`
|
||||
3. The issue is usually caused by too strict rate limiting for static files
|
||||
4. Static files are now excluded from rate limiting automatically
|
||||
|
||||
### SSL Certificate Issues
|
||||
Certificates are managed by Let's Encrypt and stored at:
|
||||
```
|
||||
|
|
@ -173,12 +181,22 @@ code-server (127.0.0.1:8443) - VSCode Server
|
|||
- code-server runs as root user (WorkingDirectory=/root)
|
||||
- Authentication is enabled with password
|
||||
- WebSocket support is enabled for VSCode features
|
||||
- Rate limiting is configured to prevent abuse
|
||||
- Rate limiting is configured to prevent abuse:
|
||||
- General requests: 200 requests/minute (burst: 50)
|
||||
- Login attempts: 5 requests/minute (burst: 2)
|
||||
- Static files (JS, CSS, images): No rate limiting
|
||||
- Automatic restart is configured (Restart=always)
|
||||
- Service is enabled to start on boot (enabled via systemctl)
|
||||
|
||||
## Recent Changes (2025-11-19)
|
||||
## Recent Changes
|
||||
|
||||
### 2025-11-22
|
||||
1. ✅ Fixed 429 (Too Many Requests) error for static files
|
||||
- Excluded static files (`/static/`, `/out/`, file extensions) from rate limiting
|
||||
- Increased general rate limit from 30r/m to 200r/m
|
||||
- Added caching for static files
|
||||
|
||||
### 2025-11-19
|
||||
1. ✅ Fixed code-server service configuration
|
||||
2. ✅ Deployed nginx configuration
|
||||
3. ✅ Fixed IPv6/IPv4 issue (localhost → 127.0.0.1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue