From 85aab14cbaee137d32eea4151a44fcfaba0a11e5 Mon Sep 17 00:00:00 2001 From: veypi Date: Mon, 16 Oct 2023 21:49:34 +0800 Subject: [PATCH] nats --- Makefile | 3 - oab/Cargo.lock | 247 ++- oab/Cargo.toml | 4 + oab/Makefile | 6 + oab/src/api/token.rs | 123 +- oab/src/cfg.rs | 14 +- oab/src/main.rs | 31 +- oab/src/models/user_plugin.rs | 4 +- oab/src/result.rs | 5 +- oaweb/package.json | 4 +- oaweb/public/icons/favicon-128x128.png | Bin 12324 -> 0 bytes oaweb/public/icons/favicon-16x16.png | Bin 859 -> 0 bytes oaweb/public/icons/favicon-32x32.png | Bin 2039 -> 0 bytes oaweb/public/icons/favicon-96x96.png | Bin 9643 -> 0 bytes oaweb/quasar.config.js | 2 + oaweb/src/boot/nats.ts | 40 + oaweb/src/boot/oaer.ts | 22 + oaweb/src/boot/pack.ts | 22 - oaweb/src/components/FsTree.vue | 2 +- oaweb/src/components/editor/index.vue | 2 +- oaweb/src/components/uploader/uploader.vue | 2 +- oaweb/src/libs/{evt.ts => bus.ts} | 4 +- oaweb/src/libs/jetstream/consumer.ts | 1064 ++++++++++ oaweb/src/libs/jetstream/internal_mod.ts | 153 ++ oaweb/src/libs/jetstream/jsapi_types.ts | 1082 ++++++++++ oaweb/src/libs/jetstream/jsbaseclient_api.ts | 128 ++ oaweb/src/libs/jetstream/jsclient.ts | 1032 +++++++++ oaweb/src/libs/jetstream/jslister.ts | 117 ++ oaweb/src/libs/jetstream/jsm.ts | 173 ++ oaweb/src/libs/jetstream/jsmconsumer_api.ts | 215 ++ oaweb/src/libs/jetstream/jsmsg.ts | 292 +++ oaweb/src/libs/jetstream/jsmstream_api.ts | 592 ++++++ oaweb/src/libs/jetstream/jsutil.ts | 236 +++ oaweb/src/libs/jetstream/kv.ts | 1046 +++++++++ oaweb/src/libs/jetstream/mod.ts | 142 ++ oaweb/src/libs/jetstream/objectstore.ts | 812 +++++++ oaweb/src/libs/jetstream/types.ts | 1867 +++++++++++++++++ .../libs/nats-base-client/authenticator.ts | 164 ++ oaweb/src/libs/nats-base-client/base64.ts | 67 + oaweb/src/libs/nats-base-client/bench.ts | 430 ++++ oaweb/src/libs/nats-base-client/codec.ts | 80 + oaweb/src/libs/nats-base-client/core.ts | 1399 ++++++++++++ oaweb/src/libs/nats-base-client/databuffer.ts | 129 ++ oaweb/src/libs/nats-base-client/denobuffer.ts | 248 +++ oaweb/src/libs/nats-base-client/encoders.ts | 53 + oaweb/src/libs/nats-base-client/error.ts | 14 + oaweb/src/libs/nats-base-client/headers.ts | 299 +++ oaweb/src/libs/nats-base-client/heartbeats.ts | 92 + .../libs/nats-base-client/idleheartbeat.ts | 139 ++ .../src/libs/nats-base-client/internal_mod.ts | 129 ++ oaweb/src/libs/nats-base-client/ipparser.ts | 215 ++ oaweb/src/libs/nats-base-client/mod.ts | 102 + oaweb/src/libs/nats-base-client/msg.ts | 116 + .../libs/nats-base-client/muxsubscription.ts | 106 + oaweb/src/libs/nats-base-client/nats.ts | 545 +++++ oaweb/src/libs/nats-base-client/nkeys.ts | 2 + oaweb/src/libs/nats-base-client/nuid.ts | 126 ++ oaweb/src/libs/nats-base-client/options.ts | 166 ++ oaweb/src/libs/nats-base-client/parser.ts | 748 +++++++ oaweb/src/libs/nats-base-client/protocol.ts | 1100 ++++++++++ .../libs/nats-base-client/queued_iterator.ts | 202 ++ oaweb/src/libs/nats-base-client/request.ts | 164 ++ oaweb/src/libs/nats-base-client/semver.ts | 157 ++ oaweb/src/libs/nats-base-client/servers.ts | 328 +++ oaweb/src/libs/nats-base-client/service.ts | 676 ++++++ .../libs/nats-base-client/serviceclient.ts | 98 + oaweb/src/libs/nats-base-client/sha256.js | 360 ++++ oaweb/src/libs/nats-base-client/testa.ts | 3 + oaweb/src/libs/nats-base-client/transport.ts | 116 + oaweb/src/libs/nats-base-client/typedsub.ts | 229 ++ oaweb/src/libs/nats-base-client/types.ts | 26 + oaweb/src/libs/nats-base-client/util.ts | 239 +++ oaweb/src/libs/nats.ws/connect.ts | 69 + oaweb/src/libs/nats.ws/index.ts | 17 + oaweb/src/libs/nats.ws/nats-base-client.ts | 16 + oaweb/src/libs/nats.ws/ws_transport.ts | 299 +++ oaweb/src/libs/nkey/base32.ts | 71 + oaweb/src/libs/nkey/codec.ts | 146 ++ oaweb/src/libs/nkey/crc16.ts | 298 +++ oaweb/src/libs/nkey/helper.ts | 46 + oaweb/src/libs/nkey/kp.ts | 85 + oaweb/src/libs/nkey/mod.ts | 30 + oaweb/src/libs/nkey/nkeys.ts | 250 +++ oaweb/src/libs/nkey/public.ts | 73 + oaweb/src/libs/nkey/util.ts | 55 + oaweb/src/libs/util.ts | 4 +- oaweb/src/pages/AppHome.vue | 2 +- oaweb/src/pages/docItem.vue | 2 +- oaweb/src/pages/fs.vue | 2 +- oaweb/src/pages/login.vue | 30 +- oaweb/yarn.lock | 56 +- script/nats.yml | 21 + 92 files changed, 20010 insertions(+), 117 deletions(-) delete mode 100644 oaweb/public/icons/favicon-128x128.png delete mode 100644 oaweb/public/icons/favicon-16x16.png delete mode 100644 oaweb/public/icons/favicon-32x32.png delete mode 100644 oaweb/public/icons/favicon-96x96.png create mode 100644 oaweb/src/boot/nats.ts create mode 100644 oaweb/src/boot/oaer.ts rename oaweb/src/libs/{evt.ts => bus.ts} (80%) create mode 100644 oaweb/src/libs/jetstream/consumer.ts create mode 100644 oaweb/src/libs/jetstream/internal_mod.ts create mode 100644 oaweb/src/libs/jetstream/jsapi_types.ts create mode 100644 oaweb/src/libs/jetstream/jsbaseclient_api.ts create mode 100644 oaweb/src/libs/jetstream/jsclient.ts create mode 100644 oaweb/src/libs/jetstream/jslister.ts create mode 100644 oaweb/src/libs/jetstream/jsm.ts create mode 100644 oaweb/src/libs/jetstream/jsmconsumer_api.ts create mode 100644 oaweb/src/libs/jetstream/jsmsg.ts create mode 100644 oaweb/src/libs/jetstream/jsmstream_api.ts create mode 100644 oaweb/src/libs/jetstream/jsutil.ts create mode 100644 oaweb/src/libs/jetstream/kv.ts create mode 100644 oaweb/src/libs/jetstream/mod.ts create mode 100644 oaweb/src/libs/jetstream/objectstore.ts create mode 100644 oaweb/src/libs/jetstream/types.ts create mode 100644 oaweb/src/libs/nats-base-client/authenticator.ts create mode 100644 oaweb/src/libs/nats-base-client/base64.ts create mode 100644 oaweb/src/libs/nats-base-client/bench.ts create mode 100644 oaweb/src/libs/nats-base-client/codec.ts create mode 100644 oaweb/src/libs/nats-base-client/core.ts create mode 100644 oaweb/src/libs/nats-base-client/databuffer.ts create mode 100644 oaweb/src/libs/nats-base-client/denobuffer.ts create mode 100644 oaweb/src/libs/nats-base-client/encoders.ts create mode 100644 oaweb/src/libs/nats-base-client/error.ts create mode 100644 oaweb/src/libs/nats-base-client/headers.ts create mode 100644 oaweb/src/libs/nats-base-client/heartbeats.ts create mode 100644 oaweb/src/libs/nats-base-client/idleheartbeat.ts create mode 100644 oaweb/src/libs/nats-base-client/internal_mod.ts create mode 100644 oaweb/src/libs/nats-base-client/ipparser.ts create mode 100644 oaweb/src/libs/nats-base-client/mod.ts create mode 100644 oaweb/src/libs/nats-base-client/msg.ts create mode 100644 oaweb/src/libs/nats-base-client/muxsubscription.ts create mode 100644 oaweb/src/libs/nats-base-client/nats.ts create mode 100644 oaweb/src/libs/nats-base-client/nkeys.ts create mode 100644 oaweb/src/libs/nats-base-client/nuid.ts create mode 100644 oaweb/src/libs/nats-base-client/options.ts create mode 100644 oaweb/src/libs/nats-base-client/parser.ts create mode 100644 oaweb/src/libs/nats-base-client/protocol.ts create mode 100644 oaweb/src/libs/nats-base-client/queued_iterator.ts create mode 100644 oaweb/src/libs/nats-base-client/request.ts create mode 100644 oaweb/src/libs/nats-base-client/semver.ts create mode 100644 oaweb/src/libs/nats-base-client/servers.ts create mode 100644 oaweb/src/libs/nats-base-client/service.ts create mode 100644 oaweb/src/libs/nats-base-client/serviceclient.ts create mode 100644 oaweb/src/libs/nats-base-client/sha256.js create mode 100644 oaweb/src/libs/nats-base-client/testa.ts create mode 100644 oaweb/src/libs/nats-base-client/transport.ts create mode 100644 oaweb/src/libs/nats-base-client/typedsub.ts create mode 100644 oaweb/src/libs/nats-base-client/types.ts create mode 100644 oaweb/src/libs/nats-base-client/util.ts create mode 100644 oaweb/src/libs/nats.ws/connect.ts create mode 100644 oaweb/src/libs/nats.ws/index.ts create mode 100644 oaweb/src/libs/nats.ws/nats-base-client.ts create mode 100644 oaweb/src/libs/nats.ws/ws_transport.ts create mode 100644 oaweb/src/libs/nkey/base32.ts create mode 100644 oaweb/src/libs/nkey/codec.ts create mode 100644 oaweb/src/libs/nkey/crc16.ts create mode 100644 oaweb/src/libs/nkey/helper.ts create mode 100644 oaweb/src/libs/nkey/kp.ts create mode 100644 oaweb/src/libs/nkey/mod.ts create mode 100644 oaweb/src/libs/nkey/nkeys.ts create mode 100644 oaweb/src/libs/nkey/public.ts create mode 100644 oaweb/src/libs/nkey/util.ts create mode 100644 script/nats.yml diff --git a/Makefile b/Makefile index 8d584ce..1e692d7 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,6 @@ dropTag: run: go run *.go -d -.PHONY:build -build: - @GOOS=linux GOARCH=amd64 go build -o ./build/OneAuth syncDB: @scp -P 19529 oa.db root@alco.host:/root/ diff --git a/oab/Cargo.lock b/oab/Cargo.lock index 736313b..0708c9c 100644 --- a/oab/Cargo.lock +++ b/oab/Cargo.lock @@ -381,6 +381,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "arrayvec" version = "0.7.4" @@ -393,6 +399,40 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" +[[package]] +name = "async-nats" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e45b67ea596bb94741ef15ba1d90b72c92bdc07553d8033734cb620a2b39f1c" +dependencies = [ + "base64 0.21.4", + "bytes", + "futures", + "http", + "memchr", + "nkeys", + "nuid", + "once_cell", + "rand", + "regex", + "ring", + "rustls 0.21.7", + "rustls-native-certs", + "rustls-pemfile", + "rustls-webpki", + "serde", + "serde_json", + "serde_nanos", + "serde_repr", + "thiserror", + "time", + "tokio", + "tokio-retry", + "tokio-rustls 0.24.1", + "tracing", + "url", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -655,6 +695,9 @@ name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] [[package]] name = "bytestring" @@ -773,6 +816,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -875,6 +928,33 @@ dependencies = [ "cipher", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "darling" version = "0.20.3" @@ -910,6 +990,12 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + [[package]] name = "dav-server" version = "0.5.7" @@ -1041,6 +1127,27 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +dependencies = [ + "curve25519-dalek", + "ed25519", + "sha2", + "signature", +] + [[package]] name = "either" version = "1.9.0" @@ -1109,6 +1216,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + [[package]] name = "finl_unicode" version = "1.2.0" @@ -1813,6 +1926,22 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nkeys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aad178aad32087b19042ee36dfd450b73f5f934fbfb058b59b198684dfec4c47" +dependencies = [ + "byteorder", + "data-encoding", + "ed25519", + "ed25519-dalek", + "getrandom", + "log", + "rand", + "signatory", +] + [[package]] name = "nom" version = "7.1.3" @@ -1833,6 +1962,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nuid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc895af95856f929163a0aa20c26a78d26bfdc839f51b9d5aa7a5b79e52b7e83" +dependencies = [ + "rand", +] + [[package]] name = "num-bigint" version = "0.3.3" @@ -1922,8 +2060,11 @@ dependencies = [ "actix-multipart", "actix-web", "aes-gcm", + "anyhow", + "async-nats", "base64 0.13.1", "block-padding", + "bytes", "chrono", "clap", "dav-server", @@ -1935,6 +2076,7 @@ dependencies = [ "jsonwebtoken", "lazy_static", "mime_guess", + "nkeys", "proc", "rand", "rust-embed", @@ -1974,6 +2116,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "ordered-float" version = "3.9.1" @@ -2193,6 +2341,12 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + [[package]] name = "polyval" version = "0.5.3" @@ -2576,11 +2730,24 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ + "log", "ring", "rustls-webpki", "sct 0.7.0", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.3" @@ -2615,6 +2782,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2735,6 +2911,29 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.19" @@ -2781,6 +2980,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_nanos" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae801b7733ca8d6a2b580debe99f67f36826a0f5b8a36055dc6bc40f8d6bc71" +dependencies = [ + "serde", +] + [[package]] name = "serde_plain" version = "1.0.2" @@ -2888,11 +3096,23 @@ dependencies = [ "libc", ] +[[package]] +name = "signatory" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e303f8205714074f6068773f0e29527e0453937fe837c9717d066635b65f31" +dependencies = [ + "pkcs8 0.10.2", + "rand_core", + "signature", + "zeroize", +] + [[package]] name = "signature" -version = "2.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" dependencies = [ "digest", "rand_core", @@ -3276,7 +3496,7 @@ checksum = "4db708cd3e459078f85f39f96a00960bd841f66ee2a669e90bf36907f5a79aae" dependencies = [ "once_cell", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", ] [[package]] @@ -3498,6 +3718,17 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "tokio-retry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +dependencies = [ + "pin-project", + "rand", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.22.0" @@ -3509,6 +3740,16 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.7", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" diff --git a/oab/Cargo.toml b/oab/Cargo.toml index 459b8c5..5a43a72 100644 --- a/oab/Cargo.toml +++ b/oab/Cargo.toml @@ -56,4 +56,8 @@ actix-cors = "0.6.4" rust-embed = "8.0.0" mime_guess = "2.0.4" service-manager = "0.3.0" +async-nats = "0.32.1" +anyhow = "1.0.75" +bytes = "1.5.0" +nkeys = "0.3.2" diff --git a/oab/Makefile b/oab/Makefile index fcbbe7f..69c3422 100644 --- a/oab/Makefile +++ b/oab/Makefile @@ -15,3 +15,9 @@ sqlx: entity: @sea-orm-cli generate entity --database-url mysql://root:123456@localhost:3306/oneauth -o ./src/models/entity/ --with-serde both --model-extra-derives Default,sqlx::FromRow --serde-skip-hidden-column --date-time-crate chrono + +# install_target: +# @rustup target add x86_64-unknown-linux-gnu + +build_linux: + @cargo build --release --target-dir ./target/linux/ diff --git a/oab/src/api/token.rs b/oab/src/api/token.rs index 8a6c167..65cb94c 100644 --- a/oab/src/api/token.rs +++ b/oab/src/api/token.rs @@ -5,64 +5,107 @@ // Distributed under terms of the MIT license. // -use actix_web::{get, web, Responder}; -use proc::access_read; +use actix_web::{post, web, Responder}; +use nkeys; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use serde::{Deserialize, Serialize}; +use tracing::info; use crate::{ - models::{self, AUStatus, Token, UserPlugin}, + models::{self, AUStatus, AccessCore, UserPlugin}, AppState, Error, Result, }; -#[get("/app/{aid}/token/")] -#[access_read("app")] +#[derive(Debug, Deserialize, Serialize)] +pub struct GetOptions { + app_id: Option, + token: String, + nonce: Option, +} + +// 转换token +#[post("/app/{aid}/token/")] pub async fn get( aid: web::Path, stat: web::Data, - t: web::ReqData, + query: web::Json, ) -> Result { - let n = aid.into_inner(); - if !n.is_empty() { - let s = models::app_user::Entity::find() - .filter(models::app_user::Column::AppId.eq(&n)) - .filter(models::app_user::Column::UserId.eq(&t.id)) - .one(stat.db()) - .await?; - if s.is_none() { - return Err(Error::NotAuthed); - }; - let s = s.unwrap(); - if s.status == AUStatus::OK as i32 { - let result = sqlx::query_as::<_, models::AccessCore>( + let aid = aid.into_inner(); + let mut key = stat.key.clone(); + let sid = match &query.app_id { + Some(i) => { + if !i.is_empty() { + match models::app::Entity::find_by_id(i).one(stat.db()).await? { + Some(sapp) => key = sapp.key, + None => {} + } + info!("{}", key); + }; + i + } + _ => "", + }; + info!("{}", key); + let token = models::Token::from(&query.token, &key)?; + if aid.starts_with("nats") { + let nonce = &query.nonce.clone().unwrap(); + let u = nkeys::KeyPair::from_seed(&stat.nats_secret).unwrap(); + let res = base64::encode(u.sign(nonce.as_bytes()).unwrap()); + return Ok(res); + }; + if !aid.is_empty() { + // 从OA token 转向其他app token + if sid.is_empty() { + let s = models::app_user::Entity::find() + .filter(models::app_user::Column::AppId.eq(&aid)) + .filter(models::app_user::Column::UserId.eq(&token.id)) + .one(stat.db()) + .await?; + if s.is_none() { + return Err(Error::NotAuthed); + }; + let s = s.unwrap(); + if s.status == AUStatus::OK as i32 { + let result = sqlx::query_as::<_, models::AccessCore>( "select access.name, access.rid, access.level from access, user_role, role WHERE user_role.user_id = ? && access.role_id=user_role.role_id && role.id=user_role.role_id && role.app_id = ?", ) - .bind(&t.id) - .bind(&n) + .bind(&token.id) + .bind(&aid) .fetch_all(stat.sqlx()) .await?; - let appobj = models::app::Entity::find_by_id(&n) - .one(stat.db()) - .await? - .unwrap(); - let u = models::user::Entity::find_by_id(&t.id) + let appobj = models::app::Entity::find_by_id(&aid) + .one(stat.db()) + .await? + .unwrap(); + let u = models::user::Entity::find_by_id(&token.id) + .one(stat.db()) + .await? + .unwrap(); + let str = u.token(result).to_string(&appobj.key)?; + Ok(str) + } else { + Err(Error::NotAuthed) + } + } else { + let u = models::user::Entity::find_by_id(&token.id) .one(stat.db()) .await? .unwrap(); - let str = u.token(result).to_string(&appobj.key)?; - // tokio::spawn(async move { - // let mut interval = tokio::time::interval(Duration::from_secs(5)); - // interval.tick().await; - // let start = Instant::now(); - // println!("time:{:?}", start); - // loop { - // interval.tick().await; - // println!("time:{:?}", start.elapsed()); - // } - // }); - + let str = u + .token(vec![ + AccessCore { + name: "app".to_string(), + rid: None, + level: models::AccessLevel::Read, + }, + AccessCore { + name: "user".to_string(), + rid: None, + level: models::AccessLevel::Read, + }, + ]) + .to_string(&stat.key)?; Ok(str) - } else { - Err(Error::NotAuthed) } } else { Err(Error::Missing("id".to_string())) diff --git a/oab/src/cfg.rs b/oab/src/cfg.rs index 3f45a90..03eadde 100644 --- a/oab/src/cfg.rs +++ b/oab/src/cfg.rs @@ -26,7 +26,6 @@ lazy_static! { pub static ref CLI: AppCli = AppCli::new(); } -pub static mut KEY: String = String::new(); // lazy_static! { // pub static ref CONFIG: ApplicationConfig = ApplicationConfig::new(); // } @@ -116,11 +115,13 @@ pub struct AppState { pub db_name: String, pub log_dir: Option, pub fs_root: String, + pub nats_key: String, + pub nats_secret: String, + /// "100MB" 日志分割尺寸-单位KB,MB,GB pub log_temp_size: Option, pub log_pack_compress: Option, pub log_level: Option, - pub jwt_secret: Option, pub user_init_space: i64, #[serde(skip)] @@ -136,9 +137,6 @@ impl AppState { Ok(f) => f, Err(ref e) if e.kind() == io::ErrorKind::NotFound => { // res.connect_sqlx().unwrap(); - unsafe { - KEY = res.key.clone(); - } return res; } Err(e) => panic!("{}", e), @@ -154,9 +152,6 @@ impl AppState { } else { println!("release_mode is enable!") } - unsafe { - KEY = res.key.clone(); - } res } pub fn defaut() -> Self { @@ -175,9 +170,10 @@ impl AppState { media_path: "/Users/veypi/test/media".to_string(), fs_root: "/Users/veypi/test/media".to_string(), log_level: None, - jwt_secret: None, _sqlx: None, _db: None, + nats_key: "UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL".to_string(), + nats_secret: "SUACQNAAFKDKRBXS62J4JYZ7DWZS7UNUQI52BOFGGBUACHTDHRQP7I66GI".to_string(), user_init_space: 300, } } diff --git a/oab/src/main.rs b/oab/src/main.rs index 47cc647..fa9fab2 100644 --- a/oab/src/main.rs +++ b/oab/src/main.rs @@ -5,6 +5,8 @@ // Distributed under terms of the Apache license. // +use bytes::Bytes; + use actix_files as fs; use actix_web::{ dev::{self, Service}, @@ -25,13 +27,13 @@ use tracing::{error, info, warn}; async fn main() -> Result<()> { std::env::set_var("RUST_LOG", "debug"); std::env::set_var("RUST_BACKTRACE", "1"); + std::env::set_var("asd", "asd"); init_log(); let mut data = AppState::new(); - data.connect().await?; - data.connect_sqlx()?; if let Some(c) = &CLI.command { match c { Clis::Init => { + data.connect_sqlx()?; models::init(data).await; return Ok(()); } @@ -41,10 +43,24 @@ async fn main() -> Result<()> { _ => {} }; }; + data.connect().await?; + data.connect_sqlx()?; web(data).await?; Ok(()) } async fn web(data: AppState) -> Result<()> { + let client = match async_nats::ConnectOptions::new() + .nkey(data.nats_secret.clone()) + .connect("127.0.0.1:4222") + .await + { + Ok(r) => r, + Err(e) => return Err(oab::Error::Unknown), + }; + client + .publish("msg".to_string(), Bytes::from("asd")) + .await + .unwrap(); let url = data.server_url.clone(); let dav = libs::fs::core(); let serv = HttpServer::new(move || { @@ -61,7 +77,13 @@ async fn web(data: AppState) -> Result<()> { ) .into() }); - let cors = actix_cors::Cors::permissive(); + let cors = actix_cors::Cors::default() + .allow_any_method() + .allow_any_header() + .supports_credentials() + .allowed_origin_fn(|_, _| { + return true; + }); let app = App::new(); app.wrap(logger) .wrap(middleware::Compress::default()) @@ -85,7 +107,7 @@ async fn web(data: AppState) -> Result<()> { .wrap_fn(|req, srv| { let headers = &req.headers().clone(); let origin = match headers.get("Origin") { - Some(o) => o.to_str().unwrap().clone().to_string(), + Some(o) => o.to_str().unwrap().to_string(), None => "".to_string(), }; srv.call(req).map(move |res| { @@ -129,6 +151,7 @@ struct Asset; #[actix_web::get("/{_:.*}")] async fn index(p: web::Path) -> impl Responder { info!("{}", p); + let p = &p.into_inner(); match Asset::get(p) { Some(content) => HttpResponse::Ok() diff --git a/oab/src/models/user_plugin.rs b/oab/src/models/user_plugin.rs index c7673ce..ce6f4d6 100644 --- a/oab/src/models/user_plugin.rs +++ b/oab/src/models/user_plugin.rs @@ -66,7 +66,7 @@ impl UserPlugin for super::entity::user::Model { exp: (Utc::now() + Duration::days(4)).timestamp(), iat: Utc::now().timestamp(), id: self.id.clone(), - ico: self.icon.as_ref().unwrap_or(&default_ico).to_string(), + icon: self.icon.as_ref().unwrap_or(&default_ico).to_string(), access: Some(ac), nickname: self .nickname @@ -173,7 +173,7 @@ pub struct Token { pub iat: i64, // Optional. 发布时间 pub id: String, // 用户id pub nickname: String, - pub ico: String, + pub icon: String, pub access: Option>, } diff --git a/oab/src/result.rs b/oab/src/result.rs index d4792ad..14f31be 100644 --- a/oab/src/result.rs +++ b/oab/src/result.rs @@ -41,7 +41,7 @@ where // pub type AsyncResult = std::result::Result>; -#[derive(Clone, ThisError, Debug, Deserialize, Serialize)] +#[derive(ThisError, Debug)] pub enum Error { // system // EnvVarError, @@ -128,6 +128,9 @@ pub enum Error { #[error("unknown error")] Unknown, + + #[error(transparent)] + Other(#[from] anyhow::Error), } impl From for Error { diff --git a/oaweb/package.json b/oaweb/package.json index 91167be..c37d930 100644 --- a/oaweb/package.json +++ b/oaweb/package.json @@ -17,7 +17,7 @@ "@toast-ui/editor": "^3.2.2", "@types/validator": "^13.11.2", "@veypi/msg": "^0.1.1", - "@veypi/oaer": "^0.0.1", + "@veypi/oaer": "^0.0.3", "@veypi/one-icon": "2", "animate.css": "^4.1.1", "axios": "^1.2.1", @@ -25,8 +25,10 @@ "js-base64": "^3.7.5", "mathjax": "3", "mitt": "^3.0.1", + "nats.ws": "^1.18.0", "pinia": "^2.0.11", "quasar": "^2.6.0", + "ts-nkeys": "^1.0.16", "validator": "^13.11.0", "vite-plugin-rewrite-all": "^1.0.1", "vue": "^3.0.0", diff --git a/oaweb/public/icons/favicon-128x128.png b/oaweb/public/icons/favicon-128x128.png deleted file mode 100644 index 14011761929f4ffbef81be318a347c0032eb6f42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12324 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 h$J#u>{O`^5_ + * 2023-10-16 16:18 + * Distributed under terms of the MIT license. + */ + +import axios from 'axios' +import util from '../libs/util' +import { connect, StringCodec } from '../libs/nats.ws' + + + + +const sc = StringCodec(); +const nc = await connect({ + servers: 'ws://127.0.0.1:4221', + authenticator: function(nonce?: string) { + let nkey = 'UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL' + // let nre = nkeyAuthenticator(nkey_seed) + let res = { + nkey: nkey, + sig: async function() { + let response = await axios.post('/api/app/nats/token/', { token: util.getToken(), nonce: nonce }); + console.log(response) + return response.data + } + }; + return res + } as any +}) + +nc.publish('msg', '123') +const sub = nc.subscribe("msg"); +(async () => { + for await (const m of sub) { + console.log(`[${sub.getProcessed()}]: ${sc.decode(m.data)}`); + } + console.log("subscription closed"); +})(); diff --git a/oaweb/src/boot/oaer.ts b/oaweb/src/boot/oaer.ts new file mode 100644 index 0000000..36bb289 --- /dev/null +++ b/oaweb/src/boot/oaer.ts @@ -0,0 +1,22 @@ +/* + * oaer.ts + * Copyright (C) 2023 veypi + * 2023-10-16 21:20 + * Distributed under terms of the MIT license. + */ + + +// import '@veypi/oaer' +import oaer from '@veypi/oaer' +import bus from 'src/libs/bus' +import util from 'src/libs/util' + +oaer.set({ + token: util.getToken(), + host: 'http://' + window.location.host, + uuid: 'FR9P5t8debxc11aFF', +}) + +bus.on('token', (t: any) => { + oaer.set({ token: t }) +}) diff --git a/oaweb/src/boot/pack.ts b/oaweb/src/boot/pack.ts index c2a1f0b..82dc872 100644 --- a/oaweb/src/boot/pack.ts +++ b/oaweb/src/boot/pack.ts @@ -7,33 +7,11 @@ -import { boot } from 'quasar/wrappers' import '@veypi/msg/index.css' import { conf } from '@veypi/msg' import '../assets/icon.js' -import '@veypi/oaer/dist/index.css' import 'cherry-markdown/dist/cherry-markdown.css'; -import oafs from 'src/libs/oafs' -import { Cfg } from '@veypi/oaer' -import util from 'src/libs/util.js' -import evt from 'src/libs/evt.js' - - -oafs.setCfg({ token: util.getToken(), app_id: 'FR9P5t8debxc11aFF' }) -Cfg.token.value = util.getToken() - conf.timeout = 5000 -Cfg.host.value = 'http://' + window.location.host -Cfg.uuid.value = 'FR9P5t8debxc11aFF' -evt.on('token', (t: any) => { - oafs.setCfg({ token: t }) - Cfg.token.value = t -}) -// "async" is optional; -// more info on params: https://v2.quasar.dev/quasar-cli/boot-files -export default boot(async (/* { app, router, ... } */) => { - // something to do -}) diff --git a/oaweb/src/components/FsTree.vue b/oaweb/src/components/FsTree.vue index 886bb7e..93929eb 100644 --- a/oaweb/src/components/FsTree.vue +++ b/oaweb/src/components/FsTree.vue @@ -28,7 +28,7 @@ diff --git a/oaweb/yarn.lock b/oaweb/yarn.lock index 4900d1d..7ced1d4 100644 --- a/oaweb/yarn.lock +++ b/oaweb/yarn.lock @@ -530,20 +530,18 @@ resolved "https://registry.yarnpkg.com/@veypi/msg/-/msg-0.1.1.tgz#94864ae2c0a81991b8a30d87f12d2245fdebbead" integrity sha512-UiAF/Y0EGT/37tGApptzHBNUpo78LbnrEkCqGAGMkJp86wrUyOgTAvuvQ197Ifqw9PIbjZM9dAgMv4DfMJQEYA== -"@veypi/oaer@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@veypi/oaer/-/oaer-0.0.1.tgz#b22ebaf72a7bfd5abf62f099b72b533a8cf27abd" - integrity sha512-ILY8SXK7yihH2/qhUFfPbD2FNE7O4IHh7Q9Z1A+Ild6zonCb3RM7LcOBM4/9WriEi3mPdBNmFfuoP8YFCIxHuA== +"@veypi/oaer@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@veypi/oaer/-/oaer-0.0.3.tgz#b72623ae3b124ac03ca65a6715cc1a2aaa1590ee" + integrity sha512-KfbbXJFUiGoCWoYpMAKOEX32Hc2qxk0NnApCWgXAVwU5iyFC4onJpvwPn0ekbWXULWSov5T3Yde61kOirGToIw== dependencies: "@veypi/msg" "^0.1.0" "@veypi/one-icon" "2" animate.css "^4.1.1" autoprefixer "^10.4.16" - axios "^1.5.1" js-base64 "^3.7.5" + mitt "^3.0.1" postcss "^8.4.31" - tailwindcss "^3.3.3" - vue "^3.3.4" webdav "^5.3.0" "@veypi/one-icon@2": @@ -871,15 +869,6 @@ axios@^1.2.1: form-data "^4.0.0" proxy-from-env "^1.1.0" -axios@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f" - integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3137,6 +3126,20 @@ nanoid@^3.3.6: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +nats.ws@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/nats.ws/-/nats.ws-1.18.0.tgz#eeef911608cc3c0f0f8ff2509c8a231f40213cb5" + integrity sha512-5ITvGO2gd4vAVK733u494ysEOuorfygpig9pqqLapV3FuiFWp4APsZdtZ893zXCC5UclF9MYUzdiTj2cKPDxAA== + optionalDependencies: + nkeys.js "1.0.5" + +nats@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nats/-/nats-2.17.0.tgz#1f6ffa5d89bb8ea4549e205f42601dbf66c4561e" + integrity sha512-749TtweWL6bc9R9yNra4a+tuk8J0bqurxcPV/9R2D+WPTplY4PPde/LPSXspqR/eCCTxiM80/AjVlfboEafRxA== + dependencies: + nkeys.js "1.0.5" + natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -3157,6 +3160,13 @@ nested-property@^4.0.0: resolved "https://registry.yarnpkg.com/nested-property/-/nested-property-4.0.0.tgz#a67b5a31991e701e03cdbaa6453bc5b1011bb88d" integrity sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA== +nkeys.js@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nkeys.js/-/nkeys.js-1.0.5.tgz#3024bde671eb33be0316ff2d5abe8b8cec960158" + integrity sha512-u25YnRPHiGVsNzwyHnn+PT90sgAhnS8jUJ1nxmkHMFYCJ6+Ic0lv291w7uhRBpJVJ3PH2GWbYqA151lGCRrB5g== + dependencies: + tweetnacl "1.0.3" + no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -4116,6 +4126,13 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== +ts-nkeys@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/ts-nkeys/-/ts-nkeys-1.0.16.tgz#b0c6e7c4f16f976c7e7ddb6982fc789a2f971248" + integrity sha512-1qrhAlavbm36wtW+7NtKOgxpzl+70NTF8xlz9mEhiA5zHMlMxjj3sEVKWm3pGZhHXE0Q3ykjrj+OSRVaYw+Dqg== + dependencies: + tweetnacl "^1.0.3" + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -4133,6 +4150,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tweetnacl@1.0.3, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -4294,7 +4316,7 @@ vue-router@^4.0.0: dependencies: "@vue/devtools-api" "^6.5.0" -vue@^3.0.0, vue@^3.2.20, vue@^3.3.4: +vue@^3.0.0, vue@^3.2.20: version "3.3.4" resolved "https://registry.yarnpkg.com/vue/-/vue-3.3.4.tgz#8ed945d3873667df1d0fcf3b2463ada028f88bd6" integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw== diff --git a/script/nats.yml b/script/nats.yml new file mode 100644 index 0000000..0c38051 --- /dev/null +++ b/script/nats.yml @@ -0,0 +1,21 @@ +# nats cfg +# +host: 127.0.0.1 +port: 4222 + +# 监控端口 +http_port: 8222 + +jetstream: { +} + +authorization: { + users: [ + { nkey: UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL} + ] +} + +websocket: { + listen: '0.0.0.0:4221' + no_tls: true +}