feat: secure home credentials
This commit is contained in:
@@ -6,22 +6,36 @@ class IgnisApi {
|
||||
final Dio _dio = Dio();
|
||||
Dio get dioInstance => _dio;
|
||||
|
||||
/// Инициализация базового URL и API-ключа
|
||||
void init(String baseUrl, String apiKey) {
|
||||
String url = baseUrl.trim();
|
||||
if (!url.startsWith('http')) {
|
||||
static String normalizeBaseUrl(String baseUrl) {
|
||||
var url = baseUrl.trim();
|
||||
final lowerUrl = url.toLowerCase();
|
||||
if (!lowerUrl.startsWith('http://') && !lowerUrl.startsWith('https://')) {
|
||||
url = 'https://$url';
|
||||
}
|
||||
// Убираем trailing slash
|
||||
if (url.endsWith('/')) url = url.substring(0, url.length - 1);
|
||||
while (url.endsWith('/')) {
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
_dio.options.baseUrl = url;
|
||||
/// Инициализация базового URL и API-ключа
|
||||
void init(String baseUrl, String apiKey) {
|
||||
_dio.options.baseUrl = normalizeBaseUrl(baseUrl);
|
||||
_dio.options.headers['X-API-Key'] = apiKey;
|
||||
// Бэкенд WiZ ламп тормозит -- даём запас
|
||||
_dio.options.connectTimeout = const Duration(seconds: 15);
|
||||
_dio.options.receiveTimeout = const Duration(seconds: 15);
|
||||
}
|
||||
|
||||
Future<void> validateCredentials(String baseUrl, String apiKey) async {
|
||||
final probe = IgnisApi()..init(baseUrl, apiKey);
|
||||
try {
|
||||
await probe.getAuthMe();
|
||||
} finally {
|
||||
probe.dioInstance.close();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Авторизация ───────────────────────────────────────────
|
||||
|
||||
/// Проверка текущего ключа: возвращает {is_admin, name}
|
||||
@@ -40,7 +54,10 @@ class IgnisApi {
|
||||
|
||||
/// Создать группу
|
||||
Future<Response> createGroup(String id, String name, List<String> macs) =>
|
||||
_dio.post('/devices/groups', data: {'id': id, 'name': name, 'macs': macs});
|
||||
_dio.post(
|
||||
'/devices/groups',
|
||||
data: {'id': id, 'name': name, 'macs': macs},
|
||||
);
|
||||
|
||||
/// Удалить группу
|
||||
Future<Response> deleteGroup(String groupId) =>
|
||||
@@ -85,8 +102,7 @@ class IgnisApi {
|
||||
Future<Response> getTasks() => _dio.get('/schedules/tasks');
|
||||
|
||||
/// Отменить задачу расписания
|
||||
Future<Response> cancelTask(String jobId) =>
|
||||
_dio.delete('/schedules/$jobId');
|
||||
Future<Response> cancelTask(String jobId) => _dio.delete('/schedules/$jobId');
|
||||
|
||||
// ─── API-ключи ─────────────────────────────────────────────
|
||||
|
||||
@@ -94,11 +110,8 @@ class IgnisApi {
|
||||
Future<Response> getApiKeys() => _dio.get('/api-keys');
|
||||
|
||||
/// Создать гостевой ключ
|
||||
Future<Response> createApiKey(String name, {bool isAdmin = false}) =>
|
||||
_dio.post('/api-keys', queryParameters: {
|
||||
'name': name,
|
||||
'is_admin': isAdmin,
|
||||
});
|
||||
Future<Response> createApiKey(String name, {bool isAdmin = false}) => _dio
|
||||
.post('/api-keys', queryParameters: {'name': name, 'is_admin': isAdmin});
|
||||
|
||||
/// Отозвать ключ (body: {key: ...})
|
||||
Future<Response> revokeApiKey(String key) =>
|
||||
|
||||
Reference in New Issue
Block a user