Refactor database layer: convert to DatabaseProvider class with initialization
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
.dockerignore
|
||||||
|
Dockerfile
|
||||||
|
build/
|
||||||
|
.dart_tool/
|
||||||
|
.git/
|
||||||
|
.github/
|
||||||
|
.gitignore
|
||||||
|
.idea/
|
||||||
|
.packages
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Environment variables for sky_kfm_backend
|
||||||
|
# JWT secret used for signing tokens
|
||||||
|
JWT_SECRET=your-super-secret-key-change-me
|
||||||
|
# Secret pepper added to passwords before hashing (should be random and kept secret)
|
||||||
|
PASSWORD_PEPPER=your-random-pepper-string-change-me
|
||||||
|
# Database connection URL
|
||||||
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/family_safety
|
||||||
|
# TOKEN_LIFETIME in minutes
|
||||||
|
TOKEN_LIFETIME=600
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# https://dart.dev/guides/libraries/private-files
|
||||||
|
# Created by `dart pub`
|
||||||
|
.dart_tool/
|
||||||
Generated
+3
@@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="PyInterpreterInspection" enabled="true" level="INFORMATION" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredErrors">
|
||||||
|
<list>
|
||||||
|
<option value="N802" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
Generated
+524
@@ -0,0 +1,524 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="Dart Packages" type="DartPackagesLibraryType">
|
||||||
|
<properties>
|
||||||
|
<option name="packageNameToDirsMap">
|
||||||
|
<entry key="_fe_analyzer_shared">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-99.0.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="adaptive_number">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/adaptive_number-1.0.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="analyzer">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-12.1.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="args">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="async">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="bcrypt">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/bcrypt-1.2.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="boolean_selector">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="buffer">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/buffer-1.2.3/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="charcode">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/charcode-1.4.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="cli_config">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/cli_config-0.2.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="clock">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="collection">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="convert">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="coverage">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/coverage-1.15.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="crypto">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="dart_jsonwebtoken">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/dart_jsonwebtoken-2.17.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="dotenv">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/dotenv-4.2.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="ed25519_edwards">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/ed25519_edwards-0.3.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="file">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="fixnum">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="frontend_server_client">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/frontend_server_client-4.0.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="glob">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="http">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="http_methods">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http_methods-1.1.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="http_multi_server">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http_multi_server-3.2.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="http_parser">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="io">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="js">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="lints">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/lints-6.1.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="logging">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="matcher">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.20/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="meta">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.18.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="mime">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="node_preamble">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/node_preamble-2.0.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="package_config">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="path">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="pointycastle">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/pointycastle-3.9.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="pool">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="postgres">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/postgres-3.5.10/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="pub_semver">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="shelf">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf-1.4.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="shelf_packages_handler">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_packages_handler-3.0.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="shelf_router">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_router-1.1.4/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="shelf_static">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_static-1.1.3/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="shelf_web_socket">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_web_socket-3.0.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="source_map_stack_trace">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/source_map_stack_trace-2.1.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="source_maps">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/source_maps-0.10.13/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="source_span">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="stack_trace">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="stream_channel">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="string_scanner">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="term_glyph">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="test">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/test-1.31.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="test_api">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.12/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="test_core">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/test_core-0.6.18/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="typed_data">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="uuid">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/uuid-4.5.3/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="vm_service">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.2.0/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="watcher">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="web">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="web_socket">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket-1.0.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="web_socket_channel">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket_channel-3.0.3/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="webkit_inspection_protocol">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="yaml">
|
||||||
|
<value>
|
||||||
|
<list>
|
||||||
|
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3/lib" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</option>
|
||||||
|
</properties>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-99.0.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/adaptive_number-1.0.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-12.1.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/bcrypt-1.2.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/buffer-1.2.3/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/charcode-1.4.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/cli_config-0.2.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/coverage-1.15.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/dart_jsonwebtoken-2.17.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/dotenv-4.2.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/ed25519_edwards-0.3.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/frontend_server_client-4.0.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http_methods-1.1.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http_multi_server-3.2.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/lints-6.1.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.20/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.18.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/node_preamble-2.0.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/pointycastle-3.9.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/postgres-3.5.10/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf-1.4.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_packages_handler-3.0.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_router-1.1.4/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_static-1.1.3/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_web_socket-3.0.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/source_map_stack_trace-2.1.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/source_maps-0.10.13/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/test-1.31.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.12/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/test_core-0.6.18/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/uuid-4.5.3/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.2.0/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket-1.0.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket_channel-3.0.3/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1/lib" />
|
||||||
|
<root url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3/lib" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
Generated
+31
@@ -0,0 +1,31 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="Dart SDK">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/_internal" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/async" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/cli" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/collection" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/concurrent" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/convert" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/core" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/developer" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/ffi" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/html" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/indexed_db" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/io" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/isolate" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/js" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/js_interop" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/js_interop_unsafe" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/js_util" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/math" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/mirrors" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/svg" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/typed_data" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/web_audio" />
|
||||||
|
<root url="file://$PROJECT_DIR$/../../../../tools/flutter/bin/cache/dart-sdk/lib/web_gl" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/family_safety_tracker.iml" filepath="$PROJECT_DIR$/family_safety_tracker.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# AGENTS.md - Family Safety Tracker
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Dart server app (Shelf + PostgreSQL) for sharing geolocation with family members. REST API with JWT auth, bcrypt password hashing, and auto-expiring position data.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
```bash
|
||||||
|
dart pub get
|
||||||
|
dart run bin/server.dart
|
||||||
|
```
|
||||||
|
Server starts on port `8080` (override with `PORT` env var).
|
||||||
|
|
||||||
|
## Code Structure
|
||||||
|
- **`bin/`** - All application code lives here (not `lib/`, which is empty).
|
||||||
|
- `bin/server.dart` - Entry point. Starts Shelf server, database connection, and cleanup timer.
|
||||||
|
- `bin/routes/` - Route handlers (`auth_routes.dart`, `user_routes.dart`, `geo_routes.dart`)
|
||||||
|
- `bin/repositories/` - Data access layer (`user_repo.dart`, `geoposition_repo.dart`)
|
||||||
|
- `bin/models/` - Domain models (`user.dart`, `geoposition.dart`, `log.dart`)
|
||||||
|
- `bin/database/` - Database connection and auto-migration
|
||||||
|
- **`lib/`** - Empty scaffold directory (stale, can be ignored).
|
||||||
|
|
||||||
|
## Database
|
||||||
|
- PostgreSQL with connection via environment variables (`POSTGRES_HOST`, `POSTGRES_DB`, etc.) or defaults.
|
||||||
|
- **Auto-migration**: Tables are created on startup via `Database.initialize()`. No manual migration needed.
|
||||||
|
- Tables: `users`, `geopositions`, `logs`.
|
||||||
|
|
||||||
|
## Runtime Behavior
|
||||||
|
- Expired geopositions are cleaned up every 5 minutes by a periodic timer in `server.dart`.
|
||||||
|
- Share links use UUIDs stored in-memory via `GeopositionRepository`.
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
- `POST /login` - Authenticate with login/password, returns user data.
|
||||||
|
- `/user` - CRUD for users.
|
||||||
|
- `/geo` - POST to create position, UPDATE to update (with lifetime expiry).
|
||||||
|
- `GET /watch?unique_id=...` - Returns latest position for a share link.
|
||||||
|
- `/share` - Creates a one-time share link UUID.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
```bash
|
||||||
|
dart test
|
||||||
|
```
|
||||||
|
Tests spawn the server process and hit endpoints. Server listens on port `8080` by default.
|
||||||
|
|
||||||
|
## Build/Quality Commands
|
||||||
|
```bash
|
||||||
|
dart analyze # Static analysis (uses analysis_options.yaml)
|
||||||
|
dart format --set . # Format code
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- `shelf`, `shelf_router` - HTTP framework
|
||||||
|
- `postgres` - PostgreSQL driver
|
||||||
|
- `bcrypt` - Password hashing
|
||||||
|
- `dart_jsonwebtoken` - JWT tokens
|
||||||
|
- `dotenv` - Environment config
|
||||||
|
- `uuid` - UUID generation
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
- SDK: `^3.10.1`
|
||||||
|
- No Docker setup present (`.dockerignore` exists but no `Dockerfile`).
|
||||||
|
- Documentation in `README.md` is in Russian; the API is designed for geolocation sharing between family members.
|
||||||
|
- `test_bcrypt.dart` is a standalone test file, not part of the test suite.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
- Initial version.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
A server app built using [Shelf](https://pub.dev/packages/shelf),
|
||||||
|
|
||||||
|
Это новый проект.
|
||||||
|
Давай добавим описание проекта -
|
||||||
|
Сервер - приложения для реализации возможности делиться геопозицией с другим человеком.
|
||||||
|
База данных (в данном случае это будет postges) с отметками о геопозиции человека
|
||||||
|
Какие таблицы будут в базе данных -
|
||||||
|
Пользователи - ID, login, pwd
|
||||||
|
Geoposition - id, x value, y value, datetime, lifetime
|
||||||
|
Logs - username, action, datetime
|
||||||
|
|
||||||
|
Основа приложения - это REST API.
|
||||||
|
Вот какие методы нужны.
|
||||||
|
/login - авторизация.
|
||||||
|
/user - CRUD пользователей.
|
||||||
|
/geo - POST - создание позиции, UPDATE - обновление позиции. (при создании указывается время жизни, после которого данные будут удалены из базы)
|
||||||
|
/watch?{unique id} - возращает геопозицию+время последней отметки + оставшееся время жизни отметки
|
||||||
|
/share - метод который создает одноразовую ссылку (/watch?{unique id} ) - по которой доступны данные о геопозиции. В памяти приложения создается связь между geo из таблицы и {unique id}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# This file configures the static analysis results for your project (errors,
|
||||||
|
# warnings, and lints).
|
||||||
|
#
|
||||||
|
# This enables the 'recommended' set of lints from `package:lints`.
|
||||||
|
# This set helps identify many issues that may lead to problems when running
|
||||||
|
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||||
|
# style and format.
|
||||||
|
#
|
||||||
|
# If you want a smaller set of lints you can change this to specify
|
||||||
|
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||||
|
# (the recommended set includes the core lints).
|
||||||
|
# The core lints are also what is used by pub.dev for scoring packages.
|
||||||
|
|
||||||
|
include: package:lints/recommended.yaml
|
||||||
|
|
||||||
|
# Uncomment the following section to specify additional rules.
|
||||||
|
|
||||||
|
# linter:
|
||||||
|
# rules:
|
||||||
|
# - camel_case_types
|
||||||
|
|
||||||
|
# analyzer:
|
||||||
|
# exclude:
|
||||||
|
# - path/to/excluded/files/**
|
||||||
|
|
||||||
|
# For more information about the core and recommended set of lints, see
|
||||||
|
# https://dart.dev/go/core-lints
|
||||||
|
|
||||||
|
# For additional information about configuring this file, see
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:bcrypt/bcrypt.dart';
|
||||||
|
import 'package:dotenv/dotenv.dart';
|
||||||
|
import 'package:postgres/postgres.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
import '../models/user.dart';
|
||||||
|
import '../models/geoposition.dart';
|
||||||
|
import '../models/log.dart';
|
||||||
|
|
||||||
|
class DatabaseProvider {
|
||||||
|
late Connection _dbConnection;
|
||||||
|
|
||||||
|
final Map<String, int> _shareLinks = {};
|
||||||
|
final _uuid = const Uuid();
|
||||||
|
|
||||||
|
Future<void> initialize() async {
|
||||||
|
final dotenv = DotEnv();
|
||||||
|
|
||||||
|
final host = dotenv['POSTGRES_HOST'] ?? 'localhost';
|
||||||
|
final port = int.parse(dotenv['POSTGRES_PORT'] ?? '5432');
|
||||||
|
final databaseName = dotenv['POSTGRES_DB'] ?? 'family_safety';
|
||||||
|
final username = dotenv['POSTGRES_USER'] ?? 'postgres';
|
||||||
|
final password = dotenv['POSTGRES_PASSWORD'] ?? '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
final defaultConnection = await Connection.open(
|
||||||
|
settings: ConnectionSettings(sslMode: SslMode.disable),
|
||||||
|
Endpoint(
|
||||||
|
host: host,
|
||||||
|
port: port,
|
||||||
|
database: 'postgres',
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final results = await defaultConnection.execute(
|
||||||
|
Sql.named('SELECT 1 FROM pg_database WHERE datname = @dbName'),
|
||||||
|
parameters: {'dbName': databaseName},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.isEmpty) {
|
||||||
|
await defaultConnection.execute(
|
||||||
|
Sql.named('CREATE DATABASE @dbName'),
|
||||||
|
parameters: {'dbName': databaseName},
|
||||||
|
);
|
||||||
|
print('Database $databaseName created.');
|
||||||
|
} else {
|
||||||
|
print('Database $databaseName already exists.');
|
||||||
|
}
|
||||||
|
|
||||||
|
await defaultConnection.close();
|
||||||
|
|
||||||
|
_dbConnection = await Connection.open(
|
||||||
|
settings: ConnectionSettings(sslMode: SslMode.disable),
|
||||||
|
Endpoint(
|
||||||
|
host: host,
|
||||||
|
port: port,
|
||||||
|
database: databaseName,
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
print('Connected to database $databaseName.');
|
||||||
|
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
login VARCHAR(255) UNIQUE NOT NULL,
|
||||||
|
pwd_hash VARCHAR(255) NOT NULL
|
||||||
|
)
|
||||||
|
'''),
|
||||||
|
);
|
||||||
|
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
CREATE TABLE IF NOT EXISTS geopositions (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
x_value DOUBLE PRECISION NOT NULL,
|
||||||
|
y_value DOUBLE PRECISION NOT NULL,
|
||||||
|
datetime TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
lifetime INTERVAL NOT NULL,
|
||||||
|
expires_at TIMESTAMP NOT NULL
|
||||||
|
)
|
||||||
|
'''),
|
||||||
|
);
|
||||||
|
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
CREATE TABLE IF NOT EXISTS logs (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
action VARCHAR(255) NOT NULL,
|
||||||
|
datetime TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
)
|
||||||
|
'''),
|
||||||
|
);
|
||||||
|
|
||||||
|
print('All tables ensured to exist.');
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
stderr.writeln('Database initialization error: $e');
|
||||||
|
stderr.writeln(stackTrace);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> close() async {
|
||||||
|
await _dbConnection.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== User operations ====================
|
||||||
|
|
||||||
|
Future<User?> findUserByLogin(String login) async {
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('SELECT id, login, pwd_hash FROM users WHERE login = @login'),
|
||||||
|
parameters: {'login': login},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.isEmpty) return null;
|
||||||
|
final row = results.first;
|
||||||
|
return User(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
login: row[1] as String,
|
||||||
|
pwdHash: row[2] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<User> createUser(String login, String password) async {
|
||||||
|
final hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
|
||||||
|
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
INSERT INTO users (login, pwd_hash) VALUES (@login, @pwdHash)
|
||||||
|
RETURNING id, login, pwd_hash
|
||||||
|
'''),
|
||||||
|
parameters: {
|
||||||
|
'login': login,
|
||||||
|
'pwdHash': hashedPassword,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final row = results.first;
|
||||||
|
return User(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
login: row[1] as String,
|
||||||
|
pwdHash: row[2] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteUser(int id) async {
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('DELETE FROM users WHERE id = @id'),
|
||||||
|
parameters: {'id': id},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<User> updateUser(int id, String newLogin, String? newPassword) async {
|
||||||
|
if (newPassword != null) {
|
||||||
|
final hashedPassword = BCrypt.hashpw(newPassword, BCrypt.gensalt());
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
UPDATE users SET login = @login, pwd_hash = @pwdHash WHERE id = @id
|
||||||
|
'''),
|
||||||
|
parameters: {
|
||||||
|
'login': newLogin,
|
||||||
|
'pwdHash': hashedPassword,
|
||||||
|
'id': id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('UPDATE users SET login = @login WHERE id = @id'),
|
||||||
|
parameters: {
|
||||||
|
'login': newLogin,
|
||||||
|
'id': id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final user = await findUserByLogin(newLogin);
|
||||||
|
return user!;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<User>> getAllUsers() async {
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('SELECT id, login, pwd_hash FROM users'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return results
|
||||||
|
.map(
|
||||||
|
(row) => User(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
login: row[1] as String,
|
||||||
|
pwdHash: row[2] as String,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Geoposition operations ====================
|
||||||
|
|
||||||
|
Future<Geoposition> createPosition(
|
||||||
|
int userId,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
Duration lifetime,
|
||||||
|
) async {
|
||||||
|
final expiresAt = DateTime.now().add(lifetime);
|
||||||
|
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
INSERT INTO geopositions (user_id, x_value, y_value, datetime, lifetime, expires_at)
|
||||||
|
VALUES (@userId, @xValue, @yValue, NOW(), @lifetime, @expiresAt)
|
||||||
|
RETURNING id, user_id, x_value, y_value, datetime, lifetime, expires_at
|
||||||
|
'''),
|
||||||
|
parameters: {
|
||||||
|
'userId': userId,
|
||||||
|
'xValue': x,
|
||||||
|
'yValue': y,
|
||||||
|
'lifetime': _toInterval(lifetime),
|
||||||
|
'expiresAt': expiresAt.toIso8601String(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final row = results.first;
|
||||||
|
return Geoposition(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
userId: int.parse(row[1].toString()),
|
||||||
|
xValue: double.parse(row[2].toString()),
|
||||||
|
yValue: double.parse(row[3].toString()),
|
||||||
|
datetime: DateTime.parse(row[4].toString()),
|
||||||
|
lifetime: lifetime,
|
||||||
|
expiresAt: DateTime.parse(row[6].toString()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Geoposition> updatePosition(
|
||||||
|
int userId,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
Duration lifetime,
|
||||||
|
) async {
|
||||||
|
final expiresAt = DateTime.now().add(lifetime);
|
||||||
|
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
INSERT INTO geopositions (user_id, x_value, y_value, datetime, lifetime, expires_at)
|
||||||
|
VALUES (@userId, @xValue, @yValue, NOW(), @lifetime, @expiresAt)
|
||||||
|
RETURNING id, user_id, x_value, y_value, datetime, lifetime, expires_at
|
||||||
|
'''),
|
||||||
|
parameters: {
|
||||||
|
'userId': userId,
|
||||||
|
'xValue': x,
|
||||||
|
'yValue': y,
|
||||||
|
'lifetime': _toInterval(lifetime),
|
||||||
|
'expiresAt': expiresAt.toIso8601String(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final row = results.first;
|
||||||
|
return Geoposition(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
userId: int.parse(row[1].toString()),
|
||||||
|
xValue: double.parse(row[2].toString()),
|
||||||
|
yValue: double.parse(row[3].toString()),
|
||||||
|
datetime: DateTime.parse(row[4].toString()),
|
||||||
|
lifetime: lifetime,
|
||||||
|
expiresAt: DateTime.parse(row[6].toString()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Geoposition?> getLatestPosition(int userId) async {
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
SELECT id, user_id, x_value, y_value, datetime, lifetime, expires_at
|
||||||
|
FROM geopositions
|
||||||
|
WHERE user_id = @userId AND expires_at > NOW()
|
||||||
|
ORDER BY datetime DESC
|
||||||
|
LIMIT 1
|
||||||
|
'''),
|
||||||
|
parameters: {'userId': userId},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.isEmpty) return null;
|
||||||
|
|
||||||
|
final row = results.first;
|
||||||
|
return Geoposition(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
userId: int.parse(row[1].toString()),
|
||||||
|
xValue: double.parse(row[2].toString()),
|
||||||
|
yValue: double.parse(row[3].toString()),
|
||||||
|
datetime: DateTime.parse(row[4].toString()),
|
||||||
|
lifetime: Duration(
|
||||||
|
seconds: int.tryParse(row[5].toString()) ?? 0),
|
||||||
|
expiresAt: DateTime.parse(row[6].toString()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> cleanupExpired() async {
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('DELETE FROM geopositions WHERE expires_at < NOW()'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Share operations ====================
|
||||||
|
|
||||||
|
String createShareId(int userId) {
|
||||||
|
final uniqueId = _uuid.v4();
|
||||||
|
_shareLinks[uniqueId] = userId;
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getUserIdByShareId(String uniqueId) {
|
||||||
|
return _shareLinks[uniqueId];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Log operations ====================
|
||||||
|
|
||||||
|
Future<void> createLog(String username, String action) async {
|
||||||
|
await _dbConnection.execute(
|
||||||
|
Sql.named('''
|
||||||
|
INSERT INTO logs (username, action) VALUES (@username, @action)
|
||||||
|
'''),
|
||||||
|
parameters: {
|
||||||
|
'username': username,
|
||||||
|
'action': action,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Log>> getAllLogs() async {
|
||||||
|
final results = await _dbConnection.execute(
|
||||||
|
Sql.named('SELECT id, username, action, datetime FROM logs'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return results
|
||||||
|
.map(
|
||||||
|
(row) => Log(
|
||||||
|
id: int.parse(row[0].toString()),
|
||||||
|
username: row[1] as String,
|
||||||
|
action: row[2] as String,
|
||||||
|
datetime: DateTime.parse(row[3].toString()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _toInterval(Duration duration) {
|
||||||
|
final seconds = duration.inSeconds;
|
||||||
|
return '$seconds seconds';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
login VARCHAR(255) UNIQUE NOT NULL,
|
||||||
|
pwd_hash VARCHAR(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS geopositions (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
x_value DOUBLE PRECISION NOT NULL,
|
||||||
|
y_value DOUBLE PRECISION NOT NULL,
|
||||||
|
datetime TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
lifetime INTERVAL NOT NULL,
|
||||||
|
expires_at TIMESTAMP NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS logs (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
action VARCHAR(255) NOT NULL,
|
||||||
|
datetime TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
class Geoposition {
|
||||||
|
final int id;
|
||||||
|
final int userId;
|
||||||
|
final double xValue;
|
||||||
|
final double yValue;
|
||||||
|
final DateTime datetime;
|
||||||
|
final Duration lifetime;
|
||||||
|
final DateTime expiresAt;
|
||||||
|
|
||||||
|
Geoposition({
|
||||||
|
required this.id,
|
||||||
|
required this.userId,
|
||||||
|
required this.xValue,
|
||||||
|
required this.yValue,
|
||||||
|
required this.datetime,
|
||||||
|
required this.lifetime,
|
||||||
|
required this.expiresAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'x': xValue,
|
||||||
|
'y': yValue,
|
||||||
|
'datetime': datetime.toIso8601String(),
|
||||||
|
'remainingSeconds': expiresAt.difference(DateTime.now()).inSeconds,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Geoposition.fromMap(Map<String, dynamic> map) {
|
||||||
|
return Geoposition(
|
||||||
|
id: map['id'],
|
||||||
|
userId: map['user_id'],
|
||||||
|
xValue: map['x_value'].toDouble(),
|
||||||
|
yValue: map['y_value'].toDouble(),
|
||||||
|
datetime: map['datetime'] as DateTime,
|
||||||
|
lifetime: Duration(seconds: map['lifetime']),
|
||||||
|
expiresAt: map['expires_at'] as DateTime,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
class Log {
|
||||||
|
final int id;
|
||||||
|
final String username;
|
||||||
|
final String action;
|
||||||
|
final DateTime datetime;
|
||||||
|
|
||||||
|
Log({
|
||||||
|
required this.id,
|
||||||
|
required this.username,
|
||||||
|
required this.action,
|
||||||
|
required this.datetime,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Log.fromMap(Map<String, dynamic> map) {
|
||||||
|
return Log(
|
||||||
|
id: map['id'],
|
||||||
|
username: map['username'],
|
||||||
|
action: map['action'],
|
||||||
|
datetime: map['datetime'] as DateTime,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
class User {
|
||||||
|
final int id;
|
||||||
|
final String login;
|
||||||
|
final String pwdHash;
|
||||||
|
|
||||||
|
User({
|
||||||
|
required this.id,
|
||||||
|
required this.login,
|
||||||
|
required this.pwdHash,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'login': login,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory User.fromMap(Map<String, dynamic> map) {
|
||||||
|
return User(
|
||||||
|
id: map['id'],
|
||||||
|
login: map['login'],
|
||||||
|
pwdHash: map['pwd_hash'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import 'package:shelf/shelf.dart';
|
||||||
|
import 'package:shelf_router/shelf_router.dart';
|
||||||
|
import 'package:bcrypt/bcrypt.dart';
|
||||||
|
import '../database/database_provider.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class AuthRoutes {
|
||||||
|
final DatabaseProvider database;
|
||||||
|
|
||||||
|
AuthRoutes(this.database);
|
||||||
|
|
||||||
|
Router get routes {
|
||||||
|
final router = Router();
|
||||||
|
router.post('/login', _login);
|
||||||
|
router.get('/watch', _watch);
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _login(Request request) async {
|
||||||
|
final body = await request.readAsString();
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
|
||||||
|
final login = data['login'];
|
||||||
|
final password = data['password'];
|
||||||
|
|
||||||
|
final user = await database.findUserByLogin(login);
|
||||||
|
|
||||||
|
if (user == null || !BCrypt.checkpw(password, user.pwdHash)) {
|
||||||
|
return Response(401, body: 'Invalid credentials');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response(200, body: jsonEncode({'user': user.toMap()}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _watch(Request request) async {
|
||||||
|
final uniqueId = request.url.queryParameters['unique_id'];
|
||||||
|
|
||||||
|
final userId = database.getUserIdByShareId(uniqueId!);
|
||||||
|
|
||||||
|
if (userId == null) {
|
||||||
|
return Response(404, body: 'Share link not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
final position = await database.getLatestPosition(userId);
|
||||||
|
|
||||||
|
if (position == null) {
|
||||||
|
return Response(404, body: 'No position available');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response(200, body: position.toJson());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import 'package:shelf/shelf.dart';
|
||||||
|
import 'package:shelf_router/shelf_router.dart';
|
||||||
|
import '../database/database_provider.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class GeoRoutes {
|
||||||
|
final DatabaseProvider database;
|
||||||
|
|
||||||
|
GeoRoutes(this.database);
|
||||||
|
|
||||||
|
Router get routes {
|
||||||
|
final router = Router();
|
||||||
|
router.post('/geo', _createPosition);
|
||||||
|
router.put('/geo', _updatePosition);
|
||||||
|
router.post('/share', _createShare);
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _createPosition(Request request) async {
|
||||||
|
final body = await request.readAsString();
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
|
||||||
|
final userId = data['user_id'];
|
||||||
|
final x = data['x'];
|
||||||
|
final y = data['y'];
|
||||||
|
final lifetimeSeconds = data['lifetime'];
|
||||||
|
final lifetime = Duration(seconds: lifetimeSeconds);
|
||||||
|
|
||||||
|
final position = await database.createPosition(userId, x, y, lifetime);
|
||||||
|
return Response(201, body: position.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _updatePosition(Request request) async {
|
||||||
|
final body = await request.readAsString();
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
|
||||||
|
final userId = data['user_id'];
|
||||||
|
final x = data['x'];
|
||||||
|
final y = data['y'];
|
||||||
|
final lifetimeSeconds = data['lifetime'];
|
||||||
|
final lifetime = Duration(seconds: lifetimeSeconds);
|
||||||
|
|
||||||
|
final position = await database.updatePosition(userId, x, y, lifetime);
|
||||||
|
return Response(200, body: position.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _createShare(Request request) async {
|
||||||
|
final body = await request.readAsString();
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
|
||||||
|
final userId = data['user_id'];
|
||||||
|
final shareId = database.createShareId(userId);
|
||||||
|
|
||||||
|
return Response(200, body: jsonEncode({'share_id': shareId}));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import 'package:shelf/shelf.dart';
|
||||||
|
import 'package:shelf_router/shelf_router.dart';
|
||||||
|
import '../database/database_provider.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class UserRoutes {
|
||||||
|
final DatabaseProvider database;
|
||||||
|
|
||||||
|
UserRoutes(this.database);
|
||||||
|
|
||||||
|
Router get routes {
|
||||||
|
final router = Router();
|
||||||
|
router.get('/user', _getAllUsers);
|
||||||
|
router.post('/user', _createUser);
|
||||||
|
router.put('/user/<id>', _updateUser);
|
||||||
|
router.delete('/user/<id>', _deleteUser);
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _getAllUsers(Request request) async {
|
||||||
|
final users = await database.getAllUsers();
|
||||||
|
return Response(200, body: jsonEncode(users.map((u) => u.toMap()).toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _createUser(Request request) async {
|
||||||
|
final body = await request.readAsString();
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
|
||||||
|
final login = data['login'];
|
||||||
|
final password = data['password'];
|
||||||
|
|
||||||
|
final user = await database.createUser(login, password);
|
||||||
|
return Response(201, body: jsonEncode(user.toMap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _updateUser(Request request) async {
|
||||||
|
final id = int.parse(request.params['id']!);
|
||||||
|
|
||||||
|
final body = await request.readAsString();
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
|
||||||
|
final login = data['login'];
|
||||||
|
final password = data['password'];
|
||||||
|
|
||||||
|
final user = await database.updateUser(id, login, password);
|
||||||
|
return Response(200, body: jsonEncode(user.toMap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> _deleteUser(Request request) async {
|
||||||
|
final id = int.parse(request.params['id']!);
|
||||||
|
await database.deleteUser(id);
|
||||||
|
return Response(204);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:shelf/shelf.dart';
|
||||||
|
import 'package:shelf/shelf_io.dart';
|
||||||
|
import 'package:shelf_router/shelf_router.dart';
|
||||||
|
|
||||||
|
import 'database/database_provider.dart';
|
||||||
|
import 'routes/auth_routes.dart';
|
||||||
|
import 'routes/user_routes.dart';
|
||||||
|
import 'routes/geo_routes.dart';
|
||||||
|
|
||||||
|
void main(List<String> args) async {
|
||||||
|
final database = DatabaseProvider();
|
||||||
|
await database.initialize();
|
||||||
|
|
||||||
|
Timer.periodic(const Duration(minutes: 5), (timer) {
|
||||||
|
database.cleanupExpired();
|
||||||
|
});
|
||||||
|
|
||||||
|
final authRoutes = AuthRoutes(database);
|
||||||
|
final userRoutes = UserRoutes(database);
|
||||||
|
final geoRoutes = GeoRoutes(database);
|
||||||
|
|
||||||
|
final router = Router()
|
||||||
|
..mount('', authRoutes.routes.call)
|
||||||
|
..mount('', userRoutes.routes.call)
|
||||||
|
..mount('', geoRoutes.routes.call)
|
||||||
|
..get('/', (Request req) => Response.ok('Family Safety Tracker API\n'));
|
||||||
|
|
||||||
|
final handler = Pipeline()
|
||||||
|
.addMiddleware(logRequests())
|
||||||
|
.addHandler(router.call);
|
||||||
|
|
||||||
|
final ip = InternetAddress.anyIPv4;
|
||||||
|
final port = int.parse(Platform.environment['PORT'] ?? '8080');
|
||||||
|
final server = await serve(handler, ip, port);
|
||||||
|
print('Server listening on port ${server.port}');
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||||
|
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"provider": {
|
||||||
|
"llama.cpp": {
|
||||||
|
"npm": "@ai-sdk/openai-compatible",
|
||||||
|
"name": "llama-server (local)",
|
||||||
|
"options": {
|
||||||
|
"baseURL": "http://127.0.0.1:9988/v1"
|
||||||
|
},
|
||||||
|
"models": {
|
||||||
|
"qwen3-coder:a3b": {
|
||||||
|
"name": "Qwen_Qwen3.5-9B-Q6_K (local)",
|
||||||
|
"limit": {
|
||||||
|
"context": 42000,
|
||||||
|
"output": 42000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mcp": {
|
||||||
|
"IntelliJIdea": {
|
||||||
|
"type": "remote",
|
||||||
|
"url": "http://127.0.0.1:64342/stream",
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+517
@@ -0,0 +1,517 @@
|
|||||||
|
# Generated by pub
|
||||||
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
|
packages:
|
||||||
|
_fe_analyzer_shared:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _fe_analyzer_shared
|
||||||
|
sha256: a49d6cf99e8d8e7a8e93668d09ced0bbdb954d0b4fccc2f5f9241c6b87fad95c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "99.0.0"
|
||||||
|
adaptive_number:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: adaptive_number
|
||||||
|
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
analyzer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer
|
||||||
|
sha256: "663efa951fb8a45e06f491223a604c93820598f20e6a99c25617a1576065e8b7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "12.1.0"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.0"
|
||||||
|
async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: async
|
||||||
|
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.13.1"
|
||||||
|
bcrypt:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: bcrypt
|
||||||
|
sha256: "6073a700cbbc59f1d4ab27cd532755e3de5e676c4941f535f351374df849270b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
boolean_selector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: boolean_selector
|
||||||
|
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
buffer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: buffer
|
||||||
|
sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.3"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
|
cli_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_config
|
||||||
|
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
|
clock:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: clock
|
||||||
|
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: collection
|
||||||
|
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.19.1"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
|
coverage:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: coverage
|
||||||
|
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.15.0"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.7"
|
||||||
|
dart_jsonwebtoken:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dart_jsonwebtoken
|
||||||
|
sha256: "00a0812d2aeaeb0d30bcbc4dd3cee57971dbc0ab2216adf4f0247f37793f15ef"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.17.0"
|
||||||
|
dotenv:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dotenv
|
||||||
|
sha256: "379e64b6fc82d3df29461d349a1796ecd2c436c480d4653f3af6872eccbc90e1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.0"
|
||||||
|
ed25519_edwards:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ed25519_edwards
|
||||||
|
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.1"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
frontend_server_client:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: frontend_server_client
|
||||||
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0"
|
||||||
|
glob:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: glob
|
||||||
|
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.3"
|
||||||
|
http:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.0"
|
||||||
|
http_methods:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_methods
|
||||||
|
sha256: "6bccce8f1ec7b5d701e7921dca35e202d425b57e317ba1a37f2638590e29e566"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
http_multi_server:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_multi_server
|
||||||
|
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.2"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.2"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.5"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.2"
|
||||||
|
lints:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: lints
|
||||||
|
sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.0"
|
||||||
|
logging:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
matcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: matcher
|
||||||
|
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.20"
|
||||||
|
meta:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: meta
|
||||||
|
sha256: df0c643f44ad098eb37988027a8e2b2b5a031fd3977f06bbfd3a76637e8df739
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.18.2"
|
||||||
|
mime:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
node_preamble:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_preamble
|
||||||
|
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
package_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_config
|
||||||
|
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
|
path:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path
|
||||||
|
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.9.1"
|
||||||
|
pointycastle:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pointycastle
|
||||||
|
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.9.1"
|
||||||
|
pool:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pool
|
||||||
|
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.2"
|
||||||
|
postgres:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: postgres
|
||||||
|
sha256: "3af8a28b89fef68ee5b26b4fd27254d5a286389e9c7fb6293a5f46e30490f800"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.5.10"
|
||||||
|
pub_semver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pub_semver
|
||||||
|
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
|
shelf:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shelf
|
||||||
|
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.2"
|
||||||
|
shelf_packages_handler:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_packages_handler
|
||||||
|
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
shelf_router:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shelf_router
|
||||||
|
sha256: f5e5d492440a7fb165fe1e2e1a623f31f734d3370900070b2b1e0d0428d59864
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.4"
|
||||||
|
shelf_static:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_static
|
||||||
|
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.3"
|
||||||
|
shelf_web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_web_socket
|
||||||
|
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
|
source_map_stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_map_stack_trace
|
||||||
|
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
source_maps:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_maps
|
||||||
|
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.13"
|
||||||
|
source_span:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_span
|
||||||
|
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.2"
|
||||||
|
stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stack_trace
|
||||||
|
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.12.1"
|
||||||
|
stream_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_channel
|
||||||
|
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.4"
|
||||||
|
string_scanner:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_scanner
|
||||||
|
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.1"
|
||||||
|
term_glyph:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: term_glyph
|
||||||
|
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.2"
|
||||||
|
test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: test
|
||||||
|
sha256: ca578dc12bb8b2f40b67b7d3bd2fac4f31c01a6ff7130a14e2597b919934507f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.31.1"
|
||||||
|
test_api:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_api
|
||||||
|
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.12"
|
||||||
|
test_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_core
|
||||||
|
sha256: d2e98ec12998368dc59ddd47ab709f2cd55acd6b66dc7db764455a44082f4bc5
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.18"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
|
uuid:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.3"
|
||||||
|
vm_service:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vm_service
|
||||||
|
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "15.2.0"
|
||||||
|
watcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: watcher
|
||||||
|
sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket
|
||||||
|
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
web_socket_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket_channel
|
||||||
|
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.3"
|
||||||
|
webkit_inspection_protocol:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webkit_inspection_protocol
|
||||||
|
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
|
sdks:
|
||||||
|
dart: ">=3.10.1 <4.0.0"
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
name: family_safety_tracker
|
||||||
|
description: A server app using the shelf package and Docker.
|
||||||
|
version: 1.0.0
|
||||||
|
# repository: https://github.com/my_org/my_repo
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ^3.10.1
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
shelf: ^1.4.2
|
||||||
|
shelf_router: ^1.1.2
|
||||||
|
dart_jsonwebtoken: ^2.16.0
|
||||||
|
bcrypt: ^1.2.0
|
||||||
|
dotenv: ^4.1.0
|
||||||
|
postgres: ^3.5.10
|
||||||
|
uuid: ^4.5.0
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
http: ^1.2.2
|
||||||
|
lints: ^6.0.0
|
||||||
|
test: ^1.25.6
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final port = '8080';
|
||||||
|
final host = 'http://0.0.0.0:$port';
|
||||||
|
late Process p;
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
p = await Process.start(
|
||||||
|
'dart',
|
||||||
|
['run', 'bin/server.dart'],
|
||||||
|
environment: {'PORT': port},
|
||||||
|
);
|
||||||
|
// Wait for server to start and print to stdout.
|
||||||
|
await p.stdout.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() => p.kill());
|
||||||
|
|
||||||
|
test('Root', () async {
|
||||||
|
final response = await get(Uri.parse('$host/'));
|
||||||
|
expect(response.statusCode, 200);
|
||||||
|
expect(response.body, 'Hello, World!\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Echo', () async {
|
||||||
|
final response = await get(Uri.parse('$host/echo/hello'));
|
||||||
|
expect(response.statusCode, 200);
|
||||||
|
expect(response.body, 'hello\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('404', () async {
|
||||||
|
final response = await get(Uri.parse('$host/foobar'));
|
||||||
|
expect(response.statusCode, 404);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import 'package:bcrypt/bcrypt.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
print(BCrypt);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user