feat: get in the friends server
This commit is contained in:
parent
9f9393cfe5
commit
2417c109e4
9 changed files with 473 additions and 21 deletions
89
Cargo.lock
generated
89
Cargo.lock
generated
|
|
@ -18,6 +18,8 @@ dependencies = [
|
||||||
"gxhash",
|
"gxhash",
|
||||||
"hex",
|
"hex",
|
||||||
"hmac",
|
"hmac",
|
||||||
|
"juniper",
|
||||||
|
"juniper_rocket",
|
||||||
"log",
|
"log",
|
||||||
"md-5",
|
"md-5",
|
||||||
"mii",
|
"mii",
|
||||||
|
|
@ -234,6 +236,18 @@ version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "auto_enums"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c170965892137a3a9aeb000b4524aa3cc022a310e709d848b6e1cdce4ab4781"
|
||||||
|
dependencies = [
|
||||||
|
"derive_utils",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
|
@ -617,6 +631,17 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_utils"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "devise"
|
name = "devise"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -839,6 +864,7 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
|
@ -1558,6 +1584,52 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "juniper"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "943306315b1a7a03d27af9dfb0c288d9f4da8830c17df4bceb7d50a47da0982c"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"auto_enums",
|
||||||
|
"chrono",
|
||||||
|
"fnv",
|
||||||
|
"futures",
|
||||||
|
"indexmap 2.7.1",
|
||||||
|
"juniper_codegen",
|
||||||
|
"serde",
|
||||||
|
"smartstring",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "juniper_codegen"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "760dbe46660494d469023d661e8d268f413b2cb68c999975dcc237407096a693"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "juniper_rocket"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce74561b72a9aab16a16df022d7b6551fa8018b0cedfe2187417eeb602b65b3e"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"futures",
|
||||||
|
"inlinable_string",
|
||||||
|
"juniper",
|
||||||
|
"pear",
|
||||||
|
"rocket",
|
||||||
|
"serde_json",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -2708,6 +2780,17 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smartstring"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"static_assertions",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.8"
|
version = "0.5.8"
|
||||||
|
|
@ -2955,6 +3038,12 @@ dependencies = [
|
||||||
"loom",
|
"loom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stringprep"
|
name = "stringprep"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,13 @@ minio = { git = "https://github.com/minio/minio-rs.git" }
|
||||||
crc32fast = "1.4.2"
|
crc32fast = "1.4.2"
|
||||||
gxhash = "3.4.1"
|
gxhash = "3.4.1"
|
||||||
|
|
||||||
|
juniper = { version = "0.16.1", features = ["chrono"] }
|
||||||
|
juniper_rocket = "0.9.0"
|
||||||
|
|
||||||
tonic = "0.12.3"
|
tonic = "0.12.3"
|
||||||
prost = "0.13.4"
|
prost = "0.13.4"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tonic-build = "0.12.3"
|
tonic-build = "0.12.3"
|
||||||
|
|
@ -124,7 +124,7 @@ pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<Use
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_bearer_auth_token(connection: &Pool, token: &str) -> Option<User> {
|
pub async fn read_bearer_auth_token(connection: &Pool, token: &str) -> Option<User> {
|
||||||
let data = TokenData::decode(token)?;
|
let data = TokenData::decode(token)?;
|
||||||
|
|
||||||
let token_info =
|
let token_info =
|
||||||
|
|
|
||||||
107
src/graphql/mod.rs
Normal file
107
src/graphql/mod.rs
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
use chrono::NaiveDateTime;
|
||||||
|
use juniper::{graphql_object, EmptyMutation, EmptySubscription, GraphQLObject, RootNode, ScalarValue};
|
||||||
|
use rocket::response::content::RawHtml;
|
||||||
|
use rocket::State;
|
||||||
|
use crate::account::account::{read_basic_auth_token, read_bearer_auth_token};
|
||||||
|
use crate::nnid::oauth::TokenData;
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub type Schema = RootNode<
|
||||||
|
'static,
|
||||||
|
Query,
|
||||||
|
EmptyMutation<Context>,
|
||||||
|
EmptySubscription<Context>
|
||||||
|
>;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Context(pub Pool);
|
||||||
|
impl juniper::Context for Context{}
|
||||||
|
|
||||||
|
#[derive(GraphQLObject)]
|
||||||
|
#[graphql(description = "Data inside of a token")]
|
||||||
|
struct TokenInfo {
|
||||||
|
pid: i32,
|
||||||
|
expire_date: NaiveDateTime,
|
||||||
|
title_id: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Query;
|
||||||
|
|
||||||
|
#[graphql_object]
|
||||||
|
#[graphql(context = Context)]
|
||||||
|
impl Query {
|
||||||
|
fn api_version() -> &'static str {
|
||||||
|
"1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn token(
|
||||||
|
token_data: String,
|
||||||
|
context: &Context,
|
||||||
|
) -> Option<TokenInfo>{
|
||||||
|
let data = TokenData::decode(&token_data)?;
|
||||||
|
|
||||||
|
let token_info =
|
||||||
|
sqlx::query!(
|
||||||
|
"select * from tokens where pid = $1 and token_id = $2 and random = $3",
|
||||||
|
data.pid, data.token_id, data.random
|
||||||
|
).
|
||||||
|
fetch_one(&context.0).await.ok()?;
|
||||||
|
|
||||||
|
Some(TokenInfo{
|
||||||
|
pid: data.pid,
|
||||||
|
expire_date: token_info.expires,
|
||||||
|
title_id: token_info.title_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct Mutation;
|
||||||
|
|
||||||
|
|
||||||
|
#[graphql_object]
|
||||||
|
#[graphql(
|
||||||
|
context = Context,
|
||||||
|
// If we need to use `ScalarValue` parametrization explicitly somewhere
|
||||||
|
// in the object definition (like here in `FieldResult`), we could
|
||||||
|
// declare an explicit type parameter for that, and specify it.
|
||||||
|
scalar = S: ScalarValue + Display,
|
||||||
|
)]
|
||||||
|
impl Mutation {
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[rocket::get("/graphiql")]
|
||||||
|
pub fn graphiql() -> RawHtml<String> {
|
||||||
|
juniper_rocket::graphiql_source("/graphql", None)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[rocket::get("/playground")]
|
||||||
|
pub fn playground() -> RawHtml<String> {
|
||||||
|
juniper_rocket::playground_source("/graphql", None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::get("/graphql?<request..>")]
|
||||||
|
pub async fn get_graphql(
|
||||||
|
db: &State<Context>,
|
||||||
|
request: juniper_rocket::GraphQLRequest,
|
||||||
|
schema: &State<Schema>,
|
||||||
|
) -> juniper_rocket::GraphQLResponse {
|
||||||
|
request.execute(schema, db).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::post("/graphql", data = "<request>")]
|
||||||
|
pub async fn post_graphql(
|
||||||
|
db: &State<Context>,
|
||||||
|
request: juniper_rocket::GraphQLRequest,
|
||||||
|
schema: &State<Schema>,
|
||||||
|
) -> juniper_rocket::GraphQLResponse {
|
||||||
|
request.execute(schema, db).await
|
||||||
|
}
|
||||||
103
src/grpc/mod.rs
103
src/grpc/mod.rs
|
|
@ -1,30 +1,103 @@
|
||||||
use tonic::{async_trait, Request, Response, Status};
|
|
||||||
use crate::grpc::grpc::{ExchangeTokenForUserDataRequest, GetNexDataRequest, GetNexDataResponse, GetNexPasswordRequest, GetNexPasswordResponse, GetUserDataRequest, GetUserDataResponse, UpdatePnidPermissionsRequest};
|
|
||||||
use crate::Pool;
|
use crate::Pool;
|
||||||
|
use crate::grpc::grpc::{
|
||||||
|
ExchangeTokenForUserDataRequest, GetNexDataRequest, GetNexDataResponse, GetNexPasswordRequest,
|
||||||
|
GetNexPasswordResponse, GetUserDataRequest, GetUserDataResponse, UpdatePnidPermissionsRequest,
|
||||||
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::env;
|
||||||
|
use tonic::metadata::MetadataMap;
|
||||||
|
use tonic::{Request, Response, Status, async_trait};
|
||||||
|
|
||||||
mod grpc {
|
/// This module is a legacy module meant for interacting with existing pretendo
|
||||||
|
/// servers. This will inevitably be removed completely as this is only meant as
|
||||||
|
/// a stopgap until RNEX is in a fully functional state.
|
||||||
|
|
||||||
|
pub mod grpc {
|
||||||
tonic::include_proto!("account");
|
tonic::include_proto!("account");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GRPC_PASSWORD: Lazy<Box<str>> = Lazy::new(|| {
|
||||||
|
env::var("GRPC_PASSWORD")
|
||||||
|
.expect("GRPC_PASSWORD not specified")
|
||||||
|
.into_boxed_str()
|
||||||
|
});
|
||||||
|
|
||||||
|
fn verify_grpc_key(meta: &MetadataMap) -> Result<(), Status> {
|
||||||
|
// req.metadata_mut().insert("x-api-key", API_KEY.clone());
|
||||||
|
|
||||||
|
let key = meta
|
||||||
|
.get("x-api-key")
|
||||||
|
.ok_or(Status::permission_denied("api key missing"))?;
|
||||||
|
|
||||||
|
if key.as_bytes() != GRPC_PASSWORD.as_bytes() {
|
||||||
|
return Err(Status::permission_denied("GO AWAY"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AccountService(pub Pool);
|
pub struct AccountService(pub Pool);
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl grpc::account_server::Account for AccountService{
|
impl grpc::account_server::Account for AccountService {
|
||||||
async fn exchange_token_for_user_data(&self, request: Request<ExchangeTokenForUserDataRequest>) -> Result<Response<GetUserDataResponse>, Status> {
|
async fn exchange_token_for_user_data(
|
||||||
todo!()
|
&self,
|
||||||
|
request: Request<ExchangeTokenForUserDataRequest>,
|
||||||
|
) -> Result<Response<GetUserDataResponse>, Status> {
|
||||||
|
verify_grpc_key(request.metadata())?;
|
||||||
|
|
||||||
|
Err(Status::unimplemented(
|
||||||
|
"grpc tecnically isnt supported by account-rs as such no full support is guaranteed(you called a stubbed function)",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
async fn get_nex_data(&self, request: Request<GetNexDataRequest>) -> Result<Response<GetNexDataResponse>, Status> {
|
async fn get_nex_data(
|
||||||
todo!()
|
&self,
|
||||||
|
request: Request<GetNexDataRequest>,
|
||||||
|
) -> Result<Response<GetNexDataResponse>, Status> {
|
||||||
|
verify_grpc_key(request.metadata())?;
|
||||||
|
|
||||||
|
Err(Status::unimplemented(
|
||||||
|
"grpc tecnically isnt supported by account-rs as such no full support is guaranteed(you called a stubbed function)",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
async fn get_nex_password(&self, request: Request<GetNexPasswordRequest>) -> Result<Response<GetNexPasswordResponse>, Status> {
|
async fn get_nex_password(
|
||||||
todo!()
|
&self,
|
||||||
|
request: Request<GetNexPasswordRequest>,
|
||||||
|
) -> Result<Response<GetNexPasswordResponse>, Status> {
|
||||||
|
verify_grpc_key(request.metadata())?;
|
||||||
|
|
||||||
|
let data = request.get_ref();
|
||||||
|
|
||||||
|
let password = sqlx::query!(
|
||||||
|
"select nex_password from users where pid = $1",
|
||||||
|
data.pid as i32
|
||||||
|
)
|
||||||
|
.fetch_one(&self.0)
|
||||||
|
.await
|
||||||
|
.map_err(|_| Status::invalid_argument("No NEX account found"))?
|
||||||
|
.nex_password;
|
||||||
|
|
||||||
|
Ok(Response::new(GetNexPasswordResponse { password }))
|
||||||
}
|
}
|
||||||
async fn update_pnid_permissions(&self, request: Request<UpdatePnidPermissionsRequest>) -> Result<Response<()>, Status> {
|
async fn update_pnid_permissions(
|
||||||
todo!()
|
&self,
|
||||||
|
request: Request<UpdatePnidPermissionsRequest>,
|
||||||
|
) -> Result<Response<()>, Status> {
|
||||||
|
verify_grpc_key(request.metadata())?;
|
||||||
|
|
||||||
|
Err(Status::unimplemented(
|
||||||
|
"grpc tecnically isnt supported by account-rs as such no full support is guaranteed(you called a stubbed function)",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_data(&self, request: Request<GetUserDataRequest>) -> Result<Response<GetUserDataResponse>, Status> {
|
async fn get_user_data(
|
||||||
todo!()
|
&self,
|
||||||
|
request: Request<GetUserDataRequest>,
|
||||||
|
) -> Result<Response<GetUserDataResponse>, Status> {
|
||||||
|
verify_grpc_key(request.metadata())?;
|
||||||
|
|
||||||
|
Err(Status::unimplemented(
|
||||||
|
"grpc tecnically isnt supported by account-rs as such no full support is guaranteed(you called a stubbed function)",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
src/main.rs
59
src/main.rs
|
|
@ -1,15 +1,20 @@
|
||||||
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
|
use juniper::{EmptyMutation, EmptySubscription};
|
||||||
use log::info;
|
use log::info;
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
|
use rocket::futures::FutureExt;
|
||||||
use rocket::http::Header;
|
use rocket::http::Header;
|
||||||
use rocket::routes;
|
use rocket::routes;
|
||||||
use sqlx::Postgres;
|
use sqlx::Postgres;
|
||||||
use sqlx::postgres::PgPoolOptions;
|
use sqlx::postgres::PgPoolOptions;
|
||||||
|
use tonic::transport::Server;
|
||||||
|
use crate::graphql::{Query, Schema};
|
||||||
|
|
||||||
mod xml;
|
mod xml;
|
||||||
mod conntest;
|
mod conntest;
|
||||||
|
|
@ -18,15 +23,49 @@ mod account;
|
||||||
mod error;
|
mod error;
|
||||||
mod dsresponse;
|
mod dsresponse;
|
||||||
mod data_wrapper;
|
mod data_wrapper;
|
||||||
|
#[deprecated]
|
||||||
mod grpc;
|
mod grpc;
|
||||||
|
mod graphql;
|
||||||
|
|
||||||
type Pool = sqlx::Pool<Postgres>;
|
type Pool = sqlx::Pool<Postgres>;
|
||||||
|
|
||||||
|
async fn start_grpc(){
|
||||||
|
let act_database_url = env::var("DATABASE_URL").expect("account database url is not set");
|
||||||
|
|
||||||
|
let pool = PgPoolOptions::new()
|
||||||
|
.max_connections(5)
|
||||||
|
.connect(&act_database_url)
|
||||||
|
.await
|
||||||
|
.expect("unable to create pool");
|
||||||
|
|
||||||
|
let grpc_instance = grpc::AccountService(pool);
|
||||||
|
|
||||||
|
let addr: SocketAddr =
|
||||||
|
SocketAddr::from((
|
||||||
|
env::var("ROCKET_ADDRESS").ok()
|
||||||
|
.map(|v| v.parse().expect("unable to read address"))
|
||||||
|
.unwrap_or(IpAddr::V4(Ipv4Addr::LOCALHOST)),
|
||||||
|
7071
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tokio::spawn(async move{
|
||||||
|
Server::builder()
|
||||||
|
.add_service(grpc::grpc::account_server::AccountServer::new(grpc_instance))
|
||||||
|
.serve(addr)
|
||||||
|
.await
|
||||||
|
.expect("unable to start grpc server");
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[rocket::launch]
|
#[rocket::launch]
|
||||||
async fn launch() -> _ {
|
async fn launch() -> _ {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
|
|
||||||
|
start_grpc().await;
|
||||||
|
|
||||||
let act_database_url = env::var("DATABASE_URL").expect("account database url is not set");
|
let act_database_url = env::var("DATABASE_URL").expect("account database url is not set");
|
||||||
|
|
||||||
|
|
@ -35,8 +74,19 @@ async fn launch() -> _ {
|
||||||
.connect(&act_database_url).await
|
.connect(&act_database_url).await
|
||||||
.expect("unable to create pool");
|
.expect("unable to create pool");
|
||||||
|
|
||||||
|
let graph_pool = PgPoolOptions::new()
|
||||||
|
.max_connections(5)
|
||||||
|
.connect(&act_database_url).await
|
||||||
|
.expect("unable to create pool");
|
||||||
|
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.manage(pool)
|
.manage(pool)
|
||||||
|
.manage(graphql::Context(graph_pool))
|
||||||
|
.manage(Schema::new(
|
||||||
|
Query,
|
||||||
|
EmptyMutation::new(),
|
||||||
|
EmptySubscription::new())
|
||||||
|
)
|
||||||
.attach(AdHoc::on_response("org", |_, response| Box::pin(async move {
|
.attach(AdHoc::on_response("org", |_, response| Box::pin(async move {
|
||||||
//response.adjoin_header(Header::new("x-organization", "Nintendo"));
|
//response.adjoin_header(Header::new("x-organization", "Nintendo"));
|
||||||
response.adjoin_header(Header::new("x-nintendo-date", SystemTime::now()
|
response.adjoin_header(Header::new("x-nintendo-date", SystemTime::now()
|
||||||
|
|
@ -64,5 +114,12 @@ async fn launch() -> _ {
|
||||||
nnid::people::get_own_profile,
|
nnid::people::get_own_profile,
|
||||||
nnid::oauth::generate_token::generate_token,
|
nnid::oauth::generate_token::generate_token,
|
||||||
nnid::provider::get_nex_token,
|
nnid::provider::get_nex_token,
|
||||||
|
nnid::provider::get_service_token,
|
||||||
|
nnid::mapped_ids::mapped_ids,
|
||||||
|
//graphql
|
||||||
|
graphql::graphiql,
|
||||||
|
graphql::playground,
|
||||||
|
graphql::get_graphql,
|
||||||
|
graphql::post_graphql,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
83
src/nnid/mapped_ids.rs
Normal file
83
src/nnid/mapped_ids.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
use rocket::{get, State};
|
||||||
|
use serde::Serialize;
|
||||||
|
use crate::Pool;
|
||||||
|
use crate::xml::Xml;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(rename = "mapped_id")]
|
||||||
|
struct MappedId {
|
||||||
|
in_id: String,
|
||||||
|
out_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(rename = "mapped_ids")]
|
||||||
|
struct MappedIds {
|
||||||
|
mapped_id: Vec<MappedId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UserIdAndName {
|
||||||
|
pid: i32,
|
||||||
|
username: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v1/api/admin/mapped_ids?<input_type>&<output_type>&<input>")]
|
||||||
|
pub async fn mapped_ids(pool: &State<Pool>, input_type: String, output_type: String, input: String) -> Option<Xml<MappedIds>> {
|
||||||
|
let pool = pool.inner();
|
||||||
|
|
||||||
|
let is_input_pid = input_type == "pid";
|
||||||
|
let is_output_pid = output_type == "pid";
|
||||||
|
|
||||||
|
let mut outputs = Vec::new();
|
||||||
|
|
||||||
|
for input in input.split(',') {
|
||||||
|
if input == ""{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let Some(user) =
|
||||||
|
(if is_input_pid {
|
||||||
|
let id: i32 = input.parse().ok()?;
|
||||||
|
|
||||||
|
sqlx::query_as!(
|
||||||
|
UserIdAndName,
|
||||||
|
"select pid, username from users where pid = $1",
|
||||||
|
id
|
||||||
|
).fetch_one(pool)
|
||||||
|
.await.ok()
|
||||||
|
} else {
|
||||||
|
sqlx::query_as!(
|
||||||
|
UserIdAndName,
|
||||||
|
"select pid, username from users where username = $1",
|
||||||
|
input
|
||||||
|
).fetch_one(pool)
|
||||||
|
.await.ok()
|
||||||
|
}) else {
|
||||||
|
outputs.push(MappedId{
|
||||||
|
in_id: input.to_string(),
|
||||||
|
out_id: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
continue
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if is_output_pid{
|
||||||
|
outputs.push(MappedId{
|
||||||
|
in_id: input.to_string(),
|
||||||
|
out_id: Some(user.pid.to_string()),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
outputs.push(MappedId{
|
||||||
|
in_id: input.to_string(),
|
||||||
|
out_id: Some(user.username),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Xml(
|
||||||
|
MappedIds{
|
||||||
|
mapped_id: outputs
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
@ -7,3 +7,4 @@ pub mod oauth;
|
||||||
mod pid_distribution;
|
mod pid_distribution;
|
||||||
pub mod people;
|
pub mod people;
|
||||||
pub mod provider;
|
pub mod provider;
|
||||||
|
pub mod mapped_ids;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,19 @@ use sqlx::types::ipnetwork::IpNetwork::V4;
|
||||||
use crate::account::account::Auth;
|
use crate::account::account::Auth;
|
||||||
use crate::nnid::oauth::generate_token::create_token;
|
use crate::nnid::oauth::generate_token::create_token;
|
||||||
use crate::nnid::oauth::generate_token::token_type::NEX_TOKEN;
|
use crate::nnid::oauth::generate_token::token_type::NEX_TOKEN;
|
||||||
|
use crate::nnid::provider::Test::{A, B};
|
||||||
use crate::Pool;
|
use crate::Pool;
|
||||||
use crate::xml::Xml;
|
use crate::xml::Xml;
|
||||||
|
|
||||||
|
enum Test{
|
||||||
|
A(String),
|
||||||
|
B(i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(rename = "nex_token")]
|
#[serde(rename = "nex_token")]
|
||||||
struct NexToken{
|
pub struct NexToken{
|
||||||
host: Ipv4Addr,
|
host: Ipv4Addr,
|
||||||
nex_password: String,
|
nex_password: String,
|
||||||
pid: i32,
|
pid: i32,
|
||||||
|
|
@ -19,20 +26,51 @@ struct NexToken{
|
||||||
token: String
|
token: String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/v1/api/provider/nex_token/@me?<game_server_id>")]
|
#[derive(Serialize)]
|
||||||
pub async fn get_nex_token(pool: &State<Pool>, auth: Auth<true>, game_server_id: String) -> Option<Xml<NexToken>>{
|
#[serde(rename = "service_token")]
|
||||||
|
pub struct ServiceToken{
|
||||||
|
token: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v1/api/provider/service_token/@me")]
|
||||||
|
pub async fn get_service_token(pool: &State<Pool>, auth: Auth<true>) -> Option<Xml<ServiceToken>>{
|
||||||
// just gonna put this here as a side note for the future:
|
// just gonna put this here as a side note for the future:
|
||||||
// we could also be using key derivation to derive the nex token as if it were a key
|
// we could also be using key derivation to derive the nex token as if it were a key
|
||||||
// that way we could reduce the data the database needs to store and also reduce the transfer
|
// that way we could reduce the data the database needs to store and also reduce the transfer
|
||||||
// cost of sending an entire row from the user table (which is required for the auth code unless
|
// cost of sending an entire row from the user table (which is required for the auth code unless
|
||||||
// we change the way we read in data to essentially having the user object be a proxy for its
|
// we change the way we read in data to essentially having the user object be a proxy for its
|
||||||
// table row)
|
// table row)
|
||||||
|
|
||||||
|
let pool = pool.inner();
|
||||||
|
|
||||||
|
let token = create_token(pool, auth.pid, NEX_TOKEN, None).await;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Some(
|
||||||
|
Xml(
|
||||||
|
ServiceToken{
|
||||||
|
token
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v1/api/provider/nex_token/@me?<game_server_id>")]
|
||||||
|
pub async fn get_nex_token(pool: &State<Pool>, auth: Auth<true>, game_server_id: &str) -> Option<Xml<NexToken>>{
|
||||||
|
// just gonna put this here as a side note for the future:
|
||||||
|
// we could also be using key derivation to derive the nex token as if it were a key
|
||||||
|
// that way we could reduce the data the database needs to store and also reduce the transfer
|
||||||
|
// cost of sending an entire row from the user table (which is required for the auth code unless
|
||||||
|
// we change the way we read in data to essentially having the user object be a proxy for its
|
||||||
|
// table row)
|
||||||
|
|
||||||
let pool = pool.inner();
|
let pool = pool.inner();
|
||||||
|
|
||||||
let server = sqlx::query!(
|
let server = sqlx::query!(
|
||||||
"select * from nex_servers where game_server_id = $1",
|
"select address, port from nex_servers where game_server_id = $1",
|
||||||
game_server_id
|
game_server_id
|
||||||
) .fetch_one(pool).await.ok()?;
|
) .fetch_one(pool).await.unwrap();
|
||||||
|
|
||||||
let token = create_token(pool, auth.pid, NEX_TOKEN, None).await;
|
let token = create_token(pool, auth.pid, NEX_TOKEN, None).await;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue