Compare commits

..

2 Commits

Author SHA1 Message Date
3ef21ea010
feat: add new crud macro for easier entity manipulation in DB
Some checks failed
CI / tests (pull_request) Failing after 1s
CI / tests (push) Failing after 4m57s
2025-01-15 03:40:36 +01:00
a2ea5a157d
feat: OAuth implementation with Discord
This commit separates the core features of géjdr from the backend as
these will also be used by the bot in the future.

This commit also updates the dependencies of the project. It also
removes the dependency lettre as well as the mailpit docker service
for developers as it appears clearer this project won’t send emails
anytime soon.

The publication of a docker image is also postponed until later.
2025-01-11 22:10:16 +01:00
15 changed files with 606 additions and 209 deletions

View File

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
branches: branches:
- 'main' - 'main'
- 'develop'
jobs: jobs:
publish: publish:
@ -20,14 +21,26 @@ jobs:
with: with:
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
registry: ${{ var.REGISTRY }}
- uses: cachix/install-nix-action@v27 - uses: cachix/install-nix-action@v27
with: with:
nix_path: nixpkgs=channel:nixos-unstable nix_path: nixpkgs=channel:nixos-unstable
- name: Build Docker image - name: Build Docker image
run: nix develop --command -- just docker-build run: nix develop --command -- just backend build-docker
- name: Load Docker image - name: Load Docker image
run: docker load < result run: docker load < result
- name: Docker Metadata action - name: Docker Metadata action
uses: docker/metadata-action@v5.5.1 uses: docker/metadata-action@v5.6.1
with: with:
image: tal-backend:latest image: gejdr-backend:latest
tags:
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
labels: |
org.opencontainers.image.title=Backend GéJDR
org.opencontainers.image.description=Backend for GéJDR
org.opencontainers.image.vendor=Lucien Cartier-Tilet <lucien@phundrak.com>

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
.env .env
/result /result
/coverage/ /coverage/
/gejdr-backend/result
/gejdr-bot/result

270
Cargo.lock generated
View File

@ -135,6 +135,12 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.83" version = "0.1.83"
@ -143,7 +149,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -572,8 +578,8 @@ dependencies = [
"ident_case", "ident_case",
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim 0.11.1",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -584,7 +590,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -593,6 +599,47 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "deluxe"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488"
dependencies = [
"deluxe-core",
"deluxe-macros",
"once_cell",
"proc-macro2",
"syn 2.0.96",
]
[[package]]
name = "deluxe-core"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313"
dependencies = [
"arrayvec",
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 2.0.96",
]
[[package]]
name = "deluxe-macros"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117"
dependencies = [
"deluxe-core",
"heck 0.4.1",
"if_chain",
"proc-macro-crate 1.3.1",
"proc-macro2",
"quote",
"syn 2.0.96",
]
[[package]] [[package]]
name = "der" name = "der"
version = "0.7.9" version = "0.7.9"
@ -630,7 +677,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
"unicode-xid", "unicode-xid",
] ]
@ -663,7 +710,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -760,6 +807,12 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.1" version = "1.2.1"
@ -836,7 +889,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -912,6 +965,7 @@ name = "gejdr-core"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"gejdr-macros",
"serde", "serde",
"sqlx", "sqlx",
"tracing", "tracing",
@ -919,6 +973,17 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "gejdr-macros"
version = "0.1.0"
dependencies = [
"deluxe",
"proc-macro2",
"quote",
"sqlx",
"syn 2.0.96",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -1021,6 +1086,11 @@ name = "hashbrown"
version = "0.15.1" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]] [[package]]
name = "hashlink" name = "hashlink"
@ -1033,11 +1103,11 @@ dependencies = [
[[package]] [[package]]
name = "hashlink" name = "hashlink"
version = "0.9.1" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
dependencies = [ dependencies = [
"hashbrown 0.14.5", "hashbrown 0.15.1",
] ]
[[package]] [[package]]
@ -1064,6 +1134,12 @@ dependencies = [
"http 1.1.0", "http 1.1.0",
] ]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.5.0" version = "0.5.0"
@ -1421,7 +1497,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -1451,6 +1527,12 @@ dependencies = [
"icu_properties", "icu_properties",
] ]
[[package]]
name = "if_chain"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.6.0" version = "2.6.0"
@ -1529,7 +1611,6 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
dependencies = [ dependencies = [
"cc",
"pkg-config", "pkg-config",
"vcpkg", "vcpkg",
] ]
@ -1809,12 +1890,6 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]] [[package]]
name = "pathdiff" name = "pathdiff"
version = "0.2.2" version = "0.2.2"
@ -1867,7 +1942,7 @@ dependencies = [
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -1994,10 +2069,10 @@ version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2553c04acbd3887e2ad1959ff007fb9ec05d15d67931b6fdd6eb47de138649" checksum = "7f2553c04acbd3887e2ad1959ff007fb9ec05d15d67931b6fdd6eb47de138649"
dependencies = [ dependencies = [
"proc-macro-crate", "proc-macro-crate 3.2.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -2037,11 +2112,11 @@ dependencies = [
"http 1.1.0", "http 1.1.0",
"indexmap", "indexmap",
"mime", "mime",
"proc-macro-crate", "proc-macro-crate 3.2.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"regex", "regex",
"syn 2.0.89", "syn 2.0.96",
"thiserror 1.0.69", "thiserror 1.0.69",
] ]
@ -2106,20 +2181,30 @@ dependencies = [
"indexmap", "indexmap",
] ]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
dependencies = [
"once_cell",
"toml_edit 0.19.15",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.2.0" version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [ dependencies = [
"toml_edit", "toml_edit 0.22.22",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.92" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -2188,9 +2273,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -2581,7 +2666,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -2747,21 +2832,11 @@ dependencies = [
"der", "der",
] ]
[[package]]
name = "sqlformat"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790"
dependencies = [
"nom",
"unicode_categories",
]
[[package]] [[package]]
name = "sqlx" name = "sqlx"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f"
dependencies = [ dependencies = [
"sqlx-core", "sqlx-core",
"sqlx-macros", "sqlx-macros",
@ -2772,38 +2847,32 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-core" name = "sqlx-core"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0"
dependencies = [ dependencies = [
"atoi",
"byteorder",
"bytes 1.8.0", "bytes 1.8.0",
"chrono", "chrono",
"crc", "crc",
"crossbeam-queue", "crossbeam-queue",
"either", "either",
"event-listener", "event-listener",
"futures-channel",
"futures-core", "futures-core",
"futures-intrusive", "futures-intrusive",
"futures-io", "futures-io",
"futures-util", "futures-util",
"hashbrown 0.14.5", "hashbrown 0.15.1",
"hashlink 0.9.1", "hashlink 0.10.0",
"hex",
"indexmap", "indexmap",
"log", "log",
"memchr", "memchr",
"once_cell", "once_cell",
"paste",
"percent-encoding", "percent-encoding",
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.10.8", "sha2 0.10.8",
"smallvec", "smallvec",
"sqlformat", "thiserror 2.0.3",
"thiserror 1.0.69",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tracing", "tracing",
@ -2813,26 +2882,26 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-macros" name = "sqlx-macros"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"sqlx-core", "sqlx-core",
"sqlx-macros-core", "sqlx-macros-core",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
name = "sqlx-macros-core" name = "sqlx-macros-core"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad"
dependencies = [ dependencies = [
"dotenvy", "dotenvy",
"either", "either",
"heck", "heck 0.5.0",
"hex", "hex",
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
@ -2844,7 +2913,7 @@ dependencies = [
"sqlx-mysql", "sqlx-mysql",
"sqlx-postgres", "sqlx-postgres",
"sqlx-sqlite", "sqlx-sqlite",
"syn 2.0.89", "syn 2.0.96",
"tempfile", "tempfile",
"tokio", "tokio",
"url", "url",
@ -2852,9 +2921,9 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-mysql" name = "sqlx-mysql"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64 0.22.1", "base64 0.22.1",
@ -2888,7 +2957,7 @@ dependencies = [
"smallvec", "smallvec",
"sqlx-core", "sqlx-core",
"stringprep", "stringprep",
"thiserror 1.0.69", "thiserror 2.0.3",
"tracing", "tracing",
"uuid", "uuid",
"whoami", "whoami",
@ -2896,9 +2965,9 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-postgres" name = "sqlx-postgres"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64 0.22.1", "base64 0.22.1",
@ -2910,7 +2979,6 @@ dependencies = [
"etcetera", "etcetera",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io",
"futures-util", "futures-util",
"hex", "hex",
"hkdf", "hkdf",
@ -2928,7 +2996,7 @@ dependencies = [
"smallvec", "smallvec",
"sqlx-core", "sqlx-core",
"stringprep", "stringprep",
"thiserror 1.0.69", "thiserror 2.0.3",
"tracing", "tracing",
"uuid", "uuid",
"whoami", "whoami",
@ -2936,9 +3004,9 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-sqlite" name = "sqlx-sqlite"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540"
dependencies = [ dependencies = [
"atoi", "atoi",
"chrono", "chrono",
@ -2988,6 +3056,12 @@ dependencies = [
"unicode-properties", "unicode-properties",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@ -3013,9 +3087,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.89" version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3045,7 +3119,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -3108,7 +3182,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -3119,7 +3193,7 @@ checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -3221,7 +3295,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -3290,7 +3364,7 @@ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit", "toml_edit 0.22.22",
] ]
[[package]] [[package]]
@ -3302,6 +3376,17 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "toml_edit"
version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap",
"toml_datetime",
"winnow 0.5.40",
]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.22" version = "0.22.22"
@ -3312,7 +3397,7 @@ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"winnow", "winnow 0.6.20",
] ]
[[package]] [[package]]
@ -3341,7 +3426,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -3462,12 +3547,6 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "unicode_categories"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]] [[package]]
name = "universal-hash" name = "universal-hash"
version = "0.4.0" version = "0.4.0"
@ -3526,9 +3605,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.11.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"serde", "serde",
@ -3595,7 +3674,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3629,7 +3708,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3900,6 +3979,15 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.20" version = "0.6.20"
@ -3962,7 +4050,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
"synstructure", "synstructure",
] ]
@ -3984,7 +4072,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]
[[package]] [[package]]
@ -4004,7 +4092,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
"synstructure", "synstructure",
] ]
@ -4033,5 +4121,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.89", "syn 2.0.96",
] ]

View File

@ -4,5 +4,6 @@ members = [
"gejdr-core", "gejdr-core",
"gejdr-bot", "gejdr-bot",
"gejdr-backend", "gejdr-backend",
"gejdr-macros"
] ]
resolver = "2" resolver = "2"

View File

@ -1,19 +0,0 @@
default: run
prepare:
pushd gejdr-backend
cargo sqlx prepare
popd
build:
cargo auditable build
build-release:
cargo auditable build --release
run:
cargo auditable run --bin gejdr-backend
## Local Variables:
## mode: makefile
## End:

View File

@ -18,30 +18,61 @@
rustc = rustVersion; rustc = rustVersion;
}; };
appName = "gejdr-backend"; appNameBackend = "gejdr-backend";
appNameBot = "gejdr-bot";
appRustBuild = rustPlatform.buildRustPackage { appRustBuildBackend = rustPlatform.buildRustPackage {
pname = appName; pname = appNameBackend;
version = "0.1.0"; version = "0.1.0";
src = ./.; src = ./.;
cargoLock.lockFile = ./Cargo.lock; cargoLock.lockFile = ./Cargo.lock;
buildPhase = ''
cd gejdr-backend
SQLX_OFFLINE="1" cargo build --release --bin gejdr-backend
'';
installPhase = ''
cargo install --path . --root "$out/bin/"
'';
};
appRustBuildBot = rustPlatform.buildRustPackage {
pname = appNameBot;
version = "0.1.0";
src = ./.;
cargoLock.lockFile = ./Cargo.lock;
buildPhase = ''
SQLX_OFFLINE="1" cargo build --release --bin gejdr-bot
'';
}; };
dockerImage = pkgs.dockerTools.buildLayeredImage { dockerImageBackend = pkgs.dockerTools.buildLayeredImage {
name = appName; name = appNameBackend;
tag = "latest";
config = { config = {
Entrypoint = [ "${appRustBuild}/bin/${appName}" ]; Entrypoint = [ "${appRustBuildBackend}/bin/${appNameBackend}" ];
Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]; Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ];
Tag = "latest"; Tag = "latest";
}; };
contents = [ appRustBuild pkgs.cacert ]; contents = [ appRustBuildBackend pkgs.cacert ];
};
dockerImageBot = pkgs.dockerTools.buildLayeredImage {
name = appNameBot;
tag = "latest";
fromImageTag = "latest";
config = {
Entrypoint = [ "${appRustBuildBot}/bin/${appNameBot}" ];
Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ];
Tag = "latest";
};
contents = [ appRustBuildBot pkgs.cacert ];
}; };
in { in {
packages = { packages = {
rustPackage = appRustBuild; backend = appRustBuildBot;
docker = dockerImage; bot = appRustBuildBot;
dockerBackend = dockerImageBackend;
dockerBot = dockerImageBot;
}; };
defaultPackage = dockerImage; defaultPackage = dockerImageBackend;
devShell = with pkgs; mkShell { devShell = with pkgs; mkShell {
buildInputs = [ buildInputs = [
bacon bacon

View File

@ -0,0 +1,18 @@
default: run
build $SQLX_OFFLINE="1":
pwd
cargo auditable build --bin gejdr-backend
build-release $SQLX_OFFLINE="1":
cargo auditable build --release --bin gejdr-backend
build-docker:
nix build .#dockerBackend
run:
cargo auditable run --bin gejdr-backend
## Local Variables:
## mode: makefile
## End:

View File

@ -9,8 +9,9 @@ serde = "1.0.215"
tracing = "0.1.40" tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["fmt", "std", "env-filter", "registry", "json", "tracing-log"] } tracing-subscriber = { version = "0.3.18", features = ["fmt", "std", "env-filter", "registry", "json", "tracing-log"] }
uuid = { version = "1.11.0", features = ["v4", "serde"] } uuid = { version = "1.11.0", features = ["v4", "serde"] }
gejdr-macros = { path = "../gejdr-macros" }
[dependencies.sqlx] [dependencies.sqlx]
version = "0.8.2" version = "0.8.3"
default-features = false default-features = false
features = ["postgres", "uuid", "chrono", "migrate", "runtime-tokio", "macros"] features = ["postgres", "uuid", "chrono", "migrate", "runtime-tokio", "macros"]

View File

@ -1,4 +1,5 @@
use sqlx::PgPool; use sqlx::PgPool;
use super::Crud;
type Timestampz = chrono::DateTime<chrono::Utc>; type Timestampz = chrono::DateTime<chrono::Utc>;
@ -17,13 +18,15 @@ impl RemoteUser {
pub async fn refresh_in_database(self, pool: &PgPool) -> Result<User, sqlx::Error> { pub async fn refresh_in_database(self, pool: &PgPool) -> Result<User, sqlx::Error> {
match User::find(pool, &self.id).await? { match User::find(pool, &self.id).await? {
Some(local_user) => local_user.update_from_remote(self).update(pool).await, Some(local_user) => local_user.update_from_remote(self).update(pool).await,
None => User::from(self).save(pool).await, None => User::from(self).create(pool).await,
} }
} }
} }
#[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq, Default, Clone)] #[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq, Default, Clone, Crud)]
#[crud(table = "users")]
pub struct User { pub struct User {
#[crud(id = true)]
pub id: String, pub id: String,
pub username: String, pub username: String,
pub email: Option<String>, pub email: Option<String>,
@ -79,68 +82,6 @@ impl User {
} }
} }
} }
pub async fn find(pool: &PgPool, id: &String) -> Result<Option<Self>, sqlx::Error> {
sqlx::query_as!(Self, r#"SELECT * FROM users WHERE id = $1"#, id)
.fetch_optional(pool)
.await
}
pub async fn save(&self, pool: &PgPool) -> Result<Self, sqlx::Error> {
sqlx::query_as!(
Self,
r#"
INSERT INTO users (id, username, email, avatar, name, created_at, last_updated)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING *
"#,
self.id,
self.username,
self.email,
self.avatar,
self.name,
self.created_at,
self.last_updated
)
.fetch_one(pool)
.await
}
pub async fn update(&self, pool: &PgPool) -> Result<Self, sqlx::Error> {
sqlx::query_as!(
Self,
r#"
UPDATE users
SET username = $1, email = $2, avatar = $3, name = $4, last_updated = $5
WHERE id = $6
RETURNING *
"#,
self.username,
self.email,
self.avatar,
self.name,
self.last_updated,
self.id
)
.fetch_one(pool)
.await
}
pub async fn save_or_update(&self, pool: &PgPool) -> Result<Self, sqlx::Error> {
if Self::find(pool, &self.id).await?.is_some() {
self.update(pool).await
} else {
self.save(pool).await
}
}
pub async fn delete(pool: &PgPool, id: &String) -> Result<u64, sqlx::Error> {
let rows_affected = sqlx::query!("DELETE FROM users WHERE id = $1", id)
.execute(pool)
.await?
.rows_affected();
Ok(rows_affected)
}
} }
#[cfg(test)] #[cfg(test)]
@ -287,7 +228,7 @@ mod tests {
username: "user1".into(), username: "user1".into(),
..Default::default() ..Default::default()
}; };
user.save(&pool).await?; user.create(&pool).await?;
let users = sqlx::query_as!(User, "SELECT * FROM users") let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&pool) .fetch_all(&pool)
.await?; .await?;
@ -328,7 +269,7 @@ mod tests {
username: "user1".into(), username: "user1".into(),
..Default::default() ..Default::default()
}; };
user.save_or_update(&pool).await?; user.create_or_update(&pool).await?;
let rows = sqlx::query_as!(User, "SELECT * FROM users") let rows = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&pool) .fetch_all(&pool)
.await?; .await?;
@ -350,7 +291,7 @@ mod tests {
name: Some("Cool Nam".into()), name: Some("Cool Nam".into()),
..Default::default() ..Default::default()
}; };
user.save_or_update(&pool).await?; user.create_or_update(&pool).await?;
let rows = sqlx::query_as!(User, "SELECT * FROM users") let rows = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&pool) .fetch_all(&pool)
.await?; .await?;
@ -369,7 +310,7 @@ mod tests {
.await?; .await?;
assert_eq!(2, rows.len()); assert_eq!(2, rows.len());
let id = "id1".to_string(); let id = "id1".to_string();
let deletions = User::delete(&pool, &id).await?; let deletions = User::delete_by_id(&pool, &id).await?;
assert_eq!(1, deletions); assert_eq!(1, deletions);
let rows = sqlx::query_as!(User, "SELECT * FROM users") let rows = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&pool) .fetch_all(&pool)
@ -385,7 +326,7 @@ mod tests {
.await?; .await?;
assert_eq!(2, rows.len()); assert_eq!(2, rows.len());
let id = "invalid".to_string(); let id = "invalid".to_string();
let deletions = User::delete(&pool, &id).await?; let deletions = User::delete_by_id(&pool, &id).await?;
assert_eq!(0, deletions); assert_eq!(0, deletions);
let rows = sqlx::query_as!(User, "SELECT * FROM users") let rows = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&pool) .fetch_all(&pool)

View File

@ -1 +1,73 @@
pub mod accounts; pub mod accounts;
pub use gejdr_macros::Crud;
pub trait Crud<Id> {
/// Find the entiy in the database based on its identifier.
///
/// # Errors
/// Returns any error Postgres may have encountered
fn find(
pool: &sqlx::PgPool,
id: &Id,
) -> impl std::future::Future<Output = sqlx::Result<Option<Self>>> + Send
where
Self: Sized;
/// Create the entity in the database.
///
/// # Errors
/// Returns any error Postgres may have encountered
fn create(
&self,
pool: &sqlx::PgPool,
) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
where
Self: Sized;
/// Update an entity with a matching identifier in the database.
///
/// # Errors
/// Returns any error Postgres may have encountered
fn update(
&self,
pool: &sqlx::PgPool,
) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
where
Self: Sized;
/// Update an entity with a matching identifier in the database if
/// it exists, create it otherwise.
///
/// # Errors
/// Returns any error Postgres may have encountered
fn create_or_update(
&self,
pool: &sqlx::PgPool,
) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
where
Self: Sized;
/// Delete the entity from the database if it exists.
///
/// # Returns
/// Returns the amount of rows affected by the deletion.
///
/// # Errors
/// Returns any error Postgres may have encountered
fn delete(
&self,
pool: &sqlx::PgPool,
) -> impl std::future::Future<Output = sqlx::Result<u64>> + Send;
/// Delete any entity with the identifier `id`.
///
/// # Returns
/// Returns the amount of rows affected by the deletion.
///
/// # Errors
/// Returns any error Postgres may have encountered
fn delete_by_id(
pool: &sqlx::PgPool,
id: &Id,
) -> impl std::future::Future<Output = sqlx::Result<u64>> + Send;
}

18
gejdr-macros/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "gejdr-macros"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
deluxe = "0.5.0"
proc-macro2 = "1.0.93"
quote = "1.0.38"
syn = "2.0.96"
[dependencies.sqlx]
version = "0.8.3"
default-features = false
features = ["postgres", "uuid", "chrono", "migrate", "runtime-tokio", "macros"]

View File

@ -0,0 +1,23 @@
#[derive(deluxe::ExtractAttributes)]
#[deluxe(attributes(crud))]
pub struct CrudStructAttributes {
pub table: String,
}
#[derive(deluxe::ExtractAttributes, Clone)]
#[deluxe(attributes(crud))]
pub struct CrudFieldAttributes {
#[deluxe(default = false)]
pub id: bool,
#[deluxe(default = None)]
pub column: Option<String>,
}
#[derive(Clone)]
pub struct CrudField {
pub ident: syn::Ident,
pub field: syn::Field,
pub column: String,
pub id: bool,
pub ty: syn::Type
}

View File

@ -0,0 +1,195 @@
use ir::{CrudField, CrudFieldAttributes, CrudStructAttributes};
use quote::quote;
use syn::DeriveInput;
mod ir;
fn extract_crud_field_attrs(
ast: &mut DeriveInput,
) -> deluxe::Result<(Vec<CrudField>, CrudField)> {
let mut field_attrs: Vec<CrudField> = Vec::new();
// let mut identifier: Option<CrudIdentifier> = None;
let mut identifier: Option<CrudField> = None;
let mut identifier_counter = 0;
if let syn::Data::Struct(s) = &mut ast.data {
for field in &mut s.fields {
let ident = field.clone().ident.unwrap();
let ty = field.clone().ty;
let attrs: CrudFieldAttributes =
deluxe::extract_attributes(field).expect("Could not extract attributes from field");
let field = CrudField {
ident: ident.clone(),
field: field.to_owned(),
column: attrs.column.unwrap_or_else(|| ident.to_string()),
id: attrs.id,
ty
};
if attrs.id {
identifier_counter += 1;
identifier = Some(field.clone());
}
if identifier_counter > 1 {
return Err(syn::Error::new_spanned(
field.field,
"Struct {name} can only have one identifier",
));
}
field_attrs.push(field);
}
}
if identifier_counter < 1 {
Err(syn::Error::new_spanned(
ast,
"Struct {name} must have one identifier",
))
} else {
Ok((field_attrs, identifier.unwrap()))
}
}
fn generate_find_query(
table: &str,
id: &CrudField
) -> proc_macro2::TokenStream {
let find_string = format!("SELECT * FROM {} WHERE {} = $1", table, id.column);
let ty = &id.ty;
quote! {
async fn find(pool: &::sqlx::PgPool, id: &#ty) -> ::sqlx::Result<Option<Self>> {
::sqlx::query_as!(Self, #find_string, id)
.fetch_optional(pool)
.await
}
}
}
fn generate_create_query(
table: &str,
fields: &[CrudField]
) -> proc_macro2::TokenStream {
let inputs: Vec<String> = (1..=fields.len())
.map(|num| format!("${num}"))
.collect();
let create_string = format!(
"INSERT INTO {} ({}) VALUES ({}) RETURNING *",
table,
fields.iter().map(|v| v.column.clone()).collect::<Vec<String>>().join(", "),
inputs.join(", ")
);
let field_idents: Vec<syn::Ident> = fields.iter().map(|f| f.ident.clone()).collect();
quote! {
async fn create(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<Self> {
::sqlx::query_as!(
Self,
#create_string,
#(self.#field_idents),*
)
.fetch_one(pool)
.await
}
}
}
fn generate_update_query(
table: &str,
fields: &[CrudField],
id: &CrudField
) -> proc_macro2::TokenStream {
let mut fields: Vec<&CrudField> = fields.iter().filter(|f| !f.id).collect();
let update_columns = fields.iter().enumerate()
.map(|(i, &field)| format!("{} = ${}", field.column, i + 1))
.collect::<Vec<String>>()
.join(", ");
let update_string = format!(
"UPDATE {} SET {} WHERE {} = ${} RETURNING *",
table,
update_columns,
id.column,
fields.len() + 1
);
fields.push(id);
let field_idents: Vec<_> = fields.iter().map(|f| f.ident.clone()).collect();
quote! {
async fn update(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<Self> {
::sqlx::query_as!(
Self,
#update_string,
#(self.#field_idents),*
)
.fetch_one(pool)
.await
}
}
}
fn generate_delete_query(
table: &str,
id: &CrudField
) -> proc_macro2::TokenStream {
let delete_string = format!("DELETE FROM {} WHERE {} = $1", table, id.column);
let ty = &id.ty;
let ident = &id.ident;
quote! {
async fn delete_by_id(pool: &::sqlx::PgPool, id: &#ty) -> ::sqlx::Result<u64> {
let rows_affected = ::sqlx::query!(#delete_string, id)
.execute(pool)
.await?
.rows_affected();
Ok(rows_affected)
}
async fn delete(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<u64> {
let rows_affected = ::sqlx::query!(#delete_string, self.#ident)
.execute(pool)
.await?
.rows_affected();
Ok(rows_affected)
}
}
}
pub fn crud_derive_macro2(
item: proc_macro2::TokenStream,
) -> deluxe::Result<proc_macro2::TokenStream> {
// parse
let mut ast: DeriveInput = syn::parse2(item).expect("Failed to parse input");
// extract struct attributes
let CrudStructAttributes { table } =
deluxe::extract_attributes(&mut ast).expect("Could not extract attributes from struct");
// extract field attributes
let (fields, id) = extract_crud_field_attrs(&mut ast)?;
let ty = &id.ty;
let id_ident = &id.ident;
// define impl variables
let ident = &ast.ident;
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
// generate
let find_query = generate_find_query(&table, &id);
let create_query = generate_create_query(&table, &fields);
let update_query = generate_update_query(&table, &fields, &id);
let delete_query = generate_delete_query(&table, &id);
let code = quote! {
impl #impl_generics Crud<#ty> for #ident #type_generics #where_clause {
#find_query
#create_query
#update_query
async fn create_or_update(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<Self> {
if Self::find(pool, &self.#id_ident).await?.is_some() {
self.update(pool).await
} else {
self.create(pool).await
}
}
#delete_query
}
};
Ok(code)
}

19
gejdr-macros/src/lib.rs Normal file
View File

@ -0,0 +1,19 @@
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![deny(clippy::nursery)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::unused_async)]
#![allow(clippy::useless_let_if_seq)] // Reason: prevents some OpenApi structs from compiling
mod crud;
use crud::crud_derive_macro2;
/// Generates CRUD code for Sqlx for a struct.
///
/// # Panics
///
/// May panic if errors arise while parsing and generating code.
#[proc_macro_derive(Crud, attributes(crud))]
pub fn crud_derive_macro(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
crud_derive_macro2(item.into()).unwrap().into()
}

View File

@ -1,4 +1,4 @@
mod backend mod backend 'gejdr-backend/backend.just'
mod docker mod docker
default: lint default: lint
@ -12,28 +12,22 @@ format-check:
migrate: migrate:
sqlx migrate run --source gejdr-core/migrations sqlx migrate run --source gejdr-core/migrations
build: build $SQLX_OFFLINE="1":
cargo auditable build --bin gejdr-backend cargo auditable build --bin gejdr-backend
cargo auditable build --bin gejdr-bot cargo auditable build --bin gejdr-bot
lint: build-release $SQLX_OFFLINE="1":
cargo clippy --all-targets
msrv:
cargo msrv verify
release-build:
cargo auditable build --release --bin gejdr-backend cargo auditable build --release --bin gejdr-backend
cargo auditable build --release --bin gejdr-bot cargo auditable build --release --bin gejdr-bot
release-run: lint:
cargo auditable run --release cargo clippy --all-targets
audit: build audit: build
cargo audit bin target/debug/gejdr-backend cargo audit bin target/debug/gejdr-backend
cargo audit bin target/debug/gejdr-bot cargo audit bin target/debug/gejdr-bot
audit-release: audit-release: build-release
cargo audit bin target/release/gejdr-backend cargo audit bin target/release/gejdr-backend
cargo audit bin target/release/gejdr-bot cargo audit bin target/release/gejdr-bot
@ -48,10 +42,10 @@ coverage-ci:
mkdir -p coverage mkdir -p coverage
cargo tarpaulin --config .tarpaulin.ci.toml cargo tarpaulin --config .tarpaulin.ci.toml
check-all: format-check lint msrv coverage audit check-all: format-check lint coverage audit
# docker-build: docker-backend $SQLX_OFFLINE="1":
# nix build .#docker nix build .#dockerBackend
## Local Variables: ## Local Variables:
## mode: makefile ## mode: makefile