Skip to content

Commit 0d32fc7

Browse files
committed
Oh wow I removed all of the unwraps
1 parent d52b50f commit 0d32fc7

19 files changed

+668
-316
lines changed

.sqlx/query-347403ed249d8ec43bf21e6baf291191defc8174cdd8c8641b4de6ff61ec8a04.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-6925f6336488799fe9e01ee31dab3b1f1a3aed7a62559c656807e349e2bd7f0f.json

Lines changed: 0 additions & 23 deletions
This file was deleted.

docker-compose.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: '3.8'
2+
3+
services:
4+
postgres:
5+
image: postgres:latest
6+
container_name: db
7+
environment:
8+
POSTGRES_USER: rideboard
9+
POSTGRES_PASSWORD: supersecurepassword
10+
POSTGRES_DB: rideboard
11+
volumes:
12+
- ./src/migrations:/docker-entrypoint-initdb.d
13+
ports:
14+
- "5432:5432"
15+
16+
redis:
17+
image: redis:latest
18+
container_name: redis
19+
ports:
20+
- "6379:6379"

src/api/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ use actix_web::{body::BoxBody, web, HttpResponse, Scope};
22
use utoipa::OpenApi;
33
use utoipa_swagger_ui::SwaggerUi;
44

5+
use crate::app::ApiError;
6+
57
mod v1;
68

79
#[derive(OpenApi)]
810
#[openapi(
911
nest(
1012
(path = "/api/v1", api = v1::ApiDoc)
1113
),
14+
components(schemas(ApiError))
1215
)]
1316
pub(super) struct ApiDoc;
1417

src/api/v1/auth/common.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
use actix_session::Session;
12
use actix_web::{HttpResponse, Responder};
3+
use anyhow::Result;
24
use oauth2::basic::BasicClient;
35
use oauth2::{CsrfToken, Scope as OAuthScope};
46

7+
use super::models::UserInfo;
8+
59
pub async fn login(client: &BasicClient, scopes: Vec<String>) -> impl Responder {
610
//let (pkce_code_challenge, _pkce_code_verifier) = PkceCodeChallenge::new_random_sha256();
711

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

1923
HttpResponse::Ok().body(authorize_url.to_string())
2024
}
25+
26+
pub fn login_session(session: &Session, user_info: UserInfo) -> Result<()> {
27+
session.insert("login", true)?;
28+
session.insert("userinfo", user_info)?;
29+
Ok(())
30+
}

src/api/v1/auth/csh.rs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::api::v1::auth::models::{CSHUserInfo, UserInfo};
2-
use crate::app::AppState;
2+
use crate::app::{ApiError, AppState};
33
use crate::db::user::{UserData, UserRealm};
44
use actix_session::Session;
55
use actix_web::http::header;
@@ -10,18 +10,17 @@ use oauth2::reqwest::async_http_client;
1010
use oauth2::{AuthorizationCode, TokenResponse};
1111
use reqwest::Client;
1212
use serde::Deserialize;
13-
use serde_json::json;
1413
use utoipa::{OpenApi, ToSchema};
1514

16-
use crate::api::v1::auth::common;
15+
use crate::api::v1::auth::common::{self, login_session};
1716

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

2221
#[utoipa::path(
2322
responses(
24-
(status = 200, description = "Redirect to OAuth2 Link to Log In")
23+
(status = 200, description = "OAuth2 Link to Log In")
2524
)
2625
)]
2726
#[get("/")]
@@ -42,7 +41,8 @@ pub struct AuthRequest {
4241

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

56-
let token = &data
56+
let token = match &data
5757
.csh_oauth
5858
.exchange_code(code)
5959
.request_async(async_http_client)
6060
.await
61-
.unwrap();
61+
{
62+
Ok(token) => token.access_token().secret().clone(),
63+
Err(err) => {
64+
error!("{}", err);
65+
return HttpResponse::InternalServerError()
66+
.json(ApiError::from("Failed to get OAuth Token".to_string()));
67+
}
68+
};
6269

6370
let client = Client::new();
6471

65-
let user_info: CSHUserInfo = client
72+
let user_info: CSHUserInfo = match client
6673
.get(&data.csh_userinfo_url)
67-
.bearer_auth(token.access_token().secret())
74+
.bearer_auth(token)
6875
.send()
6976
.await
70-
.unwrap()
71-
.json()
72-
.await
73-
.unwrap();
77+
{
78+
Ok(res) => match res.json().await {
79+
Ok(out) => out,
80+
Err(err) => {
81+
error!("{}", err);
82+
return HttpResponse::InternalServerError().json(ApiError::from(
83+
"Failed to deserialize UserInfo token".to_string(),
84+
));
85+
}
86+
},
87+
Err(err) => {
88+
error!("{}", err);
89+
return HttpResponse::InternalServerError()
90+
.json(ApiError::from("Failed to get UserInfo Token".to_string()));
91+
}
92+
};
7493

7594
if let Err(err) = UserData::insert_new(
7695
user_info.ldap_id.clone(),
@@ -82,15 +101,15 @@ async fn auth(
82101
.await
83102
{
84103
error!("{}", err);
85-
return HttpResponse::InternalServerError().json(json!({
86-
"error": "Failed to add user to database"
87-
}));
104+
return HttpResponse::InternalServerError()
105+
.json(ApiError::from("Failed to add user to database".to_string()));
88106
}
89107

90-
session.insert("login", true).unwrap();
91-
session
92-
.insert("userinfo", UserInfo::from(user_info))
93-
.unwrap();
108+
if let Err(err) = login_session(&session, UserInfo::from(user_info)) {
109+
error!("{}", err);
110+
return HttpResponse::InternalServerError()
111+
.json(ApiError::from("Failed to Authorize Session".to_string()));
112+
}
94113

95114
HttpResponse::Found()
96115
.append_header((header::LOCATION, "/"))

src/api/v1/auth/google.rs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::api::v1::auth::common;
22
use crate::api::v1::auth::models::{GoogleUserInfo, UserInfo};
3-
use crate::app::AppState;
3+
use crate::app::{ApiError, AppState};
44
use crate::db::user::{UserData, UserRealm};
55
use actix_session::Session;
66
use actix_web::http::header;
@@ -11,9 +11,10 @@ use oauth2::reqwest::async_http_client;
1111
use oauth2::{AuthorizationCode, TokenResponse};
1212
use reqwest::Client;
1313
use serde::Deserialize;
14-
use serde_json::json;
1514
use utoipa::{OpenApi, ToSchema};
1615

16+
use super::common::login_session;
17+
1718
#[derive(OpenApi)]
1819
#[openapi(paths(login, auth,), components(schemas(AuthRequest)))]
1920
pub(super) struct ApiDoc;
@@ -45,7 +46,8 @@ pub struct AuthRequest {
4546

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

6062
// Exchange the code with a token.
61-
let token = &data
63+
let token = match &data
6264
.google_oauth
6365
.exchange_code(code)
6466
.request_async(async_http_client)
6567
.await
66-
.unwrap();
68+
{
69+
Ok(token) => token.access_token().secret().clone(),
70+
Err(err) => {
71+
error!("{}", err);
72+
return HttpResponse::InternalServerError()
73+
.json(ApiError::from("Failed to get OAuth Token".to_string()));
74+
}
75+
};
6776

6877
let client = Client::new();
6978

70-
let user_info: GoogleUserInfo = client
79+
let user_info: GoogleUserInfo = match client
7180
.get(&data.google_userinfo_url)
72-
.bearer_auth(token.access_token().secret())
81+
.bearer_auth(token)
7382
.send()
7483
.await
75-
.unwrap()
76-
.json()
77-
.await
78-
.unwrap();
84+
{
85+
Ok(res) => match res.json().await {
86+
Ok(out) => out,
87+
Err(err) => {
88+
error!("{}", err);
89+
return HttpResponse::InternalServerError().json(ApiError::from(
90+
"Failed to deserialize UserInfo token".to_string(),
91+
));
92+
}
93+
},
94+
Err(err) => {
95+
error!("{}", err);
96+
return HttpResponse::InternalServerError()
97+
.json(ApiError::from("Failed to get UserInfo Token".to_string()));
98+
}
99+
};
79100

80101
if let Err(err) = UserData::insert_new(
81102
user_info.sub.clone(),
@@ -87,15 +108,15 @@ async fn auth(
87108
.await
88109
{
89110
error!("{}", err);
90-
return HttpResponse::InternalServerError().json(json!({
91-
"error": "Failed to add user to database"
92-
}));
111+
return HttpResponse::InternalServerError()
112+
.json(ApiError::from("Failed to add user to database".to_string()));
93113
}
94114

95-
session.insert("login", true).unwrap();
96-
session
97-
.insert("userinfo", UserInfo::from(user_info))
98-
.unwrap();
115+
if let Err(err) = login_session(&session, UserInfo::from(user_info)) {
116+
error!("{}", err);
117+
return HttpResponse::InternalServerError()
118+
.json(ApiError::from("Failed to Authorize Session".to_string()));
119+
}
99120

100121
HttpResponse::Found()
101122
.append_header((header::LOCATION, "/"))

src/api/v1/auth/mod.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use crate::api::v1::auth::models::UserInfo;
21
use crate::auth::SessionAuth;
2+
use crate::{api::v1::auth::models::UserInfo, app::ApiError};
33
use actix_session::Session;
44
use actix_web::{get, http::header, post, web, HttpResponse, Responder, Scope};
5+
use log::error;
56
use utoipa::OpenApi;
67

78
mod common;
@@ -11,7 +12,7 @@ pub mod models;
1112

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

2627
#[utoipa::path(
2728
responses(
28-
(status = 200, description = "List current todo items")
29+
(status = 200, description = "Get current user information"),
30+
(status = 500, body = ApiError)
2931
)
3032
)]
3133
#[get("/", wrap = "SessionAuth")]
3234
async fn get_user_data(session: Session) -> impl Responder {
33-
let out: Option<UserInfo> = session.get("userinfo").unwrap();
34-
HttpResponse::Ok().json(out)
35+
match session.get::<UserInfo>("userinfo") {
36+
Ok(data) => HttpResponse::Ok().json(data),
37+
Err(err) => {
38+
error!("{}", err);
39+
HttpResponse::InternalServerError()
40+
.json(ApiError::from("Failed to get Session Data".to_string()))
41+
}
42+
}
3543
}
3644

3745
#[derive(OpenApi)]

0 commit comments

Comments
 (0)