Skip to content

Commit

Permalink
Oh wow I removed all of the unwraps
Browse files Browse the repository at this point in the history
  • Loading branch information
jabbate19 committed Oct 15, 2024
1 parent d52b50f commit 0d32fc7
Show file tree
Hide file tree
Showing 19 changed files with 668 additions and 316 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

20 changes: 20 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: '3.8'

services:
postgres:
image: postgres:latest
container_name: db
environment:
POSTGRES_USER: rideboard
POSTGRES_PASSWORD: supersecurepassword
POSTGRES_DB: rideboard
volumes:
- ./src/migrations:/docker-entrypoint-initdb.d
ports:
- "5432:5432"

redis:
image: redis:latest
container_name: redis
ports:
- "6379:6379"
3 changes: 3 additions & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ use actix_web::{body::BoxBody, web, HttpResponse, Scope};
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;

use crate::app::ApiError;

mod v1;

#[derive(OpenApi)]
#[openapi(
nest(
(path = "/api/v1", api = v1::ApiDoc)
),
components(schemas(ApiError))
)]
pub(super) struct ApiDoc;

Expand Down
10 changes: 10 additions & 0 deletions src/api/v1/auth/common.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use actix_session::Session;
use actix_web::{HttpResponse, Responder};
use anyhow::Result;
use oauth2::basic::BasicClient;
use oauth2::{CsrfToken, Scope as OAuthScope};

use super::models::UserInfo;

pub async fn login(client: &BasicClient, scopes: Vec<String>) -> impl Responder {
//let (pkce_code_challenge, _pkce_code_verifier) = PkceCodeChallenge::new_random_sha256();

Expand All @@ -18,3 +22,9 @@ pub async fn login(client: &BasicClient, scopes: Vec<String>) -> impl Responder

HttpResponse::Ok().body(authorize_url.to_string())
}

pub fn login_session(session: &Session, user_info: UserInfo) -> Result<()> {
session.insert("login", true)?;
session.insert("userinfo", user_info)?;
Ok(())
}
59 changes: 39 additions & 20 deletions src/api/v1/auth/csh.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::v1::auth::models::{CSHUserInfo, UserInfo};
use crate::app::AppState;
use crate::app::{ApiError, AppState};
use crate::db::user::{UserData, UserRealm};
use actix_session::Session;
use actix_web::http::header;
Expand All @@ -10,18 +10,17 @@ use oauth2::reqwest::async_http_client;
use oauth2::{AuthorizationCode, TokenResponse};
use reqwest::Client;
use serde::Deserialize;
use serde_json::json;
use utoipa::{OpenApi, ToSchema};

use crate::api::v1::auth::common;
use crate::api::v1::auth::common::{self, login_session};

#[derive(OpenApi)]
#[openapi(paths(login, auth,), components(schemas(AuthRequest)))]
pub(super) struct ApiDoc;

#[utoipa::path(
responses(
(status = 200, description = "Redirect to OAuth2 Link to Log In")
(status = 200, description = "OAuth2 Link to Log In")
)
)]
#[get("/")]
Expand All @@ -42,7 +41,8 @@ pub struct AuthRequest {

#[utoipa::path(
responses(
(status = 200, description = "Redirect to OAuth2 to verify code and update user info.")
(status = 302, description = "Successful login, Redirect to home page."),
(status = 500, body = ApiError)
)
)]
#[get("/redirect")]
Expand All @@ -53,24 +53,43 @@ async fn auth(
) -> impl Responder {
let code = AuthorizationCode::new(params.code.clone());

let token = &data
let token = match &data
.csh_oauth
.exchange_code(code)
.request_async(async_http_client)
.await
.unwrap();
{
Ok(token) => token.access_token().secret().clone(),
Err(err) => {
error!("{}", err);
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to get OAuth Token".to_string()));
}
};

let client = Client::new();

let user_info: CSHUserInfo = client
let user_info: CSHUserInfo = match client
.get(&data.csh_userinfo_url)
.bearer_auth(token.access_token().secret())
.bearer_auth(token)
.send()
.await
.unwrap()
.json()
.await
.unwrap();
{
Ok(res) => match res.json().await {
Ok(out) => out,
Err(err) => {
error!("{}", err);
return HttpResponse::InternalServerError().json(ApiError::from(
"Failed to deserialize UserInfo token".to_string(),
));
}
},
Err(err) => {
error!("{}", err);
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to get UserInfo Token".to_string()));
}
};

if let Err(err) = UserData::insert_new(
user_info.ldap_id.clone(),
Expand All @@ -82,15 +101,15 @@ async fn auth(
.await
{
error!("{}", err);
return HttpResponse::InternalServerError().json(json!({
"error": "Failed to add user to database"
}));
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to add user to database".to_string()));
}

session.insert("login", true).unwrap();
session
.insert("userinfo", UserInfo::from(user_info))
.unwrap();
if let Err(err) = login_session(&session, UserInfo::from(user_info)) {
error!("{}", err);
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to Authorize Session".to_string()));
}

HttpResponse::Found()
.append_header((header::LOCATION, "/"))
Expand Down
57 changes: 39 additions & 18 deletions src/api/v1/auth/google.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::api::v1::auth::common;
use crate::api::v1::auth::models::{GoogleUserInfo, UserInfo};
use crate::app::AppState;
use crate::app::{ApiError, AppState};
use crate::db::user::{UserData, UserRealm};
use actix_session::Session;
use actix_web::http::header;
Expand All @@ -11,9 +11,10 @@ use oauth2::reqwest::async_http_client;
use oauth2::{AuthorizationCode, TokenResponse};
use reqwest::Client;
use serde::Deserialize;
use serde_json::json;
use utoipa::{OpenApi, ToSchema};

use super::common::login_session;

#[derive(OpenApi)]
#[openapi(paths(login, auth,), components(schemas(AuthRequest)))]
pub(super) struct ApiDoc;
Expand Down Expand Up @@ -45,7 +46,8 @@ pub struct AuthRequest {

#[utoipa::path(
responses(
(status = 200, description = "Redirect to OAuth2 to verify code and update user info.")
(status = 302, description = "Successful login, Redirect to home page."),
(status = 500, body = ApiError)
)
)]
#[get("/redirect")]
Expand All @@ -58,24 +60,43 @@ async fn auth(
//let _scope = params.scope.clone();

// Exchange the code with a token.
let token = &data
let token = match &data
.google_oauth
.exchange_code(code)
.request_async(async_http_client)
.await
.unwrap();
{
Ok(token) => token.access_token().secret().clone(),
Err(err) => {
error!("{}", err);
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to get OAuth Token".to_string()));
}
};

let client = Client::new();

let user_info: GoogleUserInfo = client
let user_info: GoogleUserInfo = match client
.get(&data.google_userinfo_url)
.bearer_auth(token.access_token().secret())
.bearer_auth(token)
.send()
.await
.unwrap()
.json()
.await
.unwrap();
{
Ok(res) => match res.json().await {
Ok(out) => out,
Err(err) => {
error!("{}", err);
return HttpResponse::InternalServerError().json(ApiError::from(
"Failed to deserialize UserInfo token".to_string(),
));
}
},
Err(err) => {
error!("{}", err);
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to get UserInfo Token".to_string()));
}
};

if let Err(err) = UserData::insert_new(
user_info.sub.clone(),
Expand All @@ -87,15 +108,15 @@ async fn auth(
.await
{
error!("{}", err);
return HttpResponse::InternalServerError().json(json!({
"error": "Failed to add user to database"
}));
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to add user to database".to_string()));
}

session.insert("login", true).unwrap();
session
.insert("userinfo", UserInfo::from(user_info))
.unwrap();
if let Err(err) = login_session(&session, UserInfo::from(user_info)) {
error!("{}", err);
return HttpResponse::InternalServerError()
.json(ApiError::from("Failed to Authorize Session".to_string()));
}

HttpResponse::Found()
.append_header((header::LOCATION, "/"))
Expand Down
18 changes: 13 additions & 5 deletions src/api/v1/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::api::v1::auth::models::UserInfo;
use crate::auth::SessionAuth;
use crate::{api::v1::auth::models::UserInfo, app::ApiError};
use actix_session::Session;
use actix_web::{get, http::header, post, web, HttpResponse, Responder, Scope};
use log::error;
use utoipa::OpenApi;

mod common;
Expand All @@ -11,7 +12,7 @@ pub mod models;

#[utoipa::path(
responses(
(status = 200, description = "List current todo items")
(status = 302, description = "Logged out")
)
)]
#[post("/logout")]
Expand All @@ -25,13 +26,20 @@ async fn logout(session: Session) -> impl Responder {

#[utoipa::path(
responses(
(status = 200, description = "List current todo items")
(status = 200, description = "Get current user information"),
(status = 500, body = ApiError)
)
)]
#[get("/", wrap = "SessionAuth")]
async fn get_user_data(session: Session) -> impl Responder {
let out: Option<UserInfo> = session.get("userinfo").unwrap();
HttpResponse::Ok().json(out)
match session.get::<UserInfo>("userinfo") {
Ok(data) => HttpResponse::Ok().json(data),
Err(err) => {
error!("{}", err);
HttpResponse::InternalServerError()
.json(ApiError::from("Failed to get Session Data".to_string()))
}
}
}

#[derive(OpenApi)]
Expand Down
Loading

0 comments on commit 0d32fc7

Please sign in to comment.