JMAP/changes: Update newState with last changeId if an invalid fromChangeId is provided
This commit is contained in:
@@ -199,7 +199,6 @@ fn validate_identity_value(
|
|||||||
identity: &mut ParticipantIdentity,
|
identity: &mut ParticipantIdentity,
|
||||||
allowed_emails: &AHashSet<String>,
|
allowed_emails: &AHashSet<String>,
|
||||||
) -> Result<(), SetError<ParticipantIdentityProperty>> {
|
) -> Result<(), SetError<ParticipantIdentityProperty>> {
|
||||||
let mut changed_address = None;
|
|
||||||
for (property, value) in update.into_expanded_object() {
|
for (property, value) in update.into_expanded_object() {
|
||||||
let Key::Property(property) = property else {
|
let Key::Property(property) = property else {
|
||||||
return Err(SetError::invalid_properties()
|
return Err(SetError::invalid_properties()
|
||||||
@@ -213,7 +212,27 @@ fn validate_identity_value(
|
|||||||
}
|
}
|
||||||
(ParticipantIdentityProperty::CalendarAddress, Value::Str(value)) => {
|
(ParticipantIdentityProperty::CalendarAddress, Value::Str(value)) => {
|
||||||
if identity.calendar_address != value {
|
if identity.calendar_address != value {
|
||||||
changed_address = Some(value);
|
let email = if let Some(email) = value.strip_prefix("mailto:") {
|
||||||
|
sanitize_email(email)
|
||||||
|
} else {
|
||||||
|
sanitize_email(&value)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(email) = email {
|
||||||
|
if allowed_emails.iter().any(|e| e == &email) {
|
||||||
|
identity.calendar_address = format!("mailto:{email}");
|
||||||
|
} else {
|
||||||
|
return Err(SetError::invalid_properties()
|
||||||
|
.with_property(ParticipantIdentityProperty::CalendarAddress)
|
||||||
|
.with_description(
|
||||||
|
"Calendar address not configured for this account.".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(SetError::invalid_properties()
|
||||||
|
.with_property(ParticipantIdentityProperty::CalendarAddress)
|
||||||
|
.with_description("Invalid or missing calendar address.".to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(property, _) => {
|
(property, _) => {
|
||||||
@@ -223,34 +242,10 @@ fn validate_identity_value(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate email address
|
// Validate email address
|
||||||
if !identity.calendar_address.is_empty() {
|
if !identity.calendar_address.is_empty() {
|
||||||
if let Some(new_address) = changed_address {
|
Ok(())
|
||||||
let email = if let Some(email) = new_address.strip_prefix("mailto:") {
|
|
||||||
sanitize_email(email)
|
|
||||||
} else {
|
|
||||||
sanitize_email(&new_address)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(email) = email {
|
|
||||||
if allowed_emails.iter().any(|e| e == &email) {
|
|
||||||
identity.calendar_address = format!("mailto:{email}");
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(SetError::invalid_properties()
|
|
||||||
.with_property(ParticipantIdentityProperty::CalendarAddress)
|
|
||||||
.with_description(
|
|
||||||
"Calendar address not configured for this account.".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(SetError::invalid_properties()
|
|
||||||
.with_property(ParticipantIdentityProperty::CalendarAddress)
|
|
||||||
.with_description("Invalid or missing calendar address.".to_string()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(SetError::invalid_properties()
|
Err(SetError::invalid_properties()
|
||||||
.with_property(ParticipantIdentityProperty::CalendarAddress)
|
.with_property(ParticipantIdentityProperty::CalendarAddress)
|
||||||
|
|||||||
@@ -63,14 +63,14 @@ impl Store {
|
|||||||
pub async fn changes(
|
pub async fn changes(
|
||||||
&self,
|
&self,
|
||||||
account_id: u32,
|
account_id: u32,
|
||||||
collection: LogCollection,
|
collection_: LogCollection,
|
||||||
query: Query,
|
query: Query,
|
||||||
) -> trc::Result<Changes> {
|
) -> trc::Result<Changes> {
|
||||||
let is_share_log = matches!(
|
let is_share_log = matches!(
|
||||||
collection,
|
collection_,
|
||||||
LogCollection::Sync(SyncCollection::ShareNotification)
|
LogCollection::Sync(SyncCollection::ShareNotification)
|
||||||
);
|
);
|
||||||
let collection = u8::from(collection);
|
let collection = u8::from(collection_);
|
||||||
|
|
||||||
let (is_inclusive, from_change_id, to_change_id) = match query {
|
let (is_inclusive, from_change_id, to_change_id) = match query {
|
||||||
Query::All => (true, 0, u64::MAX),
|
Query::All => (true, 0, u64::MAX),
|
||||||
@@ -127,13 +127,13 @@ impl Store {
|
|||||||
.await
|
.await
|
||||||
.caused_by(trc::location!())?;
|
.caused_by(trc::location!())?;
|
||||||
|
|
||||||
if changelog.changes.is_empty() {
|
// A non-existing change id was requested, return the last change id
|
||||||
changelog.from_change_id = from_change_id;
|
if changelog.changes.is_empty() && from_change_id != 0 && changelog.from_change_id == 0 {
|
||||||
changelog.to_change_id = if to_change_id != u64::MAX {
|
changelog.from_change_id = self
|
||||||
to_change_id
|
.get_last_change_id(account_id, collection_)
|
||||||
} else {
|
.await?
|
||||||
from_change_id
|
.unwrap_or_default();
|
||||||
};
|
changelog.to_change_id = changelog.from_change_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(changelog)
|
Ok(changelog)
|
||||||
|
|||||||
Reference in New Issue
Block a user