This commit is contained in:
parent
fa063d78fb
commit
124916e62c
6 changed files with 556 additions and 0 deletions
15
.sqlx/query-7d5d57a9c0065301382767c85de4f25f0636ec0e7c0beed4cdb627c419e407c4.json
generated
Normal file
15
.sqlx/query-7d5d57a9c0065301382767c85de4f25f0636ec0e7c0beed4cdb627c419e407c4.json
generated
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n INSERT INTO device_parental_controls (serial_number, email, updated_at)\n VALUES ($1, $2, NOW())\n ON CONFLICT (serial_number)\n DO UPDATE SET email = EXCLUDED.email, updated_at = NOW()\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Varchar",
|
||||||
|
"Varchar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "7d5d57a9c0065301382767c85de4f25f0636ec0e7c0beed4cdb627c419e407c4"
|
||||||
|
}
|
||||||
190
res/email/masterKeyTemplate.html
Normal file
190
res/email/masterKeyTemplate.html
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" lang="en">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="color-scheme" content="light dark">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
supported-color-schemes:light dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
body.email-body,
|
||||||
|
table.centerer,
|
||||||
|
table.wrapper {
|
||||||
|
background-color: #FFFFFF !important;
|
||||||
|
color: #000000 !important;
|
||||||
|
}
|
||||||
|
table.card {
|
||||||
|
background-color: #B60000 !important;
|
||||||
|
}
|
||||||
|
span.shoutout {
|
||||||
|
color: #FFB3B3 !important;
|
||||||
|
}
|
||||||
|
td.confirm-link {
|
||||||
|
background-color: #FF4D4D !important;
|
||||||
|
}
|
||||||
|
td.confirm-code {
|
||||||
|
background-color: #FFB3B3 !important;
|
||||||
|
color: #660000 !important;
|
||||||
|
}
|
||||||
|
td.notice {
|
||||||
|
color: #FF4D4D !important;
|
||||||
|
}
|
||||||
|
td.notice a {
|
||||||
|
color: #B60000 !important;
|
||||||
|
}
|
||||||
|
img.logo {
|
||||||
|
content: url("https://spfn.spbr.net/res/img/spfn.png") !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body.email-body,
|
||||||
|
table.centerer,
|
||||||
|
table.wrapper {
|
||||||
|
background-color: #3B1B1B !important;
|
||||||
|
color: #FFFFFF !important;
|
||||||
|
}
|
||||||
|
table.card {
|
||||||
|
background-color: #4A2323 !important;
|
||||||
|
}
|
||||||
|
span.shoutout {
|
||||||
|
color: #FF9999 !important;
|
||||||
|
}
|
||||||
|
td.confirm-link {
|
||||||
|
background-color: #B60000 !important;
|
||||||
|
}
|
||||||
|
td.confirm-code {
|
||||||
|
background-color: #652323 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
td.notice {
|
||||||
|
color: #C18989 !important;
|
||||||
|
}
|
||||||
|
td.notice a {
|
||||||
|
color: #F5C1C1 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="email-body" bgcolor="#1B1F3B" style="margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; font-family: Poppins, Arial, Helvetica, sans-serif;">
|
||||||
|
<div style="display:none;">Hello. You have requested a reset of parental controls on your console.</div>
|
||||||
|
<table class="centerer" bgcolor="#1B1F3B" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table class="wrapper" bgcolor="#1B1F3B" style="font-family: Poppins, Arial, Helvetica, sans-serif;" border="0" cellpadding="0" cellspacing="0" height="100%" width="420px">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td width="32px"> </td>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td height="36px" style="line-height: 36px;" width="100%"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="https://spfn.spbr.net">
|
||||||
|
<img class="logo" width="auto" height="48px" src="https://spfn.spbr.net/res/img/spfn.png" alt="SPFN">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="36px" style="line-height: 36px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table class="card" bgcolor="#23274a" style="color: #ffffff; border-radius: 10px;" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td width="24px" height="100%"> </td>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr width="100%" height="48px" style="line-height: 48px;">
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-size: 24px; font-weight: 700;">
|
||||||
|
<td>
|
||||||
|
Hello.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="color: #ffffff; ">
|
||||||
|
Your email was linked to a Wii U console with serial number {{serial}} for parental controls.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
You have requested a master key to reset your parental controls PIN. The master key you must enter on your Wii U is:
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="confirm-code" bgcolor="#373c65" style="color: #ffffff; font-size: 14px; font-weight: 700; border-radius: 10px; padding: 12px" align="center">
|
||||||
|
{{mkey}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="36px" style="line-height: 36px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Please make sure to change your PIN as soon as possible.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="right">
|
||||||
|
The SPFN team
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td width="24px" height="100%"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="18px" style="line-height: 18px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="notice" style="color: #8990c1; font-size: 12px;">
|
||||||
|
Note: this email message was auto-generated, please do not respond. For further assistance, please join our <a href="https://discord.gg/grMSxZf" style="text-decoration: none; color: #ffffff; ">Discord server</a>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="48px" style="line-height: 48px;"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td width="32px"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
177
res/email/parentalControlsTemplate.html
Normal file
177
res/email/parentalControlsTemplate.html
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" lang="en">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="color-scheme" content="light dark">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
supported-color-schemes:light dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
body.email-body,
|
||||||
|
table.centerer,
|
||||||
|
table.wrapper {
|
||||||
|
background-color: #FFFFFF !important;
|
||||||
|
color: #000000 !important;
|
||||||
|
}
|
||||||
|
table.card {
|
||||||
|
background-color: #B60000 !important;
|
||||||
|
}
|
||||||
|
span.shoutout {
|
||||||
|
color: #FFB3B3 !important;
|
||||||
|
}
|
||||||
|
td.confirm-link {
|
||||||
|
background-color: #FF4D4D !important;
|
||||||
|
}
|
||||||
|
td.confirm-code {
|
||||||
|
background-color: #FFB3B3 !important;
|
||||||
|
color: #660000 !important;
|
||||||
|
}
|
||||||
|
td.notice {
|
||||||
|
color: #FF4D4D !important;
|
||||||
|
}
|
||||||
|
td.notice a {
|
||||||
|
color: #B60000 !important;
|
||||||
|
}
|
||||||
|
img.logo {
|
||||||
|
content: url("https://spfn.spbr.net/res/img/spfn.png") !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body.email-body,
|
||||||
|
table.centerer,
|
||||||
|
table.wrapper {
|
||||||
|
background-color: #3B1B1B !important;
|
||||||
|
color: #FFFFFF !important;
|
||||||
|
}
|
||||||
|
table.card {
|
||||||
|
background-color: #4A2323 !important;
|
||||||
|
}
|
||||||
|
span.shoutout {
|
||||||
|
color: #FF9999 !important;
|
||||||
|
}
|
||||||
|
td.confirm-link {
|
||||||
|
background-color: #B60000 !important;
|
||||||
|
}
|
||||||
|
td.confirm-code {
|
||||||
|
background-color: #652323 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
td.notice {
|
||||||
|
color: #C18989 !important;
|
||||||
|
}
|
||||||
|
td.notice a {
|
||||||
|
color: #F5C1C1 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="email-body" bgcolor="#1B1F3B" style="margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; font-family: Poppins, Arial, Helvetica, sans-serif;">
|
||||||
|
<div style="display:none;">Hello. The console with the serial number {{serial}} has been linked to your email for parental controls.</div>
|
||||||
|
<table class="centerer" bgcolor="#1B1F3B" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table class="wrapper" bgcolor="#1B1F3B" style="font-family: Poppins, Arial, Helvetica, sans-serif;" border="0" cellpadding="0" cellspacing="0" height="100%" width="420px">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td width="32px"> </td>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td height="36px" style="line-height: 36px;" width="100%"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="https://spfn.spbr.net">
|
||||||
|
<img class="logo" width="auto" height="48px" src="https://spfn.spbr.net/res/img/spfn.png" alt="SPFN">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="36px" style="line-height: 36px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table class="card" bgcolor="#23274a" style="color: #ffffff; border-radius: 10px;" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td width="24px" height="100%"> </td>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
|
||||||
|
<tr width="100%" height="48px" style="line-height: 48px;">
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-size: 24px; font-weight: 700;">
|
||||||
|
<td>
|
||||||
|
Hello.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="color: #ffffff; ">
|
||||||
|
Your email was linked to a Wii U console with serial number {{serial}} for parental controls.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
If you did not authorize this, please contact our team at support@spbr.net.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="36px" style="line-height: 36px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="right">
|
||||||
|
The SPFN team
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="24px" style="line-height: 24px;"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td width="24px" height="100%"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="18px" style="line-height: 18px;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="notice" style="color: #8990c1; font-size: 12px;">
|
||||||
|
Note: this email message was auto-generated, please do not respond. For further assistance, please join our <a href="https://discord.gg/grMSxZf" style="text-decoration: none; color: #ffffff; ">Discord server</a>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="48px" style="line-height: 48px;"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td width="32px"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
67
src/email.rs
67
src/email.rs
|
|
@ -70,3 +70,70 @@ pub async fn send_reset_email(to: &str, pwd: &str, username: &str) -> Result<(),
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn send_pc_email(to: &str, serial: &str) -> Result<(), String> {
|
||||||
|
let smtp_user = env::var("SMTP_USER").map_err(|_| "SMTP_USER not set".to_string())?;
|
||||||
|
let smtp_pass = env::var("SMTP_PASS").map_err(|_| "SMTP_PASS not set".to_string())?;
|
||||||
|
let smtp_server = env::var("SMTP_SERVER").map_err(|_| "SMTP_SERVER not set".to_string())?;
|
||||||
|
|
||||||
|
// Load template
|
||||||
|
let template = fs::read_to_string("res/email/parentalControlsTemplate.html")
|
||||||
|
.map_err(|e| format!("Failed to read email template: {}", e))?;
|
||||||
|
|
||||||
|
// Replace placeholders
|
||||||
|
let body = template
|
||||||
|
.replace("{{serial}}", serial);
|
||||||
|
|
||||||
|
let email = Message::builder()
|
||||||
|
.from(smtp_user.parse().unwrap())
|
||||||
|
.to(to.parse().unwrap())
|
||||||
|
.subject("Parental controls confirmation for SPFN")
|
||||||
|
.header(lettre::message::header::ContentType::TEXT_HTML)
|
||||||
|
.body(body)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let creds = Credentials::new(smtp_user, smtp_pass);
|
||||||
|
|
||||||
|
let mailer = SmtpTransport::relay(&smtp_server)
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.credentials(creds)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
mailer.send(&email).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_reset_pin_email(to: &str, serial: &str, master_key: &str) -> Result<(), String> {
|
||||||
|
let smtp_user = env::var("SMTP_USER").map_err(|_| "SMTP_USER not set".to_string())?;
|
||||||
|
let smtp_pass = env::var("SMTP_PASS").map_err(|_| "SMTP_PASS not set".to_string())?;
|
||||||
|
let smtp_server = env::var("SMTP_SERVER").map_err(|_| "SMTP_SERVER not set".to_string())?;
|
||||||
|
|
||||||
|
// Load template
|
||||||
|
let template = fs::read_to_string("res/email/masterKeyTemplate.html")
|
||||||
|
.map_err(|e| format!("Failed to read email template: {}", e))?;
|
||||||
|
|
||||||
|
// Replace placeholders
|
||||||
|
let body = template
|
||||||
|
.replace("{{serial}}", serial)
|
||||||
|
.replace("{{mkey}}", master_key);
|
||||||
|
|
||||||
|
let email = Message::builder()
|
||||||
|
.from(smtp_user.parse().unwrap())
|
||||||
|
.to(to.parse().unwrap())
|
||||||
|
.subject("Parental controls PIN reset for SPFN")
|
||||||
|
.header(lettre::message::header::ContentType::TEXT_HTML)
|
||||||
|
.body(body)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let creds = Credentials::new(smtp_user, smtp_pass);
|
||||||
|
|
||||||
|
let mailer = SmtpTransport::relay(&smtp_server)
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.credentials(creds)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
mailer.send(&email).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -102,6 +102,8 @@ async fn launch() -> _ {
|
||||||
nnid::support::verify_email,
|
nnid::support::verify_email,
|
||||||
nnid::support::resend_email,
|
nnid::support::resend_email,
|
||||||
nnid::support::forgotten_password,
|
nnid::support::forgotten_password,
|
||||||
|
nnid::support::send_parental_controls_pin,
|
||||||
|
nnid::support::send_forgotten_pin,
|
||||||
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,
|
||||||
|
|
|
||||||
|
|
@ -220,5 +220,110 @@ pub async fn forgotten_password(
|
||||||
UNAUTHORIZED_DEVICE_ERROR
|
UNAUTHORIZED_DEVICE_ERROR
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DeviceSerial(pub String);
|
||||||
|
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl<'r> FromRequest<'r> for DeviceSerial {
|
||||||
|
type Error = Errors<'static>;
|
||||||
|
|
||||||
|
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||||
|
match req.headers().get_one("x-nintendo-serial-number") {
|
||||||
|
Some(val) if !val.trim().is_empty() => {
|
||||||
|
request::Outcome::Success(DeviceSerial(val.to_string()))
|
||||||
|
}
|
||||||
|
_ => request::Outcome::Error((
|
||||||
|
Status::BadRequest,
|
||||||
|
Errors {
|
||||||
|
error: &[Error {
|
||||||
|
code: "0130",
|
||||||
|
message: "Serial not found",
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v1/api/support/send_confirmation/pin/<email>")]
|
||||||
|
pub async fn send_parental_controls_pin(
|
||||||
|
database: &State<Pool>,
|
||||||
|
serial: DeviceSerial,
|
||||||
|
email: &str,
|
||||||
|
) -> Result<(), Errors<'static>> {
|
||||||
|
let db = database.inner();
|
||||||
|
let serial_number = serial.0;
|
||||||
|
let email = email.trim().to_lowercase();
|
||||||
|
|
||||||
|
if email.is_empty() || !email.contains('@') {
|
||||||
|
return Err(Errors {
|
||||||
|
error: &[Error {
|
||||||
|
code: "0103",
|
||||||
|
message: "Email format is invalid",
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let db_result = sqlx::query!(
|
||||||
|
"
|
||||||
|
INSERT INTO device_parental_controls (serial_number, email, updated_at)
|
||||||
|
VALUES ($1, $2, NOW())
|
||||||
|
ON CONFLICT (serial_number)
|
||||||
|
DO UPDATE SET email = EXCLUDED.email, updated_at = NOW()
|
||||||
|
",
|
||||||
|
serial_number,
|
||||||
|
email
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Err(e) = db_result {
|
||||||
|
eprintln!("Failed to associate serial {serial_number} with email {email}: {e}");
|
||||||
|
return Err(Errors {
|
||||||
|
error: &[Error {
|
||||||
|
code: "0130",
|
||||||
|
message: "PID has not been registered yet",
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::email::send_pc_email(&email, &serial_number)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Failed to send parental controls email to {email}: {e}");
|
||||||
|
Errors {
|
||||||
|
error: &[Error {
|
||||||
|
code: "0130",
|
||||||
|
message: "PID has not been registered yet",
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v1/api/support/send_forgotten/pin/<email>/<master_key>")]
|
||||||
|
pub async fn send_forgotten_pin(
|
||||||
|
serial: DeviceSerial,
|
||||||
|
email: &str,
|
||||||
|
master_key: &str,
|
||||||
|
) -> Result<(), Errors<'static>> {
|
||||||
|
let serial_number = serial.0;
|
||||||
|
let email = email.trim().to_lowercase();
|
||||||
|
|
||||||
|
crate::email::send_reset_pin_email(&email, &serial_number, &master_key)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Failed to send parental controls email to {email}: {e}");
|
||||||
|
Errors {
|
||||||
|
error: &[Error {
|
||||||
|
code: "0130",
|
||||||
|
message: "PID has not been registered yet",
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue