fix up routes and add email resending
All checks were successful
Build and Test / account (push) Successful in 5m36s

This commit is contained in:
red binder 2026-06-06 14:31:19 +02:00
commit cf5dd20132
22 changed files with 622 additions and 101 deletions

View file

@ -6,7 +6,8 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "exists", "name": "exists",
"type_info": "Bool" "type_info": "Bool",
"origin": "Expression"
} }
], ],
"parameters": { "parameters": {

View file

@ -0,0 +1,52 @@
{
"db_name": "PostgreSQL",
"query": "SELECT username, verification_code, email FROM users WHERE pid = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "username",
"type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
},
{
"ordinal": 1,
"name": "verification_code",
"type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "verification_code"
}
}
},
{
"ordinal": 2,
"name": "email",
"type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "email"
}
}
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false,
false,
false
]
},
"hash": "1ceb8af3151c013c341d9c0cafe67ab8f7901a9612da8077b87a7b8533b0dfcb"
}

View file

@ -6,7 +6,8 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int8" "type_info": "Int8",
"origin": "Expression"
} }
], ],
"parameters": { "parameters": {

View file

@ -6,32 +6,68 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "token_id", "name": "token_id",
"type_info": "Int8" "type_info": "Int8",
"origin": {
"Table": {
"table": "tokens",
"name": "token_id"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "token_type", "name": "token_type",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "token_type"
}
}
}, },
{ {
"ordinal": 3, "ordinal": 3,
"name": "random", "name": "random",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "random"
}
}
}, },
{ {
"ordinal": 4, "ordinal": 4,
"name": "title_id", "name": "title_id",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "tokens",
"name": "title_id"
}
}
}, },
{ {
"ordinal": 5, "ordinal": 5,
"name": "expires", "name": "expires",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "tokens",
"name": "expires"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,12 +6,24 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,12 +6,24 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "address", "name": "address",
"type_info": "Inet" "type_info": "Inet",
"origin": {
"Table": {
"table": "nex_servers",
"name": "address"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "port", "name": "port",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "nex_servers",
"name": "port"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,97 +6,211 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "password", "name": "password",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "password"
}
}
}, },
{ {
"ordinal": 3, "ordinal": 3,
"name": "birthdate", "name": "birthdate",
"type_info": "Date" "type_info": "Date",
"origin": {
"Table": {
"table": "users",
"name": "birthdate"
}
}
}, },
{ {
"ordinal": 4, "ordinal": 4,
"name": "timezone", "name": "timezone",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "timezone"
}
}
}, },
{ {
"ordinal": 5, "ordinal": 5,
"name": "email", "name": "email",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "email"
}
}
}, },
{ {
"ordinal": 6, "ordinal": 6,
"name": "email_verified_since", "name": "email_verified_since",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "users",
"name": "email_verified_since"
}
}
}, },
{ {
"ordinal": 7, "ordinal": 7,
"name": "country", "name": "country",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "country"
}
}
}, },
{ {
"ordinal": 8, "ordinal": 8,
"name": "language", "name": "language",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "language"
}
}
}, },
{ {
"ordinal": 9, "ordinal": 9,
"name": "gender", "name": "gender",
"type_info": "Bpchar" "type_info": "Bpchar",
"origin": {
"Table": {
"table": "users",
"name": "gender"
}
}
}, },
{ {
"ordinal": 10, "ordinal": 10,
"name": "marketing_allowed", "name": "marketing_allowed",
"type_info": "Bool" "type_info": "Bool",
"origin": {
"Table": {
"table": "users",
"name": "marketing_allowed"
}
}
}, },
{ {
"ordinal": 11, "ordinal": 11,
"name": "off_device_allowed", "name": "off_device_allowed",
"type_info": "Bool" "type_info": "Bool",
"origin": {
"Table": {
"table": "users",
"name": "off_device_allowed"
}
}
}, },
{ {
"ordinal": 12, "ordinal": 12,
"name": "region", "name": "region",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "region"
}
}
}, },
{ {
"ordinal": 13, "ordinal": 13,
"name": "mii_data", "name": "mii_data",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "mii_data"
}
}
}, },
{ {
"ordinal": 14, "ordinal": 14,
"name": "account_level", "name": "account_level",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "account_level"
}
}
}, },
{ {
"ordinal": 15, "ordinal": 15,
"name": "creation_date", "name": "creation_date",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "users",
"name": "creation_date"
}
}
}, },
{ {
"ordinal": 16, "ordinal": 16,
"name": "updated", "name": "updated",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "users",
"name": "updated"
}
}
}, },
{ {
"ordinal": 17, "ordinal": 17,
"name": "nex_password", "name": "nex_password",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "nex_password"
}
}
}, },
{ {
"ordinal": 18, "ordinal": 18,
"name": "verification_code", "name": "verification_code",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "verification_code"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "select nex_password from users where pid = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "nex_password",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false
]
},
"hash": "6c1df0b05553305ba847f571a5859bf11353f28c25e4f81268e9379b5b2cb375"
}

View file

@ -6,27 +6,57 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "account_level", "name": "account_level",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "account_level"
}
}
}, },
{ {
"ordinal": 3, "ordinal": 3,
"name": "nex_password", "name": "nex_password",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "nex_password"
}
}
}, },
{ {
"ordinal": 4, "ordinal": 4,
"name": "mii_data", "name": "mii_data",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "mii_data"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,97 +6,211 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "password", "name": "password",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "password"
}
}
}, },
{ {
"ordinal": 3, "ordinal": 3,
"name": "birthdate", "name": "birthdate",
"type_info": "Date" "type_info": "Date",
"origin": {
"Table": {
"table": "users",
"name": "birthdate"
}
}
}, },
{ {
"ordinal": 4, "ordinal": 4,
"name": "timezone", "name": "timezone",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "timezone"
}
}
}, },
{ {
"ordinal": 5, "ordinal": 5,
"name": "email", "name": "email",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "email"
}
}
}, },
{ {
"ordinal": 6, "ordinal": 6,
"name": "email_verified_since", "name": "email_verified_since",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "users",
"name": "email_verified_since"
}
}
}, },
{ {
"ordinal": 7, "ordinal": 7,
"name": "country", "name": "country",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "country"
}
}
}, },
{ {
"ordinal": 8, "ordinal": 8,
"name": "language", "name": "language",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "language"
}
}
}, },
{ {
"ordinal": 9, "ordinal": 9,
"name": "gender", "name": "gender",
"type_info": "Bpchar" "type_info": "Bpchar",
"origin": {
"Table": {
"table": "users",
"name": "gender"
}
}
}, },
{ {
"ordinal": 10, "ordinal": 10,
"name": "marketing_allowed", "name": "marketing_allowed",
"type_info": "Bool" "type_info": "Bool",
"origin": {
"Table": {
"table": "users",
"name": "marketing_allowed"
}
}
}, },
{ {
"ordinal": 11, "ordinal": 11,
"name": "off_device_allowed", "name": "off_device_allowed",
"type_info": "Bool" "type_info": "Bool",
"origin": {
"Table": {
"table": "users",
"name": "off_device_allowed"
}
}
}, },
{ {
"ordinal": 12, "ordinal": 12,
"name": "region", "name": "region",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "region"
}
}
}, },
{ {
"ordinal": 13, "ordinal": 13,
"name": "mii_data", "name": "mii_data",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "mii_data"
}
}
}, },
{ {
"ordinal": 14, "ordinal": 14,
"name": "account_level", "name": "account_level",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "account_level"
}
}
}, },
{ {
"ordinal": 15, "ordinal": 15,
"name": "creation_date", "name": "creation_date",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "users",
"name": "creation_date"
}
}
}, },
{ {
"ordinal": 16, "ordinal": 16,
"name": "updated", "name": "updated",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "users",
"name": "updated"
}
}
}, },
{ {
"ordinal": 17, "ordinal": 17,
"name": "nex_password", "name": "nex_password",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "nex_password"
}
}
}, },
{ {
"ordinal": 18, "ordinal": 18,
"name": "verification_code", "name": "verification_code",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "verification_code"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,32 +6,68 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "token_id", "name": "token_id",
"type_info": "Int8" "type_info": "Int8",
"origin": {
"Table": {
"table": "tokens",
"name": "token_id"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "token_type", "name": "token_type",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "token_type"
}
}
}, },
{ {
"ordinal": 3, "ordinal": 3,
"name": "random", "name": "random",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "random"
}
}
}, },
{ {
"ordinal": 4, "ordinal": 4,
"name": "title_id", "name": "title_id",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "tokens",
"name": "title_id"
}
}
}, },
{ {
"ordinal": 5, "ordinal": 5,
"name": "expires", "name": "expires",
"type_info": "Timestamp" "type_info": "Timestamp",
"origin": {
"Table": {
"table": "tokens",
"name": "expires"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,7 +6,13 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "mii_data", "name": "mii_data",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "mii_data"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,7 +6,13 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "verification_code", "name": "verification_code",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "verification_code"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,7 +6,8 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "exists", "name": "exists",
"type_info": "Bool" "type_info": "Bool",
"origin": "Expression"
} }
], ],
"parameters": { "parameters": {

View file

@ -6,22 +6,46 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "account_level", "name": "account_level",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "account_level"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "nex_password", "name": "nex_password",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "nex_password"
}
}
}, },
{ {
"ordinal": 3, "ordinal": 3,
"name": "mii_data", "name": "mii_data",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "mii_data"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,12 +6,24 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "token_id", "name": "token_id",
"type_info": "Int8" "type_info": "Int8",
"origin": {
"Table": {
"table": "tokens",
"name": "token_id"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "random", "name": "random",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "tokens",
"name": "random"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,12 +6,24 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -6,17 +6,35 @@
{ {
"ordinal": 0, "ordinal": 0,
"name": "pid", "name": "pid",
"type_info": "Int4" "type_info": "Int4",
"origin": {
"Table": {
"table": "users",
"name": "pid"
}
}
}, },
{ {
"ordinal": 1, "ordinal": 1,
"name": "username", "name": "username",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "username"
}
}
}, },
{ {
"ordinal": 2, "ordinal": 2,
"name": "mii_data", "name": "mii_data",
"type_info": "Varchar" "type_info": "Varchar",
"origin": {
"Table": {
"table": "users",
"name": "mii_data"
}
}
} }
], ],
"parameters": { "parameters": {

View file

@ -100,6 +100,7 @@ async fn launch() -> _ {
nnid::person_exists::person_exists, nnid::person_exists::person_exists,
nnid::support::validate, nnid::support::validate,
nnid::support::verify_email, nnid::support::verify_email,
nnid::support::resend_email,
nnid::people::create_account, nnid::people::create_account,
nnid::people::get_own_profile, nnid::people::get_own_profile,
nnid::people::get_device_owner, nnid::people::get_device_owner,
@ -109,8 +110,8 @@ async fn launch() -> _ {
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::provider::get_service_token,
nnid::mapped_ids::mapped_ids, nnid::admin::mapped_ids,
nnid::mapped_ids::get_time, nnid::admin::get_time,
json_api::oauth::generate_token::generate_token, json_api::oauth::generate_token::generate_token,
json_api::users::profile::get_own_profile, json_api::users::profile::get_own_profile,
json_api::users::mii::get_mii_data_by_pid, json_api::users::mii::get_mii_data_by_pid,

View file

@ -6,6 +6,6 @@ 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; pub mod admin;
pub mod support; pub mod support;
pub mod miis; pub mod miis;

View file

@ -3,7 +3,9 @@ use crate::error::{Error, Errors};
use chrono::Utc; use chrono::Utc;
use hickory_resolver::TokioAsyncResolver; use hickory_resolver::TokioAsyncResolver;
use rocket::form::Form; use rocket::form::Form;
use rocket::{FromForm, State, post, put}; use rocket::{FromForm, State, post, put, get, Request};
use rocket::request::{self, FromRequest};
use rocket::http::Status;
const BAD_CODE_ERROR: Errors = Errors { const BAD_CODE_ERROR: Errors = Errors {
error: &[Error { error: &[Error {
@ -17,6 +19,25 @@ pub struct ValidateEmailInput {
email: String, email: String,
} }
// sorry maple i really tried and couldn't find a better way
pub struct EmailPid(pub i32);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for EmailPid {
type Error = Errors<'static>;
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
match req.headers().get_one("x-nintendo-pid") {
Some(val) => match val.parse::<i32>() {
Ok(parsed_id) => request::Outcome::Success(EmailPid(parsed_id)),
Err(_) => request::Outcome::Error((Status::BadRequest, BAD_CODE_ERROR)),
},
None => request::Outcome::Error((Status::BadRequest, BAD_CODE_ERROR)),
}
}
}
// i was tired at 1 am ok have mercy
#[post("/v1/api/support/validate/email", data = "<data>")] #[post("/v1/api/support/validate/email", data = "<data>")]
pub async fn validate( pub async fn validate(
data: Form<ValidateEmailInput>, data: Form<ValidateEmailInput>,
@ -106,3 +127,37 @@ pub async fn verify_email(
Err(BAD_CODE_ERROR) Err(BAD_CODE_ERROR)
} }
#[get("/v1/api/support/resend_confirmation")]
pub async fn resend_email(
database: &State<Pool>,
pid: EmailPid,
) -> Result<(), Errors<'static>> {
let pid = pid.0;
let user_data = sqlx::query!(
"SELECT username, verification_code, email FROM users WHERE pid = $1",
pid
)
.fetch_optional(&**database)
.await
.map_err(|e| {
eprintln!("{}", e);
BAD_CODE_ERROR
})?;
let user = match user_data {
Some(row) => row,
None => return Err(BAD_CODE_ERROR),
};
crate::email::send_verification_email(&user.email, user.verification_code, &user.username)
.await
.map_err(|e| {
eprintln!("Failed to send email: {}", e);
BAD_CODE_ERROR
})?;
Ok(())
}