添加用户auth相关功能
build / build-rust (push) Failing after 1m40s
Details
build / build-rust (push) Failing after 1m40s
Details
调整草稿和发布数据接口(需要user_id的从context中获取用户信息)
This commit is contained in:
parent
c1a4a3701e
commit
a0967e7583
|
@ -18,6 +18,7 @@
|
|||
"protoc",
|
||||
"protos",
|
||||
"repr",
|
||||
"reqwest",
|
||||
"rtss",
|
||||
"sqlx",
|
||||
"sysinfo",
|
||||
|
|
|
@ -288,6 +288,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
|
@ -776,6 +782,16 @@ dependencies = [
|
|||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
|
@ -1072,6 +1088,21 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[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]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
|
@ -1213,6 +1244,25 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "handlebars"
|
||||
version = "5.1.2"
|
||||
|
@ -1377,6 +1427,7 @@ dependencies = [
|
|||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
|
@ -1385,6 +1436,40 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
|
@ -1394,12 +1479,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1452,6 +1542,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
|
@ -1649,6 +1745,23 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
|
@ -1746,6 +1859,50 @@ version = "1.19.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"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.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.6.0"
|
||||
|
@ -2143,6 +2300,64 @@ version = "0.8.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.1",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.8.1"
|
||||
|
@ -2187,6 +2402,7 @@ dependencies = [
|
|||
"base64 0.22.1",
|
||||
"bevy_ecs",
|
||||
"chrono",
|
||||
"reqwest",
|
||||
"rtss_db",
|
||||
"rtss_dto",
|
||||
"rtss_log",
|
||||
|
@ -2318,6 +2534,46 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
|
@ -2330,12 +2586,44 @@ version = "1.0.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
|
@ -2787,6 +3075,9 @@ name = "sync_wrapper"
|
|||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
|
@ -2802,6 +3093,27 @@ dependencies = [
|
|||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.12.0"
|
||||
|
@ -2896,6 +3208,27 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.15"
|
||||
|
@ -3093,6 +3426,12 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.21.0"
|
||||
|
@ -3169,6 +3508,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.2"
|
||||
|
@ -3219,6 +3564,15 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -3376,7 +3730,7 @@ checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
|||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-result 0.1.2",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
|
@ -3402,6 +3756,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
||||
dependencies = [
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
|
@ -3411,6 +3776,25 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result 0.2.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
|
|
@ -5,3 +5,9 @@ port = 8765
|
|||
|
||||
[log]
|
||||
level = "debug"
|
||||
|
||||
[sso]
|
||||
base_url = "http://localhost:8080"
|
||||
login_url = "/api/login"
|
||||
logout_url = "/api/login/logout"
|
||||
user_info_url = "/api/login/getUserInfo"
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
[database]
|
||||
url = "postgresql://joylink:Joylink@0503@localhost:5432/joylink"
|
||||
|
||||
[sso]
|
||||
base_url = "https://joylink.club/jlcloud"
|
||||
|
|
|
@ -2,4 +2,7 @@
|
|||
url = "postgresql://joylink:Joylink@0503@10.11.11.2:5432/joylink"
|
||||
|
||||
[log]
|
||||
level = "info"
|
||||
level = "debug"
|
||||
|
||||
[sso]
|
||||
base_url = "http://192.168.33.233/rtss-server"
|
||||
|
|
|
@ -17,6 +17,7 @@ async-graphql = { version = "7.0.7", features = ["chrono", "dataloader"] }
|
|||
async-graphql-axum = "7.0.6"
|
||||
base64 = "0.22.1"
|
||||
sysinfo = "0.31.3"
|
||||
reqwest = { version = "0.12.7", features = ["json"] }
|
||||
|
||||
bevy_ecs = { workspace = true }
|
||||
rtss_log = { path = "../rtss_log" }
|
||||
|
|
|
@ -8,11 +8,13 @@ use rtss_db::RtssDbAccessor;
|
|||
use rtss_dto::common::DataType;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::apis::PageQueryDto;
|
||||
use crate::apis::{PageDto, PageQueryDto};
|
||||
|
||||
use super::common::{DataOptions, IscsDataOptions};
|
||||
use super::release_data::ReleaseDataId;
|
||||
use super::{PageDto, RtssDbLoader};
|
||||
use crate::RtssDbLoader;
|
||||
|
||||
use crate::user_auth::{Role, RoleGuard, UserInfoDto};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DraftDataQuery;
|
||||
|
@ -23,6 +25,7 @@ pub struct DraftDataMutation;
|
|||
#[Object]
|
||||
impl DraftDataQuery {
|
||||
/// 分页查询所有草稿数据(系统管理用)
|
||||
#[graphql(guard = "RoleGuard::new(Role::Admin)")]
|
||||
async fn draft_data_paging<'ctx>(
|
||||
&self,
|
||||
ctx: &Context<'ctx>,
|
||||
|
@ -36,20 +39,24 @@ impl DraftDataQuery {
|
|||
Ok(paging_result.into())
|
||||
}
|
||||
/// 分页查询用户的草稿ISCS数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn user_draft_iscs_data_paging<'ctx>(
|
||||
&self,
|
||||
ctx: &Context<'ctx>,
|
||||
paging: PageQueryDto,
|
||||
mut query: UserDraftDataFilterDto<IscsDataOptions>,
|
||||
) -> async_graphql::Result<PageDto<DraftIscsDataDto>> {
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
query.user_id = user.id_i32();
|
||||
query.data_type = Some(DataType::Iscs);
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let paging_result = db_accessor
|
||||
.query_draft_data(query.into(), paging.into())
|
||||
.await?;
|
||||
Ok(paging_result.into())
|
||||
}
|
||||
/// 分页查询共享的草稿ISCS数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn shared_draft_iscs_data_paging<'ctx>(
|
||||
&self,
|
||||
ctx: &Context<'ctx>,
|
||||
|
@ -64,18 +71,21 @@ impl DraftDataQuery {
|
|||
Ok(paging_result.into())
|
||||
}
|
||||
/// 根据id获取草稿数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn draft_data(&self, ctx: &Context<'_>, id: i32) -> async_graphql::Result<DraftDataDto> {
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let draft_data = db_accessor.query_draft_data_by_id(id).await?;
|
||||
Ok(draft_data.into())
|
||||
}
|
||||
/// 查询是否已经存在同一用户下的同名草稿数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn draft_data_exist(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
user_id: i32,
|
||||
name: String,
|
||||
) -> async_graphql::Result<bool> {
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
let user_id = user.id_i32();
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let exist = db_accessor.is_draft_data_exist(user_id, &name).await?;
|
||||
Ok(exist)
|
||||
|
@ -85,16 +95,20 @@ impl DraftDataQuery {
|
|||
#[Object]
|
||||
impl DraftDataMutation {
|
||||
/// 创建草稿ISCS数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn create_draft_iscs_data(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
input: CreateDraftDataDto<IscsDataOptions>,
|
||||
mut input: CreateDraftDataDto<IscsDataOptions>,
|
||||
) -> async_graphql::Result<DraftIscsDataDto> {
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
input = input.with_user_id(user.id_i32());
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let draft_data = db_accessor.create_draft_data(input.into()).await?;
|
||||
Ok(draft_data.into())
|
||||
}
|
||||
/// 更新草稿数据name
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn update_draft_data_name(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -107,6 +121,7 @@ impl DraftDataMutation {
|
|||
}
|
||||
/// 更新草稿数据data
|
||||
/// data为base64编码的字符串
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn update_draft_data_data(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -121,6 +136,7 @@ impl DraftDataMutation {
|
|||
Ok(draft_data.into())
|
||||
}
|
||||
/// 更新草稿数据共享状态
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn update_draft_data_shared(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -132,6 +148,7 @@ impl DraftDataMutation {
|
|||
Ok(draft_data.into())
|
||||
}
|
||||
/// 删除草稿数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn delete_draft_data(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -142,6 +159,7 @@ impl DraftDataMutation {
|
|||
Ok(true)
|
||||
}
|
||||
/// 设置草稿数据的默认发布数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn set_default_release_data_id(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -155,13 +173,15 @@ impl DraftDataMutation {
|
|||
Ok(draft_data.into())
|
||||
}
|
||||
/// 草稿数据另存为
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn save_as_new_draft_data(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
id: i32,
|
||||
name: String,
|
||||
user_id: i32,
|
||||
) -> async_graphql::Result<DraftDataDto> {
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
let user_id = user.id_i32();
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let draft_data = db_accessor.save_as_new_draft(id, &name, user_id).await?;
|
||||
Ok(draft_data.into())
|
||||
|
@ -173,12 +193,24 @@ impl DraftDataMutation {
|
|||
pub struct CreateDraftDataDto<T: DataOptions> {
|
||||
pub name: String,
|
||||
pub options: Option<T>,
|
||||
pub user_id: i32,
|
||||
#[graphql(skip)]
|
||||
pub user_id: Option<i32>,
|
||||
}
|
||||
|
||||
impl<T: DataOptions> CreateDraftDataDto<T> {
|
||||
pub fn with_user_id(mut self, id: i32) -> Self {
|
||||
self.user_id = Some(id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DataOptions> From<CreateDraftDataDto<T>> for rtss_db::CreateDraftData {
|
||||
fn from(value: CreateDraftDataDto<T>) -> Self {
|
||||
let cdd = Self::new(&value.name, DataType::Iscs, value.user_id);
|
||||
let cdd = Self::new(
|
||||
&value.name,
|
||||
DataType::Iscs,
|
||||
value.user_id.expect("CreateDraftDataDto need user_id"),
|
||||
);
|
||||
if value.options.is_some() {
|
||||
cdd.with_options(serde_json::to_value(value.options).unwrap())
|
||||
} else {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use async_graphql::dataloader::DataLoader;
|
||||
use async_graphql::{EmptySubscription, MergedObject, Schema};
|
||||
use async_graphql::{Enum, InputObject, OutputType, SimpleObject};
|
||||
use async_graphql::{Enum, InputObject, MergedObject, OutputType, SimpleObject};
|
||||
use draft_data::{DraftDataMutation, DraftDataQuery};
|
||||
use release_data::{ReleaseDataMutation, ReleaseDataQuery};
|
||||
|
||||
use crate::simulation_definition::MutexSimulationManager;
|
||||
use crate::ServerConfig;
|
||||
mod simulation_definition;
|
||||
mod sys_info;
|
||||
use simulation_definition::*;
|
||||
|
||||
mod common;
|
||||
mod draft_data;
|
||||
|
@ -74,25 +73,3 @@ impl<T: OutputType, M: Into<T>> From<rtss_db::common::PageResult<M>> for PageDto
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RtssDbLoader {
|
||||
pub(crate) db_accessor: rtss_db::RtssDbAccessor,
|
||||
}
|
||||
|
||||
impl RtssDbLoader {
|
||||
pub fn new(db_accessor: rtss_db::RtssDbAccessor) -> Self {
|
||||
Self { db_accessor }
|
||||
}
|
||||
}
|
||||
|
||||
pub type RtssAppSchema = Schema<Query, Mutation, EmptySubscription>;
|
||||
|
||||
pub async fn new_schema(config: &ServerConfig) -> RtssAppSchema {
|
||||
let dba = rtss_db::get_db_accessor(&config.database_url).await;
|
||||
let loader = RtssDbLoader::new(dba.clone());
|
||||
Schema::build(Query::default(), Mutation::default(), EmptySubscription)
|
||||
.data(dba)
|
||||
.data(DataLoader::new(loader, tokio::spawn))
|
||||
.data(MutexSimulationManager::default())
|
||||
.finish()
|
||||
}
|
||||
|
|
|
@ -12,9 +12,12 @@ use rtss_dto::common::DataType;
|
|||
use serde_json::Value;
|
||||
|
||||
use crate::apis::draft_data::DraftDataDto;
|
||||
use crate::RtssDbLoader;
|
||||
|
||||
use super::common::{DataOptions, IscsDataOptions};
|
||||
use super::{PageDto, PageQueryDto, RtssDbLoader};
|
||||
use super::{PageDto, PageQueryDto};
|
||||
|
||||
use crate::user_auth::{Role, RoleGuard, UserInfoDto};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ReleaseDataQuery;
|
||||
|
@ -25,6 +28,7 @@ pub struct ReleaseDataMutation;
|
|||
#[Object]
|
||||
impl ReleaseDataQuery {
|
||||
/// 分页查询所有发布数据(系统管理用)
|
||||
#[graphql(guard = "RoleGuard::new(Role::Admin)")]
|
||||
async fn release_data_paging(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -39,6 +43,7 @@ impl ReleaseDataQuery {
|
|||
}
|
||||
|
||||
/// 分页查询发布的ISCS数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn release_iscs_data_paging(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -54,6 +59,7 @@ impl ReleaseDataQuery {
|
|||
}
|
||||
|
||||
/// id查询发布数据及当前使用的版本数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn release_data(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -65,6 +71,7 @@ impl ReleaseDataQuery {
|
|||
}
|
||||
|
||||
/// 是否已经存在相同name的发布数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn is_release_data_name_exists(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -79,6 +86,7 @@ impl ReleaseDataQuery {
|
|||
}
|
||||
|
||||
/// 查询发布数据的版本
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn release_data_version_paging(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -93,6 +101,7 @@ impl ReleaseDataQuery {
|
|||
}
|
||||
|
||||
/// 根据id获取发布数据版本详情
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn release_data_version(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -109,6 +118,7 @@ impl ReleaseDataQuery {
|
|||
#[Object]
|
||||
impl ReleaseDataMutation {
|
||||
/// 发布到新的发布数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn release_new_from_draft(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -116,28 +126,34 @@ impl ReleaseDataMutation {
|
|||
name: String,
|
||||
description: String,
|
||||
) -> async_graphql::Result<ReleaseDataWithUsedVersionDto> {
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
let user_id = user.id_i32();
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let result = db_accessor
|
||||
.release_new_from_draft(draft_id, &name, &description)
|
||||
.release_new_from_draft(draft_id, &name, &description, Some(user_id))
|
||||
.await?;
|
||||
Ok(result.into())
|
||||
}
|
||||
|
||||
/// 发布到默认发布数据,需要草稿数据发布过或设置了默认发布数据id
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn release_to_default_release_data(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
draft_id: i32,
|
||||
description: String,
|
||||
) -> async_graphql::Result<ReleaseDataWithUsedVersionDto> {
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
let user_id = user.id_i32();
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let result = db_accessor
|
||||
.release_to_existing(draft_id, &description)
|
||||
.release_to_existing(draft_id, &description, Some(user_id))
|
||||
.await?;
|
||||
Ok(result.into())
|
||||
}
|
||||
|
||||
/// 更新发布数据name
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn update_release_data_name(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -150,6 +166,7 @@ impl ReleaseDataMutation {
|
|||
}
|
||||
|
||||
/// 上下架发布数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn update_release_data_published(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -164,6 +181,7 @@ impl ReleaseDataMutation {
|
|||
}
|
||||
|
||||
/// 更新发布数据使用的版本
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn update_release_data_used_version(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -178,12 +196,14 @@ impl ReleaseDataMutation {
|
|||
}
|
||||
|
||||
/// 从发布数据版本中创建草稿数据
|
||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||
async fn create_draft_data_from_release_data_version(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
version_id: i32,
|
||||
user_id: i32,
|
||||
) -> async_graphql::Result<DraftDataDto> {
|
||||
let user = ctx.data::<UserInfoDto>()?;
|
||||
let user_id = user.id_i32();
|
||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||
let result = db_accessor
|
||||
.create_draft_from_release_version(version_id, user_id)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use async_graphql::{Context, InputObject, Object};
|
||||
use rtss_sim_manage::{AvailablePlugins, SimulationBuilder};
|
||||
|
||||
use crate::simulation_definition::{MutexSimulationManager, SimulationOperation};
|
||||
use super::{MutexSimulationManager, SimulationOperation};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SimulationQuery;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// mod jwt_auth;
|
||||
mod apis;
|
||||
mod server;
|
||||
mod simulation_definition;
|
||||
mod sys_info;
|
||||
mod user_auth;
|
||||
|
||||
pub use server::*;
|
||||
|
|
|
@ -8,16 +8,22 @@ use axum::{
|
|||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use dataloader::DataLoader;
|
||||
use http::{playground_source, GraphQLPlaygroundConfig};
|
||||
use rtss_log::tracing::{debug, info};
|
||||
use tokio::net::TcpListener;
|
||||
use tower_http::cors::CorsLayer;
|
||||
|
||||
use crate::apis::RtssAppSchema;
|
||||
use crate::apis::{Mutation, Query};
|
||||
use crate::user_auth;
|
||||
|
||||
pub use crate::user_auth::UserAuthClient;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ServerConfig {
|
||||
pub database_url: String,
|
||||
pub port: u16,
|
||||
pub user_auth_client: Option<user_auth::UserAuthClient>,
|
||||
}
|
||||
|
||||
impl ServerConfig {
|
||||
|
@ -25,16 +31,22 @@ impl ServerConfig {
|
|||
Self {
|
||||
database_url: database_url.to_string(),
|
||||
port,
|
||||
user_auth_client: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_user_auth_client(mut self, user_auth_client: user_auth::UserAuthClient) -> Self {
|
||||
self.user_auth_client = Some(user_auth_client);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_socket_addr(&self) -> String {
|
||||
format!("0.0.0.0:{}", self.port)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn serve(config: ServerConfig) -> anyhow::Result<()> {
|
||||
let schema = crate::apis::new_schema(&config).await;
|
||||
let schema = new_schema(config.clone()).await;
|
||||
|
||||
let app = Router::new()
|
||||
.route("/", get(graphiql).post(graphql_handler))
|
||||
|
@ -58,23 +70,45 @@ pub async fn serve(config: ServerConfig) -> anyhow::Result<()> {
|
|||
|
||||
async fn graphql_handler(
|
||||
State(schema): State<RtssAppSchema>,
|
||||
_headers: HeaderMap,
|
||||
headers: HeaderMap,
|
||||
req: GraphQLRequest,
|
||||
) -> GraphQLResponse {
|
||||
let req = req.into_inner();
|
||||
// let mut req = req.into_inner();
|
||||
// let token = jwt_auth::get_token_from_headers(headers);
|
||||
// match token {
|
||||
// Ok(token) => {
|
||||
// req = req.data(token);
|
||||
// }
|
||||
// Err(e) => {
|
||||
// error!("Error getting token from headers: {:?}", e);
|
||||
// }
|
||||
// }
|
||||
let mut req = req.into_inner();
|
||||
let token = user_auth::get_token_from_headers(&headers);
|
||||
if let Some(token) = token {
|
||||
req = req.data(token);
|
||||
}
|
||||
schema.execute(req).await.into()
|
||||
}
|
||||
|
||||
async fn graphiql() -> impl IntoResponse {
|
||||
Html(playground_source(GraphQLPlaygroundConfig::new("/")))
|
||||
}
|
||||
|
||||
pub struct RtssDbLoader {
|
||||
pub(crate) db_accessor: rtss_db::RtssDbAccessor,
|
||||
}
|
||||
|
||||
impl RtssDbLoader {
|
||||
pub fn new(db_accessor: rtss_db::RtssDbAccessor) -> Self {
|
||||
Self { db_accessor }
|
||||
}
|
||||
}
|
||||
|
||||
pub type RtssAppSchema = Schema<Query, Mutation, EmptySubscription>;
|
||||
|
||||
pub async fn new_schema(config: ServerConfig) -> RtssAppSchema {
|
||||
let user_info_cache = crate::user_auth::UserAuthCache::new(
|
||||
config
|
||||
.user_auth_client
|
||||
.expect("user auth client not configured"),
|
||||
);
|
||||
let dba = rtss_db::get_db_accessor(&config.database_url).await;
|
||||
let loader = RtssDbLoader::new(dba.clone());
|
||||
Schema::build(Query::default(), Mutation::default(), EmptySubscription)
|
||||
.data(user_info_cache)
|
||||
.data(dba)
|
||||
.data(DataLoader::new(loader, tokio::spawn))
|
||||
// .data(MutexSimulationManager::default())
|
||||
.finish()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use async_graphql::Guard;
|
||||
use axum::http::HeaderMap;
|
||||
use rtss_log::tracing::error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Copy)]
|
||||
pub enum Role {
|
||||
Admin,
|
||||
User,
|
||||
}
|
||||
|
||||
pub struct RoleGuard {
|
||||
role: Role,
|
||||
}
|
||||
|
||||
impl RoleGuard {
|
||||
pub fn new(role: Role) -> Self {
|
||||
Self { role }
|
||||
}
|
||||
}
|
||||
|
||||
impl Guard for RoleGuard {
|
||||
async fn check(&self, ctx: &async_graphql::Context<'_>) -> async_graphql::Result<()> {
|
||||
if let Some(token) = ctx.data_opt::<Token>() {
|
||||
// 从ctx中获取UserAuthCache, 从cache中获取用户信息
|
||||
let user_auth_cache = ctx.data::<UserAuthCache>().unwrap();
|
||||
let user_info = user_auth_cache.query_user(&token.0).await?;
|
||||
// 判断用户角色
|
||||
if user_info.roles().contains(&self.role) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Err(async_graphql::Error::new("Unauthorized"))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UserAuthCache {
|
||||
// TODO: 使用 LRU 等缓存策略,而不是简单的 HashMap
|
||||
cache: Arc<Mutex<HashMap<String, UserInfoDto>>>,
|
||||
client: UserAuthClient,
|
||||
}
|
||||
|
||||
impl UserAuthCache {
|
||||
pub fn new(user_auth_client: UserAuthClient) -> Self {
|
||||
Self {
|
||||
cache: Arc::new(Mutex::new(HashMap::with_capacity(100))),
|
||||
client: user_auth_client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Token(pub String);
|
||||
|
||||
pub fn get_token_from_headers(headers: &HeaderMap) -> Option<Token> {
|
||||
headers
|
||||
.get("Token")
|
||||
.and_then(|token| token.to_str().map(|s| Token(s.to_string())).ok())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UserAuthClient {
|
||||
pub base_url: String,
|
||||
pub login_url: String,
|
||||
pub logout_url: String,
|
||||
pub user_info_url: String,
|
||||
}
|
||||
|
||||
impl UserAuthClient {
|
||||
#[allow(dead_code)]
|
||||
async fn login(&self, login_info: LoginInfo) -> anyhow::Result<String> {
|
||||
let url = format!("{}{}", self.base_url, self.login_url);
|
||||
let response = reqwest::Client::new()
|
||||
.post(&url)
|
||||
.json(&login_info)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let common = response.json::<CommonResponseDto>().await?;
|
||||
|
||||
if common.code != 200 {
|
||||
// 记录详细日志
|
||||
error!("Login failed with code {}: {}", common.code, common.message);
|
||||
return Err(anyhow::anyhow!(common.message));
|
||||
}
|
||||
|
||||
// 安全地处理 Option 类型
|
||||
match common.data {
|
||||
Some(data) => {
|
||||
if let Some(token_str) = data.as_str() {
|
||||
Ok(token_str.to_string())
|
||||
} else {
|
||||
// 记录详细日志
|
||||
error!("Data is not a string");
|
||||
Err(anyhow::anyhow!("Data is not a string"))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// 记录详细日志
|
||||
error!("No data returned");
|
||||
Err(anyhow::anyhow!("No data returned"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn query_user_info(&self, token: &str) -> anyhow::Result<UserInfoDto> {
|
||||
let url = format!("{}{}?token={token}", self.base_url, self.user_info_url);
|
||||
let response = reqwest::get(url).await?;
|
||||
let common = response.json::<CommonResponseDto>().await?;
|
||||
if common.code != 200 {
|
||||
return Err(anyhow::anyhow!(common.message));
|
||||
}
|
||||
let user_info = serde_json::from_value(common.data.unwrap())?;
|
||||
Ok(user_info)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LoginInfo {
|
||||
pub account: String,
|
||||
pub password: String,
|
||||
#[serde(rename = "clientId")]
|
||||
pub client_id: String,
|
||||
pub secret: String,
|
||||
pub project: String,
|
||||
}
|
||||
|
||||
impl Default for LoginInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
account: "17791995809".to_string(),
|
||||
password: "e10adc3949ba59abbe56e057f20f883e".to_string(),
|
||||
client_id: "1".to_string(),
|
||||
secret: "joylink".to_string(),
|
||||
project: "DEFAULT".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CommonResponseDto {
|
||||
pub code: i32,
|
||||
pub message: String,
|
||||
pub data: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct UserInfoDto {
|
||||
pub id: String,
|
||||
pub name: Option<String>,
|
||||
pub nickname: Option<String>,
|
||||
pub roles: Vec<String>,
|
||||
}
|
||||
|
||||
impl UserInfoDto {
|
||||
pub fn id_i32(&self) -> i32 {
|
||||
self.id
|
||||
.parse::<i32>()
|
||||
.expect("parse UserInfoDto.id to i32 failed")
|
||||
}
|
||||
|
||||
pub fn roles(&self) -> Vec<Role> {
|
||||
self.roles
|
||||
.iter()
|
||||
.filter_map(|role| match role.as_str() {
|
||||
"04" | "05" => Some(Role::Admin),
|
||||
"01" | "03" => Some(Role::User),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl UserAuthCache {
|
||||
#[allow(dead_code)]
|
||||
pub fn len(&self) -> usize {
|
||||
let cache = self.cache.lock().unwrap();
|
||||
cache.len()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_all(&self) -> HashMap<String, UserInfoDto> {
|
||||
let cache = self.cache.lock().unwrap();
|
||||
cache.clone()
|
||||
}
|
||||
|
||||
fn insert(&self, key: String, value: UserInfoDto) {
|
||||
let mut cache = self.cache.lock().unwrap();
|
||||
cache.insert(key, value);
|
||||
}
|
||||
|
||||
fn get(&self, key: &str) -> Option<UserInfoDto> {
|
||||
let cache = self.cache.lock().unwrap();
|
||||
cache.get(key).cloned()
|
||||
}
|
||||
|
||||
pub async fn query_user(&self, token: &str) -> anyhow::Result<UserInfoDto> {
|
||||
if let Some(user_info) = self.get(token) {
|
||||
Ok(user_info)
|
||||
} else {
|
||||
let user_info = self.client.query_user_info(token).await?;
|
||||
self.insert(token.to_string(), user_info.clone());
|
||||
Ok(user_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Ok;
|
||||
use rtss_log::tracing::Level;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_login_info_serialize() {
|
||||
let login_info = LoginInfo::default();
|
||||
let json = serde_json::to_string(&login_info).unwrap();
|
||||
println!("{}", json);
|
||||
assert_eq!(
|
||||
json,
|
||||
r#"{"account":"17791995809","password":"e10adc3949ba59abbe56e057f20f883e","clientId":"1","secret":"joylink","project":"DEFAULT"}"#
|
||||
);
|
||||
let login_info: LoginInfo = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(login_info.account, "17791995809");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_auth_cache() -> anyhow::Result<()> {
|
||||
rtss_log::Logging::default().with_level(Level::DEBUG).init();
|
||||
let cache = UserAuthCache::new(UserAuthClient {
|
||||
base_url: "https://joylink.club/jlcloud".to_string(),
|
||||
login_url: "/api/login".to_string(),
|
||||
logout_url: "/api/login/logout".to_string(),
|
||||
user_info_url: "/api/login/getUserInfo".to_string(),
|
||||
});
|
||||
let token = cache.client.login(LoginInfo::default()).await?;
|
||||
let user = cache.query_user(&token).await?;
|
||||
println!("token: {}, {:?}", token, user);
|
||||
assert_eq!(cache.len(), 1);
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -21,12 +21,14 @@ pub trait ReleaseDataAccessor {
|
|||
draft_id: i32,
|
||||
name: &str,
|
||||
description: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<(ReleaseDataModel, ReleaseDataVersionModel), DbAccessError>;
|
||||
/// 从草稿发布到已有草稿默认的release data的新version,并使用新version
|
||||
async fn release_to_existing(
|
||||
&self,
|
||||
draft_id: i32,
|
||||
description: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<(ReleaseDataModel, ReleaseDataVersionModel), DbAccessError>;
|
||||
/// 分页查询发布数据列表
|
||||
async fn query_release_data_list(
|
||||
|
@ -241,6 +243,7 @@ impl ReleaseDataAccessor for RtssDbAccessor {
|
|||
draft_id: i32,
|
||||
name: &str,
|
||||
description: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<(ReleaseDataModel, ReleaseDataVersionModel), DbAccessError> {
|
||||
// 查询草稿数据
|
||||
let draft = self.query_draft_data_by_id(draft_id).await?;
|
||||
|
@ -272,7 +275,7 @@ impl ReleaseDataAccessor for RtssDbAccessor {
|
|||
.bind(name)
|
||||
.bind(draft.data_type as i32)
|
||||
.bind(draft.options.clone())
|
||||
.bind(draft.user_id)
|
||||
.bind(user_id.or(Some(draft.user_id)))
|
||||
.fetch_one(&mut *tx)
|
||||
.await?;
|
||||
// 创建发布数据版本
|
||||
|
@ -283,7 +286,7 @@ impl ReleaseDataAccessor for RtssDbAccessor {
|
|||
options: draft.options.clone(),
|
||||
data: draft.data.unwrap(),
|
||||
description: description.to_string(),
|
||||
user_id: draft.user_id,
|
||||
user_id: user_id.unwrap_or(draft.user_id),
|
||||
},
|
||||
&mut *tx,
|
||||
)
|
||||
|
@ -310,6 +313,7 @@ impl ReleaseDataAccessor for RtssDbAccessor {
|
|||
&self,
|
||||
draft_id: i32,
|
||||
description: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<(ReleaseDataModel, ReleaseDataVersionModel), DbAccessError> {
|
||||
// 查询草稿数据
|
||||
let draft = self.query_draft_data_by_id(draft_id).await?;
|
||||
|
@ -336,7 +340,7 @@ impl ReleaseDataAccessor for RtssDbAccessor {
|
|||
options: draft.options.clone(),
|
||||
data: draft.data.unwrap(),
|
||||
description: description.to_string(),
|
||||
user_id: draft.user_id,
|
||||
user_id: user_id.unwrap_or(draft.user_id),
|
||||
},
|
||||
&mut *tx,
|
||||
)
|
||||
|
@ -709,7 +713,9 @@ mod tests {
|
|||
let name = "test_release";
|
||||
let description = "test release";
|
||||
// 发布到默认发布数据
|
||||
let result = accessor.release_to_existing(draft.id, description).await;
|
||||
let result = accessor
|
||||
.release_to_existing(draft.id, description, None)
|
||||
.await;
|
||||
assert!(result.is_err());
|
||||
if let Some(e) = result.err() {
|
||||
match e {
|
||||
|
@ -722,7 +728,7 @@ mod tests {
|
|||
|
||||
// 发布新版本
|
||||
let (release_data, version1) = accessor
|
||||
.release_new_from_draft(draft.id, name, &description)
|
||||
.release_new_from_draft(draft.id, name, &description, None)
|
||||
.await?;
|
||||
assert_eq!(release_data.name, name);
|
||||
// 检查使用版本是刚刚发布的版本
|
||||
|
@ -752,7 +758,9 @@ mod tests {
|
|||
let data = "test2".as_bytes();
|
||||
accessor.update_draft_data_data(draft.id, data).await?;
|
||||
// 发布到已存在发布数据成功测试
|
||||
let (release_data, version2) = accessor.release_to_existing(draft.id, description).await?;
|
||||
let (release_data, version2) = accessor
|
||||
.release_to_existing(draft.id, description, None)
|
||||
.await?;
|
||||
assert_eq!(release_data.name, name);
|
||||
// 检查使用版本是刚刚发布的版本
|
||||
assert_eq!(release_data.used_version_id, Some(version2.id));
|
||||
|
@ -828,12 +836,12 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
let (release_data, _) = accessor
|
||||
.release_new_from_draft(draft.id, &name, &description)
|
||||
.release_new_from_draft(draft.id, &name, &description, None)
|
||||
.await?;
|
||||
assert_eq!(release_data.name, name);
|
||||
let another_name = format!("{}_another", name);
|
||||
let (release_data, _) = accessor
|
||||
.release_new_from_draft(draft.id, &another_name, &description)
|
||||
.release_new_from_draft(draft.id, &another_name, &description, None)
|
||||
.await?;
|
||||
assert_eq!(release_data.name, another_name);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,22 @@ impl From<Log> for rtss_log::Logging {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct Sso {
|
||||
pub base_url: String,
|
||||
pub login_url: String,
|
||||
pub logout_url: String,
|
||||
pub user_info_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct AppConfig {
|
||||
pub server: Server,
|
||||
pub log: Log,
|
||||
pub database: Database,
|
||||
pub sso: Sso,
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
|
|
13
src/cmd.rs
13
src/cmd.rs
|
@ -31,10 +31,15 @@ impl CmdExecutor for ServerOpts {
|
|||
app_config::AppConfig::new(&self.config_path).expect("Failed to load app config");
|
||||
let log: rtss_log::Logging = app_config.log.into();
|
||||
log.init();
|
||||
rtss_api::serve(rtss_api::ServerConfig::new(
|
||||
&app_config.database.url,
|
||||
app_config.server.port,
|
||||
))
|
||||
rtss_api::serve(
|
||||
rtss_api::ServerConfig::new(&app_config.database.url, app_config.server.port)
|
||||
.with_user_auth_client(rtss_api::UserAuthClient {
|
||||
base_url: app_config.sso.base_url,
|
||||
login_url: app_config.sso.login_url,
|
||||
logout_url: app_config.sso.logout_url,
|
||||
user_info_url: app_config.sso.user_info_url,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue