
/invite/join/<hash>/<name> is the real path to be used now but the app ui should this behavior in some clever way
108 lines
3.3 KiB
Rust
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);
|
|
}
|
|
|
|
}
|