Bootstrapping fixes

This commit is contained in:
Maurus Decimus
2026-04-20 16:35:21 +02:00
parent 170d0e95a6
commit 1edd85486b
16 changed files with 142 additions and 47 deletions

View File

@@ -62,7 +62,7 @@ impl PrincipalGetAvailability for Server {
access_token: &AccessToken,
) -> trc::Result<GetAvailabilityResponse> {
if !self.core.groupware.allow_directory_query
&& !access_token.has_permission(Permission::SysAccountQuery)
&& !access_token.has_permission(Permission::JmapPrincipalGetAvailability)
{
return Err(trc::JmapEvent::Forbidden
.into_err()

View File

@@ -32,7 +32,7 @@ impl PrincipalGet for Server {
access_token: &AccessToken,
) -> trc::Result<GetResponse<Principal>> {
if !self.core.groupware.allow_directory_query
&& !access_token.has_permission(Permission::SysAccountQuery)
&& !access_token.has_permission(Permission::JmapPrincipalGet)
{
return Err(trc::JmapEvent::Forbidden
.into_err()

View File

@@ -42,7 +42,7 @@ impl PrincipalQuery for Server {
access_token: &AccessToken,
) -> trc::Result<QueryResponse> {
if !self.core.groupware.allow_directory_query
&& !access_token.has_permission(Permission::SysAccountQuery)
&& !access_token.has_permission(Permission::JmapPrincipalQuery)
{
return Err(trc::JmapEvent::Forbidden
.into_err()

View File

@@ -120,7 +120,18 @@ pub(crate) async fn account_set(
set.response.not_updated.append(id, SetError::not_found());
}
let mut account_pass = AccountPassword::default();
let mut account_pass = AccountPassword {
secret: None,
current_secret: None,
otp_auth: OtpAuth {
otp_code: None,
otp_url: if old_credential.otp_auth.is_some() {
Some(MASKED_PASSWORD.to_string())
} else {
None
},
},
};
for (key, value) in value.into_expanded_object() {
let ptr = match key {
@@ -149,23 +160,26 @@ pub(crate) async fn account_set(
}
}
let is_empty_secret =
account_pass.secret.is_empty() || account_pass.secret == MASKED_PASSWORD;
let is_empty_otp = account_pass
.otp_auth
.otp_url
let is_empty_secret = account_pass
.secret
.as_ref()
.is_none_or(|url| url != MASKED_PASSWORD);
.is_none_or(|secret| secret == MASKED_PASSWORD);
let is_empty_otp = account_pass.otp_auth.otp_url.as_deref()
== Some(MASKED_PASSWORD)
|| (account_pass.otp_auth.otp_url.is_none()
&& old_credential.otp_auth.is_none());
if !is_empty_secret || !is_empty_otp {
if is_empty_secret {
account_pass.secret = old_credential.secret.clone();
}
let user_provided_secret = if !is_empty_secret {
account_pass.secret.as_ref().unwrap()
} else {
old_credential.secret.as_str()
};
if is_empty_otp {
account_pass.otp_auth.otp_url = old_credential.otp_auth.clone();
}
// Password changes are not supported when using external directories
if (account_pass.secret != old_credential.secret
if (user_provided_secret != old_credential.secret
|| account_pass.otp_auth.otp_url != old_credential.otp_auth)
&& set
.server
@@ -183,7 +197,7 @@ pub(crate) async fn account_set(
continue 'outer;
}
if account_pass.secret != old_credential.secret
if user_provided_secret != old_credential.secret
|| account_pass.otp_auth.otp_url != old_credential.otp_auth
{
if old_credential.secret.is_empty() {
@@ -249,9 +263,9 @@ pub(crate) async fn account_set(
}
}
if account_pass.secret != old_credential.secret {
if user_provided_secret != old_credential.secret {
if let Err(err) =
set.server.is_secure_password(&account_pass.secret, &[])
set.server.is_secure_password(user_provided_secret, &[])
{
set.response.not_updated.append(
id,
@@ -278,7 +292,7 @@ pub(crate) async fn account_set(
old_credential.secret = hash_secret(
set.server.core.network.security.password_hash_algorithm,
account_pass.secret.into_bytes(),
user_provided_secret.as_bytes().to_vec(),
)
.await
.caused_by(trc::location!())?;
@@ -722,7 +736,7 @@ pub(crate) async fn account_get(
None
},
},
secret: MASKED_PASSWORD.into(),
secret: MASKED_PASSWORD.to_string().into(),
}
.into_value(),
);