6 changed files with 234 additions and 9 deletions
@ -0,0 +1,70 @@ |
|||||||
|
use crate::api::{CurrentUser, JsonAPI, PolicyError::*}; |
||||||
|
use crate::rds_conn::RdsConn; |
||||||
|
use crate::rds_models::*; |
||||||
|
use rocket::form::Form; |
||||||
|
use rocket::futures::future; |
||||||
|
use rocket::serde::json::{json, Value}; |
||||||
|
|
||||||
|
pub async fn get_poll_dict(pid: i32, rconn: &RdsConn, namehash: &str) -> Option<Value> { |
||||||
|
let opts = PollOption::init(pid, rconn) |
||||||
|
.get_list() |
||||||
|
.await |
||||||
|
.unwrap_or_default(); |
||||||
|
if opts.is_empty() { |
||||||
|
None |
||||||
|
} else { |
||||||
|
let choice = future::join_all(opts.iter().enumerate().map(|(idx, opt)| async move { |
||||||
|
PollVote::init(pid, idx, rconn) |
||||||
|
.has(namehash) |
||||||
|
.await |
||||||
|
.unwrap_or_default() |
||||||
|
.then(|| opt) |
||||||
|
})) |
||||||
|
.await |
||||||
|
.into_iter() |
||||||
|
.filter_map(|x| x) |
||||||
|
.collect::<Vec<&String>>() |
||||||
|
.pop(); |
||||||
|
Some(json!({ |
||||||
|
"answers": future::join_all( |
||||||
|
opts.iter().enumerate().map(|(idx, opt)| async move { |
||||||
|
json!({ |
||||||
|
"option": opt, |
||||||
|
"votes": PollVote::init(pid, idx, rconn).count().await.unwrap_or_default(), |
||||||
|
}) |
||||||
|
}) |
||||||
|
).await, |
||||||
|
"vote": choice, |
||||||
|
})) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(FromForm)] |
||||||
|
pub struct VoteInput { |
||||||
|
pid: i32, |
||||||
|
vote: String, |
||||||
|
} |
||||||
|
|
||||||
|
#[post("/vote", data = "<vi>")] |
||||||
|
pub async fn vote(vi: Form<VoteInput>, user: CurrentUser, rconn: RdsConn) -> JsonAPI { |
||||||
|
let pid = vi.pid; |
||||||
|
let opts = PollOption::init(pid, &rconn).get_list().await?; |
||||||
|
if opts.is_empty() { |
||||||
|
Err(NotAllowed)?; |
||||||
|
} |
||||||
|
|
||||||
|
for idx in 0..opts.len() { |
||||||
|
if PollVote::init(pid, idx, &rconn).has(&user.namehash).await? { |
||||||
|
Err(NotAllowed)?; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let idx: usize = opts |
||||||
|
.iter() |
||||||
|
.position(|x| x.eq(&vi.vote)) |
||||||
|
.ok_or_else(|| NotAllowed)?; |
||||||
|
|
||||||
|
PollVote::init(pid, idx, &rconn).add(&user.namehash).await?; |
||||||
|
|
||||||
|
code0!(get_poll_dict(vi.pid, &rconn, &user.namehash).await) |
||||||
|
} |
@ -0,0 +1,114 @@ |
|||||||
|
use crate::db_conn::Db; |
||||||
|
use crate::models::User; |
||||||
|
use rocket::request::{FromRequest, Outcome, Request}; |
||||||
|
use rocket::response::Redirect; |
||||||
|
use rocket::serde::Deserialize; |
||||||
|
use std::env; |
||||||
|
use url::Url; |
||||||
|
|
||||||
|
pub struct RefHeader(pub String); |
||||||
|
|
||||||
|
#[rocket::async_trait] |
||||||
|
impl<'r> FromRequest<'r> for RefHeader { |
||||||
|
type Error = (); |
||||||
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { |
||||||
|
match request.headers().get_one("Referer") { |
||||||
|
Some(h) => Outcome::Success(RefHeader(h.to_string())), |
||||||
|
None => Outcome::Forward(()), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[get("/?p=cs")] |
||||||
|
pub fn cs_login(r: RefHeader) -> Redirect { |
||||||
|
let mast_url = env::var("MAST_BASE_URL").unwrap(); |
||||||
|
let mast_cli = env::var("MAST_CLIENT").unwrap(); |
||||||
|
let mast_scope = env::var("MAST_SCOPE").unwrap(); |
||||||
|
|
||||||
|
let mut redirect_url = Url::parse(&r.0).unwrap(); |
||||||
|
redirect_url.set_path("/_login/cs/auth"); |
||||||
|
redirect_url.set_query(None); |
||||||
|
|
||||||
|
redirect_url = Url::parse_with_params( |
||||||
|
redirect_url.as_str(), |
||||||
|
&[("redirect_url", redirect_url.as_str())], |
||||||
|
) |
||||||
|
.unwrap(); |
||||||
|
let url = Url::parse_with_params( |
||||||
|
&format!("{}oauth/authorize", mast_url), |
||||||
|
&[ |
||||||
|
("redirect_uri", redirect_url.as_str()), |
||||||
|
("client_id", &mast_cli), |
||||||
|
("scope", &mast_scope), |
||||||
|
("response_type", "code"), |
||||||
|
], |
||||||
|
) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
Redirect::to(url.to_string()) |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)] |
||||||
|
#[serde(crate = "rocket::serde")] |
||||||
|
struct Token { |
||||||
|
pub access_token: String, |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)] |
||||||
|
#[serde(crate = "rocket::serde")] |
||||||
|
struct Account { |
||||||
|
pub id: String, |
||||||
|
} |
||||||
|
#[get("/cs/auth?<code>&<redirect_url>")] |
||||||
|
pub async fn cs_auth(code: String, redirect_url: String, db: Db) -> Redirect { |
||||||
|
let mast_url = env::var("MAST_BASE_URL").unwrap(); |
||||||
|
let mast_cli = env::var("MAST_CLIENT").unwrap(); |
||||||
|
let mast_sec = env::var("MAST_SECRET").unwrap(); |
||||||
|
let mast_scope = env::var("MAST_SCOPE").unwrap(); |
||||||
|
|
||||||
|
// to keep same
|
||||||
|
let redirect_url = Url::parse_with_params( |
||||||
|
redirect_url.as_str(), |
||||||
|
&[("redirect_url", redirect_url.as_str())], |
||||||
|
) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
let client = reqwest::Client::new(); |
||||||
|
let token: Token = client |
||||||
|
.post(format!("{}oauth/token", &mast_url)) |
||||||
|
.form(&[ |
||||||
|
("client_id", mast_cli.as_str()), |
||||||
|
("client_secret", mast_sec.as_str()), |
||||||
|
("scope", mast_scope.as_str()), |
||||||
|
("redirect_uri", redirect_url.as_str()), |
||||||
|
("grant_type", "authorization_code"), |
||||||
|
("code", code.as_str()), |
||||||
|
]) |
||||||
|
.send() |
||||||
|
.await |
||||||
|
.unwrap() |
||||||
|
.json() |
||||||
|
.await |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
//dbg!(&token);
|
||||||
|
|
||||||
|
let client = reqwest::Client::new(); |
||||||
|
let account = client |
||||||
|
.get(format!("{}api/v1/accounts/verify_credentials", &mast_url)) |
||||||
|
.bearer_auth(token.access_token) |
||||||
|
.send() |
||||||
|
.await |
||||||
|
.unwrap() |
||||||
|
.json::<Account>() |
||||||
|
.await |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
//dbg!(&account);
|
||||||
|
|
||||||
|
let tk = User::find_or_create_token(&db, &format!("cs_{}", &account.id), false) |
||||||
|
.await |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
Redirect::to(format!("/?token={}", tk)) |
||||||
|
} |
Loading…
Reference in new issue