aboutsummaryrefslogtreecommitdiff
path: root/crates/secd/src/util/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--crates/secd/src/util/mod.rs189
1 files changed, 33 insertions, 156 deletions
diff --git a/crates/secd/src/util/mod.rs b/crates/secd/src/util/mod.rs
index bb177cb..6677c2f 100644
--- a/crates/secd/src/util/mod.rs
+++ b/crates/secd/src/util/mod.rs
@@ -1,38 +1,12 @@
-use std::str::FromStr;
+pub(crate) mod from;
-use anyhow::{bail, Context};
-use log::error;
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
-use reqwest::header;
-use serde::{Deserialize, Serialize};
+use sha2::{Digest, Sha256};
+use time::OffsetDateTime;
use url::Url;
-use crate::{
- OauthProvider, OauthProviderName, OauthValidation, SecdError, ValidationRequestId,
- INTERNAL_ERR_MSG,
-};
-
-pub(crate) fn log_err(e: Box<dyn std::error::Error>, new_e: SecdError) -> SecdError {
- error!("{:?}", e);
- new_e
-}
-pub(crate) fn to_secd_err(e: anyhow::Error, new_e: SecdError) -> SecdError {
- error!("{:?}", e);
- new_e
-}
-
-pub(crate) fn log_err_sqlx(e: sqlx::Error) -> sqlx::Error {
- error!("{:?}", e);
- e
-}
-pub(crate) fn generate_random_url_safe(n: usize) -> String {
- thread_rng()
- .sample_iter(&Alphanumeric)
- .take(n)
- .map(char::from)
- .collect()
-}
+use crate::{AddressType, IdentityId, SecdError, Session, SESSION_DURATION, SESSION_SIZE_BYTES};
pub(crate) fn remove_trailing_slash(url: &mut Url) -> String {
let mut u = url.to_string();
@@ -44,134 +18,37 @@ pub(crate) fn remove_trailing_slash(url: &mut Url) -> String {
u
}
-pub(crate) fn build_oauth_auth_url(
- p: &OauthProvider,
- validation_id: ValidationRequestId,
-) -> Result<Url, SecdError> {
- let redirect_url = remove_trailing_slash(&mut p.redirect_url.clone());
-
- Ok(Url::from_str(&format!(
- "{}?client_id={}&response_type={}&redirect_uri={}&scope={}&state={}",
- p.base_url,
- p.client_id,
- p.response.to_string().to_lowercase(),
- redirect_url,
- p.default_scope,
- validation_id.to_string()
- ))
- .map_err(|_| SecdError::InternalError(INTERNAL_ERR_MSG.into()))?)
-}
-
-pub(crate) async fn get_oauth_identity_data(
- validation: &OauthValidation,
-) -> anyhow::Result<OauthAccessIdentity> {
- let provider = validation.oauth_provider.name;
- let token = validation
- .access_token
- .clone()
- .ok_or(SecdError::InternalError(
- "no access token provided with which to build oauth data url".into(),
- ))?;
-
- let url = Url::from_str(&format!(
- "{}{}",
- match provider {
- OauthProviderName::Google =>
- "https://www.googleapis.com/oauth2/v2/userinfo?access_token=",
- _ => unimplemented!(),
- },
- token
- ))?;
-
- let resp = reqwest::get(url).await?.json::<serde_json::Value>().await?;
- let identity = match provider {
- OauthProviderName::Google => OauthAccessIdentity {
- email: resp
- .get("email")
- .and_then(|v| v.as_str().map(|s| s.to_string())),
- email_is_verified: resp.get("verified_email").and_then(|v| v.as_bool()),
- picture_url: resp
- .get("picture")
- .and_then(|v| Url::from_str(&v.to_string()).ok()),
- },
- _ => unimplemented!(),
- };
-
- Ok(identity)
-}
-
-#[derive(Debug, Serialize)]
-pub(crate) struct OauthAccessTokenGoogleRequest {
- grant_type: String,
- code: String,
- client_id: String,
- client_secret: String,
- redirect_uri: String,
-}
-
-#[derive(Debug, Deserialize)]
-pub(crate) struct OauthAccessTokenGoogleResponse {
- access_token: String,
- expires_in: i32,
- token_type: String,
- scope: String,
- id_token: String,
+pub(crate) fn hash(i: &[u8]) -> Vec<u8> {
+ let mut hasher = Sha256::new();
+ hasher.update(i);
+ hasher.finalize().to_vec()
}
-#[derive(Debug)]
-pub(crate) struct OauthAccessIdentity {
- pub(crate) email: Option<String>,
- pub(crate) email_is_verified: Option<bool>,
- pub(crate) picture_url: Option<Url>,
-}
-
-type AccessTokenRequestData = String;
-
-pub(crate) async fn get_oauth_access_token(
- validation: &OauthValidation,
- secret_code: &String,
-) -> anyhow::Result<String> {
- let provider = validation.oauth_provider.name;
-
- let url = Url::from_str(match provider {
- OauthProviderName::Google => "https://accounts.google.com/o/oauth2/token",
- _ => unimplemented!(),
- })?;
-
- let request_data = serde_json::to_string(&match provider {
- OauthProviderName::Google => OauthAccessTokenGoogleRequest {
- grant_type: "authorization_code".to_string(),
- code: secret_code.to_string(),
- client_id: validation.oauth_provider.client_id.clone(),
- client_secret: validation.oauth_provider.client_secret.clone(),
- redirect_uri: remove_trailing_slash(
- &mut validation.oauth_provider.redirect_url.clone(),
- ),
- },
- _ => unimplemented!(),
- })?;
-
- let r = reqwest::Client::new()
- .post(url)
- .body(request_data)
- .header(header::CONTENT_TYPE, "application/json")
- .send()
- .await
- .context(format!(
- "Failed to successfully POST a new access token for: {}",
- provider
- ))?;
-
- let access_token = match provider {
- OauthProviderName::Google => {
- let resp: OauthAccessTokenGoogleResponse = r.json().await.context(format!(
- "Failed to parse access token response for: {}",
- provider
- ))?;
- resp.access_token
+impl AddressType {
+ pub fn get_value(&self) -> Option<String> {
+ match &self {
+ AddressType::Email { email_address } => {
+ email_address.as_ref().map(|a| a.to_string().clone())
+ }
+ AddressType::Sms { phone_number } => phone_number.as_ref().cloned(),
}
- _ => unimplemented!(),
- };
+ }
+}
- Ok(access_token)
+impl Session {
+ pub(crate) fn new(identity_id: IdentityId) -> Result<Self, SecdError> {
+ let token = (0..SESSION_SIZE_BYTES)
+ .map(|_| rand::random::<u8>())
+ .collect::<Vec<u8>>();
+ let now = OffsetDateTime::now_utc();
+ Ok(Session {
+ identity_id,
+ token,
+ created_at: now,
+ expired_at: now
+ .checked_add(time::Duration::new(SESSION_DURATION, 0))
+ .ok_or(SecdError::Todo)?,
+ revoked_at: None,
+ })
+ }
}