callSecureOps static method
Calls secureOps. On web, uses secureOpsWeb (HTTP with CORS). On mobile, uses the callable secureOps via Firebase SDK.
Implementation
static Future<Map<String, dynamic>> callSecureOps(Map<String, dynamic> data) async {
if (kIsWeb) {
final user = FirebaseAuth.instance.currentUser;
final isPublicAction = data['action'] == 'getConfig';
if (user == null && !isPublicAction) {
throw Exception('Authentication required — user not logged in');
}
final url = Uri.parse(_getSecureOpsWebUrl());
final token = user != null ? await user.getIdToken() : null;
final headers = <String, String>{
'Content-Type': 'application/json',
if (token != null) 'Authorization': 'Bearer $token',
};
final response = await http.post(
url,
headers: headers,
body: jsonEncode({'data': data}),
);
if (response.statusCode != 200) {
throw Exception('secureOpsWeb HTTP ${response.statusCode}: ${response.body}');
}
final body = jsonDecode(response.body);
if (body is Map<String, dynamic>) {
if (body['error'] != null) {
final err = body['error'];
throw Exception(err is Map ? (err['message'] ?? 'Unknown error') : err.toString());
}
// onCall wraps in 'result', HTTP returns directly
if (body.containsKey('result') && body['result'] is Map) {
return body['result'] as Map<String, dynamic>;
}
return body;
}
return {};
}
// Mobile: use Firebase SDK callable
final callable = FirebaseFunctions.instance.httpsCallable('secureOps');
final result = await callable.call<Map<String, dynamic>>(data);
return result.data;
}