Compare commits
9 Commits
d27022b26a
...
0.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1736aeb122 | ||
|
|
37d0c33633 | ||
|
|
3bfe779425 | ||
|
|
395099d0ee | ||
|
|
b922a610e6 | ||
|
|
7010aee5b2 | ||
|
|
614f044160 | ||
|
|
5b9ab3f47d | ||
|
|
b6f03f9efb |
@@ -3,7 +3,7 @@ name: Release
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*.*.*'
|
- "v*.*.*"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_release:
|
build_release:
|
||||||
@@ -22,6 +22,11 @@ jobs:
|
|||||||
- name: Build release
|
- name: Build release
|
||||||
run: |
|
run: |
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
|
- name: Package frontend
|
||||||
|
run: |
|
||||||
|
zip -r static.zip static
|
||||||
|
|
||||||
- name: Generate a changelog
|
- name: Generate a changelog
|
||||||
uses: orhun/git-cliff-action@v4
|
uses: orhun/git-cliff-action@v4
|
||||||
id: git-cliff
|
id: git-cliff
|
||||||
@@ -31,8 +36,10 @@ jobs:
|
|||||||
github_token: ""
|
github_token: ""
|
||||||
env:
|
env:
|
||||||
OUTPUT: CHANGELOG.md
|
OUTPUT: CHANGELOG.md
|
||||||
|
|
||||||
- uses: akkuman/gitea-release-action@v1
|
- uses: akkuman/gitea-release-action@v1
|
||||||
with:
|
with:
|
||||||
files: |-
|
files: |-
|
||||||
target/release/weight_tracker
|
target/release/weight_tracker
|
||||||
body: Release build for weight_tracker
|
static.zip
|
||||||
|
body: ${{ steps.git-cliff.outputs.content }}
|
||||||
|
|||||||
235
Cargo.lock
generated
235
Cargo.lock
generated
@@ -37,6 +37,17 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.2.17",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "allocator-api2"
|
name = "allocator-api2"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@@ -225,7 +236,7 @@ dependencies = [
|
|||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"cookie",
|
"cookie",
|
||||||
@@ -259,6 +270,12 @@ dependencies = [
|
|||||||
"sqlx",
|
"sqlx",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
@@ -280,6 +297,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
@@ -409,6 +432,25 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "config"
|
||||||
|
version = "0.13.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"json5",
|
||||||
|
"lazy_static",
|
||||||
|
"nom",
|
||||||
|
"pathdiff",
|
||||||
|
"ron",
|
||||||
|
"rust-ini",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"toml",
|
||||||
|
"yaml-rust",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-oid"
|
name = "const-oid"
|
||||||
version = "0.9.6"
|
version = "0.9.6"
|
||||||
@@ -422,7 +464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"subtle",
|
"subtle",
|
||||||
@@ -581,6 +623,12 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlv-list"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenvy"
|
name = "dotenvy"
|
||||||
version = "0.15.7"
|
version = "0.15.7"
|
||||||
@@ -882,6 +930,15 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
@@ -1049,7 +1106,7 @@ version = "0.1.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
|
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -1310,6 +1367,17 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "json5"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -1343,7 +1411,7 @@ version = "0.1.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"
|
checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"libc",
|
"libc",
|
||||||
"plain",
|
"plain",
|
||||||
"redox_syscall 0.7.4",
|
"redox_syscall 0.7.4",
|
||||||
@@ -1360,6 +1428,12 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
@@ -1425,6 +1499,12 @@ dependencies = [
|
|||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -1436,6 +1516,16 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nonempty"
|
name = "nonempty"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -1500,7 +1590,7 @@ version = "5.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d"
|
checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
"getrandom 0.2.17",
|
"getrandom 0.2.17",
|
||||||
"http",
|
"http",
|
||||||
@@ -1532,6 +1622,16 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
|
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-multimap"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
|
||||||
|
dependencies = [
|
||||||
|
"dlv-list",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking"
|
name = "parking"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
@@ -1561,6 +1661,12 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathdiff"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pem-rfc7468"
|
name = "pem-rfc7468"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -1576,6 +1682,49 @@ version = "2.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_derive"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_generator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_generator"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_meta",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_meta"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@@ -1829,7 +1978,7 @@ version = "0.5.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1838,7 +1987,7 @@ version = "0.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a"
|
checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1847,7 +1996,7 @@ version = "0.12.28"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
|
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"http",
|
"http",
|
||||||
@@ -1885,7 +2034,7 @@ version = "0.13.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801"
|
checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -1933,6 +2082,17 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rsa"
|
name = "rsa"
|
||||||
version = "0.9.10"
|
version = "0.9.10"
|
||||||
@@ -1953,6 +2113,16 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-ini"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"ordered-multimap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "2.1.2"
|
version = "2.1.2"
|
||||||
@@ -2077,7 +2247,7 @@ version = "3.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"core-foundation 0.10.1",
|
"core-foundation 0.10.1",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2277,7 +2447,7 @@ version = "0.8.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
|
checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"crc",
|
"crc",
|
||||||
@@ -2354,8 +2524,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
|
checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -2398,8 +2568,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
|
checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"chrono",
|
"chrono",
|
||||||
"crc",
|
"crc",
|
||||||
@@ -2516,7 +2686,7 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
|
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"system-configuration-sys",
|
"system-configuration-sys",
|
||||||
]
|
]
|
||||||
@@ -2689,6 +2859,15 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
@@ -2711,7 +2890,7 @@ version = "0.6.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -2789,6 +2968,12 @@ version = "1.19.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
@@ -3019,7 +3204,7 @@ version = "0.244.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"hashbrown 0.15.5",
|
"hashbrown 0.15.5",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"semver",
|
"semver",
|
||||||
@@ -3074,13 +3259,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "weight_tracker"
|
name = "weight_tracker"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"askama",
|
"askama",
|
||||||
"axum",
|
"axum",
|
||||||
"axum_session",
|
"axum_session",
|
||||||
"axum_session_sqlx",
|
"axum_session_sqlx",
|
||||||
|
"config",
|
||||||
"oauth2",
|
"oauth2",
|
||||||
"reqwest 0.13.2",
|
"reqwest 0.13.2",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3534,7 +3720,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3570,6 +3756,15 @@ version = "0.6.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
|
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yoke"
|
name = "yoke"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "weight_tracker"
|
name = "weight_tracker"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -16,4 +16,5 @@ tokio = { version = "1.0", features = ["full"] }
|
|||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
config = { version = "0.13", features = ["toml"] }
|
||||||
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
||||||
|
|||||||
20
config.example.toml
Normal file
20
config.example.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# OIDC Configuration
|
||||||
|
[oidc]
|
||||||
|
client_id = "your_client_id"
|
||||||
|
client_secret = "your_client_secret"
|
||||||
|
auth_url = "https://your-provider.com/auth"
|
||||||
|
token_url = "https://your-provider.com/token"
|
||||||
|
redirect_url = "http://localhost:3000/auth/callback"
|
||||||
|
|
||||||
|
# Server Configuration
|
||||||
|
[server]
|
||||||
|
host = "127.0.0.1"
|
||||||
|
port = 3000
|
||||||
|
|
||||||
|
# Database Configuration
|
||||||
|
[database]
|
||||||
|
url = "sqlite:weight_tracker.db"
|
||||||
|
|
||||||
|
# Session Configuration
|
||||||
|
[session]
|
||||||
|
secret = "your_secret_key_that_is_long_enough_so_the_library_does_not_complain"
|
||||||
@@ -14,7 +14,7 @@ if [ "${CONFIRM}" != "Y" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git commit -am "chore: bump version to ${VERSION}"
|
git commit --allow-empty -am "chore: bump version to ${VERSION}"
|
||||||
git tag -am "Version ${VERSION}" "${VERSION}"
|
git tag -am "Version ${VERSION}" "${VERSION}"
|
||||||
|
|
||||||
echo Press Y to push commit and tag
|
echo Press Y to push commit and tag
|
||||||
|
|||||||
113
src/config.rs
Normal file
113
src/config.rs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
use oauth2::{AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl, basic::BasicClient};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::OidcClient;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub oidc: OidcConfig,
|
||||||
|
pub server: ServerConfig,
|
||||||
|
pub database: DatabaseConfig,
|
||||||
|
pub session: SessionConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct OidcConfig {
|
||||||
|
pub client_id: String,
|
||||||
|
pub client_secret: String,
|
||||||
|
pub auth_url: String,
|
||||||
|
pub token_url: String,
|
||||||
|
pub redirect_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OidcConfig {
|
||||||
|
pub fn to_client(
|
||||||
|
&self,
|
||||||
|
) -> OidcClient {
|
||||||
|
let client_id = ClientId::new(self.client_id.clone());
|
||||||
|
let client_secret = ClientSecret::new(self.client_secret.clone());
|
||||||
|
let auth_url = AuthUrl::new(self.auth_url.clone()).unwrap();
|
||||||
|
let token_url = TokenUrl::new(self.token_url.clone()).unwrap();
|
||||||
|
let redirect_url = RedirectUrl::new(self.redirect_url.clone()).unwrap();
|
||||||
|
|
||||||
|
BasicClient::new(client_id)
|
||||||
|
.set_client_secret(client_secret)
|
||||||
|
.set_auth_uri(auth_url)
|
||||||
|
.set_token_uri(token_url)
|
||||||
|
.set_redirect_uri(redirect_url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ServerConfig {
|
||||||
|
pub host: String,
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct DatabaseConfig {
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SessionConfig {
|
||||||
|
pub secret: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
/// Load configuration from a TOML file and environment variables
|
||||||
|
/// config-rs merges file config with environment variables automatically
|
||||||
|
pub fn load(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let mut builder = config::Config::builder();
|
||||||
|
|
||||||
|
// Add default values first
|
||||||
|
let defaults = Self::defaults();
|
||||||
|
builder = builder.add_source(
|
||||||
|
config::Config::try_from(&defaults)
|
||||||
|
.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load from file if it exists
|
||||||
|
if Path::new(path).exists() {
|
||||||
|
builder = builder.add_source(config::File::with_name(path).required(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override with environment variables
|
||||||
|
// Environment variables should be prefixed with the app name and use __ for nesting
|
||||||
|
// e.g., WEIGHT_TRACKER_OIDC__CLIENT_ID for oidc.client_id
|
||||||
|
builder = builder.add_source(
|
||||||
|
config::Environment::with_prefix("WEIGHT_TRACKER")
|
||||||
|
.try_parsing(true)
|
||||||
|
.separator("__"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let config = builder.build()?;
|
||||||
|
let result: Config = config.try_deserialize()?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get default configuration values
|
||||||
|
fn defaults() -> Self {
|
||||||
|
Config {
|
||||||
|
oidc: OidcConfig {
|
||||||
|
client_id: "your_client_id".to_string(),
|
||||||
|
client_secret: "your_client_secret".to_string(),
|
||||||
|
auth_url: "https://your-provider.com/auth".to_string(),
|
||||||
|
token_url: "https://your-provider.com/token".to_string(),
|
||||||
|
redirect_url: "http://localhost:3000/auth/callback".to_string(),
|
||||||
|
},
|
||||||
|
server: ServerConfig {
|
||||||
|
host: "127.0.0.1".to_string(),
|
||||||
|
port: 3000,
|
||||||
|
},
|
||||||
|
database: DatabaseConfig {
|
||||||
|
url: "sqlite:weight_tracker.db".to_string(),
|
||||||
|
},
|
||||||
|
session: SessionConfig {
|
||||||
|
secret: "your_secret_key_that_is_long_enough_so_the_library_does_not_complain"
|
||||||
|
.to_string(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,11 @@ use axum::response::{Html, Redirect};
|
|||||||
use axum::{Form, extract::Query, extract::State};
|
use axum::{Form, extract::Query, extract::State};
|
||||||
use axum_session::Session;
|
use axum_session::Session;
|
||||||
use axum_session_sqlx::SessionSqlitePool;
|
use axum_session_sqlx::SessionSqlitePool;
|
||||||
use oauth2::{AuthorizationCode, CsrfToken, PkceCodeChallenge, PkceCodeVerifier, Scope, TokenResponse, HttpRequest, HttpResponse};
|
|
||||||
use oauth2::http;
|
use oauth2::http;
|
||||||
|
use oauth2::{
|
||||||
|
AuthorizationCode, CsrfToken, HttpRequest, HttpResponse, PkceCodeChallenge, PkceCodeVerifier,
|
||||||
|
Scope, TokenResponse,
|
||||||
|
};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@@ -17,6 +20,7 @@ pub struct IndexTemplate {
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct WeightForm {
|
pub struct WeightForm {
|
||||||
date: String,
|
date: String,
|
||||||
|
time: String,
|
||||||
weight: f64,
|
weight: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +32,10 @@ pub async fn index(State(state): State<crate::AppState>) -> Html<String> {
|
|||||||
Html(template.render().unwrap())
|
Html(template.render().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login(State(state): State<crate::AppState>, session: Session<SessionSqlitePool>) -> Redirect {
|
pub async fn login(
|
||||||
|
State(state): State<crate::AppState>,
|
||||||
|
session: Session<SessionSqlitePool>,
|
||||||
|
) -> Redirect {
|
||||||
// Generate PKCE challenge
|
// Generate PKCE challenge
|
||||||
let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();
|
let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();
|
||||||
|
|
||||||
@@ -102,9 +109,7 @@ pub async fn callback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Async HTTP client for oauth2
|
// Async HTTP client for oauth2
|
||||||
async fn async_http_client(
|
async fn async_http_client(req: HttpRequest) -> Result<HttpResponse, reqwest::Error> {
|
||||||
req: HttpRequest,
|
|
||||||
) -> Result<HttpResponse, reqwest::Error> {
|
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
|
|
||||||
// Convert http::Method to reqwest::Method
|
// Convert http::Method to reqwest::Method
|
||||||
@@ -130,8 +135,7 @@ async fn async_http_client(
|
|||||||
let body = response.bytes().await?;
|
let body = response.bytes().await?;
|
||||||
|
|
||||||
// Construct an http::Response
|
// Construct an http::Response
|
||||||
let mut http_response = http::Response::builder()
|
let mut http_response = http::Response::builder().status(status_code);
|
||||||
.status(status_code);
|
|
||||||
|
|
||||||
for (k, v) in headers.iter() {
|
for (k, v) in headers.iter() {
|
||||||
http_response = http_response.header(k, v);
|
http_response = http_response.header(k, v);
|
||||||
@@ -147,7 +151,8 @@ pub async fn input_post(
|
|||||||
) -> Result<Html<String>, Redirect> {
|
) -> Result<Html<String>, Redirect> {
|
||||||
// Check if user is authenticated
|
// Check if user is authenticated
|
||||||
if let Some(user_id) = session.get::<String>("user_id") {
|
if let Some(user_id) = session.get::<String>("user_id") {
|
||||||
super::models::insert_weight(&state.pool, &user_id, &form.date, form.weight)
|
let datetime = format!("{}T{}", form.date, form.time);
|
||||||
|
super::models::insert_weight(&state.pool, &user_id, &datetime, form.weight)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let weights = super::models::get_all_weights(&state.pool)
|
let weights = super::models::get_all_weights(&state.pool)
|
||||||
@@ -157,7 +162,7 @@ pub async fn input_post(
|
|||||||
for weight in weights {
|
for weight in weights {
|
||||||
html.push_str(&format!(
|
html.push_str(&format!(
|
||||||
"<p>{}: {} kg by {}</p>\n",
|
"<p>{}: {} kg by {}</p>\n",
|
||||||
weight.date, weight.weight, weight.user_id
|
weight.date, weight.weight, &user_id
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(Html(html))
|
Ok(Html(html))
|
||||||
|
|||||||
13
src/lib.rs
13
src/lib.rs
@@ -1,5 +1,6 @@
|
|||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
pub mod config;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
Router,
|
Router,
|
||||||
@@ -10,10 +11,7 @@ use axum_session_sqlx::SessionSqlitePool;
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub type OidcClient = oauth2::Client<
|
||||||
pub struct AppState {
|
|
||||||
pub pool: SqlitePool,
|
|
||||||
pub oidc_client: oauth2::Client<
|
|
||||||
oauth2::StandardErrorResponse<oauth2::basic::BasicErrorResponseType>,
|
oauth2::StandardErrorResponse<oauth2::basic::BasicErrorResponseType>,
|
||||||
oauth2::StandardTokenResponse<oauth2::EmptyExtraTokenFields, oauth2::basic::BasicTokenType>,
|
oauth2::StandardTokenResponse<oauth2::EmptyExtraTokenFields, oauth2::basic::BasicTokenType>,
|
||||||
oauth2::StandardTokenIntrospectionResponse<
|
oauth2::StandardTokenIntrospectionResponse<
|
||||||
@@ -27,7 +25,12 @@ pub struct AppState {
|
|||||||
oauth2::EndpointNotSet,
|
oauth2::EndpointNotSet,
|
||||||
oauth2::EndpointNotSet,
|
oauth2::EndpointNotSet,
|
||||||
oauth2::EndpointSet,
|
oauth2::EndpointSet,
|
||||||
>,
|
>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AppState {
|
||||||
|
pub pool: SqlitePool,
|
||||||
|
pub oidc_client: OidcClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_app(state: AppState, session_secret: Vec<u8>, pool: SqlitePool) -> Router {
|
pub async fn create_app(state: AppState, session_secret: Vec<u8>, pool: SqlitePool) -> Router {
|
||||||
|
|||||||
56
src/main.rs
56
src/main.rs
@@ -1,44 +1,33 @@
|
|||||||
use oauth2::{AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl, basic::BasicClient};
|
use std::str::FromStr;
|
||||||
|
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use std::env;
|
use weight_tracker::{AppState, config::Config, create_app};
|
||||||
use weight_tracker::{AppState, create_app};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
let config = Config::load("config.toml").unwrap_or_else(|e| {
|
||||||
|
eprintln!("Failed to load configuration: {}", e);
|
||||||
|
eprintln!("Using default values. Set environment variables prefixed with WEIGHT_TRACKER_ to override.");
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
// Set up database
|
// Set up database
|
||||||
let database_url = "sqlite:weight_tracker.db";
|
let pool = SqlitePool::connect_with(
|
||||||
let pool = SqlitePool::connect(database_url)
|
sqlx::sqlite::SqliteConnectOptions::from_str(&config.database.url)
|
||||||
|
.expect("Could not parse database URL")
|
||||||
|
.create_if_missing(true),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to connect to database");
|
.expect("Failed to connect to database");
|
||||||
|
sqlx::migrate!()
|
||||||
|
.run(&pool)
|
||||||
|
.await
|
||||||
|
.expect("Could not run database migrations");
|
||||||
|
|
||||||
// Set up OIDC client
|
// Set up OIDC client
|
||||||
let client_id =
|
let oidc_client = config.oidc.to_client();
|
||||||
ClientId::new(env::var("OIDC_CLIENT_ID").unwrap_or_else(|_| "your_client_id".to_string()));
|
|
||||||
let client_secret = ClientSecret::new(
|
|
||||||
env::var("OIDC_CLIENT_SECRET").unwrap_or_else(|_| "your_client_secret".to_string()),
|
|
||||||
);
|
|
||||||
let auth_url = AuthUrl::new(
|
|
||||||
env::var("OIDC_AUTH_URL").unwrap_or_else(|_| "https://your-provider.com/auth".to_string()),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let token_url = TokenUrl::new(
|
|
||||||
env::var("OIDC_TOKEN_URL")
|
|
||||||
.unwrap_or_else(|_| "https://your-provider.com/token".to_string()),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let redirect_url = RedirectUrl::new("http://localhost:3000/auth/callback".to_string()).unwrap();
|
|
||||||
|
|
||||||
let oidc_client = BasicClient::new(client_id)
|
let secret = config.session.secret.as_bytes().to_vec();
|
||||||
.set_client_secret(client_secret)
|
|
||||||
.set_auth_uri(auth_url)
|
|
||||||
.set_token_uri(token_url)
|
|
||||||
// Set the URL the user will be redirected to after the authorization process.
|
|
||||||
.set_redirect_uri(redirect_url);
|
|
||||||
|
|
||||||
let secret = env::var("SESSION_SECRET")
|
|
||||||
.unwrap_or_else(|_| "your_secret_key_that_is_long_enough_so_the_library_does_not_complain".to_string())
|
|
||||||
.as_bytes()
|
|
||||||
.to_vec();
|
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
pool: pool.clone(),
|
pool: pool.clone(),
|
||||||
@@ -47,9 +36,8 @@ async fn main() {
|
|||||||
|
|
||||||
let app = create_app(app_state, secret, pool).await;
|
let app = create_app(app_state, secret, pool).await;
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
let addr = format!("{}:{}", config.server.host, config.server.port);
|
||||||
.await
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||||
.unwrap();
|
|
||||||
println!("listening on {}", listener.local_addr().unwrap());
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,46 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Weight Tracker</title>
|
<title>Weight Tracker</title>
|
||||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function fillCurrentDateTime() {
|
||||||
|
// Fill date and time with current values
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
// Format date as YYYY-MM-DD
|
||||||
|
const year = now.getFullYear();
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(now.getDate()).padStart(2, '0');
|
||||||
|
document.getElementById('date').value = `${year}-${month}-${day}`;
|
||||||
|
|
||||||
|
// Format time as HH:MM
|
||||||
|
const hours = String(now.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||||
|
document.getElementById('time').value = `${hours}:${minutes}`;
|
||||||
|
|
||||||
|
// Fill weight with the latest weight from the list
|
||||||
|
const weightElements = document.querySelectorAll('#weights p');
|
||||||
|
if (weightElements.length > 0) {
|
||||||
|
const latestWeightText = weightElements[0].textContent;
|
||||||
|
// Extract weight value from format "YYYY-MM-DD: XX.X kg by username"
|
||||||
|
const match = latestWeightText.match(/(\d+\.?\d*)\s*kg/);
|
||||||
|
if (match) {
|
||||||
|
document.getElementById('weight').value = match[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showInputDialog() {
|
||||||
|
fillCurrentDateTime();
|
||||||
|
document.getElementById('inputDialog').showModal();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Weight Tracker</h1>
|
<h1>Weight Tracker</h1>
|
||||||
<div id="weights">
|
<div id="weights">
|
||||||
@@ -12,16 +48,20 @@
|
|||||||
<p>{{ weight.date }}: {{ weight.weight }} kg by {{ weight.user_id }}</p>
|
<p>{{ weight.date }}: {{ weight.weight }} kg by {{ weight.user_id }}</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<button onclick="document.getElementById('inputDialog').showModal()">Add Weight</button>
|
<button onclick="showInputDialog()">Add Weight</button>
|
||||||
<dialog id="inputDialog">
|
<dialog id="inputDialog">
|
||||||
<h1>Add Weight</h1>
|
<h1>Add Weight</h1>
|
||||||
<form hx-post="/input" hx-target="#weights" hx-swap="innerHTML" hx-on:htmx:after-request="document.getElementById('inputDialog').close()">
|
<form hx-post="/input" hx-target="#weights" hx-swap="innerHTML"
|
||||||
|
hx-on:htmx:after-request="document.getElementById('inputDialog').close()">
|
||||||
<label for="date">Date:</label>
|
<label for="date">Date:</label>
|
||||||
<input type="date" id="date" name="date" required><br>
|
<input type="date" id="date" name="date" required><br>
|
||||||
|
<label for="time">Time:</label>
|
||||||
|
<input type="time" id="time" name="time" required><br>
|
||||||
<label for="weight">Weight (kg):</label>
|
<label for="weight">Weight (kg):</label>
|
||||||
<input type="number" step="0.1" id="weight" name="weight" required><br>
|
<input type="number" step="0.1" id="weight" name="weight" required><br>
|
||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Add Weight</title>
|
|
||||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Add Weight</h1>
|
|
||||||
<form hx-post="/input" hx-target="#result" hx-swap="innerHTML">
|
|
||||||
<label for="date">Date:</label>
|
|
||||||
<input type="date" id="date" name="date" required><br>
|
|
||||||
<label for="weight">Weight (kg):</label>
|
|
||||||
<input type="number" step="0.1" id="weight" name="weight" required><br>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</form>
|
|
||||||
<div id="result"></div>
|
|
||||||
<a href="/">Back to Tracker</a>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -18,8 +18,8 @@ async fn make_app() -> axum::Router {
|
|||||||
Some(TokenUrl::new("http://localhost/token".into()).unwrap()),
|
Some(TokenUrl::new("http://localhost/token".into()).unwrap()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let state = AppState { pool, oidc_client };
|
let state = AppState { pool: pool.clone(), oidc_client };
|
||||||
create_app(state, b"01234567890123456789012345678901".to_vec())
|
create_app(state, b"01234567890123456789012345678901".to_vec(), pool).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
Reference in New Issue
Block a user