2019-03-19 14:37:56 +01:00
|
|
|
#![warn(clippy::too_many_arguments)]
|
2019-03-20 17:56:17 +01:00
|
|
|
use rocket::{
|
|
|
|
request::{Form, Request},
|
|
|
|
response::{self, Responder},
|
|
|
|
};
|
2018-12-06 18:54:16 +01:00
|
|
|
use rocket_contrib::json::Json;
|
2018-10-22 15:30:04 +02:00
|
|
|
use serde_json;
|
|
|
|
|
|
|
|
use plume_common::utils::random_hex;
|
2019-03-20 17:56:17 +01:00
|
|
|
use plume_models::{api_tokens::*, apps::App, db_conn::DbConn, users::User, Error};
|
2018-10-22 15:30:04 +02:00
|
|
|
|
2018-12-29 09:36:07 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ApiError(Error);
|
|
|
|
|
|
|
|
impl From<Error> for ApiError {
|
|
|
|
fn from(err: Error) -> ApiError {
|
|
|
|
ApiError(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> Responder<'r> for ApiError {
|
|
|
|
fn respond_to(self, req: &Request) -> response::Result<'r> {
|
|
|
|
match self.0 {
|
|
|
|
Error::NotFound => Json(json!({
|
|
|
|
"error": "Not found"
|
2019-03-20 17:56:17 +01:00
|
|
|
}))
|
|
|
|
.respond_to(req),
|
2018-12-29 09:36:07 +01:00
|
|
|
Error::Unauthorized => Json(json!({
|
|
|
|
"error": "You are not authorized to access this resource"
|
2019-03-20 17:56:17 +01:00
|
|
|
}))
|
|
|
|
.respond_to(req),
|
2018-12-29 09:36:07 +01:00
|
|
|
_ => Json(json!({
|
|
|
|
"error": "Server error"
|
2019-03-20 17:56:17 +01:00
|
|
|
}))
|
|
|
|
.respond_to(req),
|
2018-12-29 09:36:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-22 15:30:04 +02:00
|
|
|
#[derive(FromForm)]
|
2018-12-06 18:54:16 +01:00
|
|
|
pub struct OAuthRequest {
|
2018-10-22 15:30:04 +02:00
|
|
|
client_id: String,
|
|
|
|
client_secret: String,
|
|
|
|
password: String,
|
|
|
|
username: String,
|
|
|
|
scopes: String,
|
|
|
|
}
|
|
|
|
|
2018-12-06 18:54:16 +01:00
|
|
|
#[get("/oauth2?<query..>")]
|
2018-12-29 09:36:07 +01:00
|
|
|
pub fn oauth(query: Form<OAuthRequest>, conn: DbConn) -> Result<Json<serde_json::Value>, ApiError> {
|
|
|
|
let app = App::find_by_client_id(&*conn, &query.client_id)?;
|
2018-10-22 15:30:04 +02:00
|
|
|
if app.client_secret == query.client_secret {
|
2019-03-06 18:28:10 +01:00
|
|
|
if let Ok(user) = User::find_by_fqn(&*conn, &query.username) {
|
2018-11-26 10:21:52 +01:00
|
|
|
if user.auth(&query.password) {
|
2019-03-20 17:56:17 +01:00
|
|
|
let token = ApiToken::insert(
|
|
|
|
&*conn,
|
|
|
|
NewApiToken {
|
|
|
|
app_id: app.id,
|
|
|
|
user_id: user.id,
|
|
|
|
value: random_hex(),
|
|
|
|
scopes: query.scopes.clone(),
|
|
|
|
},
|
|
|
|
)?;
|
2018-12-29 09:36:07 +01:00
|
|
|
Ok(Json(json!({
|
2018-10-22 15:30:04 +02:00
|
|
|
"token": token.value
|
2018-12-29 09:36:07 +01:00
|
|
|
})))
|
2018-10-22 15:30:04 +02:00
|
|
|
} else {
|
2018-12-29 09:36:07 +01:00
|
|
|
Ok(Json(json!({
|
2018-10-23 11:50:52 +02:00
|
|
|
"error": "Invalid credentials"
|
2018-12-29 09:36:07 +01:00
|
|
|
})))
|
2018-10-22 15:30:04 +02:00
|
|
|
}
|
|
|
|
} else {
|
2018-10-23 11:50:52 +02:00
|
|
|
// Making fake password verification to avoid different
|
|
|
|
// response times that would make it possible to know
|
|
|
|
// if a username is registered or not.
|
2018-12-29 09:36:07 +01:00
|
|
|
User::get(&*conn, 1)?.auth(&query.password);
|
|
|
|
Ok(Json(json!({
|
2018-10-23 11:50:52 +02:00
|
|
|
"error": "Invalid credentials"
|
2018-12-29 09:36:07 +01:00
|
|
|
})))
|
2018-10-22 15:30:04 +02:00
|
|
|
}
|
|
|
|
} else {
|
2018-12-29 09:36:07 +01:00
|
|
|
Ok(Json(json!({
|
2018-10-22 15:30:04 +02:00
|
|
|
"error": "Invalid client_secret"
|
2018-12-29 09:36:07 +01:00
|
|
|
})))
|
2018-10-22 15:30:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-21 18:22:27 +02:00
|
|
|
pub mod apps;
|
2018-10-23 11:37:24 +02:00
|
|
|
pub mod authorization;
|
2018-09-19 16:49:34 +02:00
|
|
|
pub mod posts;
|