Add configurable Fill Assist rules URL (#7791)

This commit is contained in:
Tom authored and GitHub committed 2026-10-29 22:25:23 +01:00
1 parent be5d3ad907
commit 863395f5e2
6 files changed
+94 -5

No files matched your search

+1
View File
@@ -247,6 +247,7 @@ fn config() -> Json<Value> {
"notifications": format!("{domain}/notifications"),
"sso": "",
"cloudRegion": null,
"fillAssistRules": CONFIG.fill_assist_rules_url(),
},
// Bitwarden uses this for the self-hosted servers to indicate the default push technology
"push": {
+58 -4
View File
@@ -16,9 +16,9 @@ use crate::{
DbConn,
models::{
Cipher, CipherId, Collection, CollectionCipher, CollectionGroup, CollectionId, CollectionUser, Device,
EventType, Group, GroupId, GroupUser, Invitation, Membership, MembershipId, MembershipStatus,
MembershipType, OrgPolicy, OrgPolicyType, Organization, OrganizationApiKey, OrganizationId, TwoFactor,
TwoFactorType, User, UserId,
EventType, FillAssistPolicyData, Group, GroupId, GroupUser, Invitation, Membership, MembershipId,
MembershipStatus, MembershipType, OrgPolicy, OrgPolicyType, Organization, OrganizationApiKey,
OrganizationId, TwoFactor, TwoFactorType, User, UserId,
},
},
mail,
@@ -2048,6 +2048,29 @@ async fn put_policy(
err!("Invalid or unsupported policy type")
};
let current_policy = OrgPolicy::find_by_org_and_type(&org_id, pol_type_enum, &conn).await;
let is_currently_enabled = current_policy.as_ref().is_some_and(|policy| policy.enabled);
// Fill Assist depends on Single Organization. Match Bitwarden's dependency checks by only checking when the
// policy changes state.
if pol_type_enum == OrgPolicyType::FillAssist && data.enabled && !is_currently_enabled {
let single_org_policy_enabled =
OrgPolicy::find_by_org_and_type(&org_id, OrgPolicyType::SingleOrg, &conn).await.is_some_and(|p| p.enabled);
if !single_org_policy_enabled {
err!("Turn on the Single organization policy because it is required for the Activate fill assist policy.")
}
}
if pol_type_enum == OrgPolicyType::SingleOrg && !data.enabled && is_currently_enabled {
let fill_assist_policy_enabled =
OrgPolicy::find_by_org_and_type(&org_id, OrgPolicyType::FillAssist, &conn).await.is_some_and(|p| p.enabled);
if fill_assist_policy_enabled {
err!("Turn off the Activate fill assist policy because it requires the Single organization policy.")
}
}
// Bitwarden only allows the Reset Password policy when Single Org policy is enabled
// Vaultwarden encouraged to use multiple orgs instead of groups because groups were not available in the past
// Now that groups are available we can enforce this option when wanted.
@@ -2080,6 +2103,37 @@ async fn put_policy(
}
}
if pol_type_enum == OrgPolicyType::FillAssist {
let fill_assist_data = match data.data.as_ref() {
None | Some(Value::Null) => FillAssistPolicyData {
rules_url: None,
},
Some(data) => {
let Ok(data) = serde_json::from_value::<FillAssistPolicyData>(data.clone()) else {
err!("Invalid data for FillAssist policy: rulesUrl has an invalid value.")
};
data
}
};
if data.enabled {
let Some(rules_url) = fill_assist_data.rules_url.filter(|url| !url.trim().is_empty()) else {
err!("The RulesUrl field is required.")
};
let Ok(rules_url) = url::Url::parse(&rules_url) else {
err!("The RulesUrl field is not a valid fully-qualified http, https, or ftp URL.")
};
if !rules_url.has_host() || !matches!(rules_url.scheme(), "http" | "https" | "ftp") {
err!("The RulesUrl field is not a valid fully-qualified http, https, or ftp URL.")
}
if rules_url.scheme() != "https" {
err!("RulesUrl must use HTTPS.")
}
}
}
// When enabling the TwoFactorAuthentication policy, revoke all members that do not have 2FA
if pol_type_enum == OrgPolicyType::TwoFactorAuthentication && data.enabled {
two_factor::enforce_2fa_policy_for_org(
@@ -2127,7 +2181,7 @@ async fn put_policy(
}
}
let mut policy = match OrgPolicy::find_by_org_and_type(&org_id, pol_type_enum, &conn).await {
let mut policy = match current_policy {
Some(p) => p,
None => OrgPolicy::new(org_id.clone(), pol_type_enum, false, "{}".to_owned()),
};