From 2f4d42d3ed8970178eae62556a5f697351ea052b Mon Sep 17 00:00:00 2001 From: red binder Date: Sun, 12 Apr 2026 23:35:55 +0200 Subject: [PATCH 01/19] Start work on super mario maker --- editions.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/editions.yaml b/editions.yaml index 7a6869c..50e589a 100644 --- a/editions.yaml +++ b/editions.yaml @@ -27,3 +27,13 @@ friends: RNEX_VIRTUAL_PORT_SECURE: "1:10" RNEX_DEFAULT_PORT: 6000 RNEX_ACCESS_KEY: "ridfebb9" +super-mario-maker: + features: + - prudpv1 + - v3-8-15 + settings: + AUTH_REPORT_VERSION: "branch:origin/project/wup-ama build:3_8_29_3022_0" + RNEX_VIRTUAL_PORT_INSECURE: "1:10" + RNEX_VIRTUAL_PORT_SECURE: "1:10" + RNEX_DEFAULT_PORT: 6000 + RNEX_ACCESS_KEY: "9f2b4678" \ No newline at end of file From 7e22acda5988e86ec2dd5805cdbb250b2495317f Mon Sep 17 00:00:00 2001 From: red binder Date: Mon, 13 Apr 2026 00:27:30 +0200 Subject: [PATCH 02/19] Basic test for SMM functionality --- rnex-core/src/nex/datastore.rs | 31 ++++++++++ rnex-core/src/nex/mod.rs | 1 + rnex-core/src/rmc/protocols/datastore.rs | 74 ++++++++++++++++++++++++ rnex-core/src/rmc/protocols/mod.rs | 1 + 4 files changed, 107 insertions(+) create mode 100644 rnex-core/src/nex/datastore.rs create mode 100644 rnex-core/src/rmc/protocols/datastore.rs diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs new file mode 100644 index 0000000..c24f75c --- /dev/null +++ b/rnex-core/src/nex/datastore.rs @@ -0,0 +1,31 @@ +use rnex_core::rmc::protocols::datastore::DataStore; +// use crate::define_rmc_proto; +// use macros::rmc_struct; +use rnex_core::prudp::socket_addr::PRUDPSockAddr; +use std::sync::{Weak}; +use rnex_core::PID; +use crate::nex::remote_console::RemoteConsole; +use rnex_core::rmc::response::ErrorCode; +use rnex_core::rmc::protocols::datastore::{GetMetaInfo, GetMetaParam}; + +pub struct User { + pub pid: PID, + pub ip: PRUDPSockAddr, + pub this: Weak, + pub remote: RemoteConsole, +} + +impl DataStore for User { + async fn get_meta(&self, metaparam: GetMetaParam) -> Result { + // // bogus + // let info: GetMetaInfo = GetMetaInfo { + // dataid: 10, + // owner: 1121, + // size: 1024, + // name: "idk" + // } + + // just trying to see what methods it tries to use + Err(rnex_core::rmc::response::ErrorCode::DataStore_NotFound) + } +} \ No newline at end of file diff --git a/rnex-core/src/nex/mod.rs b/rnex-core/src/nex/mod.rs index 0f52c13..2f628cd 100644 --- a/rnex-core/src/nex/mod.rs +++ b/rnex-core/src/nex/mod.rs @@ -5,3 +5,4 @@ pub mod friends_handler; pub mod matchmake; pub mod remote_console; pub mod user; +pub mod datastore; \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs new file mode 100644 index 0000000..796281d --- /dev/null +++ b/rnex-core/src/rmc/protocols/datastore.rs @@ -0,0 +1,74 @@ +use macros::{method_id, rmc_proto, RmcSerialize, rmc_struct}; +use crate::rmc::response::ErrorCode; +use rnex_core::rmc::structures::qbuffer::QBuffer; + +use rnex_core::kerberos::KerberosDateTime; +use rnex_core::PID; + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct PersistenceTarget { + pub owner: PID, + pub persistence_slot_id: u16, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct Permission { + pub permission: u8, + pub recipient_ids: Vec, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct RatingInfoWithSlot { + pub slot: i8, + pub rating: RatingInfo, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct RatingInfo { + pub total_value: i64, + pub count: u32, + pub initial_value: i64, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct GetMetaParam { + pub dataid: u64, + pub persistence_target: PersistenceTarget, + pub result_option: u8, + pub access_password: u64, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct GetMetaInfo { + pub dataid: u64, + pub owner: PID, + pub size: u32, + pub name: &'static str, + pub data_type: u16, + pub meta_binary: QBuffer, + pub permission: Permission, + pub del_permission: Permission, + pub created_time: KerberosDateTime, + pub updated_time: KerberosDateTime, + pub period: u16, + pub status: u8, + pub reffered_count: u32, + pub refer_dat_id: u32, + pub flag: u32, + pub referred_time: KerberosDateTime, + pub expire_time: KerberosDateTime, + pub tags: Vec<&'static str>, + pub ratings: Vec, +} + +#[rmc_proto(115)] +pub trait DataStore{ + #[method_id(8)] + async fn get_meta(&self, metaparam: GetMetaParam) -> Result; +} \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/mod.rs b/rnex-core/src/rmc/protocols/mod.rs index 8feb2f3..e3f1364 100644 --- a/rnex-core/src/rmc/protocols/mod.rs +++ b/rnex-core/src/rmc/protocols/mod.rs @@ -10,6 +10,7 @@ pub mod nat_traversal; pub mod notifications; pub mod ranking; pub mod secure; +pub mod datastore; use crate::result::ResultExtension; use crate::rmc::message::RMCMessage; From 35ac0e9f4649cb61a039e3a20e576f0140976fe4 Mon Sep 17 00:00:00 2001 From: red binder Date: Mon, 13 Apr 2026 00:30:10 +0200 Subject: [PATCH 03/19] Compiler pissing me off --- rnex-core/src/nex/datastore.rs | 4 ++-- rnex-core/src/rmc/protocols/datastore.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index c24f75c..a3b55c8 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -16,7 +16,7 @@ pub struct User { } impl DataStore for User { - async fn get_meta(&self, metaparam: GetMetaParam) -> Result { + async fn get_meta(&self, metaparam: GetMetaParam) -> Result { // // bogus // let info: GetMetaInfo = GetMetaInfo { // dataid: 10, @@ -26,6 +26,6 @@ impl DataStore for User { // } // just trying to see what methods it tries to use - Err(rnex_core::rmc::response::ErrorCode::DataStore_NotFound) + Err(ErrorCode::DataStore_NotFound) } } \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs index 796281d..d1eb4ff 100644 --- a/rnex-core/src/rmc/protocols/datastore.rs +++ b/rnex-core/src/rmc/protocols/datastore.rs @@ -1,5 +1,5 @@ use macros::{method_id, rmc_proto, RmcSerialize, rmc_struct}; -use crate::rmc::response::ErrorCode; +use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::qbuffer::QBuffer; use rnex_core::kerberos::KerberosDateTime; @@ -70,5 +70,5 @@ pub struct GetMetaInfo { #[rmc_proto(115)] pub trait DataStore{ #[method_id(8)] - async fn get_meta(&self, metaparam: GetMetaParam) -> Result; + async fn get_meta(&self, metaparam: GetMetaParam) -> Result; } \ No newline at end of file From 535e448541b7cc29d286ccee8915d36cf1e32b9c Mon Sep 17 00:00:00 2001 From: red binder Date: Mon, 13 Apr 2026 00:36:12 +0200 Subject: [PATCH 04/19] long sigh --- rnex-core/src/nex/datastore.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index a3b55c8..83b7cce 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -1,5 +1,5 @@ use rnex_core::rmc::protocols::datastore::DataStore; -// use crate::define_rmc_proto; +use crate::define_rmc_proto; // use macros::rmc_struct; use rnex_core::prudp::socket_addr::PRUDPSockAddr; use std::sync::{Weak}; @@ -8,14 +8,20 @@ use crate::nex::remote_console::RemoteConsole; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::protocols::datastore::{GetMetaInfo, GetMetaParam}; -pub struct User { +define_rmc_proto!( + proto DataStoreUser { + DataStore + } +); + +pub struct DataStoreUser { pub pid: PID, pub ip: PRUDPSockAddr, - pub this: Weak, + pub this: Weak, pub remote: RemoteConsole, } -impl DataStore for User { +impl DataStore for DataStoreUser { async fn get_meta(&self, metaparam: GetMetaParam) -> Result { // // bogus // let info: GetMetaInfo = GetMetaInfo { From f020ed86341a44373b5a1714715af05ebd1bbfb3 Mon Sep 17 00:00:00 2001 From: red binder Date: Mon, 13 Apr 2026 00:38:38 +0200 Subject: [PATCH 05/19] ACTUALLY define the protocol Maple, why --- rnex-core/src/nex/datastore.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 83b7cce..e6b532e 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -1,12 +1,12 @@ -use rnex_core::rmc::protocols::datastore::DataStore; use crate::define_rmc_proto; -// use macros::rmc_struct; +use macros::rmc_struct; use rnex_core::prudp::socket_addr::PRUDPSockAddr; use std::sync::{Weak}; use rnex_core::PID; -use crate::nex::remote_console::RemoteConsole; +use rnex_core::nex::remote_console::RemoteConsole; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::protocols::datastore::{GetMetaInfo, GetMetaParam}; +use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore}; define_rmc_proto!( proto DataStoreUser { @@ -14,6 +14,7 @@ define_rmc_proto!( } ); +#[rmc_struct(DataStoreUser)] pub struct DataStoreUser { pub pid: PID, pub ip: PRUDPSockAddr, From 3a4eb78d2c3f042de0f9be84fc7a16da126137cc Mon Sep 17 00:00:00 2001 From: red binder Date: Mon, 13 Apr 2026 10:43:51 +0200 Subject: [PATCH 06/19] ACTUALLY define the protocol thanks maple for helping out --- rnex-core/src/nex/datastore.rs | 18 +++--------------- rnex-core/src/nex/user.rs | 4 +++- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index e6b532e..30a6ff7 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -5,24 +5,12 @@ use std::sync::{Weak}; use rnex_core::PID; use rnex_core::nex::remote_console::RemoteConsole; use rnex_core::rmc::response::ErrorCode; +use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure}; use rnex_core::rmc::protocols::datastore::{GetMetaInfo, GetMetaParam}; use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore}; +use crate::nex::user::User; -define_rmc_proto!( - proto DataStoreUser { - DataStore - } -); - -#[rmc_struct(DataStoreUser)] -pub struct DataStoreUser { - pub pid: PID, - pub ip: PRUDPSockAddr, - pub this: Weak, - pub remote: RemoteConsole, -} - -impl DataStore for DataStoreUser { +impl DataStore for User { async fn get_meta(&self, metaparam: GetMetaParam) -> Result { // // bogus // let info: GetMetaInfo = GetMetaInfo { diff --git a/rnex-core/src/nex/user.rs b/rnex-core/src/nex/user.rs index c86ae73..f271355 100644 --- a/rnex-core/src/nex/user.rs +++ b/rnex-core/src/nex/user.rs @@ -26,6 +26,7 @@ use rnex_core::rmc::protocols::matchmake_extension::{ }; use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking}; use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure}; +use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore}; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::any::Any; use rnex_core::rmc::structures::matchmake::{ @@ -51,7 +52,8 @@ define_rmc_proto!( MatchmakeExt, Matchmake, NatTraversal, - Ranking + Ranking, + DataStore } ); From 0fe0b754a152812525fb21a5a19849fecf8afc94 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 14 Apr 2026 09:00:49 +0200 Subject: [PATCH 07/19] More work on datastore --- Cargo.lock | 1973 +++++++++++++++++++++- build-edition.sh | 3 +- editions.yaml | 3 +- rnex-core/Cargo.toml | 7 +- rnex-core/src/nex/datastore.rs | 48 +- rnex-core/src/nex/mod.rs | 3 +- rnex-core/src/nex/s3presigner.rs | 72 + rnex-core/src/rmc/protocols/datastore.rs | 94 +- 8 files changed, 2097 insertions(+), 106 deletions(-) create mode 100644 rnex-core/src/nex/s3presigner.rs diff --git a/Cargo.lock b/Cargo.lock index ce7b5e9..3e1d57d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,18 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -49,6 +46,21 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +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.5.0" @@ -56,31 +68,483 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "backtrace" -version = "0.3.75" +name = "aws-config" +version = "1.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "11493b0bad143270fb8ad284a096dd529ba91924c5409adeac856cc1bf047dbc" dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 1.3.1", + "sha1", + "time", + "tokio", + "tracing", + "url", + "zeroize", ] +[[package]] +name = "aws-credential-types" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f20799b373a1be121fe3005fba0c2090af9411573878f224df44b42727fcaf7" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "aws-runtime" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc0651c57e384202e47153c1260b84a9936e19803d747615edf199dc3b98d17" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "bytes-utils", + "fastrand", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "http-body 1.0.1", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-s3" +version = "1.129.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d4e8410fadbc0ee453145dd77a4958227b18b05bf67c2795d0a8b8596c9aa0f" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-checksums", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "bytes", + "fastrand", + "hex", + "hmac", + "http 0.2.12", + "http 1.3.1", + "http-body 1.0.1", + "lru", + "percent-encoding", + "regex-lite", + "sha2", + "tracing", + "url", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.97.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aadc669e184501caaa6beafb28c6267fc1baef0810fb58f9b205485ca3f2567" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http 1.3.1", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1342a7db8f358d3de0aed2007a0b54e875458e39848d54cc1d46700b2bfcb0a8" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http 1.3.1", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.101.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab41ad64e4051ecabeea802d6a17845a91e83287e1dd249e6963ea1ba78c428a" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "fastrand", + "http 0.2.12", + "http 1.3.1", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b660013a6683ab23797778e21f1f854744fdf05f68204b4cca4c8c04b5d1f4" +dependencies = [ + "aws-credential-types", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "crypto-bigint 0.5.5", + "form_urlencoded", + "hex", + "hmac", + "http 0.2.12", + "http 1.3.1", + "p256", + "percent-encoding", + "ring", + "sha2", + "subtle", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffcaf626bdda484571968400c326a244598634dc75fd451325a54ad1a59acfc" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-checksums" +version = "0.64.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6750f3dd509b0694a4377f0293ed2f9630d710b1cebe281fa8bac8f099f88bc6" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "crc-fast", + "hex", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "md-5", + "pin-project-lite", + "sha1", + "sha2", + "tracing", +] + +[[package]] +name = "aws-smithy-eventstream" +version = "0.60.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09d74e5e32f76b8762da505a3cd59303e367a664ca67295387baa8c1d7548" +dependencies = [ + "aws-smithy-types", + "bytes", + "crc32fast", +] + +[[package]] +name = "aws-smithy-http" +version = "0.63.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231" +dependencies = [ + "aws-smithy-eventstream", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-http-client" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a2f165a7feee6f263028b899d0a181987f4fa7179a6411a32a439fba7c5f769" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "h2 0.3.27", + "h2 0.4.13", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper 1.9.0", + "hyper-rustls 0.24.2", + "hyper-rustls 0.27.8", + "hyper-util", + "pin-project-lite", + "rustls 0.21.12", + "rustls 0.23.31", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.4", + "tower", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.62.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9648b0bb82a2eedd844052c6ad2a1a822d1f8e3adee5fbf668366717e428856a" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-observability" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06c2315d173edbf1920da8ba3a7189695827002e4c0fc961973ab1c54abca9c" +dependencies = [ + "aws-smithy-runtime-api", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a56d79744fb3edb5d722ef79d86081e121d3b9422cb209eb03aea6aa4f21ebd" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028999056d2d2fd58a697232f9eec4a643cf73a71cf327690a7edad1d2af2110" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-http-client", + "aws-smithy-observability", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "pin-project-lite", + "pin-utils", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876ab3c9c29791ba4ba02b780a3049e21ec63dabda09268b175272c3733a79e6" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.3.1", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-types" +version = "1.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d73dbfbaa8e4bc57b9045137680b958d274823509a360abfd8e1d514d40c95c" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce02add1aa3677d022f8adf81dcbe3046a95f17a1b1e8979c145cd21d3d22b3" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c8323699dd9b3c8d5b3c13051ae9cdef58fd179957c882f8374dd8725962d9" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "rustc_version", + "tracing", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -118,17 +582,36 @@ dependencies = [ ] [[package]] -name = "bytes" -version = "1.10.1" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] [[package]] name = "cc" -version = "1.2.31" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -162,6 +645,30 @@ dependencies = [ "inout", ] +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "cookie" version = "0.18.1" @@ -216,6 +723,33 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc-fast" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd92aca2c6001b1bf5ba0ff84ee74ec8501b52bbef0cac80bf25a6c1d87a83d" +dependencies = [ + "crc", + "digest", + "rustversion", + "spin 0.10.0", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -225,6 +759,43 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -241,6 +812,27 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.4.0" @@ -257,6 +849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -287,12 +880,109 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve", + "rfc6979", + "signature 1.6.4", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest", + "ff", + "generic-array", + "group", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "flate2" version = "1.1.5" @@ -303,12 +993,35 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -318,12 +1031,56 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + [[package]] name = "futures-macro" version = "0.3.31" @@ -354,9 +1111,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", + "futures-io", "futures-macro", "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -396,16 +1155,90 @@ dependencies = [ ] [[package]] -name = "gimli" -version = "0.31.1" +name = "group" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" @@ -413,6 +1246,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -422,6 +1264,26 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.3.1" @@ -433,12 +1295,151 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2 0.4.13", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "log", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2b52f86d1d4bc0d6b4e6826d960b1b333217e07d36b882dca570a5e1c48895b" +dependencies = [ + "http 1.3.1", + "hyper 1.9.0", + "hyper-util", + "rustls 0.23.31", + "rustls-native-certs", + "tokio", + "tokio-rustls 0.26.4", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.9.0", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.3", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.63" @@ -572,7 +1573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", ] [[package]] @@ -585,21 +1586,26 @@ dependencies = [ ] [[package]] -name = "io-uring" -version = "0.7.9" +name = "ipnet" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] [[package]] name = "js-sys" @@ -618,10 +1624,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" [[package]] -name = "libc" -version = "0.2.174" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin 0.9.8", +] + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "bitflags", + "libc", + "plain", + "redox_syscall 0.7.4", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] [[package]] name = "litemap" @@ -651,6 +1694,15 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "lru" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +dependencies = [ + "hashbrown 0.16.1", +] + [[package]] name = "macros" version = "0.0.0" @@ -698,13 +1750,29 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", - "windows-sys 0.59.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", ] [[package]] @@ -713,6 +1781,26 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -720,6 +1808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -731,15 +1820,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -752,6 +1832,29 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.4" @@ -770,9 +1873,9 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.17", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -781,6 +1884,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -799,6 +1911,49 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der 0.7.10", + "pkcs8 0.10.2", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.10", + "spki 0.7.3", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "potential_utf" version = "0.1.4" @@ -999,6 +2154,32 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + [[package]] name = "ring" version = "0.17.14" @@ -1018,6 +2199,9 @@ name = "rnex-core" version = "0.1.1" dependencies = [ "anyhow", + "aws-config", + "aws-sdk-s3", + "base64", "bytemuck", "cfg-if", "chrono", @@ -1034,7 +2218,9 @@ dependencies = [ "rc4", "serde", "serde_json", + "sha2", "simplelog", + "sqlx", "thiserror", "tokio", "typenum", @@ -1043,10 +2229,45 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.26" +name = "rsa" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "signature 2.2.0", + "spki 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] [[package]] name = "rustls" @@ -1054,11 +2275,12 @@ version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.4", "subtle", "zeroize", ] @@ -1084,12 +2306,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustls-webpki" version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1101,6 +2334,12 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "schannel" version = "0.1.28" @@ -1116,6 +2355,30 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "3.5.1" @@ -1139,6 +2402,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.228" @@ -1182,6 +2451,18 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -1193,6 +2474,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1208,6 +2500,26 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1236,15 +2548,248 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] [[package]] name = "socket2" -version = "0.6.0" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.10", +] + +[[package]] +name = "sqlx" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +dependencies = [ + "base64", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.5", + "hashlink", + "indexmap", + "log", + "memchr", + "once_cell", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "thiserror", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.104", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.104", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "thiserror", + "tracing", + "url", ] [[package]] @@ -1253,6 +2798,17 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "subtle" version = "2.6.1" @@ -1365,43 +2921,65 @@ dependencies = [ ] [[package]] -name = "tokio" -version = "1.47.1" +name = "tinyvec" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2", + "socket2 0.6.3", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls", + "rustls 0.23.31", "tokio", ] @@ -1413,14 +2991,87 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.23.31", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tungstenite", ] +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[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.28.0" @@ -1429,11 +3080,11 @@ checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.3.1", "httparse", "log", "rand 0.9.2", - "rustls", + "rustls 0.23.31", "rustls-pki-types", "sha1", "thiserror", @@ -1446,12 +3097,33 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "untrusted" version = "0.9.0" @@ -1469,7 +3141,7 @@ dependencies = [ "flate2", "log", "percent-encoding", - "rustls", + "rustls 0.23.31", "rustls-pki-types", "serde", "serde_json", @@ -1485,7 +3157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" dependencies = [ "base64", - "http", + "http 1.3.1", "httparse", "log", ] @@ -1501,6 +3173,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -1513,6 +3191,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "v-byte-helpers" version = "0.1.1" @@ -1522,12 +3210,33 @@ dependencies = [ "macros 0.1.1", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[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.1+wasi-snapshot-preview1" @@ -1543,6 +3252,12 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -1610,6 +3325,16 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + [[package]] name = "winapi-util" version = "0.1.9" @@ -1684,13 +3409,22 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1699,7 +3433,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1711,34 +3445,67 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1751,24 +3518,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1787,6 +3578,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + [[package]] name = "yoke" version = "0.8.1" diff --git a/build-edition.sh b/build-edition.sh index 5d65fc3..ede64d3 100755 --- a/build-edition.sh +++ b/build-edition.sh @@ -10,4 +10,5 @@ echo $EDITION_FEATURES echo ENV SETTINGS: env -OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl +#OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl +OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 cargo build --release --features "$EDITION_FEATURES" diff --git a/editions.yaml b/editions.yaml index 50e589a..40c2e10 100644 --- a/editions.yaml +++ b/editions.yaml @@ -31,9 +31,10 @@ super-mario-maker: features: - prudpv1 - v3-8-15 + - datastore settings: AUTH_REPORT_VERSION: "branch:origin/project/wup-ama build:3_8_29_3022_0" RNEX_VIRTUAL_PORT_INSECURE: "1:10" RNEX_VIRTUAL_PORT_SECURE: "1:10" RNEX_DEFAULT_PORT: 6000 - RNEX_ACCESS_KEY: "9f2b4678" \ No newline at end of file + RNEX_ACCESS_KEY: "9f2b4678" diff --git a/rnex-core/Cargo.toml b/rnex-core/Cargo.toml index ff2b7b3..07e5dd8 100644 --- a/rnex-core/Cargo.toml +++ b/rnex-core/Cargo.toml @@ -28,6 +28,11 @@ anyhow = "1.0.100" ureq = { version = "3.1.4", features = [ "json" ] } serde = { version = "1.0.228", features = [ "derive" ] } serde_json = "1.0.149" +sqlx = { version = "0.8.6", optional = true } +aws-sdk-s3 = { version = "1.129.0", optional = true } +aws-config = { version = "1.8.15", optional = true } +base64 = "0.22.1" +sha2 = "0.10.9" [dev-dependencies] # criterion = "0.7.0" @@ -40,7 +45,7 @@ big_pid = [] v3-8-15 = ["rmc_struct_header"] v4-3-11 = ["v3-8-15"] nx = ["big_pid"] - +datastore = ["dep:sqlx", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"] [[bench]] name = "rmc_serialization" diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 30a6ff7..9299906 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -4,23 +4,53 @@ use rnex_core::prudp::socket_addr::PRUDPSockAddr; use std::sync::{Weak}; use rnex_core::PID; use rnex_core::nex::remote_console::RemoteConsole; +use rnex_core::nex::s3presigner::S3Presigner; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure}; -use rnex_core::rmc::protocols::datastore::{GetMetaInfo, GetMetaParam}; -use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore}; +use rnex_core::rmc::protocols::datastore::{CompletePostParam, GetMetaInfo, GetMetaParam, KeyValue, RateCustomRankingParam}; +use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; use crate::nex::user::User; impl DataStore for User { async fn get_meta(&self, metaparam: GetMetaParam) -> Result { - // // bogus - // let info: GetMetaInfo = GetMetaInfo { - // dataid: 10, - // owner: 1121, - // size: 1024, - // name: "idk" - // } + println!("dataid: {}", metaparam.dataid); + println!("access password: {}", metaparam.access_password); // just trying to see what methods it tries to use Err(ErrorCode::DataStore_NotFound) } + + async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result { + let data_id: u64 = 9400001; + let presigner = S3Presigner::new("https://s3.perditum.com", "miku".into()).await; + + let key = format!("data/{}.bin", data_id); + + let (upload_url, fields) = presigner.generate_presigned_post(&key).await; + + let form_fields = fields.into_iter().map(|(k, v)| { + KeyValue { key: k, value: v } + }).collect(); + + Ok(ReqPostInfo { + dataid: data_id, + url: upload_url, + request_headers: vec![], + form_fields, + root_ca_cert: vec![], + }) + } + + async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode> { + // whatever + println!("dataid: {}", completeparam.dataid); + println!("succeeded?: {}", completeparam.success); + + Ok(()) + } + + async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode> { + // this returns nothing + Ok(()) + } } \ No newline at end of file diff --git a/rnex-core/src/nex/mod.rs b/rnex-core/src/nex/mod.rs index 2f628cd..91bb866 100644 --- a/rnex-core/src/nex/mod.rs +++ b/rnex-core/src/nex/mod.rs @@ -5,4 +5,5 @@ pub mod friends_handler; pub mod matchmake; pub mod remote_console; pub mod user; -pub mod datastore; \ No newline at end of file +pub mod datastore; +pub mod s3presigner; \ No newline at end of file diff --git a/rnex-core/src/nex/s3presigner.rs b/rnex-core/src/nex/s3presigner.rs new file mode 100644 index 0000000..c348c9d --- /dev/null +++ b/rnex-core/src/nex/s3presigner.rs @@ -0,0 +1,72 @@ +use aws_sdk_s3::presigning::PresigningConfig; +use base64::{engine::general_purpose, Engine as _}; +use hmac::{Hmac, Mac}; +use sha2::{Sha256, Digest}; +use chrono::{Utc, Duration}; +use serde_json::json; + +pub struct S3Presigner { + endpoint: String, + bucket: String, +} + +impl S3Presigner { + pub async fn new(endpoint: &str, bucket: String) -> Self { + Self { + endpoint: endpoint.trim_end_matches('/').to_string(), + bucket, + } + } + pub async fn generate_presigned_post(&self, key: &str) -> (String, Vec<(String, String)>) { + let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key"); + let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key"); + let region = "us-east-1"; + let date_short = Utc::now().format("%Y%m%d").to_string(); + let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string(); + let expiration = (Utc::now() + Duration::minutes(15)).format("%Y-%m-%dT%H:%M:%SZ").to_string(); + + let credential = format!("{}/{}/{}/s3/aws4_request", access_key, date_short, region); + + let policy_json = json!({ + "expiration": expiration, + "conditions": [ + {"bucket": self.bucket}, + ["starts-with", "$key", key], + {"x-amz-credential": credential}, + {"x-amz-algorithm": "AWS4-HMAC-SHA256"}, + {"x-amz-date": date_full} + ] + }); + + let policy_base64 = general_purpose::STANDARD.encode(policy_json.to_string()); + + let signature = self.calculate_signature(&secret_key, &date_short, region, &policy_base64); + + let mut fields = vec![ + ("key".to_string(), key.to_string()), + ("X-Amz-Algorithm".to_string(), "AWS4-HMAC-SHA256".to_string()), + ("X-Amz-Credential".to_string(), credential), + ("X-Amz-Date".to_string(), date_full), + ("Policy".to_string(), policy_base64), + ("X-Amz-Signature".to_string(), signature), + ]; + + let url = format!("https://s3.perditum.com/{}", self.bucket); + (url, fields) + } + + fn calculate_signature(&self, secret: &str, date: &str, region: &str, policy: &str) -> String { + let k_date = self.hmac_sha256(format!("AWS4{}", secret).as_bytes(), date); + let k_region = self.hmac_sha256(&k_date, region); + let k_service = self.hmac_sha256(&k_region, "s3"); + let k_signing = self.hmac_sha256(&k_service, "aws4_request"); + + hex::encode(self.hmac_sha256(&k_signing, policy)) + } + + fn hmac_sha256(&self, key: &[u8], data: &str) -> Vec { + let mut mac = Hmac::::new_from_slice(key).expect("HMAC can take key of any size"); + mac.update(data.as_bytes()); + mac.finalize().into_bytes().to_vec() + } +} \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs index d1eb4ff..9055355 100644 --- a/rnex-core/src/rmc/protocols/datastore.rs +++ b/rnex-core/src/rmc/protocols/datastore.rs @@ -1,6 +1,6 @@ use macros::{method_id, rmc_proto, RmcSerialize, rmc_struct}; -use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::qbuffer::QBuffer; +use rnex_core::rmc::response::ErrorCode; use rnex_core::kerberos::KerberosDateTime; use rnex_core::PID; @@ -12,7 +12,7 @@ pub struct PersistenceTarget { pub persistence_slot_id: u16, } -#[derive(RmcSerialize, Clone)] +#[derive(RmcSerialize, Clone, Debug)] #[rmc_struct(0)] pub struct Permission { pub permission: u8, @@ -49,7 +49,7 @@ pub struct GetMetaInfo { pub dataid: u64, pub owner: PID, pub size: u32, - pub name: &'static str, + pub name: String, pub data_type: u16, pub meta_binary: QBuffer, pub permission: Permission, @@ -58,17 +58,101 @@ pub struct GetMetaInfo { pub updated_time: KerberosDateTime, pub period: u16, pub status: u8, - pub reffered_count: u32, + pub referred_count: u32, pub refer_dat_id: u32, pub flag: u32, pub referred_time: KerberosDateTime, pub expire_time: KerberosDateTime, - pub tags: Vec<&'static str>, + pub tags: Vec, pub ratings: Vec, } +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct RatingInitParam { + pub flag: u8, + pub internal_flag: u8, + pub lock_type: u8, + pub intial_valie: i64, + pub range_min: i32, + pub range_max: i32, + pub period_hour: i8, + pub period_duration: i16 +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct RatingInitParamWithSlot { + pub slot: i8, + pub param: RatingInitParam, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct PersistenceInitParam { + pub persistence_slot_id: u16, + pub delete_last_object: bool, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct KeyValue { + pub key: String, + pub value: String, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct PreparePostParam { + pub size: u32, + pub name: String, + pub data_type: u16, + pub meta_binary: QBuffer, + pub permission: Permission, + pub del_permission: Permission, + pub flag: u32, + pub period: u16, + pub refer_data_id: u32, + pub tags: Vec, + pub rating_init_params: Vec, + pub persistence_init_param: PersistenceInitParam, + pub extra_data: Vec, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct ReqPostInfo { + pub dataid: u64, + pub url: String, + pub request_headers: Vec, + pub form_fields: Vec, + pub root_ca_cert: Vec, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct CompletePostParam { + pub dataid: u64, + pub success: bool, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct RateCustomRankingParam { + pub dataid: u64, + pub appid: u32, + pub score: u32, + pub period: u16, +} + #[rmc_proto(115)] pub trait DataStore{ #[method_id(8)] async fn get_meta(&self, metaparam: GetMetaParam) -> Result; + #[method_id(24)] + async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result; + #[method_id(26)] + async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode>; + #[method_id(48)] + async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode>; } \ No newline at end of file From 75c6e9df49e2ee6a8f3795ff00e2c6726c1505ec Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 14 Apr 2026 09:19:00 +0200 Subject: [PATCH 08/19] Dynamically load S3 details --- rnex-core/src/executables/common.rs | 12 +++++++++++- rnex-core/src/nex/datastore.rs | 6 +++++- rnex-core/src/nex/s3presigner.rs | 5 +++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/rnex-core/src/executables/common.rs b/rnex-core/src/executables/common.rs index 416e450..08ba399 100644 --- a/rnex-core/src/executables/common.rs +++ b/rnex-core/src/executables/common.rs @@ -8,14 +8,24 @@ use std::io::Cursor; use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use tokio::net::TcpListener; +use std::sync::LazyLock; use log::error; use std::error::Error; - +use std::string::ToString; use crate::reggie::UnitPacketRead; const IP_REQ_SERVICE_URL: &str = "https://ipinfo.io/ip"; +pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATASTORE_S3_ENDPOINT") + .expect("RNEX_DATASTORE_S3_ENDPOINT must be set") +}); +pub static RNEX_DATASTORE_S3_BUCKET: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATASTORE_S3_BUCKET") + .expect("RNEX_DATASTORE_S3_BUCKET must be set") +}); + pub fn try_get_ip() -> Result> { let mut req = ureq::get(IP_REQ_SERVICE_URL).call()?; diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 9299906..89e5a02 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -10,6 +10,7 @@ use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, Remote use rnex_core::rmc::protocols::datastore::{CompletePostParam, GetMetaInfo, GetMetaParam, KeyValue, RateCustomRankingParam}; use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; use crate::nex::user::User; +use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT}; impl DataStore for User { async fn get_meta(&self, metaparam: GetMetaParam) -> Result { @@ -22,7 +23,10 @@ impl DataStore for User { async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result { let data_id: u64 = 9400001; - let presigner = S3Presigner::new("https://s3.perditum.com", "miku".into()).await; + let presigner = S3Presigner::new( + &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), + format!("{}", *RNEX_DATASTORE_S3_BUCKET) + ).await; let key = format!("data/{}.bin", data_id); diff --git a/rnex-core/src/nex/s3presigner.rs b/rnex-core/src/nex/s3presigner.rs index c348c9d..169293b 100644 --- a/rnex-core/src/nex/s3presigner.rs +++ b/rnex-core/src/nex/s3presigner.rs @@ -4,6 +4,7 @@ use hmac::{Hmac, Mac}; use sha2::{Sha256, Digest}; use chrono::{Utc, Duration}; use serde_json::json; +use rnex_core::executables::common::RNEX_DATASTORE_S3_ENDPOINT; pub struct S3Presigner { endpoint: String, @@ -20,7 +21,7 @@ impl S3Presigner { pub async fn generate_presigned_post(&self, key: &str) -> (String, Vec<(String, String)>) { let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key"); let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key"); - let region = "us-east-1"; + let region = "us-east-1"; // hardcoded because its the default region for most s3 clones let date_short = Utc::now().format("%Y%m%d").to_string(); let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string(); let expiration = (Utc::now() + Duration::minutes(15)).format("%Y-%m-%dT%H:%M:%SZ").to_string(); @@ -51,7 +52,7 @@ impl S3Presigner { ("X-Amz-Signature".to_string(), signature), ]; - let url = format!("https://s3.perditum.com/{}", self.bucket); + let url = format!("https://{}/{}", *RNEX_DATASTORE_S3_ENDPOINT, self.bucket); (url, fields) } From 3b103e12d4c58f5e1269505e30c7c4d9f085d6a2 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 14 Apr 2026 09:42:18 +0200 Subject: [PATCH 09/19] Implement GetApplicationConfig --- rnex-core/src/nex/datastore.rs | 36 ++++++++++++++++++++++++ rnex-core/src/rmc/protocols/datastore.rs | 9 ++++++ 2 files changed, 45 insertions(+) diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 89e5a02..a2d8b8a 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -57,4 +57,40 @@ impl DataStore for User { // this returns nothing Ok(()) } + + async fn get_application_config(&self, appid: u32) -> Result, ErrorCode> { + const MAX_COURSE_UPLOADS: i32 = 100; + + let config = match appid { + 0 => vec![ + 0x00000001, 0x00000032, 0x00000096, 0x0000012c, 0x000001f4, + 0x00000320, 0x00000514, 0x000007d0, 0x00000bb8, 0x00001388, + MAX_COURSE_UPLOADS, 0x00000014, 0x0000001e, 0x00000028, 0x00000032, + 0x0000003c, 0x00000046, 0x00000050, 0x0000005a, 0x00000064, + 0x00000023, 0x0000004b, 0x00000023, 0x0000004b, 0x00000032, + 0x00000000, 0x00000003, 0x00000003, 0x00000064, 0x00000006, + 0x00000001, 0x00000060, 0x00000005, 0x00000060, 0x00000000, + 0x000007e4, 0x00000001, 0x00000001, 0x0000000c, 0x00000000, + ], + 1 => vec![ + 2, + 1770179696, + 1770179664, + 1770179640, + 1770180827, + 1770180777, + 1770180745, + 1770177625, + 1770177590, + ], + 2 => vec![0x000007df, 0x0000000c, 0x00000016, 0x00000005, 0x00000000], + 10 => vec![35, 75, 96, 40, 5, 6], + _ => { + log::error!("unknown SMM app id: {}", appid); + return Err(ErrorCode::DataStore_Unknown); + } + }; + + Ok(config) + } } \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs index 9055355..3899f93 100644 --- a/rnex-core/src/rmc/protocols/datastore.rs +++ b/rnex-core/src/rmc/protocols/datastore.rs @@ -145,6 +145,13 @@ pub struct RateCustomRankingParam { pub period: u16, } +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct BufferQueueParam { + pub dataid: u64, + pub slot: u32, +} + #[rmc_proto(115)] pub trait DataStore{ #[method_id(8)] @@ -155,4 +162,6 @@ pub trait DataStore{ async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode>; #[method_id(48)] async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode>; + #[method_id(61)] + async fn get_application_config(&self, appid: u32) -> Result, ErrorCode>; } \ No newline at end of file From ee798408f06fa393a38ca2523447e9f0d03b2431 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 14 Apr 2026 10:49:30 +0200 Subject: [PATCH 10/19] preliminary DB support --- Cargo.lock | 22 +++++++++ ...b44a630eb066846c777c462b8c9341e26b696.json | 38 ++++++++++++++ rnex-core/Cargo.toml | 2 +- .../src/executables/backend_server_secure.rs | 11 +++++ rnex-core/src/executables/common.rs | 12 +++++ rnex-core/src/nex/datastore.rs | 49 ++++++++++++++++++- 6 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json diff --git a/Cargo.lock b/Cargo.lock index 3e1d57d..8fd84b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2628,6 +2628,7 @@ checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ "base64", "bytes", + "chrono", "crc", "crossbeam-queue", "either", @@ -2648,6 +2649,9 @@ dependencies = [ "sha2", "smallvec", "thiserror", + "time", + "tokio", + "tokio-stream", "tracing", "url", ] @@ -2686,6 +2690,7 @@ dependencies = [ "sqlx-postgres", "sqlx-sqlite", "syn 2.0.104", + "tokio", "url", ] @@ -2700,6 +2705,7 @@ dependencies = [ "bitflags", "byteorder", "bytes", + "chrono", "crc", "digest", "dotenvy", @@ -2727,6 +2733,7 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror", + "time", "tracing", "whoami", ] @@ -2741,6 +2748,7 @@ dependencies = [ "base64", "bitflags", "byteorder", + "chrono", "crc", "dotenvy", "etcetera", @@ -2764,6 +2772,7 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror", + "time", "tracing", "whoami", ] @@ -2775,6 +2784,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" dependencies = [ "atoi", + "chrono", "flume", "futures-channel", "futures-core", @@ -2788,6 +2798,7 @@ dependencies = [ "serde_urlencoded", "sqlx-core", "thiserror", + "time", "tracing", "url", ] @@ -2983,6 +2994,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-tungstenite" version = "0.28.0" diff --git a/rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json b/rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json new file mode 100644 index 0000000..f91446a --- /dev/null +++ b/rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json @@ -0,0 +1,38 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int4", + "Text", + "Int4", + "Bytea", + "Int4", + "Int4Array", + "Int4", + "Int4Array", + "Int4", + "Int4", + "Int8", + "TextArray", + "Int4", + "TextArray", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + false + ] + }, + "hash": "039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696" +} diff --git a/rnex-core/Cargo.toml b/rnex-core/Cargo.toml index 07e5dd8..646b65e 100644 --- a/rnex-core/Cargo.toml +++ b/rnex-core/Cargo.toml @@ -28,7 +28,7 @@ anyhow = "1.0.100" ureq = { version = "3.1.4", features = [ "json" ] } serde = { version = "1.0.228", features = [ "derive" ] } serde_json = "1.0.149" -sqlx = { version = "0.8.6", optional = true } +sqlx = { version = "0.8.6", optional = true, features = ["postgres", "runtime-tokio", "chrono", "time"] } aws-sdk-s3 = { version = "1.129.0", optional = true } aws-config = { version = "1.8.15", optional = true } base64 = "0.22.1" diff --git a/rnex-core/src/executables/backend_server_secure.rs b/rnex-core/src/executables/backend_server_secure.rs index 91b83b3..a92ba9a 100644 --- a/rnex-core/src/executables/backend_server_secure.rs +++ b/rnex-core/src/executables/backend_server_secure.rs @@ -1,5 +1,6 @@ use cfg_if::cfg_if; use rnex_core::common::setup; +use rnex_core::executables::common::DB_POOL; use rnex_core::executables::common::new_simple_backend; use rnex_core::executables::friends_backend::start_friends_backend; use rnex_core::nex::matchmake::MatchmakeManager; @@ -8,6 +9,7 @@ use rnex_core::nex::user::User; use rnex_core::rmc::protocols::{RemoteDisconnectable, RmcPureRemoteObject}; use std::sync::Arc; use std::sync::atomic::AtomicU32; +use sqlx::PgPool; #[tokio::main] async fn main() { @@ -16,6 +18,15 @@ async fn main() { cfg_if! { if #[cfg(feature = "friends")]{ start_friends_backend().await; + } else if #[cfg(feature = "datastore")] { + let database_url = std::env::var("RNEX_DATASTORE_DATABASE_URL") + .expect("RNEX_DATASTORE_DATABASE_URL must be set"); + + let pool = PgPool::connect(&database_url) + .await + .expect("Failed to create pool"); + + DB_POOL.set(pool).expect("failed to set global DB_POOL"); } else { use rnex_core::executables::regular_backend; regular_backend::start_regular_backend().await diff --git a/rnex-core/src/executables/common.rs b/rnex-core/src/executables/common.rs index 08ba399..ec27f43 100644 --- a/rnex-core/src/executables/common.rs +++ b/rnex-core/src/executables/common.rs @@ -9,6 +9,8 @@ use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use tokio::net::TcpListener; use std::sync::LazyLock; +use std::sync::OnceLock; +use sqlx::postgres::PgPool; use log::error; use std::error::Error; @@ -17,6 +19,16 @@ use crate::reggie::UnitPacketRead; const IP_REQ_SERVICE_URL: &str = "https://ipinfo.io/ip"; +pub static RNEX_DATASTORE_DATABASE_URL: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATASTORE_DATABASE_URL") + .expect("RNEX_DATASTORE_DATABASE_URL must be set") +}); + +pub static DB_POOL: OnceLock = OnceLock::new(); + +pub fn get_db() -> &'static PgPool { + DB_POOL.get().expect("db_pool not initialized") +} pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock = LazyLock::new(|| { std::env::var("RNEX_DATASTORE_S3_ENDPOINT") .expect("RNEX_DATASTORE_S3_ENDPOINT must be set") diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index a2d8b8a..57635a7 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -2,6 +2,9 @@ use crate::define_rmc_proto; use macros::rmc_struct; use rnex_core::prudp::socket_addr::PRUDPSockAddr; use std::sync::{Weak}; +use chrono::Utc; +use sqlx::types::time; +use sqlx::types::time::PrimitiveDateTime; use rnex_core::PID; use rnex_core::nex::remote_console::RemoteConsole; use rnex_core::nex::s3presigner::S3Presigner; @@ -10,7 +13,7 @@ use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, Remote use rnex_core::rmc::protocols::datastore::{CompletePostParam, GetMetaInfo, GetMetaParam, KeyValue, RateCustomRankingParam}; use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; use crate::nex::user::User; -use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT}; +use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT, get_db}; impl DataStore for User { async fn get_meta(&self, metaparam: GetMetaParam) -> Result { @@ -22,7 +25,49 @@ impl DataStore for User { } async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result { - let data_id: u64 = 9400001; + // Prepare your arrays first (Postgres needs i32, not u32) + let recipient_ids: Vec = postparam.permission.recipient_ids.iter().map(|&id| id as i32).collect(); + let del_recipient_ids: Vec = postparam.del_permission.recipient_ids.iter().map(|&id| id as i32).collect(); + let now = time::OffsetDateTime::now_utc(); + + let row = sqlx::query!( + r#" + INSERT INTO datastore.objects ( + owner, size, name, data_type, meta_binary, + permission, permission_recipients, + delete_permission, delete_permission_recipients, + flag, period, refer_data_id, tags, + persistence_slot_id, extra_data, creation_date, update_date + ) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17 + ) RETURNING data_id + "#, + self.pid as i32, + postparam.size as i32, + postparam.name, + postparam.data_type as i32, + &postparam.meta_binary.0, // unwrap QBuffer to &[u8] + postparam.permission.permission as i32, + &recipient_ids, + postparam.del_permission.permission as i32, + &del_recipient_ids, + postparam.flag as i32, + postparam.period as i32, + postparam.refer_data_id as i64, + &postparam.tags, + postparam.persistence_init_param.persistence_slot_id as i32, + &postparam.extra_data, + time::PrimitiveDateTime::new(now.date(), now.time()), + time::PrimitiveDateTime::new(now.date(), now.time()) + ) + .fetch_one(get_db()) + .await + .map_err(|e| { + log::error!("DB Error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + + let data_id = row.data_id as u64; let presigner = S3Presigner::new( &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), format!("{}", *RNEX_DATASTORE_S3_BUCKET) From b07c97f2bcd269f6c8db1559a5bfa757b3577258 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 14 Apr 2026 10:53:57 +0200 Subject: [PATCH 11/19] I've got to be like a professional dumbass or smth --- rnex-core/src/executables/backend_server_secure.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rnex-core/src/executables/backend_server_secure.rs b/rnex-core/src/executables/backend_server_secure.rs index a92ba9a..0beeafc 100644 --- a/rnex-core/src/executables/backend_server_secure.rs +++ b/rnex-core/src/executables/backend_server_secure.rs @@ -27,6 +27,8 @@ async fn main() { .expect("Failed to create pool"); DB_POOL.set(pool).expect("failed to set global DB_POOL"); + use rnex_core::executables::regular_backend; + regular_backend::start_regular_backend().await } else { use rnex_core::executables::regular_backend; regular_backend::start_regular_backend().await From 2b8132452f5e7a8331e0c793de54e125e3a1ff72 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 14 Apr 2026 19:42:44 +0200 Subject: [PATCH 12/19] More work on datastore --- ...b44a630eb066846c777c462b8c9341e26b696.json | 38 ++ ...d3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json | 28 ++ ...077f9b06ffe11cab2693e4e365c265f8e2418.json | 125 +++++ ...88d2d26f7644e85bfd65423e6e32c469e3695.json | 16 + ...b8158ea907d36588e1e59f6cbe752d89361bb.json | 22 + ...f7803ee88233c53efaa2df9966a6c72c8c763.json | 23 + ...a4beaf37e879c28c81c22abeddb3d030535df.json | 28 ++ ...8be8946430d93821dbccb6dc9324ef0544c17.json | 29 ++ ...1d9f4ef96adbdab7ca7d008acf596af91fc2b.json | 112 +++++ ...e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json | 40 ++ ...fe18e500d243f1b55fd18e7d96d281605bcf9.json | 14 + build-edition.sh | 1 + ...d3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json | 28 ++ ...077f9b06ffe11cab2693e4e365c265f8e2418.json | 125 +++++ ...88d2d26f7644e85bfd65423e6e32c469e3695.json | 16 + ...b8158ea907d36588e1e59f6cbe752d89361bb.json | 22 + ...f7803ee88233c53efaa2df9966a6c72c8c763.json | 23 + ...a4beaf37e879c28c81c22abeddb3d030535df.json | 28 ++ ...8be8946430d93821dbccb6dc9324ef0544c17.json | 29 ++ ...1d9f4ef96adbdab7ca7d008acf596af91fc2b.json | 112 +++++ ...e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json | 40 ++ ...fe18e500d243f1b55fd18e7d96d281605bcf9.json | 14 + rnex-core/src/kerberos/mod.rs | 17 + rnex-core/src/nex/datastore.rs | 465 +++++++++++++++++- rnex-core/src/rmc/protocols/datastore.rs | 25 +- 25 files changed, 1406 insertions(+), 14 deletions(-) create mode 100644 .sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json create mode 100644 .sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json create mode 100644 .sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json create mode 100644 .sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json create mode 100644 .sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json create mode 100644 .sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json create mode 100644 .sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json create mode 100644 .sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json create mode 100644 .sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json create mode 100644 .sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json create mode 100644 .sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json create mode 100644 rnex-core/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json create mode 100644 rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json create mode 100644 rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json create mode 100644 rnex-core/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json create mode 100644 rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json create mode 100644 rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json create mode 100644 rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json create mode 100644 rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json create mode 100644 rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json create mode 100644 rnex-core/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json diff --git a/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json b/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json new file mode 100644 index 0000000..f91446a --- /dev/null +++ b/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json @@ -0,0 +1,38 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int4", + "Text", + "Int4", + "Bytea", + "Int4", + "Int4Array", + "Int4", + "Int4Array", + "Int4", + "Int4", + "Int8", + "TextArray", + "Int4", + "TextArray", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + false + ] + }, + "hash": "039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696" +} diff --git a/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json b/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json new file mode 100644 index 0000000..abf5c03 --- /dev/null +++ b/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT owner, under_review FROM datastore.objects WHERE data_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "owner", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "under_review", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + true, + false + ] + }, + "hash": "164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9" +} diff --git a/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json b/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json new file mode 100644 index 0000000..7471873 --- /dev/null +++ b/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json @@ -0,0 +1,125 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "owner", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "size", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "data_type", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "meta_binary", + "type_info": "Bytea" + }, + { + "ordinal": 6, + "name": "permission", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 8, + "name": "delete_permission", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "delete_permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 10, + "name": "period", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "refer_data_id", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "flag", + "type_info": "Int4" + }, + { + "ordinal": 13, + "name": "tags", + "type_info": "TextArray" + }, + { + "ordinal": 14, + "name": "creation_date", + "type_info": "Timestamp" + }, + { + "ordinal": 15, + "name": "update_date", + "type_info": "Timestamp" + }, + { + "ordinal": 16, + "name": "access_password", + "type_info": "Int8" + }, + { + "ordinal": 17, + "name": "under_review", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int4" + ] + }, + "nullable": [ + false, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + false, + false + ] + }, + "hash": "18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418" +} diff --git a/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json b/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json new file mode 100644 index 0000000..5411a38 --- /dev/null +++ b/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695" +} diff --git a/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json b/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json new file mode 100644 index 0000000..83246ca --- /dev/null +++ b/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + null + ] + }, + "hash": "2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb" +} diff --git a/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json b/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json new file mode 100644 index 0000000..7a1cc6f --- /dev/null +++ b/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "buffer", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int4" + ] + }, + "nullable": [ + false + ] + }, + "hash": "48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763" +} diff --git a/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json b/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json new file mode 100644 index 0000000..4f07b49 --- /dev/null +++ b/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "under_review", + "type_info": "Bool" + }, + { + "ordinal": 1, + "name": "access_password", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df" +} diff --git a/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json b/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json new file mode 100644 index 0000000..867701f --- /dev/null +++ b/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "value", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8Array", + "Int8" + ] + }, + "nullable": [ + false, + true + ] + }, + "hash": "8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17" +} diff --git a/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json b/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json new file mode 100644 index 0000000..539fdeb --- /dev/null +++ b/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json @@ -0,0 +1,112 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "owner", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "size", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "data_type", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "meta_binary", + "type_info": "Bytea" + }, + { + "ordinal": 6, + "name": "permission", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 8, + "name": "delete_permission", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "delete_permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 10, + "name": "period", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "refer_data_id", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "flag", + "type_info": "Int4" + }, + { + "ordinal": 13, + "name": "tags", + "type_info": "TextArray" + }, + { + "ordinal": 14, + "name": "creation_date", + "type_info": "Timestamp" + }, + { + "ordinal": 15, + "name": "update_date", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "hash": "a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b" +} diff --git a/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json b/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json new file mode 100644 index 0000000..095ca6f --- /dev/null +++ b/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "slot", + "type_info": "Int2" + }, + { + "ordinal": 1, + "name": "total_value", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "count", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "initial_value", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + true, + false, + true + ] + }, + "hash": "c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa" +} diff --git a/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json b/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json new file mode 100644 index 0000000..552f92a --- /dev/null +++ b/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9" +} diff --git a/build-edition.sh b/build-edition.sh index ede64d3..d2c0750 100755 --- a/build-edition.sh +++ b/build-edition.sh @@ -11,4 +11,5 @@ echo ENV SETTINGS: env #OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl +OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 cargo sqlx prepare --workspace -- --features "$EDITION_FEATURES" OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 cargo build --release --features "$EDITION_FEATURES" diff --git a/rnex-core/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json b/rnex-core/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json new file mode 100644 index 0000000..abf5c03 --- /dev/null +++ b/rnex-core/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT owner, under_review FROM datastore.objects WHERE data_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "owner", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "under_review", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + true, + false + ] + }, + "hash": "164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9" +} diff --git a/rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json b/rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json new file mode 100644 index 0000000..7471873 --- /dev/null +++ b/rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json @@ -0,0 +1,125 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "owner", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "size", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "data_type", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "meta_binary", + "type_info": "Bytea" + }, + { + "ordinal": 6, + "name": "permission", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 8, + "name": "delete_permission", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "delete_permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 10, + "name": "period", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "refer_data_id", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "flag", + "type_info": "Int4" + }, + { + "ordinal": 13, + "name": "tags", + "type_info": "TextArray" + }, + { + "ordinal": 14, + "name": "creation_date", + "type_info": "Timestamp" + }, + { + "ordinal": 15, + "name": "update_date", + "type_info": "Timestamp" + }, + { + "ordinal": 16, + "name": "access_password", + "type_info": "Int8" + }, + { + "ordinal": 17, + "name": "under_review", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int4" + ] + }, + "nullable": [ + false, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + false, + false + ] + }, + "hash": "18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418" +} diff --git a/rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json b/rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json new file mode 100644 index 0000000..5411a38 --- /dev/null +++ b/rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695" +} diff --git a/rnex-core/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json b/rnex-core/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json new file mode 100644 index 0000000..83246ca --- /dev/null +++ b/rnex-core/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + null + ] + }, + "hash": "2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb" +} diff --git a/rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json b/rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json new file mode 100644 index 0000000..7a1cc6f --- /dev/null +++ b/rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "buffer", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int4" + ] + }, + "nullable": [ + false + ] + }, + "hash": "48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763" +} diff --git a/rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json b/rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json new file mode 100644 index 0000000..4f07b49 --- /dev/null +++ b/rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "under_review", + "type_info": "Bool" + }, + { + "ordinal": 1, + "name": "access_password", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df" +} diff --git a/rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json b/rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json new file mode 100644 index 0000000..867701f --- /dev/null +++ b/rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "value", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8Array", + "Int8" + ] + }, + "nullable": [ + false, + true + ] + }, + "hash": "8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17" +} diff --git a/rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json b/rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json new file mode 100644 index 0000000..539fdeb --- /dev/null +++ b/rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json @@ -0,0 +1,112 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "owner", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "size", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "data_type", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "meta_binary", + "type_info": "Bytea" + }, + { + "ordinal": 6, + "name": "permission", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 8, + "name": "delete_permission", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "delete_permission_recipients", + "type_info": "Int4Array" + }, + { + "ordinal": 10, + "name": "period", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "refer_data_id", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "flag", + "type_info": "Int4" + }, + { + "ordinal": 13, + "name": "tags", + "type_info": "TextArray" + }, + { + "ordinal": 14, + "name": "creation_date", + "type_info": "Timestamp" + }, + { + "ordinal": 15, + "name": "update_date", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "hash": "a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b" +} diff --git a/rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json b/rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json new file mode 100644 index 0000000..095ca6f --- /dev/null +++ b/rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "slot", + "type_info": "Int2" + }, + { + "ordinal": 1, + "name": "total_value", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "count", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "initial_value", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + true, + false, + true + ] + }, + "hash": "c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa" +} diff --git a/rnex-core/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json b/rnex-core/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json new file mode 100644 index 0000000..552f92a --- /dev/null +++ b/rnex-core/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9" +} diff --git a/rnex-core/src/kerberos/mod.rs b/rnex-core/src/kerberos/mod.rs index 205c62a..00f775d 100644 --- a/rnex-core/src/kerberos/mod.rs +++ b/rnex-core/src/kerberos/mod.rs @@ -51,6 +51,23 @@ pub fn derive_key(pid: PID, password: &[u8]) -> [u8; 16] { pub struct KerberosDateTime(pub u64); impl KerberosDateTime { + pub fn from_u64(val: u64) -> Self { + Self(val) + } + + pub fn from_naive(dt: chrono::NaiveDateTime) -> Self { + use chrono::Datelike; + use chrono::Timelike; + Self::new( + dt.second() as u64, + dt.minute() as u64, + dt.hour() as u64, + dt.day() as u64, + dt.month() as u64, + dt.year() as u64, + ) + } + pub fn new(second: u64, minute: u64, hour: u64, day: u64, month: u64, year: u64) -> Self { Self(second | (minute << 6) | (hour << 12) | (day << 17) | (month << 22) | (year << 26)) } diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 57635a7..19db2b4 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -10,22 +10,360 @@ use rnex_core::nex::remote_console::RemoteConsole; use rnex_core::nex::s3presigner::S3Presigner; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure}; -use rnex_core::rmc::protocols::datastore::{CompletePostParam, GetMetaInfo, GetMetaParam, KeyValue, RateCustomRankingParam}; +use rnex_core::rmc::protocols::datastore::{BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, DataStoreGetCustomRankingByDataIDParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, RateCustomRankingParam, RatingInfo, RatingInfoWithSlot}; use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; use crate::nex::user::User; use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT, get_db}; +use rnex_core::rmc::structures::qbuffer::QBuffer; +use sqlx::types::chrono::DateTime; +use rnex_core::kerberos::KerberosDateTime; +use rnex_core::rmc::structures::qresult::QResult; + +fn map_row_to_meta_info( + row_data_id: i64, + row_owner: i32, + row_size: i32, + row_name: String, + row_data_type: i16, + row_meta_binary: Vec, + row_permission: i16, + row_permission_recipients: Vec, + row_delete_permission: i16, + row_delete_permission_recipients: Vec, + row_period: i16, + row_refer_data_id: i64, + row_flag: i32, + row_tags: Vec, + row_creation_date: chrono::NaiveDateTime, + row_update_date: chrono::NaiveDateTime, + ratings: Vec +) -> GetMetaInfo { + GetMetaInfo { + dataid: row_data_id as u64, + owner: row_owner as u32, + size: row_size as u32, + name: row_name, + data_type: row_data_type as u16, + meta_binary: QBuffer(row_meta_binary), + permission: Permission { + permission: row_permission as u8, + recipient_ids: row_permission_recipients.into_iter().map(|id| id as u32).collect(), + }, + del_permission: Permission { + permission: row_delete_permission as u8, + recipient_ids: row_delete_permission_recipients.into_iter().map(|id| id as u32).collect(), + }, + period: row_period as u16, + status: 0, + referred_count: 0, + refer_dat_id: row_refer_data_id as u32, + flag: row_flag as u32, + tags: row_tags, + expire_time: KerberosDateTime::from_u64(0x9C3F3E0000), + created_time: KerberosDateTime::from_naive(row_creation_date), + updated_time: KerberosDateTime::from_naive(row_update_date), + referred_time: KerberosDateTime::from_naive(row_creation_date), + ratings, + } +} + +async fn check_object_availability(data_id: u64, password: u64) -> Result<(), ErrorCode> { + let row = sqlx::query!( + r#" + SELECT under_review, access_password + FROM datastore.objects + WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE + "#, + data_id as i64 + ) + .fetch_optional(get_db()) + .await + .map_err(|e| { + eprintln!("Availability check DB error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })? + .ok_or(ErrorCode::DataStore_NotFound)?; + + let access_password = row.access_password as u64; + if access_password != 0 && access_password != password { + return Err(ErrorCode::DataStore_InvalidPassword); + } + + if row.under_review { + return Err(ErrorCode::DataStore_UnderReviewing); + } + + Ok(()) +} + +async fn get_object_ratings(data_id: u64, password: u64) -> Result, ErrorCode> { + check_object_availability(data_id, password).await?; + + let rows = sqlx::query!( + r#" + SELECT slot, total_value, count, initial_value + FROM datastore.object_ratings + WHERE data_id = $1 + "#, + data_id as i64 + ) + .fetch_all(get_db()) + .await + .map_err(|e| { + eprintln!("Ratings fetch error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + + let ratings = rows.into_iter().map(|row| { + RatingInfoWithSlot { + slot: row.slot as i8, + rating: RatingInfo { + total_value: row.total_value.unwrap_or(0), + count: row.count as u32, + initial_value: row.initial_value.unwrap_or(0), + }, + } + }).collect(); + + Ok(ratings) +} + +async fn get_object_info_by_data_id(data_id: u64, password: u64) -> Result { + check_object_availability(data_id, password).await?; + + let row = sqlx::query!( + r#"SELECT data_id, owner, size, name, data_type, meta_binary, + permission, permission_recipients, delete_permission, delete_permission_recipients, + period, refer_data_id, flag, tags, creation_date, update_date + FROM datastore.objects WHERE data_id = $1"#, + data_id as i64 + ) + .fetch_optional(get_db()) + .await + .map_err(|_| ErrorCode::DataStore_SystemFileError)? + .ok_or(ErrorCode::DataStore_NotFound)?; + + let ratings = get_object_ratings(data_id, password).await?; + + Ok(map_row_to_meta_info( + row.data_id, + row.owner.unwrap_or(0), + row.size.unwrap_or(0), + row.name.unwrap_or_default(), + row.data_type.unwrap_or(0) as i16, + row.meta_binary.unwrap_or_default(), + row.permission.unwrap_or(0) as i16, + row.permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.delete_permission.unwrap_or(0) as i16, + row.delete_permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.period.unwrap_or(0) as i16, + row.refer_data_id.unwrap_or(0), + row.flag.unwrap_or(0), + row.tags.unwrap_or_default(), + row.creation_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + row.update_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + ratings + )) +} + +async fn get_object_info_by_persistence_target(target: PersistenceTarget, password: u64) -> Result { + let row = sqlx::query!( + r#"SELECT data_id, owner, size, name, data_type, meta_binary, + permission, permission_recipients, delete_permission, delete_permission_recipients, + period, refer_data_id, flag, tags, creation_date, update_date, + access_password, under_review + FROM datastore.objects + WHERE owner = $1 AND persistence_slot_id = $2 + AND upload_completed = TRUE AND deleted = FALSE"#, + target.owner as i32, + target.persistence_slot_id as i16 + ) + .fetch_optional(get_db()) + .await + .map_err(|_| ErrorCode::DataStore_SystemFileError)? + .ok_or(ErrorCode::DataStore_NotFound)?; + + let db_password = row.access_password as u64; + if db_password != 0 && db_password != password { + return Err(ErrorCode::DataStore_InvalidPassword); + } + + if row.under_review { + return Err(ErrorCode::DataStore_UnderReviewing); + } + + let ratings = get_object_ratings(row.data_id as u64, password).await?; + + Ok(map_row_to_meta_info( + row.data_id, + row.owner.unwrap_or(0), + row.size.unwrap_or(0), + row.name.unwrap_or_default(), + row.data_type.unwrap_or(0) as i16, + row.meta_binary.unwrap_or_default(), + row.permission.unwrap_or(0) as i16, + row.permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.delete_permission.unwrap_or(0) as i16, + row.delete_permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.period.unwrap_or(0) as i16, + row.refer_data_id.unwrap_or(0), + row.flag.unwrap_or(0), + row.tags.unwrap_or_default(), + row.creation_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + row.update_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + ratings + )) +} + +async fn get_buffer_queues_by_data_id_and_slot( + data_id: u64, + slot: u32 +) -> Result, ErrorCode> { + check_object_availability(data_id, 0).await?; + + let rows = sqlx::query!( + r#" + SELECT buffer + FROM datastore.buffer_queues + WHERE data_id = $1 AND slot = $2 + ORDER BY creation_date ASC + "#, + data_id as i64, + slot as i32 + ) + .fetch_all(get_db()) + .await + .map_err(|e| { + log::error!("Buffer queue fetch error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + + let buffer_queues = rows + .into_iter() + .map(|row| QBuffer(row.buffer)) + .collect(); + + Ok(buffer_queues) +} + +fn verify_object_permission( + owner_id: u32, + viewer_id: u32, + permission: &Permission, +) -> Result<(), ErrorCode> { + if owner_id == viewer_id { + return Ok(()); + } + + match permission.permission { + 0 => Ok(()), // All can read + 1 => Err(ErrorCode::DataStore_PermissionDenied), // Friends only, unimplemented + 2 => { + // Recipient IDs can read + if permission.recipient_ids.contains(&viewer_id) { + Ok(()) + } else { + Err(ErrorCode::DataStore_PermissionDenied) + } + } + 3 => Err(ErrorCode::DataStore_PermissionDenied), // Owner only, redundant + _ => Err(ErrorCode::DataStore_InvalidArgument), // ??? haxx0r + } +} + +fn filter_properties_by_result_option( + meta_info: &mut GetMetaInfo, + result_option: u8, +) { + if (result_option & 0x01) == 0 { + meta_info.meta_binary = QBuffer(Vec::new()); + } + + if (result_option & 0x04) == 0 { + meta_info.ratings = Vec::new(); + } + + // No idea what the other things do. :shrug: +} + +// Dawg... +async fn get_custom_rankings_by_data_ids( + application_id: u32, + data_ids: Vec +) -> Vec { + let mut results = Vec::with_capacity(data_ids.len()); + + let rows = sqlx::query!( + r#" + SELECT + rankings.data_id, + rankings.value + FROM datastore.object_custom_rankings rankings + JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord) + ON rankings.data_id = rows.data_id + AND rankings.application_id = $2 + ORDER BY rows.ord + "#, + &data_ids.iter().map(|&id| id as i64).collect::>(), + application_id as i32 + ) + .fetch_all(get_db()) + .await; + + let rows = match rows { + Ok(r) => r, + Err(e) => { + log::error!("Custom ranking query error: {:?}", e); + return results; + } + }; + + for row in rows { + let data_id = row.data_id as u64; + let score = row.value.unwrap_or(0) as u32; + + if let Ok(meta) = get_object_info_by_data_id(data_id, 0).await { + results.push(DataStoreCustomRankingResult { + score, + meta_info: meta, + }); + } else { + log::warn!("Could not find metadata for ranked object {}", data_id); + } + } + + results +} impl DataStore for User { - async fn get_meta(&self, metaparam: GetMetaParam) -> Result { - println!("dataid: {}", metaparam.dataid); - println!("access password: {}", metaparam.access_password); + async fn get_meta(&self, mut metaparam: GetMetaParam) -> Result { + let mut meta_info = if metaparam.dataid != 0 { + get_object_info_by_data_id(metaparam.dataid, metaparam.access_password).await? + } else { + get_object_info_by_persistence_target(metaparam.persistence_target, metaparam.access_password).await? + }; - // just trying to see what methods it tries to use - Err(ErrorCode::DataStore_NotFound) + let current_pid = self.pid; + verify_object_permission(meta_info.owner, current_pid, &meta_info.permission)?; + + filter_properties_by_result_option(&mut meta_info, metaparam.result_option); + + Ok(meta_info) } async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result { - // Prepare your arrays first (Postgres needs i32, not u32) let recipient_ids: Vec = postparam.permission.recipient_ids.iter().map(|&id| id as i32).collect(); let del_recipient_ids: Vec = postparam.del_permission.recipient_ids.iter().map(|&id| id as i32).collect(); let now = time::OffsetDateTime::now_utc(); @@ -46,7 +384,7 @@ impl DataStore for User { postparam.size as i32, postparam.name, postparam.data_type as i32, - &postparam.meta_binary.0, // unwrap QBuffer to &[u8] + &postparam.meta_binary.0, postparam.permission.permission as i32, &recipient_ids, postparam.del_permission.permission as i32, @@ -91,15 +429,78 @@ impl DataStore for User { } async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode> { - // whatever - println!("dataid: {}", completeparam.dataid); - println!("succeeded?: {}", completeparam.success); + let record = sqlx::query!( + r#"SELECT owner, under_review FROM datastore.objects WHERE data_id = $1"#, + completeparam.dataid as i64 + ) + .fetch_optional(get_db()) + .await + .map_err(|e| { + eprintln!("select error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + + let record = record.ok_or(ErrorCode::DataStore_NotFound)?; + + if record.under_review { + return Err(ErrorCode::DataStore_UnderReviewing); + } + + if record.owner.unwrap_or(0) as u32 != self.pid { + return Err(ErrorCode::DataStore_PermissionDenied); + } + + if completeparam.success { + sqlx::query!( + r#"UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1"#, + completeparam.dataid as i64 + ) + .execute(get_db()) + .await + .map_err(|e| { + eprintln!("update error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + } else { + return Err(ErrorCode::Transport_TemporaryServerError); + } Ok(()) } async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode> { - // this returns nothing + for param in rankingparam { + let exists = sqlx::query_scalar!( + r#"SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)"#, + param.dataid as i64 + ) + .fetch_one(get_db()) + .await + .map_err(|_| ErrorCode::DataStore_SystemFileError)?; + + if !exists.unwrap_or(false) { + return Err(ErrorCode::DataStore_NotFound); + } + + sqlx::query!( + r#" + INSERT INTO datastore.object_custom_rankings (data_id, application_id, value) + VALUES ($1, $2, $3) + ON CONFLICT (data_id, application_id) + DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value + "#, + param.dataid as i64, + param.appid as i32, + param.score as i32 + ) + .execute(get_db()) + .await + .map_err(|e| { + log::error!("update/insert error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + } + Ok(()) } @@ -138,4 +539,44 @@ impl DataStore for User { Ok(config) } + + async fn get_custom_ranking_by_data_id( + &self, + param: DataStoreGetCustomRankingByDataIDParam + ) -> Result<(Vec, Vec), ErrorCode> { + + let mut ranking_results = get_custom_rankings_by_data_ids(param.application_id, param.data_id_list).await; + + let mut q_results = Vec::with_capacity(ranking_results.len()); + + for result in &mut ranking_results { + if (param.result_option & 0x01) == 0 { + result.meta_info.tags = Vec::new(); + } + + if (param.result_option & 0x02) == 0 { + result.meta_info.ratings = Vec::new(); + } + + if (param.result_option & 0x04) == 0 { + result.meta_info.meta_binary = QBuffer(Vec::new()); + } + + if (param.result_option & 0x20) == 0 { + result.score = 0; + } + + q_results.push(QResult::success(ErrorCode::Core_Unknown)); + } + + Ok((ranking_results, q_results)) + } + + async fn get_buffer_queue(&self, param: BufferQueueParam) -> Result, ErrorCode> { + // log::info!("GetBufferQueue: dataid={}, slot={}", param.dataid, param.slot); + + let buffers = get_buffer_queues_by_data_id_and_slot(param.dataid, param.slot).await?; + + Ok(buffers) + } } \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs index 3899f93..00e522f 100644 --- a/rnex-core/src/rmc/protocols/datastore.rs +++ b/rnex-core/src/rmc/protocols/datastore.rs @@ -1,11 +1,11 @@ use macros::{method_id, rmc_proto, RmcSerialize, rmc_struct}; use rnex_core::rmc::structures::qbuffer::QBuffer; use rnex_core::rmc::response::ErrorCode; - +use rnex_core::rmc::structures::qresult::QResult; use rnex_core::kerberos::KerberosDateTime; use rnex_core::PID; -#[derive(RmcSerialize, Clone)] +#[derive(RmcSerialize, Clone, Debug)] #[rmc_struct(0)] pub struct PersistenceTarget { pub owner: PID, @@ -152,6 +152,23 @@ pub struct BufferQueueParam { pub slot: u32, } +// I just realized I forgot to add "DataStore" in front of the structs. I can't be assed to change it, sucks to be you lol. + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct DataStoreGetCustomRankingByDataIDParam { + pub application_id: u32, + pub data_id_list: Vec, + pub result_option: u8, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct DataStoreCustomRankingResult { + pub score: u32, + pub meta_info: GetMetaInfo, +} + #[rmc_proto(115)] pub trait DataStore{ #[method_id(8)] @@ -164,4 +181,8 @@ pub trait DataStore{ async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode>; #[method_id(61)] async fn get_application_config(&self, appid: u32) -> Result, ErrorCode>; + #[method_id(50)] + async fn get_custom_ranking_by_data_id(&self, param: DataStoreGetCustomRankingByDataIDParam) -> Result<(Vec, Vec), ErrorCode>; + #[method_id(54)] + async fn get_buffer_queue(&self, param: BufferQueueParam) -> Result, ErrorCode>; } \ No newline at end of file From 08fac7af039d8b9850b649fcfff228320b75a3d8 Mon Sep 17 00:00:00 2001 From: red binder Date: Mon, 20 Apr 2026 14:06:04 +0200 Subject: [PATCH 13/19] Even more work on datastore --- ...b44a630eb066846c777c462b8c9341e26b696.json | 38 --- ...d3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json | 28 --- ...077f9b06ffe11cab2693e4e365c265f8e2418.json | 125 ---------- ...88d2d26f7644e85bfd65423e6e32c469e3695.json | 16 -- ...b8158ea907d36588e1e59f6cbe752d89361bb.json | 22 -- ...f7803ee88233c53efaa2df9966a6c72c8c763.json | 23 -- ...a4beaf37e879c28c81c22abeddb3d030535df.json | 28 --- ...8be8946430d93821dbccb6dc9324ef0544c17.json | 29 --- ...1d9f4ef96adbdab7ca7d008acf596af91fc2b.json | 112 --------- ...e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json | 40 ---- ...fe18e500d243f1b55fd18e7d96d281605bcf9.json | 14 -- Cargo.lock | 1 + rnex-core/Cargo.toml | 1 + rnex-core/src/nex/datastore.rs | 226 ++++++++++++++++-- rnex-core/src/nex/s3presigner.rs | 44 ++++ rnex-core/src/rmc/protocols/datastore.rs | 64 ++++- rnex-core/src/rmc/protocols/ranking.rs | 9 +- rnex-core/src/rmc/structures/mod.rs | 1 + rnex-core/src/rmc/structures/qbuffer.rs | 2 +- rnex-core/src/rmc/structures/resultsrange.rs | 8 + 20 files changed, 327 insertions(+), 504 deletions(-) delete mode 100644 .sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json delete mode 100644 .sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json delete mode 100644 .sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json delete mode 100644 .sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json delete mode 100644 .sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json delete mode 100644 .sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json delete mode 100644 .sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json delete mode 100644 .sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json delete mode 100644 .sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json delete mode 100644 .sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json delete mode 100644 .sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json create mode 100644 rnex-core/src/rmc/structures/resultsrange.rs diff --git a/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json b/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json deleted file mode 100644 index f91446a..0000000 --- a/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "data_id", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int4", - "Int4", - "Text", - "Int4", - "Bytea", - "Int4", - "Int4Array", - "Int4", - "Int4Array", - "Int4", - "Int4", - "Int8", - "TextArray", - "Int4", - "TextArray", - "Timestamp", - "Timestamp" - ] - }, - "nullable": [ - false - ] - }, - "hash": "039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696" -} diff --git a/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json b/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json deleted file mode 100644 index abf5c03..0000000 --- a/.sqlx/query-164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT owner, under_review FROM datastore.objects WHERE data_id = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "owner", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "under_review", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - true, - false - ] - }, - "hash": "164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9" -} diff --git a/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json b/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json deleted file mode 100644 index 7471873..0000000 --- a/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "data_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "owner", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "size", - "type_info": "Int4" - }, - { - "ordinal": 3, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "data_type", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "meta_binary", - "type_info": "Bytea" - }, - { - "ordinal": 6, - "name": "permission", - "type_info": "Int4" - }, - { - "ordinal": 7, - "name": "permission_recipients", - "type_info": "Int4Array" - }, - { - "ordinal": 8, - "name": "delete_permission", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "delete_permission_recipients", - "type_info": "Int4Array" - }, - { - "ordinal": 10, - "name": "period", - "type_info": "Int4" - }, - { - "ordinal": 11, - "name": "refer_data_id", - "type_info": "Int8" - }, - { - "ordinal": 12, - "name": "flag", - "type_info": "Int4" - }, - { - "ordinal": 13, - "name": "tags", - "type_info": "TextArray" - }, - { - "ordinal": 14, - "name": "creation_date", - "type_info": "Timestamp" - }, - { - "ordinal": 15, - "name": "update_date", - "type_info": "Timestamp" - }, - { - "ordinal": 16, - "name": "access_password", - "type_info": "Int8" - }, - { - "ordinal": 17, - "name": "under_review", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Int4", - "Int4" - ] - }, - "nullable": [ - false, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - false, - false - ] - }, - "hash": "18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418" -} diff --git a/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json b/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json deleted file mode 100644 index 5411a38..0000000 --- a/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int8", - "Int8" - ] - }, - "nullable": [] - }, - "hash": "29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695" -} diff --git a/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json b/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json deleted file mode 100644 index 83246ca..0000000 --- a/.sqlx/query-2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "exists", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - null - ] - }, - "hash": "2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb" -} diff --git a/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json b/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json deleted file mode 100644 index 7a1cc6f..0000000 --- a/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "buffer", - "type_info": "Bytea" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int4" - ] - }, - "nullable": [ - false - ] - }, - "hash": "48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763" -} diff --git a/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json b/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json deleted file mode 100644 index 4f07b49..0000000 --- a/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "under_review", - "type_info": "Bool" - }, - { - "ordinal": 1, - "name": "access_password", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - false - ] - }, - "hash": "60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df" -} diff --git a/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json b/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json deleted file mode 100644 index 867701f..0000000 --- a/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "data_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "value", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8Array", - "Int8" - ] - }, - "nullable": [ - false, - true - ] - }, - "hash": "8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17" -} diff --git a/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json b/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json deleted file mode 100644 index 539fdeb..0000000 --- a/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "data_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "owner", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "size", - "type_info": "Int4" - }, - { - "ordinal": 3, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "data_type", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "meta_binary", - "type_info": "Bytea" - }, - { - "ordinal": 6, - "name": "permission", - "type_info": "Int4" - }, - { - "ordinal": 7, - "name": "permission_recipients", - "type_info": "Int4Array" - }, - { - "ordinal": 8, - "name": "delete_permission", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "delete_permission_recipients", - "type_info": "Int4Array" - }, - { - "ordinal": 10, - "name": "period", - "type_info": "Int4" - }, - { - "ordinal": 11, - "name": "refer_data_id", - "type_info": "Int8" - }, - { - "ordinal": 12, - "name": "flag", - "type_info": "Int4" - }, - { - "ordinal": 13, - "name": "tags", - "type_info": "TextArray" - }, - { - "ordinal": 14, - "name": "creation_date", - "type_info": "Timestamp" - }, - { - "ordinal": 15, - "name": "update_date", - "type_info": "Timestamp" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true - ] - }, - "hash": "a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b" -} diff --git a/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json b/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json deleted file mode 100644 index 095ca6f..0000000 --- a/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "slot", - "type_info": "Int2" - }, - { - "ordinal": 1, - "name": "total_value", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "count", - "type_info": "Int4" - }, - { - "ordinal": 3, - "name": "initial_value", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - true, - false, - true - ] - }, - "hash": "c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa" -} diff --git a/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json b/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json deleted file mode 100644 index 552f92a..0000000 --- a/.sqlx/query-e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [] - }, - "hash": "e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9" -} diff --git a/Cargo.lock b/Cargo.lock index 8fd84b8..bf83871 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2225,6 +2225,7 @@ dependencies = [ "tokio", "typenum", "ureq", + "urlencoding", "v-byte-helpers", ] diff --git a/rnex-core/Cargo.toml b/rnex-core/Cargo.toml index 646b65e..620357b 100644 --- a/rnex-core/Cargo.toml +++ b/rnex-core/Cargo.toml @@ -33,6 +33,7 @@ aws-sdk-s3 = { version = "1.129.0", optional = true } aws-config = { version = "1.8.15", optional = true } base64 = "0.22.1" sha2 = "0.10.9" +urlencoding = "2.1.3" [dev-dependencies] # criterion = "0.7.0" diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 19db2b4..498a75d 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -10,7 +10,7 @@ use rnex_core::nex::remote_console::RemoteConsole; use rnex_core::nex::s3presigner::S3Presigner; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure}; -use rnex_core::rmc::protocols::datastore::{BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, DataStoreGetCustomRankingByDataIDParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, RateCustomRankingParam, RatingInfo, RatingInfoWithSlot}; +use rnex_core::rmc::protocols::datastore::{BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, DataStoreGetCustomRankingByDataIDParam, DataStorePrepareGetParam, DataStoreReqGetInfo, DataStoreSearchParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, RateCustomRankingParam, RatingInfo, RatingInfoWithSlot}; use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; use crate::nex::user::User; use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT, get_db}; @@ -336,6 +336,7 @@ async fn get_custom_rankings_by_data_ids( if let Ok(meta) = get_object_info_by_data_id(data_id, 0).await { results.push(DataStoreCustomRankingResult { + order: 0, score, meta_info: meta, }); @@ -347,6 +348,70 @@ async fn get_custom_rankings_by_data_ids( results } +async fn get_user_course_object_ids(owner_pid: u32) -> Result, ErrorCode> { + let rows = sqlx::query!( + r#" + SELECT data_id + FROM datastore.objects + WHERE owner = $1 AND data_type > 2 AND data_type < 50 + "#, + owner_pid as i64 + ) + .fetch_all(get_db()) + .await + .map_err(|e| { + log::error!("error fetching course IDs for PID {}: {:?}", owner_pid, e); + ErrorCode::DataStore_SystemFileError + })?; + + let mut valid_ids = Vec::new(); + for row in rows { + let data_id = row.data_id as u64; + // always check avail + if check_object_availability(data_id, 0).await.is_ok() { + valid_ids.push(data_id); + } + } + + Ok(valid_ids) +} + +fn get_blacklist_1() -> Vec { + vec![ + "けされ", "消され", "削除され", "リセットされ", "BANされ", "BANされ", + "キミのコース", "君のコース", "きみのコース", "い い ね", "遊びます", "地震", + "震災", "被災", "津波", "バンされ", "い~ね", "震度", "じしん", "banされ", + "くわしくは", "詳しくは", "ちんちん", "ち0こ", "bicth", "い.い.ね", + "ナイ~ス", "い&い", "い-いね", "いぃね", "nigger", "ngger", "star if u", + "Star if u", "Star if you", "star if you", "PENlS", "マンコ", "butthole", + "LILI", "vagina", "vagyna", "うんち", "うんこ", "ウンコ", "Iine", + "EENE", "まんこ", "ウンチ", "niglet", "nigglet", "please like", "きんたま", + "Butthole", "llね", "iいね", "give a star", "ちんぽ", "亀頭", "penis", + "ウンコ", "plz more stars", "star plz", "い()ね", "PLEASE star", "Bitte Sterne", + ].into_iter().map(String::from).collect() +} + +fn get_blacklist_2() -> Vec { + vec![ + "ゼロから", "0から", "0から", "い  い  ね", "いい", "東日本", "大震", + ].into_iter().map(String::from).collect() +} + +fn get_blacklist_3() -> Vec { + vec![ + "いいね", "下さい", "ください", "押して", "おして", "返す", "かえす", + "星", "してくれ", "するよ", "☆くれたら", "☆あげます", "★くれたら", + "★あげます", "しね", "ころす", "ころされた", "アナル", "ファック", + "キンタマ", "○ね", "キチガイ", "うんこ", "KITIGAI", "金玉", "おっぱい", + "☆おす", "☆押す", "★おす", "★押す", "いいする", "いいよ", "イイネ", + "ケツ", "うんち", "かくせいざい", "覚せい剤", "シャブ", "きんたま", + "ちんちん", "おしっこ", "ちんぽこ", "ころして", "グッド", "グット", + "レ●プ", "バーカ", "きちがい", "ちんげ", "マンコ", "まんこ", "チンポ", + "クズ", "ウンコ", "ナイスおねがいします", "penis", "イイね", "☆よろ", + "ナイス!して", "ま/んこ", "まん/こ", + ].into_iter().map(String::from).collect() +} + impl DataStore for User { async fn get_meta(&self, mut metaparam: GetMetaParam) -> Result { let mut meta_info = if metaparam.dataid != 0 { @@ -429,6 +494,9 @@ impl DataStore for User { } async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode> { + log::info!("Data ID: {:?}", completeparam.dataid); + log::info!("Success: {:?}", completeparam.success); + let record = sqlx::query!( r#"SELECT owner, under_review FROM datastore.objects WHERE data_id = $1"#, completeparam.dataid as i64 @@ -469,10 +537,10 @@ impl DataStore for User { } async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode> { - for param in rankingparam { + for abcparam in rankingparam { let exists = sqlx::query_scalar!( r#"SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)"#, - param.dataid as i64 + abcparam.dataid as i64 ) .fetch_one(get_db()) .await @@ -489,9 +557,9 @@ impl DataStore for User { ON CONFLICT (data_id, application_id) DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value "#, - param.dataid as i64, - param.appid as i32, - param.score as i32 + abcparam.dataid as i64, + abcparam.appid as i32, + abcparam.score as i32 ) .execute(get_db()) .await @@ -542,27 +610,30 @@ impl DataStore for User { async fn get_custom_ranking_by_data_id( &self, - param: DataStoreGetCustomRankingByDataIDParam + custom_ranking_param: DataStoreGetCustomRankingByDataIDParam ) -> Result<(Vec, Vec), ErrorCode> { + println!("appid: {:?}", custom_ranking_param.application_id); + println!("dataid list: {:?}", custom_ranking_param.data_id_list); + println!("result option: {:?}", custom_ranking_param.result_option); - let mut ranking_results = get_custom_rankings_by_data_ids(param.application_id, param.data_id_list).await; + let mut ranking_results = get_custom_rankings_by_data_ids(custom_ranking_param.application_id, custom_ranking_param.data_id_list).await; let mut q_results = Vec::with_capacity(ranking_results.len()); for result in &mut ranking_results { - if (param.result_option & 0x01) == 0 { + if (custom_ranking_param.result_option & 0x01) == 0 { result.meta_info.tags = Vec::new(); } - if (param.result_option & 0x02) == 0 { + if (custom_ranking_param.result_option & 0x02) == 0 { result.meta_info.ratings = Vec::new(); } - if (param.result_option & 0x04) == 0 { + if (custom_ranking_param.result_option & 0x04) == 0 { result.meta_info.meta_binary = QBuffer(Vec::new()); } - if (param.result_option & 0x20) == 0 { + if (custom_ranking_param.result_option & 0x20) == 0 { result.score = 0; } @@ -572,11 +643,138 @@ impl DataStore for User { Ok((ranking_results, q_results)) } - async fn get_buffer_queue(&self, param: BufferQueueParam) -> Result, ErrorCode> { + async fn get_buffer_queue(&self, bufferparam: BufferQueueParam) -> Result, ErrorCode> { // log::info!("GetBufferQueue: dataid={}, slot={}", param.dataid, param.slot); - let buffers = get_buffer_queues_by_data_id_and_slot(param.dataid, param.slot).await?; + let buffers = get_buffer_queues_by_data_id_and_slot(bufferparam.dataid, bufferparam.slot).await?; Ok(buffers) } + + async fn prepare_get_object(&self, prepare_get_param: DataStorePrepareGetParam) -> Result { + let meta_info = if prepare_get_param.dataid != 0 { + get_object_info_by_data_id(prepare_get_param.dataid, prepare_get_param.access_password).await? + } else { + get_object_info_by_persistence_target(prepare_get_param.persistence_target, prepare_get_param.access_password).await? + }; + + verify_object_permission(meta_info.owner, self.pid, &meta_info.permission)?; + + let presigner = S3Presigner::new( + &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), + format!("{}", *RNEX_DATASTORE_S3_BUCKET) + ).await; + + let key = format!("data/{}.bin", meta_info.dataid); + let download_url = presigner.generate_presigned_get(&key); + + Ok(DataStoreReqGetInfo { + url: download_url, + request_headers: vec![], + size: meta_info.size, + root_ca_cert: vec![], + dataid: meta_info.dataid, + }) + } + + async fn followings_latest_course_search_object( + &self, + course_search_param: DataStoreSearchParam, + _extra_data: Vec + ) -> Result, ErrorCode> { + let mut all_results = Vec::new(); + + for &owner_pid in &course_search_param.owner_ids { + let course_ids = get_user_course_object_ids(owner_pid).await?; + + if course_ids.is_empty() { + continue; + } + + let mut results = get_custom_rankings_by_data_ids(0, course_ids).await; + + // Flag 0x1: Return Tags + // Flag 0x2: Return Ratings + // Flag 0x4: Return MetaBinary + // Flag 0x20: Return Score + for res in &mut results { + if course_search_param.result_option & 0x1 == 0 { + res.meta_info.tags = Vec::new(); + } + if course_search_param.result_option & 0x2 == 0 { + res.meta_info.ratings = Vec::new(); + } + if course_search_param.result_option & 0x4 == 0 { + res.meta_info.meta_binary = rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); + } + if course_search_param.result_option & 0x20 == 0 { + res.score = 0; + } + } + + all_results.extend(results); + } + + // note: we assume the client sorts the data lol + + Ok(all_results) + } + + async fn get_application_config_string(&self, application_id: u32) -> Result, ErrorCode> { + let config = match application_id { + 128 => get_blacklist_1(), + 129 => get_blacklist_2(), + 130 => get_blacklist_3(), + _ => { + log::warn!("unsupported application_id in GetApplicationConfigString: {}", application_id); + Vec::new() + } + }; + + Ok(config) + } + + async fn get_metas_multiple_param( + &self, + params: Vec + ) -> Result<(Vec, Vec), ErrorCode> { + let mut metas = Vec::with_capacity(params.len()); + let mut results = Vec::with_capacity(params.len()); + + for param in params { + let info_result = if param.dataid != 0 { + get_object_info_by_data_id(param.dataid, param.access_password).await + } else { + get_object_info_by_persistence_target(param.persistence_target, param.access_password).await + }; + + match info_result { + Ok(mut meta) => { + if let Err(e) = verify_object_permission(meta.owner, self.pid, &meta.permission) { + metas.push(GetMetaInfo::default()); + results.push(QResult::error(e)); + } else { + if param.result_option & 0x1 == 0 { + meta.tags = Vec::new(); + } + if param.result_option & 0x2 == 0 { + meta.ratings = Vec::new(); + } + if param.result_option & 0x4 == 0 { + meta.meta_binary = rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); + } + + metas.push(meta); + results.push(QResult::success(ErrorCode::Core_Unknown)); + } + } + Err(e) => { + metas.push(GetMetaInfo::default()); + results.push(QResult::error(e)); + } + } + } + + Ok((metas, results)) + } } \ No newline at end of file diff --git a/rnex-core/src/nex/s3presigner.rs b/rnex-core/src/nex/s3presigner.rs index 169293b..afe61d4 100644 --- a/rnex-core/src/nex/s3presigner.rs +++ b/rnex-core/src/nex/s3presigner.rs @@ -56,6 +56,50 @@ impl S3Presigner { (url, fields) } + pub fn generate_presigned_get(&self, key: &str) -> String { + let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key"); + let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key"); + let region = "us-east-1"; + let date_short = Utc::now().format("%Y%m%d").to_string(); + let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string(); + + let credential_scope = format!("{}/{}/s3/aws4_request", date_short, region); + + let query_string = format!( + "X-Amz-Algorithm=AWS4-HMAC-SHA256&\ + X-Amz-Credential={}%2F{}&\ + X-Amz-Date={}&\ + X-Amz-Expires=900&\ + X-Amz-SignedHeaders=host", + access_key, + urlencoding::encode(&credential_scope), + date_full + ); + + let canonical_request = format!( + "GET\n/{}/{}\n{}\nhost:{}\n\nhost\nUNSIGNED-PAYLOAD", + self.bucket, key, query_string, *RNEX_DATASTORE_S3_ENDPOINT + ); + + let hashed_request = hex::encode(Sha256::digest(canonical_request.as_bytes())); + + let string_to_sign = format!( + "AWS4-HMAC-SHA256\n{}\n{}\n{}", + date_full, credential_scope, hashed_request + ); + + let k_date = self.hmac_sha256(format!("AWS4{}", secret_key).as_bytes(), &date_short); + let k_region = self.hmac_sha256(&k_date, region); + let k_service = self.hmac_sha256(&k_region, "s3"); + let k_signing = self.hmac_sha256(&k_service, "aws4_request"); + let signature = hex::encode(self.hmac_sha256(&k_signing, &string_to_sign)); + + format!( + "https://{}/{}/{}?{}&X-Amz-Signature={}", + *RNEX_DATASTORE_S3_ENDPOINT, self.bucket, key, query_string, signature + ) + } + fn calculate_signature(&self, secret: &str, date: &str, region: &str, policy: &str) -> String { let k_date = self.hmac_sha256(format!("AWS4{}", secret).as_bytes(), date); let k_region = self.hmac_sha256(&k_date, region); diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs index 00e522f..0c68fc5 100644 --- a/rnex-core/src/rmc/protocols/datastore.rs +++ b/rnex-core/src/rmc/protocols/datastore.rs @@ -4,15 +4,16 @@ use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::qresult::QResult; use rnex_core::kerberos::KerberosDateTime; use rnex_core::PID; +use rnex_core::rmc::structures::resultsrange::ResultsRange; -#[derive(RmcSerialize, Clone, Debug)] +#[derive(RmcSerialize, Clone, Debug, Default)] #[rmc_struct(0)] pub struct PersistenceTarget { pub owner: PID, pub persistence_slot_id: u16, } -#[derive(RmcSerialize, Clone, Debug)] +#[derive(RmcSerialize, Clone, Debug, Default)] #[rmc_struct(0)] pub struct Permission { pub permission: u8, @@ -34,7 +35,7 @@ pub struct RatingInfo { pub initial_value: i64, } -#[derive(RmcSerialize, Clone)] +#[derive(RmcSerialize, Clone, Default)] #[rmc_struct(0)] pub struct GetMetaParam { pub dataid: u64, @@ -43,7 +44,7 @@ pub struct GetMetaParam { pub access_password: u64, } -#[derive(RmcSerialize, Clone)] +#[derive(RmcSerialize, Clone, Default)] #[rmc_struct(0)] pub struct GetMetaInfo { pub dataid: u64, @@ -165,14 +166,59 @@ pub struct DataStoreGetCustomRankingByDataIDParam { #[derive(RmcSerialize, Clone)] #[rmc_struct(0)] pub struct DataStoreCustomRankingResult { + pub order: u32, pub score: u32, pub meta_info: GetMetaInfo, } +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct DataStorePrepareGetParam { + pub dataid: u64, + pub lockid: u32, + pub persistence_target: PersistenceTarget, + pub access_password: u64, + pub extra_data: Vec, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(0)] +pub struct DataStoreReqGetInfo { + pub url: String, + pub request_headers: Vec, + pub size: u32, + pub root_ca_cert: Vec, + pub dataid: u64, +} + +#[derive(RmcSerialize, Clone)] +#[rmc_struct(1)] +pub struct DataStoreSearchParam { + pub search_target: u8, + pub owner_ids: Vec, + pub owner_type: u8, + pub destination_ids: Vec, + pub data_type: u16, + pub created_after: KerberosDateTime, + pub created_before: KerberosDateTime, + pub updated_after: KerberosDateTime, + pub updated_before: KerberosDateTime, + pub refer_dat_id: u32, + pub tags: Vec, + pub result_order_column: u8, + pub result_order: u8, + pub result_range: ResultsRange, + pub result_option: u8, + pub minimal_rating_frequency: u32, + pub use_cache: bool, +} + #[rmc_proto(115)] pub trait DataStore{ #[method_id(8)] async fn get_meta(&self, metaparam: GetMetaParam) -> Result; + #[method_id(36)] + async fn get_metas_multiple_param(&self, params: Vec) -> Result<(Vec, Vec), ErrorCode>; #[method_id(24)] async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result; #[method_id(26)] @@ -182,7 +228,13 @@ pub trait DataStore{ #[method_id(61)] async fn get_application_config(&self, appid: u32) -> Result, ErrorCode>; #[method_id(50)] - async fn get_custom_ranking_by_data_id(&self, param: DataStoreGetCustomRankingByDataIDParam) -> Result<(Vec, Vec), ErrorCode>; + async fn get_custom_ranking_by_data_id(&self, custom_ranking_param: DataStoreGetCustomRankingByDataIDParam) -> Result<(Vec, Vec), ErrorCode>; #[method_id(54)] - async fn get_buffer_queue(&self, param: BufferQueueParam) -> Result, ErrorCode>; + async fn get_buffer_queue(&self, bufferparam: BufferQueueParam) -> Result, ErrorCode>; + #[method_id(25)] + async fn prepare_get_object(&self, prepare_get_param: DataStorePrepareGetParam) -> Result; + #[method_id(65)] + async fn followings_latest_course_search_object(&self, course_search_param: DataStoreSearchParam, extra_data: Vec) -> Result, ErrorCode>; + #[method_id(74)] + async fn get_application_config_string(&self, application_id: u32) -> Result, ErrorCode>; } \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/ranking.rs b/rnex-core/src/rmc/protocols/ranking.rs index b9dba06..53ec9af 100644 --- a/rnex-core/src/rmc/protocols/ranking.rs +++ b/rnex-core/src/rmc/protocols/ranking.rs @@ -2,17 +2,10 @@ use macros::{rmc_struct, rmc_proto, RmcSerialize, method_id}; use rnex_core::kerberos::KerberosDateTime; use rnex_core::rmc::structures::qbuffer::QBuffer; - +use rnex_core::rmc::structures::resultsrange::ResultsRange; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::ranking::UploadCompetitionData; -#[derive(RmcSerialize, Debug, Default, Clone)] -#[rmc_struct(0)] -pub struct ResultsRange{ - pub offset: u32, - pub size: u32 -} - #[derive(RmcSerialize, Debug, Default, Clone)] #[rmc_struct(1)] pub struct CompetitionRankingGetParam { diff --git a/rnex-core/src/rmc/structures/mod.rs b/rnex-core/src/rmc/structures/mod.rs index 996cc4b..459aeac 100644 --- a/rnex-core/src/rmc/structures/mod.rs +++ b/rnex-core/src/rmc/structures/mod.rs @@ -37,6 +37,7 @@ pub mod ranking; pub mod rmc_struct; pub mod string; pub mod variant; +pub mod resultsrange; pub trait RmcSerialize { fn serialize(&self, writer: &mut impl Write) -> Result<()>; diff --git a/rnex-core/src/rmc/structures/qbuffer.rs b/rnex-core/src/rmc/structures/qbuffer.rs index 2f7b23a..7f2aa7b 100644 --- a/rnex-core/src/rmc/structures/qbuffer.rs +++ b/rnex-core/src/rmc/structures/qbuffer.rs @@ -3,7 +3,7 @@ use bytemuck::bytes_of; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; use crate::rmc::structures::{Result, RmcSerialize}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct QBuffer(pub Vec); impl RmcSerialize for QBuffer{ diff --git a/rnex-core/src/rmc/structures/resultsrange.rs b/rnex-core/src/rmc/structures/resultsrange.rs new file mode 100644 index 0000000..ba62e49 --- /dev/null +++ b/rnex-core/src/rmc/structures/resultsrange.rs @@ -0,0 +1,8 @@ +use macros::RmcSerialize; + +#[derive(RmcSerialize, Debug, Default, Clone)] +#[rmc_struct(0)] +pub struct ResultsRange{ + pub offset: u32, + pub size: u32 +} \ No newline at end of file From 20ee0e20dc3ed9def60865aac0353fda2d20d946 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 21 Apr 2026 20:36:51 +0200 Subject: [PATCH 14/19] add super mario maker to CI --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 900885c..7b9a013 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,3 +24,7 @@ splatoon: friends: stage: build_and_test script: ./.ci-scripts/make-edition.sh friends + +super-mario-maker: + stage: build_and_test + script: ./.ci-scripts/make-edition.sh super-mario-maker From e5a0b374922887c8c99f888bd354050a95539280 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 21 Apr 2026 20:46:38 +0200 Subject: [PATCH 15/19] sqlx prepare --- ...0f608f018cb20125bf0ed30fdfb4319a14cf0.json | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json diff --git a/rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json b/rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json new file mode 100644 index 0000000..775d98d --- /dev/null +++ b/rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT data_id\n FROM datastore.objects\n WHERE owner = $1 AND data_type > 2 AND data_type < 50\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + false + ] + }, + "hash": "74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0" +} From 49dab174cc3aa2c2dbbf4adf5f352f91505f04fe Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 21 Apr 2026 21:00:13 +0200 Subject: [PATCH 16/19] revert build-edition to normal, and try to allow normal builds to succeed --- build-edition.sh | 4 +- ...b44a630eb066846c777c462b8c9341e26b696.json | 38 - ...f67d1812b99e1ec952a044fc03e1a5c63703.json} | 4 +- ...a1675439bb44c91158f8b8a696e326c45447c.json | 38 + ...57f27247530878b7f82feeb65802d995a38c4.json | 16 + ...88d2d26f7644e85bfd65423e6e32c469e3695.json | 16 - ...1a6a6c5c38acb06d91c5b0924c3f0a5d2e92.json} | 4 +- ...02e9186ce1dfc6c68b52d9d2a8a38f5c3a1f.json} | 4 +- ...8a7a9bf551126712c1d1089a4263453090e79.json | 29 + ...1340561031d8e5c91f46c041f83e54c31a7d.json} | 4 +- ...8be8946430d93821dbccb6dc9324ef0544c17.json | 29 - ...8f5eb4a3761dd71129ba6939cdd0d62569fb.json} | 4 +- ...cecccf8f0f8dd20d890a76acf85265b2192c.json} | 4 +- rnex-core/src/nex/datastore.rs | 1479 +++++++++-------- 14 files changed, 838 insertions(+), 835 deletions(-) delete mode 100644 rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json rename rnex-core/.sqlx/{query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json => query-1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703.json} (85%) create mode 100644 rnex-core/.sqlx/query-219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c.json create mode 100644 rnex-core/.sqlx/query-29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4.json delete mode 100644 rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json rename rnex-core/.sqlx/{query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json => query-37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92.json} (51%) rename rnex-core/.sqlx/{query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json => query-3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f.json} (50%) create mode 100644 rnex-core/.sqlx/query-8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79.json rename rnex-core/.sqlx/{query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json => query-8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d.json} (69%) delete mode 100644 rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json rename rnex-core/.sqlx/{query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json => query-93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb.json} (57%) rename rnex-core/.sqlx/{query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json => query-efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c.json} (81%) diff --git a/build-edition.sh b/build-edition.sh index d2c0750..5d65fc3 100755 --- a/build-edition.sh +++ b/build-edition.sh @@ -10,6 +10,4 @@ echo $EDITION_FEATURES echo ENV SETTINGS: env -#OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl -OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 cargo sqlx prepare --workspace -- --features "$EDITION_FEATURES" -OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 cargo build --release --features "$EDITION_FEATURES" +OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl diff --git a/rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json b/rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json deleted file mode 100644 index f91446a..0000000 --- a/rnex-core/.sqlx/query-039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "data_id", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int4", - "Int4", - "Text", - "Int4", - "Bytea", - "Int4", - "Int4Array", - "Int4", - "Int4Array", - "Int4", - "Int4", - "Int8", - "TextArray", - "Int4", - "TextArray", - "Timestamp", - "Timestamp" - ] - }, - "nullable": [ - false - ] - }, - "hash": "039d134f0d1b681b55b1394a710b44a630eb066846c777c462b8c9341e26b696" -} diff --git a/rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json b/rnex-core/.sqlx/query-1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703.json similarity index 85% rename from rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json rename to rnex-core/.sqlx/query-1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703.json index 539fdeb..befa7e1 100644 --- a/rnex-core/.sqlx/query-a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b.json +++ b/rnex-core/.sqlx/query-1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1", + "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1", "describe": { "columns": [ { @@ -108,5 +108,5 @@ true ] }, - "hash": "a5e86d7e66d0e16e5f35df883e11d9f4ef96adbdab7ca7d008acf596af91fc2b" + "hash": "1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703" } diff --git a/rnex-core/.sqlx/query-219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c.json b/rnex-core/.sqlx/query-219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c.json new file mode 100644 index 0000000..cf80412 --- /dev/null +++ b/rnex-core/.sqlx/query-219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c.json @@ -0,0 +1,38 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int4", + "Text", + "Int4", + "Bytea", + "Int4", + "Int4Array", + "Int4", + "Int4Array", + "Int4", + "Int4", + "Int8", + "TextArray", + "Int4", + "TextArray", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + false + ] + }, + "hash": "219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c" +} diff --git a/rnex-core/.sqlx/query-29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4.json b/rnex-core/.sqlx/query-29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4.json new file mode 100644 index 0000000..0c3393d --- /dev/null +++ b/rnex-core/.sqlx/query-29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4" +} diff --git a/rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json b/rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json deleted file mode 100644 index 5411a38..0000000 --- a/rnex-core/.sqlx/query-29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int8", - "Int8" - ] - }, - "nullable": [] - }, - "hash": "29e18f241dc860dca12c03cabb788d2d26f7644e85bfd65423e6e32c469e3695" -} diff --git a/rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json b/rnex-core/.sqlx/query-37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92.json similarity index 51% rename from rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json rename to rnex-core/.sqlx/query-37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92.json index 775d98d..35c78ee 100644 --- a/rnex-core/.sqlx/query-74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0.json +++ b/rnex-core/.sqlx/query-37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT data_id\n FROM datastore.objects\n WHERE owner = $1 AND data_type > 2 AND data_type < 50\n ", + "query": "\n SELECT data_id\n FROM datastore.objects\n WHERE owner = $1 AND data_type > 2 AND data_type < 50\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "74408b6923370db5de1589b62360f608f018cb20125bf0ed30fdfb4319a14cf0" + "hash": "37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92" } diff --git a/rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json b/rnex-core/.sqlx/query-3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f.json similarity index 50% rename from rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json rename to rnex-core/.sqlx/query-3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f.json index 7a1cc6f..166c25d 100644 --- a/rnex-core/.sqlx/query-48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763.json +++ b/rnex-core/.sqlx/query-3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ", + "query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ", "describe": { "columns": [ { @@ -19,5 +19,5 @@ false ] }, - "hash": "48d94383f1a261f19060f5c75d9f7803ee88233c53efaa2df9966a6c72c8c763" + "hash": "3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f" } diff --git a/rnex-core/.sqlx/query-8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79.json b/rnex-core/.sqlx/query-8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79.json new file mode 100644 index 0000000..dd1c783 --- /dev/null +++ b/rnex-core/.sqlx/query-8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "data_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "value", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8Array", + "Int8" + ] + }, + "nullable": [ + false, + true + ] + }, + "hash": "8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79" +} diff --git a/rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json b/rnex-core/.sqlx/query-8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d.json similarity index 69% rename from rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json rename to rnex-core/.sqlx/query-8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d.json index 095ca6f..dbab55e 100644 --- a/rnex-core/.sqlx/query-c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa.json +++ b/rnex-core/.sqlx/query-8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ", + "query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ", "describe": { "columns": [ { @@ -36,5 +36,5 @@ true ] }, - "hash": "c2a0ca72fdcb060a7fb1c670b25e1efdbf3cef31e4b6cea4adbd51ee0218f5aa" + "hash": "8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d" } diff --git a/rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json b/rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json deleted file mode 100644 index 867701f..0000000 --- a/rnex-core/.sqlx/query-8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "data_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "value", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8Array", - "Int8" - ] - }, - "nullable": [ - false, - true - ] - }, - "hash": "8909f81fbf26a9b559d26e138568be8946430d93821dbccb6dc9324ef0544c17" -} diff --git a/rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json b/rnex-core/.sqlx/query-93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb.json similarity index 57% rename from rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json rename to rnex-core/.sqlx/query-93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb.json index 4f07b49..0a8127b 100644 --- a/rnex-core/.sqlx/query-60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df.json +++ b/rnex-core/.sqlx/query-93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ", + "query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ", "describe": { "columns": [ { @@ -24,5 +24,5 @@ false ] }, - "hash": "60d8ebcf914d887439096df400fa4beaf37e879c28c81c22abeddb3d030535df" + "hash": "93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb" } diff --git a/rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json b/rnex-core/.sqlx/query-efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c.json similarity index 81% rename from rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json rename to rnex-core/.sqlx/query-efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c.json index 7471873..60714c0 100644 --- a/rnex-core/.sqlx/query-18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418.json +++ b/rnex-core/.sqlx/query-efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE", + "query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE", "describe": { "columns": [ { @@ -121,5 +121,5 @@ false ] }, - "hash": "18fb671d9d97353420446413b74077f9b06ffe11cab2693e4e365c265f8e2418" + "hash": "efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c" } diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs index 498a75d..763bc3e 100644 --- a/rnex-core/src/nex/datastore.rs +++ b/rnex-core/src/nex/datastore.rs @@ -1,780 +1,785 @@ -use crate::define_rmc_proto; -use macros::rmc_struct; -use rnex_core::prudp::socket_addr::PRUDPSockAddr; -use std::sync::{Weak}; -use chrono::Utc; -use sqlx::types::time; -use sqlx::types::time::PrimitiveDateTime; -use rnex_core::PID; -use rnex_core::nex::remote_console::RemoteConsole; -use rnex_core::nex::s3presigner::S3Presigner; -use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure}; -use rnex_core::rmc::protocols::datastore::{BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, DataStoreGetCustomRankingByDataIDParam, DataStorePrepareGetParam, DataStoreReqGetInfo, DataStoreSearchParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, RateCustomRankingParam, RatingInfo, RatingInfoWithSlot}; -use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; -use crate::nex::user::User; -use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT, get_db}; -use rnex_core::rmc::structures::qbuffer::QBuffer; -use sqlx::types::chrono::DateTime; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::rmc::structures::qresult::QResult; +use cfg_if::cfg_if; +cfg_if! { + if #[cfg(feature = "datastore")] { + use crate::define_rmc_proto; + use macros::rmc_struct; + use rnex_core::prudp::socket_addr::PRUDPSockAddr; + use std::sync::{Weak}; + use chrono::Utc; + use sqlx::types::time; + use sqlx::types::time::PrimitiveDateTime; + use rnex_core::PID; + use rnex_core::nex::remote_console::RemoteConsole; + use rnex_core::nex::s3presigner::S3Presigner; + use rnex_core::rmc::response::ErrorCode; + use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure}; + use rnex_core::rmc::protocols::datastore::{BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, DataStoreGetCustomRankingByDataIDParam, DataStorePrepareGetParam, DataStoreReqGetInfo, DataStoreSearchParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, RateCustomRankingParam, RatingInfo, RatingInfoWithSlot}; + use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo}; + use crate::nex::user::User; + use rnex_core::executables::common::{RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT, get_db}; + use rnex_core::rmc::structures::qbuffer::QBuffer; + use sqlx::types::chrono::DateTime; + use rnex_core::kerberos::KerberosDateTime; + use rnex_core::rmc::structures::qresult::QResult; -fn map_row_to_meta_info( - row_data_id: i64, - row_owner: i32, - row_size: i32, - row_name: String, - row_data_type: i16, - row_meta_binary: Vec, - row_permission: i16, - row_permission_recipients: Vec, - row_delete_permission: i16, - row_delete_permission_recipients: Vec, - row_period: i16, - row_refer_data_id: i64, - row_flag: i32, - row_tags: Vec, - row_creation_date: chrono::NaiveDateTime, - row_update_date: chrono::NaiveDateTime, - ratings: Vec -) -> GetMetaInfo { - GetMetaInfo { - dataid: row_data_id as u64, - owner: row_owner as u32, - size: row_size as u32, - name: row_name, - data_type: row_data_type as u16, - meta_binary: QBuffer(row_meta_binary), - permission: Permission { - permission: row_permission as u8, - recipient_ids: row_permission_recipients.into_iter().map(|id| id as u32).collect(), - }, - del_permission: Permission { - permission: row_delete_permission as u8, - recipient_ids: row_delete_permission_recipients.into_iter().map(|id| id as u32).collect(), - }, - period: row_period as u16, - status: 0, - referred_count: 0, - refer_dat_id: row_refer_data_id as u32, - flag: row_flag as u32, - tags: row_tags, - expire_time: KerberosDateTime::from_u64(0x9C3F3E0000), - created_time: KerberosDateTime::from_naive(row_creation_date), - updated_time: KerberosDateTime::from_naive(row_update_date), - referred_time: KerberosDateTime::from_naive(row_creation_date), - ratings, - } -} - -async fn check_object_availability(data_id: u64, password: u64) -> Result<(), ErrorCode> { - let row = sqlx::query!( - r#" - SELECT under_review, access_password - FROM datastore.objects - WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE - "#, - data_id as i64 - ) - .fetch_optional(get_db()) - .await - .map_err(|e| { - eprintln!("Availability check DB error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })? - .ok_or(ErrorCode::DataStore_NotFound)?; - - let access_password = row.access_password as u64; - if access_password != 0 && access_password != password { - return Err(ErrorCode::DataStore_InvalidPassword); - } - - if row.under_review { - return Err(ErrorCode::DataStore_UnderReviewing); - } - - Ok(()) -} - -async fn get_object_ratings(data_id: u64, password: u64) -> Result, ErrorCode> { - check_object_availability(data_id, password).await?; - - let rows = sqlx::query!( - r#" - SELECT slot, total_value, count, initial_value - FROM datastore.object_ratings - WHERE data_id = $1 - "#, - data_id as i64 - ) - .fetch_all(get_db()) - .await - .map_err(|e| { - eprintln!("Ratings fetch error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let ratings = rows.into_iter().map(|row| { - RatingInfoWithSlot { - slot: row.slot as i8, - rating: RatingInfo { - total_value: row.total_value.unwrap_or(0), - count: row.count as u32, - initial_value: row.initial_value.unwrap_or(0), - }, - } - }).collect(); - - Ok(ratings) -} - -async fn get_object_info_by_data_id(data_id: u64, password: u64) -> Result { - check_object_availability(data_id, password).await?; - - let row = sqlx::query!( - r#"SELECT data_id, owner, size, name, data_type, meta_binary, - permission, permission_recipients, delete_permission, delete_permission_recipients, - period, refer_data_id, flag, tags, creation_date, update_date - FROM datastore.objects WHERE data_id = $1"#, - data_id as i64 - ) - .fetch_optional(get_db()) - .await - .map_err(|_| ErrorCode::DataStore_SystemFileError)? - .ok_or(ErrorCode::DataStore_NotFound)?; - - let ratings = get_object_ratings(data_id, password).await?; - - Ok(map_row_to_meta_info( - row.data_id, - row.owner.unwrap_or(0), - row.size.unwrap_or(0), - row.name.unwrap_or_default(), - row.data_type.unwrap_or(0) as i16, - row.meta_binary.unwrap_or_default(), - row.permission.unwrap_or(0) as i16, - row.permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), - row.delete_permission.unwrap_or(0) as i16, - row.delete_permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), - row.period.unwrap_or(0) as i16, - row.refer_data_id.unwrap_or(0), - row.flag.unwrap_or(0), - row.tags.unwrap_or_default(), - row.creation_date.map(|dt| chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), - chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() - )).unwrap_or_default(), - row.update_date.map(|dt| chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), - chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() - )).unwrap_or_default(), - ratings - )) -} - -async fn get_object_info_by_persistence_target(target: PersistenceTarget, password: u64) -> Result { - let row = sqlx::query!( - r#"SELECT data_id, owner, size, name, data_type, meta_binary, - permission, permission_recipients, delete_permission, delete_permission_recipients, - period, refer_data_id, flag, tags, creation_date, update_date, - access_password, under_review - FROM datastore.objects - WHERE owner = $1 AND persistence_slot_id = $2 - AND upload_completed = TRUE AND deleted = FALSE"#, - target.owner as i32, - target.persistence_slot_id as i16 - ) - .fetch_optional(get_db()) - .await - .map_err(|_| ErrorCode::DataStore_SystemFileError)? - .ok_or(ErrorCode::DataStore_NotFound)?; - - let db_password = row.access_password as u64; - if db_password != 0 && db_password != password { - return Err(ErrorCode::DataStore_InvalidPassword); - } - - if row.under_review { - return Err(ErrorCode::DataStore_UnderReviewing); - } - - let ratings = get_object_ratings(row.data_id as u64, password).await?; - - Ok(map_row_to_meta_info( - row.data_id, - row.owner.unwrap_or(0), - row.size.unwrap_or(0), - row.name.unwrap_or_default(), - row.data_type.unwrap_or(0) as i16, - row.meta_binary.unwrap_or_default(), - row.permission.unwrap_or(0) as i16, - row.permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), - row.delete_permission.unwrap_or(0) as i16, - row.delete_permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), - row.period.unwrap_or(0) as i16, - row.refer_data_id.unwrap_or(0), - row.flag.unwrap_or(0), - row.tags.unwrap_or_default(), - row.creation_date.map(|dt| chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), - chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() - )).unwrap_or_default(), - row.update_date.map(|dt| chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), - chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() - )).unwrap_or_default(), - ratings - )) -} - -async fn get_buffer_queues_by_data_id_and_slot( - data_id: u64, - slot: u32 -) -> Result, ErrorCode> { - check_object_availability(data_id, 0).await?; - - let rows = sqlx::query!( - r#" - SELECT buffer - FROM datastore.buffer_queues - WHERE data_id = $1 AND slot = $2 - ORDER BY creation_date ASC - "#, - data_id as i64, - slot as i32 - ) - .fetch_all(get_db()) - .await - .map_err(|e| { - log::error!("Buffer queue fetch error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let buffer_queues = rows - .into_iter() - .map(|row| QBuffer(row.buffer)) - .collect(); - - Ok(buffer_queues) -} - -fn verify_object_permission( - owner_id: u32, - viewer_id: u32, - permission: &Permission, -) -> Result<(), ErrorCode> { - if owner_id == viewer_id { - return Ok(()); - } - - match permission.permission { - 0 => Ok(()), // All can read - 1 => Err(ErrorCode::DataStore_PermissionDenied), // Friends only, unimplemented - 2 => { - // Recipient IDs can read - if permission.recipient_ids.contains(&viewer_id) { - Ok(()) - } else { - Err(ErrorCode::DataStore_PermissionDenied) + fn map_row_to_meta_info( + row_data_id: i64, + row_owner: i32, + row_size: i32, + row_name: String, + row_data_type: i16, + row_meta_binary: Vec, + row_permission: i16, + row_permission_recipients: Vec, + row_delete_permission: i16, + row_delete_permission_recipients: Vec, + row_period: i16, + row_refer_data_id: i64, + row_flag: i32, + row_tags: Vec, + row_creation_date: chrono::NaiveDateTime, + row_update_date: chrono::NaiveDateTime, + ratings: Vec + ) -> GetMetaInfo { + GetMetaInfo { + dataid: row_data_id as u64, + owner: row_owner as u32, + size: row_size as u32, + name: row_name, + data_type: row_data_type as u16, + meta_binary: QBuffer(row_meta_binary), + permission: Permission { + permission: row_permission as u8, + recipient_ids: row_permission_recipients.into_iter().map(|id| id as u32).collect(), + }, + del_permission: Permission { + permission: row_delete_permission as u8, + recipient_ids: row_delete_permission_recipients.into_iter().map(|id| id as u32).collect(), + }, + period: row_period as u16, + status: 0, + referred_count: 0, + refer_dat_id: row_refer_data_id as u32, + flag: row_flag as u32, + tags: row_tags, + expire_time: KerberosDateTime::from_u64(0x9C3F3E0000), + created_time: KerberosDateTime::from_naive(row_creation_date), + updated_time: KerberosDateTime::from_naive(row_update_date), + referred_time: KerberosDateTime::from_naive(row_creation_date), + ratings, } } - 3 => Err(ErrorCode::DataStore_PermissionDenied), // Owner only, redundant - _ => Err(ErrorCode::DataStore_InvalidArgument), // ??? haxx0r - } -} -fn filter_properties_by_result_option( - meta_info: &mut GetMetaInfo, - result_option: u8, -) { - if (result_option & 0x01) == 0 { - meta_info.meta_binary = QBuffer(Vec::new()); - } - - if (result_option & 0x04) == 0 { - meta_info.ratings = Vec::new(); - } - - // No idea what the other things do. :shrug: -} - -// Dawg... -async fn get_custom_rankings_by_data_ids( - application_id: u32, - data_ids: Vec -) -> Vec { - let mut results = Vec::with_capacity(data_ids.len()); - - let rows = sqlx::query!( - r#" - SELECT - rankings.data_id, - rankings.value - FROM datastore.object_custom_rankings rankings - JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord) - ON rankings.data_id = rows.data_id - AND rankings.application_id = $2 - ORDER BY rows.ord - "#, - &data_ids.iter().map(|&id| id as i64).collect::>(), - application_id as i32 - ) - .fetch_all(get_db()) - .await; - - let rows = match rows { - Ok(r) => r, - Err(e) => { - log::error!("Custom ranking query error: {:?}", e); - return results; - } - }; - - for row in rows { - let data_id = row.data_id as u64; - let score = row.value.unwrap_or(0) as u32; - - if let Ok(meta) = get_object_info_by_data_id(data_id, 0).await { - results.push(DataStoreCustomRankingResult { - order: 0, - score, - meta_info: meta, - }); - } else { - log::warn!("Could not find metadata for ranked object {}", data_id); - } - } - - results -} - -async fn get_user_course_object_ids(owner_pid: u32) -> Result, ErrorCode> { - let rows = sqlx::query!( - r#" - SELECT data_id - FROM datastore.objects - WHERE owner = $1 AND data_type > 2 AND data_type < 50 - "#, - owner_pid as i64 - ) - .fetch_all(get_db()) - .await - .map_err(|e| { - log::error!("error fetching course IDs for PID {}: {:?}", owner_pid, e); - ErrorCode::DataStore_SystemFileError - })?; - - let mut valid_ids = Vec::new(); - for row in rows { - let data_id = row.data_id as u64; - // always check avail - if check_object_availability(data_id, 0).await.is_ok() { - valid_ids.push(data_id); - } - } - - Ok(valid_ids) -} - -fn get_blacklist_1() -> Vec { - vec![ - "けされ", "消され", "削除され", "リセットされ", "BANされ", "BANされ", - "キミのコース", "君のコース", "きみのコース", "い い ね", "遊びます", "地震", - "震災", "被災", "津波", "バンされ", "い~ね", "震度", "じしん", "banされ", - "くわしくは", "詳しくは", "ちんちん", "ち0こ", "bicth", "い.い.ね", - "ナイ~ス", "い&い", "い-いね", "いぃね", "nigger", "ngger", "star if u", - "Star if u", "Star if you", "star if you", "PENlS", "マンコ", "butthole", - "LILI", "vagina", "vagyna", "うんち", "うんこ", "ウンコ", "Iine", - "EENE", "まんこ", "ウンチ", "niglet", "nigglet", "please like", "きんたま", - "Butthole", "llね", "iいね", "give a star", "ちんぽ", "亀頭", "penis", - "ウンコ", "plz more stars", "star plz", "い()ね", "PLEASE star", "Bitte Sterne", - ].into_iter().map(String::from).collect() -} - -fn get_blacklist_2() -> Vec { - vec![ - "ゼロから", "0から", "0から", "い  い  ね", "いい", "東日本", "大震", - ].into_iter().map(String::from).collect() -} - -fn get_blacklist_3() -> Vec { - vec![ - "いいね", "下さい", "ください", "押して", "おして", "返す", "かえす", - "星", "してくれ", "するよ", "☆くれたら", "☆あげます", "★くれたら", - "★あげます", "しね", "ころす", "ころされた", "アナル", "ファック", - "キンタマ", "○ね", "キチガイ", "うんこ", "KITIGAI", "金玉", "おっぱい", - "☆おす", "☆押す", "★おす", "★押す", "いいする", "いいよ", "イイネ", - "ケツ", "うんち", "かくせいざい", "覚せい剤", "シャブ", "きんたま", - "ちんちん", "おしっこ", "ちんぽこ", "ころして", "グッド", "グット", - "レ●プ", "バーカ", "きちがい", "ちんげ", "マンコ", "まんこ", "チンポ", - "クズ", "ウンコ", "ナイスおねがいします", "penis", "イイね", "☆よろ", - "ナイス!して", "ま/んこ", "まん/こ", - ].into_iter().map(String::from).collect() -} - -impl DataStore for User { - async fn get_meta(&self, mut metaparam: GetMetaParam) -> Result { - let mut meta_info = if metaparam.dataid != 0 { - get_object_info_by_data_id(metaparam.dataid, metaparam.access_password).await? - } else { - get_object_info_by_persistence_target(metaparam.persistence_target, metaparam.access_password).await? - }; - - let current_pid = self.pid; - verify_object_permission(meta_info.owner, current_pid, &meta_info.permission)?; - - filter_properties_by_result_option(&mut meta_info, metaparam.result_option); - - Ok(meta_info) - } - - async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result { - let recipient_ids: Vec = postparam.permission.recipient_ids.iter().map(|&id| id as i32).collect(); - let del_recipient_ids: Vec = postparam.del_permission.recipient_ids.iter().map(|&id| id as i32).collect(); - let now = time::OffsetDateTime::now_utc(); - - let row = sqlx::query!( + async fn check_object_availability(data_id: u64, password: u64) -> Result<(), ErrorCode> { + let row = sqlx::query!( r#" - INSERT INTO datastore.objects ( - owner, size, name, data_type, meta_binary, - permission, permission_recipients, - delete_permission, delete_permission_recipients, - flag, period, refer_data_id, tags, - persistence_slot_id, extra_data, creation_date, update_date - ) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17 - ) RETURNING data_id + SELECT under_review, access_password + FROM datastore.objects + WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE "#, - self.pid as i32, - postparam.size as i32, - postparam.name, - postparam.data_type as i32, - &postparam.meta_binary.0, - postparam.permission.permission as i32, - &recipient_ids, - postparam.del_permission.permission as i32, - &del_recipient_ids, - postparam.flag as i32, - postparam.period as i32, - postparam.refer_data_id as i64, - &postparam.tags, - postparam.persistence_init_param.persistence_slot_id as i32, - &postparam.extra_data, - time::PrimitiveDateTime::new(now.date(), now.time()), - time::PrimitiveDateTime::new(now.date(), now.time()) + data_id as i64 ) - .fetch_one(get_db()) - .await - .map_err(|e| { - log::error!("DB Error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let data_id = row.data_id as u64; - let presigner = S3Presigner::new( - &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), - format!("{}", *RNEX_DATASTORE_S3_BUCKET) - ).await; - - let key = format!("data/{}.bin", data_id); - - let (upload_url, fields) = presigner.generate_presigned_post(&key).await; - - let form_fields = fields.into_iter().map(|(k, v)| { - KeyValue { key: k, value: v } - }).collect(); - - Ok(ReqPostInfo { - dataid: data_id, - url: upload_url, - request_headers: vec![], - form_fields, - root_ca_cert: vec![], - }) - } - - async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode> { - log::info!("Data ID: {:?}", completeparam.dataid); - log::info!("Success: {:?}", completeparam.success); - - let record = sqlx::query!( - r#"SELECT owner, under_review FROM datastore.objects WHERE data_id = $1"#, - completeparam.dataid as i64 - ) - .fetch_optional(get_db()) - .await - .map_err(|e| { - eprintln!("select error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let record = record.ok_or(ErrorCode::DataStore_NotFound)?; - - if record.under_review { - return Err(ErrorCode::DataStore_UnderReviewing); - } - - if record.owner.unwrap_or(0) as u32 != self.pid { - return Err(ErrorCode::DataStore_PermissionDenied); - } - - if completeparam.success { - sqlx::query!( - r#"UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1"#, - completeparam.dataid as i64 - ) - .execute(get_db()) + .fetch_optional(get_db()) .await .map_err(|e| { - eprintln!("update error: {:?}", e); + eprintln!("Availability check DB error: {:?}", e); ErrorCode::DataStore_SystemFileError - })?; - } else { - return Err(ErrorCode::Transport_TemporaryServerError); - } + })? + .ok_or(ErrorCode::DataStore_NotFound)?; - Ok(()) - } - - async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode> { - for abcparam in rankingparam { - let exists = sqlx::query_scalar!( - r#"SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)"#, - abcparam.dataid as i64 - ) - .fetch_one(get_db()) - .await - .map_err(|_| ErrorCode::DataStore_SystemFileError)?; - - if !exists.unwrap_or(false) { - return Err(ErrorCode::DataStore_NotFound); + let access_password = row.access_password as u64; + if access_password != 0 && access_password != password { + return Err(ErrorCode::DataStore_InvalidPassword); } - sqlx::query!( - r#" - INSERT INTO datastore.object_custom_rankings (data_id, application_id, value) - VALUES ($1, $2, $3) - ON CONFLICT (data_id, application_id) - DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value - "#, - abcparam.dataid as i64, - abcparam.appid as i32, - abcparam.score as i32 - ) - .execute(get_db()) + if row.under_review { + return Err(ErrorCode::DataStore_UnderReviewing); + } + + Ok(()) + } + + async fn get_object_ratings(data_id: u64, password: u64) -> Result, ErrorCode> { + check_object_availability(data_id, password).await?; + + let rows = sqlx::query!( + r#" + SELECT slot, total_value, count, initial_value + FROM datastore.object_ratings + WHERE data_id = $1 + "#, + data_id as i64 + ) + .fetch_all(get_db()) .await .map_err(|e| { - log::error!("update/insert error: {:?}", e); + eprintln!("Ratings fetch error: {:?}", e); ErrorCode::DataStore_SystemFileError })?; + + let ratings = rows.into_iter().map(|row| { + RatingInfoWithSlot { + slot: row.slot as i8, + rating: RatingInfo { + total_value: row.total_value.unwrap_or(0), + count: row.count as u32, + initial_value: row.initial_value.unwrap_or(0), + }, + } + }).collect(); + + Ok(ratings) } - Ok(()) - } + async fn get_object_info_by_data_id(data_id: u64, password: u64) -> Result { + check_object_availability(data_id, password).await?; - async fn get_application_config(&self, appid: u32) -> Result, ErrorCode> { - const MAX_COURSE_UPLOADS: i32 = 100; + let row = sqlx::query!( + r#"SELECT data_id, owner, size, name, data_type, meta_binary, + permission, permission_recipients, delete_permission, delete_permission_recipients, + period, refer_data_id, flag, tags, creation_date, update_date + FROM datastore.objects WHERE data_id = $1"#, + data_id as i64 + ) + .fetch_optional(get_db()) + .await + .map_err(|_| ErrorCode::DataStore_SystemFileError)? + .ok_or(ErrorCode::DataStore_NotFound)?; - let config = match appid { - 0 => vec![ - 0x00000001, 0x00000032, 0x00000096, 0x0000012c, 0x000001f4, - 0x00000320, 0x00000514, 0x000007d0, 0x00000bb8, 0x00001388, - MAX_COURSE_UPLOADS, 0x00000014, 0x0000001e, 0x00000028, 0x00000032, - 0x0000003c, 0x00000046, 0x00000050, 0x0000005a, 0x00000064, - 0x00000023, 0x0000004b, 0x00000023, 0x0000004b, 0x00000032, - 0x00000000, 0x00000003, 0x00000003, 0x00000064, 0x00000006, - 0x00000001, 0x00000060, 0x00000005, 0x00000060, 0x00000000, - 0x000007e4, 0x00000001, 0x00000001, 0x0000000c, 0x00000000, - ], - 1 => vec![ - 2, - 1770179696, - 1770179664, - 1770179640, - 1770180827, - 1770180777, - 1770180745, - 1770177625, - 1770177590, - ], - 2 => vec![0x000007df, 0x0000000c, 0x00000016, 0x00000005, 0x00000000], - 10 => vec![35, 75, 96, 40, 5, 6], - _ => { - log::error!("unknown SMM app id: {}", appid); - return Err(ErrorCode::DataStore_Unknown); - } - }; + let ratings = get_object_ratings(data_id, password).await?; - Ok(config) - } - - async fn get_custom_ranking_by_data_id( - &self, - custom_ranking_param: DataStoreGetCustomRankingByDataIDParam - ) -> Result<(Vec, Vec), ErrorCode> { - println!("appid: {:?}", custom_ranking_param.application_id); - println!("dataid list: {:?}", custom_ranking_param.data_id_list); - println!("result option: {:?}", custom_ranking_param.result_option); - - let mut ranking_results = get_custom_rankings_by_data_ids(custom_ranking_param.application_id, custom_ranking_param.data_id_list).await; - - let mut q_results = Vec::with_capacity(ranking_results.len()); - - for result in &mut ranking_results { - if (custom_ranking_param.result_option & 0x01) == 0 { - result.meta_info.tags = Vec::new(); - } - - if (custom_ranking_param.result_option & 0x02) == 0 { - result.meta_info.ratings = Vec::new(); - } - - if (custom_ranking_param.result_option & 0x04) == 0 { - result.meta_info.meta_binary = QBuffer(Vec::new()); - } - - if (custom_ranking_param.result_option & 0x20) == 0 { - result.score = 0; - } - - q_results.push(QResult::success(ErrorCode::Core_Unknown)); + Ok(map_row_to_meta_info( + row.data_id, + row.owner.unwrap_or(0), + row.size.unwrap_or(0), + row.name.unwrap_or_default(), + row.data_type.unwrap_or(0) as i16, + row.meta_binary.unwrap_or_default(), + row.permission.unwrap_or(0) as i16, + row.permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.delete_permission.unwrap_or(0) as i16, + row.delete_permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.period.unwrap_or(0) as i16, + row.refer_data_id.unwrap_or(0), + row.flag.unwrap_or(0), + row.tags.unwrap_or_default(), + row.creation_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + row.update_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + ratings + )) } - Ok((ranking_results, q_results)) - } + async fn get_object_info_by_persistence_target(target: PersistenceTarget, password: u64) -> Result { + let row = sqlx::query!( + r#"SELECT data_id, owner, size, name, data_type, meta_binary, + permission, permission_recipients, delete_permission, delete_permission_recipients, + period, refer_data_id, flag, tags, creation_date, update_date, + access_password, under_review + FROM datastore.objects + WHERE owner = $1 AND persistence_slot_id = $2 + AND upload_completed = TRUE AND deleted = FALSE"#, + target.owner as i32, + target.persistence_slot_id as i16 + ) + .fetch_optional(get_db()) + .await + .map_err(|_| ErrorCode::DataStore_SystemFileError)? + .ok_or(ErrorCode::DataStore_NotFound)?; - async fn get_buffer_queue(&self, bufferparam: BufferQueueParam) -> Result, ErrorCode> { - // log::info!("GetBufferQueue: dataid={}, slot={}", param.dataid, param.slot); - - let buffers = get_buffer_queues_by_data_id_and_slot(bufferparam.dataid, bufferparam.slot).await?; - - Ok(buffers) - } - - async fn prepare_get_object(&self, prepare_get_param: DataStorePrepareGetParam) -> Result { - let meta_info = if prepare_get_param.dataid != 0 { - get_object_info_by_data_id(prepare_get_param.dataid, prepare_get_param.access_password).await? - } else { - get_object_info_by_persistence_target(prepare_get_param.persistence_target, prepare_get_param.access_password).await? - }; - - verify_object_permission(meta_info.owner, self.pid, &meta_info.permission)?; - - let presigner = S3Presigner::new( - &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), - format!("{}", *RNEX_DATASTORE_S3_BUCKET) - ).await; - - let key = format!("data/{}.bin", meta_info.dataid); - let download_url = presigner.generate_presigned_get(&key); - - Ok(DataStoreReqGetInfo { - url: download_url, - request_headers: vec![], - size: meta_info.size, - root_ca_cert: vec![], - dataid: meta_info.dataid, - }) - } - - async fn followings_latest_course_search_object( - &self, - course_search_param: DataStoreSearchParam, - _extra_data: Vec - ) -> Result, ErrorCode> { - let mut all_results = Vec::new(); - - for &owner_pid in &course_search_param.owner_ids { - let course_ids = get_user_course_object_ids(owner_pid).await?; - - if course_ids.is_empty() { - continue; + let db_password = row.access_password as u64; + if db_password != 0 && db_password != password { + return Err(ErrorCode::DataStore_InvalidPassword); } - let mut results = get_custom_rankings_by_data_ids(0, course_ids).await; - - // Flag 0x1: Return Tags - // Flag 0x2: Return Ratings - // Flag 0x4: Return MetaBinary - // Flag 0x20: Return Score - for res in &mut results { - if course_search_param.result_option & 0x1 == 0 { - res.meta_info.tags = Vec::new(); - } - if course_search_param.result_option & 0x2 == 0 { - res.meta_info.ratings = Vec::new(); - } - if course_search_param.result_option & 0x4 == 0 { - res.meta_info.meta_binary = rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); - } - if course_search_param.result_option & 0x20 == 0 { - res.score = 0; - } + if row.under_review { + return Err(ErrorCode::DataStore_UnderReviewing); } - all_results.extend(results); + let ratings = get_object_ratings(row.data_id as u64, password).await?; + + Ok(map_row_to_meta_info( + row.data_id, + row.owner.unwrap_or(0), + row.size.unwrap_or(0), + row.name.unwrap_or_default(), + row.data_type.unwrap_or(0) as i16, + row.meta_binary.unwrap_or_default(), + row.permission.unwrap_or(0) as i16, + row.permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.delete_permission.unwrap_or(0) as i16, + row.delete_permission_recipients.unwrap_or_default().into_iter().map(|id| id as i64).collect(), + row.period.unwrap_or(0) as i16, + row.refer_data_id.unwrap_or(0), + row.flag.unwrap_or(0), + row.tags.unwrap_or_default(), + row.creation_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + row.update_date.map(|dt| chrono::NaiveDateTime::new( + chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32).unwrap(), + chrono::NaiveTime::from_hms_opt(dt.hour() as u32, dt.minute() as u32, dt.second() as u32).unwrap() + )).unwrap_or_default(), + ratings + )) } - // note: we assume the client sorts the data lol + async fn get_buffer_queues_by_data_id_and_slot( + data_id: u64, + slot: u32 + ) -> Result, ErrorCode> { + check_object_availability(data_id, 0).await?; - Ok(all_results) - } + let rows = sqlx::query!( + r#" + SELECT buffer + FROM datastore.buffer_queues + WHERE data_id = $1 AND slot = $2 + ORDER BY creation_date ASC + "#, + data_id as i64, + slot as i32 + ) + .fetch_all(get_db()) + .await + .map_err(|e| { + log::error!("Buffer queue fetch error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; - async fn get_application_config_string(&self, application_id: u32) -> Result, ErrorCode> { - let config = match application_id { - 128 => get_blacklist_1(), - 129 => get_blacklist_2(), - 130 => get_blacklist_3(), - _ => { - log::warn!("unsupported application_id in GetApplicationConfigString: {}", application_id); - Vec::new() + let buffer_queues = rows + .into_iter() + .map(|row| QBuffer(row.buffer)) + .collect(); + + Ok(buffer_queues) + } + + fn verify_object_permission( + owner_id: u32, + viewer_id: u32, + permission: &Permission, + ) -> Result<(), ErrorCode> { + if owner_id == viewer_id { + return Ok(()); } - }; - Ok(config) - } - - async fn get_metas_multiple_param( - &self, - params: Vec - ) -> Result<(Vec, Vec), ErrorCode> { - let mut metas = Vec::with_capacity(params.len()); - let mut results = Vec::with_capacity(params.len()); - - for param in params { - let info_result = if param.dataid != 0 { - get_object_info_by_data_id(param.dataid, param.access_password).await - } else { - get_object_info_by_persistence_target(param.persistence_target, param.access_password).await - }; - - match info_result { - Ok(mut meta) => { - if let Err(e) = verify_object_permission(meta.owner, self.pid, &meta.permission) { - metas.push(GetMetaInfo::default()); - results.push(QResult::error(e)); + match permission.permission { + 0 => Ok(()), // All can read + 1 => Err(ErrorCode::DataStore_PermissionDenied), // Friends only, unimplemented + 2 => { + // Recipient IDs can read + if permission.recipient_ids.contains(&viewer_id) { + Ok(()) } else { - if param.result_option & 0x1 == 0 { - meta.tags = Vec::new(); - } - if param.result_option & 0x2 == 0 { - meta.ratings = Vec::new(); - } - if param.result_option & 0x4 == 0 { - meta.meta_binary = rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); - } - - metas.push(meta); - results.push(QResult::success(ErrorCode::Core_Unknown)); + Err(ErrorCode::DataStore_PermissionDenied) } } - Err(e) => { - metas.push(GetMetaInfo::default()); - results.push(QResult::error(e)); - } + 3 => Err(ErrorCode::DataStore_PermissionDenied), // Owner only, redundant + _ => Err(ErrorCode::DataStore_InvalidArgument), // ??? haxx0r } } - Ok((metas, results)) + fn filter_properties_by_result_option( + meta_info: &mut GetMetaInfo, + result_option: u8, + ) { + if (result_option & 0x01) == 0 { + meta_info.meta_binary = QBuffer(Vec::new()); + } + + if (result_option & 0x04) == 0 { + meta_info.ratings = Vec::new(); + } + + // No idea what the other things do. :shrug: + } + + // Dawg... + async fn get_custom_rankings_by_data_ids( + application_id: u32, + data_ids: Vec + ) -> Vec { + let mut results = Vec::with_capacity(data_ids.len()); + + let rows = sqlx::query!( + r#" + SELECT + rankings.data_id, + rankings.value + FROM datastore.object_custom_rankings rankings + JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord) + ON rankings.data_id = rows.data_id + AND rankings.application_id = $2 + ORDER BY rows.ord + "#, + &data_ids.iter().map(|&id| id as i64).collect::>(), + application_id as i32 + ) + .fetch_all(get_db()) + .await; + + let rows = match rows { + Ok(r) => r, + Err(e) => { + log::error!("Custom ranking query error: {:?}", e); + return results; + } + }; + + for row in rows { + let data_id = row.data_id as u64; + let score = row.value.unwrap_or(0) as u32; + + if let Ok(meta) = get_object_info_by_data_id(data_id, 0).await { + results.push(DataStoreCustomRankingResult { + order: 0, + score, + meta_info: meta, + }); + } else { + log::warn!("Could not find metadata for ranked object {}", data_id); + } + } + + results + } + + async fn get_user_course_object_ids(owner_pid: u32) -> Result, ErrorCode> { + let rows = sqlx::query!( + r#" + SELECT data_id + FROM datastore.objects + WHERE owner = $1 AND data_type > 2 AND data_type < 50 + "#, + owner_pid as i64 + ) + .fetch_all(get_db()) + .await + .map_err(|e| { + log::error!("error fetching course IDs for PID {}: {:?}", owner_pid, e); + ErrorCode::DataStore_SystemFileError + })?; + + let mut valid_ids = Vec::new(); + for row in rows { + let data_id = row.data_id as u64; + // always check avail + if check_object_availability(data_id, 0).await.is_ok() { + valid_ids.push(data_id); + } + } + + Ok(valid_ids) + } + + fn get_blacklist_1() -> Vec { + vec![ + "けされ", "消され", "削除され", "リセットされ", "BANされ", "BANされ", + "キミのコース", "君のコース", "きみのコース", "い い ね", "遊びます", "地震", + "震災", "被災", "津波", "バンされ", "い~ね", "震度", "じしん", "banされ", + "くわしくは", "詳しくは", "ちんちん", "ち0こ", "bicth", "い.い.ね", + "ナイ~ス", "い&い", "い-いね", "いぃね", "nigger", "ngger", "star if u", + "Star if u", "Star if you", "star if you", "PENlS", "マンコ", "butthole", + "LILI", "vagina", "vagyna", "うんち", "うんこ", "ウンコ", "Iine", + "EENE", "まんこ", "ウンチ", "niglet", "nigglet", "please like", "きんたま", + "Butthole", "llね", "iいね", "give a star", "ちんぽ", "亀頭", "penis", + "ウンコ", "plz more stars", "star plz", "い()ね", "PLEASE star", "Bitte Sterne", + ].into_iter().map(String::from).collect() + } + + fn get_blacklist_2() -> Vec { + vec![ + "ゼロから", "0から", "0から", "い  い  ね", "いい", "東日本", "大震", + ].into_iter().map(String::from).collect() + } + + fn get_blacklist_3() -> Vec { + vec![ + "いいね", "下さい", "ください", "押して", "おして", "返す", "かえす", + "星", "してくれ", "するよ", "☆くれたら", "☆あげます", "★くれたら", + "★あげます", "しね", "ころす", "ころされた", "アナル", "ファック", + "キンタマ", "○ね", "キチガイ", "うんこ", "KITIGAI", "金玉", "おっぱい", + "☆おす", "☆押す", "★おす", "★押す", "いいする", "いいよ", "イイネ", + "ケツ", "うんち", "かくせいざい", "覚せい剤", "シャブ", "きんたま", + "ちんちん", "おしっこ", "ちんぽこ", "ころして", "グッド", "グット", + "レ●プ", "バーカ", "きちがい", "ちんげ", "マンコ", "まんこ", "チンポ", + "クズ", "ウンコ", "ナイスおねがいします", "penis", "イイね", "☆よろ", + "ナイス!して", "ま/んこ", "まん/こ", + ].into_iter().map(String::from).collect() + } + + impl DataStore for User { + async fn get_meta(&self, mut metaparam: GetMetaParam) -> Result { + let mut meta_info = if metaparam.dataid != 0 { + get_object_info_by_data_id(metaparam.dataid, metaparam.access_password).await? + } else { + get_object_info_by_persistence_target(metaparam.persistence_target, metaparam.access_password).await? + }; + + let current_pid = self.pid; + verify_object_permission(meta_info.owner, current_pid, &meta_info.permission)?; + + filter_properties_by_result_option(&mut meta_info, metaparam.result_option); + + Ok(meta_info) + } + + async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result { + let recipient_ids: Vec = postparam.permission.recipient_ids.iter().map(|&id| id as i32).collect(); + let del_recipient_ids: Vec = postparam.del_permission.recipient_ids.iter().map(|&id| id as i32).collect(); + let now = time::OffsetDateTime::now_utc(); + + let row = sqlx::query!( + r#" + INSERT INTO datastore.objects ( + owner, size, name, data_type, meta_binary, + permission, permission_recipients, + delete_permission, delete_permission_recipients, + flag, period, refer_data_id, tags, + persistence_slot_id, extra_data, creation_date, update_date + ) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17 + ) RETURNING data_id + "#, + self.pid as i32, + postparam.size as i32, + postparam.name, + postparam.data_type as i32, + &postparam.meta_binary.0, + postparam.permission.permission as i32, + &recipient_ids, + postparam.del_permission.permission as i32, + &del_recipient_ids, + postparam.flag as i32, + postparam.period as i32, + postparam.refer_data_id as i64, + &postparam.tags, + postparam.persistence_init_param.persistence_slot_id as i32, + &postparam.extra_data, + time::PrimitiveDateTime::new(now.date(), now.time()), + time::PrimitiveDateTime::new(now.date(), now.time()) + ) + .fetch_one(get_db()) + .await + .map_err(|e| { + log::error!("DB Error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + + let data_id = row.data_id as u64; + let presigner = S3Presigner::new( + &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), + format!("{}", *RNEX_DATASTORE_S3_BUCKET) + ).await; + + let key = format!("data/{}.bin", data_id); + + let (upload_url, fields) = presigner.generate_presigned_post(&key).await; + + let form_fields = fields.into_iter().map(|(k, v)| { + KeyValue { key: k, value: v } + }).collect(); + + Ok(ReqPostInfo { + dataid: data_id, + url: upload_url, + request_headers: vec![], + form_fields, + root_ca_cert: vec![], + }) + } + + async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode> { + log::info!("Data ID: {:?}", completeparam.dataid); + log::info!("Success: {:?}", completeparam.success); + + let record = sqlx::query!( + r#"SELECT owner, under_review FROM datastore.objects WHERE data_id = $1"#, + completeparam.dataid as i64 + ) + .fetch_optional(get_db()) + .await + .map_err(|e| { + eprintln!("select error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + + let record = record.ok_or(ErrorCode::DataStore_NotFound)?; + + if record.under_review { + return Err(ErrorCode::DataStore_UnderReviewing); + } + + if record.owner.unwrap_or(0) as u32 != self.pid { + return Err(ErrorCode::DataStore_PermissionDenied); + } + + if completeparam.success { + sqlx::query!( + r#"UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1"#, + completeparam.dataid as i64 + ) + .execute(get_db()) + .await + .map_err(|e| { + eprintln!("update error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + } else { + return Err(ErrorCode::Transport_TemporaryServerError); + } + + Ok(()) + } + + async fn rate_custom_ranking(&self, rankingparam: Vec) -> Result<(), ErrorCode> { + for abcparam in rankingparam { + let exists = sqlx::query_scalar!( + r#"SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)"#, + abcparam.dataid as i64 + ) + .fetch_one(get_db()) + .await + .map_err(|_| ErrorCode::DataStore_SystemFileError)?; + + if !exists.unwrap_or(false) { + return Err(ErrorCode::DataStore_NotFound); + } + + sqlx::query!( + r#" + INSERT INTO datastore.object_custom_rankings (data_id, application_id, value) + VALUES ($1, $2, $3) + ON CONFLICT (data_id, application_id) + DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value + "#, + abcparam.dataid as i64, + abcparam.appid as i32, + abcparam.score as i32 + ) + .execute(get_db()) + .await + .map_err(|e| { + log::error!("update/insert error: {:?}", e); + ErrorCode::DataStore_SystemFileError + })?; + } + + Ok(()) + } + + async fn get_application_config(&self, appid: u32) -> Result, ErrorCode> { + const MAX_COURSE_UPLOADS: i32 = 100; + + let config = match appid { + 0 => vec![ + 0x00000001, 0x00000032, 0x00000096, 0x0000012c, 0x000001f4, + 0x00000320, 0x00000514, 0x000007d0, 0x00000bb8, 0x00001388, + MAX_COURSE_UPLOADS, 0x00000014, 0x0000001e, 0x00000028, 0x00000032, + 0x0000003c, 0x00000046, 0x00000050, 0x0000005a, 0x00000064, + 0x00000023, 0x0000004b, 0x00000023, 0x0000004b, 0x00000032, + 0x00000000, 0x00000003, 0x00000003, 0x00000064, 0x00000006, + 0x00000001, 0x00000060, 0x00000005, 0x00000060, 0x00000000, + 0x000007e4, 0x00000001, 0x00000001, 0x0000000c, 0x00000000, + ], + 1 => vec![ + 2, + 1770179696, + 1770179664, + 1770179640, + 1770180827, + 1770180777, + 1770180745, + 1770177625, + 1770177590, + ], + 2 => vec![0x000007df, 0x0000000c, 0x00000016, 0x00000005, 0x00000000], + 10 => vec![35, 75, 96, 40, 5, 6], + _ => { + log::error!("unknown SMM app id: {}", appid); + return Err(ErrorCode::DataStore_Unknown); + } + }; + + Ok(config) + } + + async fn get_custom_ranking_by_data_id( + &self, + custom_ranking_param: DataStoreGetCustomRankingByDataIDParam + ) -> Result<(Vec, Vec), ErrorCode> { + println!("appid: {:?}", custom_ranking_param.application_id); + println!("dataid list: {:?}", custom_ranking_param.data_id_list); + println!("result option: {:?}", custom_ranking_param.result_option); + + let mut ranking_results = get_custom_rankings_by_data_ids(custom_ranking_param.application_id, custom_ranking_param.data_id_list).await; + + let mut q_results = Vec::with_capacity(ranking_results.len()); + + for result in &mut ranking_results { + if (custom_ranking_param.result_option & 0x01) == 0 { + result.meta_info.tags = Vec::new(); + } + + if (custom_ranking_param.result_option & 0x02) == 0 { + result.meta_info.ratings = Vec::new(); + } + + if (custom_ranking_param.result_option & 0x04) == 0 { + result.meta_info.meta_binary = QBuffer(Vec::new()); + } + + if (custom_ranking_param.result_option & 0x20) == 0 { + result.score = 0; + } + + q_results.push(QResult::success(ErrorCode::Core_Unknown)); + } + + Ok((ranking_results, q_results)) + } + + async fn get_buffer_queue(&self, bufferparam: BufferQueueParam) -> Result, ErrorCode> { + // log::info!("GetBufferQueue: dataid={}, slot={}", param.dataid, param.slot); + + let buffers = get_buffer_queues_by_data_id_and_slot(bufferparam.dataid, bufferparam.slot).await?; + + Ok(buffers) + } + + async fn prepare_get_object(&self, prepare_get_param: DataStorePrepareGetParam) -> Result { + let meta_info = if prepare_get_param.dataid != 0 { + get_object_info_by_data_id(prepare_get_param.dataid, prepare_get_param.access_password).await? + } else { + get_object_info_by_persistence_target(prepare_get_param.persistence_target, prepare_get_param.access_password).await? + }; + + verify_object_permission(meta_info.owner, self.pid, &meta_info.permission)?; + + let presigner = S3Presigner::new( + &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), + format!("{}", *RNEX_DATASTORE_S3_BUCKET) + ).await; + + let key = format!("data/{}.bin", meta_info.dataid); + let download_url = presigner.generate_presigned_get(&key); + + Ok(DataStoreReqGetInfo { + url: download_url, + request_headers: vec![], + size: meta_info.size, + root_ca_cert: vec![], + dataid: meta_info.dataid, + }) + } + + async fn followings_latest_course_search_object( + &self, + course_search_param: DataStoreSearchParam, + _extra_data: Vec + ) -> Result, ErrorCode> { + let mut all_results = Vec::new(); + + for &owner_pid in &course_search_param.owner_ids { + let course_ids = get_user_course_object_ids(owner_pid).await?; + + if course_ids.is_empty() { + continue; + } + + let mut results = get_custom_rankings_by_data_ids(0, course_ids).await; + + // Flag 0x1: Return Tags + // Flag 0x2: Return Ratings + // Flag 0x4: Return MetaBinary + // Flag 0x20: Return Score + for res in &mut results { + if course_search_param.result_option & 0x1 == 0 { + res.meta_info.tags = Vec::new(); + } + if course_search_param.result_option & 0x2 == 0 { + res.meta_info.ratings = Vec::new(); + } + if course_search_param.result_option & 0x4 == 0 { + res.meta_info.meta_binary = rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); + } + if course_search_param.result_option & 0x20 == 0 { + res.score = 0; + } + } + + all_results.extend(results); + } + + // note: we assume the client sorts the data lol + + Ok(all_results) + } + + async fn get_application_config_string(&self, application_id: u32) -> Result, ErrorCode> { + let config = match application_id { + 128 => get_blacklist_1(), + 129 => get_blacklist_2(), + 130 => get_blacklist_3(), + _ => { + log::warn!("unsupported application_id in GetApplicationConfigString: {}", application_id); + Vec::new() + } + }; + + Ok(config) + } + + async fn get_metas_multiple_param( + &self, + params: Vec + ) -> Result<(Vec, Vec), ErrorCode> { + let mut metas = Vec::with_capacity(params.len()); + let mut results = Vec::with_capacity(params.len()); + + for param in params { + let info_result = if param.dataid != 0 { + get_object_info_by_data_id(param.dataid, param.access_password).await + } else { + get_object_info_by_persistence_target(param.persistence_target, param.access_password).await + }; + + match info_result { + Ok(mut meta) => { + if let Err(e) = verify_object_permission(meta.owner, self.pid, &meta.permission) { + metas.push(GetMetaInfo::default()); + results.push(QResult::error(e)); + } else { + if param.result_option & 0x1 == 0 { + meta.tags = Vec::new(); + } + if param.result_option & 0x2 == 0 { + meta.ratings = Vec::new(); + } + if param.result_option & 0x4 == 0 { + meta.meta_binary = rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); + } + + metas.push(meta); + results.push(QResult::success(ErrorCode::Core_Unknown)); + } + } + Err(e) => { + metas.push(GetMetaInfo::default()); + results.push(QResult::error(e)); + } + } + } + + Ok((metas, results)) + } + } } } \ No newline at end of file From 458c651cd4e0f0d40ca22bfa5cc036e8695ab9e3 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 21 Apr 2026 21:41:44 +0200 Subject: [PATCH 17/19] Fix conditional compilaton --- rnex-core/src/executables/common.rs | 42 +++++++++++++++++------------ rnex-core/src/nex/mod.rs | 8 +++++- rnex-core/src/nex/user.rs | 36 ++++++++++++++++++------- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/rnex-core/src/executables/common.rs b/rnex-core/src/executables/common.rs index ec27f43..280ab7f 100644 --- a/rnex-core/src/executables/common.rs +++ b/rnex-core/src/executables/common.rs @@ -10,33 +10,41 @@ use std::sync::Arc; use tokio::net::TcpListener; use std::sync::LazyLock; use std::sync::OnceLock; -use sqlx::postgres::PgPool; - +cfg_if! { + if #[cfg(feature = "datastore")] { + use sqlx::postgres::PgPool; + } +} use log::error; use std::error::Error; use std::string::ToString; +use cfg_if::cfg_if; use crate::reggie::UnitPacketRead; const IP_REQ_SERVICE_URL: &str = "https://ipinfo.io/ip"; -pub static RNEX_DATASTORE_DATABASE_URL: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_DATABASE_URL") - .expect("RNEX_DATASTORE_DATABASE_URL must be set") -}); +cfg_if! { + if #[cfg(feature = "datastore")] { + pub static RNEX_DATASTORE_DATABASE_URL: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATASTORE_DATABASE_URL") + .expect("RNEX_DATASTORE_DATABASE_URL must be set") + }); -pub static DB_POOL: OnceLock = OnceLock::new(); + pub static DB_POOL: OnceLock = OnceLock::new(); -pub fn get_db() -> &'static PgPool { - DB_POOL.get().expect("db_pool not initialized") + pub fn get_db() -> &'static PgPool { + DB_POOL.get().expect("db_pool not initialized") + } + pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATASTORE_S3_ENDPOINT") + .expect("RNEX_DATASTORE_S3_ENDPOINT must be set") + }); + pub static RNEX_DATASTORE_S3_BUCKET: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATASTORE_S3_BUCKET") + .expect("RNEX_DATASTORE_S3_BUCKET must be set") + }); + } } -pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_S3_ENDPOINT") - .expect("RNEX_DATASTORE_S3_ENDPOINT must be set") -}); -pub static RNEX_DATASTORE_S3_BUCKET: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_S3_BUCKET") - .expect("RNEX_DATASTORE_S3_BUCKET must be set") -}); pub fn try_get_ip() -> Result> { let mut req = ureq::get(IP_REQ_SERVICE_URL).call()?; diff --git a/rnex-core/src/nex/mod.rs b/rnex-core/src/nex/mod.rs index 91bb866..f54e939 100644 --- a/rnex-core/src/nex/mod.rs +++ b/rnex-core/src/nex/mod.rs @@ -1,3 +1,5 @@ +use cfg_if::cfg_if; + pub mod account; pub mod auth_handler; pub mod common; @@ -6,4 +8,8 @@ pub mod matchmake; pub mod remote_console; pub mod user; pub mod datastore; -pub mod s3presigner; \ No newline at end of file +cfg_if! { + if #[cfg(feature = "datastore")] { + pub mod s3presigner; + } +} \ No newline at end of file diff --git a/rnex-core/src/nex/user.rs b/rnex-core/src/nex/user.rs index f271355..a812d7c 100644 --- a/rnex-core/src/nex/user.rs +++ b/rnex-core/src/nex/user.rs @@ -41,21 +41,37 @@ use rnex_core::prudp::socket_addr::PRUDPSockAddr; use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired}; use rnex_core::rmc::structures::qresult::QResult; use std::sync::{Arc, Weak}; +use cfg_if::cfg_if; use rnex_core::rmc::protocols::ranking::{CompetitionRankingScoreData, CompetitionRankingGetParam, CompetitionRankingScoreInfo}; use rnex_core::rmc::structures::ranking::{UploadCompetitionData}; use tokio::sync::{Mutex, RwLock}; -define_rmc_proto!( - proto UserProtocol{ - Secure, - MatchmakeExtension, - MatchmakeExt, - Matchmake, - NatTraversal, - Ranking, - DataStore +cfg_if! { + if #[cfg(feature = "datastore")] { + define_rmc_proto!( + proto UserProtocol{ + Secure, + MatchmakeExtension, + MatchmakeExt, + Matchmake, + NatTraversal, + Ranking, + DataStore + } + ); + } else { + define_rmc_proto!( + proto UserProtocol{ + Secure, + MatchmakeExtension, + MatchmakeExt, + Matchmake, + NatTraversal, + Ranking + } + ); } -); +} #[rmc_struct(UserProtocol)] pub struct User { From 52af146c555d4354af9c6d8eb27456a65b8e81a4 Mon Sep 17 00:00:00 2001 From: red binder Date: Tue, 21 Apr 2026 21:48:28 +0200 Subject: [PATCH 18/19] i should really start waiting maybe a minute longer before commiting --- rnex-core/src/executables/backend_server_secure.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rnex-core/src/executables/backend_server_secure.rs b/rnex-core/src/executables/backend_server_secure.rs index 0beeafc..cbb64d8 100644 --- a/rnex-core/src/executables/backend_server_secure.rs +++ b/rnex-core/src/executables/backend_server_secure.rs @@ -1,6 +1,5 @@ use cfg_if::cfg_if; use rnex_core::common::setup; -use rnex_core::executables::common::DB_POOL; use rnex_core::executables::common::new_simple_backend; use rnex_core::executables::friends_backend::start_friends_backend; use rnex_core::nex::matchmake::MatchmakeManager; @@ -9,7 +8,6 @@ use rnex_core::nex::user::User; use rnex_core::rmc::protocols::{RemoteDisconnectable, RmcPureRemoteObject}; use std::sync::Arc; use std::sync::atomic::AtomicU32; -use sqlx::PgPool; #[tokio::main] async fn main() { @@ -19,6 +17,8 @@ async fn main() { if #[cfg(feature = "friends")]{ start_friends_backend().await; } else if #[cfg(feature = "datastore")] { + use rnex_core::executables::common::DB_POOL; + use sqlx::PgPool; let database_url = std::env::var("RNEX_DATASTORE_DATABASE_URL") .expect("RNEX_DATASTORE_DATABASE_URL must be set"); From f6318f082ebaae5cce12645f285168d5512bfa67 Mon Sep 17 00:00:00 2001 From: red binder Date: Sat, 25 Apr 2026 18:05:47 +0200 Subject: [PATCH 19/19] wii u chat --- editions.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/editions.yaml b/editions.yaml index 40c2e10..d3c5a54 100644 --- a/editions.yaml +++ b/editions.yaml @@ -1,3 +1,13 @@ +wiiu-chat: + features: + - prudpv1 + - v3-8-15 + settings: + AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0" + RNEX_VIRTUAL_PORT_INSECURE: "1:10" + RNEX_VIRTUAL_PORT_SECURE: "1:10" + RNEX_DEFAULT_PORT: 10000 + RNEX_ACCESS_KEY: "e7a47214" splatoon: features: - prudpv1