BLOG-90 Intergrate error tracking with Sentry #120
488
backend/Cargo.lock
generated
488
backend/Cargo.lock
generated
@ -424,9 +424,11 @@ version = "0.2.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-session",
|
"actix-session",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"log",
|
"common",
|
||||||
"openidconnect",
|
"openidconnect",
|
||||||
|
"sentry",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
@ -617,6 +619,13 @@ dependencies = [
|
|||||||
"tokio-util",
|
"tokio-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "common"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"sqlx",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@ -656,6 +665,16 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
@ -804,6 +823,16 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "debugid"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.7.10"
|
version = "0.7.10"
|
||||||
@ -1081,6 +1110,18 @@ version = "0.2.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "findshlibs"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
@ -1114,6 +1155,21 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -1372,6 +1428,17 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hostname"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
@ -1465,6 +1532,22 @@ dependencies = [
|
|||||||
"webpki-roots 1.0.2",
|
"webpki-roots 1.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-tls"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@ -1664,10 +1747,12 @@ version = "0.2.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-multipart",
|
"actix-multipart",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"auth",
|
"auth",
|
||||||
|
"common",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"sentry",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
@ -1922,6 +2007,23 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@ -2057,6 +2159,50 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "2.10.1"
|
version = "2.10.1"
|
||||||
@ -2066,6 +2212,18 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_info"
|
||||||
|
version = "3.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"plist",
|
||||||
|
"serde",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "p256"
|
name = "p256"
|
||||||
version = "0.13.2"
|
version = "0.13.2"
|
||||||
@ -2199,6 +2357,19 @@ version = "0.3.32"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plist"
|
||||||
|
version = "1.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"indexmap 2.9.0",
|
||||||
|
"quick-xml",
|
||||||
|
"serde",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polyval"
|
name = "polyval"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
@ -2231,10 +2402,12 @@ name = "post"
|
|||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"auth",
|
"auth",
|
||||||
"chrono",
|
"chrono",
|
||||||
"log",
|
"common",
|
||||||
|
"sentry",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
@ -2273,6 +2446,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-xml"
|
||||||
|
version = "0.38.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn"
|
name = "quinn"
|
||||||
version = "0.11.8"
|
version = "0.11.8"
|
||||||
@ -2505,9 +2687,11 @@ dependencies = [
|
|||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
|
"hyper-tls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
|
"native-tls",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn",
|
"quinn",
|
||||||
@ -2518,6 +2702,7 @@ dependencies = [
|
|||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
@ -2621,6 +2806,15 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pemfile"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
@ -2653,6 +2847,15 @@ version = "1.0.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars"
|
name = "schemars"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -2697,12 +2900,168 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.26"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "989425268ab5c011e06400187eed6c298272f8ef913e49fcadc3fda788b45030"
|
||||||
|
dependencies = [
|
||||||
|
"httpdate",
|
||||||
|
"native-tls",
|
||||||
|
"reqwest",
|
||||||
|
"sentry-actix",
|
||||||
|
"sentry-anyhow",
|
||||||
|
"sentry-backtrace",
|
||||||
|
"sentry-contexts",
|
||||||
|
"sentry-core",
|
||||||
|
"sentry-debug-images",
|
||||||
|
"sentry-panic",
|
||||||
|
"sentry-tracing",
|
||||||
|
"tokio",
|
||||||
|
"ureq",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-actix"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5c675bdf6118764a8e265c3395c311b4d905d12866c92df52870c0223d2ffc1"
|
||||||
|
dependencies = [
|
||||||
|
"actix-http",
|
||||||
|
"actix-web",
|
||||||
|
"bytes",
|
||||||
|
"futures-util",
|
||||||
|
"sentry-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-anyhow"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1b4523c2595d6730bfbe401e95a6423fe9cb16dc3b6046f340551591cffe723"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"sentry-backtrace",
|
||||||
|
"sentry-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-backtrace"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68e299dd3f7bcf676875eee852c9941e1d08278a743c32ca528e2debf846a653"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"regex",
|
||||||
|
"sentry-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-contexts"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fac0c5d6892cd4c414492fc957477b620026fb3411fca9fa12774831da561c88"
|
||||||
|
dependencies = [
|
||||||
|
"hostname",
|
||||||
|
"libc",
|
||||||
|
"os_info",
|
||||||
|
"rustc_version",
|
||||||
|
"sentry-core",
|
||||||
|
"uname",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-core"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "deaa38b94e70820ff3f1f9db3c8b0aef053b667be130f618e615e0ff2492cbcc"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.9.1",
|
||||||
|
"sentry-types",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-debug-images"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00950648aa0d371c7f57057434ad5671bd4c106390df7e7284739330786a01b6"
|
||||||
|
dependencies = [
|
||||||
|
"findshlibs",
|
||||||
|
"sentry-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-panic"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b7a23b13c004873de3ce7db86eb0f59fe4adfc655a31f7bbc17fd10bacc9bfe"
|
||||||
|
dependencies = [
|
||||||
|
"sentry-backtrace",
|
||||||
|
"sentry-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-tracing"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fac841c7050aa73fc2bec8f7d8e9cb1159af0b3095757b99820823f3e54e5080"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"sentry-backtrace",
|
||||||
|
"sentry-core",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-types"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e477f4d4db08ddb4ab553717a8d3a511bc9e81dde0c808c680feacbb8105c412"
|
||||||
|
dependencies = [
|
||||||
|
"debugid",
|
||||||
|
"hex",
|
||||||
|
"rand 0.9.1",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"time",
|
||||||
|
"url",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
@ -2822,6 +3181,7 @@ dependencies = [
|
|||||||
"openidconnect",
|
"openidconnect",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"post",
|
"post",
|
||||||
|
"sentry",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"utoipa-redoc",
|
"utoipa-redoc",
|
||||||
@ -3302,6 +3662,16 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-native-tls"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||||
|
dependencies = [
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-retry"
|
name = "tokio-retry"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -3422,6 +3792,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
|
dependencies = [
|
||||||
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3436,6 +3816,15 @@ version = "1.18.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uname"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.18"
|
version = "0.3.18"
|
||||||
@ -3485,6 +3874,36 @@ version = "0.9.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ureq"
|
||||||
|
version = "3.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f0fde9bc91026e381155f8c67cb354bcd35260b2f4a29bcc84639f762760c39"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"der",
|
||||||
|
"log",
|
||||||
|
"native-tls",
|
||||||
|
"percent-encoding",
|
||||||
|
"rustls-pemfile",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"ureq-proto",
|
||||||
|
"utf-8",
|
||||||
|
"webpki-root-certs 0.26.11",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ureq-proto"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"http 1.3.1",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.5.4"
|
version = "2.5.4"
|
||||||
@ -3497,6 +3916,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf16_iter"
|
name = "utf16_iter"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
@ -3552,6 +3977,23 @@ dependencies = [
|
|||||||
"utoipa",
|
"utoipa",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@ -3685,6 +4127,24 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-root-certs"
|
||||||
|
version = "0.26.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e"
|
||||||
|
dependencies = [
|
||||||
|
"webpki-root-certs 1.0.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-root-certs"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.26.10"
|
version = "0.26.10"
|
||||||
@ -3713,6 +4173,28 @@ dependencies = [
|
|||||||
"wasite",
|
"wasite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.61.0"
|
version = "0.61.0"
|
||||||
|
@ -1,15 +1,26 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["server", "feature/auth", "feature/image", "feature/post"]
|
members = [
|
||||||
|
"server",
|
||||||
|
"feature/auth",
|
||||||
|
"feature/common",
|
||||||
|
"feature/image",
|
||||||
|
"feature/post",
|
||||||
|
"feature/common",
|
||||||
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
actix-multipart = "0.7.2"
|
actix-multipart = "0.7.2"
|
||||||
actix-session = { version = "0.10.1", features = ["redis-session"] }
|
actix-session = { version = "0.10.1", features = ["redis-session"] }
|
||||||
actix-web = "4.10.2"
|
actix-web = "4.10.2"
|
||||||
|
anyhow = "1.0.98"
|
||||||
async-trait = "0.1.88"
|
async-trait = "0.1.88"
|
||||||
chrono = "0.4.41"
|
chrono = "0.4.41"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
@ -22,6 +33,7 @@ openidconnect = { version = "4.0.1", features = [
|
|||||||
"reqwest-blocking",
|
"reqwest-blocking",
|
||||||
] }
|
] }
|
||||||
percent-encoding = "2.3.1"
|
percent-encoding = "2.3.1"
|
||||||
|
sentry = { version = "0.42.0", features = ["actix", "anyhow"] }
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
sqlx = { version = "0.8.5", features = [
|
sqlx = { version = "0.8.5", features = [
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -39,5 +51,6 @@ utoipa-redoc = { version = "6.0.0", features = ["actix-web"] }
|
|||||||
|
|
||||||
server.path = "server"
|
server.path = "server"
|
||||||
auth.path = "feature/auth"
|
auth.path = "feature/auth"
|
||||||
|
common.path = "feature/common"
|
||||||
image.path = "feature/image"
|
image.path = "feature/image"
|
||||||
post.path = "feature/post"
|
post.path = "feature/post"
|
||||||
|
@ -13,6 +13,7 @@ COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/server .
|
|||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
VOLUME ["/app/static"]
|
VOLUME ["/app/static"]
|
||||||
ENV RUST_LOG=info
|
ENV RUST_LOG=info
|
||||||
|
ENV RUST_BACKTRACE=1
|
||||||
ENV HOST=0.0.0.0
|
ENV HOST=0.0.0.0
|
||||||
ENV PORT=8080
|
ENV PORT=8080
|
||||||
ENV STORAGE_PATH=/app/static
|
ENV STORAGE_PATH=/app/static
|
||||||
@ -27,5 +28,6 @@ ENV OIDC_ISSUER_URL=
|
|||||||
ENV OIDC_REDIRECT_URL=
|
ENV OIDC_REDIRECT_URL=
|
||||||
ENV OIDC_CLIENT_ID=
|
ENV OIDC_CLIENT_ID=
|
||||||
ENV OIDC_CLIENT_SECRET=
|
ENV OIDC_CLIENT_SECRET=
|
||||||
|
ENV SENTRY_DSN=
|
||||||
|
|
||||||
CMD ["./server"]
|
CMD ["./server"]
|
||||||
|
@ -6,9 +6,12 @@ edition.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
actix-session.workspace = true
|
actix-session.workspace = true
|
||||||
actix-web.workspace = true
|
actix-web.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
log.workspace = true
|
|
||||||
openidconnect.workspace = true
|
openidconnect.workspace = true
|
||||||
|
sentry.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
sqlx.workspace = true
|
sqlx.workspace = true
|
||||||
utoipa.workspace = true
|
utoipa.workspace = true
|
||||||
|
|
||||||
|
common.workspace = true
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
#[derive(Debug, PartialEq)]
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum AuthError {
|
pub enum AuthError {
|
||||||
DatabaseError(String),
|
|
||||||
OidcError(String),
|
|
||||||
InvalidState,
|
InvalidState,
|
||||||
InvalidNonce,
|
InvalidNonce,
|
||||||
InvalidAuthCode,
|
InvalidAuthCode,
|
||||||
InvalidIdToken,
|
InvalidIdToken,
|
||||||
UserNotFound,
|
UserNotFound,
|
||||||
|
Unexpected(anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AuthError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
AuthError::InvalidState => write!(f, "Invalid state"),
|
||||||
|
AuthError::InvalidNonce => write!(f, "Invalid nonce"),
|
||||||
|
AuthError::InvalidAuthCode => write!(f, "Invalid authentication code"),
|
||||||
|
AuthError::InvalidIdToken => write!(f, "Invalid ID token"),
|
||||||
|
AuthError::UserNotFound => write!(f, "User not found"),
|
||||||
|
AuthError::Unexpected(e) => write!(f, "Unexpected error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use common::framework::error::DatabaseError;
|
||||||
use sqlx::{Pool, Postgres};
|
use sqlx::{Pool, Postgres};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -31,7 +32,7 @@ impl UserDbService for UserDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_optional(&self.db_pool)
|
.fetch_optional(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| AuthError::DatabaseError(e.to_string()))?;
|
.map_err(|e| AuthError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
match record {
|
match record {
|
||||||
Some(record) => Ok(record.into_mapper()),
|
Some(record) => Ok(record.into_mapper()),
|
||||||
@ -56,7 +57,7 @@ impl UserDbService for UserDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_optional(&self.db_pool)
|
.fetch_optional(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| AuthError::DatabaseError(e.to_string()))?;
|
.map_err(|e| AuthError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
match record {
|
match record {
|
||||||
Some(record) => Ok(record.into_mapper()),
|
Some(record) => Ok(record.into_mapper()),
|
||||||
@ -78,7 +79,7 @@ impl UserDbService for UserDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_one(&self.db_pool)
|
.fetch_one(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| AuthError::DatabaseError(e.to_string()))?;
|
.map_err(|e| AuthError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ impl AuthOidcService for AuthOidcServiceImpl {
|
|||||||
let token_response = self
|
let token_response = self
|
||||||
.oidc_client
|
.oidc_client
|
||||||
.exchange_code(AuthorizationCode::new(code.to_string()))
|
.exchange_code(AuthorizationCode::new(code.to_string()))
|
||||||
.map_err(|e| AuthError::OidcError(e.to_string()))?
|
.unwrap()
|
||||||
.request_async(&self.http_client)
|
.request_async(&self.http_client)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| AuthError::InvalidAuthCode)?;
|
.map_err(|_| AuthError::InvalidAuthCode)?;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use std::future::{self, Ready};
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
future::{self, Ready},
|
||||||
|
};
|
||||||
|
|
||||||
use actix_session::SessionExt;
|
use actix_session::SessionExt;
|
||||||
use actix_web::{Error, FromRequest, HttpRequest, dev::Payload, error::ErrorUnauthorized};
|
use actix_web::{FromRequest, HttpRequest, dev::Payload};
|
||||||
|
|
||||||
use crate::framework::web::constants::SESSION_KEY_USER_ID;
|
use crate::framework::web::constants::SESSION_KEY_USER_ID;
|
||||||
|
|
||||||
@ -14,20 +17,39 @@ impl UserId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for UserId {
|
impl FromRequest for UserId {
|
||||||
type Error = Error;
|
type Error = UnauthorizedError;
|
||||||
type Future = Ready<Result<Self, Self::Error>>;
|
type Future = Ready<Result<Self, UnauthorizedError>>;
|
||||||
|
|
||||||
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
||||||
let user_id_result = req.get_session().get::<i32>(SESSION_KEY_USER_ID);
|
let user_id_result = req.get_session().get::<i32>(SESSION_KEY_USER_ID);
|
||||||
|
|
||||||
let user_id = match user_id_result {
|
let user_id = match user_id_result {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
_ => return future::ready(Err(ErrorUnauthorized(""))),
|
_ => return future::ready(Err(UnauthorizedError)),
|
||||||
};
|
};
|
||||||
|
|
||||||
match user_id {
|
match user_id {
|
||||||
Some(id) => future::ready(Ok(UserId(id))),
|
Some(id) => future::ready(Ok(UserId(id))),
|
||||||
None => future::ready(Err(ErrorUnauthorized(""))),
|
None => future::ready(Err(UnauthorizedError)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UnauthorizedError;
|
||||||
|
|
||||||
|
impl Display for UnauthorizedError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Unauthorized access")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl actix_web::ResponseError for UnauthorizedError {
|
||||||
|
fn status_code(&self) -> actix_web::http::StatusCode {
|
||||||
|
actix_web::http::StatusCode::UNAUTHORIZED
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error_response(&self) -> actix_web::HttpResponse {
|
||||||
|
actix_web::HttpResponse::Unauthorized().finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::delivery::{auth_controller::AuthController, user_response_dto::UserResponseDto},
|
adapter::delivery::{auth_controller::AuthController, user_response_dto::UserResponseDto},
|
||||||
|
application::error::auth_error::AuthError,
|
||||||
framework::web::auth_middleware::UserId,
|
framework::web::auth_middleware::UserId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,7 +29,10 @@ pub async fn get_logged_in_user_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(user) => HttpResponse::Ok().json(user),
|
Ok(user) => HttpResponse::Ok().json(user),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
AuthError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use actix_session::Session;
|
use actix_session::Session;
|
||||||
use actix_web::{HttpResponse, Responder, http::header, web};
|
use actix_web::{HttpResponse, Responder, http::header, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::delivery::{
|
adapter::delivery::{
|
||||||
@ -48,7 +50,7 @@ pub async fn oidc_callback_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
if let Err(e) = session.insert::<i32>(SESSION_KEY_USER_ID, user.id) {
|
if let Err(e) = session.insert::<i32>(SESSION_KEY_USER_ID, user.id) {
|
||||||
log::error!("{e:?}");
|
capture_anyhow(&e.into());
|
||||||
return HttpResponse::InternalServerError().finish();
|
return HttpResponse::InternalServerError().finish();
|
||||||
}
|
}
|
||||||
HttpResponse::Found()
|
HttpResponse::Found()
|
||||||
@ -61,7 +63,10 @@ pub async fn oidc_callback_handler(
|
|||||||
| AuthError::InvalidNonce
|
| AuthError::InvalidNonce
|
||||||
| AuthError::InvalidState => HttpResponse::BadRequest().finish(),
|
| AuthError::InvalidState => HttpResponse::BadRequest().finish(),
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
AuthError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use actix_session::Session;
|
use actix_session::Session;
|
||||||
use actix_web::{HttpResponse, Responder, http::header, web};
|
use actix_web::{HttpResponse, Responder, http::header, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::delivery::auth_controller::AuthController,
|
adapter::delivery::auth_controller::AuthController,
|
||||||
|
application::error::auth_error::AuthError,
|
||||||
framework::web::constants::{SESSION_KEY_AUTH_NONCE, SESSION_KEY_AUTH_STATE},
|
framework::web::constants::{SESSION_KEY_AUTH_NONCE, SESSION_KEY_AUTH_STATE},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,11 +27,11 @@ pub async fn oidc_login_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(auth_url) => {
|
Ok(auth_url) => {
|
||||||
if let Err(e) = session.insert::<String>(SESSION_KEY_AUTH_STATE, auth_url.state) {
|
if let Err(e) = session.insert::<String>(SESSION_KEY_AUTH_STATE, auth_url.state) {
|
||||||
log::error!("{e:?}");
|
capture_anyhow(&e.into());
|
||||||
return HttpResponse::InternalServerError().finish();
|
return HttpResponse::InternalServerError().finish();
|
||||||
}
|
}
|
||||||
if let Err(e) = session.insert::<String>(SESSION_KEY_AUTH_NONCE, auth_url.nonce) {
|
if let Err(e) = session.insert::<String>(SESSION_KEY_AUTH_NONCE, auth_url.nonce) {
|
||||||
log::error!("{e:?}");
|
capture_anyhow(&e.into());
|
||||||
return HttpResponse::InternalServerError().finish();
|
return HttpResponse::InternalServerError().finish();
|
||||||
}
|
}
|
||||||
HttpResponse::Found()
|
HttpResponse::Found()
|
||||||
@ -36,7 +39,10 @@ pub async fn oidc_login_handler(
|
|||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
AuthError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
backend/feature/common/Cargo.toml
Normal file
7
backend/feature/common/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "common"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sqlx.workspace = true
|
1
backend/feature/common/src/framework.rs
Normal file
1
backend/feature/common/src/framework.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod error;
|
21
backend/feature/common/src/framework/error.rs
Normal file
21
backend/feature/common/src/framework/error.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IOError(pub std::io::Error);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DatabaseError(pub sqlx::Error);
|
||||||
|
|
||||||
|
impl std::error::Error for IOError {}
|
||||||
|
impl Display for IOError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for DatabaseError {}
|
||||||
|
impl Display for DatabaseError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
1
backend/feature/common/src/lib.rs
Normal file
1
backend/feature/common/src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod framework;
|
@ -6,11 +6,13 @@ edition.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
actix-multipart.workspace = true
|
actix-multipart.workspace = true
|
||||||
actix-web.workspace = true
|
actix-web.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
log.workspace = true
|
sentry.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
sqlx.workspace = true
|
sqlx.workspace = true
|
||||||
utoipa.workspace = true
|
utoipa.workspace = true
|
||||||
|
|
||||||
auth.workspace = true
|
auth.workspace = true
|
||||||
|
common.workspace = true
|
||||||
|
@ -57,7 +57,7 @@ impl ImageController for ImageControllerImpl {
|
|||||||
image: ImageRequestDto,
|
image: ImageRequestDto,
|
||||||
) -> Result<ImageInfoResponseDto, ImageError> {
|
) -> Result<ImageInfoResponseDto, ImageError> {
|
||||||
if !self.mime_type_whitelist.contains(&image.mime_type) {
|
if !self.mime_type_whitelist.contains(&image.mime_type) {
|
||||||
return Err(ImageError::UnsupportedMimeType);
|
return Err(ImageError::UnsupportedMimeType(image.mime_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mime_type = image.mime_type.clone();
|
let mime_type = image.mime_type.clone();
|
||||||
|
@ -1,7 +1,18 @@
|
|||||||
#[derive(Debug, PartialEq)]
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ImageError {
|
pub enum ImageError {
|
||||||
DatabaseError(String),
|
|
||||||
StorageError(String),
|
|
||||||
NotFound,
|
NotFound,
|
||||||
UnsupportedMimeType,
|
UnsupportedMimeType(String),
|
||||||
|
Unexpected(anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ImageError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ImageError::NotFound => write!(f, "Image not found"),
|
||||||
|
ImageError::UnsupportedMimeType(mime) => write!(f, "Unsupported MIME type: {}", mime),
|
||||||
|
ImageError::Unexpected(e) => write!(f, "Unexpected error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use common::framework::error::DatabaseError;
|
||||||
use sqlx::{Pool, Postgres};
|
use sqlx::{Pool, Postgres};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -34,7 +35,7 @@ impl ImageDbService for ImageDbServiceImpl {
|
|||||||
|
|
||||||
match id {
|
match id {
|
||||||
Ok(id) => Ok(id),
|
Ok(id) => Ok(id),
|
||||||
Err(e) => Err(ImageError::DatabaseError(e.to_string())),
|
Err(e) => Err(ImageError::Unexpected(DatabaseError(e).into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ impl ImageDbService for ImageDbServiceImpl {
|
|||||||
}),
|
}),
|
||||||
None => Err(ImageError::NotFound),
|
None => Err(ImageError::NotFound),
|
||||||
},
|
},
|
||||||
Err(e) => Err(ImageError::DatabaseError(e.to_string())),
|
Err(e) => Err(ImageError::Unexpected(DatabaseError(e).into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ use std::{
|
|||||||
io::Write,
|
io::Write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use common::framework::error::IOError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::gateway::image_storage::ImageStorage, application::error::image_error::ImageError,
|
adapter::gateway::image_storage::ImageStorage, application::error::image_error::ImageError,
|
||||||
};
|
};
|
||||||
@ -22,20 +24,20 @@ impl ImageStorageImpl {
|
|||||||
impl ImageStorage for ImageStorageImpl {
|
impl ImageStorage for ImageStorageImpl {
|
||||||
fn write_data(&self, id: i32, data: &[u8]) -> Result<(), ImageError> {
|
fn write_data(&self, id: i32, data: &[u8]) -> Result<(), ImageError> {
|
||||||
let dir_path = format!("{}/images", self.sotrage_path);
|
let dir_path = format!("{}/images", self.sotrage_path);
|
||||||
fs::create_dir_all(&dir_path).map_err(|e| ImageError::StorageError(e.to_string()))?;
|
fs::create_dir_all(&dir_path).map_err(|e| ImageError::Unexpected(IOError(e).into()))?;
|
||||||
|
|
||||||
let file_path = format!("{}/{}", dir_path, id);
|
let file_path = format!("{}/{}", dir_path, id);
|
||||||
let mut file =
|
let mut file =
|
||||||
File::create(&file_path).map_err(|e| ImageError::StorageError(e.to_string()))?;
|
File::create(&file_path).map_err(|e| ImageError::Unexpected(IOError(e).into()))?;
|
||||||
file.write_all(data)
|
file.write_all(data)
|
||||||
.map_err(|e| ImageError::StorageError(e.to_string()))?;
|
.map_err(|e| ImageError::Unexpected(e.into()))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_data(&self, id: i32) -> Result<Vec<u8>, ImageError> {
|
fn read_data(&self, id: i32) -> Result<Vec<u8>, ImageError> {
|
||||||
let file_path = format!("{}/images/{}", self.sotrage_path, id);
|
let file_path = format!("{}/images/{}", self.sotrage_path, id);
|
||||||
let data = fs::read(&file_path).map_err(|e| ImageError::StorageError(e.to_string()))?;
|
let data = fs::read(&file_path).map_err(|e| ImageError::Unexpected(IOError(e).into()))?;
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -29,8 +31,12 @@ pub async fn get_image_by_id_handler(
|
|||||||
.body(image_response.data),
|
.body(image_response.data),
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
ImageError::NotFound => HttpResponse::NotFound().finish(),
|
ImageError::NotFound => HttpResponse::NotFound().finish(),
|
||||||
|
ImageError::Unexpected(e) => {
|
||||||
|
capture_anyhow(&e);
|
||||||
|
HttpResponse::InternalServerError().finish()
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("{e:?}");
|
capture_anyhow(&anyhow!(e));
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use actix_multipart::Multipart;
|
use actix_multipart::Multipart;
|
||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
use auth::framework::web::auth_middleware::UserId;
|
use auth::framework::web::auth_middleware::UserId;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -73,9 +75,15 @@ pub async fn upload_image_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(image_info) => HttpResponse::Created().json(image_info),
|
Ok(image_info) => HttpResponse::Created().json(image_info),
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
ImageError::UnsupportedMimeType => HttpResponse::BadRequest().body(format!("{e:?}")),
|
ImageError::UnsupportedMimeType(mime_type) => {
|
||||||
|
HttpResponse::BadRequest().body(format!("Unsupported MIME type: {}", mime_type))
|
||||||
|
}
|
||||||
|
ImageError::Unexpected(e) => {
|
||||||
|
capture_anyhow(&e);
|
||||||
|
HttpResponse::InternalServerError().finish()
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("{e:?}");
|
capture_anyhow(&anyhow!(e));
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,11 +5,13 @@ edition.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web.workspace = true
|
actix-web.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
log.workspace = true
|
sentry.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
sqlx.workspace = true
|
sqlx.workspace = true
|
||||||
utoipa.workspace = true
|
utoipa.workspace = true
|
||||||
|
|
||||||
auth.workspace = true
|
auth.workspace = true
|
||||||
|
common.workspace = true
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
#[derive(Debug, PartialEq)]
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum PostError {
|
pub enum PostError {
|
||||||
DatabaseError(String),
|
|
||||||
NotFound,
|
NotFound,
|
||||||
|
Unexpected(anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for PostError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
PostError::NotFound => write!(f, "Post not found"),
|
||||||
|
PostError::Unexpected(e) => write!(f, "Unexpected error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use common::framework::error::DatabaseError;
|
||||||
use sqlx::{Pool, Postgres};
|
use sqlx::{Pool, Postgres};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -31,7 +32,7 @@ impl LabelDbService for LabelDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_one(&self.db_pool)
|
.fetch_one(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
@ -49,7 +50,7 @@ impl LabelDbService for LabelDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.execute(&self.db_pool)
|
.execute(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?
|
||||||
.rows_affected();
|
.rows_affected();
|
||||||
|
|
||||||
if affected_rows == 0 {
|
if affected_rows == 0 {
|
||||||
@ -71,7 +72,7 @@ impl LabelDbService for LabelDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_optional(&self.db_pool)
|
.fetch_optional(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
match record {
|
match record {
|
||||||
Some(record) => Ok(record.into_mapper()),
|
Some(record) => Ok(record.into_mapper()),
|
||||||
@ -91,7 +92,7 @@ impl LabelDbService for LabelDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_all(&self.db_pool)
|
.fetch_all(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
let mappers = records
|
let mappers = records
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use common::framework::error::DatabaseError;
|
||||||
use sqlx::{Pool, Postgres};
|
use sqlx::{Pool, Postgres};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -64,7 +65,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
.build_query_as::<PostInfoWithLabelRecord>()
|
.build_query_as::<PostInfoWithLabelRecord>()
|
||||||
.fetch_all(&self.db_pool)
|
.fetch_all(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
let mut post_info_mappers_map = HashMap::<i32, PostInfoMapper>::new();
|
let mut post_info_mappers_map = HashMap::<i32, PostInfoMapper>::new();
|
||||||
|
|
||||||
@ -136,7 +137,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
.build_query_as::<PostWithLabelRecord>()
|
.build_query_as::<PostWithLabelRecord>()
|
||||||
.fetch_all(&self.db_pool)
|
.fetch_all(&self.db_pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
if records.is_empty() {
|
if records.is_empty() {
|
||||||
return Err(PostError::NotFound);
|
return Err(PostError::NotFound);
|
||||||
@ -188,7 +189,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
.db_pool
|
.db_pool
|
||||||
.begin()
|
.begin()
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
let post_id = sqlx::query_scalar!(
|
let post_id = sqlx::query_scalar!(
|
||||||
r#"
|
r#"
|
||||||
@ -205,7 +206,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.fetch_one(&mut *tx)
|
.fetch_one(&mut *tx)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
for (order, &label_id) in label_ids.iter().enumerate() {
|
for (order, &label_id) in label_ids.iter().enumerate() {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@ -221,12 +222,12 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.execute(&mut *tx)
|
.execute(&mut *tx)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.commit()
|
tx.commit()
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
Ok(post_id)
|
Ok(post_id)
|
||||||
}
|
}
|
||||||
@ -236,7 +237,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
.db_pool
|
.db_pool
|
||||||
.begin()
|
.begin()
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
let affected_rows = sqlx::query!(
|
let affected_rows = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
@ -258,7 +259,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.execute(&mut *tx)
|
.execute(&mut *tx)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?
|
||||||
.rows_affected();
|
.rows_affected();
|
||||||
|
|
||||||
if affected_rows == 0 {
|
if affected_rows == 0 {
|
||||||
@ -274,7 +275,7 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.execute(&mut *tx)
|
.execute(&mut *tx)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
for (order, &label_id) in label_ids.iter().enumerate() {
|
for (order, &label_id) in label_ids.iter().enumerate() {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@ -290,12 +291,12 @@ impl PostDbService for PostDbServiceImpl {
|
|||||||
)
|
)
|
||||||
.execute(&mut *tx)
|
.execute(&mut *tx)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.commit()
|
tx.commit()
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
use auth::framework::web::auth_middleware::UserId;
|
use auth::framework::web::auth_middleware::UserId;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::adapter::delivery::{
|
use crate::{
|
||||||
create_label_request_dto::CreateLabelRequestDto, label_response_dto::LabelResponseDto,
|
adapter::delivery::{
|
||||||
post_controller::PostController,
|
create_label_request_dto::CreateLabelRequestDto, label_response_dto::LabelResponseDto,
|
||||||
|
post_controller::PostController,
|
||||||
|
},
|
||||||
|
application::error::post_error::PostError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@ -28,7 +33,10 @@ pub async fn create_label_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(label) => HttpResponse::Created().json(label),
|
Ok(label) => HttpResponse::Created().json(label),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
PostError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
use auth::framework::web::auth_middleware::UserId;
|
use auth::framework::web::auth_middleware::UserId;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::adapter::delivery::{
|
use crate::{
|
||||||
create_post_request_dto::CreatePostRequestDto, post_controller::PostController,
|
adapter::delivery::{
|
||||||
post_response_dto::PostResponseDto,
|
create_post_request_dto::CreatePostRequestDto, post_controller::PostController,
|
||||||
|
post_response_dto::PostResponseDto,
|
||||||
|
},
|
||||||
|
application::error::post_error::PostError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@ -28,7 +33,10 @@ pub async fn create_post_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(post) => HttpResponse::Created().json(post),
|
Ok(post) => HttpResponse::Created().json(post),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
PostError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::adapter::delivery::{
|
use crate::{
|
||||||
label_response_dto::LabelResponseDto, post_controller::PostController,
|
adapter::delivery::{label_response_dto::LabelResponseDto, post_controller::PostController},
|
||||||
|
application::error::post_error::PostError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@ -21,7 +24,10 @@ pub async fn get_all_labels_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(labels) => HttpResponse::Ok().json(labels),
|
Ok(labels) => HttpResponse::Ok().json(labels),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
PostError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::adapter::delivery::{
|
use crate::{
|
||||||
post_controller::PostController, post_info_query_dto::PostQueryDto,
|
adapter::delivery::{
|
||||||
post_info_response_dto::PostInfoResponseDto,
|
post_controller::PostController, post_info_query_dto::PostQueryDto,
|
||||||
|
post_info_response_dto::PostInfoResponseDto,
|
||||||
|
},
|
||||||
|
application::error::post_error::PostError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@ -26,7 +31,10 @@ pub async fn get_all_post_info_handler(
|
|||||||
match result {
|
match result {
|
||||||
Ok(post_info_list) => HttpResponse::Ok().json(post_info_list),
|
Ok(post_info_list) => HttpResponse::Ok().json(post_info_list),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{e:?}");
|
match e {
|
||||||
|
PostError::Unexpected(e) => capture_anyhow(&e),
|
||||||
|
_ => capture_anyhow(&anyhow!(e)),
|
||||||
|
};
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::delivery::{post_controller::PostController, post_response_dto::PostResponseDto},
|
adapter::delivery::{post_controller::PostController, post_response_dto::PostResponseDto},
|
||||||
@ -24,13 +25,12 @@ pub async fn get_post_by_id_handler(
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(post) => HttpResponse::Ok().json(post),
|
Ok(post) => HttpResponse::Ok().json(post),
|
||||||
Err(e) => {
|
Err(e) => match e {
|
||||||
if e == PostError::NotFound {
|
PostError::NotFound => HttpResponse::NotFound().finish(),
|
||||||
HttpResponse::NotFound().finish()
|
PostError::Unexpected(e) => {
|
||||||
} else {
|
capture_anyhow(&e);
|
||||||
log::error!("{e:?}");
|
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
use auth::framework::web::auth_middleware::UserId;
|
use auth::framework::web::auth_middleware::UserId;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::delivery::{
|
adapter::delivery::{
|
||||||
@ -37,8 +38,8 @@ pub async fn update_label_handler(
|
|||||||
Ok(label) => HttpResponse::Ok().json(label),
|
Ok(label) => HttpResponse::Ok().json(label),
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
PostError::NotFound => HttpResponse::NotFound().finish(),
|
PostError::NotFound => HttpResponse::NotFound().finish(),
|
||||||
_ => {
|
PostError::Unexpected(e) => {
|
||||||
log::error!("{e:?}");
|
capture_anyhow(&e);
|
||||||
HttpResponse::InternalServerError().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
use actix_web::{HttpResponse, Responder, web};
|
use actix_web::{HttpResponse, Responder, web};
|
||||||
use auth::framework::web::auth_middleware::UserId;
|
use auth::framework::web::auth_middleware::UserId;
|
||||||
|
use sentry::integrations::anyhow::capture_anyhow;
|
||||||
|
|
||||||
use crate::adapter::delivery::{
|
use crate::{
|
||||||
post_controller::PostController, post_response_dto::PostResponseDto,
|
adapter::delivery::{
|
||||||
update_post_request_dto::UpdatePostRequestDto,
|
post_controller::PostController, post_response_dto::PostResponseDto,
|
||||||
|
update_post_request_dto::UpdatePostRequestDto,
|
||||||
|
},
|
||||||
|
application::error::post_error::PostError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@ -30,14 +34,12 @@ pub async fn update_post_handler(
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(post) => HttpResponse::Ok().json(post),
|
Ok(post) => HttpResponse::Ok().json(post),
|
||||||
Err(e) => {
|
Err(e) => match e {
|
||||||
log::error!("{e:?}");
|
PostError::NotFound => HttpResponse::NotFound().finish(),
|
||||||
match e {
|
PostError::Unexpected(e) => {
|
||||||
crate::application::error::post_error::PostError::NotFound => {
|
capture_anyhow(&e);
|
||||||
HttpResponse::NotFound().finish()
|
HttpResponse::InternalServerError().finish()
|
||||||
}
|
|
||||||
_ => HttpResponse::InternalServerError().finish(),
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ env_logger.workspace = true
|
|||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
openidconnect.workspace = true
|
openidconnect.workspace = true
|
||||||
percent-encoding.workspace = true
|
percent-encoding.workspace = true
|
||||||
|
sentry.workspace = true
|
||||||
sqlx.workspace = true
|
sqlx.workspace = true
|
||||||
utoipa.workspace = true
|
utoipa.workspace = true
|
||||||
utoipa-redoc.workspace = true
|
utoipa-redoc.workspace = true
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use openidconnect::reqwest;
|
use openidconnect::reqwest;
|
||||||
|
|
||||||
use crate::configuration::{
|
use crate::configuration::{
|
||||||
db::DbConfiguration, oidc::OidcConfiguration, server::ServerConfiguration,
|
db::DbConfiguration, oidc::OidcConfiguration, sentry::SentryConfiguration,
|
||||||
session::SessionConfiguration, storage::StorageConfiguration,
|
server::ServerConfiguration, session::SessionConfiguration, storage::StorageConfiguration,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod oidc;
|
pub mod oidc;
|
||||||
|
pub mod sentry;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
@ -15,6 +16,7 @@ pub mod storage;
|
|||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub db: DbConfiguration,
|
pub db: DbConfiguration,
|
||||||
pub oidc: OidcConfiguration,
|
pub oidc: OidcConfiguration,
|
||||||
|
pub sentry: SentryConfiguration,
|
||||||
pub server: ServerConfiguration,
|
pub server: ServerConfiguration,
|
||||||
pub session: SessionConfiguration,
|
pub session: SessionConfiguration,
|
||||||
pub storage: StorageConfiguration,
|
pub storage: StorageConfiguration,
|
||||||
@ -25,6 +27,7 @@ impl Configuration {
|
|||||||
Self {
|
Self {
|
||||||
db: DbConfiguration::new(),
|
db: DbConfiguration::new(),
|
||||||
oidc: OidcConfiguration::new(http_client).await,
|
oidc: OidcConfiguration::new(http_client).await,
|
||||||
|
sentry: SentryConfiguration::new(),
|
||||||
server: ServerConfiguration::new(),
|
server: ServerConfiguration::new(),
|
||||||
session: SessionConfiguration::new(),
|
session: SessionConfiguration::new(),
|
||||||
storage: StorageConfiguration::new(),
|
storage: StorageConfiguration::new(),
|
||||||
|
23
backend/server/src/configuration/sentry.rs
Normal file
23
backend/server/src/configuration/sentry.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SentryConfiguration {
|
||||||
|
pub dsn: String,
|
||||||
|
pub options: sentry::ClientOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SentryConfiguration {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let dsn = std::env::var("SENTRY_DSN").unwrap_or("".to_string());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
dsn: dsn,
|
||||||
|
options: sentry::ClientOptions {
|
||||||
|
release: sentry::release_name!(),
|
||||||
|
traces_sample_rate: 1.0,
|
||||||
|
send_default_pii: true,
|
||||||
|
max_request_body_size: sentry::MaxRequestBodySize::Always,
|
||||||
|
attach_stacktrace: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,17 +5,19 @@ use actix_web::{
|
|||||||
App, Error, HttpServer,
|
App, Error, HttpServer,
|
||||||
body::MessageBody,
|
body::MessageBody,
|
||||||
dev::{ServiceFactory, ServiceRequest, ServiceResponse},
|
dev::{ServiceFactory, ServiceRequest, ServiceResponse},
|
||||||
|
rt::Runtime,
|
||||||
web,
|
web,
|
||||||
};
|
};
|
||||||
use auth::framework::web::auth_web_routes::configure_auth_routes;
|
use auth::framework::web::auth_web_routes::configure_auth_routes;
|
||||||
use image::framework::web::image_web_routes::configure_image_routes;
|
use image::framework::web::image_web_routes::configure_image_routes;
|
||||||
use openidconnect::reqwest;
|
use openidconnect::reqwest;
|
||||||
use post::framework::web::post_web_routes::configure_post_routes;
|
use post::framework::web::post_web_routes::configure_post_routes;
|
||||||
use server::{api_doc::configure_api_doc_routes, configuration::Configuration, container::Container};
|
use server::{
|
||||||
|
api_doc::configure_api_doc_routes, configuration::Configuration, container::Container,
|
||||||
|
};
|
||||||
use sqlx::{Pool, Postgres};
|
use sqlx::{Pool, Postgres};
|
||||||
|
|
||||||
#[actix_web::main]
|
fn main() -> std::io::Result<()> {
|
||||||
async fn main() -> std::io::Result<()> {
|
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
@ -24,31 +26,45 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.build()
|
.build()
|
||||||
.expect("Failed to create HTTP client");
|
.expect("Failed to create HTTP client");
|
||||||
|
|
||||||
let configuration = Configuration::new(http_client.clone()).await;
|
let rt = Runtime::new().unwrap();
|
||||||
|
let configuration = rt.block_on(async { Configuration::new(http_client.clone()).await });
|
||||||
|
|
||||||
let host = configuration.server.host.clone();
|
let _guard = sentry::init((
|
||||||
let port = configuration.server.port;
|
configuration.sentry.dsn.clone(),
|
||||||
|
configuration.sentry.options.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
let db_pool = configuration.db.create_connection().await;
|
actix_web::rt::System::new().block_on(async {
|
||||||
let session_key = configuration.session.session_key.clone();
|
let host = configuration.server.host.clone();
|
||||||
let session_store = configuration.session.create_session_store().await;
|
let port = configuration.server.port;
|
||||||
|
|
||||||
HttpServer::new(move || {
|
let db_pool = configuration.db.create_connection().await;
|
||||||
create_app(
|
let session_key = configuration.session.session_key.clone();
|
||||||
db_pool.clone(),
|
let session_store = configuration.session.create_session_store().await;
|
||||||
http_client.clone(),
|
|
||||||
SessionMiddleware::builder(session_store.clone(), session_key.clone()),
|
HttpServer::new(move || {
|
||||||
configuration.clone(),
|
create_app(
|
||||||
)
|
db_pool.clone(),
|
||||||
})
|
http_client.clone(),
|
||||||
.bind((host, port))?
|
sentry::integrations::actix::Sentry::builder()
|
||||||
.run()
|
.capture_server_errors(true)
|
||||||
.await
|
.start_transaction(true),
|
||||||
|
SessionMiddleware::builder(session_store.clone(), session_key.clone()),
|
||||||
|
configuration.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.bind((host, port))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_app(
|
fn create_app(
|
||||||
db_pool: Pool<Postgres>,
|
db_pool: Pool<Postgres>,
|
||||||
http_client: reqwest::Client,
|
http_client: reqwest::Client,
|
||||||
|
sentry_builder: sentry::integrations::actix::SentryBuilder,
|
||||||
session_middleware_builder: SessionMiddlewareBuilder<RedisSessionStore>,
|
session_middleware_builder: SessionMiddlewareBuilder<RedisSessionStore>,
|
||||||
configuration: Configuration,
|
configuration: Configuration,
|
||||||
) -> App<
|
) -> App<
|
||||||
@ -64,6 +80,7 @@ fn create_app(
|
|||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
// The middlewares are executed in opposite order as registration.
|
// The middlewares are executed in opposite order as registration.
|
||||||
|
.wrap(sentry_builder.finish())
|
||||||
.wrap(session_middleware_builder.build())
|
.wrap(session_middleware_builder.build())
|
||||||
.app_data(web::Data::from(container.auth_controller))
|
.app_data(web::Data::from(container.auth_controller))
|
||||||
.app_data(web::Data::from(container.image_controller))
|
.app_data(web::Data::from(container.image_controller))
|
||||||
|
3
frontend/.gitignore
vendored
3
frontend/.gitignore
vendored
@ -21,3 +21,6 @@ Thumbs.db
|
|||||||
# Vite
|
# Vite
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
|
||||||
|
# Sentry Config File
|
||||||
|
.env.sentry-build-plugin
|
||||||
|
@ -23,6 +23,8 @@ EXPOSE 3000
|
|||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV HOSTNAME=0.0.0.0
|
ENV HOSTNAME=0.0.0.0
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
|
ENV SENTRY_AUTH_TOKEN=
|
||||||
|
ENV PUBLIC_SENTRY_DSN=
|
||||||
ENV PUBLIC_API_BASE_URL=http://127.0.0.1:8080/
|
ENV PUBLIC_API_BASE_URL=http://127.0.0.1:8080/
|
||||||
ENV PUBLIC_GA_MEASUREMENT_ID=
|
ENV PUBLIC_GA_MEASUREMENT_ID=
|
||||||
CMD ["node", "build"]
|
CMD ["node", "build"]
|
||||||
|
@ -47,5 +47,8 @@
|
|||||||
"esbuild"
|
"esbuild"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.12.4"
|
"packageManager": "pnpm@10.12.4",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/sveltekit": "^10.1.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
1550
frontend/pnpm-lock.yaml
generated
1550
frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
26
frontend/src/hooks.client.ts
Normal file
26
frontend/src/hooks.client.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Environment } from '$lib/environment';
|
||||||
|
import { handleErrorWithSentry, replayIntegration } from '@sentry/sveltekit';
|
||||||
|
import * as Sentry from '@sentry/sveltekit';
|
||||||
|
|
||||||
|
Sentry.init({
|
||||||
|
dsn: Environment.SENTRY_DSN,
|
||||||
|
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
|
||||||
|
// Enable logs to be sent to Sentry
|
||||||
|
enableLogs: true,
|
||||||
|
|
||||||
|
// This sets the sample rate to be 10%. You may want this to be 100% while
|
||||||
|
// in development and sample at a lower rate in production
|
||||||
|
replaysSessionSampleRate: 0.1,
|
||||||
|
|
||||||
|
// If the entire session is not sampled, use the below sample rate to sample
|
||||||
|
// sessions when an error occurs.
|
||||||
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
|
||||||
|
// If you don't want to use Session Replay, just remove the line below:
|
||||||
|
integrations: [replayIntegration()]
|
||||||
|
});
|
||||||
|
|
||||||
|
// If you have a custom error handler, pass it to `handleErrorWithSentry`
|
||||||
|
export const handleError = handleErrorWithSentry();
|
@ -1,3 +1,5 @@
|
|||||||
|
import { sequence } from '@sveltejs/kit/hooks';
|
||||||
|
import * as Sentry from '@sentry/sveltekit';
|
||||||
import { PostRepositoryImpl } from '$lib/post/adapter/gateway/postRepositoryImpl';
|
import { PostRepositoryImpl } from '$lib/post/adapter/gateway/postRepositoryImpl';
|
||||||
import { PostBloc } from '$lib/post/adapter/presenter/postBloc';
|
import { PostBloc } from '$lib/post/adapter/presenter/postBloc';
|
||||||
import { PostListBloc } from '$lib/post/adapter/presenter/postListBloc';
|
import { PostListBloc } from '$lib/post/adapter/presenter/postListBloc';
|
||||||
@ -5,8 +7,15 @@ import { GetAllPostsUseCase } from '$lib/post/application/useCase/getAllPostsUse
|
|||||||
import { GetPostUseCase } from '$lib/post/application/useCase/getPostUseCase';
|
import { GetPostUseCase } from '$lib/post/application/useCase/getPostUseCase';
|
||||||
import { PostApiServiceImpl } from '$lib/post/framework/api/postApiServiceImpl';
|
import { PostApiServiceImpl } from '$lib/post/framework/api/postApiServiceImpl';
|
||||||
import type { Handle } from '@sveltejs/kit';
|
import type { Handle } from '@sveltejs/kit';
|
||||||
|
import { Environment } from '$lib/environment';
|
||||||
|
|
||||||
export const handle: Handle = ({ event, resolve }) => {
|
Sentry.init({
|
||||||
|
dsn: Environment.SENTRY_DSN,
|
||||||
|
tracesSampleRate: 1,
|
||||||
|
enableLogs: true
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handle: Handle = sequence(Sentry.sentryHandle(), ({ event, resolve }) => {
|
||||||
const postApiService = new PostApiServiceImpl(event.fetch);
|
const postApiService = new PostApiServiceImpl(event.fetch);
|
||||||
const postRepository = new PostRepositoryImpl(postApiService);
|
const postRepository = new PostRepositoryImpl(postApiService);
|
||||||
const getAllPostsUseCase = new GetAllPostsUseCase(postRepository);
|
const getAllPostsUseCase = new GetAllPostsUseCase(postRepository);
|
||||||
@ -16,4 +25,6 @@ export const handle: Handle = ({ event, resolve }) => {
|
|||||||
event.locals.postBloc = new PostBloc(getPostUseCase);
|
event.locals.postBloc = new PostBloc(getPostUseCase);
|
||||||
|
|
||||||
return resolve(event);
|
return resolve(event);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
export const handleError = Sentry.handleErrorWithSentry();
|
||||||
|
@ -3,4 +3,5 @@ import { env } from '$env/dynamic/public';
|
|||||||
export abstract class Environment {
|
export abstract class Environment {
|
||||||
static readonly API_BASE_URL = env.PUBLIC_API_BASE_URL ?? 'http://localhost:5173/api/';
|
static readonly API_BASE_URL = env.PUBLIC_API_BASE_URL ?? 'http://localhost:5173/api/';
|
||||||
static readonly GA_MEASUREMENT_ID = env.PUBLIC_GA_MEASUREMENT_ID ?? '';
|
static readonly GA_MEASUREMENT_ID = env.PUBLIC_GA_MEASUREMENT_ID ?? '';
|
||||||
|
static readonly SENTRY_DSN = env.PUBLIC_SENTRY_DSN ?? '';
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { sentrySvelteKit } from '@sentry/sveltekit';
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
@ -5,7 +6,16 @@ import { defineConfig } from 'vite';
|
|||||||
import { version } from './package.json';
|
import { version } from './package.json';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [tailwindcss(), sveltekit()],
|
plugins: [
|
||||||
|
sentrySvelteKit({
|
||||||
|
sourceMapsUploadOptions: {
|
||||||
|
org: 'squidspirit',
|
||||||
|
project: 'blog-beta-frontend'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
tailwindcss(),
|
||||||
|
sveltekit()
|
||||||
|
],
|
||||||
define: {
|
define: {
|
||||||
'App.__VERSION__': JSON.stringify(version)
|
'App.__VERSION__': JSON.stringify(version)
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user