Neda/Front/lib/services/api_service.dart
2026-03-06 19:55:18 +03:30

116 lines
3.8 KiB
Dart

// Backend API endpoints:
// POST /auth/login body: {"username":"...","secret":"..."}
// → {"access_token":"...","token_type":"bearer"}
// GET /groups/me header: Authorization: Bearer TOKEN
// → [{"id":"uuid","name":"...","description":"...","is_active":true}]
//
// LiveKit token از طریق WebSocket دریافت می‌شود:
// WS /ws/groups/{id}?token={jwt}
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../config/app_config.dart';
import '../models/channel.dart';
import 'auth_service.dart';
// ── Fake data (only used when AppConfig.debug == true) ────────────────────
const _fakeChannels = [
{'id': '1', 'name': 'تیم آلفا'},
{'id': '2', 'name': 'پشتیبانی میدانی'},
{'id': '3', 'name': 'فرماندهی'},
{'id': '4', 'name': 'گروه لجستیک'},
{'id': '5', 'name': 'واحد امنیت'},
];
// ─────────────────────────────────────────────────────────────────────────
class ApiService {
final AuthService _auth;
ApiService(this._auth);
Future<Map<String, String>> _headers() async {
final token = await _auth.getToken();
return {
'Content-Type': 'application/json',
if (token != null) 'Authorization': 'Bearer $token',
};
}
// استخراج user_id از JWT token (بدون نیاز به کتابخانه)
String? _extractUserIdFromJwt(String token) {
try {
final parts = token.split('.');
if (parts.length < 2) return null;
// base64url decode payload
var payload = parts[1];
// اضافه کردن padding اگه لازمه
while (payload.length % 4 != 0) {
payload += '=';
}
final decoded = utf8.decode(base64Url.decode(payload));
final map = jsonDecode(decoded) as Map<String, dynamic>;
return map['sub']?.toString();
} catch (_) {
return null;
}
}
Future<bool> login(String username, String secret) async {
if (AppConfig.debug) {
await Future.delayed(const Duration(milliseconds: 600));
await _auth.saveAuth(token: 'debug_jwt', userId: 'debug_user');
return true;
}
try {
final res = await http
.post(
Uri.parse('${AppConfig.baseUrl}/auth/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'username': username, 'secret': secret}),
)
.timeout(const Duration(seconds: 10));
if (res.statusCode == 200) {
final data = jsonDecode(res.body) as Map<String, dynamic>;
final accessToken = data['access_token'] as String?;
if (accessToken == null) return false;
final userId = _extractUserIdFromJwt(accessToken);
await _auth.saveAuth(token: accessToken, userId: userId);
return true;
}
return false;
} catch (_) {
return false;
}
}
Future<List<Channel>> getChannels() async {
if (AppConfig.debug) {
await Future.delayed(const Duration(milliseconds: 500));
return _fakeChannels
.map((e) => Channel.fromJson(e as Map<String, dynamic>))
.toList();
}
try {
final res = await http
.get(
Uri.parse('${AppConfig.baseUrl}/users/me/groups'),
headers: await _headers(),
)
.timeout(const Duration(seconds: 10));
if (res.statusCode == 200) {
final list = jsonDecode(res.body) as List;
return list
.map((e) => Channel.fromJson(e as Map<String, dynamic>))
.toList();
}
return [];
} catch (_) {
return [];
}
}
}