// Handlers for the base auth routes use crate::users{self, Member}; use crate::rand_utils::new_key; use rocket::http::Status; use std::{error, fmt}; use diesel; #[derive(FromForm)] struct JoinParams { code: u64, name: String, } #[derive(FromForm)] pub struct AuthKey { id: u64, secret: String, } pub type AuthResult = std::result::Result; #[derive(Clone)] pub struct AuthErr { msg: &'static str, status: u16, } impl fmt::Display for AuthErr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Authentication error") } } impl error::Error for AuthErr { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None } } impl<'r> Responder<'r> for AuthErr { fn respond_to(self, _:&Request) -> response::Result<'r> { Response::build() .status(Status::InternalServerError) .raw_header("db-error", self.msg) .ok() } } /* #[post("/login")] pub fn login() { } */ #[post("/join", data="")] pub fn join(conn: DBConn, params: JoinParams) -> AuthResult, AuthErr>{ /* * Requires -> body * Requires -> body * Struct JoinParams enforces this for us so if something is missing then rocket should 404 */ const expired: &'static str = "Invite expired"; const negate: &'static str = "Malformed request"; let diesel_result: Result = invites .filter(id.eq(code)) .first(&conn.0); if let Ok(data) = diesel_result { match data.uses { 1 ... std::i32::MAX => { let new_user = users::new_member(conn): // update the uses counter diesel::update(users.filter(userid.eq(user.userid))) .set(uses.eq(data.uses - 1)) .execute(&conn.0) AuthResult(Json(new_user)) } // The invite has been used up and thus should be removed std::i32::MIN ... 0 => { let _ = diesel::delete(invites.filter(id.eq(data.id))) .execute(&conn.0) .expect("Could not delete invite"); AuthResult(AuthErr{msg: expired}) } } } else { AuthResult(AuthErr{msg:negate}) } } #[post("/leave", data = "")] pub fn leave(conn: DBConn, api_key: AuthKey) -> Status { /* * Basic removal of the user from our users table */ diesel::delete(users.filter(id.eq(api_key.id), )) let db_result = diesel::delete(users) .filter(id.eq(api_key.id)) .filter(secret.eq(api_key.secret)) .execute(&conn.0); if let result = Ok(db_result) { Status::Accepted } else { Status::BadRequst } } /* #[pust("/close")] pub fn close() { } */