134 lines
4.4 KiB
Rust
134 lines
4.4 KiB
Rust
// Module handles creating invites for potentially new users
|
|
use diesel::{self, prelude::*};
|
|
use rocket_contrib::json::Json;
|
|
use rand::random;
|
|
use crate::DBConn;
|
|
use crate::models::Invite;
|
|
use crate::schema;
|
|
use crate::users::new_user_response;
|
|
use crate::payload;
|
|
use chrono::{Duration, Utc};
|
|
|
|
|
|
/*
|
|
TODO: both the generation and usage endpoints for invites need the following
|
|
* meaningful responses
|
|
* authentication
|
|
*/
|
|
|
|
#[get("/generate")]
|
|
pub fn generate_invite(conn: DBConn) -> Json<Invite> {
|
|
let dt = Utc::now() + Duration::minutes(30);
|
|
// TODO:[maybe] ensure no collisions by doing a quick database check here
|
|
let mut new_invite = Invite {
|
|
id: random::<u64>(), // hopefully there won't ever be collision with this size of pool
|
|
uses: 1, // default/hardcorded for now
|
|
expires: dt.timestamp() as u64
|
|
};
|
|
// Next we cache this invite
|
|
let result = diesel::insert_into(schema::invites::table)
|
|
.values(&new_invite)
|
|
.execute(&conn.0);
|
|
|
|
// Finally we attempt to return _something_
|
|
match result {
|
|
Ok(_val) => {
|
|
Json(new_invite)
|
|
}
|
|
Err(_e) => {
|
|
new_invite.id = 0;
|
|
new_invite.expires = 0;
|
|
new_invite.uses = 0;
|
|
Json(new_invite)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[get("/<hash>")]
|
|
pub fn use_invite(hash: u64, conn: DBConn) -> Json<payload::NewUserResponse> {
|
|
// Grab the token from our table to make sure it's even there to begin with
|
|
use schema::invites::dsl::*;
|
|
use schema::users::dsl::*;
|
|
|
|
let diesel_result: Result<Invite, diesel::result::Error> = invites.filter(id.eq(hash)).first(&conn.0);
|
|
// TODO: this is getting moved elsewhere to clean up so ignore this for now
|
|
if let Ok(data) = diesel_result {
|
|
match data.uses {
|
|
1 ... std::i32::MAX => {
|
|
let user = crate::users::create_new_user();
|
|
match diesel::insert_into(users).values(&user).execute(&conn.0) {
|
|
Ok(_v) => Json(new_user_response(&Some(user), None)),
|
|
// an issue on our end gets a 500 response
|
|
Err(_e) => Json(new_user_response(&None, Some("Unable to create user")))
|
|
}
|
|
}
|
|
// The invite has been used up and thus should be removed
|
|
std::i32::MIN ... 0 => {
|
|
// bruh
|
|
let _ = diesel::delete(invites.filter(id.eq(data.id)))
|
|
.execute(&conn.0)
|
|
.expect("Could not delete invite");
|
|
Json(new_user_response(&None, Some("Invalid invite")))
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Json(new_user_response(&None, Some("Could not create user")))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod invite_tests {
|
|
use super::*;
|
|
use rocket;
|
|
use rocket::local::Client;
|
|
use rocket::http::Status;
|
|
use serde_json;
|
|
|
|
#[test]
|
|
fn request_invite() {
|
|
let rocket = rocket::ignite()
|
|
.mount("/invite", routes![generate_invite])
|
|
.attach(DBConn::fairing());
|
|
|
|
let client = Client::new(rocket).expect("Invalid rocket instance");
|
|
let mut response = client.get("/invite/generate").dispatch();
|
|
|
|
assert_eq!(response.status(), Status::Ok);
|
|
match response.body_string() {
|
|
Some(val) => {
|
|
let invite: Result<Invite, serde_json::Error> = serde_json::from_str(&val);
|
|
match invite {
|
|
Ok(val) => {
|
|
println!("{:#?}", val)
|
|
}
|
|
Err(e) => {
|
|
panic!("{}", e)
|
|
}
|
|
}
|
|
}
|
|
None => {
|
|
println!("bro wtf");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn use_invite() {
|
|
let app = rocket::ignite()
|
|
.mount("/invite", routes![generate_invite, use_invite])
|
|
.attach(DBConn::fairing());
|
|
|
|
// We assume in this test that invite generation is fine
|
|
let client = Client::new(app).expect("Invalid rocket instance");
|
|
let mut r = client.get("/invite/generate").dispatch();
|
|
let invite: Invite = serde_json::from_str(&r.body_string().unwrap()).unwrap();
|
|
|
|
// TODO: for some reason we can't use a regular struct so figure that out at some point
|
|
let mut response = client.get(format!("/invite/{}", invite.id)).dispatch();
|
|
let body: String = response.body_string().unwrap();
|
|
println!("{}", body);
|
|
}
|
|
|
|
}
|