From 5a620f74cce2007108b07e46463194510426f7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20P=C5=A1en=C3=A1k?= Date: Mon, 24 Jan 2022 04:00:42 +0100 Subject: [PATCH 1/6] JSON Config --- bin/model/endpoint_config.dart | 23 +++++++++++++++++++++++ config/example.json | 12 ++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 bin/model/endpoint_config.dart create mode 100644 config/example.json diff --git a/bin/model/endpoint_config.dart b/bin/model/endpoint_config.dart new file mode 100644 index 0000000..e17ba6a --- /dev/null +++ b/bin/model/endpoint_config.dart @@ -0,0 +1,23 @@ +class EndpointConfig { + String? title; + String url; + + EndpointConfig({this.title, required this.url}); + + factory EndpointConfig.fromJson(Map json) { + if (json['url']! == null) { + throw Exception("url is required"); + } + return EndpointConfig( + title: json['title'], + url: json['url']!, + ); + } + + Map toJson() { + final Map data = {}; + data['title'] = title; + data['url'] = url; + return data; + } +} diff --git a/config/example.json b/config/example.json new file mode 100644 index 0000000..fc2860a --- /dev/null +++ b/config/example.json @@ -0,0 +1,12 @@ +{ + "endpoints_blocked": [ + { + "endpoint": "http://example.com/", + "reason": "some reason" + }, + { + "endpoint": "http://example.com/", + "reason": "some reason" + } + ] +} \ No newline at end of file From c33f1eef76cbd2e5db0c036cc40046d9108a9550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20P=C5=A1en=C3=A1k?= Date: Tue, 8 Feb 2022 20:37:10 +0100 Subject: [PATCH 2/6] add json config --- README.md | 2 +- bin/api_handler.dart | 35 ++++-------------- bin/api_middleware.dart | 54 +++++++++++++++++++++++++++ bin/appitoolbox.dart | 2 + bin/model/endpoint_config.dart | 61 +++++++++++++++++++++++++++---- bin/services/endpoint_config.dart | 41 +++++++++++++++++++++ bin/utils/globals.dart | 3 ++ config/example.json | 14 ++++--- pubspec.lock | 46 ++++++++++++++++++++++- pubspec.yaml | 1 + 10 files changed, 216 insertions(+), 43 deletions(-) create mode 100644 bin/api_middleware.dart create mode 100644 bin/services/endpoint_config.dart create mode 100644 bin/utils/globals.dart diff --git a/README.md b/README.md index cc11047..1a8c2a5 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ You can run the example with the [Dart SDK](https://dart.dev/get-dart) like this: ```text -$ dart run bin/server.dart +$ dart run bin/appitoolbox.dart Server listening on port 8080 ``` diff --git a/bin/api_handler.dart b/bin/api_handler.dart index 886cd1b..d4d761a 100644 --- a/bin/api_handler.dart +++ b/bin/api_handler.dart @@ -1,21 +1,12 @@ import 'package:shelf/shelf.dart'; import 'package:shelf_router/shelf_router.dart'; import 'package:http/http.dart' as http; -import 'package:dotenv/dotenv.dart' as dotenv; +import 'package:shelf_plus/shelf_plus.dart'; + +import 'api_middleware.dart'; class ApiHandler { Future _universalGetHandler(Request request) async { - if (request.headers['X-AppiToolbox-ApiKey'] == null) { - return Response.forbidden( - 'No API Key provided. Use header X-AppiToolbox-ApiKey'); - } - if (request.headers['X-AppiToolbox-ApiKey'] != - dotenv.env['MASTER_API_KEY']) { - return Response.forbidden('Wrong value of X-AppiToolbox-ApiKey'); - } - if (request.params['url'] == null) { - return Response.notFound("You must supply valid URL."); - } Uri url = Uri.parse("https://" + request.params['url']!); print("got url"); Map headers = Map.from(request.headers); @@ -37,18 +28,6 @@ class ApiHandler { } Future _universalPostHandler(Request request) async { - if (request.headers['X-AppiToolbox-ApiKey'] == null) { - return Response.forbidden( - 'No API Key provided. Use header X-AppiToolbox-ApiKey'); - } - if (request.headers['X-AppiToolbox-ApiKey'] != - dotenv.env['MASTER_API_KEY']) { - return Response.forbidden('Wrong value of X-AppiToolbox-ApiKey'); - } - - if (request.params['url'] == null) { - return Response.notFound("You must supply valid URL."); - } Uri url = Uri.parse("https://" + request.params['url']!); Map headers = Map.from(request.headers); print(headers); @@ -76,12 +55,12 @@ class ApiHandler { // By exposing a [Router] for an object, it can be mounted in other routers. Router get router { - final router = Router(); + final router = Router().plus; router - ..get('/', _universalGetHandler) - ..post('/', _universalPostHandler); + ..get('/', _universalGetHandler, use: apiMiddleware()) + ..post('/', _universalPostHandler, use: apiMiddleware()); - return router; + return router.shelfRouter; } } diff --git a/bin/api_middleware.dart b/bin/api_middleware.dart new file mode 100644 index 0000000..318888b --- /dev/null +++ b/bin/api_middleware.dart @@ -0,0 +1,54 @@ +import 'dart:async'; + +import 'package:shelf/shelf.dart'; +import 'package:shelf_router/shelf_router.dart'; +import 'model/endpoint_config.dart'; +import 'utils/globals.dart' as globals; +import 'package:dotenv/dotenv.dart' as dotenv; + +Middleware apiMiddleware({ + FutureOr Function(Request)? requestHandler, + FutureOr Function(Response)? responseHandler, + FutureOr Function(Object error, StackTrace)? errorHandler, +}) { + requestHandler ??= (request) => null; + responseHandler ??= (response) => response; + + FutureOr Function(Object, StackTrace)? onError; + if (errorHandler != null) { + onError = (error, stackTrace) { + if (error is HijackException) throw error; + return errorHandler(error, stackTrace); + }; + } + + return (Handler innerHandler) { + return (request) { + if (request.headers['X-AppiToolbox-ApiKey'] == null) { + return Response.forbidden( + 'No API Key provided. Use header X-AppiToolbox-ApiKey'); + } + if (request.headers['X-AppiToolbox-ApiKey'] != + dotenv.env['MASTER_API_KEY']) { + return Response.forbidden('Wrong value of X-AppiToolbox-ApiKey'); + } + if (request.params['url'] == null) { + return Response.notFound("You must supply valid URL."); + } + + String requestedEndpoint = request.params['url']!; + + if (globals.configService.statusByUrl(requestedEndpoint) == + Status.blocked) { + return Response.forbidden("This endpoint is blocked."); + } + + return Future.sync(() => requestHandler!(request)).then((response) { + if (response != null) return response; + + return Future.sync(() => innerHandler(request)) + .then((response) => responseHandler!(response), onError: onError); + }); + }; + }; +} diff --git a/bin/appitoolbox.dart b/bin/appitoolbox.dart index 924e781..1eeee31 100644 --- a/bin/appitoolbox.dart +++ b/bin/appitoolbox.dart @@ -4,6 +4,7 @@ import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart'; import 'package:shelf_router/shelf_router.dart'; import 'package:dotenv/dotenv.dart' as dotenv; +import 'utils/globals.dart' as globals; import 'api_handler.dart'; @@ -61,6 +62,7 @@ void main(List args) async { final port = int.parse(Platform.environment['PORT'] ?? '8080'); final server = await serve(_handler, ip, port); dotenv.load(); + globals.configService.init(); print('Server listening on port ${server.port}'); ProcessSignal.sigint.watch().listen((ProcessSignal signal) { diff --git a/bin/model/endpoint_config.dart b/bin/model/endpoint_config.dart index e17ba6a..6ec96fb 100644 --- a/bin/model/endpoint_config.dart +++ b/bin/model/endpoint_config.dart @@ -1,17 +1,64 @@ +enum Status { blocked, allowed, undefined } + +enum Method { get, post, put, delete, undefined } + class EndpointConfig { - String? title; + String title; String url; + Method method; + Status status; - EndpointConfig({this.title, required this.url}); + EndpointConfig( + {required this.title, + required this.url, + required this.method, + required this.status}); factory EndpointConfig.fromJson(Map json) { - if (json['url']! == null) { - throw Exception("url is required"); + late Status status; + late Method method; + if (json['title'] == null) { + throw Exception("Title is required"); + } + if (json['url'] == null) { + throw Exception("URL is required"); + } + if (json['method'] == null) { + throw Exception("Method is required"); + } else { + try { + method = Method.values.byName(json['method']!); + } catch (e) { + throw Exception("Method is invalid"); + } + } + if (json['status'] == null) { + throw Exception("Status is required"); + } else { + try { + status = Status.values.byName(json['status']!); + } catch (e) { + throw Exception("Status is invalid"); + } } + return EndpointConfig( - title: json['title'], - url: json['url']!, - ); + title: json['title']!, + url: json['url']!, + method: method, + status: status); + } + + Status? getStatusFromString(String status) { + status = 'Status.$status'; + return Status.values.firstWhere((f) => f.toString() == status, + orElse: () => Status.undefined); + } + + Method? getMethodFromString(String method) { + method = 'Method.$method'; + return Method.values.firstWhere((f) => f.toString() == method, + orElse: () => Method.undefined); } Map toJson() { diff --git a/bin/services/endpoint_config.dart b/bin/services/endpoint_config.dart new file mode 100644 index 0000000..b614ed4 --- /dev/null +++ b/bin/services/endpoint_config.dart @@ -0,0 +1,41 @@ +import 'dart:convert'; +import 'dart:io'; + +import '../model/endpoint_config.dart'; + +class EndpointConfigService { + List configs = []; + var defaultConfig = new File('./config/example.json'); + bool loaded = false; + + Future init() async { + await _loadEndpoints(); + loaded = true; + } + + Future _loadEndpoints() async { + final json = jsonDecode(await defaultConfig.readAsString()); + for (var item in json["endpoints"]) { + configs.add(EndpointConfig.fromJson(item)); + } + return true; + } + + Status statusByUrl(String url) { + if (!loaded) { + throw new Exception("You need to load config first"); + } + for (var item in configs) { + if (item.url == url) { + return item.status; + } + if (item.url == "https://" + url) { + return item.status; + } + if (item.url == "http://" + url) { + return item.status; + } + } + return Status.undefined; + } +} diff --git a/bin/utils/globals.dart b/bin/utils/globals.dart new file mode 100644 index 0000000..4faab02 --- /dev/null +++ b/bin/utils/globals.dart @@ -0,0 +1,3 @@ +import '../services/endpoint_config.dart'; + +EndpointConfigService configService = new EndpointConfigService(); diff --git a/config/example.json b/config/example.json index fc2860a..ccd8603 100644 --- a/config/example.json +++ b/config/example.json @@ -1,12 +1,16 @@ { - "endpoints_blocked": [ + "endpoints": [ { - "endpoint": "http://example.com/", - "reason": "some reason" + "title": "example site", + "url": "https://example.com/", + "method" : "get", + "status" : "blocked" }, { - "endpoint": "http://example.com/", - "reason": "some reason" + "title": "Create employee", + "url": "https://dummy.restapiexample.com/api/v1/create", + "method" : "post", + "status" : "blocked" } ] } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index d27476c..1ee503e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -70,7 +70,7 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.0.3" crypto: dependency: transitive description: @@ -106,6 +106,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.2" + hotreloader: + dependency: transitive + description: + name: hotreloader + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" http: dependency: "direct dev" description: @@ -183,6 +190,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + mime_type: + dependency: transitive + description: + name: mime_type + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" node_preamble: dependency: transitive description: @@ -225,6 +239,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + shelf_hotreload: + dependency: transitive + description: + name: shelf_hotreload + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" shelf_packages_handler: dependency: transitive description: @@ -232,6 +253,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.0" + shelf_plus: + dependency: "direct main" + description: + name: shelf_plus + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" shelf_router: dependency: "direct main" description: @@ -288,6 +316,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -295,6 +330,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + supercharged_dart: + dependency: transitive + description: + name: supercharged_dart + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" term_glyph: dependency: transitive description: @@ -343,7 +385,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "8.1.0" + version: "7.5.0" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3a734c6..3e4a572 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,6 +11,7 @@ dependencies: args: ^2.0.0 dotenv: ^3.0.0 shelf: ^1.1.0 + shelf_plus: ^1.2.1 shelf_router: ^1.0.0 dev_dependencies: From bab5d906689bd266903b834272f4ba5ad09589b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20P=C5=A1en=C3=A1k?= Date: Tue, 8 Feb 2022 20:39:43 +0100 Subject: [PATCH 3/6] fix analysis --- bin/api_handler.dart | 2 -- bin/services/endpoint_config.dart | 4 ++-- bin/utils/globals.dart | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bin/api_handler.dart b/bin/api_handler.dart index d4d761a..07e3f74 100644 --- a/bin/api_handler.dart +++ b/bin/api_handler.dart @@ -1,5 +1,3 @@ -import 'package:shelf/shelf.dart'; -import 'package:shelf_router/shelf_router.dart'; import 'package:http/http.dart' as http; import 'package:shelf_plus/shelf_plus.dart'; diff --git a/bin/services/endpoint_config.dart b/bin/services/endpoint_config.dart index b614ed4..35cc99d 100644 --- a/bin/services/endpoint_config.dart +++ b/bin/services/endpoint_config.dart @@ -5,7 +5,7 @@ import '../model/endpoint_config.dart'; class EndpointConfigService { List configs = []; - var defaultConfig = new File('./config/example.json'); + var defaultConfig = File('./config/example.json'); bool loaded = false; Future init() async { @@ -23,7 +23,7 @@ class EndpointConfigService { Status statusByUrl(String url) { if (!loaded) { - throw new Exception("You need to load config first"); + throw Exception("You need to load config first"); } for (var item in configs) { if (item.url == url) { diff --git a/bin/utils/globals.dart b/bin/utils/globals.dart index 4faab02..6ebca5f 100644 --- a/bin/utils/globals.dart +++ b/bin/utils/globals.dart @@ -1,3 +1,3 @@ import '../services/endpoint_config.dart'; -EndpointConfigService configService = new EndpointConfigService(); +EndpointConfigService configService = EndpointConfigService(); From eb5ee9abdae364bab8c0d262d32f64efca88a567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20P=C5=A1en=C3=A1k?= Date: Fri, 11 Feb 2022 13:10:54 +0100 Subject: [PATCH 4/6] block with method --- bin/api_middleware.dart | 3 ++- bin/model/endpoint_config.dart | 14 +++++++++++++- bin/services/endpoint_config.dart | 13 ++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bin/api_middleware.dart b/bin/api_middleware.dart index 318888b..242acaa 100644 --- a/bin/api_middleware.dart +++ b/bin/api_middleware.dart @@ -38,7 +38,8 @@ Middleware apiMiddleware({ String requestedEndpoint = request.params['url']!; - if (globals.configService.statusByUrl(requestedEndpoint) == + if (globals.configService + .endpointStatus(requestedEndpoint, request.method) == Status.blocked) { return Response.forbidden("This endpoint is blocked."); } diff --git a/bin/model/endpoint_config.dart b/bin/model/endpoint_config.dart index 6ec96fb..77cbe73 100644 --- a/bin/model/endpoint_config.dart +++ b/bin/model/endpoint_config.dart @@ -1,6 +1,18 @@ enum Status { blocked, allowed, undefined } -enum Method { get, post, put, delete, undefined } +enum Method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + undefined, + all +} class EndpointConfig { String title; diff --git a/bin/services/endpoint_config.dart b/bin/services/endpoint_config.dart index 35cc99d..0185f36 100644 --- a/bin/services/endpoint_config.dart +++ b/bin/services/endpoint_config.dart @@ -21,11 +21,22 @@ class EndpointConfigService { return true; } - Status statusByUrl(String url) { + Status endpointStatus(String url, String methodS) { + Method method; + try { + method = Method.values.byName(methodS.toLowerCase()); + } catch (e) { + method = Method.undefined; + } if (!loaded) { throw Exception("You need to load config first"); } for (var item in configs) { + if (item.method != method && + item.method != Method.undefined && + item.method != Method.all) { + break; + } if (item.url == url) { return item.status; } From b2268fece456fcac1e73cc518eefb35e9322c09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20P=C5=A1en=C3=A1k?= Date: Fri, 11 Feb 2022 13:50:36 +0100 Subject: [PATCH 5/6] default config --- bin/api_middleware.dart | 12 ++++--- bin/appitoolbox.dart | 3 +- bin/model/endpoint_config.dart | 53 +++++++++++++------------------ bin/model/global_config.dart | 33 +++++++++++++++++++ bin/model/method.dart | 13 ++++++++ bin/model/status.dart | 1 + bin/services/endpoint_config.dart | 2 ++ bin/services/global_config.dart | 41 ++++++++++++++++++++++++ bin/utils/globals.dart | 4 ++- config/example.json | 9 ++++++ 10 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 bin/model/global_config.dart create mode 100644 bin/model/method.dart create mode 100644 bin/model/status.dart create mode 100644 bin/services/global_config.dart diff --git a/bin/api_middleware.dart b/bin/api_middleware.dart index 242acaa..644d0ba 100644 --- a/bin/api_middleware.dart +++ b/bin/api_middleware.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:shelf/shelf.dart'; import 'package:shelf_router/shelf_router.dart'; -import 'model/endpoint_config.dart'; +import 'model/status.dart'; import 'utils/globals.dart' as globals; import 'package:dotenv/dotenv.dart' as dotenv; @@ -37,10 +37,14 @@ Middleware apiMiddleware({ } String requestedEndpoint = request.params['url']!; + Status status = globals.endpointConfigService + .endpointStatus(requestedEndpoint, request.method); - if (globals.configService - .endpointStatus(requestedEndpoint, request.method) == - Status.blocked) { + if (status == Status.undefined) { + status = globals.globalConfigService.defaultStatus(request.method); + } + + if (status == Status.blocked) { return Response.forbidden("This endpoint is blocked."); } diff --git a/bin/appitoolbox.dart b/bin/appitoolbox.dart index 1eeee31..018dfa6 100644 --- a/bin/appitoolbox.dart +++ b/bin/appitoolbox.dart @@ -62,7 +62,8 @@ void main(List args) async { final port = int.parse(Platform.environment['PORT'] ?? '8080'); final server = await serve(_handler, ip, port); dotenv.load(); - globals.configService.init(); + globals.endpointConfigService.init(); + globals.globalConfigService.init(); print('Server listening on port ${server.port}'); ProcessSignal.sigint.watch().listen((ProcessSignal signal) { diff --git a/bin/model/endpoint_config.dart b/bin/model/endpoint_config.dart index 77cbe73..1d93494 100644 --- a/bin/model/endpoint_config.dart +++ b/bin/model/endpoint_config.dart @@ -1,64 +1,55 @@ -enum Status { blocked, allowed, undefined } - -enum Method { - get, - head, - post, - put, - delete, - connect, - options, - trace, - patch, - undefined, - all -} +import 'method.dart'; +import 'status.dart'; class EndpointConfig { - String title; - String url; + String? title; + String? url; Method method; Status status; + bool isDefault; EndpointConfig( - {required this.title, - required this.url, - required this.method, - required this.status}); + {this.title, + this.url, + this.method = Method.undefined, + this.status = Status.undefined, + this.isDefault = false}); - factory EndpointConfig.fromJson(Map json) { + factory EndpointConfig.fromJson(Map json, + {bool isDefault = false}) { late Status status; late Method method; - if (json['title'] == null) { + if (json['title'] == null && !isDefault) { throw Exception("Title is required"); } - if (json['url'] == null) { + if (json['url'] == null && !isDefault) { throw Exception("URL is required"); } if (json['method'] == null) { - throw Exception("Method is required"); + method = Method.undefined; } else { try { method = Method.values.byName(json['method']!); } catch (e) { - throw Exception("Method is invalid"); + method = Method.undefined; } } if (json['status'] == null) { - throw Exception("Status is required"); + status = Status.undefined; } else { try { status = Status.values.byName(json['status']!); } catch (e) { - throw Exception("Status is invalid"); + status = Status.undefined; } } return EndpointConfig( - title: json['title']!, - url: json['url']!, + title: json['title'], + url: json['url'], method: method, - status: status); + status: status, + isDefault: isDefault); } Status? getStatusFromString(String status) { diff --git a/bin/model/global_config.dart b/bin/model/global_config.dart new file mode 100644 index 0000000..0f619c2 --- /dev/null +++ b/bin/model/global_config.dart @@ -0,0 +1,33 @@ +import 'endpoint_config.dart'; +import 'status.dart'; + +class GlobalConfig { + Status defaultStatus; + List defaultEndpoints; + + GlobalConfig({ + required this.defaultStatus, + required this.defaultEndpoints, + }); + + factory GlobalConfig.fromJson(Map json) { + Status defaultStatus; + if (json['defaultStatus'] == null) { + throw Exception("defaultStatus is required"); + } else { + try { + defaultStatus = Status.values.byName(json['defaultStatus']!); + } catch (e) { + throw Exception("defaultStatus have invalid value"); + } + } + + return GlobalConfig( + defaultStatus: defaultStatus, + defaultEndpoints: (json['defaultEndpoints'] as List) + .map((e) => EndpointConfig.fromJson(e as Map, + isDefault: true)) + .toList(), + ); + } +} diff --git a/bin/model/method.dart b/bin/model/method.dart new file mode 100644 index 0000000..f876b78 --- /dev/null +++ b/bin/model/method.dart @@ -0,0 +1,13 @@ +enum Method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + undefined, + all +} diff --git a/bin/model/status.dart b/bin/model/status.dart new file mode 100644 index 0000000..d2f0044 --- /dev/null +++ b/bin/model/status.dart @@ -0,0 +1 @@ +enum Status { blocked, allowed, undefined } diff --git a/bin/services/endpoint_config.dart b/bin/services/endpoint_config.dart index 0185f36..2d7030f 100644 --- a/bin/services/endpoint_config.dart +++ b/bin/services/endpoint_config.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'dart:io'; import '../model/endpoint_config.dart'; +import '../model/method.dart'; +import '../model/status.dart'; class EndpointConfigService { List configs = []; diff --git a/bin/services/global_config.dart b/bin/services/global_config.dart new file mode 100644 index 0000000..e25ad5d --- /dev/null +++ b/bin/services/global_config.dart @@ -0,0 +1,41 @@ +import 'dart:convert'; +import 'dart:io'; + +import '../model/global_config.dart'; +import '../model/method.dart'; +import '../model/status.dart'; + +class GlobalConfigService { + late GlobalConfig globalConfig; + var defaultConfig = File('./config/example.json'); + bool loaded = false; + + Future init() async { + await loadConfig(); + loaded = true; + } + + Future loadConfig() async { + final json = jsonDecode(await defaultConfig.readAsString()); + globalConfig = GlobalConfig.fromJson(json["global"]); + } + + Status defaultStatus(String methodS) { + Method method; + try { + method = Method.values.byName(methodS.toLowerCase()); + } catch (e) { + method = Method.undefined; + } + if (!loaded) { + throw Exception("You need to load config first"); + } + try { + return globalConfig.defaultEndpoints + .firstWhere((endpoint) => endpoint.method == method) + .status; + } catch (e) { + return globalConfig.defaultStatus; + } + } +} diff --git a/bin/utils/globals.dart b/bin/utils/globals.dart index 6ebca5f..8f45cb2 100644 --- a/bin/utils/globals.dart +++ b/bin/utils/globals.dart @@ -1,3 +1,5 @@ import '../services/endpoint_config.dart'; +import '../services/global_config.dart'; -EndpointConfigService configService = EndpointConfigService(); +EndpointConfigService endpointConfigService = EndpointConfigService(); +GlobalConfigService globalConfigService = GlobalConfigService(); diff --git a/config/example.json b/config/example.json index ccd8603..301f82b 100644 --- a/config/example.json +++ b/config/example.json @@ -1,4 +1,13 @@ { + "global" : { + "defaultStatus" : "blocked", + "defaultEndpoints" : [ + { + "method" : "get", + "status" : "allowed" + } + ] + }, "endpoints": [ { "title": "example site", From ad79ca960da42db31a8d004ed32d3aad4674bbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20P=C5=A1en=C3=A1k?= Date: Fri, 11 Feb 2022 14:14:04 +0100 Subject: [PATCH 6/6] set config file in env --- .env.example | 3 ++- bin/services/endpoint_config.dart | 10 +++++----- bin/services/global_config.dart | 7 +++++-- bin/utils/globals.dart | 13 +++++++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.env.example b/.env.example index fb5d28e..f3d415a 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ -MASTER_API_KEY="SOME_API_KEY" \ No newline at end of file +MASTER_API_KEY="SOME_API_KEY" +CONFIG_FILE="./config/example.json" \ No newline at end of file diff --git a/bin/services/endpoint_config.dart b/bin/services/endpoint_config.dart index 2d7030f..e59a928 100644 --- a/bin/services/endpoint_config.dart +++ b/bin/services/endpoint_config.dart @@ -1,13 +1,10 @@ -import 'dart:convert'; -import 'dart:io'; - import '../model/endpoint_config.dart'; import '../model/method.dart'; import '../model/status.dart'; +import '../utils/globals.dart' as globals; class EndpointConfigService { List configs = []; - var defaultConfig = File('./config/example.json'); bool loaded = false; Future init() async { @@ -16,7 +13,10 @@ class EndpointConfigService { } Future _loadEndpoints() async { - final json = jsonDecode(await defaultConfig.readAsString()); + if (!globals.configLoaded) { + await globals.loadConfig(); + } + final json = globals.config; for (var item in json["endpoints"]) { configs.add(EndpointConfig.fromJson(item)); } diff --git a/bin/services/global_config.dart b/bin/services/global_config.dart index e25ad5d..01d2594 100644 --- a/bin/services/global_config.dart +++ b/bin/services/global_config.dart @@ -1,9 +1,9 @@ -import 'dart:convert'; import 'dart:io'; import '../model/global_config.dart'; import '../model/method.dart'; import '../model/status.dart'; +import '../utils/globals.dart' as globals; class GlobalConfigService { late GlobalConfig globalConfig; @@ -16,7 +16,10 @@ class GlobalConfigService { } Future loadConfig() async { - final json = jsonDecode(await defaultConfig.readAsString()); + if (!globals.configLoaded) { + await globals.loadConfig(); + } + final json = globals.config; globalConfig = GlobalConfig.fromJson(json["global"]); } diff --git a/bin/utils/globals.dart b/bin/utils/globals.dart index 8f45cb2..03fab64 100644 --- a/bin/utils/globals.dart +++ b/bin/utils/globals.dart @@ -1,5 +1,18 @@ +import 'dart:convert'; +import 'dart:io'; + import '../services/endpoint_config.dart'; import '../services/global_config.dart'; +import 'package:dotenv/dotenv.dart' as dotenv; EndpointConfigService endpointConfigService = EndpointConfigService(); GlobalConfigService globalConfigService = GlobalConfigService(); +late Map config; +bool configLoaded = false; + +loadConfig() async { + String configPath = dotenv.env['CONFIG_FILE'] ?? "./config/example.json"; + File configFile = File(configPath); + config = jsonDecode(await configFile.readAsString()); + configLoaded = true; +}