2023-11-19 22:52:40 +01:00
|
|
|
import 'dart:convert';
|
|
|
|
|
|
|
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
|
|
|
|
|
|
import 'package:adguard_home_manager/models/blocked_services.dart';
|
2024-01-24 15:14:19 +01:00
|
|
|
import 'package:adguard_home_manager/models/querylog_config.dart';
|
2024-01-28 20:39:42 +01:00
|
|
|
import 'package:adguard_home_manager/models/statistics_config.dart';
|
2023-11-19 22:52:40 +01:00
|
|
|
import 'package:adguard_home_manager/models/dns_info.dart';
|
|
|
|
import 'package:adguard_home_manager/models/encryption.dart';
|
|
|
|
import 'package:adguard_home_manager/models/dhcp.dart';
|
|
|
|
import 'package:adguard_home_manager/models/rewrite_rules.dart';
|
|
|
|
import 'package:adguard_home_manager/models/filtering.dart';
|
|
|
|
import 'package:adguard_home_manager/models/filtering_status.dart';
|
|
|
|
import 'package:adguard_home_manager/models/server_info.dart';
|
|
|
|
import 'package:adguard_home_manager/models/logs.dart';
|
|
|
|
import 'package:adguard_home_manager/models/clients.dart';
|
|
|
|
import 'package:adguard_home_manager/models/clients_allowed_blocked.dart';
|
|
|
|
import 'package:adguard_home_manager/models/server.dart';
|
|
|
|
import 'package:adguard_home_manager/models/server_status.dart';
|
|
|
|
import 'package:adguard_home_manager/classes/http_client.dart';
|
|
|
|
|
|
|
|
class ApiResponse {
|
|
|
|
final bool successful;
|
|
|
|
final dynamic content;
|
|
|
|
final int? statusCode;
|
|
|
|
|
|
|
|
const ApiResponse({
|
|
|
|
required this.successful,
|
|
|
|
this.content,
|
|
|
|
this.statusCode,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
class ApiClientV2 {
|
|
|
|
final Server server;
|
|
|
|
|
|
|
|
ApiClientV2({
|
|
|
|
required this.server
|
|
|
|
});
|
|
|
|
|
2023-11-20 01:51:35 +01:00
|
|
|
Future<ApiResponse> getServerVersion() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/status', server: server);
|
|
|
|
if (result.successful == true) {
|
2023-12-20 15:50:39 +01:00
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: jsonDecode(result.body!)['version']
|
|
|
|
);
|
|
|
|
} on FormatException {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
} catch (e, stackTrace) {
|
|
|
|
Sentry.captureException(e, stackTrace: stackTrace);
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
2023-11-20 01:51:35 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-19 22:52:40 +01:00
|
|
|
Future<ApiResponse> getServerStatus() async {
|
|
|
|
final results = await Future.wait([
|
|
|
|
HttpRequestClient.get(urlPath: "/stats", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/status", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/filtering/status", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/safesearch/status", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/safebrowsing/status", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/parental/status", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/clients", server: server),
|
|
|
|
]);
|
|
|
|
if (
|
|
|
|
results.map((e) => e.successful).every((e) => e == true) &&
|
|
|
|
results.map((e) => e.body).every((e) => e != null)
|
|
|
|
) {
|
2023-11-23 10:29:21 +01:00
|
|
|
try {
|
|
|
|
final Map<String, dynamic> mappedData = {
|
|
|
|
'stats': jsonDecode(results[0].body!),
|
|
|
|
'clients': jsonDecode(results[6].body!)['clients'],
|
|
|
|
'status': jsonDecode(results[1].body!),
|
|
|
|
'filtering': jsonDecode(results[2].body!),
|
|
|
|
'safeSearch': jsonDecode(results[3].body!),
|
|
|
|
'safeBrowsingEnabled': jsonDecode(results[4].body!),
|
|
|
|
'parentalControlEnabled': jsonDecode(results[5].body!),
|
|
|
|
};
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: ServerStatus.fromJson(mappedData)
|
|
|
|
);
|
|
|
|
} on FormatException {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
} catch (e, stackTrace) {
|
|
|
|
Sentry.captureException(e, stackTrace: stackTrace);
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
2023-11-19 22:52:40 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateFiltering({
|
|
|
|
required bool enable
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: "/filtering/config",
|
|
|
|
server: server,
|
|
|
|
body: {
|
|
|
|
'enabled': enable
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateSafeBrowsing({
|
|
|
|
required bool enable
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: enable == true
|
|
|
|
? "/safebrowsing/enable"
|
|
|
|
: "/safebrowsing/disable",
|
|
|
|
server: server,
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateParentalControl({
|
|
|
|
required bool enable
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: enable == true
|
|
|
|
? "/parental/enable"
|
|
|
|
: "/parental/disable",
|
|
|
|
server: server,
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateGeneralProtection({
|
|
|
|
required bool enable,
|
|
|
|
int? time,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: "/protection",
|
|
|
|
server: server,
|
|
|
|
body: {
|
|
|
|
'enabled': enable,
|
|
|
|
'duration': time
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getClients() async {
|
|
|
|
final results = await Future.wait([
|
|
|
|
HttpRequestClient.get(urlPath: "/clients", server: server),
|
|
|
|
HttpRequestClient.get(urlPath: "/access/list", server: server),
|
|
|
|
]);
|
|
|
|
if (
|
|
|
|
results.map((e) => e.successful).every((e) => e == true) &&
|
|
|
|
results.map((e) => e.body).every((e) => e != null)
|
|
|
|
) {
|
|
|
|
try {
|
|
|
|
final clients = Clients.fromJson(jsonDecode(results[0].body!));
|
|
|
|
clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(results[1].body!));
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: clients
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> requestAllowedBlockedClientsHosts({
|
|
|
|
required Map<String, List<String>?> body
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: "/access/set",
|
|
|
|
server: server,
|
|
|
|
body: body
|
|
|
|
);
|
|
|
|
if (result.statusCode == 400) {
|
|
|
|
return const ApiResponse(
|
|
|
|
successful: false,
|
|
|
|
content: "client_another_list"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getLogs({
|
2024-09-08 18:17:05 +02:00
|
|
|
int? count,
|
2023-11-19 22:52:40 +01:00
|
|
|
int? offset,
|
|
|
|
DateTime? olderThan,
|
|
|
|
String? responseStatus,
|
|
|
|
String? search
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.get(
|
2024-09-08 18:17:05 +02:00
|
|
|
urlPath: '/querylog?${count != null ? 'limit=$count' : ''}${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}',
|
2023-11-19 22:52:40 +01:00
|
|
|
server: server
|
|
|
|
);
|
|
|
|
if (result.successful == true) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: LogsData.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getFilteringRules() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/filtering/status', server: server);
|
|
|
|
if (result.successful == true) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: FilteringStatus.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> postFilteringRules({
|
|
|
|
required Map<String, List<String>> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/set_rules',
|
|
|
|
server: server,
|
|
|
|
body: data
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> postAddClient({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/clients/add',
|
|
|
|
server: server,
|
|
|
|
body: data
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> postUpdateClient({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/clients/update',
|
|
|
|
server: server,
|
|
|
|
body: data
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> postDeleteClient({
|
|
|
|
required String name,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/clients/delete',
|
|
|
|
server: server,
|
|
|
|
body: {'name': name},
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getFiltering() async {
|
|
|
|
final results = await Future.wait([
|
|
|
|
HttpRequestClient.get(urlPath: '/filtering/status', server: server),
|
|
|
|
HttpRequestClient.get(urlPath: '/blocked_services/list', server: server),
|
|
|
|
]);
|
|
|
|
if (results[0].successful == true && results[0].body != null) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: Filtering.fromJson({
|
|
|
|
...jsonDecode(results[0].body!),
|
|
|
|
"blocked_services": results[1].body != null
|
|
|
|
? jsonDecode(results[1].body!)
|
|
|
|
: []
|
|
|
|
})
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> setCustomRules({
|
|
|
|
required List<String> rules,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/set_rules',
|
|
|
|
server: server,
|
|
|
|
body: {'rules': rules},
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> addFilteringList({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/add_url',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
content: result.body,
|
|
|
|
statusCode: result.statusCode
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateFilterList({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/set_url',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> deleteFilterList({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/remove_url',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getServerInfo() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: "/status", server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: ServerInfoData.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateLists() async {
|
|
|
|
final results = await Future.wait([
|
|
|
|
HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/refresh',
|
|
|
|
server: server,
|
|
|
|
body: {'whitelist': true},
|
|
|
|
),
|
|
|
|
HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/refresh',
|
|
|
|
server: server,
|
|
|
|
body: {'whitelist': false},
|
|
|
|
),
|
|
|
|
]);
|
|
|
|
if (
|
|
|
|
results.map((e) => e.successful).every((e) => e == true) &&
|
|
|
|
results.map((e) => e.body).every((e) => e != null)
|
|
|
|
) {
|
|
|
|
try {
|
|
|
|
final clients = Clients.fromJson(jsonDecode(results[0].body!));
|
|
|
|
clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(results[1].body!));
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: {'updated': jsonDecode(results[0].body!)['updated']+jsonDecode(results[1].body!)['updated']}
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> checkHostFiltered({
|
|
|
|
required String host
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/filtering/check_host?name=$host', server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: jsonDecode(result.body!)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> requestChangeUpdateFrequency({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/filtering/config',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> setBlockedServices({
|
|
|
|
required List<String> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/blocked_services/set',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getDhcpData() async {
|
|
|
|
final results = await Future.wait([
|
|
|
|
HttpRequestClient.get(urlPath: '/dhcp/interfaces', server: server),
|
|
|
|
HttpRequestClient.get(urlPath: '/dhcp/status', server: server),
|
|
|
|
]);
|
|
|
|
if (
|
|
|
|
results.map((e) => e.successful).every((e) => e == true) &&
|
|
|
|
results.map((e) => e.body).every((e) => e != null)
|
|
|
|
) {
|
|
|
|
try {
|
|
|
|
List<NetworkInterface> interfaces = List<NetworkInterface>.from(jsonDecode(results[0].body!).entries.map((entry) => NetworkInterface.fromJson(entry.value)));
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: DhcpModel(
|
|
|
|
networkInterfaces: interfaces,
|
2023-12-08 20:43:45 +01:00
|
|
|
dhcpStatus: jsonDecode(results[1].body!)['message'] != null
|
|
|
|
? null
|
|
|
|
: DhcpStatus.fromJson(jsonDecode(results[1].body!))
|
2023-11-19 22:52:40 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> saveDhcpConfig({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/dhcp/set_config',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> resetDhcpConfig() async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/dhcp/reset',
|
|
|
|
server: server,
|
|
|
|
body: {},
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> deleteStaticLease({
|
|
|
|
required Map<String, dynamic> data
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/dhcp/remove_static_lease',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> createStaticLease({
|
|
|
|
required Map<String, dynamic> data
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/dhcp/add_static_lease',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
if (result.statusCode == 400 && result.body != null && result.body!.contains('static lease already exists')) {
|
|
|
|
return const ApiResponse(
|
|
|
|
successful: false,
|
|
|
|
content: "already_exists",
|
|
|
|
statusCode: 400
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (result.statusCode == 400 && result.body != null && result.body!.contains('server is unconfigured')) {
|
|
|
|
return const ApiResponse(
|
|
|
|
successful: false,
|
|
|
|
content: "server_not_configured",
|
|
|
|
statusCode: 400
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> restoreAllLeases() async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/dhcp/reset_leases',
|
|
|
|
server: server,
|
|
|
|
body: {},
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getDnsRewriteRules() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/rewrite/list', server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
try {
|
|
|
|
final List<RewriteRules> data = List<RewriteRules>.from(
|
|
|
|
jsonDecode(result.body!).map((item) => RewriteRules.fromJson(item))
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: data
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> deleteDnsRewriteRule({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/rewrite/delete',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> addDnsRewriteRule({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/rewrite/add',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getQueryLogInfo() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/querylog/config', server: server);
|
|
|
|
if (result.successful) {
|
2024-01-24 15:14:19 +01:00
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: QueryLogConfig.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
2023-11-19 22:52:40 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateQueryLogParameters({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.put(
|
|
|
|
urlPath: '/querylog/config/update',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> clearLogs() async {
|
2024-01-24 13:55:15 +01:00
|
|
|
final result = await HttpRequestClient.post(
|
2023-11-19 22:52:40 +01:00
|
|
|
urlPath: '/querylog_clear',
|
|
|
|
server: server,
|
|
|
|
body: {},
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getDnsInfo() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/dns_info', server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: DnsInfo.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> setDnsConfig({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/dns_config',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
if (result.statusCode == 400) {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
content: "data_not_valid",
|
|
|
|
statusCode: result.statusCode
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getEncryptionSettings() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/tls/status', server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: EncryptionData.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> getBlockedServices() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/blocked_services/all', server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: List<BlockedService>.from(
|
|
|
|
BlockedServicesFromApi.fromJson(jsonDecode(result.body!)).blockedServices
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> checkEncryptionSettings({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/tls/validate',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
2023-11-23 01:05:18 +01:00
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
2023-11-24 20:44:56 +01:00
|
|
|
content: result.body != null ? EncryptionValidationResult(
|
2023-11-27 15:05:26 +01:00
|
|
|
isObject: true,
|
2023-11-24 20:44:56 +01:00
|
|
|
encryptionValidation: EncryptionValidation.fromJson(jsonDecode(result.body!))
|
|
|
|
) : null
|
|
|
|
);
|
|
|
|
} on FormatException {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
content: result.body != null ? EncryptionValidationResult(
|
|
|
|
isObject: false,
|
|
|
|
message: result.body
|
|
|
|
) : null
|
2023-11-23 01:05:18 +01:00
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
2023-11-23 01:05:18 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
2023-11-19 22:52:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> saveEncryptionSettings({
|
|
|
|
required Map<String, dynamic> data,
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/tls/configure',
|
|
|
|
server: server,
|
|
|
|
body: data,
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
content: result.body
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> resetDnsCache() async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/cache_clear',
|
|
|
|
server: server,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> checkServerUpdates() async {
|
|
|
|
final results = await Future.wait([
|
|
|
|
HttpRequestClient.post(urlPath: '/version.json', server: server, body: { "recheck_now": true }),
|
|
|
|
HttpRequestClient.get(urlPath: '/status', server: server),
|
|
|
|
]);
|
|
|
|
if (
|
|
|
|
results.map((e) => e.successful).every((e) => e == true) &&
|
|
|
|
results.map((e) => e.body).every((e) => e != null)
|
|
|
|
) {
|
|
|
|
try {
|
|
|
|
final Map<String, dynamic> obj = {
|
|
|
|
...jsonDecode(results[0].body!),
|
|
|
|
'current_version': ServerInfoData.fromJson(jsonDecode(results[1].body!)).version
|
|
|
|
};
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: obj
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
2023-11-27 14:45:22 +01:00
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) })
|
|
|
|
);
|
2023-11-19 22:52:40 +01:00
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> requestUpdateServer() async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/update',
|
|
|
|
server: server,
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateSafeSearchSettings({
|
|
|
|
required Map<String, bool> body
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.put(
|
|
|
|
urlPath: '/safesearch/settings',
|
|
|
|
server: server,
|
|
|
|
body: body
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateRewriteRule({
|
|
|
|
required Map<String, dynamic> body
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.put(
|
|
|
|
urlPath: '/rewrite/update',
|
|
|
|
server: server,
|
|
|
|
body: body
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
2023-12-11 14:29:08 +01:00
|
|
|
|
|
|
|
Future<ApiResponse> testUpstreamDns({
|
|
|
|
required Map<String, dynamic> body
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.post(
|
|
|
|
urlPath: '/test_upstream_dns',
|
|
|
|
server: server,
|
|
|
|
body: body
|
|
|
|
);
|
|
|
|
return ApiResponse(
|
|
|
|
successful: result.successful,
|
|
|
|
content: result.body != null ? jsonDecode(result.body!) : null
|
|
|
|
);
|
|
|
|
}
|
2024-01-28 20:39:42 +01:00
|
|
|
|
|
|
|
Future<ApiResponse> getStatisticsConfig() async {
|
|
|
|
final result = await HttpRequestClient.get(urlPath: '/stats/config', server: server);
|
|
|
|
if (result.successful) {
|
|
|
|
try {
|
|
|
|
return ApiResponse(
|
|
|
|
successful: true,
|
|
|
|
content: StatisticsConfig.fromJson(jsonDecode(result.body!))
|
|
|
|
);
|
|
|
|
} catch (e, stackTrace) {
|
|
|
|
Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stackTrace,
|
|
|
|
hint: Hint.withMap({ "statusCode": result.statusCode.toString() })
|
|
|
|
);
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return const ApiResponse(successful: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ApiResponse> updateStatisticsSettings({
|
|
|
|
required Map<String, dynamic> body
|
|
|
|
}) async {
|
|
|
|
final result = await HttpRequestClient.put(
|
|
|
|
urlPath: '/stats/config/update',
|
|
|
|
server: server,
|
|
|
|
body: body
|
|
|
|
);
|
|
|
|
return ApiResponse(successful: result.successful);
|
|
|
|
}
|
2023-11-19 22:52:40 +01:00
|
|
|
}
|