Skip to main content

haste_server/auth_n/oidc/
utilities.rs

1use haste_fhir_model::r4::generated::{resources::ClientApplication, terminology::IssueType};
2use haste_fhir_operation_error::OperationOutcomeError;
3use haste_jwt::TenantId;
4use haste_repository::{
5    Repository,
6    admin::TenantModelAdmin,
7    types::user::{CreateUser, UpdateUser},
8};
9use regex::Regex;
10
11pub fn is_valid_redirect_url(redirect_url: &str, client: &ClientApplication) -> bool {
12    let k = client.redirectUri.as_ref().and_then(|redirect_uris| {
13        redirect_uris.iter().find(|redirect_pattern| {
14            if let Some(redirect_pattern) = redirect_pattern.value.as_ref()
15                && let Ok(pattern) = Regex::new(&redirect_pattern.replace("*", "(.+)"))
16            {
17                pattern.is_match(redirect_url)
18            } else {
19                false
20            }
21        })
22    });
23
24    k.is_some() && !redirect_url.is_empty()
25}
26
27pub async fn set_user_password<Repo: Repository>(
28    repo: &Repo,
29    tenant: &TenantId,
30    user_email: &str,
31    user_id: &str,
32    password: &str,
33) -> Result<(), OperationOutcomeError> {
34    let password_strength = zxcvbn::zxcvbn(password, &[user_email]);
35
36    if u8::from(password_strength.score()) < 3 {
37        let feedback = password_strength
38            .feedback()
39            .map(|f| format!("{}", f))
40            .unwrap_or_default();
41
42        return Err(OperationOutcomeError::fatal(
43            IssueType::security(),
44            feedback,
45        ));
46    }
47
48    TenantModelAdmin::<CreateUser, _, _, _, String>::update(
49        repo,
50        tenant,
51        UpdateUser {
52            id: user_id.to_string(),
53            password: Some(password.to_string()),
54            email: None,
55            role: None,
56            method: None,
57            provider_id: None,
58        },
59    )
60    .await?;
61
62    Ok(())
63}