feat: initial working pwd reset method
This commit is contained in:
commit
c8856ddeb1
8 changed files with 3246 additions and 0 deletions
0
src/auth.rs
Normal file
0
src/auth.rs
Normal file
45
src/main.rs
Normal file
45
src/main.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
mod auth;
|
||||
mod provider;
|
||||
mod request_types;
|
||||
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
use std::env;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{Error, State};
|
||||
use rocket::http::Status;
|
||||
use crate::provider::{PurelymailProvider, SMTPUserCredentials};
|
||||
use crate::request_types::PasswordResetRequest;
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> &'static str {
|
||||
"Hello, world!"
|
||||
}
|
||||
|
||||
#[get("/onboard/<token>")]
|
||||
fn onboard(token: String) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[post("/doResetPassword", data = "<data>")]
|
||||
async fn user(data: Json<PasswordResetRequest>, provider: &State<PurelymailProvider>) -> Result<String, Status> {
|
||||
provider.reset_password(&data.email, &data.new_password).await
|
||||
.map(|_| { String::from("Good") })
|
||||
.or(Err(Status::BadRequest))
|
||||
}
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
let token = env::var("API_TOKEN").expect("API_TOKEN env var not set");
|
||||
let smtp_webmaster_username = env::var("WEBMASTER_USERNAME")
|
||||
.expect("WEBMASTER_USERNAME env var not set");
|
||||
let smtp_webmaster_password = env::var("WEBMASTER_PASSWORD")
|
||||
.expect("WEBMASTER_PASSWORD env var not set");
|
||||
let provider: PurelymailProvider = PurelymailProvider::new(
|
||||
token,
|
||||
SMTPUserCredentials::new(&smtp_webmaster_username, &smtp_webmaster_password)
|
||||
);
|
||||
rocket::build()
|
||||
.manage(provider)
|
||||
.mount("/", routes![index, onboard, user])
|
||||
}
|
||||
90
src/provider.rs
Normal file
90
src/provider.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
use reqwest::{Body, Client, RequestBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub struct SMTPUserCredentials {
|
||||
username: String,
|
||||
password: String,
|
||||
}
|
||||
impl SMTPUserCredentials {
|
||||
pub fn new(username: &str, password: &str) -> SMTPUserCredentials {
|
||||
SMTPUserCredentials {
|
||||
username: username.to_string(),
|
||||
password: password.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PurelymailProvider {
|
||||
token: String,
|
||||
webmaster: SMTPUserCredentials
|
||||
}
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct UserListResponse {
|
||||
r#type: String,
|
||||
result: UserList
|
||||
}
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct UserList {
|
||||
users: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UserUpdateRequest {
|
||||
pub user_name: String,
|
||||
pub new_user_name: Option<String>,
|
||||
pub new_password: String,
|
||||
pub enable_search_indexing: bool,
|
||||
pub enable_password_reset: bool,
|
||||
pub require_two_factor_authentication: bool,
|
||||
}
|
||||
|
||||
impl From<UserUpdateRequest> for Body {
|
||||
fn from(user: UserUpdateRequest) -> Body {
|
||||
let bytes = serde_json::to_vec(&user).expect("Failed to serialize UserUpdateRequest");
|
||||
Body::from(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl PurelymailProvider {
|
||||
pub fn new(token: String, webmaster_cred: SMTPUserCredentials) -> PurelymailProvider {
|
||||
PurelymailProvider { token, webmaster: webmaster_cred }
|
||||
}
|
||||
fn dispatch_onboarding_email() {
|
||||
todo!()
|
||||
}
|
||||
fn with_authorize(&self, req: RequestBuilder) -> RequestBuilder {
|
||||
req.header("Purelymail-Api-Token", &self.token)
|
||||
}
|
||||
pub async fn reset_password(&self, email_addr: &str, new_password: &str) -> Result<(), &str> {
|
||||
println!("Resetting password");
|
||||
let client = Client::new();
|
||||
let r = self.with_authorize(
|
||||
client.post("https://purelymail.com/api/v0/listUser")
|
||||
).body("{}").send().await.expect("Failed to reset password");
|
||||
let res = r.json::<UserListResponse>()
|
||||
.await.expect("TODO: user list bad");
|
||||
if res.r#type != "success" {
|
||||
return Err("The API returned an error");
|
||||
}
|
||||
let users = res.result.users;
|
||||
if !users.contains(&String::from(email_addr)) {
|
||||
return Err("The user does not exist");
|
||||
}
|
||||
let r = self.with_authorize(
|
||||
client.post("https://purelymail.com/api/v0/modifyUser")
|
||||
).body(UserUpdateRequest {
|
||||
user_name: email_addr.to_string(),
|
||||
new_user_name: None,
|
||||
new_password: new_password.to_string(),
|
||||
enable_search_indexing: false,
|
||||
enable_password_reset: false,
|
||||
require_two_factor_authentication: false,
|
||||
}).send().await;
|
||||
if r.is_err() {
|
||||
return Err("The API returned an error");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
7
src/request_types.rs
Normal file
7
src/request_types.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PasswordResetRequest {
|
||||
pub email: String,
|
||||
pub new_password: String,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue