freechat/server/src/invites.rs
shockrah 81e6fd0a13 Invite are now consumed via a path with two dynamic params
/invite/join/<hash>/<name> is the real path to be used now but the app ui should this behavior in some clever way
2020-05-06 02:51:26 -07:00

108 lines
3.3 KiB
Rust

// Module handles creating invites for potentially new users
use diesel::{self, prelude::*};
use rocket_contrib::json::Json;
use chrono::{Duration, Utc};
use rand::random;
use crate::auth::{join, AuthResult, AuthErr};
use crate::DBConn;
use crate::models::{User, Invite};
use crate::schema;
/*
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 doesn't really like having data in its body for whatever reason
// Problem: invite/joining system is gonna have to get a redesign
#[get("/join/<hash>/<name>")]
pub fn use_invite(hash: u64, name: String, conn: DBConn) -> AuthResult<Json<User>, AuthErr>{
join(conn, hash, name)
}
#[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);
}
}