haste_server/auth_n/oidc/
utilities.rs1use 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::TenantAuthAdmin,
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]);
36
37 if u8::from(password_strength.score()) < 3 {
38 let feedback = password_strength
39 .feedback()
40 .map(|f| format!("{}", f))
41 .unwrap_or_default();
42
43 return Err(OperationOutcomeError::fatal(
44 IssueType::Security(None),
45 feedback,
46 ));
47 }
48
49 TenantAuthAdmin::<CreateUser, _, _, _, String>::update(
50 repo,
51 &tenant,
52 UpdateUser {
53 id: user_id.to_string(),
54 password: Some(password.to_string()),
55 email: None,
56 role: None,
57 method: None,
58 provider_id: None,
59 },
60 )
61 .await?;
62
63 Ok(())
64}