39089 lines
1.4 MiB
39089 lines
1.4 MiB
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
// This file is auto-generated. Do not edit directly.
|
|
|
|
use crate::schema::prelude::*;
|
|
|
|
impl ObjectImpl for Account {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Account;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Account::User(inner) => inner.validate(errors),
|
|
Account::Group(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
Account::User(object) => {
|
|
i.typ(0);
|
|
object.index(i);
|
|
}
|
|
Account::Group(object) => {
|
|
i.typ(1);
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Account {
|
|
fn default() -> Self {
|
|
Account::User(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Account {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Account::User(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Account::Group(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Account::User),
|
|
1 => Pickle::unpickle(stream).map(Account::Group),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Account {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Account::User(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("User".into()));
|
|
obj
|
|
}
|
|
Account::Group(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Group".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Account {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
AccountType::User => *self = Account::User(Default::default()),
|
|
AccountType::Group => *self = Account::Group(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Account::User(inner) => inner.patch(pointer, value),
|
|
Account::Group(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Account {
|
|
pub fn object_type(&self) -> AccountType {
|
|
match self {
|
|
Account::User(_) => AccountType::User,
|
|
Account::Group(_) => AccountType::Group,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AccountPassword {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AccountPassword;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.secret {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
}
|
|
if let Some(value) = &self.current_secret {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::CurrentSecret));
|
|
}
|
|
}
|
|
let value = &self.otp_auth;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for AccountPassword {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.secret.pickle(out);
|
|
self.current_secret.pickle(out);
|
|
self.otp_auth.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.current_secret = Pickle::unpickle(stream)?;
|
|
this.otp_auth = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AccountPassword {
|
|
fn default() -> Self {
|
|
Self {
|
|
secret: Default::default(),
|
|
current_secret: Default::default(),
|
|
otp_auth: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AccountPassword {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
if self.secret.is_some() {
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
}
|
|
if self.current_secret.is_some() {
|
|
map.insert_unchecked(
|
|
Property::CurrentSecret,
|
|
JmapValue::Str(MASKED_PASSWORD.into()),
|
|
);
|
|
}
|
|
map.insert_unchecked(Property::OtpAuth, self.otp_auth.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AccountPassword {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::CurrentSecret) => self.current_secret.patch(pointer, value),
|
|
Some(Property::OtpAuth) => self.otp_auth.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AccountSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AccountSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.encryption_at_rest;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
if let Some(value) = &self.description {
|
|
i.text(Property::Text, value);
|
|
}
|
|
self.encryption_at_rest.index(i);
|
|
}
|
|
}
|
|
|
|
impl Pickle for AccountSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.locale.pickle(out);
|
|
self.time_zone.pickle(out);
|
|
self.encryption_at_rest.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.locale = Pickle::unpickle(stream)?;
|
|
this.time_zone = Pickle::unpickle(stream)?;
|
|
this.encryption_at_rest = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AccountSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
locale: Locale::EnUS,
|
|
time_zone: Default::default(),
|
|
encryption_at_rest: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AccountSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Locale, self.locale.into_value());
|
|
map.insert_unchecked(Property::TimeZone, self.time_zone.into_value());
|
|
map.insert_unchecked(
|
|
Property::EncryptionAtRest,
|
|
self.encryption_at_rest.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AccountSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Locale) => self.locale.patch(pointer, value),
|
|
Some(Property::TimeZone) => self.time_zone.patch(pointer, value),
|
|
Some(Property::EncryptionAtRest) => self.encryption_at_rest.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AcmeProvider {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AcmeProvider;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.contact;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Contact));
|
|
}
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Contact, 1));
|
|
}
|
|
let value = &self.directory;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Directory));
|
|
}
|
|
let value = &self.account_key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AccountKey));
|
|
}
|
|
let value = &self.account_uri;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AccountUri));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
for value in self.contact.iter() {
|
|
i.text(Property::Text, value);
|
|
}
|
|
i.text(Property::Text, &self.directory);
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for AcmeProvider {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.challenge_type.pickle(out);
|
|
self.contact.pickle(out);
|
|
self.directory.pickle(out);
|
|
self.account_key.pickle(out);
|
|
self.account_uri.pickle(out);
|
|
self.renew_before.pickle(out);
|
|
self.max_retries.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.challenge_type = Pickle::unpickle(stream)?;
|
|
this.contact = Pickle::unpickle(stream)?;
|
|
this.directory = Pickle::unpickle(stream)?;
|
|
this.account_key = Pickle::unpickle(stream)?;
|
|
this.account_uri = Pickle::unpickle(stream)?;
|
|
this.renew_before = Pickle::unpickle(stream)?;
|
|
this.max_retries = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AcmeProvider {
|
|
fn default() -> Self {
|
|
Self {
|
|
challenge_type: AcmeChallengeType::TlsAlpn01,
|
|
contact: Default::default(),
|
|
directory: "https://acme-v02.api.letsencrypt.org/directory".to_string(),
|
|
account_key: Default::default(),
|
|
account_uri: Default::default(),
|
|
renew_before: AcmeRenewBefore::R23,
|
|
max_retries: 10i64,
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AcmeProvider {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::ChallengeType, self.challenge_type.into_value());
|
|
map.insert_unchecked(Property::Contact, self.contact.into_value());
|
|
map.insert_unchecked(Property::Directory, self.directory.into_value());
|
|
map.insert_unchecked(Property::AccountKey, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
map.insert_unchecked(Property::AccountUri, self.account_uri.into_value());
|
|
map.insert_unchecked(Property::RenewBefore, self.renew_before.into_value());
|
|
map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AcmeProvider {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ChallengeType) => self.challenge_type.patch(pointer, value),
|
|
Some(Property::Contact) => self
|
|
.contact
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Directory) => self.directory.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Trim]),
|
|
value,
|
|
),
|
|
Some(property @ Property::EabHmacKey) => {
|
|
Ok(MaybeUnpatched::Unpatched { property, value })
|
|
}
|
|
Some(property @ Property::EabKeyId) => {
|
|
Ok(MaybeUnpatched::Unpatched { property, value })
|
|
}
|
|
Some(Property::AccountKey) => pointer.assert_server_set(),
|
|
Some(Property::AccountUri) => pointer.assert_server_set(),
|
|
Some(Property::RenewBefore) => self.renew_before.patch(pointer, value),
|
|
Some(Property::MaxRetries) => self.max_retries.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Action {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Action;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Action::ReloadSettings => true,
|
|
Action::ReloadTlsCertificates => true,
|
|
Action::ReloadLookupStores => true,
|
|
Action::ReloadBlockedIps => true,
|
|
Action::UpdateApps => true,
|
|
Action::TroubleshootDmarc(inner) => inner.validate(errors),
|
|
Action::ClassifySpam(inner) => inner.validate(errors),
|
|
Action::InvalidateCaches => true,
|
|
Action::InvalidateNegativeCaches => true,
|
|
Action::PauseMtaQueue => true,
|
|
Action::ResumeMtaQueue => true,
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for Action {
|
|
fn default() -> Self {
|
|
Action::ReloadSettings
|
|
}
|
|
}
|
|
|
|
impl Pickle for Action {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Action::ReloadSettings => {
|
|
0u16.pickle(out);
|
|
}
|
|
Action::ReloadTlsCertificates => {
|
|
1u16.pickle(out);
|
|
}
|
|
Action::ReloadLookupStores => {
|
|
2u16.pickle(out);
|
|
}
|
|
Action::ReloadBlockedIps => {
|
|
3u16.pickle(out);
|
|
}
|
|
Action::UpdateApps => {
|
|
4u16.pickle(out);
|
|
}
|
|
Action::TroubleshootDmarc(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Action::ClassifySpam(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Action::InvalidateCaches => {
|
|
7u16.pickle(out);
|
|
}
|
|
Action::InvalidateNegativeCaches => {
|
|
8u16.pickle(out);
|
|
}
|
|
Action::PauseMtaQueue => {
|
|
9u16.pickle(out);
|
|
}
|
|
Action::ResumeMtaQueue => {
|
|
10u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(Action::ReloadSettings),
|
|
1 => Some(Action::ReloadTlsCertificates),
|
|
2 => Some(Action::ReloadLookupStores),
|
|
3 => Some(Action::ReloadBlockedIps),
|
|
4 => Some(Action::UpdateApps),
|
|
5 => Pickle::unpickle(stream).map(Action::TroubleshootDmarc),
|
|
6 => Pickle::unpickle(stream).map(Action::ClassifySpam),
|
|
7 => Some(Action::InvalidateCaches),
|
|
8 => Some(Action::InvalidateNegativeCaches),
|
|
9 => Some(Action::PauseMtaQueue),
|
|
10 => Some(Action::ResumeMtaQueue),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Action {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Action::ReloadSettings => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ReloadSettings".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::ReloadTlsCertificates => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(
|
|
Property::Type,
|
|
JmapValue::Str("ReloadTlsCertificates".into()),
|
|
);
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::ReloadLookupStores => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ReloadLookupStores".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::ReloadBlockedIps => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ReloadBlockedIps".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::UpdateApps => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("UpdateApps".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::TroubleshootDmarc(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("TroubleshootDmarc".into()));
|
|
obj
|
|
}
|
|
Action::ClassifySpam(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("ClassifySpam".into()));
|
|
obj
|
|
}
|
|
Action::InvalidateCaches => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("InvalidateCaches".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::InvalidateNegativeCaches => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(
|
|
Property::Type,
|
|
JmapValue::Str("InvalidateNegativeCaches".into()),
|
|
);
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::PauseMtaQueue => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("PauseMtaQueue".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Action::ResumeMtaQueue => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ResumeMtaQueue".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Action {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
ActionType::ReloadSettings => *self = Action::ReloadSettings,
|
|
ActionType::ReloadTlsCertificates => *self = Action::ReloadTlsCertificates,
|
|
ActionType::ReloadLookupStores => *self = Action::ReloadLookupStores,
|
|
ActionType::ReloadBlockedIps => *self = Action::ReloadBlockedIps,
|
|
ActionType::UpdateApps => *self = Action::UpdateApps,
|
|
ActionType::TroubleshootDmarc => {
|
|
*self = Action::TroubleshootDmarc(Default::default())
|
|
}
|
|
ActionType::ClassifySpam => *self = Action::ClassifySpam(Default::default()),
|
|
ActionType::InvalidateCaches => *self = Action::InvalidateCaches,
|
|
ActionType::InvalidateNegativeCaches => *self = Action::InvalidateNegativeCaches,
|
|
ActionType::PauseMtaQueue => *self = Action::PauseMtaQueue,
|
|
ActionType::ResumeMtaQueue => *self = Action::ResumeMtaQueue,
|
|
}
|
|
}
|
|
match self {
|
|
Action::ReloadSettings => pointer.assert_eof(),
|
|
Action::ReloadTlsCertificates => pointer.assert_eof(),
|
|
Action::ReloadLookupStores => pointer.assert_eof(),
|
|
Action::ReloadBlockedIps => pointer.assert_eof(),
|
|
Action::UpdateApps => pointer.assert_eof(),
|
|
Action::TroubleshootDmarc(inner) => inner.patch(pointer, value),
|
|
Action::ClassifySpam(inner) => inner.patch(pointer, value),
|
|
Action::InvalidateCaches => pointer.assert_eof(),
|
|
Action::InvalidateNegativeCaches => pointer.assert_eof(),
|
|
Action::PauseMtaQueue => pointer.assert_eof(),
|
|
Action::ResumeMtaQueue => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Action {
|
|
pub fn object_type(&self) -> ActionType {
|
|
match self {
|
|
Action::ReloadSettings => ActionType::ReloadSettings,
|
|
Action::ReloadTlsCertificates => ActionType::ReloadTlsCertificates,
|
|
Action::ReloadLookupStores => ActionType::ReloadLookupStores,
|
|
Action::ReloadBlockedIps => ActionType::ReloadBlockedIps,
|
|
Action::UpdateApps => ActionType::UpdateApps,
|
|
Action::TroubleshootDmarc(_) => ActionType::TroubleshootDmarc,
|
|
Action::ClassifySpam(_) => ActionType::ClassifySpam,
|
|
Action::InvalidateCaches => ActionType::InvalidateCaches,
|
|
Action::InvalidateNegativeCaches => ActionType::InvalidateNegativeCaches,
|
|
Action::PauseMtaQueue => ActionType::PauseMtaQueue,
|
|
Action::ResumeMtaQueue => ActionType::ResumeMtaQueue,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AddressBook {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AddressBook;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.default_display_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultDisplayName));
|
|
}
|
|
}
|
|
if let Some(value) = &self.default_href_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultHrefName));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_address_books {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxAddressBooks, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_contacts {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxContacts, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for AddressBook {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.default_display_name.pickle(out);
|
|
self.default_href_name.pickle(out);
|
|
self.max_v_card_size.pickle(out);
|
|
self.max_address_books.pickle(out);
|
|
self.max_contacts.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.default_display_name = Pickle::unpickle(stream)?;
|
|
this.default_href_name = Pickle::unpickle(stream)?;
|
|
this.max_v_card_size = Pickle::unpickle(stream)?;
|
|
this.max_address_books = Pickle::unpickle(stream)?;
|
|
this.max_contacts = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AddressBook {
|
|
fn default() -> Self {
|
|
Self {
|
|
default_display_name: Some("Stalwart Address Book".to_string()),
|
|
default_href_name: Some("default".to_string()),
|
|
max_v_card_size: 524288u64,
|
|
max_address_books: Some(250u64),
|
|
max_contacts: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AddressBook {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(
|
|
Property::DefaultDisplayName,
|
|
self.default_display_name.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultHrefName,
|
|
self.default_href_name.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxVCardSize, self.max_v_card_size.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxAddressBooks,
|
|
self.max_address_books.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxContacts, self.max_contacts.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AddressBook {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DefaultDisplayName) => self
|
|
.default_display_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::DefaultHrefName) => self
|
|
.default_href_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MaxVCardSize) => self.max_v_card_size.patch(pointer, value),
|
|
Some(Property::MaxAddressBooks) => self.max_address_books.patch(pointer, value),
|
|
Some(Property::MaxContacts) => self.max_contacts.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AiModel {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AiModel;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.temperature;
|
|
if *value > Float::new(1.0) {
|
|
errors.push(ValidationError::max_value(Property::Temperature, 1));
|
|
}
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::Temperature, 0));
|
|
}
|
|
let value = &self.model;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Model));
|
|
}
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for AiModel {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.temperature.pickle(out);
|
|
self.model.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.model_type.pickle(out);
|
|
self.url.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.temperature = Pickle::unpickle(stream)?;
|
|
this.model = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.model_type = Pickle::unpickle(stream)?;
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AiModel {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
allow_invalid_certs: false,
|
|
temperature: Float::new(0.7f64),
|
|
model: Default::default(),
|
|
timeout: Duration::from_millis(120000),
|
|
model_type: AiModelType::Chat,
|
|
url: Default::default(),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AiModel {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Temperature, self.temperature.into_value());
|
|
map.insert_unchecked(Property::Model, self.model.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::ModelType, self.model_type.into_value());
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AiModel {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self
|
|
.name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::Temperature) => self.temperature.patch(pointer, value),
|
|
Some(Property::Model) => self
|
|
.model
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::ModelType) => self.model_type.patch(pointer, value),
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Alert {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Alert;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.email_alert;
|
|
value.validate(errors);
|
|
let value = &self.event_alert;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Alert {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: &[],
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for Alert {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.email_alert.pickle(out);
|
|
self.event_alert.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.email_alert = Pickle::unpickle(stream)?;
|
|
this.event_alert = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Alert {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
email_alert: Default::default(),
|
|
event_alert: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Alert {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::EmailAlert, self.email_alert.into_value());
|
|
map.insert_unchecked(Property::EventAlert, self.event_alert.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Alert {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::EmailAlert) => self.email_alert.patch(pointer, value),
|
|
Some(Property::EventAlert) => self.event_alert.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AlertEmail {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
AlertEmail::Disabled => true,
|
|
AlertEmail::Enabled(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for AlertEmail {
|
|
fn default() -> Self {
|
|
AlertEmail::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for AlertEmail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
AlertEmail::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
AlertEmail::Enabled(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(AlertEmail::Disabled),
|
|
1 => Pickle::unpickle(stream).map(AlertEmail::Enabled),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AlertEmail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
AlertEmail::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
AlertEmail::Enabled(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Enabled".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for AlertEmail {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
AlertEmailType::Disabled => *self = AlertEmail::Disabled,
|
|
AlertEmailType::Enabled => *self = AlertEmail::Enabled(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
AlertEmail::Disabled => pointer.assert_eof(),
|
|
AlertEmail::Enabled(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AlertEmail {
|
|
pub fn object_type(&self) -> AlertEmailType {
|
|
match self {
|
|
AlertEmail::Disabled => AlertEmailType::Disabled,
|
|
AlertEmail::Enabled(_) => AlertEmailType::Enabled,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AlertEmailProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.body;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Body));
|
|
}
|
|
let value = &self.from_address;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FromAddress));
|
|
}
|
|
if let Some(value) = &self.from_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FromName));
|
|
}
|
|
}
|
|
let value = &self.subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Subject));
|
|
}
|
|
let value = &self.to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::To));
|
|
}
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::To, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for AlertEmailProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.body.pickle(out);
|
|
self.from_address.pickle(out);
|
|
self.from_name.pickle(out);
|
|
self.subject.pickle(out);
|
|
self.to.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.body = Pickle::unpickle(stream)?;
|
|
this.from_address = Pickle::unpickle(stream)?;
|
|
this.from_name = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
this.to = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AlertEmailProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
body: Default::default(),
|
|
from_address: Default::default(),
|
|
from_name: Default::default(),
|
|
subject: Default::default(),
|
|
to: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AlertEmailProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Body, self.body.into_value());
|
|
map.insert_unchecked(Property::FromAddress, self.from_address.into_value());
|
|
map.insert_unchecked(Property::FromName, self.from_name.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
map.insert_unchecked(Property::To, self.to.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AlertEmailProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Body) => self.body.patch(pointer, value),
|
|
Some(Property::FromAddress) => self
|
|
.from_address
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::FromName) => self.from_name.patch(pointer, value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::To) => self
|
|
.to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AlertEvent {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
AlertEvent::Disabled => true,
|
|
AlertEvent::Enabled(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for AlertEvent {
|
|
fn default() -> Self {
|
|
AlertEvent::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for AlertEvent {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
AlertEvent::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
AlertEvent::Enabled(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(AlertEvent::Disabled),
|
|
1 => Pickle::unpickle(stream).map(AlertEvent::Enabled),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AlertEvent {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
AlertEvent::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
AlertEvent::Enabled(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Enabled".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for AlertEvent {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
AlertEventType::Disabled => *self = AlertEvent::Disabled,
|
|
AlertEventType::Enabled => *self = AlertEvent::Enabled(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
AlertEvent::Disabled => pointer.assert_eof(),
|
|
AlertEvent::Enabled(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AlertEvent {
|
|
pub fn object_type(&self) -> AlertEventType {
|
|
match self {
|
|
AlertEvent::Disabled => AlertEventType::Disabled,
|
|
AlertEvent::Enabled(_) => AlertEventType::Enabled,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AlertEventProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.event_message {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EventMessage));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for AlertEventProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.event_message.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.event_message = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AlertEventProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
event_message: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AlertEventProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::EventMessage, self.event_message.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AlertEventProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::EventMessage) => self.event_message.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AllowedIp {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AllowedIp;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.address;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Address, value));
|
|
}
|
|
if let Some(value) = &self.reason {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Reason));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Address, &self.address);
|
|
}
|
|
}
|
|
|
|
impl Pickle for AllowedIp {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.address.pickle(out);
|
|
self.reason.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.address = Pickle::unpickle(stream)?;
|
|
this.reason = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AllowedIp {
|
|
fn default() -> Self {
|
|
Self {
|
|
address: Default::default(),
|
|
reason: Default::default(),
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AllowedIp {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Address, self.address.into_value());
|
|
map.insert_unchecked(Property::Reason, self.reason.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AllowedIp {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Address) => self.address.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Trim]),
|
|
value,
|
|
),
|
|
Some(Property::Reason) => self
|
|
.reason
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::CreatedAt) => self.created_at.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for ApiKey {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::ApiKey;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
let value = &self.permissions;
|
|
value.validate(errors);
|
|
let value = &self.allowed_ips;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::AllowedIps, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for ApiKey {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.permissions.pickle(out);
|
|
self.allowed_ips.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
this.allowed_ips = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ApiKey {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
secret: Default::default(),
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
permissions: Default::default(),
|
|
allowed_ips: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ApiKey {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ApiKey {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Secret) => pointer.assert_server_set(),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for AppPassword {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::AppPassword;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
let value = &self.permissions;
|
|
value.validate(errors);
|
|
let value = &self.allowed_ips;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::AllowedIps, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for AppPassword {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.permissions.pickle(out);
|
|
self.allowed_ips.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
this.allowed_ips = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AppPassword {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
secret: Default::default(),
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
permissions: Default::default(),
|
|
allowed_ips: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AppPassword {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AppPassword {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Secret) => pointer.assert_server_set(),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Application {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Application;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.resource_url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResourceUrl));
|
|
}
|
|
let value = &self.url_prefix;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::UrlPrefix));
|
|
}
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::UrlPrefix, 1));
|
|
}
|
|
if let Some(value) = &self.unpack_directory {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::UnpackDirectory));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Application {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enabled.pickle(out);
|
|
self.description.pickle(out);
|
|
self.resource_url.pickle(out);
|
|
self.url_prefix.pickle(out);
|
|
self.auto_update_frequency.pickle(out);
|
|
self.unpack_directory.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enabled = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.resource_url = Pickle::unpickle(stream)?;
|
|
this.url_prefix = Pickle::unpickle(stream)?;
|
|
this.auto_update_frequency = Pickle::unpickle(stream)?;
|
|
this.unpack_directory = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Application {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
description: Default::default(),
|
|
resource_url: Default::default(),
|
|
url_prefix: Default::default(),
|
|
auto_update_frequency: Duration::from_millis(7776000000),
|
|
unpack_directory: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Application {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Enabled, self.enabled.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::ResourceUrl, self.resource_url.into_value());
|
|
map.insert_unchecked(Property::UrlPrefix, self.url_prefix.into_value());
|
|
map.insert_unchecked(
|
|
Property::AutoUpdateFrequency,
|
|
self.auto_update_frequency.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::UnpackDirectory,
|
|
self.unpack_directory.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Application {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enabled) => self.enabled.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ResourceUrl) => self
|
|
.resource_url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::UrlPrefix) => self
|
|
.url_prefix
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AutoUpdateFrequency) => self.auto_update_frequency.patch(pointer, value),
|
|
Some(Property::UnpackDirectory) => self
|
|
.unpack_directory
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchivedCalendarEvent {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.title;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Title));
|
|
}
|
|
if let Some(value) = &self.start_time {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::StartTime, value));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.archived_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedAt, value));
|
|
}
|
|
let value = &self.archived_until;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedUntil, value));
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArchivedCalendarEvent {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.title.pickle(out);
|
|
self.start_time.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.archived_at.pickle(out);
|
|
self.archived_until.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.title = Pickle::unpickle(stream)?;
|
|
this.start_time = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.archived_at = Pickle::unpickle(stream)?;
|
|
this.archived_until = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArchivedCalendarEvent {
|
|
fn default() -> Self {
|
|
Self {
|
|
title: Default::default(),
|
|
start_time: Default::default(),
|
|
created_at: Default::default(),
|
|
account_id: Default::default(),
|
|
archived_at: Default::default(),
|
|
archived_until: Default::default(),
|
|
blob_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArchivedCalendarEvent {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Title, self.title.into_value());
|
|
map.insert_unchecked(Property::StartTime, self.start_time.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value());
|
|
map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArchivedCalendarEvent {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Title) => self.title.patch(pointer, value),
|
|
Some(Property::StartTime) => self.start_time.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_can_set_account()?, value),
|
|
Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value),
|
|
Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value),
|
|
Some(Property::BlobId) => self.blob_id.patch(pointer, value),
|
|
Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchivedContactCard {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.archived_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedAt, value));
|
|
}
|
|
let value = &self.archived_until;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedUntil, value));
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArchivedContactCard {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.archived_at.pickle(out);
|
|
self.archived_until.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.archived_at = Pickle::unpickle(stream)?;
|
|
this.archived_until = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArchivedContactCard {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
created_at: Default::default(),
|
|
account_id: Default::default(),
|
|
archived_at: Default::default(),
|
|
archived_until: Default::default(),
|
|
blob_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArchivedContactCard {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value());
|
|
map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArchivedContactCard {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_can_set_account()?, value),
|
|
Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value),
|
|
Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value),
|
|
Some(Property::BlobId) => self.blob_id.patch(pointer, value),
|
|
Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchivedEmail {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::From));
|
|
}
|
|
let value = &self.subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Subject));
|
|
}
|
|
let value = &self.received_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ReceivedAt, value));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.archived_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedAt, value));
|
|
}
|
|
let value = &self.archived_until;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedUntil, value));
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArchivedEmail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.from.pickle(out);
|
|
self.subject.pickle(out);
|
|
self.received_at.pickle(out);
|
|
self.size.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.archived_at.pickle(out);
|
|
self.archived_until.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.from = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
this.received_at = Pickle::unpickle(stream)?;
|
|
this.size = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.archived_at = Pickle::unpickle(stream)?;
|
|
this.archived_until = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArchivedEmail {
|
|
fn default() -> Self {
|
|
Self {
|
|
from: Default::default(),
|
|
subject: Default::default(),
|
|
received_at: Default::default(),
|
|
size: 0u64,
|
|
account_id: Default::default(),
|
|
archived_at: Default::default(),
|
|
archived_until: Default::default(),
|
|
blob_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArchivedEmail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::From, self.from.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value());
|
|
map.insert_unchecked(Property::Size, self.size.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value());
|
|
map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArchivedEmail {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::From) => self.from.patch(pointer, value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::ReceivedAt) => self.received_at.patch(pointer, value),
|
|
Some(Property::Size) => self.size.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_can_set_account()?, value),
|
|
Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value),
|
|
Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value),
|
|
Some(Property::BlobId) => self.blob_id.patch(pointer, value),
|
|
Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchivedFileNode {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.archived_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedAt, value));
|
|
}
|
|
let value = &self.archived_until;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedUntil, value));
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArchivedFileNode {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.archived_at.pickle(out);
|
|
self.archived_until.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.archived_at = Pickle::unpickle(stream)?;
|
|
this.archived_until = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArchivedFileNode {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
created_at: Default::default(),
|
|
account_id: Default::default(),
|
|
archived_at: Default::default(),
|
|
archived_until: Default::default(),
|
|
blob_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArchivedFileNode {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value());
|
|
map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArchivedFileNode {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_can_set_account()?, value),
|
|
Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value),
|
|
Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value),
|
|
Some(Property::BlobId) => self.blob_id.patch(pointer, value),
|
|
Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for ArchivedItem {
|
|
const FLAGS: u64 = OBJ_FILTER_ACCOUNT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::ArchivedItem;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
ArchivedItem::Email(inner) => inner.validate(errors),
|
|
ArchivedItem::FileNode(inner) => inner.validate(errors),
|
|
ArchivedItem::CalendarEvent(inner) => inner.validate(errors),
|
|
ArchivedItem::ContactCard(inner) => inner.validate(errors),
|
|
ArchivedItem::SieveScript(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
ArchivedItem::Email(object) => {
|
|
object.index(i);
|
|
}
|
|
ArchivedItem::FileNode(object) => {
|
|
object.index(i);
|
|
}
|
|
ArchivedItem::CalendarEvent(object) => {
|
|
object.index(i);
|
|
}
|
|
ArchivedItem::ContactCard(object) => {
|
|
object.index(i);
|
|
}
|
|
ArchivedItem::SieveScript(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for ArchivedItem {
|
|
fn default() -> Self {
|
|
ArchivedItem::Email(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArchivedItem {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
ArchivedItem::Email(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
ArchivedItem::FileNode(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
ArchivedItem::CalendarEvent(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
ArchivedItem::ContactCard(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
ArchivedItem::SieveScript(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(ArchivedItem::Email),
|
|
1 => Pickle::unpickle(stream).map(ArchivedItem::FileNode),
|
|
2 => Pickle::unpickle(stream).map(ArchivedItem::CalendarEvent),
|
|
3 => Pickle::unpickle(stream).map(ArchivedItem::ContactCard),
|
|
4 => Pickle::unpickle(stream).map(ArchivedItem::SieveScript),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArchivedItem {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
ArchivedItem::Email(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Email".into()));
|
|
obj
|
|
}
|
|
ArchivedItem::FileNode(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FileNode".into()));
|
|
obj
|
|
}
|
|
ArchivedItem::CalendarEvent(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("CalendarEvent".into()));
|
|
obj
|
|
}
|
|
ArchivedItem::ContactCard(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("ContactCard".into()));
|
|
obj
|
|
}
|
|
ArchivedItem::SieveScript(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("SieveScript".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for ArchivedItem {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
ArchivedItemType::Email => *self = ArchivedItem::Email(Default::default()),
|
|
ArchivedItemType::FileNode => *self = ArchivedItem::FileNode(Default::default()),
|
|
ArchivedItemType::CalendarEvent => {
|
|
*self = ArchivedItem::CalendarEvent(Default::default())
|
|
}
|
|
ArchivedItemType::ContactCard => {
|
|
*self = ArchivedItem::ContactCard(Default::default())
|
|
}
|
|
ArchivedItemType::SieveScript => {
|
|
*self = ArchivedItem::SieveScript(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
ArchivedItem::Email(inner) => inner.patch(pointer, value),
|
|
ArchivedItem::FileNode(inner) => inner.patch(pointer, value),
|
|
ArchivedItem::CalendarEvent(inner) => inner.patch(pointer, value),
|
|
ArchivedItem::ContactCard(inner) => inner.patch(pointer, value),
|
|
ArchivedItem::SieveScript(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchivedItem {
|
|
pub fn object_type(&self) -> ArchivedItemType {
|
|
match self {
|
|
ArchivedItem::Email(_) => ArchivedItemType::Email,
|
|
ArchivedItem::FileNode(_) => ArchivedItemType::FileNode,
|
|
ArchivedItem::CalendarEvent(_) => ArchivedItemType::CalendarEvent,
|
|
ArchivedItem::ContactCard(_) => ArchivedItemType::ContactCard,
|
|
ArchivedItem::SieveScript(_) => ArchivedItemType::SieveScript,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchivedSieveScript {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.content;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Content));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.archived_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedAt, value));
|
|
}
|
|
let value = &self.archived_until;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedUntil, value));
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArchivedSieveScript {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.content.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.archived_at.pickle(out);
|
|
self.archived_until.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.content = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.archived_at = Pickle::unpickle(stream)?;
|
|
this.archived_until = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArchivedSieveScript {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
created_at: Default::default(),
|
|
content: Default::default(),
|
|
account_id: Default::default(),
|
|
archived_at: Default::default(),
|
|
archived_until: Default::default(),
|
|
blob_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArchivedSieveScript {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::Content, self.content.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value());
|
|
map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArchivedSieveScript {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::Content) => self.content.patch(pointer, value),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_can_set_account()?, value),
|
|
Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value),
|
|
Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value),
|
|
Some(Property::BlobId) => self.blob_id.patch(pointer, value),
|
|
Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for ArfExternalReport {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::ArfExternalReport;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.report;
|
|
value.validate(errors);
|
|
let value = &self.from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::From));
|
|
}
|
|
let value = &self.subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Subject));
|
|
}
|
|
let value = &self.to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::To));
|
|
}
|
|
}
|
|
let value = &self.received_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ReceivedAt, value));
|
|
}
|
|
let value = &self.expires_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArfExternalReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.report.pickle(out);
|
|
self.from.pickle(out);
|
|
self.subject.pickle(out);
|
|
self.to.pickle(out);
|
|
self.received_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.report = Pickle::unpickle(stream)?;
|
|
this.from = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
this.to = Pickle::unpickle(stream)?;
|
|
this.received_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArfExternalReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
report: Default::default(),
|
|
from: Default::default(),
|
|
subject: Default::default(),
|
|
to: Default::default(),
|
|
received_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArfExternalReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Report, self.report.into_value());
|
|
map.insert_unchecked(Property::From, self.from.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
map.insert_unchecked(Property::To, self.to.into_value());
|
|
map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArfExternalReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Report) => self.report.patch(pointer, value),
|
|
Some(Property::From) => self
|
|
.from
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::To) => self
|
|
.to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::ReceivedAt) => self.received_at.patch(pointer, value),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArfFeedbackReport {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.arrival_date {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArrivalDate, value));
|
|
}
|
|
}
|
|
let value = &self.authentication_results;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthenticationResults));
|
|
}
|
|
}
|
|
if let Some(value) = &self.original_envelope_id {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OriginalEnvelopeId));
|
|
}
|
|
}
|
|
if let Some(value) = &self.original_mail_from {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OriginalMailFrom));
|
|
}
|
|
}
|
|
if let Some(value) = &self.original_rcpt_to {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OriginalRcptTo));
|
|
}
|
|
}
|
|
let value = &self.reported_domains;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReportedDomains));
|
|
}
|
|
}
|
|
let value = &self.reported_uris;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReportedUris));
|
|
}
|
|
}
|
|
if let Some(value) = &self.reporting_mta {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReportingMta));
|
|
}
|
|
}
|
|
if let Some(value) = &self.source_ip {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::SourceIp, value));
|
|
}
|
|
}
|
|
if let Some(value) = &self.source_port {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::SourcePort, 1));
|
|
}
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::SourcePort, 65535));
|
|
}
|
|
}
|
|
if let Some(value) = &self.user_agent {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::UserAgent));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_adsp_dns {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimAdspDns));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_canonicalized_body {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimCanonicalizedBody));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_canonicalized_header {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimCanonicalizedHeader));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_domain {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimDomain));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_identity {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimIdentity));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_selector {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimSelector));
|
|
}
|
|
}
|
|
if let Some(value) = &self.dkim_selector_dns {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DkimSelectorDns));
|
|
}
|
|
}
|
|
if let Some(value) = &self.spf_dns {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SpfDns));
|
|
}
|
|
}
|
|
if let Some(value) = &self.message {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Message));
|
|
}
|
|
}
|
|
if let Some(value) = &self.headers {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Headers));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ArfFeedbackReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.feedback_type.pickle(out);
|
|
self.arrival_date.pickle(out);
|
|
self.authentication_results.pickle(out);
|
|
self.incidents.pickle(out);
|
|
self.original_envelope_id.pickle(out);
|
|
self.original_mail_from.pickle(out);
|
|
self.original_rcpt_to.pickle(out);
|
|
self.reported_domains.pickle(out);
|
|
self.reported_uris.pickle(out);
|
|
self.reporting_mta.pickle(out);
|
|
self.source_ip.pickle(out);
|
|
self.source_port.pickle(out);
|
|
self.user_agent.pickle(out);
|
|
self.version.pickle(out);
|
|
self.auth_failure.pickle(out);
|
|
self.delivery_result.pickle(out);
|
|
self.dkim_adsp_dns.pickle(out);
|
|
self.dkim_canonicalized_body.pickle(out);
|
|
self.dkim_canonicalized_header.pickle(out);
|
|
self.dkim_domain.pickle(out);
|
|
self.dkim_identity.pickle(out);
|
|
self.dkim_selector.pickle(out);
|
|
self.dkim_selector_dns.pickle(out);
|
|
self.spf_dns.pickle(out);
|
|
self.identity_alignment.pickle(out);
|
|
self.message.pickle(out);
|
|
self.headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.feedback_type = Pickle::unpickle(stream)?;
|
|
this.arrival_date = Pickle::unpickle(stream)?;
|
|
this.authentication_results = Pickle::unpickle(stream)?;
|
|
this.incidents = Pickle::unpickle(stream)?;
|
|
this.original_envelope_id = Pickle::unpickle(stream)?;
|
|
this.original_mail_from = Pickle::unpickle(stream)?;
|
|
this.original_rcpt_to = Pickle::unpickle(stream)?;
|
|
this.reported_domains = Pickle::unpickle(stream)?;
|
|
this.reported_uris = Pickle::unpickle(stream)?;
|
|
this.reporting_mta = Pickle::unpickle(stream)?;
|
|
this.source_ip = Pickle::unpickle(stream)?;
|
|
this.source_port = Pickle::unpickle(stream)?;
|
|
this.user_agent = Pickle::unpickle(stream)?;
|
|
this.version = Pickle::unpickle(stream)?;
|
|
this.auth_failure = Pickle::unpickle(stream)?;
|
|
this.delivery_result = Pickle::unpickle(stream)?;
|
|
this.dkim_adsp_dns = Pickle::unpickle(stream)?;
|
|
this.dkim_canonicalized_body = Pickle::unpickle(stream)?;
|
|
this.dkim_canonicalized_header = Pickle::unpickle(stream)?;
|
|
this.dkim_domain = Pickle::unpickle(stream)?;
|
|
this.dkim_identity = Pickle::unpickle(stream)?;
|
|
this.dkim_selector = Pickle::unpickle(stream)?;
|
|
this.dkim_selector_dns = Pickle::unpickle(stream)?;
|
|
this.spf_dns = Pickle::unpickle(stream)?;
|
|
this.identity_alignment = Pickle::unpickle(stream)?;
|
|
this.message = Pickle::unpickle(stream)?;
|
|
this.headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ArfFeedbackReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
feedback_type: Default::default(),
|
|
arrival_date: Default::default(),
|
|
authentication_results: Default::default(),
|
|
incidents: 0u64,
|
|
original_envelope_id: Default::default(),
|
|
original_mail_from: Default::default(),
|
|
original_rcpt_to: Default::default(),
|
|
reported_domains: Default::default(),
|
|
reported_uris: Default::default(),
|
|
reporting_mta: Default::default(),
|
|
source_ip: Default::default(),
|
|
source_port: Default::default(),
|
|
user_agent: Default::default(),
|
|
version: 1u64,
|
|
auth_failure: Default::default(),
|
|
delivery_result: Default::default(),
|
|
dkim_adsp_dns: Default::default(),
|
|
dkim_canonicalized_body: Default::default(),
|
|
dkim_canonicalized_header: Default::default(),
|
|
dkim_domain: Default::default(),
|
|
dkim_identity: Default::default(),
|
|
dkim_selector: Default::default(),
|
|
dkim_selector_dns: Default::default(),
|
|
spf_dns: Default::default(),
|
|
identity_alignment: Default::default(),
|
|
message: Default::default(),
|
|
headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ArfFeedbackReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(29);
|
|
map.insert_unchecked(Property::FeedbackType, self.feedback_type.into_value());
|
|
map.insert_unchecked(Property::ArrivalDate, self.arrival_date.into_value());
|
|
map.insert_unchecked(
|
|
Property::AuthenticationResults,
|
|
self.authentication_results.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Incidents, self.incidents.into_value());
|
|
map.insert_unchecked(
|
|
Property::OriginalEnvelopeId,
|
|
self.original_envelope_id.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::OriginalMailFrom,
|
|
self.original_mail_from.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::OriginalRcptTo, self.original_rcpt_to.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReportedDomains,
|
|
self.reported_domains.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ReportedUris, self.reported_uris.into_value());
|
|
map.insert_unchecked(Property::ReportingMta, self.reporting_mta.into_value());
|
|
map.insert_unchecked(Property::SourceIp, self.source_ip.into_value());
|
|
map.insert_unchecked(Property::SourcePort, self.source_port.into_value());
|
|
map.insert_unchecked(Property::UserAgent, self.user_agent.into_value());
|
|
map.insert_unchecked(Property::Version, self.version.into_value());
|
|
map.insert_unchecked(Property::AuthFailure, self.auth_failure.into_value());
|
|
map.insert_unchecked(Property::DeliveryResult, self.delivery_result.into_value());
|
|
map.insert_unchecked(Property::DkimAdspDns, self.dkim_adsp_dns.into_value());
|
|
map.insert_unchecked(
|
|
Property::DkimCanonicalizedBody,
|
|
self.dkim_canonicalized_body.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DkimCanonicalizedHeader,
|
|
self.dkim_canonicalized_header.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DkimDomain, self.dkim_domain.into_value());
|
|
map.insert_unchecked(Property::DkimIdentity, self.dkim_identity.into_value());
|
|
map.insert_unchecked(Property::DkimSelector, self.dkim_selector.into_value());
|
|
map.insert_unchecked(
|
|
Property::DkimSelectorDns,
|
|
self.dkim_selector_dns.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SpfDns, self.spf_dns.into_value());
|
|
map.insert_unchecked(
|
|
Property::IdentityAlignment,
|
|
self.identity_alignment.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Message, self.message.into_value());
|
|
map.insert_unchecked(Property::Headers, self.headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ArfFeedbackReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::FeedbackType) => self.feedback_type.patch(pointer, value),
|
|
Some(Property::ArrivalDate) => self.arrival_date.patch(pointer, value),
|
|
Some(Property::AuthenticationResults) => {
|
|
self.authentication_results.patch(pointer, value)
|
|
}
|
|
Some(Property::Incidents) => self.incidents.patch(pointer, value),
|
|
Some(Property::OriginalEnvelopeId) => self.original_envelope_id.patch(pointer, value),
|
|
Some(Property::OriginalMailFrom) => self
|
|
.original_mail_from
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::OriginalRcptTo) => self
|
|
.original_rcpt_to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::ReportedDomains) => self
|
|
.reported_domains
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::ReportedUris) => self.reported_uris.patch(pointer, value),
|
|
Some(Property::ReportingMta) => self.reporting_mta.patch(pointer, value),
|
|
Some(Property::SourceIp) => self.source_ip.patch(pointer, value),
|
|
Some(Property::SourcePort) => self.source_port.patch(pointer, value),
|
|
Some(Property::UserAgent) => self.user_agent.patch(pointer, value),
|
|
Some(Property::Version) => self.version.patch(pointer, value),
|
|
Some(Property::AuthFailure) => self.auth_failure.patch(pointer, value),
|
|
Some(Property::DeliveryResult) => self.delivery_result.patch(pointer, value),
|
|
Some(Property::DkimAdspDns) => self.dkim_adsp_dns.patch(pointer, value),
|
|
Some(Property::DkimCanonicalizedBody) => {
|
|
self.dkim_canonicalized_body.patch(pointer, value)
|
|
}
|
|
Some(Property::DkimCanonicalizedHeader) => {
|
|
self.dkim_canonicalized_header.patch(pointer, value)
|
|
}
|
|
Some(Property::DkimDomain) => self.dkim_domain.patch(pointer, value),
|
|
Some(Property::DkimIdentity) => self.dkim_identity.patch(pointer, value),
|
|
Some(Property::DkimSelector) => self.dkim_selector.patch(pointer, value),
|
|
Some(Property::DkimSelectorDns) => self.dkim_selector_dns.patch(pointer, value),
|
|
Some(Property::SpfDns) => self.spf_dns.patch(pointer, value),
|
|
Some(Property::IdentityAlignment) => self.identity_alignment.patch(pointer, value),
|
|
Some(Property::Message) => self.message.patch(pointer, value),
|
|
Some(Property::Headers) => self.headers.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Asn {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Asn;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Asn::Disabled => true,
|
|
Asn::Resource(inner) => inner.validate(errors),
|
|
Asn::Dns(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for Asn {
|
|
fn default() -> Self {
|
|
Asn::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for Asn {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Asn::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
Asn::Resource(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Asn::Dns(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(Asn::Disabled),
|
|
1 => Pickle::unpickle(stream).map(Asn::Resource),
|
|
2 => Pickle::unpickle(stream).map(Asn::Dns),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Asn {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Asn::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Asn::Resource(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Resource".into()));
|
|
obj
|
|
}
|
|
Asn::Dns(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Dns".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Asn {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
AsnType::Disabled => *self = Asn::Disabled,
|
|
AsnType::Resource => *self = Asn::Resource(Default::default()),
|
|
AsnType::Dns => *self = Asn::Dns(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Asn::Disabled => pointer.assert_eof(),
|
|
Asn::Resource(inner) => inner.patch(pointer, value),
|
|
Asn::Dns(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Asn {
|
|
pub fn object_type(&self) -> AsnType {
|
|
match self {
|
|
Asn::Disabled => AsnType::Disabled,
|
|
Asn::Resource(_) => AsnType::Resource,
|
|
Asn::Dns(_) => AsnType::Dns,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AsnDns {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.separator;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Separator));
|
|
}
|
|
let value = &self.zone_ip_v4;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ZoneIpV4));
|
|
}
|
|
let value = &self.zone_ip_v6;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ZoneIpV6));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for AsnDns {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.index_asn.pickle(out);
|
|
self.index_asn_name.pickle(out);
|
|
self.index_country.pickle(out);
|
|
self.separator.pickle(out);
|
|
self.zone_ip_v4.pickle(out);
|
|
self.zone_ip_v6.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.index_asn = Pickle::unpickle(stream)?;
|
|
this.index_asn_name = Pickle::unpickle(stream)?;
|
|
this.index_country = Pickle::unpickle(stream)?;
|
|
this.separator = Pickle::unpickle(stream)?;
|
|
this.zone_ip_v4 = Pickle::unpickle(stream)?;
|
|
this.zone_ip_v6 = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AsnDns {
|
|
fn default() -> Self {
|
|
Self {
|
|
index_asn: 0u64,
|
|
index_asn_name: Default::default(),
|
|
index_country: Default::default(),
|
|
separator: "|".to_string(),
|
|
zone_ip_v4: Default::default(),
|
|
zone_ip_v6: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AsnDns {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::IndexAsn, self.index_asn.into_value());
|
|
map.insert_unchecked(Property::IndexAsnName, self.index_asn_name.into_value());
|
|
map.insert_unchecked(Property::IndexCountry, self.index_country.into_value());
|
|
map.insert_unchecked(Property::Separator, self.separator.into_value());
|
|
map.insert_unchecked(Property::ZoneIpV4, self.zone_ip_v4.into_value());
|
|
map.insert_unchecked(Property::ZoneIpV6, self.zone_ip_v6.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AsnDns {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::IndexAsn) => self.index_asn.patch(pointer, value),
|
|
Some(Property::IndexAsnName) => self.index_asn_name.patch(pointer, value),
|
|
Some(Property::IndexCountry) => self.index_country.patch(pointer, value),
|
|
Some(Property::Separator) => self
|
|
.separator
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ZoneIpV4) => self
|
|
.zone_ip_v4
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ZoneIpV6) => self
|
|
.zone_ip_v6
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AsnResource {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.asn_urls;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AsnUrls));
|
|
}
|
|
}
|
|
let value = &self.geo_urls;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::GeoUrls));
|
|
}
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for AsnResource {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.expires.pickle(out);
|
|
self.max_size.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.asn_urls.pickle(out);
|
|
self.geo_urls.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.expires = Pickle::unpickle(stream)?;
|
|
this.max_size = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.asn_urls = Pickle::unpickle(stream)?;
|
|
this.geo_urls = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AsnResource {
|
|
fn default() -> Self {
|
|
Self {
|
|
expires: Duration::from_millis(86400000),
|
|
max_size: 104857600,
|
|
timeout: Duration::from_millis(300000),
|
|
asn_urls: Default::default(),
|
|
geo_urls: Default::default(),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AsnResource {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Expires, self.expires.into_value());
|
|
map.insert_unchecked(Property::MaxSize, self.max_size.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::AsnUrls, self.asn_urls.into_value());
|
|
map.insert_unchecked(Property::GeoUrls, self.geo_urls.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AsnResource {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Expires) => self.expires.patch(pointer, value),
|
|
Some(Property::MaxSize) => self.max_size.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::AsnUrls) => self
|
|
.asn_urls
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::GeoUrls) => self
|
|
.geo_urls
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Authentication {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Authentication;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.directory_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DirectoryId));
|
|
}
|
|
}
|
|
let value = &self.default_user_role_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DefaultUserRoleIds));
|
|
}
|
|
}
|
|
let value = &self.default_group_role_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DefaultGroupRoleIds));
|
|
}
|
|
}
|
|
let value = &self.default_tenant_role_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DefaultTenantRoleIds));
|
|
}
|
|
}
|
|
let value = &self.default_admin_role_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DefaultAdminRoleIds));
|
|
}
|
|
}
|
|
let value = &self.password_min_length;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PasswordMinLength, 1));
|
|
}
|
|
if *value > 100 {
|
|
errors.push(ValidationError::max_value(Property::PasswordMinLength, 100));
|
|
}
|
|
let value = &self.password_max_length;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PasswordMaxLength, 1));
|
|
}
|
|
if *value > 1000 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PasswordMaxLength,
|
|
1000,
|
|
));
|
|
}
|
|
if let Some(value) = &self.max_app_passwords {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxAppPasswords, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_api_keys {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxApiKeys, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Directory, self.directory_id, None);
|
|
for id in self.default_user_role_ids.iter() {
|
|
i.foreign_key(ObjectType::Role, Some(*id), None);
|
|
}
|
|
for id in self.default_group_role_ids.iter() {
|
|
i.foreign_key(ObjectType::Role, Some(*id), None);
|
|
}
|
|
for id in self.default_tenant_role_ids.iter() {
|
|
i.foreign_key(ObjectType::Role, Some(*id), None);
|
|
}
|
|
for id in self.default_admin_role_ids.iter() {
|
|
i.foreign_key(ObjectType::Role, Some(*id), None);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for Authentication {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.directory_id.pickle(out);
|
|
self.default_user_role_ids.pickle(out);
|
|
self.default_group_role_ids.pickle(out);
|
|
self.default_tenant_role_ids.pickle(out);
|
|
self.default_admin_role_ids.pickle(out);
|
|
self.password_hash_algorithm.pickle(out);
|
|
self.password_min_length.pickle(out);
|
|
self.password_max_length.pickle(out);
|
|
self.password_min_strength.pickle(out);
|
|
self.password_default_expiry.pickle(out);
|
|
self.max_app_passwords.pickle(out);
|
|
self.max_api_keys.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.directory_id = Pickle::unpickle(stream)?;
|
|
this.default_user_role_ids = Pickle::unpickle(stream)?;
|
|
this.default_group_role_ids = Pickle::unpickle(stream)?;
|
|
this.default_tenant_role_ids = Pickle::unpickle(stream)?;
|
|
this.default_admin_role_ids = Pickle::unpickle(stream)?;
|
|
this.password_hash_algorithm = Pickle::unpickle(stream)?;
|
|
this.password_min_length = Pickle::unpickle(stream)?;
|
|
this.password_max_length = Pickle::unpickle(stream)?;
|
|
this.password_min_strength = Pickle::unpickle(stream)?;
|
|
this.password_default_expiry = Pickle::unpickle(stream)?;
|
|
this.max_app_passwords = Pickle::unpickle(stream)?;
|
|
this.max_api_keys = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Authentication {
|
|
fn default() -> Self {
|
|
Self {
|
|
directory_id: Default::default(),
|
|
default_user_role_ids: Default::default(),
|
|
default_group_role_ids: Default::default(),
|
|
default_tenant_role_ids: Default::default(),
|
|
default_admin_role_ids: Default::default(),
|
|
password_hash_algorithm: PasswordHashAlgorithm::Argon2id,
|
|
password_min_length: 8u64,
|
|
password_max_length: 128u64,
|
|
password_min_strength: PasswordStrength::Three,
|
|
password_default_expiry: Default::default(),
|
|
max_app_passwords: Some(5u64),
|
|
max_api_keys: Some(5u64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Authentication {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::DirectoryId, self.directory_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::DefaultUserRoleIds,
|
|
self.default_user_role_ids.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultGroupRoleIds,
|
|
self.default_group_role_ids.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultTenantRoleIds,
|
|
self.default_tenant_role_ids.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultAdminRoleIds,
|
|
self.default_admin_role_ids.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PasswordHashAlgorithm,
|
|
self.password_hash_algorithm.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PasswordMinLength,
|
|
self.password_min_length.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PasswordMaxLength,
|
|
self.password_max_length.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PasswordMinStrength,
|
|
self.password_min_strength.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PasswordDefaultExpiry,
|
|
self.password_default_expiry.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxAppPasswords,
|
|
self.max_app_passwords.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxApiKeys, self.max_api_keys.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Authentication {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DirectoryId) => self.directory_id.patch(pointer, value),
|
|
Some(Property::DefaultUserRoleIds) => self.default_user_role_ids.patch(pointer, value),
|
|
Some(Property::DefaultGroupRoleIds) => {
|
|
self.default_group_role_ids.patch(pointer, value)
|
|
}
|
|
Some(Property::DefaultTenantRoleIds) => {
|
|
self.default_tenant_role_ids.patch(pointer, value)
|
|
}
|
|
Some(Property::DefaultAdminRoleIds) => {
|
|
self.default_admin_role_ids.patch(pointer, value)
|
|
}
|
|
Some(Property::PasswordHashAlgorithm) => {
|
|
self.password_hash_algorithm.patch(pointer, value)
|
|
}
|
|
Some(Property::PasswordMinLength) => self.password_min_length.patch(pointer, value),
|
|
Some(Property::PasswordMaxLength) => self.password_max_length.patch(pointer, value),
|
|
Some(Property::PasswordMinStrength) => self.password_min_strength.patch(pointer, value),
|
|
Some(Property::PasswordDefaultExpiry) => {
|
|
self.password_default_expiry.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxAppPasswords) => self.max_app_passwords.patch(pointer, value),
|
|
Some(Property::MaxApiKeys) => self.max_api_keys.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AzureStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.storage_account;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::StorageAccount));
|
|
}
|
|
let value = &self.container;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Container));
|
|
}
|
|
let value = &self.access_key;
|
|
value.validate(errors);
|
|
let value = &self.sas_token;
|
|
value.validate(errors);
|
|
let value = &self.max_retries;
|
|
if *value > 10 {
|
|
errors.push(ValidationError::max_value(Property::MaxRetries, 10));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxRetries, 1));
|
|
}
|
|
if let Some(value) = &self.key_prefix {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::KeyPrefix));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for AzureStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.storage_account.pickle(out);
|
|
self.container.pickle(out);
|
|
self.access_key.pickle(out);
|
|
self.sas_token.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.max_retries.pickle(out);
|
|
self.key_prefix.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.storage_account = Pickle::unpickle(stream)?;
|
|
this.container = Pickle::unpickle(stream)?;
|
|
this.access_key = Pickle::unpickle(stream)?;
|
|
this.sas_token = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.max_retries = Pickle::unpickle(stream)?;
|
|
this.key_prefix = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for AzureStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
storage_account: Default::default(),
|
|
container: Default::default(),
|
|
access_key: Default::default(),
|
|
sas_token: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
max_retries: 3u64,
|
|
key_prefix: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for AzureStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::StorageAccount, self.storage_account.into_value());
|
|
map.insert_unchecked(Property::Container, self.container.into_value());
|
|
map.insert_unchecked(Property::AccessKey, self.access_key.into_value());
|
|
map.insert_unchecked(Property::SasToken, self.sas_token.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value());
|
|
map.insert_unchecked(Property::KeyPrefix, self.key_prefix.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for AzureStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::StorageAccount) => self
|
|
.storage_account
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Container) => self
|
|
.container
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AccessKey) => self.access_key.patch(pointer, value),
|
|
Some(Property::SasToken) => self.sas_token.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::MaxRetries) => self.max_retries.patch(pointer, value),
|
|
Some(Property::KeyPrefix) => self
|
|
.key_prefix
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for BlobStore {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::BlobStore;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
BlobStore::Default => true,
|
|
BlobStore::Sharded(inner) => inner.validate(errors),
|
|
BlobStore::S3(inner) => inner.validate(errors),
|
|
BlobStore::Azure(inner) => inner.validate(errors),
|
|
BlobStore::FileSystem(inner) => inner.validate(errors),
|
|
BlobStore::FoundationDb(inner) => inner.validate(errors),
|
|
BlobStore::PostgreSql(inner) => inner.validate(errors),
|
|
BlobStore::MySql(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for BlobStore {
|
|
fn default() -> Self {
|
|
BlobStore::Default
|
|
}
|
|
}
|
|
|
|
impl Pickle for BlobStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
BlobStore::Default => {
|
|
0u16.pickle(out);
|
|
}
|
|
BlobStore::Sharded(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStore::S3(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStore::Azure(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStore::FileSystem(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStore::FoundationDb(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStore::PostgreSql(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStore::MySql(inner) => {
|
|
7u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(BlobStore::Default),
|
|
1 => Pickle::unpickle(stream).map(BlobStore::Sharded),
|
|
2 => Pickle::unpickle(stream).map(BlobStore::S3),
|
|
3 => Pickle::unpickle(stream).map(BlobStore::Azure),
|
|
4 => Pickle::unpickle(stream).map(BlobStore::FileSystem),
|
|
5 => Pickle::unpickle(stream).map(BlobStore::FoundationDb),
|
|
6 => Pickle::unpickle(stream).map(BlobStore::PostgreSql),
|
|
7 => Pickle::unpickle(stream).map(BlobStore::MySql),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for BlobStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
BlobStore::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
BlobStore::Sharded(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sharded".into()));
|
|
obj
|
|
}
|
|
BlobStore::S3(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("S3".into()));
|
|
obj
|
|
}
|
|
BlobStore::Azure(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Azure".into()));
|
|
obj
|
|
}
|
|
BlobStore::FileSystem(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FileSystem".into()));
|
|
obj
|
|
}
|
|
BlobStore::FoundationDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into()));
|
|
obj
|
|
}
|
|
BlobStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
BlobStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for BlobStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
BlobStoreType::Default => *self = BlobStore::Default,
|
|
BlobStoreType::Sharded => *self = BlobStore::Sharded(Default::default()),
|
|
BlobStoreType::S3 => *self = BlobStore::S3(Default::default()),
|
|
BlobStoreType::Azure => *self = BlobStore::Azure(Default::default()),
|
|
BlobStoreType::FileSystem => *self = BlobStore::FileSystem(Default::default()),
|
|
BlobStoreType::FoundationDb => *self = BlobStore::FoundationDb(Default::default()),
|
|
BlobStoreType::PostgreSql => *self = BlobStore::PostgreSql(Default::default()),
|
|
BlobStoreType::MySql => *self = BlobStore::MySql(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
BlobStore::Default => pointer.assert_eof(),
|
|
BlobStore::Sharded(inner) => inner.patch(pointer, value),
|
|
BlobStore::S3(inner) => inner.patch(pointer, value),
|
|
BlobStore::Azure(inner) => inner.patch(pointer, value),
|
|
BlobStore::FileSystem(inner) => inner.patch(pointer, value),
|
|
BlobStore::FoundationDb(inner) => inner.patch(pointer, value),
|
|
BlobStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
BlobStore::MySql(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BlobStore {
|
|
pub fn object_type(&self) -> BlobStoreType {
|
|
match self {
|
|
BlobStore::Default => BlobStoreType::Default,
|
|
BlobStore::Sharded(_) => BlobStoreType::Sharded,
|
|
BlobStore::S3(_) => BlobStoreType::S3,
|
|
BlobStore::Azure(_) => BlobStoreType::Azure,
|
|
BlobStore::FileSystem(_) => BlobStoreType::FileSystem,
|
|
BlobStore::FoundationDb(_) => BlobStoreType::FoundationDb,
|
|
BlobStore::PostgreSql(_) => BlobStoreType::PostgreSql,
|
|
BlobStore::MySql(_) => BlobStoreType::MySql,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BlobStoreBase {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
BlobStoreBase::S3(inner) => inner.validate(errors),
|
|
BlobStoreBase::Azure(inner) => inner.validate(errors),
|
|
BlobStoreBase::FileSystem(inner) => inner.validate(errors),
|
|
BlobStoreBase::FoundationDb(inner) => inner.validate(errors),
|
|
BlobStoreBase::PostgreSql(inner) => inner.validate(errors),
|
|
BlobStoreBase::MySql(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for BlobStoreBase {
|
|
fn default() -> Self {
|
|
BlobStoreBase::S3(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for BlobStoreBase {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
BlobStoreBase::S3(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStoreBase::Azure(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStoreBase::FileSystem(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStoreBase::FoundationDb(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStoreBase::PostgreSql(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
BlobStoreBase::MySql(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(BlobStoreBase::S3),
|
|
1 => Pickle::unpickle(stream).map(BlobStoreBase::Azure),
|
|
2 => Pickle::unpickle(stream).map(BlobStoreBase::FileSystem),
|
|
3 => Pickle::unpickle(stream).map(BlobStoreBase::FoundationDb),
|
|
4 => Pickle::unpickle(stream).map(BlobStoreBase::PostgreSql),
|
|
5 => Pickle::unpickle(stream).map(BlobStoreBase::MySql),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for BlobStoreBase {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
BlobStoreBase::S3(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("S3".into()));
|
|
obj
|
|
}
|
|
BlobStoreBase::Azure(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Azure".into()));
|
|
obj
|
|
}
|
|
BlobStoreBase::FileSystem(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FileSystem".into()));
|
|
obj
|
|
}
|
|
BlobStoreBase::FoundationDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into()));
|
|
obj
|
|
}
|
|
BlobStoreBase::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
BlobStoreBase::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for BlobStoreBase {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
BlobStoreBaseType::S3 => *self = BlobStoreBase::S3(Default::default()),
|
|
BlobStoreBaseType::Azure => *self = BlobStoreBase::Azure(Default::default()),
|
|
BlobStoreBaseType::FileSystem => {
|
|
*self = BlobStoreBase::FileSystem(Default::default())
|
|
}
|
|
BlobStoreBaseType::FoundationDb => {
|
|
*self = BlobStoreBase::FoundationDb(Default::default())
|
|
}
|
|
BlobStoreBaseType::PostgreSql => {
|
|
*self = BlobStoreBase::PostgreSql(Default::default())
|
|
}
|
|
BlobStoreBaseType::MySql => *self = BlobStoreBase::MySql(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
BlobStoreBase::S3(inner) => inner.patch(pointer, value),
|
|
BlobStoreBase::Azure(inner) => inner.patch(pointer, value),
|
|
BlobStoreBase::FileSystem(inner) => inner.patch(pointer, value),
|
|
BlobStoreBase::FoundationDb(inner) => inner.patch(pointer, value),
|
|
BlobStoreBase::PostgreSql(inner) => inner.patch(pointer, value),
|
|
BlobStoreBase::MySql(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BlobStoreBase {
|
|
pub fn object_type(&self) -> BlobStoreBaseType {
|
|
match self {
|
|
BlobStoreBase::S3(_) => BlobStoreBaseType::S3,
|
|
BlobStoreBase::Azure(_) => BlobStoreBaseType::Azure,
|
|
BlobStoreBase::FileSystem(_) => BlobStoreBaseType::FileSystem,
|
|
BlobStoreBase::FoundationDb(_) => BlobStoreBaseType::FoundationDb,
|
|
BlobStoreBase::PostgreSql(_) => BlobStoreBaseType::PostgreSql,
|
|
BlobStoreBase::MySql(_) => BlobStoreBaseType::MySql,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for BlockedIp {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::BlockedIp;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.address;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Address, value));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Address, &self.address);
|
|
}
|
|
}
|
|
|
|
impl Pickle for BlockedIp {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.address.pickle(out);
|
|
self.reason.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.address = Pickle::unpickle(stream)?;
|
|
this.reason = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for BlockedIp {
|
|
fn default() -> Self {
|
|
Self {
|
|
address: Default::default(),
|
|
reason: BlockReason::Manual,
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for BlockedIp {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Address, self.address.into_value());
|
|
map.insert_unchecked(Property::Reason, self.reason.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for BlockedIp {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Address) => self.address.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Reason) => self.reason.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Bootstrap {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Bootstrap;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.server_hostname;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ServerHostname));
|
|
}
|
|
let value = &self.default_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultDomain));
|
|
}
|
|
let value = &self.data_store;
|
|
value.validate(errors);
|
|
let value = &self.blob_store;
|
|
value.validate(errors);
|
|
let value = &self.search_store;
|
|
value.validate(errors);
|
|
let value = &self.in_memory_store;
|
|
value.validate(errors);
|
|
let value = &self.directory;
|
|
value.validate(errors);
|
|
let value = &self.tracer;
|
|
value.validate(errors);
|
|
let value = &self.dns_server;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Bootstrap {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.server_hostname.pickle(out);
|
|
self.default_domain.pickle(out);
|
|
self.request_tls_certificate.pickle(out);
|
|
self.generate_dkim_keys.pickle(out);
|
|
self.data_store.pickle(out);
|
|
self.blob_store.pickle(out);
|
|
self.search_store.pickle(out);
|
|
self.in_memory_store.pickle(out);
|
|
self.directory.pickle(out);
|
|
self.tracer.pickle(out);
|
|
self.dns_server.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.server_hostname = Pickle::unpickle(stream)?;
|
|
this.default_domain = Pickle::unpickle(stream)?;
|
|
this.request_tls_certificate = Pickle::unpickle(stream)?;
|
|
this.generate_dkim_keys = Pickle::unpickle(stream)?;
|
|
this.data_store = Pickle::unpickle(stream)?;
|
|
this.blob_store = Pickle::unpickle(stream)?;
|
|
this.search_store = Pickle::unpickle(stream)?;
|
|
this.in_memory_store = Pickle::unpickle(stream)?;
|
|
this.directory = Pickle::unpickle(stream)?;
|
|
this.tracer = Pickle::unpickle(stream)?;
|
|
this.dns_server = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Bootstrap {
|
|
fn default() -> Self {
|
|
Self {
|
|
server_hostname: Default::default(),
|
|
default_domain: Default::default(),
|
|
request_tls_certificate: true,
|
|
generate_dkim_keys: true,
|
|
data_store: DataStore::RocksDb(RocksDbStore {
|
|
path: "/var/lib/stalwart/".to_string(),
|
|
..Default::default()
|
|
}),
|
|
blob_store: BlobStore::Default,
|
|
search_store: SearchStore::Default,
|
|
in_memory_store: InMemoryStore::Default,
|
|
directory: DirectoryBootstrap::Internal,
|
|
tracer: Tracer::Log(TracerLog {
|
|
path: "/var/log/stalwart/".to_string(),
|
|
..Default::default()
|
|
}),
|
|
dns_server: DnsServerBootstrap::Manual,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Bootstrap {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::ServerHostname, self.server_hostname.into_value());
|
|
map.insert_unchecked(Property::DefaultDomain, self.default_domain.into_value());
|
|
map.insert_unchecked(
|
|
Property::RequestTlsCertificate,
|
|
self.request_tls_certificate.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::GenerateDkimKeys,
|
|
self.generate_dkim_keys.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DataStore, self.data_store.into_value());
|
|
map.insert_unchecked(Property::BlobStore, self.blob_store.into_value());
|
|
map.insert_unchecked(Property::SearchStore, self.search_store.into_value());
|
|
map.insert_unchecked(Property::InMemoryStore, self.in_memory_store.into_value());
|
|
map.insert_unchecked(Property::Directory, self.directory.into_value());
|
|
map.insert_unchecked(Property::Tracer, self.tracer.into_value());
|
|
map.insert_unchecked(Property::DnsServer, self.dns_server.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Bootstrap {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ServerHostname) => self
|
|
.server_hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Hostname]), value),
|
|
Some(Property::DefaultDomain) => self.default_domain.patch(pointer, value),
|
|
Some(Property::RequestTlsCertificate) => {
|
|
self.request_tls_certificate.patch(pointer, value)
|
|
}
|
|
Some(Property::GenerateDkimKeys) => self.generate_dkim_keys.patch(pointer, value),
|
|
Some(Property::DataStore) => self.data_store.patch(pointer, value),
|
|
Some(Property::BlobStore) => self.blob_store.patch(pointer, value),
|
|
Some(Property::SearchStore) => self.search_store.patch(pointer, value),
|
|
Some(Property::InMemoryStore) => self.in_memory_store.patch(pointer, value),
|
|
Some(Property::Directory) => self.directory.patch(pointer, value),
|
|
Some(Property::Tracer) => self.tracer.patch(pointer, value),
|
|
Some(Property::DnsServer) => self.dns_server.patch(pointer, value),
|
|
Some(Property::Username) => pointer.assert_server_set(),
|
|
Some(Property::Secret) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Cache {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Cache;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.access_tokens;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::AccessTokens, 2048));
|
|
}
|
|
let value = &self.contacts;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Contacts, 2048));
|
|
}
|
|
let value = &self.dns_ipv4;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsIpv4, 2048));
|
|
}
|
|
let value = &self.dns_ipv6;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsIpv6, 2048));
|
|
}
|
|
let value = &self.dns_mta_sts;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsMtaSts, 2048));
|
|
}
|
|
let value = &self.dns_mx;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsMx, 2048));
|
|
}
|
|
let value = &self.dns_ptr;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsPtr, 2048));
|
|
}
|
|
let value = &self.dns_rbl;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsRbl, 2048));
|
|
}
|
|
let value = &self.dns_tlsa;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsTlsa, 2048));
|
|
}
|
|
let value = &self.dns_txt;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DnsTxt, 2048));
|
|
}
|
|
let value = &self.events;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Events, 2048));
|
|
}
|
|
let value = &self.scheduling;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Scheduling, 2048));
|
|
}
|
|
let value = &self.files;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Files, 2048));
|
|
}
|
|
let value = &self.http_auth;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::HttpAuth, 2048));
|
|
}
|
|
let value = &self.messages;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Messages, 2048));
|
|
}
|
|
let value = &self.domains;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Domains, 2048));
|
|
}
|
|
let value = &self.domain_names;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DomainNames, 2048));
|
|
}
|
|
let value = &self.domain_names_negative;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::DomainNamesNegative,
|
|
2048,
|
|
));
|
|
}
|
|
let value = &self.email_addresses;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::EmailAddresses, 2048));
|
|
}
|
|
let value = &self.email_addresses_negative;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::EmailAddressesNegative,
|
|
2048,
|
|
));
|
|
}
|
|
let value = &self.accounts;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Accounts, 2048));
|
|
}
|
|
let value = &self.roles;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Roles, 2048));
|
|
}
|
|
let value = &self.tenants;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::Tenants, 2048));
|
|
}
|
|
let value = &self.mailing_lists;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::MailingLists, 2048));
|
|
}
|
|
let value = &self.dkim_signatures;
|
|
if *value < 2048 {
|
|
errors.push(ValidationError::min_value(Property::DkimSignatures, 2048));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Cache {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.access_tokens.pickle(out);
|
|
self.contacts.pickle(out);
|
|
self.dns_ipv4.pickle(out);
|
|
self.dns_ipv6.pickle(out);
|
|
self.dns_mta_sts.pickle(out);
|
|
self.dns_mx.pickle(out);
|
|
self.dns_ptr.pickle(out);
|
|
self.dns_rbl.pickle(out);
|
|
self.dns_tlsa.pickle(out);
|
|
self.dns_txt.pickle(out);
|
|
self.events.pickle(out);
|
|
self.scheduling.pickle(out);
|
|
self.files.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.messages.pickle(out);
|
|
self.domains.pickle(out);
|
|
self.domain_names.pickle(out);
|
|
self.domain_names_negative.pickle(out);
|
|
self.email_addresses.pickle(out);
|
|
self.email_addresses_negative.pickle(out);
|
|
self.accounts.pickle(out);
|
|
self.roles.pickle(out);
|
|
self.tenants.pickle(out);
|
|
self.mailing_lists.pickle(out);
|
|
self.dkim_signatures.pickle(out);
|
|
self.negative_ttl.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.access_tokens = Pickle::unpickle(stream)?;
|
|
this.contacts = Pickle::unpickle(stream)?;
|
|
this.dns_ipv4 = Pickle::unpickle(stream)?;
|
|
this.dns_ipv6 = Pickle::unpickle(stream)?;
|
|
this.dns_mta_sts = Pickle::unpickle(stream)?;
|
|
this.dns_mx = Pickle::unpickle(stream)?;
|
|
this.dns_ptr = Pickle::unpickle(stream)?;
|
|
this.dns_rbl = Pickle::unpickle(stream)?;
|
|
this.dns_tlsa = Pickle::unpickle(stream)?;
|
|
this.dns_txt = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.scheduling = Pickle::unpickle(stream)?;
|
|
this.files = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.messages = Pickle::unpickle(stream)?;
|
|
this.domains = Pickle::unpickle(stream)?;
|
|
this.domain_names = Pickle::unpickle(stream)?;
|
|
this.domain_names_negative = Pickle::unpickle(stream)?;
|
|
this.email_addresses = Pickle::unpickle(stream)?;
|
|
this.email_addresses_negative = Pickle::unpickle(stream)?;
|
|
this.accounts = Pickle::unpickle(stream)?;
|
|
this.roles = Pickle::unpickle(stream)?;
|
|
this.tenants = Pickle::unpickle(stream)?;
|
|
this.mailing_lists = Pickle::unpickle(stream)?;
|
|
this.dkim_signatures = Pickle::unpickle(stream)?;
|
|
this.negative_ttl = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Cache {
|
|
fn default() -> Self {
|
|
Self {
|
|
access_tokens: 10485760,
|
|
contacts: 10485760,
|
|
dns_ipv4: 5242880,
|
|
dns_ipv6: 5242880,
|
|
dns_mta_sts: 1048576,
|
|
dns_mx: 5242880,
|
|
dns_ptr: 1048576,
|
|
dns_rbl: 5242880,
|
|
dns_tlsa: 1048576,
|
|
dns_txt: 5242880,
|
|
events: 10485760,
|
|
scheduling: 1048576,
|
|
files: 10485760,
|
|
http_auth: 1048576,
|
|
messages: 52428800,
|
|
domains: 5242880,
|
|
domain_names: 10485760,
|
|
domain_names_negative: 1048576,
|
|
email_addresses: 10485760,
|
|
email_addresses_negative: 2097152,
|
|
accounts: 20971520,
|
|
roles: 5242880,
|
|
tenants: 5242880,
|
|
mailing_lists: 2097152,
|
|
dkim_signatures: 10485760,
|
|
negative_ttl: Duration::from_millis(3600000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Cache {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(28);
|
|
map.insert_unchecked(Property::AccessTokens, self.access_tokens.into_value());
|
|
map.insert_unchecked(Property::Contacts, self.contacts.into_value());
|
|
map.insert_unchecked(Property::DnsIpv4, self.dns_ipv4.into_value());
|
|
map.insert_unchecked(Property::DnsIpv6, self.dns_ipv6.into_value());
|
|
map.insert_unchecked(Property::DnsMtaSts, self.dns_mta_sts.into_value());
|
|
map.insert_unchecked(Property::DnsMx, self.dns_mx.into_value());
|
|
map.insert_unchecked(Property::DnsPtr, self.dns_ptr.into_value());
|
|
map.insert_unchecked(Property::DnsRbl, self.dns_rbl.into_value());
|
|
map.insert_unchecked(Property::DnsTlsa, self.dns_tlsa.into_value());
|
|
map.insert_unchecked(Property::DnsTxt, self.dns_txt.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::Scheduling, self.scheduling.into_value());
|
|
map.insert_unchecked(Property::Files, self.files.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::Messages, self.messages.into_value());
|
|
map.insert_unchecked(Property::Domains, self.domains.into_value());
|
|
map.insert_unchecked(Property::DomainNames, self.domain_names.into_value());
|
|
map.insert_unchecked(
|
|
Property::DomainNamesNegative,
|
|
self.domain_names_negative.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::EmailAddresses, self.email_addresses.into_value());
|
|
map.insert_unchecked(
|
|
Property::EmailAddressesNegative,
|
|
self.email_addresses_negative.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Accounts, self.accounts.into_value());
|
|
map.insert_unchecked(Property::Roles, self.roles.into_value());
|
|
map.insert_unchecked(Property::Tenants, self.tenants.into_value());
|
|
map.insert_unchecked(Property::MailingLists, self.mailing_lists.into_value());
|
|
map.insert_unchecked(Property::DkimSignatures, self.dkim_signatures.into_value());
|
|
map.insert_unchecked(Property::NegativeTtl, self.negative_ttl.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Cache {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AccessTokens) => self.access_tokens.patch(pointer, value),
|
|
Some(Property::Contacts) => self.contacts.patch(pointer, value),
|
|
Some(Property::DnsIpv4) => self.dns_ipv4.patch(pointer, value),
|
|
Some(Property::DnsIpv6) => self.dns_ipv6.patch(pointer, value),
|
|
Some(Property::DnsMtaSts) => self.dns_mta_sts.patch(pointer, value),
|
|
Some(Property::DnsMx) => self.dns_mx.patch(pointer, value),
|
|
Some(Property::DnsPtr) => self.dns_ptr.patch(pointer, value),
|
|
Some(Property::DnsRbl) => self.dns_rbl.patch(pointer, value),
|
|
Some(Property::DnsTlsa) => self.dns_tlsa.patch(pointer, value),
|
|
Some(Property::DnsTxt) => self.dns_txt.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::Scheduling) => self.scheduling.patch(pointer, value),
|
|
Some(Property::Files) => self.files.patch(pointer, value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::Messages) => self.messages.patch(pointer, value),
|
|
Some(Property::Domains) => self.domains.patch(pointer, value),
|
|
Some(Property::DomainNames) => self.domain_names.patch(pointer, value),
|
|
Some(Property::DomainNamesNegative) => self.domain_names_negative.patch(pointer, value),
|
|
Some(Property::EmailAddresses) => self.email_addresses.patch(pointer, value),
|
|
Some(Property::EmailAddressesNegative) => {
|
|
self.email_addresses_negative.patch(pointer, value)
|
|
}
|
|
Some(Property::Accounts) => self.accounts.patch(pointer, value),
|
|
Some(Property::Roles) => self.roles.patch(pointer, value),
|
|
Some(Property::Tenants) => self.tenants.patch(pointer, value),
|
|
Some(Property::MailingLists) => self.mailing_lists.patch(pointer, value),
|
|
Some(Property::DkimSignatures) => self.dkim_signatures.patch(pointer, value),
|
|
Some(Property::NegativeTtl) => self.negative_ttl.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Calendar {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Calendar;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.default_display_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultDisplayName));
|
|
}
|
|
}
|
|
if let Some(value) = &self.default_href_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultHrefName));
|
|
}
|
|
}
|
|
let value = &self.max_attendees;
|
|
if *value > 100000 {
|
|
errors.push(ValidationError::max_value(Property::MaxAttendees, 100000));
|
|
}
|
|
if let Some(value) = &self.max_calendars {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxCalendars, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_events {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxEvents, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_participant_identities {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::MaxParticipantIdentities,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_event_notifications {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::MaxEventNotifications,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Calendar {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.default_display_name.pickle(out);
|
|
self.default_href_name.pickle(out);
|
|
self.max_attendees.pickle(out);
|
|
self.max_recurrence_expansions.pickle(out);
|
|
self.max_i_calendar_size.pickle(out);
|
|
self.max_calendars.pickle(out);
|
|
self.max_events.pickle(out);
|
|
self.max_participant_identities.pickle(out);
|
|
self.max_event_notifications.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.default_display_name = Pickle::unpickle(stream)?;
|
|
this.default_href_name = Pickle::unpickle(stream)?;
|
|
this.max_attendees = Pickle::unpickle(stream)?;
|
|
this.max_recurrence_expansions = Pickle::unpickle(stream)?;
|
|
this.max_i_calendar_size = Pickle::unpickle(stream)?;
|
|
this.max_calendars = Pickle::unpickle(stream)?;
|
|
this.max_events = Pickle::unpickle(stream)?;
|
|
this.max_participant_identities = Pickle::unpickle(stream)?;
|
|
this.max_event_notifications = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Calendar {
|
|
fn default() -> Self {
|
|
Self {
|
|
default_display_name: Some("Stalwart Calendar".to_string()),
|
|
default_href_name: Some("default".to_string()),
|
|
max_attendees: 20u64,
|
|
max_recurrence_expansions: 3000u64,
|
|
max_i_calendar_size: 524288,
|
|
max_calendars: Some(250u64),
|
|
max_events: Default::default(),
|
|
max_participant_identities: Some(100u64),
|
|
max_event_notifications: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Calendar {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(
|
|
Property::DefaultDisplayName,
|
|
self.default_display_name.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultHrefName,
|
|
self.default_href_name.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxAttendees, self.max_attendees.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxRecurrenceExpansions,
|
|
self.max_recurrence_expansions.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxICalendarSize,
|
|
self.max_i_calendar_size.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxCalendars, self.max_calendars.into_value());
|
|
map.insert_unchecked(Property::MaxEvents, self.max_events.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxParticipantIdentities,
|
|
self.max_participant_identities.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxEventNotifications,
|
|
self.max_event_notifications.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Calendar {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DefaultDisplayName) => self
|
|
.default_display_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::DefaultHrefName) => self
|
|
.default_href_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MaxAttendees) => self.max_attendees.patch(pointer, value),
|
|
Some(Property::MaxRecurrenceExpansions) => {
|
|
self.max_recurrence_expansions.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxICalendarSize) => self.max_i_calendar_size.patch(pointer, value),
|
|
Some(Property::MaxCalendars) => self.max_calendars.patch(pointer, value),
|
|
Some(Property::MaxEvents) => self.max_events.patch(pointer, value),
|
|
Some(Property::MaxParticipantIdentities) => {
|
|
self.max_participant_identities.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxEventNotifications) => {
|
|
self.max_event_notifications.patch(pointer, value)
|
|
}
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for CalendarAlarm {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::CalendarAlarm;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.from_email {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FromEmail));
|
|
}
|
|
}
|
|
let value = &self.from_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FromName));
|
|
}
|
|
if let Some(value) = &self.template {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Template));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for CalendarAlarm {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.allow_external_rcpts.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.from_email.pickle(out);
|
|
self.from_name.pickle(out);
|
|
self.min_trigger_interval.pickle(out);
|
|
self.template.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.allow_external_rcpts = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.from_email = Pickle::unpickle(stream)?;
|
|
this.from_name = Pickle::unpickle(stream)?;
|
|
this.min_trigger_interval = Pickle::unpickle(stream)?;
|
|
this.template = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CalendarAlarm {
|
|
fn default() -> Self {
|
|
Self {
|
|
allow_external_rcpts: false,
|
|
enable: true,
|
|
from_email: Default::default(),
|
|
from_name: "Stalwart Calendar".to_string(),
|
|
min_trigger_interval: Duration::from_millis(3600000),
|
|
template: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CalendarAlarm {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(
|
|
Property::AllowExternalRcpts,
|
|
self.allow_external_rcpts.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::FromEmail, self.from_email.into_value());
|
|
map.insert_unchecked(Property::FromName, self.from_name.into_value());
|
|
map.insert_unchecked(
|
|
Property::MinTriggerInterval,
|
|
self.min_trigger_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Template, self.template.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CalendarAlarm {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AllowExternalRcpts) => self.allow_external_rcpts.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::FromEmail) => self
|
|
.from_email
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::FromName) => self
|
|
.from_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MinTriggerInterval) => self.min_trigger_interval.patch(pointer, value),
|
|
Some(Property::Template) => self.template.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for CalendarScheduling {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::CalendarScheduling;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.http_rsvp_url {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpRsvpUrl));
|
|
}
|
|
}
|
|
let value = &self.itip_max_size;
|
|
if *value < 100 {
|
|
errors.push(ValidationError::min_value(Property::ItipMaxSize, 100));
|
|
}
|
|
let value = &self.max_recipients;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxRecipients, 1));
|
|
}
|
|
if let Some(value) = &self.email_template {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EmailTemplate));
|
|
}
|
|
}
|
|
if let Some(value) = &self.http_rsvp_template {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpRsvpTemplate));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for CalendarScheduling {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enable.pickle(out);
|
|
self.http_rsvp_enable.pickle(out);
|
|
self.http_rsvp_link_expiry.pickle(out);
|
|
self.http_rsvp_url.pickle(out);
|
|
self.auto_add_invitations.pickle(out);
|
|
self.itip_max_size.pickle(out);
|
|
self.max_recipients.pickle(out);
|
|
self.email_template.pickle(out);
|
|
self.http_rsvp_template.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.http_rsvp_enable = Pickle::unpickle(stream)?;
|
|
this.http_rsvp_link_expiry = Pickle::unpickle(stream)?;
|
|
this.http_rsvp_url = Pickle::unpickle(stream)?;
|
|
this.auto_add_invitations = Pickle::unpickle(stream)?;
|
|
this.itip_max_size = Pickle::unpickle(stream)?;
|
|
this.max_recipients = Pickle::unpickle(stream)?;
|
|
this.email_template = Pickle::unpickle(stream)?;
|
|
this.http_rsvp_template = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CalendarScheduling {
|
|
fn default() -> Self {
|
|
Self {
|
|
enable: true,
|
|
http_rsvp_enable: true,
|
|
http_rsvp_link_expiry: Duration::from_millis(7776000000),
|
|
http_rsvp_url: Default::default(),
|
|
auto_add_invitations: false,
|
|
itip_max_size: 524288,
|
|
max_recipients: 100u64,
|
|
email_template: Default::default(),
|
|
http_rsvp_template: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CalendarScheduling {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::HttpRsvpEnable, self.http_rsvp_enable.into_value());
|
|
map.insert_unchecked(
|
|
Property::HttpRsvpLinkExpiry,
|
|
self.http_rsvp_link_expiry.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::HttpRsvpUrl, self.http_rsvp_url.into_value());
|
|
map.insert_unchecked(
|
|
Property::AutoAddInvitations,
|
|
self.auto_add_invitations.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ItipMaxSize, self.itip_max_size.into_value());
|
|
map.insert_unchecked(Property::MaxRecipients, self.max_recipients.into_value());
|
|
map.insert_unchecked(Property::EmailTemplate, self.email_template.into_value());
|
|
map.insert_unchecked(
|
|
Property::HttpRsvpTemplate,
|
|
self.http_rsvp_template.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CalendarScheduling {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::HttpRsvpEnable) => self.http_rsvp_enable.patch(pointer, value),
|
|
Some(Property::HttpRsvpLinkExpiry) => self.http_rsvp_link_expiry.patch(pointer, value),
|
|
Some(Property::HttpRsvpUrl) => self
|
|
.http_rsvp_url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AutoAddInvitations) => self.auto_add_invitations.patch(pointer, value),
|
|
Some(Property::ItipMaxSize) => self.itip_max_size.patch(pointer, value),
|
|
Some(Property::MaxRecipients) => self.max_recipients.patch(pointer, value),
|
|
Some(Property::EmailTemplate) => self.email_template.patch(pointer, value),
|
|
Some(Property::HttpRsvpTemplate) => self.http_rsvp_template.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Certificate {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Certificate;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.certificate;
|
|
value.validate(errors);
|
|
let value = &self.private_key;
|
|
value.validate(errors);
|
|
let value = &self.subject_alternative_names;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SubjectAlternativeNames));
|
|
}
|
|
}
|
|
let value = &self.not_valid_after;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::NotValidAfter, value));
|
|
}
|
|
let value = &self.not_valid_before;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::NotValidBefore, value));
|
|
}
|
|
let value = &self.issuer;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Issuer));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
for value in self.subject_alternative_names.iter() {
|
|
i.text(Property::SubjectAlternativeNames, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for Certificate {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.certificate.pickle(out);
|
|
self.private_key.pickle(out);
|
|
self.subject_alternative_names.pickle(out);
|
|
self.not_valid_after.pickle(out);
|
|
self.not_valid_before.pickle(out);
|
|
self.issuer.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.certificate = Pickle::unpickle(stream)?;
|
|
this.private_key = Pickle::unpickle(stream)?;
|
|
this.subject_alternative_names = Pickle::unpickle(stream)?;
|
|
this.not_valid_after = Pickle::unpickle(stream)?;
|
|
this.not_valid_before = Pickle::unpickle(stream)?;
|
|
this.issuer = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Certificate {
|
|
fn default() -> Self {
|
|
Self {
|
|
certificate: Default::default(),
|
|
private_key: Default::default(),
|
|
subject_alternative_names: Default::default(),
|
|
not_valid_after: Default::default(),
|
|
not_valid_before: Default::default(),
|
|
issuer: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Certificate {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Certificate, self.certificate.into_value());
|
|
map.insert_unchecked(Property::PrivateKey, self.private_key.into_value());
|
|
map.insert_unchecked(
|
|
Property::SubjectAlternativeNames,
|
|
self.subject_alternative_names.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::NotValidAfter, self.not_valid_after.into_value());
|
|
map.insert_unchecked(Property::NotValidBefore, self.not_valid_before.into_value());
|
|
map.insert_unchecked(Property::Issuer, self.issuer.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Certificate {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Certificate) => self.certificate.patch(pointer, value),
|
|
Some(Property::PrivateKey) => self.private_key.patch(pointer, value),
|
|
Some(Property::SubjectAlternativeNames) => pointer.assert_server_set(),
|
|
Some(Property::NotValidAfter) => pointer.assert_server_set(),
|
|
Some(Property::NotValidBefore) => pointer.assert_server_set(),
|
|
Some(Property::Issuer) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CertificateManagement {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
CertificateManagement::Manual => true,
|
|
CertificateManagement::Automatic(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
CertificateManagement::Manual => {}
|
|
CertificateManagement::Automatic(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for CertificateManagement {
|
|
fn default() -> Self {
|
|
CertificateManagement::Manual
|
|
}
|
|
}
|
|
|
|
impl Pickle for CertificateManagement {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
CertificateManagement::Manual => {
|
|
0u16.pickle(out);
|
|
}
|
|
CertificateManagement::Automatic(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(CertificateManagement::Manual),
|
|
1 => Pickle::unpickle(stream).map(CertificateManagement::Automatic),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CertificateManagement {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
CertificateManagement::Manual => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
CertificateManagement::Automatic(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Automatic".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for CertificateManagement {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
CertificateManagementType::Manual => *self = CertificateManagement::Manual,
|
|
CertificateManagementType::Automatic => {
|
|
*self = CertificateManagement::Automatic(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
CertificateManagement::Manual => pointer.assert_eof(),
|
|
CertificateManagement::Automatic(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CertificateManagement {
|
|
pub fn object_type(&self) -> CertificateManagementType {
|
|
match self {
|
|
CertificateManagement::Manual => CertificateManagementType::Manual,
|
|
CertificateManagement::Automatic(_) => CertificateManagementType::Automatic,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CertificateManagementProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.acme_provider_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AcmeProviderId));
|
|
}
|
|
let value = &self.subject_alternative_names;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SubjectAlternativeNames));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::AcmeProvider, self.acme_provider_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for CertificateManagementProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.acme_provider_id.pickle(out);
|
|
self.subject_alternative_names.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.acme_provider_id = Pickle::unpickle(stream)?;
|
|
this.subject_alternative_names = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CertificateManagementProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
acme_provider_id: Default::default(),
|
|
subject_alternative_names: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CertificateManagementProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::AcmeProviderId, self.acme_provider_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::SubjectAlternativeNames,
|
|
self.subject_alternative_names.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CertificateManagementProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AcmeProviderId) => self.acme_provider_id.patch(pointer, value),
|
|
Some(Property::SubjectAlternativeNames) => self
|
|
.subject_alternative_names
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClusterListenerGroup {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
ClusterListenerGroup::EnableAll => true,
|
|
ClusterListenerGroup::DisableAll => true,
|
|
ClusterListenerGroup::EnableSome(inner) => inner.validate(errors),
|
|
ClusterListenerGroup::DisableSome(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
ClusterListenerGroup::EnableAll => {}
|
|
ClusterListenerGroup::DisableAll => {}
|
|
ClusterListenerGroup::EnableSome(object) => {
|
|
object.index(i);
|
|
}
|
|
ClusterListenerGroup::DisableSome(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for ClusterListenerGroup {
|
|
fn default() -> Self {
|
|
ClusterListenerGroup::EnableAll
|
|
}
|
|
}
|
|
|
|
impl Pickle for ClusterListenerGroup {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
ClusterListenerGroup::EnableAll => {
|
|
0u16.pickle(out);
|
|
}
|
|
ClusterListenerGroup::DisableAll => {
|
|
1u16.pickle(out);
|
|
}
|
|
ClusterListenerGroup::EnableSome(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
ClusterListenerGroup::DisableSome(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(ClusterListenerGroup::EnableAll),
|
|
1 => Some(ClusterListenerGroup::DisableAll),
|
|
2 => Pickle::unpickle(stream).map(ClusterListenerGroup::EnableSome),
|
|
3 => Pickle::unpickle(stream).map(ClusterListenerGroup::DisableSome),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ClusterListenerGroup {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
ClusterListenerGroup::EnableAll => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EnableAll".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
ClusterListenerGroup::DisableAll => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("DisableAll".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
ClusterListenerGroup::EnableSome(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnableSome".into()));
|
|
obj
|
|
}
|
|
ClusterListenerGroup::DisableSome(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DisableSome".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for ClusterListenerGroup {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
ClusterListenerGroupType::EnableAll => *self = ClusterListenerGroup::EnableAll,
|
|
ClusterListenerGroupType::DisableAll => *self = ClusterListenerGroup::DisableAll,
|
|
ClusterListenerGroupType::EnableSome => {
|
|
*self = ClusterListenerGroup::EnableSome(Default::default())
|
|
}
|
|
ClusterListenerGroupType::DisableSome => {
|
|
*self = ClusterListenerGroup::DisableSome(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
ClusterListenerGroup::EnableAll => pointer.assert_eof(),
|
|
ClusterListenerGroup::DisableAll => pointer.assert_eof(),
|
|
ClusterListenerGroup::EnableSome(inner) => inner.patch(pointer, value),
|
|
ClusterListenerGroup::DisableSome(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClusterListenerGroup {
|
|
pub fn object_type(&self) -> ClusterListenerGroupType {
|
|
match self {
|
|
ClusterListenerGroup::EnableAll => ClusterListenerGroupType::EnableAll,
|
|
ClusterListenerGroup::DisableAll => ClusterListenerGroupType::DisableAll,
|
|
ClusterListenerGroup::EnableSome(_) => ClusterListenerGroupType::EnableSome,
|
|
ClusterListenerGroup::DisableSome(_) => ClusterListenerGroupType::DisableSome,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClusterListenerGroupProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.listener_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::ListenerIds));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
for id in self.listener_ids.iter() {
|
|
i.foreign_key(ObjectType::NetworkListener, Some(*id), None);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for ClusterListenerGroupProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.listener_ids.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.listener_ids = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ClusterListenerGroupProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
listener_ids: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ClusterListenerGroupProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::ListenerIds, self.listener_ids.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ClusterListenerGroupProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ListenerIds) => self.listener_ids.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for ClusterNode {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::ClusterNode;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.hostname;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Hostname));
|
|
}
|
|
let value = &self.last_renewal;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::LastRenewal, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for ClusterNode {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.node_id.pickle(out);
|
|
self.hostname.pickle(out);
|
|
self.last_renewal.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.node_id = Pickle::unpickle(stream)?;
|
|
this.hostname = Pickle::unpickle(stream)?;
|
|
this.last_renewal = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ClusterNode {
|
|
fn default() -> Self {
|
|
Self {
|
|
node_id: 1u64,
|
|
hostname: Default::default(),
|
|
last_renewal: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ClusterNode {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::NodeId, self.node_id.into_value());
|
|
map.insert_unchecked(Property::Hostname, self.hostname.into_value());
|
|
map.insert_unchecked(Property::LastRenewal, self.last_renewal.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ClusterNode {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::NodeId) => self.node_id.patch(pointer, value),
|
|
Some(Property::Hostname) => self.hostname.patch(pointer, value),
|
|
Some(Property::LastRenewal) => self.last_renewal.patch(pointer, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for ClusterRole {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::ClusterRole;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.tasks;
|
|
value.validate(errors);
|
|
let value = &self.listeners;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
self.listeners.index(i);
|
|
}
|
|
}
|
|
|
|
impl Pickle for ClusterRole {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.tasks.pickle(out);
|
|
self.listeners.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.tasks = Pickle::unpickle(stream)?;
|
|
this.listeners = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ClusterRole {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
tasks: Default::default(),
|
|
listeners: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ClusterRole {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Tasks, self.tasks.into_value());
|
|
map.insert_unchecked(Property::Listeners, self.listeners.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ClusterRole {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Tasks) => self.tasks.patch(pointer, value),
|
|
Some(Property::Listeners) => self.listeners.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClusterTaskGroup {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
ClusterTaskGroup::EnableAll => true,
|
|
ClusterTaskGroup::DisableAll => true,
|
|
ClusterTaskGroup::EnableSome(inner) => inner.validate(errors),
|
|
ClusterTaskGroup::DisableSome(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for ClusterTaskGroup {
|
|
fn default() -> Self {
|
|
ClusterTaskGroup::EnableAll
|
|
}
|
|
}
|
|
|
|
impl Pickle for ClusterTaskGroup {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
ClusterTaskGroup::EnableAll => {
|
|
0u16.pickle(out);
|
|
}
|
|
ClusterTaskGroup::DisableAll => {
|
|
1u16.pickle(out);
|
|
}
|
|
ClusterTaskGroup::EnableSome(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
ClusterTaskGroup::DisableSome(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(ClusterTaskGroup::EnableAll),
|
|
1 => Some(ClusterTaskGroup::DisableAll),
|
|
2 => Pickle::unpickle(stream).map(ClusterTaskGroup::EnableSome),
|
|
3 => Pickle::unpickle(stream).map(ClusterTaskGroup::DisableSome),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ClusterTaskGroup {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
ClusterTaskGroup::EnableAll => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EnableAll".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
ClusterTaskGroup::DisableAll => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("DisableAll".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
ClusterTaskGroup::EnableSome(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnableSome".into()));
|
|
obj
|
|
}
|
|
ClusterTaskGroup::DisableSome(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DisableSome".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for ClusterTaskGroup {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
ClusterTaskGroupType::EnableAll => *self = ClusterTaskGroup::EnableAll,
|
|
ClusterTaskGroupType::DisableAll => *self = ClusterTaskGroup::DisableAll,
|
|
ClusterTaskGroupType::EnableSome => {
|
|
*self = ClusterTaskGroup::EnableSome(Default::default())
|
|
}
|
|
ClusterTaskGroupType::DisableSome => {
|
|
*self = ClusterTaskGroup::DisableSome(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
ClusterTaskGroup::EnableAll => pointer.assert_eof(),
|
|
ClusterTaskGroup::DisableAll => pointer.assert_eof(),
|
|
ClusterTaskGroup::EnableSome(inner) => inner.patch(pointer, value),
|
|
ClusterTaskGroup::DisableSome(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClusterTaskGroup {
|
|
pub fn object_type(&self) -> ClusterTaskGroupType {
|
|
match self {
|
|
ClusterTaskGroup::EnableAll => ClusterTaskGroupType::EnableAll,
|
|
ClusterTaskGroup::DisableAll => ClusterTaskGroupType::DisableAll,
|
|
ClusterTaskGroup::EnableSome(_) => ClusterTaskGroupType::EnableSome,
|
|
ClusterTaskGroup::DisableSome(_) => ClusterTaskGroupType::DisableSome,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClusterTaskGroupProperties {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for ClusterTaskGroupProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.task_types.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.task_types = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ClusterTaskGroupProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
task_types: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ClusterTaskGroupProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::TaskTypes, self.task_types.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ClusterTaskGroupProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::TaskTypes) => self.task_types.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Coordinator {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Coordinator;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Coordinator::Disabled => true,
|
|
Coordinator::Default => true,
|
|
Coordinator::Kafka(inner) => inner.validate(errors),
|
|
Coordinator::Nats(inner) => inner.validate(errors),
|
|
Coordinator::Zenoh(inner) => inner.validate(errors),
|
|
Coordinator::Redis(inner) => inner.validate(errors),
|
|
Coordinator::RedisCluster(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for Coordinator {
|
|
fn default() -> Self {
|
|
Coordinator::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for Coordinator {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Coordinator::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
Coordinator::Default => {
|
|
1u16.pickle(out);
|
|
}
|
|
Coordinator::Kafka(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Coordinator::Nats(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Coordinator::Zenoh(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Coordinator::Redis(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Coordinator::RedisCluster(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(Coordinator::Disabled),
|
|
1 => Some(Coordinator::Default),
|
|
2 => Pickle::unpickle(stream).map(Coordinator::Kafka),
|
|
3 => Pickle::unpickle(stream).map(Coordinator::Nats),
|
|
4 => Pickle::unpickle(stream).map(Coordinator::Zenoh),
|
|
5 => Pickle::unpickle(stream).map(Coordinator::Redis),
|
|
6 => Pickle::unpickle(stream).map(Coordinator::RedisCluster),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Coordinator {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Coordinator::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Coordinator::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Coordinator::Kafka(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Kafka".into()));
|
|
obj
|
|
}
|
|
Coordinator::Nats(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Nats".into()));
|
|
obj
|
|
}
|
|
Coordinator::Zenoh(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Zenoh".into()));
|
|
obj
|
|
}
|
|
Coordinator::Redis(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Redis".into()));
|
|
obj
|
|
}
|
|
Coordinator::RedisCluster(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Coordinator {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
CoordinatorType::Disabled => *self = Coordinator::Disabled,
|
|
CoordinatorType::Default => *self = Coordinator::Default,
|
|
CoordinatorType::Kafka => *self = Coordinator::Kafka(Default::default()),
|
|
CoordinatorType::Nats => *self = Coordinator::Nats(Default::default()),
|
|
CoordinatorType::Zenoh => *self = Coordinator::Zenoh(Default::default()),
|
|
CoordinatorType::Redis => *self = Coordinator::Redis(Default::default()),
|
|
CoordinatorType::RedisCluster => {
|
|
*self = Coordinator::RedisCluster(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
Coordinator::Disabled => pointer.assert_eof(),
|
|
Coordinator::Default => pointer.assert_eof(),
|
|
Coordinator::Kafka(inner) => inner.patch(pointer, value),
|
|
Coordinator::Nats(inner) => inner.patch(pointer, value),
|
|
Coordinator::Zenoh(inner) => inner.patch(pointer, value),
|
|
Coordinator::Redis(inner) => inner.patch(pointer, value),
|
|
Coordinator::RedisCluster(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Coordinator {
|
|
pub fn object_type(&self) -> CoordinatorType {
|
|
match self {
|
|
Coordinator::Disabled => CoordinatorType::Disabled,
|
|
Coordinator::Default => CoordinatorType::Default,
|
|
Coordinator::Kafka(_) => CoordinatorType::Kafka,
|
|
Coordinator::Nats(_) => CoordinatorType::Nats,
|
|
Coordinator::Zenoh(_) => CoordinatorType::Zenoh,
|
|
Coordinator::Redis(_) => CoordinatorType::Redis,
|
|
Coordinator::RedisCluster(_) => CoordinatorType::RedisCluster,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Credential {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Credential::Password(inner) => inner.validate(errors),
|
|
Credential::AppPassword(inner) => inner.validate(errors),
|
|
Credential::ApiKey(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Credential {
|
|
fn default() -> Self {
|
|
Credential::Password(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Credential {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Credential::Password(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Credential::AppPassword(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Credential::ApiKey(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Credential::Password),
|
|
1 => Pickle::unpickle(stream).map(Credential::AppPassword),
|
|
2 => Pickle::unpickle(stream).map(Credential::ApiKey),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Credential {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Credential::Password(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Password".into()));
|
|
obj
|
|
}
|
|
Credential::AppPassword(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("AppPassword".into()));
|
|
obj
|
|
}
|
|
Credential::ApiKey(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("ApiKey".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Credential {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
CredentialType::Password => *self = Credential::Password(Default::default()),
|
|
CredentialType::AppPassword => *self = Credential::AppPassword(Default::default()),
|
|
CredentialType::ApiKey => *self = Credential::ApiKey(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Credential::Password(inner) => inner.patch(pointer, value),
|
|
Credential::AppPassword(inner) => inner.patch(pointer, value),
|
|
Credential::ApiKey(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Credential {
|
|
pub fn object_type(&self) -> CredentialType {
|
|
match self {
|
|
Credential::Password(_) => CredentialType::Password,
|
|
Credential::AppPassword(_) => CredentialType::AppPassword,
|
|
Credential::ApiKey(_) => CredentialType::ApiKey,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CredentialPermissions {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
CredentialPermissions::Inherit => true,
|
|
CredentialPermissions::Disable(inner) => inner.validate(errors),
|
|
CredentialPermissions::Replace(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for CredentialPermissions {
|
|
fn default() -> Self {
|
|
CredentialPermissions::Inherit
|
|
}
|
|
}
|
|
|
|
impl Pickle for CredentialPermissions {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
CredentialPermissions::Inherit => {
|
|
0u16.pickle(out);
|
|
}
|
|
CredentialPermissions::Disable(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
CredentialPermissions::Replace(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(CredentialPermissions::Inherit),
|
|
1 => Pickle::unpickle(stream).map(CredentialPermissions::Disable),
|
|
2 => Pickle::unpickle(stream).map(CredentialPermissions::Replace),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CredentialPermissions {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
CredentialPermissions::Inherit => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Inherit".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
CredentialPermissions::Disable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Disable".into()));
|
|
obj
|
|
}
|
|
CredentialPermissions::Replace(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Replace".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for CredentialPermissions {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
CredentialPermissionsType::Inherit => *self = CredentialPermissions::Inherit,
|
|
CredentialPermissionsType::Disable => {
|
|
*self = CredentialPermissions::Disable(Default::default())
|
|
}
|
|
CredentialPermissionsType::Replace => {
|
|
*self = CredentialPermissions::Replace(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
CredentialPermissions::Inherit => pointer.assert_eof(),
|
|
CredentialPermissions::Disable(inner) => inner.patch(pointer, value),
|
|
CredentialPermissions::Replace(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CredentialPermissions {
|
|
pub fn object_type(&self) -> CredentialPermissionsType {
|
|
match self {
|
|
CredentialPermissions::Inherit => CredentialPermissionsType::Inherit,
|
|
CredentialPermissions::Disable(_) => CredentialPermissionsType::Disable,
|
|
CredentialPermissions::Replace(_) => CredentialPermissionsType::Replace,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CredentialPermissionsList {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for CredentialPermissionsList {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.permissions.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CredentialPermissionsList {
|
|
fn default() -> Self {
|
|
Self {
|
|
permissions: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CredentialPermissionsList {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CredentialPermissionsList {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Cron {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Cron::Daily(inner) => inner.validate(errors),
|
|
Cron::Weekly(inner) => inner.validate(errors),
|
|
Cron::Hourly(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Cron {
|
|
fn default() -> Self {
|
|
Cron::Daily(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Cron {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Cron::Daily(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Cron::Weekly(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Cron::Hourly(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Cron::Daily),
|
|
1 => Pickle::unpickle(stream).map(Cron::Weekly),
|
|
2 => Pickle::unpickle(stream).map(Cron::Hourly),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Cron {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Cron::Daily(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Daily".into()));
|
|
obj
|
|
}
|
|
Cron::Weekly(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Weekly".into()));
|
|
obj
|
|
}
|
|
Cron::Hourly(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Hourly".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Cron {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
CronType::Daily => *self = Cron::Daily(Default::default()),
|
|
CronType::Weekly => *self = Cron::Weekly(Default::default()),
|
|
CronType::Hourly => *self = Cron::Hourly(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Cron::Daily(inner) => inner.patch(pointer, value),
|
|
Cron::Weekly(inner) => inner.patch(pointer, value),
|
|
Cron::Hourly(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Cron {
|
|
pub fn object_type(&self) -> CronType {
|
|
match self {
|
|
Cron::Daily(_) => CronType::Daily,
|
|
Cron::Weekly(_) => CronType::Weekly,
|
|
Cron::Hourly(_) => CronType::Hourly,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CronDaily {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.hour;
|
|
if *value > 23 {
|
|
errors.push(ValidationError::max_value(Property::Hour, 23));
|
|
}
|
|
let value = &self.minute;
|
|
if *value > 59 {
|
|
errors.push(ValidationError::max_value(Property::Minute, 59));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for CronDaily {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.hour.pickle(out);
|
|
self.minute.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.hour = Pickle::unpickle(stream)?;
|
|
this.minute = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CronDaily {
|
|
fn default() -> Self {
|
|
Self {
|
|
hour: 0u64,
|
|
minute: 0u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CronDaily {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Hour, self.hour.into_value());
|
|
map.insert_unchecked(Property::Minute, self.minute.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CronDaily {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Hour) => self.hour.patch(pointer, value),
|
|
Some(Property::Minute) => self.minute.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CronHourly {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.minute;
|
|
if *value > 59 {
|
|
errors.push(ValidationError::max_value(Property::Minute, 59));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for CronHourly {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.minute.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.minute = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CronHourly {
|
|
fn default() -> Self {
|
|
Self { minute: 0u64 }
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CronHourly {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Minute, self.minute.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CronHourly {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Minute) => self.minute.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CronWeekly {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.day;
|
|
if *value > 6 {
|
|
errors.push(ValidationError::max_value(Property::Day, 6));
|
|
}
|
|
let value = &self.hour;
|
|
if *value > 23 {
|
|
errors.push(ValidationError::max_value(Property::Hour, 23));
|
|
}
|
|
let value = &self.minute;
|
|
if *value > 59 {
|
|
errors.push(ValidationError::max_value(Property::Minute, 59));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for CronWeekly {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.day.pickle(out);
|
|
self.hour.pickle(out);
|
|
self.minute.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.day = Pickle::unpickle(stream)?;
|
|
this.hour = Pickle::unpickle(stream)?;
|
|
this.minute = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CronWeekly {
|
|
fn default() -> Self {
|
|
Self {
|
|
day: 0u64,
|
|
hour: 0u64,
|
|
minute: 0u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CronWeekly {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Day, self.day.into_value());
|
|
map.insert_unchecked(Property::Hour, self.hour.into_value());
|
|
map.insert_unchecked(Property::Minute, self.minute.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CronWeekly {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Day) => self.day.patch(pointer, value),
|
|
Some(Property::Hour) => self.hour.patch(pointer, value),
|
|
Some(Property::Minute) => self.minute.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CustomRoles {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.role_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::RoleIds));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
for id in self.role_ids.iter() {
|
|
i.foreign_key(ObjectType::Role, Some(*id), None);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for CustomRoles {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.role_ids.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.role_ids = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for CustomRoles {
|
|
fn default() -> Self {
|
|
Self {
|
|
role_ids: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for CustomRoles {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::RoleIds, self.role_ids.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for CustomRoles {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::RoleIds) => self.role_ids.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DataRetention {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DataRetention;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.expunge_schedule;
|
|
value.validate(errors);
|
|
let value = &self.data_cleanup_schedule;
|
|
value.validate(errors);
|
|
let value = &self.blob_cleanup_schedule;
|
|
value.validate(errors);
|
|
let value = &self.metrics_collection_interval;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for DataRetention {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.expunge_trash_after.pickle(out);
|
|
self.expunge_submissions_after.pickle(out);
|
|
self.expunge_share_notify_after.pickle(out);
|
|
self.expunge_scheduling_inbox_after.pickle(out);
|
|
self.expunge_schedule.pickle(out);
|
|
self.data_cleanup_schedule.pickle(out);
|
|
self.blob_cleanup_schedule.pickle(out);
|
|
self.max_changes_history.pickle(out);
|
|
self.archive_deleted_items_for.pickle(out);
|
|
self.archive_deleted_accounts_for.pickle(out);
|
|
self.hold_mta_reports_for.pickle(out);
|
|
self.hold_traces_for.pickle(out);
|
|
self.hold_metrics_for.pickle(out);
|
|
self.metrics_collection_interval.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.expunge_trash_after = Pickle::unpickle(stream)?;
|
|
this.expunge_submissions_after = Pickle::unpickle(stream)?;
|
|
this.expunge_share_notify_after = Pickle::unpickle(stream)?;
|
|
this.expunge_scheduling_inbox_after = Pickle::unpickle(stream)?;
|
|
this.expunge_schedule = Pickle::unpickle(stream)?;
|
|
this.data_cleanup_schedule = Pickle::unpickle(stream)?;
|
|
this.blob_cleanup_schedule = Pickle::unpickle(stream)?;
|
|
this.max_changes_history = Pickle::unpickle(stream)?;
|
|
this.archive_deleted_items_for = Pickle::unpickle(stream)?;
|
|
this.archive_deleted_accounts_for = Pickle::unpickle(stream)?;
|
|
this.hold_mta_reports_for = Pickle::unpickle(stream)?;
|
|
this.hold_traces_for = Pickle::unpickle(stream)?;
|
|
this.hold_metrics_for = Pickle::unpickle(stream)?;
|
|
this.metrics_collection_interval = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DataRetention {
|
|
fn default() -> Self {
|
|
Self {
|
|
expunge_trash_after: Some(Duration::from_millis(2592000000)),
|
|
expunge_submissions_after: Some(Duration::from_millis(259200000)),
|
|
expunge_share_notify_after: Some(Duration::from_millis(2592000000)),
|
|
expunge_scheduling_inbox_after: Some(Duration::from_millis(2592000000)),
|
|
expunge_schedule: Cron::Daily(CronDaily {
|
|
hour: 0u64,
|
|
minute: 0u64,
|
|
}),
|
|
data_cleanup_schedule: Cron::Daily(CronDaily {
|
|
hour: 2u64,
|
|
minute: 0u64,
|
|
}),
|
|
blob_cleanup_schedule: Cron::Daily(CronDaily {
|
|
hour: 4u64,
|
|
minute: 0u64,
|
|
}),
|
|
max_changes_history: Some(10000u64),
|
|
archive_deleted_items_for: Default::default(),
|
|
archive_deleted_accounts_for: Default::default(),
|
|
hold_mta_reports_for: Some(Duration::from_millis(2592000000)),
|
|
hold_traces_for: Some(Duration::from_millis(2592000000)),
|
|
hold_metrics_for: Some(Duration::from_millis(7776000000)),
|
|
metrics_collection_interval: Cron::Hourly(CronHourly { minute: 0u64 }),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DataRetention {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(16);
|
|
map.insert_unchecked(
|
|
Property::ExpungeTrashAfter,
|
|
self.expunge_trash_after.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ExpungeSubmissionsAfter,
|
|
self.expunge_submissions_after.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ExpungeShareNotifyAfter,
|
|
self.expunge_share_notify_after.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ExpungeSchedulingInboxAfter,
|
|
self.expunge_scheduling_inbox_after.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ExpungeSchedule,
|
|
self.expunge_schedule.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DataCleanupSchedule,
|
|
self.data_cleanup_schedule.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::BlobCleanupSchedule,
|
|
self.blob_cleanup_schedule.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxChangesHistory,
|
|
self.max_changes_history.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ArchiveDeletedItemsFor,
|
|
self.archive_deleted_items_for.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ArchiveDeletedAccountsFor,
|
|
self.archive_deleted_accounts_for.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::HoldMtaReportsFor,
|
|
self.hold_mta_reports_for.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::HoldTracesFor, self.hold_traces_for.into_value());
|
|
map.insert_unchecked(Property::HoldMetricsFor, self.hold_metrics_for.into_value());
|
|
map.insert_unchecked(
|
|
Property::MetricsCollectionInterval,
|
|
self.metrics_collection_interval.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DataRetention {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ExpungeTrashAfter) => self.expunge_trash_after.patch(pointer, value),
|
|
Some(Property::ExpungeSubmissionsAfter) => {
|
|
self.expunge_submissions_after.patch(pointer, value)
|
|
}
|
|
Some(Property::ExpungeShareNotifyAfter) => {
|
|
self.expunge_share_notify_after.patch(pointer, value)
|
|
}
|
|
Some(Property::ExpungeSchedulingInboxAfter) => {
|
|
self.expunge_scheduling_inbox_after.patch(pointer, value)
|
|
}
|
|
Some(Property::ExpungeSchedule) => self.expunge_schedule.patch(pointer, value),
|
|
Some(Property::DataCleanupSchedule) => self.data_cleanup_schedule.patch(pointer, value),
|
|
Some(Property::BlobCleanupSchedule) => self.blob_cleanup_schedule.patch(pointer, value),
|
|
Some(Property::MaxChangesHistory) => self.max_changes_history.patch(pointer, value),
|
|
Some(Property::ArchiveDeletedItemsFor) => {
|
|
self.archive_deleted_items_for.patch(pointer, value)
|
|
}
|
|
Some(Property::ArchiveDeletedAccountsFor) => {
|
|
self.archive_deleted_accounts_for.patch(pointer, value)
|
|
}
|
|
Some(Property::HoldMtaReportsFor) => self.hold_mta_reports_for.patch(pointer, value),
|
|
Some(Property::HoldTracesFor) => self.hold_traces_for.patch(pointer, value),
|
|
Some(Property::HoldMetricsFor) => self.hold_metrics_for.patch(pointer, value),
|
|
Some(Property::MetricsCollectionInterval) => {
|
|
self.metrics_collection_interval.patch(pointer, value)
|
|
}
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DataStore {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DataStore;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DataStore::RocksDb(inner) => inner.validate(errors),
|
|
DataStore::Sqlite(inner) => inner.validate(errors),
|
|
DataStore::FoundationDb(inner) => inner.validate(errors),
|
|
DataStore::PostgreSql(inner) => inner.validate(errors),
|
|
DataStore::MySql(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for DataStore {
|
|
fn default() -> Self {
|
|
DataStore::RocksDb(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for DataStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DataStore::RocksDb(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DataStore::Sqlite(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DataStore::FoundationDb(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DataStore::PostgreSql(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DataStore::MySql(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(DataStore::RocksDb),
|
|
1 => Pickle::unpickle(stream).map(DataStore::Sqlite),
|
|
2 => Pickle::unpickle(stream).map(DataStore::FoundationDb),
|
|
3 => Pickle::unpickle(stream).map(DataStore::PostgreSql),
|
|
4 => Pickle::unpickle(stream).map(DataStore::MySql),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DataStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DataStore::RocksDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("RocksDb".into()));
|
|
obj
|
|
}
|
|
DataStore::Sqlite(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sqlite".into()));
|
|
obj
|
|
}
|
|
DataStore::FoundationDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into()));
|
|
obj
|
|
}
|
|
DataStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
DataStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DataStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DataStoreType::RocksDb => *self = DataStore::RocksDb(Default::default()),
|
|
DataStoreType::Sqlite => *self = DataStore::Sqlite(Default::default()),
|
|
DataStoreType::FoundationDb => *self = DataStore::FoundationDb(Default::default()),
|
|
DataStoreType::PostgreSql => *self = DataStore::PostgreSql(Default::default()),
|
|
DataStoreType::MySql => *self = DataStore::MySql(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
DataStore::RocksDb(inner) => inner.patch(pointer, value),
|
|
DataStore::Sqlite(inner) => inner.patch(pointer, value),
|
|
DataStore::FoundationDb(inner) => inner.patch(pointer, value),
|
|
DataStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
DataStore::MySql(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DataStore {
|
|
pub fn object_type(&self) -> DataStoreType {
|
|
match self {
|
|
DataStore::RocksDb(_) => DataStoreType::RocksDb,
|
|
DataStore::Sqlite(_) => DataStoreType::Sqlite,
|
|
DataStore::FoundationDb(_) => DataStoreType::FoundationDb,
|
|
DataStore::PostgreSql(_) => DataStoreType::PostgreSql,
|
|
DataStore::MySql(_) => DataStoreType::MySql,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DeliveryError {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.error_message {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ErrorMessage));
|
|
}
|
|
}
|
|
if let Some(value) = &self.error_command {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ErrorCommand));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseHostname));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_code {
|
|
if *value < 100 {
|
|
errors.push(ValidationError::min_value(Property::ResponseCode, 100));
|
|
}
|
|
if *value > 599 {
|
|
errors.push(ValidationError::max_value(Property::ResponseCode, 599));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_enhanced {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseEnhanced));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_message {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseMessage));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DeliveryError {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.error_type.pickle(out);
|
|
self.error_message.pickle(out);
|
|
self.error_command.pickle(out);
|
|
self.response_hostname.pickle(out);
|
|
self.response_code.pickle(out);
|
|
self.response_enhanced.pickle(out);
|
|
self.response_message.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.error_type = Pickle::unpickle(stream)?;
|
|
this.error_message = Pickle::unpickle(stream)?;
|
|
this.error_command = Pickle::unpickle(stream)?;
|
|
this.response_hostname = Pickle::unpickle(stream)?;
|
|
this.response_code = Pickle::unpickle(stream)?;
|
|
this.response_enhanced = Pickle::unpickle(stream)?;
|
|
this.response_message = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DeliveryError {
|
|
fn default() -> Self {
|
|
Self {
|
|
error_type: Default::default(),
|
|
error_message: Default::default(),
|
|
error_command: Default::default(),
|
|
response_hostname: Default::default(),
|
|
response_code: Default::default(),
|
|
response_enhanced: Default::default(),
|
|
response_message: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DeliveryError {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::ErrorType, self.error_type.into_value());
|
|
map.insert_unchecked(Property::ErrorMessage, self.error_message.into_value());
|
|
map.insert_unchecked(Property::ErrorCommand, self.error_command.into_value());
|
|
map.insert_unchecked(
|
|
Property::ResponseHostname,
|
|
self.response_hostname.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ResponseCode, self.response_code.into_value());
|
|
map.insert_unchecked(
|
|
Property::ResponseEnhanced,
|
|
self.response_enhanced.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ResponseMessage,
|
|
self.response_message.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DeliveryError {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ErrorType) => self.error_type.patch(pointer, value),
|
|
Some(Property::ErrorMessage) => self.error_message.patch(pointer, value),
|
|
Some(Property::ErrorCommand) => self.error_command.patch(pointer, value),
|
|
Some(Property::ResponseHostname) => self.response_hostname.patch(pointer, value),
|
|
Some(Property::ResponseCode) => self.response_code.patch(pointer, value),
|
|
Some(Property::ResponseEnhanced) => self.response_enhanced.patch(pointer, value),
|
|
Some(Property::ResponseMessage) => self.response_message.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Directory {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Directory;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Directory::Ldap(inner) => inner.validate(errors),
|
|
Directory::Sql(inner) => inner.validate(errors),
|
|
Directory::Oidc(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
Directory::Ldap(object) => {
|
|
object.index(i);
|
|
}
|
|
Directory::Sql(object) => {
|
|
object.index(i);
|
|
}
|
|
Directory::Oidc(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Directory {
|
|
fn default() -> Self {
|
|
Directory::Ldap(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Directory {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Directory::Ldap(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Directory::Sql(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Directory::Oidc(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Directory::Ldap),
|
|
1 => Pickle::unpickle(stream).map(Directory::Sql),
|
|
2 => Pickle::unpickle(stream).map(Directory::Oidc),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Directory {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Directory::Ldap(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ldap".into()));
|
|
obj
|
|
}
|
|
Directory::Sql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sql".into()));
|
|
obj
|
|
}
|
|
Directory::Oidc(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Oidc".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Directory {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DirectoryType::Ldap => *self = Directory::Ldap(Default::default()),
|
|
DirectoryType::Sql => *self = Directory::Sql(Default::default()),
|
|
DirectoryType::Oidc => *self = Directory::Oidc(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Directory::Ldap(inner) => inner.patch(pointer, value),
|
|
Directory::Sql(inner) => inner.patch(pointer, value),
|
|
Directory::Oidc(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Directory {
|
|
pub fn object_type(&self) -> DirectoryType {
|
|
match self {
|
|
Directory::Ldap(_) => DirectoryType::Ldap,
|
|
Directory::Sql(_) => DirectoryType::Sql,
|
|
Directory::Oidc(_) => DirectoryType::Oidc,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DirectoryBootstrap {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DirectoryBootstrap::Internal => true,
|
|
DirectoryBootstrap::Ldap(inner) => inner.validate(errors),
|
|
DirectoryBootstrap::Sql(inner) => inner.validate(errors),
|
|
DirectoryBootstrap::Oidc(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DirectoryBootstrap {
|
|
fn default() -> Self {
|
|
DirectoryBootstrap::Internal
|
|
}
|
|
}
|
|
|
|
impl Pickle for DirectoryBootstrap {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DirectoryBootstrap::Internal => {
|
|
0u16.pickle(out);
|
|
}
|
|
DirectoryBootstrap::Ldap(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DirectoryBootstrap::Sql(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DirectoryBootstrap::Oidc(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(DirectoryBootstrap::Internal),
|
|
1 => Pickle::unpickle(stream).map(DirectoryBootstrap::Ldap),
|
|
2 => Pickle::unpickle(stream).map(DirectoryBootstrap::Sql),
|
|
3 => Pickle::unpickle(stream).map(DirectoryBootstrap::Oidc),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DirectoryBootstrap {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DirectoryBootstrap::Internal => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Internal".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
DirectoryBootstrap::Ldap(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ldap".into()));
|
|
obj
|
|
}
|
|
DirectoryBootstrap::Sql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sql".into()));
|
|
obj
|
|
}
|
|
DirectoryBootstrap::Oidc(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Oidc".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DirectoryBootstrap {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DirectoryBootstrapType::Internal => *self = DirectoryBootstrap::Internal,
|
|
DirectoryBootstrapType::Ldap => {
|
|
*self = DirectoryBootstrap::Ldap(Default::default())
|
|
}
|
|
DirectoryBootstrapType::Sql => *self = DirectoryBootstrap::Sql(Default::default()),
|
|
DirectoryBootstrapType::Oidc => {
|
|
*self = DirectoryBootstrap::Oidc(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
DirectoryBootstrap::Internal => pointer.assert_eof(),
|
|
DirectoryBootstrap::Ldap(inner) => inner.patch(pointer, value),
|
|
DirectoryBootstrap::Sql(inner) => inner.patch(pointer, value),
|
|
DirectoryBootstrap::Oidc(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DirectoryBootstrap {
|
|
pub fn object_type(&self) -> DirectoryBootstrapType {
|
|
match self {
|
|
DirectoryBootstrap::Internal => DirectoryBootstrapType::Internal,
|
|
DirectoryBootstrap::Ldap(_) => DirectoryBootstrapType::Ldap,
|
|
DirectoryBootstrap::Sql(_) => DirectoryBootstrapType::Sql,
|
|
DirectoryBootstrap::Oidc(_) => DirectoryBootstrapType::Oidc,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Dkim1Signature {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.auid {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Auid));
|
|
}
|
|
}
|
|
let value = &self.headers;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Headers));
|
|
}
|
|
}
|
|
let value = &self.private_key;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.third_party {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ThirdParty));
|
|
}
|
|
}
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
let value = &self.selector;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Selector));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.next_transition_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::NextTransitionAt, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
i.search(Property::DomainId, &self.domain_id);
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for Dkim1Signature {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.auid.pickle(out);
|
|
self.canonicalization.pickle(out);
|
|
self.expire.pickle(out);
|
|
self.headers.pickle(out);
|
|
self.private_key.pickle(out);
|
|
self.report.pickle(out);
|
|
self.third_party.pickle(out);
|
|
self.third_party_hash.pickle(out);
|
|
self.domain_id.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.selector.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.next_transition_at.pickle(out);
|
|
self.stage.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.auid = Pickle::unpickle(stream)?;
|
|
this.canonicalization = Pickle::unpickle(stream)?;
|
|
this.expire = Pickle::unpickle(stream)?;
|
|
this.headers = Pickle::unpickle(stream)?;
|
|
this.private_key = Pickle::unpickle(stream)?;
|
|
this.report = Pickle::unpickle(stream)?;
|
|
this.third_party = Pickle::unpickle(stream)?;
|
|
this.third_party_hash = Pickle::unpickle(stream)?;
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.selector = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.next_transition_at = Pickle::unpickle(stream)?;
|
|
this.stage = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Dkim1Signature {
|
|
fn default() -> Self {
|
|
Self {
|
|
auid: Default::default(),
|
|
canonicalization: DkimCanonicalization::RelaxedRelaxed,
|
|
expire: Default::default(),
|
|
headers: Map::new(vec![
|
|
"From".to_string(),
|
|
"To".to_string(),
|
|
"Date".to_string(),
|
|
"Subject".to_string(),
|
|
"Message-ID".to_string(),
|
|
]),
|
|
private_key: Default::default(),
|
|
report: true,
|
|
third_party: Default::default(),
|
|
third_party_hash: Default::default(),
|
|
domain_id: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
selector: Default::default(),
|
|
created_at: Default::default(),
|
|
next_transition_at: Default::default(),
|
|
stage: DkimRotationStage::Active,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Dkim1Signature {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(16);
|
|
map.insert_unchecked(Property::Auid, self.auid.into_value());
|
|
map.insert_unchecked(
|
|
Property::Canonicalization,
|
|
self.canonicalization.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Expire, self.expire.into_value());
|
|
map.insert_unchecked(Property::Headers, self.headers.into_value());
|
|
map.insert_unchecked(Property::PrivateKey, self.private_key.into_value());
|
|
map.insert_unchecked(Property::Report, self.report.into_value());
|
|
map.insert_unchecked(Property::ThirdParty, self.third_party.into_value());
|
|
map.insert_unchecked(Property::ThirdPartyHash, self.third_party_hash.into_value());
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Selector, self.selector.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(
|
|
Property::NextTransitionAt,
|
|
self.next_transition_at.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Stage, self.stage.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Dkim1Signature {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Auid) => self
|
|
.auid
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Canonicalization) => self.canonicalization.patch(pointer, value),
|
|
Some(Property::Expire) => self.expire.patch(pointer, value),
|
|
Some(Property::Headers) => self
|
|
.headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PrivateKey) => self.private_key.patch(pointer, value),
|
|
Some(Property::PublicKey) => pointer.assert_server_set(),
|
|
Some(Property::Report) => self.report.patch(pointer, value),
|
|
Some(Property::ThirdParty) => self
|
|
.third_party
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ThirdPartyHash) => self.third_party_hash.patch(pointer, value),
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Selector) => self
|
|
.selector
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::NextTransitionAt) => self.next_transition_at.patch(pointer, value),
|
|
Some(Property::Stage) => self.stage.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DkimManagement {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DkimManagement::Automatic(inner) => inner.validate(errors),
|
|
DkimManagement::Manual => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DkimManagement {
|
|
fn default() -> Self {
|
|
DkimManagement::Automatic(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for DkimManagement {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DkimManagement::Automatic(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DkimManagement::Manual => {
|
|
1u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(DkimManagement::Automatic),
|
|
1 => Some(DkimManagement::Manual),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DkimManagement {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DkimManagement::Automatic(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Automatic".into()));
|
|
obj
|
|
}
|
|
DkimManagement::Manual => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DkimManagement {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DkimManagementType::Automatic => {
|
|
*self = DkimManagement::Automatic(Default::default())
|
|
}
|
|
DkimManagementType::Manual => *self = DkimManagement::Manual,
|
|
}
|
|
}
|
|
match self {
|
|
DkimManagement::Automatic(inner) => inner.patch(pointer, value),
|
|
DkimManagement::Manual => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DkimManagement {
|
|
pub fn object_type(&self) -> DkimManagementType {
|
|
match self {
|
|
DkimManagement::Automatic(_) => DkimManagementType::Automatic,
|
|
DkimManagement::Manual => DkimManagementType::Manual,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DkimManagementProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.selector_template;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SelectorTemplate));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DkimManagementProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.algorithms.pickle(out);
|
|
self.selector_template.pickle(out);
|
|
self.rotate_after.pickle(out);
|
|
self.retire_after.pickle(out);
|
|
self.delete_after.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.algorithms = Pickle::unpickle(stream)?;
|
|
this.selector_template = Pickle::unpickle(stream)?;
|
|
this.rotate_after = Pickle::unpickle(stream)?;
|
|
this.retire_after = Pickle::unpickle(stream)?;
|
|
this.delete_after = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DkimManagementProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
algorithms: Map::new(vec![
|
|
DkimSignatureType::Dkim1Ed25519Sha256,
|
|
DkimSignatureType::Dkim1RsaSha256,
|
|
]),
|
|
selector_template: "v{version}-{algorithm}-{date-%Y%m%d}".to_string(),
|
|
rotate_after: Duration::from_millis(7776000000),
|
|
retire_after: Duration::from_millis(604800000),
|
|
delete_after: Duration::from_millis(2592000000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DkimManagementProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Algorithms, self.algorithms.into_value());
|
|
map.insert_unchecked(
|
|
Property::SelectorTemplate,
|
|
self.selector_template.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::RotateAfter, self.rotate_after.into_value());
|
|
map.insert_unchecked(Property::RetireAfter, self.retire_after.into_value());
|
|
map.insert_unchecked(Property::DeleteAfter, self.delete_after.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DkimManagementProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Algorithms) => self.algorithms.patch(pointer, value),
|
|
Some(Property::SelectorTemplate) => self
|
|
.selector_template
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::RotateAfter) => self.rotate_after.patch(pointer, value),
|
|
Some(Property::RetireAfter) => self.retire_after.patch(pointer, value),
|
|
Some(Property::DeleteAfter) => self.delete_after.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DkimReportSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DkimReportSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.from_address;
|
|
value.validate(errors);
|
|
let value = &self.from_name;
|
|
value.validate(errors);
|
|
let value = &self.send_frequency;
|
|
value.validate(errors);
|
|
let value = &self.dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.subject;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl DkimReportSettings {
|
|
pub fn ctx_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_address,
|
|
default: Some(Expression {
|
|
else_: "'noreply-dkim@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromAddress,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_name,
|
|
default: Some(Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromName,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_send_frequency(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.send_frequency,
|
|
default: Some(Expression {
|
|
else_: "[1, 1d]".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::SendFrequency,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DkimSignDomain,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_subject(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.subject,
|
|
default: Some(Expression {
|
|
else_: "'DKIM Authentication Failure Report'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Subject,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_from_address(),
|
|
self.ctx_from_name(),
|
|
self.ctx_send_frequency(),
|
|
self.ctx_dkim_sign_domain(),
|
|
self.ctx_subject(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for DkimReportSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.from_address.pickle(out);
|
|
self.from_name.pickle(out);
|
|
self.send_frequency.pickle(out);
|
|
self.dkim_sign_domain.pickle(out);
|
|
self.subject.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.from_address = Pickle::unpickle(stream)?;
|
|
this.from_name = Pickle::unpickle(stream)?;
|
|
this.send_frequency = Pickle::unpickle(stream)?;
|
|
this.dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DkimReportSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
from_address: Expression {
|
|
else_: "'noreply-dkim@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
from_name: Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
},
|
|
send_frequency: Expression {
|
|
else_: "[1, 1d]".to_string(),
|
|
..Default::default()
|
|
},
|
|
dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
subject: Expression {
|
|
else_: "'DKIM Authentication Failure Report'".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DkimReportSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::FromAddress, self.from_address.into_value());
|
|
map.insert_unchecked(Property::FromName, self.from_name.into_value());
|
|
map.insert_unchecked(Property::SendFrequency, self.send_frequency.into_value());
|
|
map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DkimReportSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::FromAddress) => self.from_address.patch(pointer, value),
|
|
Some(Property::FromName) => self.from_name.patch(pointer, value),
|
|
Some(Property::SendFrequency) => self.send_frequency.patch(pointer, value),
|
|
Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DkimSignature {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DkimSignature;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DkimSignature::Dkim1Ed25519Sha256(inner) => inner.validate(errors),
|
|
DkimSignature::Dkim1RsaSha256(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
DkimSignature::Dkim1Ed25519Sha256(object) => {
|
|
object.index(i);
|
|
}
|
|
DkimSignature::Dkim1RsaSha256(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DkimSignature {
|
|
fn default() -> Self {
|
|
DkimSignature::Dkim1Ed25519Sha256(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for DkimSignature {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DkimSignature::Dkim1Ed25519Sha256(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DkimSignature::Dkim1RsaSha256(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(DkimSignature::Dkim1Ed25519Sha256),
|
|
1 => Pickle::unpickle(stream).map(DkimSignature::Dkim1RsaSha256),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DkimSignature {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DkimSignature::Dkim1Ed25519Sha256(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Dkim1Ed25519Sha256".into()));
|
|
obj
|
|
}
|
|
DkimSignature::Dkim1RsaSha256(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Dkim1RsaSha256".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DkimSignature {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DkimSignatureType::Dkim1Ed25519Sha256 => {
|
|
*self = DkimSignature::Dkim1Ed25519Sha256(Default::default())
|
|
}
|
|
DkimSignatureType::Dkim1RsaSha256 => {
|
|
*self = DkimSignature::Dkim1RsaSha256(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
DkimSignature::Dkim1Ed25519Sha256(inner) => inner.patch(pointer, value),
|
|
DkimSignature::Dkim1RsaSha256(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DkimSignature {
|
|
pub fn object_type(&self) -> DkimSignatureType {
|
|
match self {
|
|
DkimSignature::Dkim1Ed25519Sha256(_) => DkimSignatureType::Dkim1Ed25519Sha256,
|
|
DkimSignature::Dkim1RsaSha256(_) => DkimSignatureType::Dkim1RsaSha256,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcDkimResult {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Domain));
|
|
}
|
|
let value = &self.selector;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Selector));
|
|
}
|
|
if let Some(value) = &self.human_result {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HumanResult));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcDkimResult {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.domain.pickle(out);
|
|
self.selector.pickle(out);
|
|
self.result.pickle(out);
|
|
self.human_result.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.domain = Pickle::unpickle(stream)?;
|
|
this.selector = Pickle::unpickle(stream)?;
|
|
this.result = Pickle::unpickle(stream)?;
|
|
this.human_result = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcDkimResult {
|
|
fn default() -> Self {
|
|
Self {
|
|
domain: Default::default(),
|
|
selector: Default::default(),
|
|
result: Default::default(),
|
|
human_result: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcDkimResult {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Domain, self.domain.into_value());
|
|
map.insert_unchecked(Property::Selector, self.selector.into_value());
|
|
map.insert_unchecked(Property::Result, self.result.into_value());
|
|
map.insert_unchecked(Property::HumanResult, self.human_result.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcDkimResult {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Domain) => self
|
|
.domain
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::Selector) => self.selector.patch(pointer, value),
|
|
Some(Property::Result) => self.result.patch(pointer, value),
|
|
Some(Property::HumanResult) => self.human_result.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcExtension {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.definition;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Definition));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcExtension {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.definition.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.definition = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcExtension {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
definition: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcExtension {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Definition, self.definition.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcExtension {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer, value),
|
|
Some(Property::Definition) => self.definition.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DmarcExternalReport {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DmarcExternalReport;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.report;
|
|
value.validate(errors);
|
|
let value = &self.from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::From));
|
|
}
|
|
let value = &self.subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Subject));
|
|
}
|
|
let value = &self.to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::To));
|
|
}
|
|
}
|
|
let value = &self.received_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ReceivedAt, value));
|
|
}
|
|
let value = &self.expires_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcExternalReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.report.pickle(out);
|
|
self.from.pickle(out);
|
|
self.subject.pickle(out);
|
|
self.to.pickle(out);
|
|
self.received_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.report = Pickle::unpickle(stream)?;
|
|
this.from = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
this.to = Pickle::unpickle(stream)?;
|
|
this.received_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcExternalReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
report: Default::default(),
|
|
from: Default::default(),
|
|
subject: Default::default(),
|
|
to: Default::default(),
|
|
received_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcExternalReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Report, self.report.into_value());
|
|
map.insert_unchecked(Property::From, self.from.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
map.insert_unchecked(Property::To, self.to.into_value());
|
|
map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcExternalReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Report) => self.report.patch(pointer, value),
|
|
Some(Property::From) => self
|
|
.from
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::To) => self
|
|
.to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::ReceivedAt) => self.received_at.patch(pointer, value),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DmarcInternalReport {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DmarcInternalReport;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.rua;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Rua));
|
|
}
|
|
}
|
|
let value = &self.report;
|
|
value.validate(errors);
|
|
let value = &self.domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Domain));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.deliver_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DeliverAt, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for DmarcInternalReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.rua.pickle(out);
|
|
self.policy_identifier.pickle(out);
|
|
self.report.pickle(out);
|
|
self.domain.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.deliver_at.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.rua = Pickle::unpickle(stream)?;
|
|
this.policy_identifier = Pickle::unpickle(stream)?;
|
|
this.report = Pickle::unpickle(stream)?;
|
|
this.domain = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.deliver_at = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcInternalReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
rua: Default::default(),
|
|
policy_identifier: 0u64,
|
|
report: Default::default(),
|
|
domain: Default::default(),
|
|
created_at: Default::default(),
|
|
deliver_at: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcInternalReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Rua, self.rua.into_value());
|
|
map.insert_unchecked(
|
|
Property::PolicyIdentifier,
|
|
self.policy_identifier.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Report, self.report.into_value());
|
|
map.insert_unchecked(Property::Domain, self.domain.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::DeliverAt, self.deliver_at.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcInternalReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Rua) => self
|
|
.rua
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::PolicyIdentifier) => self.policy_identifier.patch(pointer, value),
|
|
Some(Property::Report) => self.report.patch(pointer, value),
|
|
Some(Property::Domain) => self
|
|
.domain
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::CreatedAt) => self.created_at.patch(pointer, value),
|
|
Some(Property::DeliverAt) => self.deliver_at.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcPolicyOverrideReason {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.comment {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Comment));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcPolicyOverrideReason {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.override_type.pickle(out);
|
|
self.comment.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.override_type = Pickle::unpickle(stream)?;
|
|
this.comment = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcPolicyOverrideReason {
|
|
fn default() -> Self {
|
|
Self {
|
|
override_type: Default::default(),
|
|
comment: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcPolicyOverrideReason {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::OverrideType, self.override_type.into_value());
|
|
map.insert_unchecked(Property::Comment, self.comment.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcPolicyOverrideReason {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::OverrideType) => self.override_type.patch(pointer, value),
|
|
Some(Property::Comment) => self.comment.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcReport {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.org_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OrgName));
|
|
}
|
|
let value = &self.email;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Email));
|
|
}
|
|
if let Some(value) = &self.extra_contact_info {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ExtraContactInfo));
|
|
}
|
|
}
|
|
let value = &self.report_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReportId));
|
|
}
|
|
let value = &self.date_range_begin;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DateRangeBegin, value));
|
|
}
|
|
let value = &self.date_range_end;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DateRangeEnd, value));
|
|
}
|
|
let value = &self.errors;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Errors));
|
|
}
|
|
}
|
|
let value = &self.policy_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::PolicyDomain));
|
|
}
|
|
if let Some(value) = &self.policy_version {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::PolicyVersion));
|
|
}
|
|
}
|
|
let value = &self.records;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.extensions;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.version.pickle(out);
|
|
self.org_name.pickle(out);
|
|
self.email.pickle(out);
|
|
self.extra_contact_info.pickle(out);
|
|
self.report_id.pickle(out);
|
|
self.date_range_begin.pickle(out);
|
|
self.date_range_end.pickle(out);
|
|
self.errors.pickle(out);
|
|
self.policy_domain.pickle(out);
|
|
self.policy_version.pickle(out);
|
|
self.policy_adkim.pickle(out);
|
|
self.policy_aspf.pickle(out);
|
|
self.policy_disposition.pickle(out);
|
|
self.policy_subdomain_disposition.pickle(out);
|
|
self.policy_testing_mode.pickle(out);
|
|
self.policy_failure_reporting_options.pickle(out);
|
|
self.records.pickle(out);
|
|
self.extensions.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.version = Pickle::unpickle(stream)?;
|
|
this.org_name = Pickle::unpickle(stream)?;
|
|
this.email = Pickle::unpickle(stream)?;
|
|
this.extra_contact_info = Pickle::unpickle(stream)?;
|
|
this.report_id = Pickle::unpickle(stream)?;
|
|
this.date_range_begin = Pickle::unpickle(stream)?;
|
|
this.date_range_end = Pickle::unpickle(stream)?;
|
|
this.errors = Pickle::unpickle(stream)?;
|
|
this.policy_domain = Pickle::unpickle(stream)?;
|
|
this.policy_version = Pickle::unpickle(stream)?;
|
|
this.policy_adkim = Pickle::unpickle(stream)?;
|
|
this.policy_aspf = Pickle::unpickle(stream)?;
|
|
this.policy_disposition = Pickle::unpickle(stream)?;
|
|
this.policy_subdomain_disposition = Pickle::unpickle(stream)?;
|
|
this.policy_testing_mode = Pickle::unpickle(stream)?;
|
|
this.policy_failure_reporting_options = Pickle::unpickle(stream)?;
|
|
this.records = Pickle::unpickle(stream)?;
|
|
this.extensions = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
version: Float::new(1.0f64),
|
|
org_name: Default::default(),
|
|
email: Default::default(),
|
|
extra_contact_info: Default::default(),
|
|
report_id: Default::default(),
|
|
date_range_begin: Default::default(),
|
|
date_range_end: Default::default(),
|
|
errors: Default::default(),
|
|
policy_domain: Default::default(),
|
|
policy_version: Default::default(),
|
|
policy_adkim: Default::default(),
|
|
policy_aspf: Default::default(),
|
|
policy_disposition: Default::default(),
|
|
policy_subdomain_disposition: Default::default(),
|
|
policy_testing_mode: false,
|
|
policy_failure_reporting_options: Default::default(),
|
|
records: Default::default(),
|
|
extensions: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(20);
|
|
map.insert_unchecked(Property::Version, self.version.into_value());
|
|
map.insert_unchecked(Property::OrgName, self.org_name.into_value());
|
|
map.insert_unchecked(Property::Email, self.email.into_value());
|
|
map.insert_unchecked(
|
|
Property::ExtraContactInfo,
|
|
self.extra_contact_info.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ReportId, self.report_id.into_value());
|
|
map.insert_unchecked(Property::DateRangeBegin, self.date_range_begin.into_value());
|
|
map.insert_unchecked(Property::DateRangeEnd, self.date_range_end.into_value());
|
|
map.insert_unchecked(Property::Errors, self.errors.into_value());
|
|
map.insert_unchecked(Property::PolicyDomain, self.policy_domain.into_value());
|
|
map.insert_unchecked(Property::PolicyVersion, self.policy_version.into_value());
|
|
map.insert_unchecked(Property::PolicyAdkim, self.policy_adkim.into_value());
|
|
map.insert_unchecked(Property::PolicyAspf, self.policy_aspf.into_value());
|
|
map.insert_unchecked(
|
|
Property::PolicyDisposition,
|
|
self.policy_disposition.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PolicySubdomainDisposition,
|
|
self.policy_subdomain_disposition.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PolicyTestingMode,
|
|
self.policy_testing_mode.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PolicyFailureReportingOptions,
|
|
self.policy_failure_reporting_options.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Records, self.records.into_value());
|
|
map.insert_unchecked(Property::Extensions, self.extensions.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Version) => self.version.patch(pointer, value),
|
|
Some(Property::OrgName) => self.org_name.patch(pointer, value),
|
|
Some(Property::Email) => self
|
|
.email
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::ExtraContactInfo) => self.extra_contact_info.patch(pointer, value),
|
|
Some(Property::ReportId) => self.report_id.patch(pointer, value),
|
|
Some(Property::DateRangeBegin) => self.date_range_begin.patch(pointer, value),
|
|
Some(Property::DateRangeEnd) => self.date_range_end.patch(pointer, value),
|
|
Some(Property::Errors) => self.errors.patch(pointer, value),
|
|
Some(Property::PolicyDomain) => self.policy_domain.patch(pointer, value),
|
|
Some(Property::PolicyVersion) => self.policy_version.patch(pointer, value),
|
|
Some(Property::PolicyAdkim) => self.policy_adkim.patch(pointer, value),
|
|
Some(Property::PolicyAspf) => self.policy_aspf.patch(pointer, value),
|
|
Some(Property::PolicyDisposition) => self.policy_disposition.patch(pointer, value),
|
|
Some(Property::PolicySubdomainDisposition) => {
|
|
self.policy_subdomain_disposition.patch(pointer, value)
|
|
}
|
|
Some(Property::PolicyTestingMode) => self.policy_testing_mode.patch(pointer, value),
|
|
Some(Property::PolicyFailureReportingOptions) => {
|
|
self.policy_failure_reporting_options.patch(pointer, value)
|
|
}
|
|
Some(Property::Records) => self.records.patch(pointer, value),
|
|
Some(Property::Extensions) => self.extensions.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcReportRecord {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.source_ip {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::SourceIp, value));
|
|
}
|
|
}
|
|
let value = &self.policy_override_reasons;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.envelope_to {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EnvelopeTo));
|
|
}
|
|
}
|
|
let value = &self.envelope_from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EnvelopeFrom));
|
|
}
|
|
let value = &self.header_from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HeaderFrom));
|
|
}
|
|
let value = &self.dkim_results;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.spf_results;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.extensions;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcReportRecord {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.source_ip.pickle(out);
|
|
self.count.pickle(out);
|
|
self.evaluated_disposition.pickle(out);
|
|
self.evaluated_dkim.pickle(out);
|
|
self.evaluated_spf.pickle(out);
|
|
self.policy_override_reasons.pickle(out);
|
|
self.envelope_to.pickle(out);
|
|
self.envelope_from.pickle(out);
|
|
self.header_from.pickle(out);
|
|
self.dkim_results.pickle(out);
|
|
self.spf_results.pickle(out);
|
|
self.extensions.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.source_ip = Pickle::unpickle(stream)?;
|
|
this.count = Pickle::unpickle(stream)?;
|
|
this.evaluated_disposition = Pickle::unpickle(stream)?;
|
|
this.evaluated_dkim = Pickle::unpickle(stream)?;
|
|
this.evaluated_spf = Pickle::unpickle(stream)?;
|
|
this.policy_override_reasons = Pickle::unpickle(stream)?;
|
|
this.envelope_to = Pickle::unpickle(stream)?;
|
|
this.envelope_from = Pickle::unpickle(stream)?;
|
|
this.header_from = Pickle::unpickle(stream)?;
|
|
this.dkim_results = Pickle::unpickle(stream)?;
|
|
this.spf_results = Pickle::unpickle(stream)?;
|
|
this.extensions = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcReportRecord {
|
|
fn default() -> Self {
|
|
Self {
|
|
source_ip: Default::default(),
|
|
count: 0u64,
|
|
evaluated_disposition: Default::default(),
|
|
evaluated_dkim: Default::default(),
|
|
evaluated_spf: Default::default(),
|
|
policy_override_reasons: Default::default(),
|
|
envelope_to: Default::default(),
|
|
envelope_from: Default::default(),
|
|
header_from: Default::default(),
|
|
dkim_results: Default::default(),
|
|
spf_results: Default::default(),
|
|
extensions: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcReportRecord {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::SourceIp, self.source_ip.into_value());
|
|
map.insert_unchecked(Property::Count, self.count.into_value());
|
|
map.insert_unchecked(
|
|
Property::EvaluatedDisposition,
|
|
self.evaluated_disposition.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::EvaluatedDkim, self.evaluated_dkim.into_value());
|
|
map.insert_unchecked(Property::EvaluatedSpf, self.evaluated_spf.into_value());
|
|
map.insert_unchecked(
|
|
Property::PolicyOverrideReasons,
|
|
self.policy_override_reasons.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::EnvelopeTo, self.envelope_to.into_value());
|
|
map.insert_unchecked(Property::EnvelopeFrom, self.envelope_from.into_value());
|
|
map.insert_unchecked(Property::HeaderFrom, self.header_from.into_value());
|
|
map.insert_unchecked(Property::DkimResults, self.dkim_results.into_value());
|
|
map.insert_unchecked(Property::SpfResults, self.spf_results.into_value());
|
|
map.insert_unchecked(Property::Extensions, self.extensions.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcReportRecord {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::SourceIp) => self.source_ip.patch(pointer, value),
|
|
Some(Property::Count) => self.count.patch(pointer, value),
|
|
Some(Property::EvaluatedDisposition) => {
|
|
self.evaluated_disposition.patch(pointer, value)
|
|
}
|
|
Some(Property::EvaluatedDkim) => self.evaluated_dkim.patch(pointer, value),
|
|
Some(Property::EvaluatedSpf) => self.evaluated_spf.patch(pointer, value),
|
|
Some(Property::PolicyOverrideReasons) => {
|
|
self.policy_override_reasons.patch(pointer, value)
|
|
}
|
|
Some(Property::EnvelopeTo) => self.envelope_to.patch(pointer, value),
|
|
Some(Property::EnvelopeFrom) => self.envelope_from.patch(pointer, value),
|
|
Some(Property::HeaderFrom) => self.header_from.patch(pointer, value),
|
|
Some(Property::DkimResults) => self.dkim_results.patch(pointer, value),
|
|
Some(Property::SpfResults) => self.spf_results.patch(pointer, value),
|
|
Some(Property::Extensions) => self.extensions.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DmarcReportSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DmarcReportSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.aggregate_contact_info;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_from_address;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_from_name;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_max_report_size;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_org_name;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_send_frequency;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.aggregate_subject;
|
|
value.validate(errors);
|
|
let value = &self.failure_from_address;
|
|
value.validate(errors);
|
|
let value = &self.failure_from_name;
|
|
value.validate(errors);
|
|
let value = &self.failure_send_frequency;
|
|
value.validate(errors);
|
|
let value = &self.failure_dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.failure_subject;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl DmarcReportSettings {
|
|
pub fn ctx_aggregate_contact_info(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_contact_info,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateContactInfo,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_from_address,
|
|
default: Some(Expression {
|
|
else_: "'noreply-dmarc@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateFromAddress,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_from_name,
|
|
default: Some(Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateFromName,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_max_report_size(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_max_report_size,
|
|
default: Some(Expression {
|
|
else_: "5242880".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateMaxReportSize,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_org_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_org_name,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateOrgName,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_send_frequency(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_send_frequency,
|
|
default: Some(Expression {
|
|
else_: "daily".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateSendFrequency,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: MTA_AGGREGATE_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateDkimSignDomain,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_aggregate_subject(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.aggregate_subject,
|
|
default: Some(Expression {
|
|
else_: "'DMARC Aggregate Report'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AggregateSubject,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_failure_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.failure_from_address,
|
|
default: Some(Expression {
|
|
else_: "'noreply-dmarc@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FailureFromAddress,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_failure_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.failure_from_name,
|
|
default: Some(Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FailureFromName,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_failure_send_frequency(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.failure_send_frequency,
|
|
default: Some(Expression {
|
|
else_: "[1, 1d]".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FailureSendFrequency,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_failure_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.failure_dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FailureDkimSignDomain,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_failure_subject(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.failure_subject,
|
|
default: Some(Expression {
|
|
else_: "'DMARC Authentication Failure Report'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FailureSubject,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_aggregate_contact_info(),
|
|
self.ctx_aggregate_from_address(),
|
|
self.ctx_aggregate_from_name(),
|
|
self.ctx_aggregate_max_report_size(),
|
|
self.ctx_aggregate_org_name(),
|
|
self.ctx_aggregate_send_frequency(),
|
|
self.ctx_aggregate_dkim_sign_domain(),
|
|
self.ctx_aggregate_subject(),
|
|
self.ctx_failure_from_address(),
|
|
self.ctx_failure_from_name(),
|
|
self.ctx_failure_send_frequency(),
|
|
self.ctx_failure_dkim_sign_domain(),
|
|
self.ctx_failure_subject(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcReportSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.aggregate_contact_info.pickle(out);
|
|
self.aggregate_from_address.pickle(out);
|
|
self.aggregate_from_name.pickle(out);
|
|
self.aggregate_max_report_size.pickle(out);
|
|
self.aggregate_org_name.pickle(out);
|
|
self.aggregate_send_frequency.pickle(out);
|
|
self.aggregate_dkim_sign_domain.pickle(out);
|
|
self.aggregate_subject.pickle(out);
|
|
self.failure_from_address.pickle(out);
|
|
self.failure_from_name.pickle(out);
|
|
self.failure_send_frequency.pickle(out);
|
|
self.failure_dkim_sign_domain.pickle(out);
|
|
self.failure_subject.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.aggregate_contact_info = Pickle::unpickle(stream)?;
|
|
this.aggregate_from_address = Pickle::unpickle(stream)?;
|
|
this.aggregate_from_name = Pickle::unpickle(stream)?;
|
|
this.aggregate_max_report_size = Pickle::unpickle(stream)?;
|
|
this.aggregate_org_name = Pickle::unpickle(stream)?;
|
|
this.aggregate_send_frequency = Pickle::unpickle(stream)?;
|
|
this.aggregate_dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.aggregate_subject = Pickle::unpickle(stream)?;
|
|
this.failure_from_address = Pickle::unpickle(stream)?;
|
|
this.failure_from_name = Pickle::unpickle(stream)?;
|
|
this.failure_send_frequency = Pickle::unpickle(stream)?;
|
|
this.failure_dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.failure_subject = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcReportSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
aggregate_contact_info: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_from_address: Expression {
|
|
else_: "'noreply-dmarc@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_from_name: Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_max_report_size: Expression {
|
|
else_: "5242880".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_org_name: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_send_frequency: Expression {
|
|
else_: "daily".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
aggregate_subject: Expression {
|
|
else_: "'DMARC Aggregate Report'".to_string(),
|
|
..Default::default()
|
|
},
|
|
failure_from_address: Expression {
|
|
else_: "'noreply-dmarc@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
failure_from_name: Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
},
|
|
failure_send_frequency: Expression {
|
|
else_: "[1, 1d]".to_string(),
|
|
..Default::default()
|
|
},
|
|
failure_dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
failure_subject: Expression {
|
|
else_: "'DMARC Authentication Failure Report'".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcReportSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(
|
|
Property::AggregateContactInfo,
|
|
self.aggregate_contact_info.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateFromAddress,
|
|
self.aggregate_from_address.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateFromName,
|
|
self.aggregate_from_name.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateMaxReportSize,
|
|
self.aggregate_max_report_size.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateOrgName,
|
|
self.aggregate_org_name.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateSendFrequency,
|
|
self.aggregate_send_frequency.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateDkimSignDomain,
|
|
self.aggregate_dkim_sign_domain.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AggregateSubject,
|
|
self.aggregate_subject.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FailureFromAddress,
|
|
self.failure_from_address.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FailureFromName,
|
|
self.failure_from_name.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FailureSendFrequency,
|
|
self.failure_send_frequency.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FailureDkimSignDomain,
|
|
self.failure_dkim_sign_domain.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::FailureSubject, self.failure_subject.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcReportSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AggregateContactInfo) => {
|
|
self.aggregate_contact_info.patch(pointer, value)
|
|
}
|
|
Some(Property::AggregateFromAddress) => {
|
|
self.aggregate_from_address.patch(pointer, value)
|
|
}
|
|
Some(Property::AggregateFromName) => self.aggregate_from_name.patch(pointer, value),
|
|
Some(Property::AggregateMaxReportSize) => {
|
|
self.aggregate_max_report_size.patch(pointer, value)
|
|
}
|
|
Some(Property::AggregateOrgName) => self.aggregate_org_name.patch(pointer, value),
|
|
Some(Property::AggregateSendFrequency) => {
|
|
self.aggregate_send_frequency.patch(pointer, value)
|
|
}
|
|
Some(Property::AggregateDkimSignDomain) => {
|
|
self.aggregate_dkim_sign_domain.patch(pointer, value)
|
|
}
|
|
Some(Property::AggregateSubject) => self.aggregate_subject.patch(pointer, value),
|
|
Some(Property::FailureFromAddress) => self.failure_from_address.patch(pointer, value),
|
|
Some(Property::FailureFromName) => self.failure_from_name.patch(pointer, value),
|
|
Some(Property::FailureSendFrequency) => {
|
|
self.failure_send_frequency.patch(pointer, value)
|
|
}
|
|
Some(Property::FailureDkimSignDomain) => {
|
|
self.failure_dkim_sign_domain.patch(pointer, value)
|
|
}
|
|
Some(Property::FailureSubject) => self.failure_subject.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcSpfResult {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Domain));
|
|
}
|
|
if let Some(value) = &self.human_result {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HumanResult));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcSpfResult {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.domain.pickle(out);
|
|
self.scope.pickle(out);
|
|
self.result.pickle(out);
|
|
self.human_result.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.domain = Pickle::unpickle(stream)?;
|
|
this.scope = Pickle::unpickle(stream)?;
|
|
this.result = Pickle::unpickle(stream)?;
|
|
this.human_result = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcSpfResult {
|
|
fn default() -> Self {
|
|
Self {
|
|
domain: Default::default(),
|
|
scope: Default::default(),
|
|
result: Default::default(),
|
|
human_result: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcSpfResult {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Domain, self.domain.into_value());
|
|
map.insert_unchecked(Property::Scope, self.scope.into_value());
|
|
map.insert_unchecked(Property::Result, self.result.into_value());
|
|
map.insert_unchecked(Property::HumanResult, self.human_result.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcSpfResult {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Domain) => self
|
|
.domain
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::Scope) => self.scope.patch(pointer, value),
|
|
Some(Property::Result) => self.result.patch(pointer, value),
|
|
Some(Property::HumanResult) => self.human_result.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcTroubleshoot {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.remote_ip;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::RemoteIp, value));
|
|
}
|
|
let value = &self.ehlo_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EhloDomain));
|
|
}
|
|
let value = &self.mail_from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MailFrom));
|
|
}
|
|
if let Some(value) = &self.message {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Message));
|
|
}
|
|
}
|
|
let value = &self.spf_ehlo_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SpfEhloDomain));
|
|
}
|
|
let value = &self.spf_ehlo_result;
|
|
value.validate(errors);
|
|
let value = &self.spf_mail_from_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SpfMailFromDomain));
|
|
}
|
|
let value = &self.spf_mail_from_result;
|
|
value.validate(errors);
|
|
let value = &self.ip_rev_result;
|
|
value.validate(errors);
|
|
let value = &self.ip_rev_ptr;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::IpRevPtr));
|
|
}
|
|
}
|
|
let value = &self.dkim_results;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.arc_result;
|
|
value.validate(errors);
|
|
let value = &self.dmarc_result;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcTroubleshoot {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.remote_ip.pickle(out);
|
|
self.ehlo_domain.pickle(out);
|
|
self.mail_from.pickle(out);
|
|
self.message.pickle(out);
|
|
self.spf_ehlo_domain.pickle(out);
|
|
self.spf_ehlo_result.pickle(out);
|
|
self.spf_mail_from_domain.pickle(out);
|
|
self.spf_mail_from_result.pickle(out);
|
|
self.ip_rev_result.pickle(out);
|
|
self.ip_rev_ptr.pickle(out);
|
|
self.dkim_results.pickle(out);
|
|
self.dkim_pass.pickle(out);
|
|
self.arc_result.pickle(out);
|
|
self.dmarc_result.pickle(out);
|
|
self.dmarc_pass.pickle(out);
|
|
self.dmarc_policy.pickle(out);
|
|
self.elapsed.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.remote_ip = Pickle::unpickle(stream)?;
|
|
this.ehlo_domain = Pickle::unpickle(stream)?;
|
|
this.mail_from = Pickle::unpickle(stream)?;
|
|
this.message = Pickle::unpickle(stream)?;
|
|
this.spf_ehlo_domain = Pickle::unpickle(stream)?;
|
|
this.spf_ehlo_result = Pickle::unpickle(stream)?;
|
|
this.spf_mail_from_domain = Pickle::unpickle(stream)?;
|
|
this.spf_mail_from_result = Pickle::unpickle(stream)?;
|
|
this.ip_rev_result = Pickle::unpickle(stream)?;
|
|
this.ip_rev_ptr = Pickle::unpickle(stream)?;
|
|
this.dkim_results = Pickle::unpickle(stream)?;
|
|
this.dkim_pass = Pickle::unpickle(stream)?;
|
|
this.arc_result = Pickle::unpickle(stream)?;
|
|
this.dmarc_result = Pickle::unpickle(stream)?;
|
|
this.dmarc_pass = Pickle::unpickle(stream)?;
|
|
this.dmarc_policy = Pickle::unpickle(stream)?;
|
|
this.elapsed = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcTroubleshoot {
|
|
fn default() -> Self {
|
|
Self {
|
|
remote_ip: Default::default(),
|
|
ehlo_domain: Default::default(),
|
|
mail_from: Default::default(),
|
|
message: Default::default(),
|
|
spf_ehlo_domain: Default::default(),
|
|
spf_ehlo_result: Default::default(),
|
|
spf_mail_from_domain: Default::default(),
|
|
spf_mail_from_result: Default::default(),
|
|
ip_rev_result: Default::default(),
|
|
ip_rev_ptr: Default::default(),
|
|
dkim_results: Default::default(),
|
|
dkim_pass: false,
|
|
arc_result: Default::default(),
|
|
dmarc_result: Default::default(),
|
|
dmarc_pass: false,
|
|
dmarc_policy: Default::default(),
|
|
elapsed: Duration::from_millis(0),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcTroubleshoot {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(19);
|
|
map.insert_unchecked(Property::RemoteIp, self.remote_ip.into_value());
|
|
map.insert_unchecked(Property::EhloDomain, self.ehlo_domain.into_value());
|
|
map.insert_unchecked(Property::MailFrom, self.mail_from.into_value());
|
|
map.insert_unchecked(Property::Message, self.message.into_value());
|
|
map.insert_unchecked(Property::SpfEhloDomain, self.spf_ehlo_domain.into_value());
|
|
map.insert_unchecked(Property::SpfEhloResult, self.spf_ehlo_result.into_value());
|
|
map.insert_unchecked(
|
|
Property::SpfMailFromDomain,
|
|
self.spf_mail_from_domain.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::SpfMailFromResult,
|
|
self.spf_mail_from_result.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::IpRevResult, self.ip_rev_result.into_value());
|
|
map.insert_unchecked(Property::IpRevPtr, self.ip_rev_ptr.into_value());
|
|
map.insert_unchecked(Property::DkimResults, self.dkim_results.into_value());
|
|
map.insert_unchecked(Property::DkimPass, self.dkim_pass.into_value());
|
|
map.insert_unchecked(Property::ArcResult, self.arc_result.into_value());
|
|
map.insert_unchecked(Property::DmarcResult, self.dmarc_result.into_value());
|
|
map.insert_unchecked(Property::DmarcPass, self.dmarc_pass.into_value());
|
|
map.insert_unchecked(Property::DmarcPolicy, self.dmarc_policy.into_value());
|
|
map.insert_unchecked(Property::Elapsed, self.elapsed.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcTroubleshoot {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::RemoteIp) => self.remote_ip.patch(pointer, value),
|
|
Some(Property::EhloDomain) => self.ehlo_domain.patch(pointer, value),
|
|
Some(Property::MailFrom) => self
|
|
.mail_from
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Message) => self.message.patch(pointer, value),
|
|
Some(Property::SpfEhloDomain) => self.spf_ehlo_domain.patch(pointer, value),
|
|
Some(Property::SpfEhloResult) => pointer.assert_server_set(),
|
|
Some(Property::SpfMailFromDomain) => self.spf_mail_from_domain.patch(pointer, value),
|
|
Some(Property::SpfMailFromResult) => pointer.assert_server_set(),
|
|
Some(Property::IpRevResult) => pointer.assert_server_set(),
|
|
Some(Property::IpRevPtr) => pointer.assert_server_set(),
|
|
Some(Property::DkimResults) => pointer.assert_server_set(),
|
|
Some(Property::DkimPass) => pointer.assert_server_set(),
|
|
Some(Property::ArcResult) => pointer.assert_server_set(),
|
|
Some(Property::DmarcResult) => pointer.assert_server_set(),
|
|
Some(Property::DmarcPass) => pointer.assert_server_set(),
|
|
Some(Property::DmarcPolicy) => pointer.assert_server_set(),
|
|
Some(Property::Elapsed) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcTroubleshootAuthResult {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DmarcTroubleshootAuthResult::Pass => true,
|
|
DmarcTroubleshootAuthResult::Fail(inner) => inner.validate(errors),
|
|
DmarcTroubleshootAuthResult::SoftFail(inner) => inner.validate(errors),
|
|
DmarcTroubleshootAuthResult::TempError(inner) => inner.validate(errors),
|
|
DmarcTroubleshootAuthResult::PermError(inner) => inner.validate(errors),
|
|
DmarcTroubleshootAuthResult::Neutral(inner) => inner.validate(errors),
|
|
DmarcTroubleshootAuthResult::None => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcTroubleshootAuthResult {
|
|
fn default() -> Self {
|
|
DmarcTroubleshootAuthResult::Pass
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcTroubleshootAuthResult {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DmarcTroubleshootAuthResult::Pass => {
|
|
0u16.pickle(out);
|
|
}
|
|
DmarcTroubleshootAuthResult::Fail(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DmarcTroubleshootAuthResult::SoftFail(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DmarcTroubleshootAuthResult::TempError(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DmarcTroubleshootAuthResult::PermError(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DmarcTroubleshootAuthResult::Neutral(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DmarcTroubleshootAuthResult::None => {
|
|
6u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(DmarcTroubleshootAuthResult::Pass),
|
|
1 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::Fail),
|
|
2 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::SoftFail),
|
|
3 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::TempError),
|
|
4 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::PermError),
|
|
5 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::Neutral),
|
|
6 => Some(DmarcTroubleshootAuthResult::None),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcTroubleshootAuthResult {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DmarcTroubleshootAuthResult::Pass => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Pass".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
DmarcTroubleshootAuthResult::Fail(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Fail".into()));
|
|
obj
|
|
}
|
|
DmarcTroubleshootAuthResult::SoftFail(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("SoftFail".into()));
|
|
obj
|
|
}
|
|
DmarcTroubleshootAuthResult::TempError(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("TempError".into()));
|
|
obj
|
|
}
|
|
DmarcTroubleshootAuthResult::PermError(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PermError".into()));
|
|
obj
|
|
}
|
|
DmarcTroubleshootAuthResult::Neutral(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Neutral".into()));
|
|
obj
|
|
}
|
|
DmarcTroubleshootAuthResult::None => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("None".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DmarcTroubleshootAuthResult {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DmarcTroubleshootAuthResultType::Pass => *self = DmarcTroubleshootAuthResult::Pass,
|
|
DmarcTroubleshootAuthResultType::Fail => {
|
|
*self = DmarcTroubleshootAuthResult::Fail(Default::default())
|
|
}
|
|
DmarcTroubleshootAuthResultType::SoftFail => {
|
|
*self = DmarcTroubleshootAuthResult::SoftFail(Default::default())
|
|
}
|
|
DmarcTroubleshootAuthResultType::TempError => {
|
|
*self = DmarcTroubleshootAuthResult::TempError(Default::default())
|
|
}
|
|
DmarcTroubleshootAuthResultType::PermError => {
|
|
*self = DmarcTroubleshootAuthResult::PermError(Default::default())
|
|
}
|
|
DmarcTroubleshootAuthResultType::Neutral => {
|
|
*self = DmarcTroubleshootAuthResult::Neutral(Default::default())
|
|
}
|
|
DmarcTroubleshootAuthResultType::None => *self = DmarcTroubleshootAuthResult::None,
|
|
}
|
|
}
|
|
match self {
|
|
DmarcTroubleshootAuthResult::Pass => pointer.assert_eof(),
|
|
DmarcTroubleshootAuthResult::Fail(inner) => inner.patch(pointer, value),
|
|
DmarcTroubleshootAuthResult::SoftFail(inner) => inner.patch(pointer, value),
|
|
DmarcTroubleshootAuthResult::TempError(inner) => inner.patch(pointer, value),
|
|
DmarcTroubleshootAuthResult::PermError(inner) => inner.patch(pointer, value),
|
|
DmarcTroubleshootAuthResult::Neutral(inner) => inner.patch(pointer, value),
|
|
DmarcTroubleshootAuthResult::None => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcTroubleshootAuthResult {
|
|
pub fn object_type(&self) -> DmarcTroubleshootAuthResultType {
|
|
match self {
|
|
DmarcTroubleshootAuthResult::Pass => DmarcTroubleshootAuthResultType::Pass,
|
|
DmarcTroubleshootAuthResult::Fail(_) => DmarcTroubleshootAuthResultType::Fail,
|
|
DmarcTroubleshootAuthResult::SoftFail(_) => DmarcTroubleshootAuthResultType::SoftFail,
|
|
DmarcTroubleshootAuthResult::TempError(_) => DmarcTroubleshootAuthResultType::TempError,
|
|
DmarcTroubleshootAuthResult::PermError(_) => DmarcTroubleshootAuthResultType::PermError,
|
|
DmarcTroubleshootAuthResult::Neutral(_) => DmarcTroubleshootAuthResultType::Neutral,
|
|
DmarcTroubleshootAuthResult::None => DmarcTroubleshootAuthResultType::None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DmarcTroubleshootDetails {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.details {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Details));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DmarcTroubleshootDetails {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.details.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.details = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DmarcTroubleshootDetails {
|
|
fn default() -> Self {
|
|
Self {
|
|
details: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DmarcTroubleshootDetails {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Details, self.details.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DmarcTroubleshootDetails {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Details) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsCustomResolver {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.address;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Address, value));
|
|
}
|
|
let value = &self.port;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsCustomResolver {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.protocol.pickle(out);
|
|
self.address.pickle(out);
|
|
self.port.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.protocol = Pickle::unpickle(stream)?;
|
|
this.address = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsCustomResolver {
|
|
fn default() -> Self {
|
|
Self {
|
|
protocol: DnsResolverProtocol::Udp,
|
|
address: IpAddr::from_str("127.0.0.1").unwrap(),
|
|
port: 53u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsCustomResolver {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Protocol, self.protocol.into_value());
|
|
map.insert_unchecked(Property::Address, self.address.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsCustomResolver {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Protocol) => self.protocol.patch(pointer, value),
|
|
Some(Property::Address) => self
|
|
.address
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsManagement {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DnsManagement::Manual => true,
|
|
DnsManagement::Automatic(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
DnsManagement::Manual => {}
|
|
DnsManagement::Automatic(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DnsManagement {
|
|
fn default() -> Self {
|
|
DnsManagement::Manual
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsManagement {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DnsManagement::Manual => {
|
|
0u16.pickle(out);
|
|
}
|
|
DnsManagement::Automatic(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(DnsManagement::Manual),
|
|
1 => Pickle::unpickle(stream).map(DnsManagement::Automatic),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsManagement {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DnsManagement::Manual => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
DnsManagement::Automatic(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Automatic".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DnsManagement {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DnsManagementType::Manual => *self = DnsManagement::Manual,
|
|
DnsManagementType::Automatic => {
|
|
*self = DnsManagement::Automatic(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
DnsManagement::Manual => pointer.assert_eof(),
|
|
DnsManagement::Automatic(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsManagement {
|
|
pub fn object_type(&self) -> DnsManagementType {
|
|
match self {
|
|
DnsManagement::Manual => DnsManagementType::Manual,
|
|
DnsManagement::Automatic(_) => DnsManagementType::Automatic,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsManagementProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.dns_server_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DnsServerId));
|
|
}
|
|
if let Some(value) = &self.origin {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Origin));
|
|
}
|
|
}
|
|
let value = &self.publish_records;
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::PublishRecords, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::DnsServer, self.dns_server_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsManagementProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.dns_server_id.pickle(out);
|
|
self.origin.pickle(out);
|
|
self.publish_records.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.dns_server_id = Pickle::unpickle(stream)?;
|
|
this.origin = Pickle::unpickle(stream)?;
|
|
this.publish_records = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsManagementProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
dns_server_id: Default::default(),
|
|
origin: Default::default(),
|
|
publish_records: Map::new(vec![
|
|
DnsRecordType::Dkim,
|
|
DnsRecordType::Spf,
|
|
DnsRecordType::Mx,
|
|
DnsRecordType::Dmarc,
|
|
DnsRecordType::Srv,
|
|
DnsRecordType::MtaSts,
|
|
DnsRecordType::TlsRpt,
|
|
DnsRecordType::Caa,
|
|
DnsRecordType::AutoConfig,
|
|
DnsRecordType::AutoConfigLegacy,
|
|
DnsRecordType::AutoDiscover,
|
|
]),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsManagementProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::DnsServerId, self.dns_server_id.into_value());
|
|
map.insert_unchecked(Property::Origin, self.origin.into_value());
|
|
map.insert_unchecked(Property::PublishRecords, self.publish_records.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsManagementProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DnsServerId) => self.dns_server_id.patch(pointer, value),
|
|
Some(Property::Origin) => self
|
|
.origin
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PublishRecords) => self.publish_records.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DnsResolver {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DnsResolver;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DnsResolver::System(inner) => inner.validate(errors),
|
|
DnsResolver::Custom(inner) => inner.validate(errors),
|
|
DnsResolver::Cloudflare(inner) => inner.validate(errors),
|
|
DnsResolver::Quad9(inner) => inner.validate(errors),
|
|
DnsResolver::Google(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for DnsResolver {
|
|
fn default() -> Self {
|
|
DnsResolver::System(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsResolver {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DnsResolver::System(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsResolver::Custom(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsResolver::Cloudflare(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsResolver::Quad9(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsResolver::Google(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(DnsResolver::System),
|
|
1 => Pickle::unpickle(stream).map(DnsResolver::Custom),
|
|
2 => Pickle::unpickle(stream).map(DnsResolver::Cloudflare),
|
|
3 => Pickle::unpickle(stream).map(DnsResolver::Quad9),
|
|
4 => Pickle::unpickle(stream).map(DnsResolver::Google),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsResolver {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DnsResolver::System(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("System".into()));
|
|
obj
|
|
}
|
|
DnsResolver::Custom(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Custom".into()));
|
|
obj
|
|
}
|
|
DnsResolver::Cloudflare(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Cloudflare".into()));
|
|
obj
|
|
}
|
|
DnsResolver::Quad9(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Quad9".into()));
|
|
obj
|
|
}
|
|
DnsResolver::Google(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Google".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DnsResolver {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DnsResolverType::System => *self = DnsResolver::System(Default::default()),
|
|
DnsResolverType::Custom => *self = DnsResolver::Custom(Default::default()),
|
|
DnsResolverType::Cloudflare => *self = DnsResolver::Cloudflare(Default::default()),
|
|
DnsResolverType::Quad9 => *self = DnsResolver::Quad9(Default::default()),
|
|
DnsResolverType::Google => *self = DnsResolver::Google(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
DnsResolver::System(inner) => inner.patch(pointer, value),
|
|
DnsResolver::Custom(inner) => inner.patch(pointer, value),
|
|
DnsResolver::Cloudflare(inner) => inner.patch(pointer, value),
|
|
DnsResolver::Quad9(inner) => inner.patch(pointer, value),
|
|
DnsResolver::Google(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsResolver {
|
|
pub fn object_type(&self) -> DnsResolverType {
|
|
match self {
|
|
DnsResolver::System(_) => DnsResolverType::System,
|
|
DnsResolver::Custom(_) => DnsResolverType::Custom,
|
|
DnsResolver::Cloudflare(_) => DnsResolverType::Cloudflare,
|
|
DnsResolver::Quad9(_) => DnsResolverType::Quad9,
|
|
DnsResolver::Google(_) => DnsResolverType::Google,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsResolverCommon {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsResolverCommon {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.attempts.pickle(out);
|
|
self.concurrency.pickle(out);
|
|
self.enable_edns.pickle(out);
|
|
self.preserve_intermediates.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.tcp_on_error.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.attempts = Pickle::unpickle(stream)?;
|
|
this.concurrency = Pickle::unpickle(stream)?;
|
|
this.enable_edns = Pickle::unpickle(stream)?;
|
|
this.preserve_intermediates = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.tcp_on_error = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsResolverCommon {
|
|
fn default() -> Self {
|
|
Self {
|
|
attempts: 2u64,
|
|
concurrency: 2u64,
|
|
enable_edns: true,
|
|
preserve_intermediates: true,
|
|
timeout: Duration::from_millis(5000),
|
|
tcp_on_error: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsResolverCommon {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Attempts, self.attempts.into_value());
|
|
map.insert_unchecked(Property::Concurrency, self.concurrency.into_value());
|
|
map.insert_unchecked(Property::EnableEdns, self.enable_edns.into_value());
|
|
map.insert_unchecked(
|
|
Property::PreserveIntermediates,
|
|
self.preserve_intermediates.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::TcpOnError, self.tcp_on_error.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsResolverCommon {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Attempts) => self.attempts.patch(pointer, value),
|
|
Some(Property::Concurrency) => self.concurrency.patch(pointer, value),
|
|
Some(Property::EnableEdns) => self.enable_edns.patch(pointer, value),
|
|
Some(Property::PreserveIntermediates) => {
|
|
self.preserve_intermediates.patch(pointer, value)
|
|
}
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::TcpOnError) => self.tcp_on_error.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsResolverCustom {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.servers;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Servers, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsResolverCustom {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.servers.pickle(out);
|
|
self.attempts.pickle(out);
|
|
self.concurrency.pickle(out);
|
|
self.enable_edns.pickle(out);
|
|
self.preserve_intermediates.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.tcp_on_error.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.servers = Pickle::unpickle(stream)?;
|
|
this.attempts = Pickle::unpickle(stream)?;
|
|
this.concurrency = Pickle::unpickle(stream)?;
|
|
this.enable_edns = Pickle::unpickle(stream)?;
|
|
this.preserve_intermediates = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.tcp_on_error = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsResolverCustom {
|
|
fn default() -> Self {
|
|
Self {
|
|
servers: Default::default(),
|
|
attempts: 2u64,
|
|
concurrency: 2u64,
|
|
enable_edns: true,
|
|
preserve_intermediates: true,
|
|
timeout: Duration::from_millis(5000),
|
|
tcp_on_error: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsResolverCustom {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Servers, self.servers.into_value());
|
|
map.insert_unchecked(Property::Attempts, self.attempts.into_value());
|
|
map.insert_unchecked(Property::Concurrency, self.concurrency.into_value());
|
|
map.insert_unchecked(Property::EnableEdns, self.enable_edns.into_value());
|
|
map.insert_unchecked(
|
|
Property::PreserveIntermediates,
|
|
self.preserve_intermediates.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::TcpOnError, self.tcp_on_error.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsResolverCustom {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Servers) => self.servers.patch(pointer, value),
|
|
Some(Property::Attempts) => self.attempts.patch(pointer, value),
|
|
Some(Property::Concurrency) => self.concurrency.patch(pointer, value),
|
|
Some(Property::EnableEdns) => self.enable_edns.patch(pointer, value),
|
|
Some(Property::PreserveIntermediates) => {
|
|
self.preserve_intermediates.patch(pointer, value)
|
|
}
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::TcpOnError) => self.tcp_on_error.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsResolverTls {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsResolverTls {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.use_tls.pickle(out);
|
|
self.attempts.pickle(out);
|
|
self.concurrency.pickle(out);
|
|
self.enable_edns.pickle(out);
|
|
self.preserve_intermediates.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.tcp_on_error.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.attempts = Pickle::unpickle(stream)?;
|
|
this.concurrency = Pickle::unpickle(stream)?;
|
|
this.enable_edns = Pickle::unpickle(stream)?;
|
|
this.preserve_intermediates = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.tcp_on_error = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsResolverTls {
|
|
fn default() -> Self {
|
|
Self {
|
|
use_tls: true,
|
|
attempts: 2u64,
|
|
concurrency: 2u64,
|
|
enable_edns: true,
|
|
preserve_intermediates: true,
|
|
timeout: Duration::from_millis(5000),
|
|
tcp_on_error: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsResolverTls {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(Property::Attempts, self.attempts.into_value());
|
|
map.insert_unchecked(Property::Concurrency, self.concurrency.into_value());
|
|
map.insert_unchecked(Property::EnableEdns, self.enable_edns.into_value());
|
|
map.insert_unchecked(
|
|
Property::PreserveIntermediates,
|
|
self.preserve_intermediates.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::TcpOnError, self.tcp_on_error.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsResolverTls {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::Attempts) => self.attempts.patch(pointer, value),
|
|
Some(Property::Concurrency) => self.concurrency.patch(pointer, value),
|
|
Some(Property::EnableEdns) => self.enable_edns.patch(pointer, value),
|
|
Some(Property::PreserveIntermediates) => {
|
|
self.preserve_intermediates.patch(pointer, value)
|
|
}
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::TcpOnError) => self.tcp_on_error.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DnsServer {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DnsServer;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DnsServer::Tsig(inner) => inner.validate(errors),
|
|
DnsServer::Sig0(inner) => inner.validate(errors),
|
|
DnsServer::Cloudflare(inner) => inner.validate(errors),
|
|
DnsServer::DigitalOcean(inner) => inner.validate(errors),
|
|
DnsServer::DeSEC(inner) => inner.validate(errors),
|
|
DnsServer::Ovh(inner) => inner.validate(errors),
|
|
DnsServer::Bunny(inner) => inner.validate(errors),
|
|
DnsServer::Porkbun(inner) => inner.validate(errors),
|
|
DnsServer::Dnsimple(inner) => inner.validate(errors),
|
|
DnsServer::Spaceship(inner) => inner.validate(errors),
|
|
DnsServer::Route53(inner) => inner.validate(errors),
|
|
DnsServer::GoogleCloudDns(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
DnsServer::Tsig(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Sig0(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Cloudflare(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::DigitalOcean(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::DeSEC(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Ovh(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Bunny(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Porkbun(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Dnsimple(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Spaceship(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::Route53(object) => {
|
|
object.index(i);
|
|
}
|
|
DnsServer::GoogleCloudDns(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServer {
|
|
fn default() -> Self {
|
|
DnsServer::Tsig(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServer {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DnsServer::Tsig(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Sig0(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Cloudflare(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::DigitalOcean(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::DeSEC(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Ovh(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Bunny(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Porkbun(inner) => {
|
|
7u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Dnsimple(inner) => {
|
|
8u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Spaceship(inner) => {
|
|
9u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::Route53(inner) => {
|
|
10u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServer::GoogleCloudDns(inner) => {
|
|
11u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(DnsServer::Tsig),
|
|
1 => Pickle::unpickle(stream).map(DnsServer::Sig0),
|
|
2 => Pickle::unpickle(stream).map(DnsServer::Cloudflare),
|
|
3 => Pickle::unpickle(stream).map(DnsServer::DigitalOcean),
|
|
4 => Pickle::unpickle(stream).map(DnsServer::DeSEC),
|
|
5 => Pickle::unpickle(stream).map(DnsServer::Ovh),
|
|
6 => Pickle::unpickle(stream).map(DnsServer::Bunny),
|
|
7 => Pickle::unpickle(stream).map(DnsServer::Porkbun),
|
|
8 => Pickle::unpickle(stream).map(DnsServer::Dnsimple),
|
|
9 => Pickle::unpickle(stream).map(DnsServer::Spaceship),
|
|
10 => Pickle::unpickle(stream).map(DnsServer::Route53),
|
|
11 => Pickle::unpickle(stream).map(DnsServer::GoogleCloudDns),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServer {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DnsServer::Tsig(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Tsig".into()));
|
|
obj
|
|
}
|
|
DnsServer::Sig0(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sig0".into()));
|
|
obj
|
|
}
|
|
DnsServer::Cloudflare(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Cloudflare".into()));
|
|
obj
|
|
}
|
|
DnsServer::DigitalOcean(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DigitalOcean".into()));
|
|
obj
|
|
}
|
|
DnsServer::DeSEC(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DeSEC".into()));
|
|
obj
|
|
}
|
|
DnsServer::Ovh(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ovh".into()));
|
|
obj
|
|
}
|
|
DnsServer::Bunny(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Bunny".into()));
|
|
obj
|
|
}
|
|
DnsServer::Porkbun(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Porkbun".into()));
|
|
obj
|
|
}
|
|
DnsServer::Dnsimple(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Dnsimple".into()));
|
|
obj
|
|
}
|
|
DnsServer::Spaceship(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Spaceship".into()));
|
|
obj
|
|
}
|
|
DnsServer::Route53(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Route53".into()));
|
|
obj
|
|
}
|
|
DnsServer::GoogleCloudDns(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("GoogleCloudDns".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DnsServer {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DnsServerType::Tsig => *self = DnsServer::Tsig(Default::default()),
|
|
DnsServerType::Sig0 => *self = DnsServer::Sig0(Default::default()),
|
|
DnsServerType::Cloudflare => *self = DnsServer::Cloudflare(Default::default()),
|
|
DnsServerType::DigitalOcean => *self = DnsServer::DigitalOcean(Default::default()),
|
|
DnsServerType::DeSEC => *self = DnsServer::DeSEC(Default::default()),
|
|
DnsServerType::Ovh => *self = DnsServer::Ovh(Default::default()),
|
|
DnsServerType::Bunny => *self = DnsServer::Bunny(Default::default()),
|
|
DnsServerType::Porkbun => *self = DnsServer::Porkbun(Default::default()),
|
|
DnsServerType::Dnsimple => *self = DnsServer::Dnsimple(Default::default()),
|
|
DnsServerType::Spaceship => *self = DnsServer::Spaceship(Default::default()),
|
|
DnsServerType::Route53 => *self = DnsServer::Route53(Default::default()),
|
|
DnsServerType::GoogleCloudDns => {
|
|
*self = DnsServer::GoogleCloudDns(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
DnsServer::Tsig(inner) => inner.patch(pointer, value),
|
|
DnsServer::Sig0(inner) => inner.patch(pointer, value),
|
|
DnsServer::Cloudflare(inner) => inner.patch(pointer, value),
|
|
DnsServer::DigitalOcean(inner) => inner.patch(pointer, value),
|
|
DnsServer::DeSEC(inner) => inner.patch(pointer, value),
|
|
DnsServer::Ovh(inner) => inner.patch(pointer, value),
|
|
DnsServer::Bunny(inner) => inner.patch(pointer, value),
|
|
DnsServer::Porkbun(inner) => inner.patch(pointer, value),
|
|
DnsServer::Dnsimple(inner) => inner.patch(pointer, value),
|
|
DnsServer::Spaceship(inner) => inner.patch(pointer, value),
|
|
DnsServer::Route53(inner) => inner.patch(pointer, value),
|
|
DnsServer::GoogleCloudDns(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServer {
|
|
pub fn object_type(&self) -> DnsServerType {
|
|
match self {
|
|
DnsServer::Tsig(_) => DnsServerType::Tsig,
|
|
DnsServer::Sig0(_) => DnsServerType::Sig0,
|
|
DnsServer::Cloudflare(_) => DnsServerType::Cloudflare,
|
|
DnsServer::DigitalOcean(_) => DnsServerType::DigitalOcean,
|
|
DnsServer::DeSEC(_) => DnsServerType::DeSEC,
|
|
DnsServer::Ovh(_) => DnsServerType::Ovh,
|
|
DnsServer::Bunny(_) => DnsServerType::Bunny,
|
|
DnsServer::Porkbun(_) => DnsServerType::Porkbun,
|
|
DnsServer::Dnsimple(_) => DnsServerType::Dnsimple,
|
|
DnsServer::Spaceship(_) => DnsServerType::Spaceship,
|
|
DnsServer::Route53(_) => DnsServerType::Route53,
|
|
DnsServer::GoogleCloudDns(_) => DnsServerType::GoogleCloudDns,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerBootstrap {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
DnsServerBootstrap::Manual => true,
|
|
DnsServerBootstrap::Tsig(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Sig0(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Cloudflare(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::DigitalOcean(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::DeSEC(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Ovh(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Bunny(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Porkbun(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Dnsimple(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Spaceship(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::Route53(inner) => inner.validate(errors),
|
|
DnsServerBootstrap::GoogleCloudDns(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerBootstrap {
|
|
fn default() -> Self {
|
|
DnsServerBootstrap::Manual
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerBootstrap {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
DnsServerBootstrap::Manual => {
|
|
0u16.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Tsig(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Sig0(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Cloudflare(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::DigitalOcean(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::DeSEC(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Ovh(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Bunny(inner) => {
|
|
7u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Porkbun(inner) => {
|
|
8u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Dnsimple(inner) => {
|
|
9u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Spaceship(inner) => {
|
|
10u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::Route53(inner) => {
|
|
11u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
DnsServerBootstrap::GoogleCloudDns(inner) => {
|
|
12u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(DnsServerBootstrap::Manual),
|
|
1 => Pickle::unpickle(stream).map(DnsServerBootstrap::Tsig),
|
|
2 => Pickle::unpickle(stream).map(DnsServerBootstrap::Sig0),
|
|
3 => Pickle::unpickle(stream).map(DnsServerBootstrap::Cloudflare),
|
|
4 => Pickle::unpickle(stream).map(DnsServerBootstrap::DigitalOcean),
|
|
5 => Pickle::unpickle(stream).map(DnsServerBootstrap::DeSEC),
|
|
6 => Pickle::unpickle(stream).map(DnsServerBootstrap::Ovh),
|
|
7 => Pickle::unpickle(stream).map(DnsServerBootstrap::Bunny),
|
|
8 => Pickle::unpickle(stream).map(DnsServerBootstrap::Porkbun),
|
|
9 => Pickle::unpickle(stream).map(DnsServerBootstrap::Dnsimple),
|
|
10 => Pickle::unpickle(stream).map(DnsServerBootstrap::Spaceship),
|
|
11 => Pickle::unpickle(stream).map(DnsServerBootstrap::Route53),
|
|
12 => Pickle::unpickle(stream).map(DnsServerBootstrap::GoogleCloudDns),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerBootstrap {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
DnsServerBootstrap::Manual => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
DnsServerBootstrap::Tsig(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Tsig".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Sig0(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sig0".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Cloudflare(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Cloudflare".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::DigitalOcean(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DigitalOcean".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::DeSEC(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DeSEC".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Ovh(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ovh".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Bunny(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Bunny".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Porkbun(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Porkbun".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Dnsimple(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Dnsimple".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Spaceship(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Spaceship".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::Route53(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Route53".into()));
|
|
obj
|
|
}
|
|
DnsServerBootstrap::GoogleCloudDns(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("GoogleCloudDns".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for DnsServerBootstrap {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
DnsServerBootstrapType::Manual => *self = DnsServerBootstrap::Manual,
|
|
DnsServerBootstrapType::Tsig => {
|
|
*self = DnsServerBootstrap::Tsig(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Sig0 => {
|
|
*self = DnsServerBootstrap::Sig0(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Cloudflare => {
|
|
*self = DnsServerBootstrap::Cloudflare(Default::default())
|
|
}
|
|
DnsServerBootstrapType::DigitalOcean => {
|
|
*self = DnsServerBootstrap::DigitalOcean(Default::default())
|
|
}
|
|
DnsServerBootstrapType::DeSEC => {
|
|
*self = DnsServerBootstrap::DeSEC(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Ovh => *self = DnsServerBootstrap::Ovh(Default::default()),
|
|
DnsServerBootstrapType::Bunny => {
|
|
*self = DnsServerBootstrap::Bunny(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Porkbun => {
|
|
*self = DnsServerBootstrap::Porkbun(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Dnsimple => {
|
|
*self = DnsServerBootstrap::Dnsimple(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Spaceship => {
|
|
*self = DnsServerBootstrap::Spaceship(Default::default())
|
|
}
|
|
DnsServerBootstrapType::Route53 => {
|
|
*self = DnsServerBootstrap::Route53(Default::default())
|
|
}
|
|
DnsServerBootstrapType::GoogleCloudDns => {
|
|
*self = DnsServerBootstrap::GoogleCloudDns(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
DnsServerBootstrap::Manual => pointer.assert_eof(),
|
|
DnsServerBootstrap::Tsig(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Sig0(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Cloudflare(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::DigitalOcean(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::DeSEC(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Ovh(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Bunny(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Porkbun(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Dnsimple(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Spaceship(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::Route53(inner) => inner.patch(pointer, value),
|
|
DnsServerBootstrap::GoogleCloudDns(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerBootstrap {
|
|
pub fn object_type(&self) -> DnsServerBootstrapType {
|
|
match self {
|
|
DnsServerBootstrap::Manual => DnsServerBootstrapType::Manual,
|
|
DnsServerBootstrap::Tsig(_) => DnsServerBootstrapType::Tsig,
|
|
DnsServerBootstrap::Sig0(_) => DnsServerBootstrapType::Sig0,
|
|
DnsServerBootstrap::Cloudflare(_) => DnsServerBootstrapType::Cloudflare,
|
|
DnsServerBootstrap::DigitalOcean(_) => DnsServerBootstrapType::DigitalOcean,
|
|
DnsServerBootstrap::DeSEC(_) => DnsServerBootstrapType::DeSEC,
|
|
DnsServerBootstrap::Ovh(_) => DnsServerBootstrapType::Ovh,
|
|
DnsServerBootstrap::Bunny(_) => DnsServerBootstrapType::Bunny,
|
|
DnsServerBootstrap::Porkbun(_) => DnsServerBootstrapType::Porkbun,
|
|
DnsServerBootstrap::Dnsimple(_) => DnsServerBootstrapType::Dnsimple,
|
|
DnsServerBootstrap::Spaceship(_) => DnsServerBootstrapType::Spaceship,
|
|
DnsServerBootstrap::Route53(_) => DnsServerBootstrapType::Route53,
|
|
DnsServerBootstrap::GoogleCloudDns(_) => DnsServerBootstrapType::GoogleCloudDns,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerCloud {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.secret;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerCloud {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.secret.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerCloud {
|
|
fn default() -> Self {
|
|
Self {
|
|
secret: Default::default(),
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerCloud {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::Secret, self.secret.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerCloud {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerCloudflare {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.email {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Email));
|
|
}
|
|
}
|
|
let value = &self.secret;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerCloudflare {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.email.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.email = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerCloudflare {
|
|
fn default() -> Self {
|
|
Self {
|
|
email: Default::default(),
|
|
secret: Default::default(),
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerCloudflare {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Email, self.email.into_value());
|
|
map.insert_unchecked(Property::Secret, self.secret.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerCloudflare {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Email) => self
|
|
.email
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerDnsimple {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.auth_token;
|
|
value.validate(errors);
|
|
let value = &self.account_identifier;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AccountIdentifier));
|
|
}
|
|
let value = &self.secret;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerDnsimple {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.auth_token.pickle(out);
|
|
self.account_identifier.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.auth_token = Pickle::unpickle(stream)?;
|
|
this.account_identifier = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerDnsimple {
|
|
fn default() -> Self {
|
|
Self {
|
|
auth_token: Default::default(),
|
|
account_identifier: Default::default(),
|
|
secret: Default::default(),
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerDnsimple {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(12);
|
|
map.insert_unchecked(Property::AuthToken, self.auth_token.into_value());
|
|
map.insert_unchecked(
|
|
Property::AccountIdentifier,
|
|
self.account_identifier.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Secret, self.secret.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerDnsimple {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AuthToken) => self.auth_token.patch(pointer, value),
|
|
Some(Property::AccountIdentifier) => self
|
|
.account_identifier
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerGoogleCloudDns {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.service_account_json;
|
|
value.validate(errors);
|
|
let value = &self.project_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ProjectId));
|
|
}
|
|
if let Some(value) = &self.managed_zone {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ManagedZone));
|
|
}
|
|
}
|
|
if let Some(value) = &self.impersonate_service_account {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(
|
|
Property::ImpersonateServiceAccount,
|
|
));
|
|
}
|
|
}
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerGoogleCloudDns {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.service_account_json.pickle(out);
|
|
self.project_id.pickle(out);
|
|
self.managed_zone.pickle(out);
|
|
self.private_zone.pickle(out);
|
|
self.impersonate_service_account.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.service_account_json = Pickle::unpickle(stream)?;
|
|
this.project_id = Pickle::unpickle(stream)?;
|
|
this.managed_zone = Pickle::unpickle(stream)?;
|
|
this.private_zone = Pickle::unpickle(stream)?;
|
|
this.impersonate_service_account = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerGoogleCloudDns {
|
|
fn default() -> Self {
|
|
Self {
|
|
service_account_json: Default::default(),
|
|
project_id: Default::default(),
|
|
managed_zone: Default::default(),
|
|
private_zone: false,
|
|
impersonate_service_account: Default::default(),
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerGoogleCloudDns {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(
|
|
Property::ServiceAccountJson,
|
|
self.service_account_json.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ProjectId, self.project_id.into_value());
|
|
map.insert_unchecked(Property::ManagedZone, self.managed_zone.into_value());
|
|
map.insert_unchecked(Property::PrivateZone, self.private_zone.into_value());
|
|
map.insert_unchecked(
|
|
Property::ImpersonateServiceAccount,
|
|
self.impersonate_service_account.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerGoogleCloudDns {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ServiceAccountJson) => self.service_account_json.patch(pointer, value),
|
|
Some(Property::ProjectId) => self
|
|
.project_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ManagedZone) => self
|
|
.managed_zone
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PrivateZone) => self.private_zone.patch(pointer, value),
|
|
Some(Property::ImpersonateServiceAccount) => self
|
|
.impersonate_service_account
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerOvh {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.application_key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ApplicationKey));
|
|
}
|
|
let value = &self.application_secret;
|
|
value.validate(errors);
|
|
let value = &self.consumer_key;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerOvh {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.application_key.pickle(out);
|
|
self.application_secret.pickle(out);
|
|
self.consumer_key.pickle(out);
|
|
self.ovh_endpoint.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.application_key = Pickle::unpickle(stream)?;
|
|
this.application_secret = Pickle::unpickle(stream)?;
|
|
this.consumer_key = Pickle::unpickle(stream)?;
|
|
this.ovh_endpoint = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerOvh {
|
|
fn default() -> Self {
|
|
Self {
|
|
application_key: Default::default(),
|
|
application_secret: Default::default(),
|
|
consumer_key: Default::default(),
|
|
ovh_endpoint: OvhEndpoint::OvhEu,
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerOvh {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::ApplicationKey, self.application_key.into_value());
|
|
map.insert_unchecked(
|
|
Property::ApplicationSecret,
|
|
self.application_secret.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ConsumerKey, self.consumer_key.into_value());
|
|
map.insert_unchecked(Property::OvhEndpoint, self.ovh_endpoint.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerOvh {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ApplicationKey) => self
|
|
.application_key
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ApplicationSecret) => self.application_secret.patch(pointer, value),
|
|
Some(Property::ConsumerKey) => self.consumer_key.patch(pointer, value),
|
|
Some(Property::OvhEndpoint) => self.ovh_endpoint.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerPorkbun {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.api_key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ApiKey));
|
|
}
|
|
let value = &self.secret_api_key;
|
|
value.validate(errors);
|
|
let value = &self.secret;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerPorkbun {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.api_key.pickle(out);
|
|
self.secret_api_key.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.api_key = Pickle::unpickle(stream)?;
|
|
this.secret_api_key = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerPorkbun {
|
|
fn default() -> Self {
|
|
Self {
|
|
api_key: Default::default(),
|
|
secret_api_key: Default::default(),
|
|
secret: Default::default(),
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerPorkbun {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(12);
|
|
map.insert_unchecked(Property::ApiKey, self.api_key.into_value());
|
|
map.insert_unchecked(Property::SecretApiKey, self.secret_api_key.into_value());
|
|
map.insert_unchecked(Property::Secret, self.secret.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerPorkbun {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ApiKey) => self
|
|
.api_key
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::SecretApiKey) => self.secret_api_key.patch(pointer, value),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerRoute53 {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.access_key_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AccessKeyId));
|
|
}
|
|
let value = &self.secret_access_key;
|
|
value.validate(errors);
|
|
let value = &self.session_token;
|
|
value.validate(errors);
|
|
let value = &self.region;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Region));
|
|
}
|
|
if let Some(value) = &self.hosted_zone_id {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HostedZoneId));
|
|
}
|
|
}
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerRoute53 {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.access_key_id.pickle(out);
|
|
self.secret_access_key.pickle(out);
|
|
self.session_token.pickle(out);
|
|
self.region.pickle(out);
|
|
self.hosted_zone_id.pickle(out);
|
|
self.private_zone_only.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.access_key_id = Pickle::unpickle(stream)?;
|
|
this.secret_access_key = Pickle::unpickle(stream)?;
|
|
this.session_token = Pickle::unpickle(stream)?;
|
|
this.region = Pickle::unpickle(stream)?;
|
|
this.hosted_zone_id = Pickle::unpickle(stream)?;
|
|
this.private_zone_only = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerRoute53 {
|
|
fn default() -> Self {
|
|
Self {
|
|
access_key_id: Default::default(),
|
|
secret_access_key: Default::default(),
|
|
session_token: Default::default(),
|
|
region: "us-east-1".to_string(),
|
|
hosted_zone_id: Default::default(),
|
|
private_zone_only: false,
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerRoute53 {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(Property::AccessKeyId, self.access_key_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::SecretAccessKey,
|
|
self.secret_access_key.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SessionToken, self.session_token.into_value());
|
|
map.insert_unchecked(Property::Region, self.region.into_value());
|
|
map.insert_unchecked(Property::HostedZoneId, self.hosted_zone_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::PrivateZoneOnly,
|
|
self.private_zone_only.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerRoute53 {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AccessKeyId) => self
|
|
.access_key_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::SecretAccessKey) => self.secret_access_key.patch(pointer, value),
|
|
Some(Property::SessionToken) => self.session_token.patch(pointer, value),
|
|
Some(Property::Region) => self
|
|
.region
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::HostedZoneId) => self
|
|
.hosted_zone_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PrivateZoneOnly) => self.private_zone_only.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerSig0 {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.host;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Host, value));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.public_key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::PublicKey));
|
|
}
|
|
let value = &self.key;
|
|
value.validate(errors);
|
|
let value = &self.signer_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SignerName));
|
|
}
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerSig0 {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.public_key.pickle(out);
|
|
self.key.pickle(out);
|
|
self.signer_name.pickle(out);
|
|
self.protocol.pickle(out);
|
|
self.sig0_algorithm.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.public_key = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.signer_name = Pickle::unpickle(stream)?;
|
|
this.protocol = Pickle::unpickle(stream)?;
|
|
this.sig0_algorithm = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerSig0 {
|
|
fn default() -> Self {
|
|
Self {
|
|
host: Default::default(),
|
|
port: 53u64,
|
|
public_key: Default::default(),
|
|
key: Default::default(),
|
|
signer_name: Default::default(),
|
|
protocol: IpProtocol::Udp,
|
|
sig0_algorithm: Sig0Algorithm::Ed25519,
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerSig0 {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(16);
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::PublicKey, self.public_key.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::SignerName, self.signer_name.into_value());
|
|
map.insert_unchecked(Property::Protocol, self.protocol.into_value());
|
|
map.insert_unchecked(Property::Sig0Algorithm, self.sig0_algorithm.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerSig0 {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::PublicKey) => self
|
|
.public_key
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::SignerName) => self
|
|
.signer_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Protocol) => self.protocol.patch(pointer, value),
|
|
Some(Property::Sig0Algorithm) => self.sig0_algorithm.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerSpaceship {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.api_key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ApiKey));
|
|
}
|
|
let value = &self.secret;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerSpaceship {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.api_key.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.api_key = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerSpaceship {
|
|
fn default() -> Self {
|
|
Self {
|
|
api_key: Default::default(),
|
|
secret: Default::default(),
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerSpaceship {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::ApiKey, self.api_key.into_value());
|
|
map.insert_unchecked(Property::Secret, self.secret.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerSpaceship {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ApiKey) => self
|
|
.api_key
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnsServerTsig {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.host;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Host, value));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.key_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::KeyName));
|
|
}
|
|
let value = &self.key;
|
|
value.validate(errors);
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for DnsServerTsig {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.key_name.pickle(out);
|
|
self.key.pickle(out);
|
|
self.protocol.pickle(out);
|
|
self.tsig_algorithm.pickle(out);
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.ttl.pickle(out);
|
|
self.polling_interval.pickle(out);
|
|
self.propagation_timeout.pickle(out);
|
|
self.propagation_delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.key_name = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.protocol = Pickle::unpickle(stream)?;
|
|
this.tsig_algorithm = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.ttl = Pickle::unpickle(stream)?;
|
|
this.polling_interval = Pickle::unpickle(stream)?;
|
|
this.propagation_timeout = Pickle::unpickle(stream)?;
|
|
this.propagation_delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DnsServerTsig {
|
|
fn default() -> Self {
|
|
Self {
|
|
host: Default::default(),
|
|
port: 53u64,
|
|
key_name: Default::default(),
|
|
key: Default::default(),
|
|
protocol: IpProtocol::Udp,
|
|
tsig_algorithm: TsigAlgorithm::HmacSha512,
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
ttl: Duration::from_millis(300000),
|
|
polling_interval: Duration::from_millis(15000),
|
|
propagation_timeout: Duration::from_millis(60000),
|
|
propagation_delay: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DnsServerTsig {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::KeyName, self.key_name.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Protocol, self.protocol.into_value());
|
|
map.insert_unchecked(Property::TsigAlgorithm, self.tsig_algorithm.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Ttl, self.ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::PollingInterval,
|
|
self.polling_interval.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationTimeout,
|
|
self.propagation_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PropagationDelay,
|
|
self.propagation_delay.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DnsServerTsig {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::KeyName) => self
|
|
.key_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::Protocol) => self.protocol.patch(pointer, value),
|
|
Some(Property::TsigAlgorithm) => self.tsig_algorithm.patch(pointer, value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Ttl) => self.ttl.patch(pointer, value),
|
|
Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value),
|
|
Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value),
|
|
Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Domain {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Domain;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.aliases;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Aliases));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
if let Some(value) = &self.logo {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Logo));
|
|
}
|
|
}
|
|
let value = &self.certificate_management;
|
|
value.validate(errors);
|
|
let value = &self.dkim_management;
|
|
value.validate(errors);
|
|
let value = &self.dns_management;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
if let Some(value) = &self.directory_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DirectoryId));
|
|
}
|
|
}
|
|
if let Some(value) = &self.catch_all_address {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::CatchAllAddress));
|
|
}
|
|
}
|
|
let value = &self.sub_addressing;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.report_address_uri {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReportAddressUri));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
i.text(Property::Text, &self.name);
|
|
for value in self.aliases.iter() {
|
|
i.text(Property::Text, value);
|
|
}
|
|
if let Some(value) = &self.description {
|
|
i.text(Property::Text, value);
|
|
}
|
|
self.certificate_management.index(i);
|
|
self.dns_management.index(i);
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
i.foreign_key(ObjectType::Directory, self.directory_id, None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for Domain {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.aliases.pickle(out);
|
|
self.is_enabled.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.description.pickle(out);
|
|
self.logo.pickle(out);
|
|
self.certificate_management.pickle(out);
|
|
self.dkim_management.pickle(out);
|
|
self.dns_management.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.directory_id.pickle(out);
|
|
self.catch_all_address.pickle(out);
|
|
self.sub_addressing.pickle(out);
|
|
self.allow_relaying.pickle(out);
|
|
self.report_address_uri.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.aliases = Pickle::unpickle(stream)?;
|
|
this.is_enabled = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.logo = Pickle::unpickle(stream)?;
|
|
this.certificate_management = Pickle::unpickle(stream)?;
|
|
this.dkim_management = Pickle::unpickle(stream)?;
|
|
this.dns_management = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.directory_id = Pickle::unpickle(stream)?;
|
|
this.catch_all_address = Pickle::unpickle(stream)?;
|
|
this.sub_addressing = Pickle::unpickle(stream)?;
|
|
this.allow_relaying = Pickle::unpickle(stream)?;
|
|
this.report_address_uri = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Domain {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
aliases: Default::default(),
|
|
is_enabled: true,
|
|
created_at: Default::default(),
|
|
description: Default::default(),
|
|
logo: Default::default(),
|
|
certificate_management: Default::default(),
|
|
dkim_management: Default::default(),
|
|
dns_management: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
directory_id: Default::default(),
|
|
catch_all_address: Default::default(),
|
|
sub_addressing: Default::default(),
|
|
allow_relaying: false,
|
|
report_address_uri: Some("mailto:postmaster".to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Domain {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(17);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Aliases, self.aliases.into_value());
|
|
map.insert_unchecked(Property::IsEnabled, self.is_enabled.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Logo, self.logo.into_value());
|
|
map.insert_unchecked(
|
|
Property::CertificateManagement,
|
|
self.certificate_management.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DkimManagement, self.dkim_management.into_value());
|
|
map.insert_unchecked(Property::DnsManagement, self.dns_management.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::DirectoryId, self.directory_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::CatchAllAddress,
|
|
self.catch_all_address.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SubAddressing, self.sub_addressing.into_value());
|
|
map.insert_unchecked(Property::AllowRelaying, self.allow_relaying.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReportAddressUri,
|
|
self.report_address_uri.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Domain {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self
|
|
.name
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::Aliases) => self
|
|
.aliases
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::IsEnabled) => self.is_enabled.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Logo) => self.logo.patch(pointer, value),
|
|
Some(Property::CertificateManagement) => {
|
|
self.certificate_management.patch(pointer, value)
|
|
}
|
|
Some(Property::DkimManagement) => self.dkim_management.patch(pointer, value),
|
|
Some(Property::DnsManagement) => self.dns_management.patch(pointer, value),
|
|
Some(Property::DnsZoneFile) => pointer.assert_server_set(),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::DirectoryId) => self.directory_id.patch(pointer, value),
|
|
Some(Property::CatchAllAddress) => self
|
|
.catch_all_address
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::SubAddressing) => self.sub_addressing.patch(pointer, value),
|
|
Some(Property::AllowRelaying) => self.allow_relaying.patch(pointer, value),
|
|
Some(Property::ReportAddressUri) => self
|
|
.report_address_uri
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for DsnReportSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::DsnReportSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.from_address;
|
|
value.validate(errors);
|
|
let value = &self.from_name;
|
|
value.validate(errors);
|
|
let value = &self.dkim_sign_domain;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl DsnReportSettings {
|
|
pub fn ctx_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_address,
|
|
default: Some(Expression {
|
|
else_: "'MAILER-DAEMON@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromAddress,
|
|
allowed_variables: MTA_QUEUE_SENDER_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_name,
|
|
default: Some(Expression {
|
|
else_: "'Mail Delivery Subsystem'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromName,
|
|
allowed_variables: MTA_QUEUE_SENDER_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DkimSignDomain,
|
|
allowed_variables: MTA_QUEUE_SENDER_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_from_address(),
|
|
self.ctx_from_name(),
|
|
self.ctx_dkim_sign_domain(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for DsnReportSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.from_address.pickle(out);
|
|
self.from_name.pickle(out);
|
|
self.dkim_sign_domain.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.from_address = Pickle::unpickle(stream)?;
|
|
this.from_name = Pickle::unpickle(stream)?;
|
|
this.dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for DsnReportSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
from_address: Expression {
|
|
else_: "'MAILER-DAEMON@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
from_name: Expression {
|
|
else_: "'Mail Delivery Subsystem'".to_string(),
|
|
..Default::default()
|
|
},
|
|
dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for DsnReportSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::FromAddress, self.from_address.into_value());
|
|
map.insert_unchecked(Property::FromName, self.from_name.into_value());
|
|
map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for DsnReportSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::FromAddress) => self.from_address.patch(pointer, value),
|
|
Some(Property::FromName) => self.from_name.patch(pointer, value),
|
|
Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ElasticSearchStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.num_replicas;
|
|
if *value > 2048 {
|
|
errors.push(ValidationError::max_value(Property::NumReplicas, 2048));
|
|
}
|
|
let value = &self.num_shards;
|
|
if *value > 1048576 {
|
|
errors.push(ValidationError::max_value(Property::NumShards, 1048576));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::NumShards, 1));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ElasticSearchStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.url.pickle(out);
|
|
self.num_replicas.pickle(out);
|
|
self.num_shards.pickle(out);
|
|
self.include_source.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.num_replicas = Pickle::unpickle(stream)?;
|
|
this.num_shards = Pickle::unpickle(stream)?;
|
|
this.include_source = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ElasticSearchStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
url: Default::default(),
|
|
num_replicas: 0u64,
|
|
num_shards: 3u64,
|
|
include_source: false,
|
|
timeout: Duration::from_millis(30000),
|
|
allow_invalid_certs: false,
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ElasticSearchStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::NumReplicas, self.num_replicas.into_value());
|
|
map.insert_unchecked(Property::NumShards, self.num_shards.into_value());
|
|
map.insert_unchecked(Property::IncludeSource, self.include_source.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ElasticSearchStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::NumReplicas) => self.num_replicas.patch(pointer, value),
|
|
Some(Property::NumShards) => self.num_shards.patch(pointer, value),
|
|
Some(Property::IncludeSource) => self.include_source.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Email {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Email;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_attachment_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxAttachmentSize, 1));
|
|
}
|
|
let value = &self.max_message_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMessageSize, 1));
|
|
}
|
|
let value = &self.max_mailbox_depth;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMailboxDepth, 1));
|
|
}
|
|
let value = &self.max_mailbox_name_length;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::MaxMailboxNameLength,
|
|
1,
|
|
));
|
|
}
|
|
let value = &self.default_folders;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.max_messages {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMessages, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_submissions {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxSubmissions, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_identities {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxIdentities, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_mailboxes {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMailboxes, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_masked_addresses {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMaskedAddresses, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_public_keys {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxPublicKeys, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Email {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_attachment_size.pickle(out);
|
|
self.max_message_size.pickle(out);
|
|
self.max_mailbox_depth.pickle(out);
|
|
self.max_mailbox_name_length.pickle(out);
|
|
self.encrypt_on_append.pickle(out);
|
|
self.encrypt_at_rest.pickle(out);
|
|
self.compression_algorithm.pickle(out);
|
|
self.default_folders.pickle(out);
|
|
self.max_messages.pickle(out);
|
|
self.max_submissions.pickle(out);
|
|
self.max_identities.pickle(out);
|
|
self.max_mailboxes.pickle(out);
|
|
self.max_masked_addresses.pickle(out);
|
|
self.max_public_keys.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_attachment_size = Pickle::unpickle(stream)?;
|
|
this.max_message_size = Pickle::unpickle(stream)?;
|
|
this.max_mailbox_depth = Pickle::unpickle(stream)?;
|
|
this.max_mailbox_name_length = Pickle::unpickle(stream)?;
|
|
this.encrypt_on_append = Pickle::unpickle(stream)?;
|
|
this.encrypt_at_rest = Pickle::unpickle(stream)?;
|
|
this.compression_algorithm = Pickle::unpickle(stream)?;
|
|
this.default_folders = Pickle::unpickle(stream)?;
|
|
this.max_messages = Pickle::unpickle(stream)?;
|
|
this.max_submissions = Pickle::unpickle(stream)?;
|
|
this.max_identities = Pickle::unpickle(stream)?;
|
|
this.max_mailboxes = Pickle::unpickle(stream)?;
|
|
this.max_masked_addresses = Pickle::unpickle(stream)?;
|
|
this.max_public_keys = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Email {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_attachment_size: 50000000u64,
|
|
max_message_size: 75000000u64,
|
|
max_mailbox_depth: 10u64,
|
|
max_mailbox_name_length: 255u64,
|
|
encrypt_on_append: false,
|
|
encrypt_at_rest: true,
|
|
compression_algorithm: CompressionAlgo::Lz4,
|
|
default_folders: Default::default(),
|
|
max_messages: Default::default(),
|
|
max_submissions: Some(500u64),
|
|
max_identities: Some(20u64),
|
|
max_mailboxes: Some(250u64),
|
|
max_masked_addresses: Some(5u64),
|
|
max_public_keys: Some(5u64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Email {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(16);
|
|
map.insert_unchecked(
|
|
Property::MaxAttachmentSize,
|
|
self.max_attachment_size.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxMessageSize, self.max_message_size.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxMailboxDepth,
|
|
self.max_mailbox_depth.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxMailboxNameLength,
|
|
self.max_mailbox_name_length.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::EncryptOnAppend,
|
|
self.encrypt_on_append.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::EncryptAtRest, self.encrypt_at_rest.into_value());
|
|
map.insert_unchecked(
|
|
Property::CompressionAlgorithm,
|
|
self.compression_algorithm.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DefaultFolders, self.default_folders.into_value());
|
|
map.insert_unchecked(Property::MaxMessages, self.max_messages.into_value());
|
|
map.insert_unchecked(Property::MaxSubmissions, self.max_submissions.into_value());
|
|
map.insert_unchecked(Property::MaxIdentities, self.max_identities.into_value());
|
|
map.insert_unchecked(Property::MaxMailboxes, self.max_mailboxes.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxMaskedAddresses,
|
|
self.max_masked_addresses.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxPublicKeys, self.max_public_keys.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Email {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxAttachmentSize) => self.max_attachment_size.patch(pointer, value),
|
|
Some(Property::MaxMessageSize) => self.max_message_size.patch(pointer, value),
|
|
Some(Property::MaxMailboxDepth) => self.max_mailbox_depth.patch(pointer, value),
|
|
Some(Property::MaxMailboxNameLength) => {
|
|
self.max_mailbox_name_length.patch(pointer, value)
|
|
}
|
|
Some(Property::EncryptOnAppend) => self.encrypt_on_append.patch(pointer, value),
|
|
Some(Property::EncryptAtRest) => self.encrypt_at_rest.patch(pointer, value),
|
|
Some(Property::CompressionAlgorithm) => {
|
|
self.compression_algorithm.patch(pointer, value)
|
|
}
|
|
Some(Property::DefaultFolders) => self.default_folders.patch(pointer, value),
|
|
Some(Property::MaxMessages) => self.max_messages.patch(pointer, value),
|
|
Some(Property::MaxSubmissions) => self.max_submissions.patch(pointer, value),
|
|
Some(Property::MaxIdentities) => self.max_identities.patch(pointer, value),
|
|
Some(Property::MaxMailboxes) => self.max_mailboxes.patch(pointer, value),
|
|
Some(Property::MaxMaskedAddresses) => self.max_masked_addresses.patch(pointer, value),
|
|
Some(Property::MaxPublicKeys) => self.max_public_keys.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EmailAlias {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global_composite(Property::Email, &self.name, &self.domain_id);
|
|
i.text(Property::Text, &self.name);
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for EmailAlias {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enabled.pickle(out);
|
|
self.name.pickle(out);
|
|
self.domain_id.pickle(out);
|
|
self.description.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enabled = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for EmailAlias {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
name: Default::default(),
|
|
domain_id: Default::default(),
|
|
description: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for EmailAlias {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Enabled, self.enabled.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for EmailAlias {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enabled) => self.enabled.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer.with_validators(&[StringValidator::EmailLocalPart]),
|
|
value,
|
|
),
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EmailFolder {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.aliases;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Aliases));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for EmailFolder {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.create.pickle(out);
|
|
self.subscribe.pickle(out);
|
|
self.aliases.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.create = Pickle::unpickle(stream)?;
|
|
this.subscribe = Pickle::unpickle(stream)?;
|
|
this.aliases = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for EmailFolder {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
create: true,
|
|
subscribe: true,
|
|
aliases: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for EmailFolder {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Create, self.create.into_value());
|
|
map.insert_unchecked(Property::Subscribe, self.subscribe.into_value());
|
|
map.insert_unchecked(Property::Aliases, self.aliases.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for EmailFolder {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self
|
|
.name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Create) => self.create.patch(pointer, value),
|
|
Some(Property::Subscribe) => self.subscribe.patch(pointer, value),
|
|
Some(Property::Aliases) => self
|
|
.aliases
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EncryptionAtRest {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
EncryptionAtRest::Disabled => true,
|
|
EncryptionAtRest::Aes128(inner) => inner.validate(errors),
|
|
EncryptionAtRest::Aes256(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
EncryptionAtRest::Disabled => {}
|
|
EncryptionAtRest::Aes128(object) => {
|
|
object.index(i);
|
|
}
|
|
EncryptionAtRest::Aes256(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for EncryptionAtRest {
|
|
fn default() -> Self {
|
|
EncryptionAtRest::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for EncryptionAtRest {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
EncryptionAtRest::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
EncryptionAtRest::Aes128(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
EncryptionAtRest::Aes256(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(EncryptionAtRest::Disabled),
|
|
1 => Pickle::unpickle(stream).map(EncryptionAtRest::Aes128),
|
|
2 => Pickle::unpickle(stream).map(EncryptionAtRest::Aes256),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for EncryptionAtRest {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
EncryptionAtRest::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
EncryptionAtRest::Aes128(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Aes128".into()));
|
|
obj
|
|
}
|
|
EncryptionAtRest::Aes256(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Aes256".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for EncryptionAtRest {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
EncryptionAtRestType::Disabled => *self = EncryptionAtRest::Disabled,
|
|
EncryptionAtRestType::Aes128 => {
|
|
*self = EncryptionAtRest::Aes128(Default::default())
|
|
}
|
|
EncryptionAtRestType::Aes256 => {
|
|
*self = EncryptionAtRest::Aes256(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
EncryptionAtRest::Disabled => pointer.assert_eof(),
|
|
EncryptionAtRest::Aes128(inner) => inner.patch(pointer, value),
|
|
EncryptionAtRest::Aes256(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EncryptionAtRest {
|
|
pub fn object_type(&self) -> EncryptionAtRestType {
|
|
match self {
|
|
EncryptionAtRest::Disabled => EncryptionAtRestType::Disabled,
|
|
EncryptionAtRest::Aes128(_) => EncryptionAtRestType::Aes128,
|
|
EncryptionAtRest::Aes256(_) => EncryptionAtRestType::Aes256,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EncryptionSettings {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.public_key;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::PublicKey));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::PublicKey, self.public_key.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for EncryptionSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.public_key.pickle(out);
|
|
self.encrypt_on_append.pickle(out);
|
|
self.allow_spam_training.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.public_key = Pickle::unpickle(stream)?;
|
|
this.encrypt_on_append = Pickle::unpickle(stream)?;
|
|
this.allow_spam_training = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for EncryptionSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
public_key: Default::default(),
|
|
encrypt_on_append: false,
|
|
allow_spam_training: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for EncryptionSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::PublicKey, self.public_key.into_value());
|
|
map.insert_unchecked(
|
|
Property::EncryptOnAppend,
|
|
self.encrypt_on_append.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AllowSpamTraining,
|
|
self.allow_spam_training.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for EncryptionSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::PublicKey) => self.public_key.patch(pointer, value),
|
|
Some(Property::EncryptOnAppend) => self.encrypt_on_append.patch(pointer, value),
|
|
Some(Property::AllowSpamTraining) => self.allow_spam_training.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Enterprise {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Enterprise;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.api_key;
|
|
value.validate(errors);
|
|
let value = &self.license_key;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.logo_url {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::LogoUrl));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Enterprise {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.api_key.pickle(out);
|
|
self.license_key.pickle(out);
|
|
self.logo_url.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.api_key = Pickle::unpickle(stream)?;
|
|
this.license_key = Pickle::unpickle(stream)?;
|
|
this.logo_url = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Enterprise {
|
|
fn default() -> Self {
|
|
Self {
|
|
api_key: Default::default(),
|
|
license_key: Default::default(),
|
|
logo_url: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Enterprise {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::ApiKey, self.api_key.into_value());
|
|
map.insert_unchecked(Property::LicenseKey, self.license_key.into_value());
|
|
map.insert_unchecked(Property::LogoUrl, self.logo_url.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Enterprise {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ApiKey) => self.api_key.patch(pointer, value),
|
|
Some(Property::LicenseKey) => self.license_key.patch(pointer, value),
|
|
Some(Property::LogoUrl) => self
|
|
.logo_url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for EventTracingLevel {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::EventTracingLevel;
|
|
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Event, &self.event);
|
|
}
|
|
}
|
|
|
|
impl Pickle for EventTracingLevel {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.event.pickle(out);
|
|
self.level.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.event = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for EventTracingLevel {
|
|
fn default() -> Self {
|
|
Self {
|
|
event: Default::default(),
|
|
level: TracingLevelOpt::Info,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for EventTracingLevel {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Event, self.event.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for EventTracingLevel {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Event) => self.event.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Expression {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.match_;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.else_;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Else));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for Expression {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.match_.pickle(out);
|
|
self.else_.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.match_ = Pickle::unpickle(stream)?;
|
|
this.else_ = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Expression {
|
|
fn default() -> Self {
|
|
Self {
|
|
match_: Default::default(),
|
|
else_: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Expression {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Match, self.match_.into_value());
|
|
map.insert_unchecked(Property::Else, self.else_.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Expression {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Match) => self.match_.patch(pointer, value),
|
|
Some(Property::Else) => self.else_.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ExpressionMatch {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.if_;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::If));
|
|
}
|
|
let value = &self.then;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Then));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ExpressionMatch {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.if_.pickle(out);
|
|
self.then.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.if_ = Pickle::unpickle(stream)?;
|
|
this.then = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ExpressionMatch {
|
|
fn default() -> Self {
|
|
Self {
|
|
if_: Default::default(),
|
|
then: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ExpressionMatch {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::If, self.if_.into_value());
|
|
map.insert_unchecked(Property::Then, self.then.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ExpressionMatch {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::If) => self.if_.patch(pointer, value),
|
|
Some(Property::Then) => self.then.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for FileStorage {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::FileStorage;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.max_files {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxFiles, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_folders {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxFolders, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for FileStorage {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_size.pickle(out);
|
|
self.max_files.pickle(out);
|
|
self.max_folders.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_size = Pickle::unpickle(stream)?;
|
|
this.max_files = Pickle::unpickle(stream)?;
|
|
this.max_folders = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for FileStorage {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_size: 26214400,
|
|
max_files: Default::default(),
|
|
max_folders: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for FileStorage {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::MaxSize, self.max_size.into_value());
|
|
map.insert_unchecked(Property::MaxFiles, self.max_files.into_value());
|
|
map.insert_unchecked(Property::MaxFolders, self.max_folders.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for FileStorage {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxSize) => self.max_size.patch(pointer, value),
|
|
Some(Property::MaxFiles) => self.max_files.patch(pointer, value),
|
|
Some(Property::MaxFolders) => self.max_folders.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FileSystemStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.path;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Path));
|
|
}
|
|
let value = &self.depth;
|
|
if *value > 5 {
|
|
errors.push(ValidationError::max_value(Property::Depth, 5));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for FileSystemStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.path.pickle(out);
|
|
self.depth.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.path = Pickle::unpickle(stream)?;
|
|
this.depth = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for FileSystemStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
path: Default::default(),
|
|
depth: 2u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for FileSystemStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Path, self.path.into_value());
|
|
map.insert_unchecked(Property::Depth, self.depth.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for FileSystemStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Path) => self
|
|
.path
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Depth) => self.depth.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FoundationDbStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.cluster_file {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ClusterFile));
|
|
}
|
|
}
|
|
if let Some(value) = &self.datacenter_id {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DatacenterId));
|
|
}
|
|
}
|
|
if let Some(value) = &self.machine_id {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MachineId));
|
|
}
|
|
}
|
|
if let Some(value) = &self.transaction_retry_limit {
|
|
if *value > 1000 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::TransactionRetryLimit,
|
|
1000,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::TransactionRetryLimit,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for FoundationDbStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.cluster_file.pickle(out);
|
|
self.datacenter_id.pickle(out);
|
|
self.machine_id.pickle(out);
|
|
self.transaction_retry_delay.pickle(out);
|
|
self.transaction_retry_limit.pickle(out);
|
|
self.transaction_timeout.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.cluster_file = Pickle::unpickle(stream)?;
|
|
this.datacenter_id = Pickle::unpickle(stream)?;
|
|
this.machine_id = Pickle::unpickle(stream)?;
|
|
this.transaction_retry_delay = Pickle::unpickle(stream)?;
|
|
this.transaction_retry_limit = Pickle::unpickle(stream)?;
|
|
this.transaction_timeout = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for FoundationDbStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
cluster_file: Default::default(),
|
|
datacenter_id: Default::default(),
|
|
machine_id: Default::default(),
|
|
transaction_retry_delay: Default::default(),
|
|
transaction_retry_limit: Default::default(),
|
|
transaction_timeout: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for FoundationDbStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::ClusterFile, self.cluster_file.into_value());
|
|
map.insert_unchecked(Property::DatacenterId, self.datacenter_id.into_value());
|
|
map.insert_unchecked(Property::MachineId, self.machine_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::TransactionRetryDelay,
|
|
self.transaction_retry_delay.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TransactionRetryLimit,
|
|
self.transaction_retry_limit.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TransactionTimeout,
|
|
self.transaction_timeout.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for FoundationDbStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ClusterFile) => self
|
|
.cluster_file
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::DatacenterId) => self
|
|
.datacenter_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MachineId) => self
|
|
.machine_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::TransactionRetryDelay) => {
|
|
self.transaction_retry_delay.patch(pointer, value)
|
|
}
|
|
Some(Property::TransactionRetryLimit) => {
|
|
self.transaction_retry_limit.patch(pointer, value)
|
|
}
|
|
Some(Property::TransactionTimeout) => self.transaction_timeout.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FtrlParameters {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.alpha;
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::Alpha, 0));
|
|
}
|
|
let value = &self.beta;
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::Beta, 0));
|
|
}
|
|
let value = &self.l1_ratio;
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::L1Ratio, 0));
|
|
}
|
|
let value = &self.l2_ratio;
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::L2Ratio, 0));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for FtrlParameters {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.alpha.pickle(out);
|
|
self.beta.pickle(out);
|
|
self.num_features.pickle(out);
|
|
self.l1_ratio.pickle(out);
|
|
self.l2_ratio.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.alpha = Pickle::unpickle(stream)?;
|
|
this.beta = Pickle::unpickle(stream)?;
|
|
this.num_features = Pickle::unpickle(stream)?;
|
|
this.l1_ratio = Pickle::unpickle(stream)?;
|
|
this.l2_ratio = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for FtrlParameters {
|
|
fn default() -> Self {
|
|
Self {
|
|
alpha: Float::new(2.0f64),
|
|
beta: Float::new(1.0f64),
|
|
num_features: ModelSize::V20,
|
|
l1_ratio: Float::new(0.001f64),
|
|
l2_ratio: Float::new(0.0001f64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for FtrlParameters {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Alpha, self.alpha.into_value());
|
|
map.insert_unchecked(Property::Beta, self.beta.into_value());
|
|
map.insert_unchecked(Property::NumFeatures, self.num_features.into_value());
|
|
map.insert_unchecked(Property::L1Ratio, self.l1_ratio.into_value());
|
|
map.insert_unchecked(Property::L2Ratio, self.l2_ratio.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for FtrlParameters {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Alpha) => self.alpha.patch(pointer, value),
|
|
Some(Property::Beta) => self.beta.patch(pointer, value),
|
|
Some(Property::NumFeatures) => self.num_features.patch(pointer, value),
|
|
Some(Property::L1Ratio) => self.l1_ratio.patch(pointer, value),
|
|
Some(Property::L2Ratio) => self.l2_ratio.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GroupAccount {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
let value = &self.roles;
|
|
value.validate(errors);
|
|
let value = &self.permissions;
|
|
value.validate(errors);
|
|
let value = &self.aliases;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global_composite(Property::Email, &self.name, &self.domain_id);
|
|
i.text(Property::Text, &self.name);
|
|
i.search(Property::Name, &self.name);
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
i.search(Property::DomainId, &self.domain_id);
|
|
if let Some(value) = &self.description {
|
|
i.text(Property::Text, value);
|
|
}
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
self.roles.index(i);
|
|
for item in self.aliases.values() {
|
|
item.index(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for GroupAccount {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.domain_id.pickle(out);
|
|
self.description.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.roles.pickle(out);
|
|
self.quotas.pickle(out);
|
|
self.permissions.pickle(out);
|
|
self.aliases.pickle(out);
|
|
self.locale.pickle(out);
|
|
self.time_zone.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.roles = Pickle::unpickle(stream)?;
|
|
this.quotas = Pickle::unpickle(stream)?;
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
this.aliases = Pickle::unpickle(stream)?;
|
|
this.locale = Pickle::unpickle(stream)?;
|
|
this.time_zone = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for GroupAccount {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
domain_id: Default::default(),
|
|
description: Default::default(),
|
|
created_at: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
roles: Default::default(),
|
|
quotas: Default::default(),
|
|
permissions: Default::default(),
|
|
aliases: Default::default(),
|
|
locale: Locale::EnUS,
|
|
time_zone: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for GroupAccount {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Roles, self.roles.into_value());
|
|
map.insert_unchecked(Property::Quotas, self.quotas.into_value());
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
map.insert_unchecked(Property::Aliases, self.aliases.into_value());
|
|
map.insert_unchecked(Property::Locale, self.locale.into_value());
|
|
map.insert_unchecked(Property::TimeZone, self.time_zone.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for GroupAccount {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer.with_validators(&[StringValidator::EmailLocalPart]),
|
|
value,
|
|
),
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer, value),
|
|
Some(Property::EmailAddress) => pointer.assert_server_set(),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Roles) => self.roles.patch(pointer, value),
|
|
Some(Property::Quotas) => self.quotas.patch(pointer, value),
|
|
Some(Property::UsedDiskQuota) => pointer.assert_server_set(),
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::Aliases) => self.aliases.patch(pointer, value),
|
|
Some(Property::Locale) => self.locale.patch(pointer, value),
|
|
Some(Property::TimeZone) => self.time_zone.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Http {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Http;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.rate_limit_authenticated {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.rate_limit_anonymous {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.allowed_endpoints;
|
|
value.validate(errors);
|
|
let value = &self.response_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Http {
|
|
pub fn ctx_allowed_endpoints(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.allowed_endpoints,
|
|
default: Some(Expression {
|
|
else_: "200".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AllowedEndpoints,
|
|
allowed_variables: HTTP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_allowed_endpoints()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for Http {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.rate_limit_authenticated.pickle(out);
|
|
self.rate_limit_anonymous.pickle(out);
|
|
self.allowed_endpoints.pickle(out);
|
|
self.enable_hsts.pickle(out);
|
|
self.use_permissive_cors.pickle(out);
|
|
self.response_headers.pickle(out);
|
|
self.use_x_forwarded.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.rate_limit_authenticated = Pickle::unpickle(stream)?;
|
|
this.rate_limit_anonymous = Pickle::unpickle(stream)?;
|
|
this.allowed_endpoints = Pickle::unpickle(stream)?;
|
|
this.enable_hsts = Pickle::unpickle(stream)?;
|
|
this.use_permissive_cors = Pickle::unpickle(stream)?;
|
|
this.response_headers = Pickle::unpickle(stream)?;
|
|
this.use_x_forwarded = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Http {
|
|
fn default() -> Self {
|
|
Self {
|
|
rate_limit_authenticated: Some(Rate {
|
|
count: 1000u64,
|
|
period: Duration::from_millis(60000),
|
|
}),
|
|
rate_limit_anonymous: Some(Rate {
|
|
count: 100u64,
|
|
period: Duration::from_millis(60000),
|
|
}),
|
|
allowed_endpoints: Expression {
|
|
else_: "200".to_string(),
|
|
..Default::default()
|
|
},
|
|
enable_hsts: false,
|
|
use_permissive_cors: false,
|
|
response_headers: Default::default(),
|
|
use_x_forwarded: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Http {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(
|
|
Property::RateLimitAuthenticated,
|
|
self.rate_limit_authenticated.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::RateLimitAnonymous,
|
|
self.rate_limit_anonymous.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AllowedEndpoints,
|
|
self.allowed_endpoints.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::EnableHsts, self.enable_hsts.into_value());
|
|
map.insert_unchecked(
|
|
Property::UsePermissiveCors,
|
|
self.use_permissive_cors.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ResponseHeaders,
|
|
self.response_headers.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::UseXForwarded, self.use_x_forwarded.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Http {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::RateLimitAuthenticated) => {
|
|
self.rate_limit_authenticated.patch(pointer, value)
|
|
}
|
|
Some(Property::RateLimitAnonymous) => self.rate_limit_anonymous.patch(pointer, value),
|
|
Some(Property::AllowedEndpoints) => self.allowed_endpoints.patch(pointer, value),
|
|
Some(Property::EnableHsts) => self.enable_hsts.patch(pointer, value),
|
|
Some(Property::UsePermissiveCors) => self.use_permissive_cors.patch(pointer, value),
|
|
Some(Property::ResponseHeaders) => self
|
|
.response_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::UseXForwarded) => self.use_x_forwarded.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpAuth {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
HttpAuth::Unauthenticated => true,
|
|
HttpAuth::Basic(inner) => inner.validate(errors),
|
|
HttpAuth::Bearer(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for HttpAuth {
|
|
fn default() -> Self {
|
|
HttpAuth::Unauthenticated
|
|
}
|
|
}
|
|
|
|
impl Pickle for HttpAuth {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
HttpAuth::Unauthenticated => {
|
|
0u16.pickle(out);
|
|
}
|
|
HttpAuth::Basic(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
HttpAuth::Bearer(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(HttpAuth::Unauthenticated),
|
|
1 => Pickle::unpickle(stream).map(HttpAuth::Basic),
|
|
2 => Pickle::unpickle(stream).map(HttpAuth::Bearer),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpAuth {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
HttpAuth::Unauthenticated => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Unauthenticated".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
HttpAuth::Basic(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Basic".into()));
|
|
obj
|
|
}
|
|
HttpAuth::Bearer(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Bearer".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for HttpAuth {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
HttpAuthType::Unauthenticated => *self = HttpAuth::Unauthenticated,
|
|
HttpAuthType::Basic => *self = HttpAuth::Basic(Default::default()),
|
|
HttpAuthType::Bearer => *self = HttpAuth::Bearer(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
HttpAuth::Unauthenticated => pointer.assert_eof(),
|
|
HttpAuth::Basic(inner) => inner.patch(pointer, value),
|
|
HttpAuth::Bearer(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpAuth {
|
|
pub fn object_type(&self) -> HttpAuthType {
|
|
match self {
|
|
HttpAuth::Unauthenticated => HttpAuthType::Unauthenticated,
|
|
HttpAuth::Basic(_) => HttpAuthType::Basic,
|
|
HttpAuth::Bearer(_) => HttpAuthType::Bearer,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpAuthBasic {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.username;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Username));
|
|
}
|
|
let value = &self.secret;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for HttpAuthBasic {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.username.pickle(out);
|
|
self.secret.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.username = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for HttpAuthBasic {
|
|
fn default() -> Self {
|
|
Self {
|
|
username: Default::default(),
|
|
secret: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpAuthBasic {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Username, self.username.into_value());
|
|
map.insert_unchecked(Property::Secret, self.secret.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for HttpAuthBasic {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Username) => self
|
|
.username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpAuthBearer {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.bearer_token;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for HttpAuthBearer {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.bearer_token.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.bearer_token = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for HttpAuthBearer {
|
|
fn default() -> Self {
|
|
Self {
|
|
bearer_token: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpAuthBearer {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::BearerToken, self.bearer_token.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for HttpAuthBearer {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::BearerToken) => self.bearer_token.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for HttpForm {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::HttpForm;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.deliver_to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DeliverTo));
|
|
}
|
|
}
|
|
let value = &self.default_from_address;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultFromAddress));
|
|
}
|
|
if let Some(value) = &self.field_email {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FieldEmail));
|
|
}
|
|
}
|
|
if let Some(value) = &self.field_honey_pot {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FieldHoneyPot));
|
|
}
|
|
}
|
|
let value = &self.default_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultName));
|
|
}
|
|
if let Some(value) = &self.field_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FieldName));
|
|
}
|
|
}
|
|
if let Some(value) = &self.rate_limit {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.default_subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultSubject));
|
|
}
|
|
if let Some(value) = &self.field_subject {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FieldSubject));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for HttpForm {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.deliver_to.pickle(out);
|
|
self.default_from_address.pickle(out);
|
|
self.field_email.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.field_honey_pot.pickle(out);
|
|
self.max_size.pickle(out);
|
|
self.default_name.pickle(out);
|
|
self.field_name.pickle(out);
|
|
self.rate_limit.pickle(out);
|
|
self.default_subject.pickle(out);
|
|
self.field_subject.pickle(out);
|
|
self.validate_domain.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.deliver_to = Pickle::unpickle(stream)?;
|
|
this.default_from_address = Pickle::unpickle(stream)?;
|
|
this.field_email = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.field_honey_pot = Pickle::unpickle(stream)?;
|
|
this.max_size = Pickle::unpickle(stream)?;
|
|
this.default_name = Pickle::unpickle(stream)?;
|
|
this.field_name = Pickle::unpickle(stream)?;
|
|
this.rate_limit = Pickle::unpickle(stream)?;
|
|
this.default_subject = Pickle::unpickle(stream)?;
|
|
this.field_subject = Pickle::unpickle(stream)?;
|
|
this.validate_domain = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for HttpForm {
|
|
fn default() -> Self {
|
|
Self {
|
|
deliver_to: Default::default(),
|
|
default_from_address: "postmaster@localhost".to_string(),
|
|
field_email: Default::default(),
|
|
enable: false,
|
|
field_honey_pot: Default::default(),
|
|
max_size: 102400,
|
|
default_name: "Anonymous".to_string(),
|
|
field_name: Default::default(),
|
|
rate_limit: Some(Rate {
|
|
count: 5u64,
|
|
period: Duration::from_millis(3600000),
|
|
}),
|
|
default_subject: "Contact form submission".to_string(),
|
|
field_subject: Default::default(),
|
|
validate_domain: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpForm {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::DeliverTo, self.deliver_to.into_value());
|
|
map.insert_unchecked(
|
|
Property::DefaultFromAddress,
|
|
self.default_from_address.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::FieldEmail, self.field_email.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::FieldHoneyPot, self.field_honey_pot.into_value());
|
|
map.insert_unchecked(Property::MaxSize, self.max_size.into_value());
|
|
map.insert_unchecked(Property::DefaultName, self.default_name.into_value());
|
|
map.insert_unchecked(Property::FieldName, self.field_name.into_value());
|
|
map.insert_unchecked(Property::RateLimit, self.rate_limit.into_value());
|
|
map.insert_unchecked(Property::DefaultSubject, self.default_subject.into_value());
|
|
map.insert_unchecked(Property::FieldSubject, self.field_subject.into_value());
|
|
map.insert_unchecked(Property::ValidateDomain, self.validate_domain.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for HttpForm {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DeliverTo) => self
|
|
.deliver_to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::DefaultFromAddress) => self
|
|
.default_from_address
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::FieldEmail) => self
|
|
.field_email
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::FieldHoneyPot) => self
|
|
.field_honey_pot
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MaxSize) => self.max_size.patch(pointer, value),
|
|
Some(Property::DefaultName) => self
|
|
.default_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::FieldName) => self
|
|
.field_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::RateLimit) => self.rate_limit.patch(pointer, value),
|
|
Some(Property::DefaultSubject) => self
|
|
.default_subject
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::FieldSubject) => self
|
|
.field_subject
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ValidateDomain) => self.validate_domain.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for HttpLookup {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::HttpLookup;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.namespace;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Namespace));
|
|
}
|
|
let value = &self.format;
|
|
value.validate(errors);
|
|
let value = &self.max_entries;
|
|
if *value > 1048576 {
|
|
errors.push(ValidationError::max_value(Property::MaxEntries, 1048576));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxEntries, 1));
|
|
}
|
|
let value = &self.max_entry_size;
|
|
if *value > 1048576 {
|
|
errors.push(ValidationError::max_value(Property::MaxEntrySize, 1048576));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxEntrySize, 1));
|
|
}
|
|
let value = &self.max_size;
|
|
if *value > 1073741824 {
|
|
errors.push(ValidationError::max_value(Property::MaxSize, 1073741824));
|
|
}
|
|
if *value < 10 {
|
|
errors.push(ValidationError::min_value(Property::MaxSize, 10));
|
|
}
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global(Property::Namespace, &self.namespace);
|
|
}
|
|
}
|
|
|
|
impl Pickle for HttpLookup {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.namespace.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.format.pickle(out);
|
|
self.is_gzipped.pickle(out);
|
|
self.max_entries.pickle(out);
|
|
self.max_entry_size.pickle(out);
|
|
self.max_size.pickle(out);
|
|
self.refresh.pickle(out);
|
|
self.retry.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.url.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.namespace = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.format = Pickle::unpickle(stream)?;
|
|
this.is_gzipped = Pickle::unpickle(stream)?;
|
|
this.max_entries = Pickle::unpickle(stream)?;
|
|
this.max_entry_size = Pickle::unpickle(stream)?;
|
|
this.max_size = Pickle::unpickle(stream)?;
|
|
this.refresh = Pickle::unpickle(stream)?;
|
|
this.retry = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.url = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for HttpLookup {
|
|
fn default() -> Self {
|
|
Self {
|
|
namespace: Default::default(),
|
|
enable: true,
|
|
format: Default::default(),
|
|
is_gzipped: false,
|
|
max_entries: 100000u64,
|
|
max_entry_size: 512u64,
|
|
max_size: 104857600,
|
|
refresh: Duration::from_millis(43200000),
|
|
retry: Duration::from_millis(3600000),
|
|
timeout: Duration::from_millis(30000),
|
|
url: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpLookup {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::Namespace, self.namespace.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Format, self.format.into_value());
|
|
map.insert_unchecked(Property::IsGzipped, self.is_gzipped.into_value());
|
|
map.insert_unchecked(Property::MaxEntries, self.max_entries.into_value());
|
|
map.insert_unchecked(Property::MaxEntrySize, self.max_entry_size.into_value());
|
|
map.insert_unchecked(Property::MaxSize, self.max_size.into_value());
|
|
map.insert_unchecked(Property::Refresh, self.refresh.into_value());
|
|
map.insert_unchecked(Property::Retry, self.retry.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for HttpLookup {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Namespace) => self.namespace.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Trim]),
|
|
value,
|
|
),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Format) => self.format.patch(pointer, value),
|
|
Some(Property::IsGzipped) => self.is_gzipped.patch(pointer, value),
|
|
Some(Property::MaxEntries) => self.max_entries.patch(pointer, value),
|
|
Some(Property::MaxEntrySize) => self.max_entry_size.patch(pointer, value),
|
|
Some(Property::MaxSize) => self.max_size.patch(pointer, value),
|
|
Some(Property::Refresh) => self.refresh.patch(pointer, value),
|
|
Some(Property::Retry) => self.retry.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpLookupCsv {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.separator;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Separator));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for HttpLookupCsv {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.index_key.pickle(out);
|
|
self.index_value.pickle(out);
|
|
self.separator.pickle(out);
|
|
self.skip_first.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.index_key = Pickle::unpickle(stream)?;
|
|
this.index_value = Pickle::unpickle(stream)?;
|
|
this.separator = Pickle::unpickle(stream)?;
|
|
this.skip_first = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for HttpLookupCsv {
|
|
fn default() -> Self {
|
|
Self {
|
|
index_key: 0u64,
|
|
index_value: Default::default(),
|
|
separator: ",".to_string(),
|
|
skip_first: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpLookupCsv {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::IndexKey, self.index_key.into_value());
|
|
map.insert_unchecked(Property::IndexValue, self.index_value.into_value());
|
|
map.insert_unchecked(Property::Separator, self.separator.into_value());
|
|
map.insert_unchecked(Property::SkipFirst, self.skip_first.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for HttpLookupCsv {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::IndexKey) => self.index_key.patch(pointer, value),
|
|
Some(Property::IndexValue) => self.index_value.patch(pointer, value),
|
|
Some(Property::Separator) => self
|
|
.separator
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::SkipFirst) => self.skip_first.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpLookupFormat {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
HttpLookupFormat::Csv(inner) => inner.validate(errors),
|
|
HttpLookupFormat::List => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for HttpLookupFormat {
|
|
fn default() -> Self {
|
|
HttpLookupFormat::Csv(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for HttpLookupFormat {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
HttpLookupFormat::Csv(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
HttpLookupFormat::List => {
|
|
1u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(HttpLookupFormat::Csv),
|
|
1 => Some(HttpLookupFormat::List),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for HttpLookupFormat {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
HttpLookupFormat::Csv(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Csv".into()));
|
|
obj
|
|
}
|
|
HttpLookupFormat::List => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("List".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for HttpLookupFormat {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
HttpLookupFormatType::Csv => *self = HttpLookupFormat::Csv(Default::default()),
|
|
HttpLookupFormatType::List => *self = HttpLookupFormat::List,
|
|
}
|
|
}
|
|
match self {
|
|
HttpLookupFormat::Csv(inner) => inner.patch(pointer, value),
|
|
HttpLookupFormat::List => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpLookupFormat {
|
|
pub fn object_type(&self) -> HttpLookupFormatType {
|
|
match self {
|
|
HttpLookupFormat::Csv(_) => HttpLookupFormatType::Csv,
|
|
HttpLookupFormat::List => HttpLookupFormatType::List,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Imap {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Imap;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_auth_failures;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxAuthFailures, 1));
|
|
}
|
|
if let Some(value) = &self.max_concurrent {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxConcurrent, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_request_rate {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Imap {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.allow_plain_text_auth.pickle(out);
|
|
self.max_auth_failures.pickle(out);
|
|
self.max_concurrent.pickle(out);
|
|
self.max_request_rate.pickle(out);
|
|
self.max_request_size.pickle(out);
|
|
self.timeout_anonymous.pickle(out);
|
|
self.timeout_authenticated.pickle(out);
|
|
self.timeout_idle.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.allow_plain_text_auth = Pickle::unpickle(stream)?;
|
|
this.max_auth_failures = Pickle::unpickle(stream)?;
|
|
this.max_concurrent = Pickle::unpickle(stream)?;
|
|
this.max_request_rate = Pickle::unpickle(stream)?;
|
|
this.max_request_size = Pickle::unpickle(stream)?;
|
|
this.timeout_anonymous = Pickle::unpickle(stream)?;
|
|
this.timeout_authenticated = Pickle::unpickle(stream)?;
|
|
this.timeout_idle = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Imap {
|
|
fn default() -> Self {
|
|
Self {
|
|
allow_plain_text_auth: false,
|
|
max_auth_failures: 3u64,
|
|
max_concurrent: Some(16u64),
|
|
max_request_rate: Some(Rate {
|
|
count: 2000u64,
|
|
period: Duration::from_millis(60000),
|
|
}),
|
|
max_request_size: 52428800,
|
|
timeout_anonymous: Duration::from_millis(60000),
|
|
timeout_authenticated: Duration::from_millis(1800000),
|
|
timeout_idle: Duration::from_millis(1800000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Imap {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(
|
|
Property::AllowPlainTextAuth,
|
|
self.allow_plain_text_auth.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxAuthFailures,
|
|
self.max_auth_failures.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxConcurrent, self.max_concurrent.into_value());
|
|
map.insert_unchecked(Property::MaxRequestRate, self.max_request_rate.into_value());
|
|
map.insert_unchecked(Property::MaxRequestSize, self.max_request_size.into_value());
|
|
map.insert_unchecked(
|
|
Property::TimeoutAnonymous,
|
|
self.timeout_anonymous.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TimeoutAuthenticated,
|
|
self.timeout_authenticated.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::TimeoutIdle, self.timeout_idle.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Imap {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AllowPlainTextAuth) => self.allow_plain_text_auth.patch(pointer, value),
|
|
Some(Property::MaxAuthFailures) => self.max_auth_failures.patch(pointer, value),
|
|
Some(Property::MaxConcurrent) => self.max_concurrent.patch(pointer, value),
|
|
Some(Property::MaxRequestRate) => self.max_request_rate.patch(pointer, value),
|
|
Some(Property::MaxRequestSize) => self.max_request_size.patch(pointer, value),
|
|
Some(Property::TimeoutAnonymous) => self.timeout_anonymous.patch(pointer, value),
|
|
Some(Property::TimeoutAuthenticated) => {
|
|
self.timeout_authenticated.patch(pointer, value)
|
|
}
|
|
Some(Property::TimeoutIdle) => self.timeout_idle.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for InMemoryStore {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::InMemoryStore;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
InMemoryStore::Default => true,
|
|
InMemoryStore::Sharded(inner) => inner.validate(errors),
|
|
InMemoryStore::Redis(inner) => inner.validate(errors),
|
|
InMemoryStore::RedisCluster(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for InMemoryStore {
|
|
fn default() -> Self {
|
|
InMemoryStore::Default
|
|
}
|
|
}
|
|
|
|
impl Pickle for InMemoryStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
InMemoryStore::Default => {
|
|
0u16.pickle(out);
|
|
}
|
|
InMemoryStore::Sharded(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
InMemoryStore::Redis(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
InMemoryStore::RedisCluster(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(InMemoryStore::Default),
|
|
1 => Pickle::unpickle(stream).map(InMemoryStore::Sharded),
|
|
2 => Pickle::unpickle(stream).map(InMemoryStore::Redis),
|
|
3 => Pickle::unpickle(stream).map(InMemoryStore::RedisCluster),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for InMemoryStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
InMemoryStore::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
InMemoryStore::Sharded(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sharded".into()));
|
|
obj
|
|
}
|
|
InMemoryStore::Redis(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Redis".into()));
|
|
obj
|
|
}
|
|
InMemoryStore::RedisCluster(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for InMemoryStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
InMemoryStoreType::Default => *self = InMemoryStore::Default,
|
|
InMemoryStoreType::Sharded => *self = InMemoryStore::Sharded(Default::default()),
|
|
InMemoryStoreType::Redis => *self = InMemoryStore::Redis(Default::default()),
|
|
InMemoryStoreType::RedisCluster => {
|
|
*self = InMemoryStore::RedisCluster(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
InMemoryStore::Default => pointer.assert_eof(),
|
|
InMemoryStore::Sharded(inner) => inner.patch(pointer, value),
|
|
InMemoryStore::Redis(inner) => inner.patch(pointer, value),
|
|
InMemoryStore::RedisCluster(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl InMemoryStore {
|
|
pub fn object_type(&self) -> InMemoryStoreType {
|
|
match self {
|
|
InMemoryStore::Default => InMemoryStoreType::Default,
|
|
InMemoryStore::Sharded(_) => InMemoryStoreType::Sharded,
|
|
InMemoryStore::Redis(_) => InMemoryStoreType::Redis,
|
|
InMemoryStore::RedisCluster(_) => InMemoryStoreType::RedisCluster,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl InMemoryStoreBase {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
InMemoryStoreBase::Redis(inner) => inner.validate(errors),
|
|
InMemoryStoreBase::RedisCluster(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for InMemoryStoreBase {
|
|
fn default() -> Self {
|
|
InMemoryStoreBase::Redis(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for InMemoryStoreBase {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
InMemoryStoreBase::Redis(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
InMemoryStoreBase::RedisCluster(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(InMemoryStoreBase::Redis),
|
|
1 => Pickle::unpickle(stream).map(InMemoryStoreBase::RedisCluster),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for InMemoryStoreBase {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
InMemoryStoreBase::Redis(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Redis".into()));
|
|
obj
|
|
}
|
|
InMemoryStoreBase::RedisCluster(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for InMemoryStoreBase {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
InMemoryStoreBaseType::Redis => {
|
|
*self = InMemoryStoreBase::Redis(Default::default())
|
|
}
|
|
InMemoryStoreBaseType::RedisCluster => {
|
|
*self = InMemoryStoreBase::RedisCluster(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
InMemoryStoreBase::Redis(inner) => inner.patch(pointer, value),
|
|
InMemoryStoreBase::RedisCluster(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl InMemoryStoreBase {
|
|
pub fn object_type(&self) -> InMemoryStoreBaseType {
|
|
match self {
|
|
InMemoryStoreBase::Redis(_) => InMemoryStoreBaseType::Redis,
|
|
InMemoryStoreBase::RedisCluster(_) => InMemoryStoreBaseType::RedisCluster,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Jmap {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Jmap;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.parse_limit_event;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ParseLimitEvent, 1));
|
|
}
|
|
let value = &self.parse_limit_contact;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ParseLimitContact, 1));
|
|
}
|
|
let value = &self.parse_limit_email;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ParseLimitEmail, 1));
|
|
}
|
|
let value = &self.changes_max_results;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ChangesMaxResults, 1));
|
|
}
|
|
let value = &self.get_max_results;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::GetMaxResults, 1));
|
|
}
|
|
let value = &self.query_max_results;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::QueryMaxResults, 1));
|
|
}
|
|
let value = &self.max_method_calls;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMethodCalls, 1));
|
|
}
|
|
if let Some(value) = &self.max_concurrent_requests {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::MaxConcurrentRequests,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
let value = &self.max_request_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxRequestSize, 1));
|
|
}
|
|
let value = &self.set_max_objects;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::SetMaxObjects, 1));
|
|
}
|
|
let value = &self.snippet_max_results;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::SnippetMaxResults, 1));
|
|
}
|
|
if let Some(value) = &self.max_concurrent_uploads {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::MaxConcurrentUploads,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
let value = &self.max_upload_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxUploadSize, 1));
|
|
}
|
|
let value = &self.max_upload_count;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxUploadCount, 1));
|
|
}
|
|
let value = &self.upload_quota;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::UploadQuota, 1));
|
|
}
|
|
let value = &self.push_max_attempts;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PushMaxAttempts, 1));
|
|
}
|
|
let value = &self.push_shards_total;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PushShardsTotal, 1));
|
|
}
|
|
if let Some(value) = &self.max_subscriptions {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxSubscriptions, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Jmap {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.parse_limit_event.pickle(out);
|
|
self.parse_limit_contact.pickle(out);
|
|
self.parse_limit_email.pickle(out);
|
|
self.changes_max_results.pickle(out);
|
|
self.get_max_results.pickle(out);
|
|
self.query_max_results.pickle(out);
|
|
self.max_method_calls.pickle(out);
|
|
self.max_concurrent_requests.pickle(out);
|
|
self.max_request_size.pickle(out);
|
|
self.set_max_objects.pickle(out);
|
|
self.snippet_max_results.pickle(out);
|
|
self.max_concurrent_uploads.pickle(out);
|
|
self.max_upload_size.pickle(out);
|
|
self.max_upload_count.pickle(out);
|
|
self.upload_quota.pickle(out);
|
|
self.upload_ttl.pickle(out);
|
|
self.event_source_throttle.pickle(out);
|
|
self.push_attempt_wait.pickle(out);
|
|
self.push_max_attempts.pickle(out);
|
|
self.push_retry_wait.pickle(out);
|
|
self.push_throttle.pickle(out);
|
|
self.push_request_timeout.pickle(out);
|
|
self.push_verify_timeout.pickle(out);
|
|
self.push_shards_total.pickle(out);
|
|
self.websocket_heartbeat.pickle(out);
|
|
self.websocket_throttle.pickle(out);
|
|
self.websocket_timeout.pickle(out);
|
|
self.max_subscriptions.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.parse_limit_event = Pickle::unpickle(stream)?;
|
|
this.parse_limit_contact = Pickle::unpickle(stream)?;
|
|
this.parse_limit_email = Pickle::unpickle(stream)?;
|
|
this.changes_max_results = Pickle::unpickle(stream)?;
|
|
this.get_max_results = Pickle::unpickle(stream)?;
|
|
this.query_max_results = Pickle::unpickle(stream)?;
|
|
this.max_method_calls = Pickle::unpickle(stream)?;
|
|
this.max_concurrent_requests = Pickle::unpickle(stream)?;
|
|
this.max_request_size = Pickle::unpickle(stream)?;
|
|
this.set_max_objects = Pickle::unpickle(stream)?;
|
|
this.snippet_max_results = Pickle::unpickle(stream)?;
|
|
this.max_concurrent_uploads = Pickle::unpickle(stream)?;
|
|
this.max_upload_size = Pickle::unpickle(stream)?;
|
|
this.max_upload_count = Pickle::unpickle(stream)?;
|
|
this.upload_quota = Pickle::unpickle(stream)?;
|
|
this.upload_ttl = Pickle::unpickle(stream)?;
|
|
this.event_source_throttle = Pickle::unpickle(stream)?;
|
|
this.push_attempt_wait = Pickle::unpickle(stream)?;
|
|
this.push_max_attempts = Pickle::unpickle(stream)?;
|
|
this.push_retry_wait = Pickle::unpickle(stream)?;
|
|
this.push_throttle = Pickle::unpickle(stream)?;
|
|
this.push_request_timeout = Pickle::unpickle(stream)?;
|
|
this.push_verify_timeout = Pickle::unpickle(stream)?;
|
|
this.push_shards_total = Pickle::unpickle(stream)?;
|
|
this.websocket_heartbeat = Pickle::unpickle(stream)?;
|
|
this.websocket_throttle = Pickle::unpickle(stream)?;
|
|
this.websocket_timeout = Pickle::unpickle(stream)?;
|
|
this.max_subscriptions = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Jmap {
|
|
fn default() -> Self {
|
|
Self {
|
|
parse_limit_event: 10u64,
|
|
parse_limit_contact: 10u64,
|
|
parse_limit_email: 10u64,
|
|
changes_max_results: 5000u64,
|
|
get_max_results: 500u64,
|
|
query_max_results: 5000u64,
|
|
max_method_calls: 16u64,
|
|
max_concurrent_requests: Some(4u64),
|
|
max_request_size: 10000000u64,
|
|
set_max_objects: 500u64,
|
|
snippet_max_results: 100u64,
|
|
max_concurrent_uploads: Some(4u64),
|
|
max_upload_size: 50000000u64,
|
|
max_upload_count: 1000u64,
|
|
upload_quota: 50000000u64,
|
|
upload_ttl: Duration::from_millis(3600000),
|
|
event_source_throttle: Duration::from_millis(1000),
|
|
push_attempt_wait: Duration::from_millis(60000),
|
|
push_max_attempts: 3u64,
|
|
push_retry_wait: Duration::from_millis(1000),
|
|
push_throttle: Duration::from_millis(1000),
|
|
push_request_timeout: Duration::from_millis(10000),
|
|
push_verify_timeout: Duration::from_millis(60000),
|
|
push_shards_total: 1u64,
|
|
websocket_heartbeat: Duration::from_millis(60000),
|
|
websocket_throttle: Duration::from_millis(1000),
|
|
websocket_timeout: Duration::from_millis(600000),
|
|
max_subscriptions: Some(15u64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Jmap {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(30);
|
|
map.insert_unchecked(
|
|
Property::ParseLimitEvent,
|
|
self.parse_limit_event.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ParseLimitContact,
|
|
self.parse_limit_contact.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ParseLimitEmail,
|
|
self.parse_limit_email.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ChangesMaxResults,
|
|
self.changes_max_results.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::GetMaxResults, self.get_max_results.into_value());
|
|
map.insert_unchecked(
|
|
Property::QueryMaxResults,
|
|
self.query_max_results.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxMethodCalls, self.max_method_calls.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxConcurrentRequests,
|
|
self.max_concurrent_requests.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxRequestSize, self.max_request_size.into_value());
|
|
map.insert_unchecked(Property::SetMaxObjects, self.set_max_objects.into_value());
|
|
map.insert_unchecked(
|
|
Property::SnippetMaxResults,
|
|
self.snippet_max_results.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxConcurrentUploads,
|
|
self.max_concurrent_uploads.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxUploadSize, self.max_upload_size.into_value());
|
|
map.insert_unchecked(Property::MaxUploadCount, self.max_upload_count.into_value());
|
|
map.insert_unchecked(Property::UploadQuota, self.upload_quota.into_value());
|
|
map.insert_unchecked(Property::UploadTtl, self.upload_ttl.into_value());
|
|
map.insert_unchecked(
|
|
Property::EventSourceThrottle,
|
|
self.event_source_throttle.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PushAttemptWait,
|
|
self.push_attempt_wait.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PushMaxAttempts,
|
|
self.push_max_attempts.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::PushRetryWait, self.push_retry_wait.into_value());
|
|
map.insert_unchecked(Property::PushThrottle, self.push_throttle.into_value());
|
|
map.insert_unchecked(
|
|
Property::PushRequestTimeout,
|
|
self.push_request_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PushVerifyTimeout,
|
|
self.push_verify_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PushShardsTotal,
|
|
self.push_shards_total.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::WebsocketHeartbeat,
|
|
self.websocket_heartbeat.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::WebsocketThrottle,
|
|
self.websocket_throttle.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::WebsocketTimeout,
|
|
self.websocket_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxSubscriptions,
|
|
self.max_subscriptions.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Jmap {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ParseLimitEvent) => self.parse_limit_event.patch(pointer, value),
|
|
Some(Property::ParseLimitContact) => self.parse_limit_contact.patch(pointer, value),
|
|
Some(Property::ParseLimitEmail) => self.parse_limit_email.patch(pointer, value),
|
|
Some(Property::ChangesMaxResults) => self.changes_max_results.patch(pointer, value),
|
|
Some(Property::GetMaxResults) => self.get_max_results.patch(pointer, value),
|
|
Some(Property::QueryMaxResults) => self.query_max_results.patch(pointer, value),
|
|
Some(Property::MaxMethodCalls) => self.max_method_calls.patch(pointer, value),
|
|
Some(Property::MaxConcurrentRequests) => {
|
|
self.max_concurrent_requests.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxRequestSize) => self.max_request_size.patch(pointer, value),
|
|
Some(Property::SetMaxObjects) => self.set_max_objects.patch(pointer, value),
|
|
Some(Property::SnippetMaxResults) => self.snippet_max_results.patch(pointer, value),
|
|
Some(Property::MaxConcurrentUploads) => {
|
|
self.max_concurrent_uploads.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxUploadSize) => self.max_upload_size.patch(pointer, value),
|
|
Some(Property::MaxUploadCount) => self.max_upload_count.patch(pointer, value),
|
|
Some(Property::UploadQuota) => self.upload_quota.patch(pointer, value),
|
|
Some(Property::UploadTtl) => self.upload_ttl.patch(pointer, value),
|
|
Some(Property::EventSourceThrottle) => self.event_source_throttle.patch(pointer, value),
|
|
Some(Property::PushAttemptWait) => self.push_attempt_wait.patch(pointer, value),
|
|
Some(Property::PushMaxAttempts) => self.push_max_attempts.patch(pointer, value),
|
|
Some(Property::PushRetryWait) => self.push_retry_wait.patch(pointer, value),
|
|
Some(Property::PushThrottle) => self.push_throttle.patch(pointer, value),
|
|
Some(Property::PushRequestTimeout) => self.push_request_timeout.patch(pointer, value),
|
|
Some(Property::PushVerifyTimeout) => self.push_verify_timeout.patch(pointer, value),
|
|
Some(Property::PushShardsTotal) => self.push_shards_total.patch(pointer, value),
|
|
Some(Property::WebsocketHeartbeat) => self.websocket_heartbeat.patch(pointer, value),
|
|
Some(Property::WebsocketThrottle) => self.websocket_throttle.patch(pointer, value),
|
|
Some(Property::WebsocketTimeout) => self.websocket_timeout.patch(pointer, value),
|
|
Some(Property::MaxSubscriptions) => self.max_subscriptions.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl KafkaCoordinator {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.brokers;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Brokers));
|
|
}
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Brokers, 1));
|
|
}
|
|
let value = &self.group_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::GroupId));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for KafkaCoordinator {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.brokers.pickle(out);
|
|
self.group_id.pickle(out);
|
|
self.timeout_message.pickle(out);
|
|
self.timeout_session.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.brokers = Pickle::unpickle(stream)?;
|
|
this.group_id = Pickle::unpickle(stream)?;
|
|
this.timeout_message = Pickle::unpickle(stream)?;
|
|
this.timeout_session = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for KafkaCoordinator {
|
|
fn default() -> Self {
|
|
Self {
|
|
brokers: Default::default(),
|
|
group_id: Default::default(),
|
|
timeout_message: Duration::from_millis(5000),
|
|
timeout_session: Duration::from_millis(5000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for KafkaCoordinator {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Brokers, self.brokers.into_value());
|
|
map.insert_unchecked(Property::GroupId, self.group_id.into_value());
|
|
map.insert_unchecked(Property::TimeoutMessage, self.timeout_message.into_value());
|
|
map.insert_unchecked(Property::TimeoutSession, self.timeout_session.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for KafkaCoordinator {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Brokers) => self.brokers.patch(pointer, value),
|
|
Some(Property::GroupId) => self
|
|
.group_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::TimeoutMessage) => self.timeout_message.patch(pointer, value),
|
|
Some(Property::TimeoutSession) => self.timeout_session.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl LdapDirectory {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.base_dn;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BaseDn));
|
|
}
|
|
if let Some(value) = &self.bind_dn {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BindDn));
|
|
}
|
|
}
|
|
let value = &self.bind_secret;
|
|
value.validate(errors);
|
|
let value = &self.filter_login;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FilterLogin));
|
|
}
|
|
let value = &self.filter_mailbox;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FilterMailbox));
|
|
}
|
|
if let Some(value) = &self.filter_member_of {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FilterMemberOf));
|
|
}
|
|
}
|
|
let value = &self.attr_class;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrClass));
|
|
}
|
|
}
|
|
let value = &self.attr_description;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrDescription));
|
|
}
|
|
}
|
|
let value = &self.attr_email;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrEmail));
|
|
}
|
|
}
|
|
let value = &self.attr_email_alias;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrEmailAlias));
|
|
}
|
|
}
|
|
let value = &self.attr_member_of;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrMemberOf));
|
|
}
|
|
}
|
|
let value = &self.attr_secret;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrSecret));
|
|
}
|
|
}
|
|
let value = &self.attr_secret_changed;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AttrSecretChanged));
|
|
}
|
|
}
|
|
let value = &self.group_class;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::GroupClass));
|
|
}
|
|
let value = &self.pool_max_connections;
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMaxConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for LdapDirectory {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.url.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.use_tls.pickle(out);
|
|
self.base_dn.pickle(out);
|
|
self.bind_dn.pickle(out);
|
|
self.bind_secret.pickle(out);
|
|
self.bind_authentication.pickle(out);
|
|
self.filter_login.pickle(out);
|
|
self.filter_mailbox.pickle(out);
|
|
self.filter_member_of.pickle(out);
|
|
self.attr_class.pickle(out);
|
|
self.attr_description.pickle(out);
|
|
self.attr_email.pickle(out);
|
|
self.attr_email_alias.pickle(out);
|
|
self.attr_member_of.pickle(out);
|
|
self.attr_secret.pickle(out);
|
|
self.attr_secret_changed.pickle(out);
|
|
self.group_class.pickle(out);
|
|
self.pool_max_connections.pickle(out);
|
|
self.pool_timeout_create.pickle(out);
|
|
self.pool_timeout_recycle.pickle(out);
|
|
self.pool_timeout_wait.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.base_dn = Pickle::unpickle(stream)?;
|
|
this.bind_dn = Pickle::unpickle(stream)?;
|
|
this.bind_secret = Pickle::unpickle(stream)?;
|
|
this.bind_authentication = Pickle::unpickle(stream)?;
|
|
this.filter_login = Pickle::unpickle(stream)?;
|
|
this.filter_mailbox = Pickle::unpickle(stream)?;
|
|
this.filter_member_of = Pickle::unpickle(stream)?;
|
|
this.attr_class = Pickle::unpickle(stream)?;
|
|
this.attr_description = Pickle::unpickle(stream)?;
|
|
this.attr_email = Pickle::unpickle(stream)?;
|
|
this.attr_email_alias = Pickle::unpickle(stream)?;
|
|
this.attr_member_of = Pickle::unpickle(stream)?;
|
|
this.attr_secret = Pickle::unpickle(stream)?;
|
|
this.attr_secret_changed = Pickle::unpickle(stream)?;
|
|
this.group_class = Pickle::unpickle(stream)?;
|
|
this.pool_max_connections = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_create = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_recycle = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_wait = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for LdapDirectory {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
url: "ldap://localhost:389".to_string(),
|
|
timeout: Duration::from_millis(30000),
|
|
allow_invalid_certs: false,
|
|
use_tls: false,
|
|
base_dn: Default::default(),
|
|
bind_dn: Default::default(),
|
|
bind_secret: Default::default(),
|
|
bind_authentication: true,
|
|
filter_login: "(&(objectClass=inetOrgPerson)(mail=?))".to_string(),
|
|
filter_mailbox: "(|(&(objectClass=inetOrgPerson)(|(mail=?)(mailAlias=?)))(&(objectClass=groupOfNames)(|(mail=?)(mailAlias=?))))".to_string(),
|
|
filter_member_of: Some("(&(objectClass=groupOfNames)(member=?))".to_string()),
|
|
attr_class: Map::new(vec!["objectClass".to_string()]),
|
|
attr_description: Map::new(vec!["description".to_string()]),
|
|
attr_email: Map::new(vec!["mail".to_string()]),
|
|
attr_email_alias: Map::new(vec!["mailAlias".to_string()]),
|
|
attr_member_of: Map::new(vec!["memberOf".to_string()]),
|
|
attr_secret: Map::new(vec!["userPassword".to_string()]),
|
|
attr_secret_changed: Map::new(vec!["pwdChangeTime".to_string()]),
|
|
group_class: "groupOfNames".to_string(),
|
|
pool_max_connections: 10u64,
|
|
pool_timeout_create: Duration::from_millis(30000),
|
|
pool_timeout_recycle: Duration::from_millis(30000),
|
|
pool_timeout_wait: Duration::from_millis(30000),
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for LdapDirectory {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(27);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(Property::BaseDn, self.base_dn.into_value());
|
|
map.insert_unchecked(Property::BindDn, self.bind_dn.into_value());
|
|
map.insert_unchecked(Property::BindSecret, self.bind_secret.into_value());
|
|
map.insert_unchecked(
|
|
Property::BindAuthentication,
|
|
self.bind_authentication.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::FilterLogin, self.filter_login.into_value());
|
|
map.insert_unchecked(Property::FilterMailbox, self.filter_mailbox.into_value());
|
|
map.insert_unchecked(Property::FilterMemberOf, self.filter_member_of.into_value());
|
|
map.insert_unchecked(Property::AttrClass, self.attr_class.into_value());
|
|
map.insert_unchecked(
|
|
Property::AttrDescription,
|
|
self.attr_description.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::AttrEmail, self.attr_email.into_value());
|
|
map.insert_unchecked(Property::AttrEmailAlias, self.attr_email_alias.into_value());
|
|
map.insert_unchecked(Property::AttrMemberOf, self.attr_member_of.into_value());
|
|
map.insert_unchecked(Property::AttrSecret, self.attr_secret.into_value());
|
|
map.insert_unchecked(
|
|
Property::AttrSecretChanged,
|
|
self.attr_secret_changed.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::GroupClass, self.group_class.into_value());
|
|
map.insert_unchecked(
|
|
Property::PoolMaxConnections,
|
|
self.pool_max_connections.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutCreate,
|
|
self.pool_timeout_create.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutRecycle,
|
|
self.pool_timeout_recycle.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutWait,
|
|
self.pool_timeout_wait.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for LdapDirectory {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::BaseDn) => self
|
|
.base_dn
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::BindDn) => self
|
|
.bind_dn
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::BindSecret) => self.bind_secret.patch(pointer, value),
|
|
Some(Property::BindAuthentication) => self.bind_authentication.patch(pointer, value),
|
|
Some(Property::FilterLogin) => self
|
|
.filter_login
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::FilterMailbox) => self
|
|
.filter_mailbox
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::FilterMemberOf) => self
|
|
.filter_member_of
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrClass) => self
|
|
.attr_class
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrDescription) => self
|
|
.attr_description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrEmail) => self
|
|
.attr_email
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrEmailAlias) => self
|
|
.attr_email_alias
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrMemberOf) => self
|
|
.attr_member_of
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrSecret) => self
|
|
.attr_secret
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AttrSecretChanged) => self
|
|
.attr_secret_changed
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::GroupClass) => self
|
|
.group_class
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value),
|
|
Some(Property::PoolTimeoutCreate) => self.pool_timeout_create.patch(pointer, value),
|
|
Some(Property::PoolTimeoutRecycle) => self.pool_timeout_recycle.patch(pointer, value),
|
|
Some(Property::PoolTimeoutWait) => self.pool_timeout_wait.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Log {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Log;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.timestamp;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Timestamp, value));
|
|
}
|
|
let value = &self.details;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Details));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Log {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.timestamp.pickle(out);
|
|
self.level.pickle(out);
|
|
self.event.pickle(out);
|
|
self.details.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.timestamp = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.event = Pickle::unpickle(stream)?;
|
|
this.details = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Log {
|
|
fn default() -> Self {
|
|
Self {
|
|
timestamp: Default::default(),
|
|
level: Default::default(),
|
|
event: Default::default(),
|
|
details: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Log {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Timestamp, self.timestamp.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Event, self.event.into_value());
|
|
map.insert_unchecked(Property::Details, self.details.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Log {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Timestamp) => self.timestamp.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Event) => self.event.patch(pointer, value),
|
|
Some(Property::Details) => self.details.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl LookupStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
LookupStore::PostgreSql(inner) => inner.validate(errors),
|
|
LookupStore::MySql(inner) => inner.validate(errors),
|
|
LookupStore::Sqlite(inner) => inner.validate(errors),
|
|
LookupStore::Sharded(inner) => inner.validate(errors),
|
|
LookupStore::Redis(inner) => inner.validate(errors),
|
|
LookupStore::RedisCluster(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for LookupStore {
|
|
fn default() -> Self {
|
|
LookupStore::PostgreSql(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for LookupStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
LookupStore::PostgreSql(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
LookupStore::MySql(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
LookupStore::Sqlite(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
LookupStore::Sharded(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
LookupStore::Redis(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
LookupStore::RedisCluster(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(LookupStore::PostgreSql),
|
|
1 => Pickle::unpickle(stream).map(LookupStore::MySql),
|
|
2 => Pickle::unpickle(stream).map(LookupStore::Sqlite),
|
|
3 => Pickle::unpickle(stream).map(LookupStore::Sharded),
|
|
4 => Pickle::unpickle(stream).map(LookupStore::Redis),
|
|
5 => Pickle::unpickle(stream).map(LookupStore::RedisCluster),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for LookupStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
LookupStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
LookupStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
LookupStore::Sqlite(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sqlite".into()));
|
|
obj
|
|
}
|
|
LookupStore::Sharded(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sharded".into()));
|
|
obj
|
|
}
|
|
LookupStore::Redis(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Redis".into()));
|
|
obj
|
|
}
|
|
LookupStore::RedisCluster(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for LookupStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
LookupStoreType::PostgreSql => *self = LookupStore::PostgreSql(Default::default()),
|
|
LookupStoreType::MySql => *self = LookupStore::MySql(Default::default()),
|
|
LookupStoreType::Sqlite => *self = LookupStore::Sqlite(Default::default()),
|
|
LookupStoreType::Sharded => *self = LookupStore::Sharded(Default::default()),
|
|
LookupStoreType::Redis => *self = LookupStore::Redis(Default::default()),
|
|
LookupStoreType::RedisCluster => {
|
|
*self = LookupStore::RedisCluster(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
LookupStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
LookupStore::MySql(inner) => inner.patch(pointer, value),
|
|
LookupStore::Sqlite(inner) => inner.patch(pointer, value),
|
|
LookupStore::Sharded(inner) => inner.patch(pointer, value),
|
|
LookupStore::Redis(inner) => inner.patch(pointer, value),
|
|
LookupStore::RedisCluster(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl LookupStore {
|
|
pub fn object_type(&self) -> LookupStoreType {
|
|
match self {
|
|
LookupStore::PostgreSql(_) => LookupStoreType::PostgreSql,
|
|
LookupStore::MySql(_) => LookupStoreType::MySql,
|
|
LookupStore::Sqlite(_) => LookupStoreType::Sqlite,
|
|
LookupStore::Sharded(_) => LookupStoreType::Sharded,
|
|
LookupStore::Redis(_) => LookupStoreType::Redis,
|
|
LookupStore::RedisCluster(_) => LookupStoreType::RedisCluster,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MailExchanger {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Hostname));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Priority, 1));
|
|
}
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Priority, 65535));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MailExchanger {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.hostname.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.hostname = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MailExchanger {
|
|
fn default() -> Self {
|
|
Self {
|
|
hostname: Default::default(),
|
|
priority: 10u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MailExchanger {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Hostname, self.hostname.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MailExchanger {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Hostname) => self
|
|
.hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Hostname]), value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MailingList {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MailingList;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.aliases;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
let value = &self.recipients;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Recipients));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global_composite(Property::Email, &self.name, &self.domain_id);
|
|
i.text(Property::Text, &self.name);
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
if let Some(value) = &self.description {
|
|
i.text(Property::Text, value);
|
|
}
|
|
for item in self.aliases.values() {
|
|
item.index(i);
|
|
}
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
for value in self.recipients.iter() {
|
|
i.text(Property::Text, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for MailingList {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.domain_id.pickle(out);
|
|
self.description.pickle(out);
|
|
self.aliases.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.recipients.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.aliases = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.recipients = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MailingList {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
domain_id: Default::default(),
|
|
description: Default::default(),
|
|
aliases: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
recipients: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MailingList {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Aliases, self.aliases.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Recipients, self.recipients.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MailingList {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer.with_validators(&[StringValidator::EmailLocalPart]),
|
|
value,
|
|
),
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer, value),
|
|
Some(Property::EmailAddress) => pointer.assert_server_set(),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Aliases) => self.aliases.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Recipients) => self
|
|
.recipients
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MaskedEmail {
|
|
const FLAGS: u64 = OBJ_FILTER_ACCOUNT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MaskedEmail;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.email;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Email));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
if let Some(value) = &self.for_domain {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ForDomain));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.created_by {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::CreatedBy));
|
|
}
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
if let Some(value) = &self.url {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MaskedEmail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enabled.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.email.pickle(out);
|
|
self.description.pickle(out);
|
|
self.for_domain.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.created_by.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.url.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enabled = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.email = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.for_domain = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.created_by = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.url = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MaskedEmail {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
account_id: Default::default(),
|
|
email: Default::default(),
|
|
description: Default::default(),
|
|
for_domain: Default::default(),
|
|
created_at: Default::default(),
|
|
created_by: Default::default(),
|
|
expires_at: Default::default(),
|
|
url: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MaskedEmail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Enabled, self.enabled.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::Email, self.email.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::ForDomain, self.for_domain.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::CreatedBy, self.created_by.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MaskedEmail {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enabled) => self.enabled.patch(pointer, value),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::Email) => pointer.assert_server_set(),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::ForDomain) => self.for_domain.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::CreatedBy) => self.created_by.patch(pointer, value),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Url) => self.url.patch(pointer, value),
|
|
Some(property @ Property::EmailPrefix) => {
|
|
Ok(MaybeUnpatched::Unpatched { property, value })
|
|
}
|
|
Some(property @ Property::EmailDomain) => {
|
|
Ok(MaybeUnpatched::Unpatched { property, value })
|
|
}
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MeilisearchStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.max_retries;
|
|
if *value > 1024 {
|
|
errors.push(ValidationError::max_value(Property::MaxRetries, 1024));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxRetries, 1));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MeilisearchStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.url.pickle(out);
|
|
self.poll_interval.pickle(out);
|
|
self.max_retries.pickle(out);
|
|
self.fail_on_timeout.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.poll_interval = Pickle::unpickle(stream)?;
|
|
this.max_retries = Pickle::unpickle(stream)?;
|
|
this.fail_on_timeout = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MeilisearchStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
url: Default::default(),
|
|
poll_interval: Duration::from_millis(500),
|
|
max_retries: 120u64,
|
|
fail_on_timeout: true,
|
|
timeout: Duration::from_millis(30000),
|
|
allow_invalid_certs: false,
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MeilisearchStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::PollInterval, self.poll_interval.into_value());
|
|
map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value());
|
|
map.insert_unchecked(Property::FailOnTimeout, self.fail_on_timeout.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MeilisearchStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PollInterval) => self.poll_interval.patch(pointer, value),
|
|
Some(Property::MaxRetries) => self.max_retries.patch(pointer, value),
|
|
Some(Property::FailOnTimeout) => self.fail_on_timeout.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MemoryLookupKey {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MemoryLookupKey;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.namespace;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Namespace));
|
|
}
|
|
let value = &self.key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Key));
|
|
}
|
|
if value.len() > 255 {
|
|
errors.push(ValidationError::max_length(Property::Key, 255));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global_composite(Property::Namespace, &self.namespace, &self.key);
|
|
i.search(Property::Namespace, &self.namespace);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MemoryLookupKey {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.namespace.pickle(out);
|
|
self.key.pickle(out);
|
|
self.is_glob_pattern.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.namespace = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.is_glob_pattern = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MemoryLookupKey {
|
|
fn default() -> Self {
|
|
Self {
|
|
namespace: Default::default(),
|
|
key: Default::default(),
|
|
is_glob_pattern: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MemoryLookupKey {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Namespace, self.namespace.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::IsGlobPattern, self.is_glob_pattern.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MemoryLookupKey {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Namespace) => self.namespace.patch(pointer, value),
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::IsGlobPattern) => self.is_glob_pattern.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MemoryLookupKeyValue {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MemoryLookupKeyValue;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.namespace;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Namespace));
|
|
}
|
|
let value = &self.key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Key));
|
|
}
|
|
if value.len() > 255 {
|
|
errors.push(ValidationError::max_length(Property::Key, 255));
|
|
}
|
|
let value = &self.value;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global_composite(Property::Namespace, &self.namespace, &self.key);
|
|
i.search(Property::Namespace, &self.namespace);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MemoryLookupKeyValue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.namespace.pickle(out);
|
|
self.key.pickle(out);
|
|
self.value.pickle(out);
|
|
self.is_glob_pattern.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.namespace = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.value = Pickle::unpickle(stream)?;
|
|
this.is_glob_pattern = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MemoryLookupKeyValue {
|
|
fn default() -> Self {
|
|
Self {
|
|
namespace: Default::default(),
|
|
key: Default::default(),
|
|
value: Default::default(),
|
|
is_glob_pattern: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MemoryLookupKeyValue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Namespace, self.namespace.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
map.insert_unchecked(Property::IsGlobPattern, self.is_glob_pattern.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MemoryLookupKeyValue {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Namespace) => self.namespace.patch(pointer, value),
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::IsGlobPattern) => self.is_glob_pattern.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Metric {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Metric;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Metric::Counter(inner) => inner.validate(errors),
|
|
Metric::Gauge(inner) => inner.validate(errors),
|
|
Metric::Histogram(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for Metric {
|
|
fn default() -> Self {
|
|
Metric::Counter(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Metric {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Metric::Counter(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Metric::Gauge(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Metric::Histogram(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Metric::Counter),
|
|
1 => Pickle::unpickle(stream).map(Metric::Gauge),
|
|
2 => Pickle::unpickle(stream).map(Metric::Histogram),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Metric {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Metric::Counter(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Counter".into()));
|
|
obj
|
|
}
|
|
Metric::Gauge(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Gauge".into()));
|
|
obj
|
|
}
|
|
Metric::Histogram(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Histogram".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Metric {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MetricType::Counter => *self = Metric::Counter(Default::default()),
|
|
MetricType::Gauge => *self = Metric::Gauge(Default::default()),
|
|
MetricType::Histogram => *self = Metric::Histogram(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Metric::Counter(inner) => inner.patch(pointer, value),
|
|
Metric::Gauge(inner) => inner.patch(pointer, value),
|
|
Metric::Histogram(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Metric {
|
|
pub fn object_type(&self) -> MetricType {
|
|
match self {
|
|
Metric::Counter(_) => MetricType::Counter,
|
|
Metric::Gauge(_) => MetricType::Gauge,
|
|
Metric::Histogram(_) => MetricType::Histogram,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricCount {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricCount {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.count.pickle(out);
|
|
self.metric.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.count = Pickle::unpickle(stream)?;
|
|
this.metric = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MetricCount {
|
|
fn default() -> Self {
|
|
Self {
|
|
count: 0u64,
|
|
metric: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricCount {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Count, self.count.into_value());
|
|
map.insert_unchecked(Property::Metric, self.metric.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MetricCount {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Count) => self.count.patch(pointer, value),
|
|
Some(Property::Metric) => self.metric.patch(pointer, value),
|
|
Some(property @ Property::Timestamp) => {
|
|
Ok(MaybeUnpatched::Unpatched { property, value })
|
|
}
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricSum {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricSum {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.count.pickle(out);
|
|
self.sum.pickle(out);
|
|
self.metric.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.count = Pickle::unpickle(stream)?;
|
|
this.sum = Pickle::unpickle(stream)?;
|
|
this.metric = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MetricSum {
|
|
fn default() -> Self {
|
|
Self {
|
|
count: 0u64,
|
|
sum: 0u64,
|
|
metric: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricSum {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Count, self.count.into_value());
|
|
map.insert_unchecked(Property::Sum, self.sum.into_value());
|
|
map.insert_unchecked(Property::Metric, self.metric.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MetricSum {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Count) => self.count.patch(pointer, value),
|
|
Some(Property::Sum) => self.sum.patch(pointer, value),
|
|
Some(Property::Metric) => self.metric.patch(pointer, value),
|
|
Some(property @ Property::Timestamp) => {
|
|
Ok(MaybeUnpatched::Unpatched { property, value })
|
|
}
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Metrics {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Metrics;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.open_telemetry;
|
|
value.validate(errors);
|
|
let value = &self.prometheus;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Metrics {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.open_telemetry.pickle(out);
|
|
self.prometheus.pickle(out);
|
|
self.metrics.pickle(out);
|
|
self.metrics_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.open_telemetry = Pickle::unpickle(stream)?;
|
|
this.prometheus = Pickle::unpickle(stream)?;
|
|
this.metrics = Pickle::unpickle(stream)?;
|
|
this.metrics_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Metrics {
|
|
fn default() -> Self {
|
|
Self {
|
|
open_telemetry: Default::default(),
|
|
prometheus: Default::default(),
|
|
metrics: Default::default(),
|
|
metrics_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Metrics {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::OpenTelemetry, self.open_telemetry.into_value());
|
|
map.insert_unchecked(Property::Prometheus, self.prometheus.into_value());
|
|
map.insert_unchecked(Property::Metrics, self.metrics.into_value());
|
|
map.insert_unchecked(Property::MetricsPolicy, self.metrics_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Metrics {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::OpenTelemetry) => self.open_telemetry.patch(pointer, value),
|
|
Some(Property::Prometheus) => self.prometheus.patch(pointer, value),
|
|
Some(Property::Metrics) => self.metrics.patch(pointer, value),
|
|
Some(Property::MetricsPolicy) => self.metrics_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsOtel {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
MetricsOtel::Disabled => true,
|
|
MetricsOtel::Http(inner) => inner.validate(errors),
|
|
MetricsOtel::Grpc(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MetricsOtel {
|
|
fn default() -> Self {
|
|
MetricsOtel::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricsOtel {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
MetricsOtel::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
MetricsOtel::Http(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
MetricsOtel::Grpc(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(MetricsOtel::Disabled),
|
|
1 => Pickle::unpickle(stream).map(MetricsOtel::Http),
|
|
2 => Pickle::unpickle(stream).map(MetricsOtel::Grpc),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricsOtel {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
MetricsOtel::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
MetricsOtel::Http(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Http".into()));
|
|
obj
|
|
}
|
|
MetricsOtel::Grpc(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Grpc".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for MetricsOtel {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MetricsOtelType::Disabled => *self = MetricsOtel::Disabled,
|
|
MetricsOtelType::Http => *self = MetricsOtel::Http(Default::default()),
|
|
MetricsOtelType::Grpc => *self = MetricsOtel::Grpc(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
MetricsOtel::Disabled => pointer.assert_eof(),
|
|
MetricsOtel::Http(inner) => inner.patch(pointer, value),
|
|
MetricsOtel::Grpc(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsOtel {
|
|
pub fn object_type(&self) -> MetricsOtelType {
|
|
match self {
|
|
MetricsOtel::Disabled => MetricsOtelType::Disabled,
|
|
MetricsOtel::Http(_) => MetricsOtelType::Http,
|
|
MetricsOtel::Grpc(_) => MetricsOtelType::Grpc,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsOtelGrpc {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.endpoint {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Endpoint));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricsOtelGrpc {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.endpoint.pickle(out);
|
|
self.interval.pickle(out);
|
|
self.timeout.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.endpoint = Pickle::unpickle(stream)?;
|
|
this.interval = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MetricsOtelGrpc {
|
|
fn default() -> Self {
|
|
Self {
|
|
endpoint: Default::default(),
|
|
interval: Duration::from_millis(60000),
|
|
timeout: Duration::from_millis(10000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricsOtelGrpc {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Endpoint, self.endpoint.into_value());
|
|
map.insert_unchecked(Property::Interval, self.interval.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MetricsOtelGrpc {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Endpoint) => self
|
|
.endpoint
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Interval) => self.interval.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsOtelHttp {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.endpoint;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Endpoint));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricsOtelHttp {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.endpoint.pickle(out);
|
|
self.interval.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.endpoint = Pickle::unpickle(stream)?;
|
|
this.interval = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MetricsOtelHttp {
|
|
fn default() -> Self {
|
|
Self {
|
|
endpoint: Default::default(),
|
|
interval: Duration::from_millis(60000),
|
|
timeout: Duration::from_millis(10000),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricsOtelHttp {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Endpoint, self.endpoint.into_value());
|
|
map.insert_unchecked(Property::Interval, self.interval.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MetricsOtelHttp {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Endpoint) => self
|
|
.endpoint
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Interval) => self.interval.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsPrometheus {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
MetricsPrometheus::Disabled => true,
|
|
MetricsPrometheus::Enabled(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MetricsPrometheus {
|
|
fn default() -> Self {
|
|
MetricsPrometheus::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricsPrometheus {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
MetricsPrometheus::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
MetricsPrometheus::Enabled(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(MetricsPrometheus::Disabled),
|
|
1 => Pickle::unpickle(stream).map(MetricsPrometheus::Enabled),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricsPrometheus {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
MetricsPrometheus::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
MetricsPrometheus::Enabled(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Enabled".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for MetricsPrometheus {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MetricsPrometheusType::Disabled => *self = MetricsPrometheus::Disabled,
|
|
MetricsPrometheusType::Enabled => {
|
|
*self = MetricsPrometheus::Enabled(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
MetricsPrometheus::Disabled => pointer.assert_eof(),
|
|
MetricsPrometheus::Enabled(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsPrometheus {
|
|
pub fn object_type(&self) -> MetricsPrometheusType {
|
|
match self {
|
|
MetricsPrometheus::Disabled => MetricsPrometheusType::Disabled,
|
|
MetricsPrometheus::Enabled(_) => MetricsPrometheusType::Enabled,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsPrometheusProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricsPrometheusProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.auth_secret.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MetricsPrometheusProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
auth_secret: Default::default(),
|
|
auth_username: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricsPrometheusProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MetricsPrometheusProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MetricsStore {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MetricsStore;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
MetricsStore::Disabled => true,
|
|
MetricsStore::Default => true,
|
|
MetricsStore::FoundationDb(inner) => inner.validate(errors),
|
|
MetricsStore::PostgreSql(inner) => inner.validate(errors),
|
|
MetricsStore::MySql(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for MetricsStore {
|
|
fn default() -> Self {
|
|
MetricsStore::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for MetricsStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
MetricsStore::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
MetricsStore::Default => {
|
|
1u16.pickle(out);
|
|
}
|
|
MetricsStore::FoundationDb(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
MetricsStore::PostgreSql(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
MetricsStore::MySql(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(MetricsStore::Disabled),
|
|
1 => Some(MetricsStore::Default),
|
|
2 => Pickle::unpickle(stream).map(MetricsStore::FoundationDb),
|
|
3 => Pickle::unpickle(stream).map(MetricsStore::PostgreSql),
|
|
4 => Pickle::unpickle(stream).map(MetricsStore::MySql),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MetricsStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
MetricsStore::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
MetricsStore::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
MetricsStore::FoundationDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into()));
|
|
obj
|
|
}
|
|
MetricsStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
MetricsStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for MetricsStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MetricsStoreType::Disabled => *self = MetricsStore::Disabled,
|
|
MetricsStoreType::Default => *self = MetricsStore::Default,
|
|
MetricsStoreType::FoundationDb => {
|
|
*self = MetricsStore::FoundationDb(Default::default())
|
|
}
|
|
MetricsStoreType::PostgreSql => {
|
|
*self = MetricsStore::PostgreSql(Default::default())
|
|
}
|
|
MetricsStoreType::MySql => *self = MetricsStore::MySql(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
MetricsStore::Disabled => pointer.assert_eof(),
|
|
MetricsStore::Default => pointer.assert_eof(),
|
|
MetricsStore::FoundationDb(inner) => inner.patch(pointer, value),
|
|
MetricsStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
MetricsStore::MySql(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MetricsStore {
|
|
pub fn object_type(&self) -> MetricsStoreType {
|
|
match self {
|
|
MetricsStore::Disabled => MetricsStoreType::Disabled,
|
|
MetricsStore::Default => MetricsStoreType::Default,
|
|
MetricsStore::FoundationDb(_) => MetricsStoreType::FoundationDb,
|
|
MetricsStore::PostgreSql(_) => MetricsStoreType::PostgreSql,
|
|
MetricsStore::MySql(_) => MetricsStoreType::MySql,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaConnectionIpHost {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.ehlo_hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EhloHostname));
|
|
}
|
|
}
|
|
let value = &self.source_ip;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::SourceIp, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaConnectionIpHost {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.ehlo_hostname.pickle(out);
|
|
self.source_ip.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.ehlo_hostname = Pickle::unpickle(stream)?;
|
|
this.source_ip = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaConnectionIpHost {
|
|
fn default() -> Self {
|
|
Self {
|
|
ehlo_hostname: Default::default(),
|
|
source_ip: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaConnectionIpHost {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::EhloHostname, self.ehlo_hostname.into_value());
|
|
map.insert_unchecked(Property::SourceIp, self.source_ip.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaConnectionIpHost {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::EhloHostname) => self
|
|
.ehlo_hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Hostname]), value),
|
|
Some(Property::SourceIp) => self.source_ip.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaConnectionStrategy {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaConnectionStrategy;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
if let Some(value) = &self.ehlo_hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EhloHostname));
|
|
}
|
|
}
|
|
let value = &self.source_ips;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaConnectionStrategy {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.ehlo_hostname.pickle(out);
|
|
self.source_ips.pickle(out);
|
|
self.connect_timeout.pickle(out);
|
|
self.data_timeout.pickle(out);
|
|
self.ehlo_timeout.pickle(out);
|
|
self.greeting_timeout.pickle(out);
|
|
self.mail_from_timeout.pickle(out);
|
|
self.rcpt_to_timeout.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.ehlo_hostname = Pickle::unpickle(stream)?;
|
|
this.source_ips = Pickle::unpickle(stream)?;
|
|
this.connect_timeout = Pickle::unpickle(stream)?;
|
|
this.data_timeout = Pickle::unpickle(stream)?;
|
|
this.ehlo_timeout = Pickle::unpickle(stream)?;
|
|
this.greeting_timeout = Pickle::unpickle(stream)?;
|
|
this.mail_from_timeout = Pickle::unpickle(stream)?;
|
|
this.rcpt_to_timeout = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaConnectionStrategy {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
ehlo_hostname: Default::default(),
|
|
source_ips: Default::default(),
|
|
connect_timeout: Duration::from_millis(300000),
|
|
data_timeout: Duration::from_millis(600000),
|
|
ehlo_timeout: Duration::from_millis(300000),
|
|
greeting_timeout: Duration::from_millis(300000),
|
|
mail_from_timeout: Duration::from_millis(300000),
|
|
rcpt_to_timeout: Duration::from_millis(300000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaConnectionStrategy {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(12);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::EhloHostname, self.ehlo_hostname.into_value());
|
|
map.insert_unchecked(Property::SourceIps, self.source_ips.into_value());
|
|
map.insert_unchecked(Property::ConnectTimeout, self.connect_timeout.into_value());
|
|
map.insert_unchecked(Property::DataTimeout, self.data_timeout.into_value());
|
|
map.insert_unchecked(Property::EhloTimeout, self.ehlo_timeout.into_value());
|
|
map.insert_unchecked(
|
|
Property::GreetingTimeout,
|
|
self.greeting_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MailFromTimeout,
|
|
self.mail_from_timeout.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::RcptToTimeout, self.rcpt_to_timeout.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaConnectionStrategy {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::EhloHostname) => self
|
|
.ehlo_hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Hostname]), value),
|
|
Some(Property::SourceIps) => self.source_ips.patch(pointer, value),
|
|
Some(Property::ConnectTimeout) => self.connect_timeout.patch(pointer, value),
|
|
Some(Property::DataTimeout) => self.data_timeout.patch(pointer, value),
|
|
Some(Property::EhloTimeout) => self.ehlo_timeout.patch(pointer, value),
|
|
Some(Property::GreetingTimeout) => self.greeting_timeout.patch(pointer, value),
|
|
Some(Property::MailFromTimeout) => self.mail_from_timeout.patch(pointer, value),
|
|
Some(Property::RcptToTimeout) => self.rcpt_to_timeout.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryExpiration {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
MtaDeliveryExpiration::Ttl(inner) => inner.validate(errors),
|
|
MtaDeliveryExpiration::Attempts(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliveryExpiration {
|
|
fn default() -> Self {
|
|
MtaDeliveryExpiration::Ttl(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliveryExpiration {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
MtaDeliveryExpiration::Ttl(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
MtaDeliveryExpiration::Attempts(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(MtaDeliveryExpiration::Ttl),
|
|
1 => Pickle::unpickle(stream).map(MtaDeliveryExpiration::Attempts),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliveryExpiration {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
MtaDeliveryExpiration::Ttl(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ttl".into()));
|
|
obj
|
|
}
|
|
MtaDeliveryExpiration::Attempts(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Attempts".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for MtaDeliveryExpiration {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MtaDeliveryExpirationType::Ttl => {
|
|
*self = MtaDeliveryExpiration::Ttl(Default::default())
|
|
}
|
|
MtaDeliveryExpirationType::Attempts => {
|
|
*self = MtaDeliveryExpiration::Attempts(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
MtaDeliveryExpiration::Ttl(inner) => inner.patch(pointer, value),
|
|
MtaDeliveryExpiration::Attempts(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryExpiration {
|
|
pub fn object_type(&self) -> MtaDeliveryExpirationType {
|
|
match self {
|
|
MtaDeliveryExpiration::Ttl(_) => MtaDeliveryExpirationType::Ttl,
|
|
MtaDeliveryExpiration::Attempts(_) => MtaDeliveryExpirationType::Attempts,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryExpirationAttempts {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_attempts;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxAttempts, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliveryExpirationAttempts {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_attempts.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_attempts = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliveryExpirationAttempts {
|
|
fn default() -> Self {
|
|
Self { max_attempts: 5u64 }
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliveryExpirationAttempts {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::MaxAttempts, self.max_attempts.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaDeliveryExpirationAttempts {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxAttempts) => self.max_attempts.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryExpirationTtl {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliveryExpirationTtl {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.expire.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.expire = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliveryExpirationTtl {
|
|
fn default() -> Self {
|
|
Self {
|
|
expire: Duration::from_millis(259200000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliveryExpirationTtl {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Expire, self.expire.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaDeliveryExpirationTtl {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Expire) => self.expire.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaDeliverySchedule {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaDeliverySchedule;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.expiry;
|
|
value.validate(errors);
|
|
let value = &self.notify;
|
|
value.validate(errors);
|
|
let value = &self.queue_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::QueueId));
|
|
}
|
|
let value = &self.retry;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
i.foreign_key(ObjectType::MtaVirtualQueue, self.queue_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliverySchedule {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.expiry.pickle(out);
|
|
self.notify.pickle(out);
|
|
self.queue_id.pickle(out);
|
|
self.retry.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.expiry = Pickle::unpickle(stream)?;
|
|
this.notify = Pickle::unpickle(stream)?;
|
|
this.queue_id = Pickle::unpickle(stream)?;
|
|
this.retry = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliverySchedule {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
expiry: Default::default(),
|
|
notify: Default::default(),
|
|
queue_id: Default::default(),
|
|
retry: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliverySchedule {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Expiry, self.expiry.into_value());
|
|
map.insert_unchecked(Property::Notify, self.notify.into_value());
|
|
map.insert_unchecked(Property::QueueId, self.queue_id.into_value());
|
|
map.insert_unchecked(Property::Retry, self.retry.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaDeliverySchedule {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Expiry) => self.expiry.patch(pointer, value),
|
|
Some(Property::Notify) => self.notify.patch(pointer, value),
|
|
Some(Property::QueueId) => self.queue_id.patch(pointer, value),
|
|
Some(Property::Retry) => self.retry.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryScheduleInterval {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliveryScheduleInterval {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.duration.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.duration = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliveryScheduleInterval {
|
|
fn default() -> Self {
|
|
Self {
|
|
duration: Duration::from_millis(3600000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliveryScheduleInterval {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Duration, self.duration.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaDeliveryScheduleInterval {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Duration) => self.duration.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryScheduleIntervals {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.intervals;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Intervals, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliveryScheduleIntervals {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.intervals.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.intervals = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliveryScheduleIntervals {
|
|
fn default() -> Self {
|
|
Self {
|
|
intervals: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliveryScheduleIntervals {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Intervals, self.intervals.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaDeliveryScheduleIntervals {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Intervals) => self.intervals.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryScheduleIntervalsOrDefault {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
MtaDeliveryScheduleIntervalsOrDefault::Default => true,
|
|
MtaDeliveryScheduleIntervalsOrDefault::Custom(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MtaDeliveryScheduleIntervalsOrDefault {
|
|
fn default() -> Self {
|
|
MtaDeliveryScheduleIntervalsOrDefault::Default
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaDeliveryScheduleIntervalsOrDefault {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
MtaDeliveryScheduleIntervalsOrDefault::Default => {
|
|
0u16.pickle(out);
|
|
}
|
|
MtaDeliveryScheduleIntervalsOrDefault::Custom(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(MtaDeliveryScheduleIntervalsOrDefault::Default),
|
|
1 => Pickle::unpickle(stream).map(MtaDeliveryScheduleIntervalsOrDefault::Custom),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaDeliveryScheduleIntervalsOrDefault {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
MtaDeliveryScheduleIntervalsOrDefault::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
MtaDeliveryScheduleIntervalsOrDefault::Custom(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Custom".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for MtaDeliveryScheduleIntervalsOrDefault {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MtaDeliveryScheduleIntervalsOrDefaultType::Default => {
|
|
*self = MtaDeliveryScheduleIntervalsOrDefault::Default
|
|
}
|
|
MtaDeliveryScheduleIntervalsOrDefaultType::Custom => {
|
|
*self = MtaDeliveryScheduleIntervalsOrDefault::Custom(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
MtaDeliveryScheduleIntervalsOrDefault::Default => pointer.assert_eof(),
|
|
MtaDeliveryScheduleIntervalsOrDefault::Custom(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaDeliveryScheduleIntervalsOrDefault {
|
|
pub fn object_type(&self) -> MtaDeliveryScheduleIntervalsOrDefaultType {
|
|
match self {
|
|
MtaDeliveryScheduleIntervalsOrDefault::Default => {
|
|
MtaDeliveryScheduleIntervalsOrDefaultType::Default
|
|
}
|
|
MtaDeliveryScheduleIntervalsOrDefault::Custom(_) => {
|
|
MtaDeliveryScheduleIntervalsOrDefaultType::Custom
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaExtensions {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaExtensions;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.chunking;
|
|
value.validate(errors);
|
|
let value = &self.deliver_by;
|
|
value.validate(errors);
|
|
let value = &self.dsn;
|
|
value.validate(errors);
|
|
let value = &self.expn;
|
|
value.validate(errors);
|
|
let value = &self.future_release;
|
|
value.validate(errors);
|
|
let value = &self.mt_priority;
|
|
value.validate(errors);
|
|
let value = &self.no_soliciting;
|
|
value.validate(errors);
|
|
let value = &self.pipelining;
|
|
value.validate(errors);
|
|
let value = &self.require_tls;
|
|
value.validate(errors);
|
|
let value = &self.vrfy;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaExtensions {
|
|
pub fn ctx_chunking(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.chunking,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Chunking,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_deliver_by(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.deliver_by,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "15d".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::DeliverBy,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dsn(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dsn,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::Dsn,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_expn(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.expn,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::Expn,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_future_release(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.future_release,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "7d".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::FutureRelease,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_mt_priority(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.mt_priority,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "mixer".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::MtPriority,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: MTA_PRIORITY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_no_soliciting(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.no_soliciting,
|
|
default: Some(Expression {
|
|
else_: "''".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::NoSoliciting,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_pipelining(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.pipelining,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Pipelining,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_require_tls(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.require_tls,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::RequireTls,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_vrfy(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.vrfy,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::Vrfy,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_chunking(),
|
|
self.ctx_deliver_by(),
|
|
self.ctx_dsn(),
|
|
self.ctx_expn(),
|
|
self.ctx_future_release(),
|
|
self.ctx_mt_priority(),
|
|
self.ctx_no_soliciting(),
|
|
self.ctx_pipelining(),
|
|
self.ctx_require_tls(),
|
|
self.ctx_vrfy(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaExtensions {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.chunking.pickle(out);
|
|
self.deliver_by.pickle(out);
|
|
self.dsn.pickle(out);
|
|
self.expn.pickle(out);
|
|
self.future_release.pickle(out);
|
|
self.mt_priority.pickle(out);
|
|
self.no_soliciting.pickle(out);
|
|
self.pipelining.pickle(out);
|
|
self.require_tls.pickle(out);
|
|
self.vrfy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.chunking = Pickle::unpickle(stream)?;
|
|
this.deliver_by = Pickle::unpickle(stream)?;
|
|
this.dsn = Pickle::unpickle(stream)?;
|
|
this.expn = Pickle::unpickle(stream)?;
|
|
this.future_release = Pickle::unpickle(stream)?;
|
|
this.mt_priority = Pickle::unpickle(stream)?;
|
|
this.no_soliciting = Pickle::unpickle(stream)?;
|
|
this.pipelining = Pickle::unpickle(stream)?;
|
|
this.require_tls = Pickle::unpickle(stream)?;
|
|
this.vrfy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaExtensions {
|
|
fn default() -> Self {
|
|
Self {
|
|
chunking: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
deliver_by: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "15d".to_string(),
|
|
}]),
|
|
},
|
|
dsn: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
expn: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
future_release: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "7d".to_string(),
|
|
}]),
|
|
},
|
|
mt_priority: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "mixer".to_string(),
|
|
}]),
|
|
},
|
|
no_soliciting: Expression {
|
|
else_: "''".to_string(),
|
|
..Default::default()
|
|
},
|
|
pipelining: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
require_tls: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
vrfy: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "!is_empty(authenticated_as)".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaExtensions {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(12);
|
|
map.insert_unchecked(Property::Chunking, self.chunking.into_value());
|
|
map.insert_unchecked(Property::DeliverBy, self.deliver_by.into_value());
|
|
map.insert_unchecked(Property::Dsn, self.dsn.into_value());
|
|
map.insert_unchecked(Property::Expn, self.expn.into_value());
|
|
map.insert_unchecked(Property::FutureRelease, self.future_release.into_value());
|
|
map.insert_unchecked(Property::MtPriority, self.mt_priority.into_value());
|
|
map.insert_unchecked(Property::NoSoliciting, self.no_soliciting.into_value());
|
|
map.insert_unchecked(Property::Pipelining, self.pipelining.into_value());
|
|
map.insert_unchecked(Property::RequireTls, self.require_tls.into_value());
|
|
map.insert_unchecked(Property::Vrfy, self.vrfy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaExtensions {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Chunking) => self.chunking.patch(pointer, value),
|
|
Some(Property::DeliverBy) => self.deliver_by.patch(pointer, value),
|
|
Some(Property::Dsn) => self.dsn.patch(pointer, value),
|
|
Some(Property::Expn) => self.expn.patch(pointer, value),
|
|
Some(Property::FutureRelease) => self.future_release.patch(pointer, value),
|
|
Some(Property::MtPriority) => self.mt_priority.patch(pointer, value),
|
|
Some(Property::NoSoliciting) => self.no_soliciting.patch(pointer, value),
|
|
Some(Property::Pipelining) => self.pipelining.patch(pointer, value),
|
|
Some(Property::RequireTls) => self.require_tls.patch(pointer, value),
|
|
Some(Property::Vrfy) => self.vrfy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaHook {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaHook;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.enable;
|
|
value.validate(errors);
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaHook {
|
|
pub fn ctx_enable(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.enable,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Enable,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_enable()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaHook {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.max_response_size.pickle(out);
|
|
self.temp_fail_on_error.pickle(out);
|
|
self.stages.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.url.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.max_response_size = Pickle::unpickle(stream)?;
|
|
this.temp_fail_on_error = Pickle::unpickle(stream)?;
|
|
this.stages = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaHook {
|
|
fn default() -> Self {
|
|
Self {
|
|
allow_invalid_certs: false,
|
|
enable: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
max_response_size: 52428800u64,
|
|
temp_fail_on_error: true,
|
|
stages: Map::new(vec![MtaStage::Data]),
|
|
timeout: Duration::from_millis(30000),
|
|
url: Default::default(),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaHook {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxResponseSize,
|
|
self.max_response_size.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TempFailOnError,
|
|
self.temp_fail_on_error.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Stages, self.stages.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaHook {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::MaxResponseSize) => self.max_response_size.patch(pointer, value),
|
|
Some(Property::TempFailOnError) => self.temp_fail_on_error.patch(pointer, value),
|
|
Some(Property::Stages) => self.stages.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaInboundSession {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaInboundSession;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_duration;
|
|
value.validate(errors);
|
|
let value = &self.timeout;
|
|
value.validate(errors);
|
|
let value = &self.transfer_limit;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaInboundSession {
|
|
pub fn ctx_max_duration(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_duration,
|
|
default: Some(Expression {
|
|
else_: "10m".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxDuration,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_timeout(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.timeout,
|
|
default: Some(Expression {
|
|
else_: "5m".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Timeout,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_transfer_limit(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.transfer_limit,
|
|
default: Some(Expression {
|
|
else_: "262144000".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::TransferLimit,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_max_duration(),
|
|
self.ctx_timeout(),
|
|
self.ctx_transfer_limit(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaInboundSession {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_duration.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.transfer_limit.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_duration = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.transfer_limit = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaInboundSession {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_duration: Expression {
|
|
else_: "10m".to_string(),
|
|
..Default::default()
|
|
},
|
|
timeout: Expression {
|
|
else_: "5m".to_string(),
|
|
..Default::default()
|
|
},
|
|
transfer_limit: Expression {
|
|
else_: "262144000".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaInboundSession {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::MaxDuration, self.max_duration.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::TransferLimit, self.transfer_limit.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaInboundSession {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxDuration) => self.max_duration.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::TransferLimit) => self.transfer_limit.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaInboundThrottle {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaInboundThrottle;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.match_;
|
|
value.validate(errors);
|
|
let value = &self.rate;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaInboundThrottle {
|
|
pub fn ctx_match_(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.match_,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Match,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_match_()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaInboundThrottle {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enable.pickle(out);
|
|
self.description.pickle(out);
|
|
self.key.pickle(out);
|
|
self.match_.pickle(out);
|
|
self.rate.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.match_ = Pickle::unpickle(stream)?;
|
|
this.rate = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaInboundThrottle {
|
|
fn default() -> Self {
|
|
Self {
|
|
enable: true,
|
|
description: Default::default(),
|
|
key: Default::default(),
|
|
match_: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
rate: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaInboundThrottle {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Match, self.match_.into_value());
|
|
map.insert_unchecked(Property::Rate, self.rate.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaInboundThrottle {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Description) => {
|
|
self.description.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::Match) => self.match_.patch(pointer, value),
|
|
Some(Property::Rate) => self.rate.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaMilter {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaMilter;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.enable;
|
|
value.validate(errors);
|
|
let value = &self.hostname;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Hostname));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.stages;
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Stages, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaMilter {
|
|
pub fn ctx_enable(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.enable,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Enable,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_enable()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaMilter {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.hostname.pickle(out);
|
|
self.max_response_size.pickle(out);
|
|
self.temp_fail_on_error.pickle(out);
|
|
self.protocol_version.pickle(out);
|
|
self.port.pickle(out);
|
|
self.stages.pickle(out);
|
|
self.timeout_command.pickle(out);
|
|
self.timeout_connect.pickle(out);
|
|
self.timeout_data.pickle(out);
|
|
self.use_tls.pickle(out);
|
|
self.flags_action.pickle(out);
|
|
self.flags_protocol.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.hostname = Pickle::unpickle(stream)?;
|
|
this.max_response_size = Pickle::unpickle(stream)?;
|
|
this.temp_fail_on_error = Pickle::unpickle(stream)?;
|
|
this.protocol_version = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.stages = Pickle::unpickle(stream)?;
|
|
this.timeout_command = Pickle::unpickle(stream)?;
|
|
this.timeout_connect = Pickle::unpickle(stream)?;
|
|
this.timeout_data = Pickle::unpickle(stream)?;
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.flags_action = Pickle::unpickle(stream)?;
|
|
this.flags_protocol = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaMilter {
|
|
fn default() -> Self {
|
|
Self {
|
|
allow_invalid_certs: false,
|
|
enable: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
hostname: Default::default(),
|
|
max_response_size: 52428800u64,
|
|
temp_fail_on_error: true,
|
|
protocol_version: MilterVersion::V6,
|
|
port: 11332u64,
|
|
stages: Map::new(vec![MtaStage::Data]),
|
|
timeout_command: Duration::from_millis(30000),
|
|
timeout_connect: Duration::from_millis(30000),
|
|
timeout_data: Duration::from_millis(60000),
|
|
use_tls: false,
|
|
flags_action: Default::default(),
|
|
flags_protocol: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaMilter {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(16);
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Hostname, self.hostname.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxResponseSize,
|
|
self.max_response_size.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TempFailOnError,
|
|
self.temp_fail_on_error.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ProtocolVersion,
|
|
self.protocol_version.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Stages, self.stages.into_value());
|
|
map.insert_unchecked(Property::TimeoutCommand, self.timeout_command.into_value());
|
|
map.insert_unchecked(Property::TimeoutConnect, self.timeout_connect.into_value());
|
|
map.insert_unchecked(Property::TimeoutData, self.timeout_data.into_value());
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(Property::FlagsAction, self.flags_action.into_value());
|
|
map.insert_unchecked(Property::FlagsProtocol, self.flags_protocol.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaMilter {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Hostname) => self
|
|
.hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MaxResponseSize) => self.max_response_size.patch(pointer, value),
|
|
Some(Property::TempFailOnError) => self.temp_fail_on_error.patch(pointer, value),
|
|
Some(Property::ProtocolVersion) => self.protocol_version.patch(pointer, value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Stages) => self.stages.patch(pointer, value),
|
|
Some(Property::TimeoutCommand) => self.timeout_command.patch(pointer, value),
|
|
Some(Property::TimeoutConnect) => self.timeout_connect.patch(pointer, value),
|
|
Some(Property::TimeoutData) => self.timeout_data.patch(pointer, value),
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::FlagsAction) => self.flags_action.patch(pointer, value),
|
|
Some(Property::FlagsProtocol) => self.flags_protocol.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaOutboundStrategy {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaOutboundStrategy;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.connection;
|
|
value.validate(errors);
|
|
let value = &self.route;
|
|
value.validate(errors);
|
|
let value = &self.schedule;
|
|
value.validate(errors);
|
|
let value = &self.tls;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaOutboundStrategy {
|
|
pub fn ctx_connection(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.connection,
|
|
default: Some(Expression {
|
|
else_: "'default'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Connection,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_route(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.route,
|
|
default: Some(Expression {
|
|
else_: "'mx'".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "is_local_domain(rcpt_domain)".to_string(),
|
|
then: "'local'".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::Route,
|
|
allowed_variables: MTA_QUEUE_RCPT_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_schedule(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.schedule,
|
|
default: Some(Expression {
|
|
else_: "'remote'".to_string(),
|
|
match_: List::from_iter([
|
|
ExpressionMatch {
|
|
if_: "is_local_domain(rcpt_domain)".to_string(),
|
|
then: "'local'".to_string(),
|
|
},
|
|
ExpressionMatch {
|
|
if_: "source == 'dsn'".to_string(),
|
|
then: "'dsn'".to_string(),
|
|
},
|
|
ExpressionMatch {
|
|
if_: "source == 'report'".to_string(),
|
|
then: "'report'".to_string(),
|
|
},
|
|
]),
|
|
}),
|
|
property: Property::Schedule,
|
|
allowed_variables: MTA_QUEUE_RCPT_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_tls(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tls,
|
|
default: Some(Expression {
|
|
else_: "'default'".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "retry_num > 0 && last_error == 'tls'".to_string(),
|
|
then: "'invalid-tls'".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::Tls,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_connection(),
|
|
self.ctx_route(),
|
|
self.ctx_schedule(),
|
|
self.ctx_tls(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaOutboundStrategy {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.connection.pickle(out);
|
|
self.route.pickle(out);
|
|
self.schedule.pickle(out);
|
|
self.tls.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.connection = Pickle::unpickle(stream)?;
|
|
this.route = Pickle::unpickle(stream)?;
|
|
this.schedule = Pickle::unpickle(stream)?;
|
|
this.tls = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaOutboundStrategy {
|
|
fn default() -> Self {
|
|
Self {
|
|
connection: Expression {
|
|
else_: "'default'".to_string(),
|
|
..Default::default()
|
|
},
|
|
route: Expression {
|
|
else_: "'mx'".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "is_local_domain(rcpt_domain)".to_string(),
|
|
then: "'local'".to_string(),
|
|
}]),
|
|
},
|
|
schedule: Expression {
|
|
else_: "'remote'".to_string(),
|
|
match_: List::from_iter([
|
|
ExpressionMatch {
|
|
if_: "is_local_domain(rcpt_domain)".to_string(),
|
|
then: "'local'".to_string(),
|
|
},
|
|
ExpressionMatch {
|
|
if_: "source == 'dsn'".to_string(),
|
|
then: "'dsn'".to_string(),
|
|
},
|
|
ExpressionMatch {
|
|
if_: "source == 'report'".to_string(),
|
|
then: "'report'".to_string(),
|
|
},
|
|
]),
|
|
},
|
|
tls: Expression {
|
|
else_: "'default'".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "retry_num > 0 && last_error == 'tls'".to_string(),
|
|
then: "'invalid-tls'".to_string(),
|
|
}]),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaOutboundStrategy {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Connection, self.connection.into_value());
|
|
map.insert_unchecked(Property::Route, self.route.into_value());
|
|
map.insert_unchecked(Property::Schedule, self.schedule.into_value());
|
|
map.insert_unchecked(Property::Tls, self.tls.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaOutboundStrategy {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Connection) => self.connection.patch(pointer, value),
|
|
Some(Property::Route) => self.route.patch(pointer, value),
|
|
Some(Property::Schedule) => self.schedule.patch(pointer, value),
|
|
Some(Property::Tls) => self.tls.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaOutboundThrottle {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaOutboundThrottle;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.match_;
|
|
value.validate(errors);
|
|
let value = &self.rate;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaOutboundThrottle {
|
|
pub fn ctx_match_(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.match_,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Match,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_match_()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaOutboundThrottle {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enable.pickle(out);
|
|
self.description.pickle(out);
|
|
self.key.pickle(out);
|
|
self.match_.pickle(out);
|
|
self.rate.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.match_ = Pickle::unpickle(stream)?;
|
|
this.rate = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaOutboundThrottle {
|
|
fn default() -> Self {
|
|
Self {
|
|
enable: true,
|
|
description: Default::default(),
|
|
key: Default::default(),
|
|
match_: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
rate: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaOutboundThrottle {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Match, self.match_.into_value());
|
|
map.insert_unchecked(Property::Rate, self.rate.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaOutboundThrottle {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::Match) => self.match_.patch(pointer, value),
|
|
Some(Property::Rate) => self.rate.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaQueueQuota {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaQueueQuota;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.key;
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Key, 1));
|
|
}
|
|
let value = &self.match_;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.messages {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Messages, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaQueueQuota {
|
|
pub fn ctx_match_(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.match_,
|
|
default: None,
|
|
property: Property::Match,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_match_()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaQueueQuota {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enable.pickle(out);
|
|
self.description.pickle(out);
|
|
self.key.pickle(out);
|
|
self.match_.pickle(out);
|
|
self.messages.pickle(out);
|
|
self.size.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.match_ = Pickle::unpickle(stream)?;
|
|
this.messages = Pickle::unpickle(stream)?;
|
|
this.size = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaQueueQuota {
|
|
fn default() -> Self {
|
|
Self {
|
|
enable: true,
|
|
description: Default::default(),
|
|
key: Default::default(),
|
|
match_: Default::default(),
|
|
messages: Default::default(),
|
|
size: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaQueueQuota {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Match, self.match_.into_value());
|
|
map.insert_unchecked(Property::Messages, self.messages.into_value());
|
|
map.insert_unchecked(Property::Size, self.size.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaQueueQuota {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Description) => {
|
|
self.description.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::Match) => self.match_.patch(pointer, value),
|
|
Some(Property::Messages) => self.messages.patch(pointer, value),
|
|
Some(Property::Size) => self.size.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaRoute {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaRoute;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
MtaRoute::Mx(inner) => inner.validate(errors),
|
|
MtaRoute::Relay(inner) => inner.validate(errors),
|
|
MtaRoute::Local(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
MtaRoute::Mx(object) => {
|
|
object.index(i);
|
|
}
|
|
MtaRoute::Relay(object) => {
|
|
object.index(i);
|
|
}
|
|
MtaRoute::Local(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MtaRoute {
|
|
fn default() -> Self {
|
|
MtaRoute::Mx(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaRoute {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
MtaRoute::Mx(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
MtaRoute::Relay(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
MtaRoute::Local(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(MtaRoute::Mx),
|
|
1 => Pickle::unpickle(stream).map(MtaRoute::Relay),
|
|
2 => Pickle::unpickle(stream).map(MtaRoute::Local),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaRoute {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
MtaRoute::Mx(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Mx".into()));
|
|
obj
|
|
}
|
|
MtaRoute::Relay(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Relay".into()));
|
|
obj
|
|
}
|
|
MtaRoute::Local(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Local".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for MtaRoute {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
MtaRouteType::Mx => *self = MtaRoute::Mx(Default::default()),
|
|
MtaRouteType::Relay => *self = MtaRoute::Relay(Default::default()),
|
|
MtaRouteType::Local => *self = MtaRoute::Local(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
MtaRoute::Mx(inner) => inner.patch(pointer, value),
|
|
MtaRoute::Relay(inner) => inner.patch(pointer, value),
|
|
MtaRoute::Local(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaRoute {
|
|
pub fn object_type(&self) -> MtaRouteType {
|
|
match self {
|
|
MtaRoute::Mx(_) => MtaRouteType::Mx,
|
|
MtaRoute::Relay(_) => MtaRouteType::Relay,
|
|
MtaRoute::Local(_) => MtaRouteType::Local,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaRouteCommon {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaRouteCommon {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaRouteCommon {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaRouteCommon {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaRouteCommon {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaRouteMx {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_multihomed;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMultihomed, 1));
|
|
}
|
|
let value = &self.max_mx_hosts;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMxHosts, 1));
|
|
}
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaRouteMx {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.ip_lookup_strategy.pickle(out);
|
|
self.max_multihomed.pickle(out);
|
|
self.max_mx_hosts.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.ip_lookup_strategy = Pickle::unpickle(stream)?;
|
|
this.max_multihomed = Pickle::unpickle(stream)?;
|
|
this.max_mx_hosts = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaRouteMx {
|
|
fn default() -> Self {
|
|
Self {
|
|
ip_lookup_strategy: MtaIpStrategy::V4ThenV6,
|
|
max_multihomed: 2u64,
|
|
max_mx_hosts: 5u64,
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaRouteMx {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(
|
|
Property::IpLookupStrategy,
|
|
self.ip_lookup_strategy.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxMultihomed, self.max_multihomed.into_value());
|
|
map.insert_unchecked(Property::MaxMxHosts, self.max_mx_hosts.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaRouteMx {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::IpLookupStrategy) => self.ip_lookup_strategy.patch(pointer, value),
|
|
Some(Property::MaxMultihomed) => self.max_multihomed.patch(pointer, value),
|
|
Some(Property::MaxMxHosts) => self.max_mx_hosts.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MtaRouteRelay {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.address;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Address));
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaRouteRelay {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.address.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.port.pickle(out);
|
|
self.protocol.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.implicit_tls.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.address = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.protocol = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.implicit_tls = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaRouteRelay {
|
|
fn default() -> Self {
|
|
Self {
|
|
address: Default::default(),
|
|
auth_secret: Default::default(),
|
|
auth_username: Default::default(),
|
|
port: 25u64,
|
|
protocol: MtaProtocol::Smtp,
|
|
allow_invalid_certs: false,
|
|
implicit_tls: false,
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaRouteRelay {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Address, self.address.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Protocol, self.protocol.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ImplicitTls, self.implicit_tls.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaRouteRelay {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Address) => self
|
|
.address
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::AuthUsername) => self.auth_username.patch(pointer, value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Protocol) => self.protocol.patch(pointer, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::ImplicitTls) => self.implicit_tls.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaStageAuth {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaStageAuth;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_failures;
|
|
value.validate(errors);
|
|
let value = &self.wait_on_fail;
|
|
value.validate(errors);
|
|
let value = &self.sasl_mechanisms;
|
|
value.validate(errors);
|
|
let value = &self.must_match_sender;
|
|
value.validate(errors);
|
|
let value = &self.require;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaStageAuth {
|
|
pub fn ctx_max_failures(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_failures,
|
|
default: Some(Expression {
|
|
else_: "3".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxFailures,
|
|
allowed_variables: MTA_EHLO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_wait_on_fail(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.wait_on_fail,
|
|
default: Some(Expression {
|
|
else_: "5s".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::WaitOnFail,
|
|
allowed_variables: MTA_EHLO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_sasl_mechanisms(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.sasl_mechanisms,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([
|
|
ExpressionMatch {
|
|
if_: "local_port != 25 && is_tls".to_string(),
|
|
then: "[plain, login, oauthbearer, xoauth2]".to_string(),
|
|
},
|
|
ExpressionMatch {
|
|
if_: "local_port != 25".to_string(),
|
|
then: "[oauthbearer, xoauth2]".to_string(),
|
|
},
|
|
]),
|
|
}),
|
|
property: Property::SaslMechanisms,
|
|
allowed_variables: MTA_EHLO_VARIABLE,
|
|
allowed_constants: MTA_AUTH_TYPE_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_must_match_sender(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.must_match_sender,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MustMatchSender,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_require(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.require,
|
|
default: Some(Expression {
|
|
else_: "local_port != 25".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Require,
|
|
allowed_variables: MTA_EHLO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_max_failures(),
|
|
self.ctx_wait_on_fail(),
|
|
self.ctx_sasl_mechanisms(),
|
|
self.ctx_must_match_sender(),
|
|
self.ctx_require(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaStageAuth {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_failures.pickle(out);
|
|
self.wait_on_fail.pickle(out);
|
|
self.sasl_mechanisms.pickle(out);
|
|
self.must_match_sender.pickle(out);
|
|
self.require.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_failures = Pickle::unpickle(stream)?;
|
|
this.wait_on_fail = Pickle::unpickle(stream)?;
|
|
this.sasl_mechanisms = Pickle::unpickle(stream)?;
|
|
this.must_match_sender = Pickle::unpickle(stream)?;
|
|
this.require = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaStageAuth {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_failures: Expression {
|
|
else_: "3".to_string(),
|
|
..Default::default()
|
|
},
|
|
wait_on_fail: Expression {
|
|
else_: "5s".to_string(),
|
|
..Default::default()
|
|
},
|
|
sasl_mechanisms: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([
|
|
ExpressionMatch {
|
|
if_: "local_port != 25 && is_tls".to_string(),
|
|
then: "[plain, login, oauthbearer, xoauth2]".to_string(),
|
|
},
|
|
ExpressionMatch {
|
|
if_: "local_port != 25".to_string(),
|
|
then: "[oauthbearer, xoauth2]".to_string(),
|
|
},
|
|
]),
|
|
},
|
|
must_match_sender: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
require: Expression {
|
|
else_: "local_port != 25".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaStageAuth {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::MaxFailures, self.max_failures.into_value());
|
|
map.insert_unchecked(Property::WaitOnFail, self.wait_on_fail.into_value());
|
|
map.insert_unchecked(Property::SaslMechanisms, self.sasl_mechanisms.into_value());
|
|
map.insert_unchecked(
|
|
Property::MustMatchSender,
|
|
self.must_match_sender.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Require, self.require.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaStageAuth {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxFailures) => self.max_failures.patch(pointer, value),
|
|
Some(Property::WaitOnFail) => self.wait_on_fail.patch(pointer, value),
|
|
Some(Property::SaslMechanisms) => self.sasl_mechanisms.patch(pointer, value),
|
|
Some(Property::MustMatchSender) => self.must_match_sender.patch(pointer, value),
|
|
Some(Property::Require) => self.require.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaStageConnect {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaStageConnect;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.smtp_greeting;
|
|
value.validate(errors);
|
|
let value = &self.hostname;
|
|
value.validate(errors);
|
|
let value = &self.script;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaStageConnect {
|
|
pub fn ctx_smtp_greeting(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.smtp_greeting,
|
|
default: Some(Expression {
|
|
else_: "system('hostname') + ' Stalwart ESMTP at your service'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::SmtpGreeting,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_hostname(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.hostname,
|
|
default: Some(Expression {
|
|
else_: "system('hostname')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Hostname,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_script(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.script,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Script,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_smtp_greeting(),
|
|
self.ctx_hostname(),
|
|
self.ctx_script(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaStageConnect {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.smtp_greeting.pickle(out);
|
|
self.hostname.pickle(out);
|
|
self.script.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.smtp_greeting = Pickle::unpickle(stream)?;
|
|
this.hostname = Pickle::unpickle(stream)?;
|
|
this.script = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaStageConnect {
|
|
fn default() -> Self {
|
|
Self {
|
|
smtp_greeting: Expression {
|
|
else_: "system('hostname') + ' Stalwart ESMTP at your service'".to_string(),
|
|
..Default::default()
|
|
},
|
|
hostname: Expression {
|
|
else_: "system('hostname')".to_string(),
|
|
..Default::default()
|
|
},
|
|
script: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaStageConnect {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::SmtpGreeting, self.smtp_greeting.into_value());
|
|
map.insert_unchecked(Property::Hostname, self.hostname.into_value());
|
|
map.insert_unchecked(Property::Script, self.script.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaStageConnect {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::SmtpGreeting) => self.smtp_greeting.patch(pointer, value),
|
|
Some(Property::Hostname) => self.hostname.patch(pointer, value),
|
|
Some(Property::Script) => self.script.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaStageData {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaStageData;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.add_auth_results_header;
|
|
value.validate(errors);
|
|
let value = &self.add_date_header;
|
|
value.validate(errors);
|
|
let value = &self.add_message_id_header;
|
|
value.validate(errors);
|
|
let value = &self.add_received_header;
|
|
value.validate(errors);
|
|
let value = &self.add_received_spf_header;
|
|
value.validate(errors);
|
|
let value = &self.add_return_path_header;
|
|
value.validate(errors);
|
|
let value = &self.max_messages;
|
|
value.validate(errors);
|
|
let value = &self.max_received_headers;
|
|
value.validate(errors);
|
|
let value = &self.max_message_size;
|
|
value.validate(errors);
|
|
let value = &self.script;
|
|
value.validate(errors);
|
|
let value = &self.enable_spam_filter;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaStageData {
|
|
pub fn ctx_add_auth_results_header(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.add_auth_results_header,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::AddAuthResultsHeader,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_add_date_header(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.add_date_header,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::AddDateHeader,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_add_message_id_header(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.add_message_id_header,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::AddMessageIdHeader,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_add_received_header(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.add_received_header,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::AddReceivedHeader,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_add_received_spf_header(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.add_received_spf_header,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::AddReceivedSpfHeader,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_add_return_path_header(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.add_return_path_header,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::AddReturnPathHeader,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_max_messages(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_messages,
|
|
default: Some(Expression {
|
|
else_: "10".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxMessages,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_max_received_headers(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_received_headers,
|
|
default: Some(Expression {
|
|
else_: "50".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxReceivedHeaders,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_max_message_size(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_message_size,
|
|
default: Some(Expression {
|
|
else_: "104857600".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxMessageSize,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_script(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.script,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Script,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_enable_spam_filter(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.enable_spam_filter,
|
|
default: Some(Expression {
|
|
else_: "is_empty(authenticated_as)".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::EnableSpamFilter,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_add_auth_results_header(),
|
|
self.ctx_add_date_header(),
|
|
self.ctx_add_message_id_header(),
|
|
self.ctx_add_received_header(),
|
|
self.ctx_add_received_spf_header(),
|
|
self.ctx_add_return_path_header(),
|
|
self.ctx_max_messages(),
|
|
self.ctx_max_received_headers(),
|
|
self.ctx_max_message_size(),
|
|
self.ctx_script(),
|
|
self.ctx_enable_spam_filter(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaStageData {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.add_auth_results_header.pickle(out);
|
|
self.add_date_header.pickle(out);
|
|
self.add_delivered_to_header.pickle(out);
|
|
self.add_message_id_header.pickle(out);
|
|
self.add_received_header.pickle(out);
|
|
self.add_received_spf_header.pickle(out);
|
|
self.add_return_path_header.pickle(out);
|
|
self.max_messages.pickle(out);
|
|
self.max_received_headers.pickle(out);
|
|
self.max_message_size.pickle(out);
|
|
self.script.pickle(out);
|
|
self.enable_spam_filter.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.add_auth_results_header = Pickle::unpickle(stream)?;
|
|
this.add_date_header = Pickle::unpickle(stream)?;
|
|
this.add_delivered_to_header = Pickle::unpickle(stream)?;
|
|
this.add_message_id_header = Pickle::unpickle(stream)?;
|
|
this.add_received_header = Pickle::unpickle(stream)?;
|
|
this.add_received_spf_header = Pickle::unpickle(stream)?;
|
|
this.add_return_path_header = Pickle::unpickle(stream)?;
|
|
this.max_messages = Pickle::unpickle(stream)?;
|
|
this.max_received_headers = Pickle::unpickle(stream)?;
|
|
this.max_message_size = Pickle::unpickle(stream)?;
|
|
this.script = Pickle::unpickle(stream)?;
|
|
this.enable_spam_filter = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaStageData {
|
|
fn default() -> Self {
|
|
Self {
|
|
add_auth_results_header: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
add_date_header: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
add_delivered_to_header: true,
|
|
add_message_id_header: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
add_received_header: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
add_received_spf_header: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
add_return_path_header: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
max_messages: Expression {
|
|
else_: "10".to_string(),
|
|
..Default::default()
|
|
},
|
|
max_received_headers: Expression {
|
|
else_: "50".to_string(),
|
|
..Default::default()
|
|
},
|
|
max_message_size: Expression {
|
|
else_: "104857600".to_string(),
|
|
..Default::default()
|
|
},
|
|
script: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
enable_spam_filter: Expression {
|
|
else_: "is_empty(authenticated_as)".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaStageData {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(
|
|
Property::AddAuthResultsHeader,
|
|
self.add_auth_results_header.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::AddDateHeader, self.add_date_header.into_value());
|
|
map.insert_unchecked(
|
|
Property::AddDeliveredToHeader,
|
|
self.add_delivered_to_header.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AddMessageIdHeader,
|
|
self.add_message_id_header.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AddReceivedHeader,
|
|
self.add_received_header.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AddReceivedSpfHeader,
|
|
self.add_received_spf_header.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AddReturnPathHeader,
|
|
self.add_return_path_header.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxMessages, self.max_messages.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxReceivedHeaders,
|
|
self.max_received_headers.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxMessageSize, self.max_message_size.into_value());
|
|
map.insert_unchecked(Property::Script, self.script.into_value());
|
|
map.insert_unchecked(
|
|
Property::EnableSpamFilter,
|
|
self.enable_spam_filter.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaStageData {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AddAuthResultsHeader) => {
|
|
self.add_auth_results_header.patch(pointer, value)
|
|
}
|
|
Some(Property::AddDateHeader) => self.add_date_header.patch(pointer, value),
|
|
Some(Property::AddDeliveredToHeader) => {
|
|
self.add_delivered_to_header.patch(pointer, value)
|
|
}
|
|
Some(Property::AddMessageIdHeader) => self.add_message_id_header.patch(pointer, value),
|
|
Some(Property::AddReceivedHeader) => self.add_received_header.patch(pointer, value),
|
|
Some(Property::AddReceivedSpfHeader) => {
|
|
self.add_received_spf_header.patch(pointer, value)
|
|
}
|
|
Some(Property::AddReturnPathHeader) => {
|
|
self.add_return_path_header.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxMessages) => self.max_messages.patch(pointer, value),
|
|
Some(Property::MaxReceivedHeaders) => self.max_received_headers.patch(pointer, value),
|
|
Some(Property::MaxMessageSize) => self.max_message_size.patch(pointer, value),
|
|
Some(Property::Script) => self.script.patch(pointer, value),
|
|
Some(Property::EnableSpamFilter) => self.enable_spam_filter.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaStageEhlo {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaStageEhlo;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.reject_non_fqdn;
|
|
value.validate(errors);
|
|
let value = &self.require;
|
|
value.validate(errors);
|
|
let value = &self.script;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaStageEhlo {
|
|
pub fn ctx_reject_non_fqdn(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.reject_non_fqdn,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::RejectNonFqdn,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_require(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.require,
|
|
default: Some(Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Require,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_script(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.script,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Script,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_reject_non_fqdn(),
|
|
self.ctx_require(),
|
|
self.ctx_script(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaStageEhlo {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.reject_non_fqdn.pickle(out);
|
|
self.require.pickle(out);
|
|
self.script.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.reject_non_fqdn = Pickle::unpickle(stream)?;
|
|
this.require = Pickle::unpickle(stream)?;
|
|
this.script = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaStageEhlo {
|
|
fn default() -> Self {
|
|
Self {
|
|
reject_non_fqdn: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "true".to_string(),
|
|
}]),
|
|
},
|
|
require: Expression {
|
|
else_: "true".to_string(),
|
|
..Default::default()
|
|
},
|
|
script: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaStageEhlo {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::RejectNonFqdn, self.reject_non_fqdn.into_value());
|
|
map.insert_unchecked(Property::Require, self.require.into_value());
|
|
map.insert_unchecked(Property::Script, self.script.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaStageEhlo {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::RejectNonFqdn) => self.reject_non_fqdn.patch(pointer, value),
|
|
Some(Property::Require) => self.require.patch(pointer, value),
|
|
Some(Property::Script) => self.script.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaStageMail {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaStageMail;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.is_sender_allowed;
|
|
value.validate(errors);
|
|
let value = &self.rewrite;
|
|
value.validate(errors);
|
|
let value = &self.script;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaStageMail {
|
|
pub fn ctx_is_sender_allowed(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.is_sender_allowed,
|
|
default: Some(Expression {
|
|
else_: "!is_empty(authenticated_as) || !key_exists('spam-block', sender_domain)"
|
|
.to_string(),
|
|
match_: List::from_iter([]),
|
|
}),
|
|
property: Property::IsSenderAllowed,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_rewrite(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.rewrite,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Rewrite,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_script(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.script,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Script,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_is_sender_allowed(),
|
|
self.ctx_rewrite(),
|
|
self.ctx_script(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaStageMail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.is_sender_allowed.pickle(out);
|
|
self.rewrite.pickle(out);
|
|
self.script.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.is_sender_allowed = Pickle::unpickle(stream)?;
|
|
this.rewrite = Pickle::unpickle(stream)?;
|
|
this.script = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaStageMail {
|
|
fn default() -> Self {
|
|
Self {
|
|
is_sender_allowed: Expression {
|
|
else_: "!is_empty(authenticated_as) || !key_exists('spam-block', sender_domain)"
|
|
.to_string(),
|
|
match_: List::from_iter([]),
|
|
},
|
|
rewrite: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
script: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaStageMail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(
|
|
Property::IsSenderAllowed,
|
|
self.is_sender_allowed.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Rewrite, self.rewrite.into_value());
|
|
map.insert_unchecked(Property::Script, self.script.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaStageMail {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::IsSenderAllowed) => self.is_sender_allowed.patch(pointer, value),
|
|
Some(Property::Rewrite) => self.rewrite.patch(pointer, value),
|
|
Some(Property::Script) => self.script.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaStageRcpt {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaStageRcpt;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_failures;
|
|
value.validate(errors);
|
|
let value = &self.wait_on_fail;
|
|
value.validate(errors);
|
|
let value = &self.max_recipients;
|
|
value.validate(errors);
|
|
let value = &self.allow_relaying;
|
|
value.validate(errors);
|
|
let value = &self.rewrite;
|
|
value.validate(errors);
|
|
let value = &self.script;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl MtaStageRcpt {
|
|
pub fn ctx_max_failures(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_failures,
|
|
default: Some(Expression {
|
|
else_: "5".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxFailures,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_wait_on_fail(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.wait_on_fail,
|
|
default: Some(Expression {
|
|
else_: "5s".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::WaitOnFail,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_max_recipients(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_recipients,
|
|
default: Some(Expression {
|
|
else_: "100".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxRecipients,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_allow_relaying(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.allow_relaying,
|
|
default: Some(Expression {
|
|
else_: "!is_empty(authenticated_as)".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::AllowRelaying,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_rewrite(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.rewrite,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Rewrite,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_script(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.script,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Script,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_max_failures(),
|
|
self.ctx_wait_on_fail(),
|
|
self.ctx_max_recipients(),
|
|
self.ctx_allow_relaying(),
|
|
self.ctx_rewrite(),
|
|
self.ctx_script(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaStageRcpt {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_failures.pickle(out);
|
|
self.wait_on_fail.pickle(out);
|
|
self.max_recipients.pickle(out);
|
|
self.allow_relaying.pickle(out);
|
|
self.rewrite.pickle(out);
|
|
self.script.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_failures = Pickle::unpickle(stream)?;
|
|
this.wait_on_fail = Pickle::unpickle(stream)?;
|
|
this.max_recipients = Pickle::unpickle(stream)?;
|
|
this.allow_relaying = Pickle::unpickle(stream)?;
|
|
this.rewrite = Pickle::unpickle(stream)?;
|
|
this.script = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaStageRcpt {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_failures: Expression {
|
|
else_: "5".to_string(),
|
|
..Default::default()
|
|
},
|
|
wait_on_fail: Expression {
|
|
else_: "5s".to_string(),
|
|
..Default::default()
|
|
},
|
|
max_recipients: Expression {
|
|
else_: "100".to_string(),
|
|
..Default::default()
|
|
},
|
|
allow_relaying: Expression {
|
|
else_: "!is_empty(authenticated_as)".to_string(),
|
|
..Default::default()
|
|
},
|
|
rewrite: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
script: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaStageRcpt {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::MaxFailures, self.max_failures.into_value());
|
|
map.insert_unchecked(Property::WaitOnFail, self.wait_on_fail.into_value());
|
|
map.insert_unchecked(Property::MaxRecipients, self.max_recipients.into_value());
|
|
map.insert_unchecked(Property::AllowRelaying, self.allow_relaying.into_value());
|
|
map.insert_unchecked(Property::Rewrite, self.rewrite.into_value());
|
|
map.insert_unchecked(Property::Script, self.script.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaStageRcpt {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxFailures) => self.max_failures.patch(pointer, value),
|
|
Some(Property::WaitOnFail) => self.wait_on_fail.patch(pointer, value),
|
|
Some(Property::MaxRecipients) => self.max_recipients.patch(pointer, value),
|
|
Some(Property::AllowRelaying) => self.allow_relaying.patch(pointer, value),
|
|
Some(Property::Rewrite) => self.rewrite.patch(pointer, value),
|
|
Some(Property::Script) => self.script.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaSts {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaSts;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.mx_hosts;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MxHosts));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for MtaSts {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_age.pickle(out);
|
|
self.mode.pickle(out);
|
|
self.mx_hosts.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_age = Pickle::unpickle(stream)?;
|
|
this.mode = Pickle::unpickle(stream)?;
|
|
this.mx_hosts = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaSts {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_age: Duration::from_millis(604800000),
|
|
mode: PolicyEnforcement::Testing,
|
|
mx_hosts: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaSts {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::MaxAge, self.max_age.into_value());
|
|
map.insert_unchecked(Property::Mode, self.mode.into_value());
|
|
map.insert_unchecked(Property::MxHosts, self.mx_hosts.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaSts {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxAge) => self.max_age.patch(pointer, value),
|
|
Some(Property::Mode) => self.mode.patch(pointer, value),
|
|
Some(Property::MxHosts) => self
|
|
.mx_hosts
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaTlsStrategy {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaTlsStrategy;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaTlsStrategy {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.dane.pickle(out);
|
|
self.description.pickle(out);
|
|
self.mta_sts.pickle(out);
|
|
self.start_tls.pickle(out);
|
|
self.mta_sts_timeout.pickle(out);
|
|
self.tls_timeout.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.dane = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.mta_sts = Pickle::unpickle(stream)?;
|
|
this.start_tls = Pickle::unpickle(stream)?;
|
|
this.mta_sts_timeout = Pickle::unpickle(stream)?;
|
|
this.tls_timeout = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaTlsStrategy {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
allow_invalid_certs: false,
|
|
dane: MtaRequiredOrOptional::Optional,
|
|
description: Default::default(),
|
|
mta_sts: MtaRequiredOrOptional::Optional,
|
|
start_tls: MtaRequiredOrOptional::Optional,
|
|
mta_sts_timeout: Duration::from_millis(300000),
|
|
tls_timeout: Duration::from_millis(180000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaTlsStrategy {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Dane, self.dane.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MtaSts, self.mta_sts.into_value());
|
|
map.insert_unchecked(Property::StartTls, self.start_tls.into_value());
|
|
map.insert_unchecked(Property::MtaStsTimeout, self.mta_sts_timeout.into_value());
|
|
map.insert_unchecked(Property::TlsTimeout, self.tls_timeout.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaTlsStrategy {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::Dane) => self.dane.patch(pointer, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::MtaSts) => self.mta_sts.patch(pointer, value),
|
|
Some(Property::StartTls) => self.start_tls.patch(pointer, value),
|
|
Some(Property::MtaStsTimeout) => self.mta_sts_timeout.patch(pointer, value),
|
|
Some(Property::TlsTimeout) => self.tls_timeout.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for MtaVirtualQueue {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::MtaVirtualQueue;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if value.len() > 8 {
|
|
errors.push(ValidationError::max_length(Property::Name, 8));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.threads_per_node;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ThreadsPerNode, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for MtaVirtualQueue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.threads_per_node.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.threads_per_node = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MtaVirtualQueue {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
threads_per_node: 25u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MtaVirtualQueue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::ThreadsPerNode, self.threads_per_node.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MtaVirtualQueue {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Trim]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::ThreadsPerNode) => self.threads_per_node.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MySqlSettings {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.host;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Host));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.database;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Database));
|
|
}
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MySqlSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.database.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.database = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MySqlSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
host: Default::default(),
|
|
port: 3306u64,
|
|
database: "stalwart".to_string(),
|
|
auth_username: Some("stalwart".to_string()),
|
|
auth_secret: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MySqlSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Database, self.database.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MySqlSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Database) => self
|
|
.database
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MySqlStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.max_allowed_packet {
|
|
if *value > 1073741824 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::MaxAllowedPacket,
|
|
1073741824,
|
|
));
|
|
}
|
|
if *value < 1024 {
|
|
errors.push(ValidationError::min_value(Property::MaxAllowedPacket, 1024));
|
|
}
|
|
}
|
|
if let Some(value) = &self.pool_max_connections {
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMaxConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.pool_min_connections {
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMinConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolMinConnections, 1));
|
|
}
|
|
}
|
|
let value = &self.read_replicas;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.host;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Host));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.database;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Database));
|
|
}
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for MySqlStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.timeout.pickle(out);
|
|
self.use_tls.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.max_allowed_packet.pickle(out);
|
|
self.pool_max_connections.pickle(out);
|
|
self.pool_min_connections.pickle(out);
|
|
self.read_replicas.pickle(out);
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.database.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.max_allowed_packet = Pickle::unpickle(stream)?;
|
|
this.pool_max_connections = Pickle::unpickle(stream)?;
|
|
this.pool_min_connections = Pickle::unpickle(stream)?;
|
|
this.read_replicas = Pickle::unpickle(stream)?;
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.database = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for MySqlStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
timeout: Some(Duration::from_millis(15000)),
|
|
use_tls: false,
|
|
allow_invalid_certs: false,
|
|
max_allowed_packet: Default::default(),
|
|
pool_max_connections: Some(10u64),
|
|
pool_min_connections: Some(5u64),
|
|
read_replicas: Default::default(),
|
|
host: Default::default(),
|
|
port: 3306u64,
|
|
database: "stalwart".to_string(),
|
|
auth_username: Some("stalwart".to_string()),
|
|
auth_secret: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for MySqlStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxAllowedPacket,
|
|
self.max_allowed_packet.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolMaxConnections,
|
|
self.pool_max_connections.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolMinConnections,
|
|
self.pool_min_connections.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ReadReplicas, self.read_replicas.into_value());
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Database, self.database.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for MySqlStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::MaxAllowedPacket) => self.max_allowed_packet.patch(pointer, value),
|
|
Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value),
|
|
Some(Property::PoolMinConnections) => self.pool_min_connections.patch(pointer, value),
|
|
Some(Property::ReadReplicas) => self.read_replicas.patch(pointer, value),
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Database) => self
|
|
.database
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl NatsCoordinator {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.addresses;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Addresses));
|
|
}
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Addresses, 1));
|
|
}
|
|
let value = &self.capacity_client;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::CapacityClient, 1));
|
|
}
|
|
let value = &self.capacity_read_buffer;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::CapacityReadBuffer, 1));
|
|
}
|
|
let value = &self.capacity_subscription;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::CapacitySubscription,
|
|
1,
|
|
));
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.credentials;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for NatsCoordinator {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.addresses.pickle(out);
|
|
self.max_reconnects.pickle(out);
|
|
self.timeout_connection.pickle(out);
|
|
self.timeout_request.pickle(out);
|
|
self.ping_interval.pickle(out);
|
|
self.capacity_client.pickle(out);
|
|
self.capacity_read_buffer.pickle(out);
|
|
self.capacity_subscription.pickle(out);
|
|
self.no_echo.pickle(out);
|
|
self.use_tls.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.credentials.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.addresses = Pickle::unpickle(stream)?;
|
|
this.max_reconnects = Pickle::unpickle(stream)?;
|
|
this.timeout_connection = Pickle::unpickle(stream)?;
|
|
this.timeout_request = Pickle::unpickle(stream)?;
|
|
this.ping_interval = Pickle::unpickle(stream)?;
|
|
this.capacity_client = Pickle::unpickle(stream)?;
|
|
this.capacity_read_buffer = Pickle::unpickle(stream)?;
|
|
this.capacity_subscription = Pickle::unpickle(stream)?;
|
|
this.no_echo = Pickle::unpickle(stream)?;
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.credentials = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for NatsCoordinator {
|
|
fn default() -> Self {
|
|
Self {
|
|
addresses: Map::new(vec!["127.0.0.1:4444".to_string()]),
|
|
max_reconnects: Default::default(),
|
|
timeout_connection: Duration::from_millis(5000),
|
|
timeout_request: Duration::from_millis(10000),
|
|
ping_interval: Duration::from_millis(60000),
|
|
capacity_client: 2048u64,
|
|
capacity_read_buffer: 65535u64,
|
|
capacity_subscription: 65536u64,
|
|
no_echo: true,
|
|
use_tls: false,
|
|
auth_secret: Default::default(),
|
|
auth_username: Some("stalwart".to_string()),
|
|
credentials: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for NatsCoordinator {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(Property::Addresses, self.addresses.into_value());
|
|
map.insert_unchecked(Property::MaxReconnects, self.max_reconnects.into_value());
|
|
map.insert_unchecked(
|
|
Property::TimeoutConnection,
|
|
self.timeout_connection.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::TimeoutRequest, self.timeout_request.into_value());
|
|
map.insert_unchecked(Property::PingInterval, self.ping_interval.into_value());
|
|
map.insert_unchecked(Property::CapacityClient, self.capacity_client.into_value());
|
|
map.insert_unchecked(
|
|
Property::CapacityReadBuffer,
|
|
self.capacity_read_buffer.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::CapacitySubscription,
|
|
self.capacity_subscription.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::NoEcho, self.no_echo.into_value());
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::Credentials, self.credentials.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for NatsCoordinator {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Addresses) => self.addresses.patch(pointer, value),
|
|
Some(Property::MaxReconnects) => self.max_reconnects.patch(pointer, value),
|
|
Some(Property::TimeoutConnection) => self.timeout_connection.patch(pointer, value),
|
|
Some(Property::TimeoutRequest) => self.timeout_request.patch(pointer, value),
|
|
Some(Property::PingInterval) => self.ping_interval.patch(pointer, value),
|
|
Some(Property::CapacityClient) => self.capacity_client.patch(pointer, value),
|
|
Some(Property::CapacityReadBuffer) => self.capacity_read_buffer.patch(pointer, value),
|
|
Some(Property::CapacitySubscription) => {
|
|
self.capacity_subscription.patch(pointer, value)
|
|
}
|
|
Some(Property::NoEcho) => self.no_echo.patch(pointer, value),
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Credentials) => self.credentials.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for NetworkListener {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::NetworkListener;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.bind;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Bind, value));
|
|
}
|
|
}
|
|
if value.len() < 1 {
|
|
errors.push(ValidationError::min_items(Property::Bind, 1));
|
|
}
|
|
let value = &self.override_proxy_trusted_networks;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(
|
|
Property::OverrideProxyTrustedNetworks,
|
|
value,
|
|
));
|
|
}
|
|
}
|
|
if let Some(value) = &self.socket_backlog {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::SocketBacklog, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.socket_receive_buffer_size {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::SocketReceiveBufferSize,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
if let Some(value) = &self.socket_send_buffer_size {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(
|
|
Property::SocketSendBufferSize,
|
|
1,
|
|
));
|
|
}
|
|
}
|
|
if let Some(value) = &self.socket_tos_v4 {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::SocketTosV4, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.socket_ttl {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::SocketTtl, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_connections {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxConnections, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for NetworkListener {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.bind.pickle(out);
|
|
self.protocol.pickle(out);
|
|
self.override_proxy_trusted_networks.pickle(out);
|
|
self.socket_backlog.pickle(out);
|
|
self.socket_no_delay.pickle(out);
|
|
self.socket_receive_buffer_size.pickle(out);
|
|
self.socket_reuse_address.pickle(out);
|
|
self.socket_reuse_port.pickle(out);
|
|
self.socket_send_buffer_size.pickle(out);
|
|
self.socket_tos_v4.pickle(out);
|
|
self.socket_ttl.pickle(out);
|
|
self.use_tls.pickle(out);
|
|
self.tls_disable_cipher_suites.pickle(out);
|
|
self.tls_disable_protocols.pickle(out);
|
|
self.tls_ignore_client_order.pickle(out);
|
|
self.tls_implicit.pickle(out);
|
|
self.tls_timeout.pickle(out);
|
|
self.max_connections.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.bind = Pickle::unpickle(stream)?;
|
|
this.protocol = Pickle::unpickle(stream)?;
|
|
this.override_proxy_trusted_networks = Pickle::unpickle(stream)?;
|
|
this.socket_backlog = Pickle::unpickle(stream)?;
|
|
this.socket_no_delay = Pickle::unpickle(stream)?;
|
|
this.socket_receive_buffer_size = Pickle::unpickle(stream)?;
|
|
this.socket_reuse_address = Pickle::unpickle(stream)?;
|
|
this.socket_reuse_port = Pickle::unpickle(stream)?;
|
|
this.socket_send_buffer_size = Pickle::unpickle(stream)?;
|
|
this.socket_tos_v4 = Pickle::unpickle(stream)?;
|
|
this.socket_ttl = Pickle::unpickle(stream)?;
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.tls_disable_cipher_suites = Pickle::unpickle(stream)?;
|
|
this.tls_disable_protocols = Pickle::unpickle(stream)?;
|
|
this.tls_ignore_client_order = Pickle::unpickle(stream)?;
|
|
this.tls_implicit = Pickle::unpickle(stream)?;
|
|
this.tls_timeout = Pickle::unpickle(stream)?;
|
|
this.max_connections = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for NetworkListener {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
bind: Default::default(),
|
|
protocol: NetworkListenerProtocol::Smtp,
|
|
override_proxy_trusted_networks: Default::default(),
|
|
socket_backlog: Some(1024u64),
|
|
socket_no_delay: true,
|
|
socket_receive_buffer_size: Default::default(),
|
|
socket_reuse_address: true,
|
|
socket_reuse_port: true,
|
|
socket_send_buffer_size: Default::default(),
|
|
socket_tos_v4: Default::default(),
|
|
socket_ttl: Default::default(),
|
|
use_tls: true,
|
|
tls_disable_cipher_suites: Default::default(),
|
|
tls_disable_protocols: Default::default(),
|
|
tls_ignore_client_order: true,
|
|
tls_implicit: false,
|
|
tls_timeout: Some(Duration::from_millis(60000)),
|
|
max_connections: Some(8192u64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for NetworkListener {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(21);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Bind, self.bind.into_value());
|
|
map.insert_unchecked(Property::Protocol, self.protocol.into_value());
|
|
map.insert_unchecked(
|
|
Property::OverrideProxyTrustedNetworks,
|
|
self.override_proxy_trusted_networks.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SocketBacklog, self.socket_backlog.into_value());
|
|
map.insert_unchecked(Property::SocketNoDelay, self.socket_no_delay.into_value());
|
|
map.insert_unchecked(
|
|
Property::SocketReceiveBufferSize,
|
|
self.socket_receive_buffer_size.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::SocketReuseAddress,
|
|
self.socket_reuse_address.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::SocketReusePort,
|
|
self.socket_reuse_port.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::SocketSendBufferSize,
|
|
self.socket_send_buffer_size.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SocketTosV4, self.socket_tos_v4.into_value());
|
|
map.insert_unchecked(Property::SocketTtl, self.socket_ttl.into_value());
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(
|
|
Property::TlsDisableCipherSuites,
|
|
self.tls_disable_cipher_suites.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TlsDisableProtocols,
|
|
self.tls_disable_protocols.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TlsIgnoreClientOrder,
|
|
self.tls_ignore_client_order.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::TlsImplicit, self.tls_implicit.into_value());
|
|
map.insert_unchecked(Property::TlsTimeout, self.tls_timeout.into_value());
|
|
map.insert_unchecked(Property::MaxConnections, self.max_connections.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for NetworkListener {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Bind) => self
|
|
.bind
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Protocol) => self.protocol.patch(pointer, value),
|
|
Some(Property::OverrideProxyTrustedNetworks) => self
|
|
.override_proxy_trusted_networks
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::SocketBacklog) => self.socket_backlog.patch(pointer, value),
|
|
Some(Property::SocketNoDelay) => self.socket_no_delay.patch(pointer, value),
|
|
Some(Property::SocketReceiveBufferSize) => {
|
|
self.socket_receive_buffer_size.patch(pointer, value)
|
|
}
|
|
Some(Property::SocketReuseAddress) => self.socket_reuse_address.patch(pointer, value),
|
|
Some(Property::SocketReusePort) => self.socket_reuse_port.patch(pointer, value),
|
|
Some(Property::SocketSendBufferSize) => {
|
|
self.socket_send_buffer_size.patch(pointer, value)
|
|
}
|
|
Some(Property::SocketTosV4) => self.socket_tos_v4.patch(pointer, value),
|
|
Some(Property::SocketTtl) => self.socket_ttl.patch(pointer, value),
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::TlsDisableCipherSuites) => {
|
|
self.tls_disable_cipher_suites.patch(pointer, value)
|
|
}
|
|
Some(Property::TlsDisableProtocols) => self.tls_disable_protocols.patch(pointer, value),
|
|
Some(Property::TlsIgnoreClientOrder) => {
|
|
self.tls_ignore_client_order.patch(pointer, value)
|
|
}
|
|
Some(Property::TlsImplicit) => self.tls_implicit.patch(pointer, value),
|
|
Some(Property::TlsTimeout) => self.tls_timeout.patch(pointer, value),
|
|
Some(Property::MaxConnections) => self.max_connections.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for OAuthClient {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::OAuthClient;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.client_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ClientId));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.contacts;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Contacts));
|
|
}
|
|
}
|
|
if let Some(value) = &self.secret {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
let value = &self.redirect_uris;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::RedirectUris));
|
|
}
|
|
}
|
|
if let Some(value) = &self.logo {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Logo));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::ClientId, &self.client_id);
|
|
if let Some(value) = &self.description {
|
|
i.text(Property::Text, value);
|
|
}
|
|
for value in self.contacts.iter() {
|
|
i.text(Property::Text, value);
|
|
}
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for OAuthClient {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.client_id.pickle(out);
|
|
self.description.pickle(out);
|
|
self.contacts.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.redirect_uris.pickle(out);
|
|
self.logo.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.client_id = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.contacts = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.redirect_uris = Pickle::unpickle(stream)?;
|
|
this.logo = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for OAuthClient {
|
|
fn default() -> Self {
|
|
Self {
|
|
client_id: Default::default(),
|
|
description: Default::default(),
|
|
contacts: Default::default(),
|
|
secret: Default::default(),
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
redirect_uris: Default::default(),
|
|
logo: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for OAuthClient {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::ClientId, self.client_id.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Contacts, self.contacts.into_value());
|
|
if self.secret.is_some() {
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
}
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::RedirectUris, self.redirect_uris.into_value());
|
|
map.insert_unchecked(Property::Logo, self.logo.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for OAuthClient {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ClientId) => self
|
|
.client_id
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Contacts) => self
|
|
.contacts
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::RedirectUris) => self.redirect_uris.patch(pointer, value),
|
|
Some(Property::Logo) => self.logo.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl OidcDirectory {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.issuer_url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::IssuerUrl));
|
|
}
|
|
if let Some(value) = &self.require_audience {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::RequireAudience));
|
|
}
|
|
}
|
|
let value = &self.require_scopes;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::RequireScopes));
|
|
}
|
|
}
|
|
let value = &self.claim_username;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ClaimUsername));
|
|
}
|
|
if let Some(value) = &self.username_domain {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::UsernameDomain));
|
|
}
|
|
}
|
|
if let Some(value) = &self.claim_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ClaimName));
|
|
}
|
|
}
|
|
if let Some(value) = &self.claim_groups {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ClaimGroups));
|
|
}
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for OidcDirectory {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.issuer_url.pickle(out);
|
|
self.require_audience.pickle(out);
|
|
self.require_scopes.pickle(out);
|
|
self.claim_username.pickle(out);
|
|
self.username_domain.pickle(out);
|
|
self.claim_name.pickle(out);
|
|
self.claim_groups.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.issuer_url = Pickle::unpickle(stream)?;
|
|
this.require_audience = Pickle::unpickle(stream)?;
|
|
this.require_scopes = Pickle::unpickle(stream)?;
|
|
this.claim_username = Pickle::unpickle(stream)?;
|
|
this.username_domain = Pickle::unpickle(stream)?;
|
|
this.claim_name = Pickle::unpickle(stream)?;
|
|
this.claim_groups = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for OidcDirectory {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
issuer_url: Default::default(),
|
|
require_audience: Some("stalwart".to_string()),
|
|
require_scopes: Map::new(vec!["openid".to_string(), "email".to_string()]),
|
|
claim_username: "preferred_username".to_string(),
|
|
username_domain: Default::default(),
|
|
claim_name: Some("name".to_string()),
|
|
claim_groups: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for OidcDirectory {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::IssuerUrl, self.issuer_url.into_value());
|
|
map.insert_unchecked(
|
|
Property::RequireAudience,
|
|
self.require_audience.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::RequireScopes, self.require_scopes.into_value());
|
|
map.insert_unchecked(Property::ClaimUsername, self.claim_username.into_value());
|
|
map.insert_unchecked(Property::UsernameDomain, self.username_domain.into_value());
|
|
map.insert_unchecked(Property::ClaimName, self.claim_name.into_value());
|
|
map.insert_unchecked(Property::ClaimGroups, self.claim_groups.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for OidcDirectory {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::IssuerUrl) => self
|
|
.issuer_url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::RequireAudience) => self
|
|
.require_audience
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::RequireScopes) => self
|
|
.require_scopes
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ClaimUsername) => self
|
|
.claim_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::UsernameDomain) => self.username_domain.patch(pointer, value),
|
|
Some(Property::ClaimName) => self
|
|
.claim_name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ClaimGroups) => self.claim_groups.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for OidcProvider {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::OidcProvider;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.auth_code_max_attempts;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::AuthCodeMaxAttempts, 1));
|
|
}
|
|
if *value > 1000 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::AuthCodeMaxAttempts,
|
|
1000,
|
|
));
|
|
}
|
|
let value = &self.encryption_key;
|
|
value.validate(errors);
|
|
let value = &self.signature_key;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for OidcProvider {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.auth_code_max_attempts.pickle(out);
|
|
self.anonymous_client_registration.pickle(out);
|
|
self.require_client_registration.pickle(out);
|
|
self.auth_code_expiry.pickle(out);
|
|
self.refresh_token_expiry.pickle(out);
|
|
self.refresh_token_renewal.pickle(out);
|
|
self.access_token_expiry.pickle(out);
|
|
self.user_code_expiry.pickle(out);
|
|
self.id_token_expiry.pickle(out);
|
|
self.encryption_key.pickle(out);
|
|
self.signature_algorithm.pickle(out);
|
|
self.signature_key.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.auth_code_max_attempts = Pickle::unpickle(stream)?;
|
|
this.anonymous_client_registration = Pickle::unpickle(stream)?;
|
|
this.require_client_registration = Pickle::unpickle(stream)?;
|
|
this.auth_code_expiry = Pickle::unpickle(stream)?;
|
|
this.refresh_token_expiry = Pickle::unpickle(stream)?;
|
|
this.refresh_token_renewal = Pickle::unpickle(stream)?;
|
|
this.access_token_expiry = Pickle::unpickle(stream)?;
|
|
this.user_code_expiry = Pickle::unpickle(stream)?;
|
|
this.id_token_expiry = Pickle::unpickle(stream)?;
|
|
this.encryption_key = Pickle::unpickle(stream)?;
|
|
this.signature_algorithm = Pickle::unpickle(stream)?;
|
|
this.signature_key = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for OidcProvider {
|
|
fn default() -> Self {
|
|
Self {
|
|
auth_code_max_attempts: 3u64,
|
|
anonymous_client_registration: false,
|
|
require_client_registration: false,
|
|
auth_code_expiry: Duration::from_millis(600000),
|
|
refresh_token_expiry: Duration::from_millis(2592000000),
|
|
refresh_token_renewal: Duration::from_millis(345600000),
|
|
access_token_expiry: Duration::from_millis(3600000),
|
|
user_code_expiry: Duration::from_millis(1800000),
|
|
id_token_expiry: Duration::from_millis(900000),
|
|
encryption_key: Default::default(),
|
|
signature_algorithm: JwtSignatureAlgorithm::Hs256,
|
|
signature_key: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for OidcProvider {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(
|
|
Property::AuthCodeMaxAttempts,
|
|
self.auth_code_max_attempts.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AnonymousClientRegistration,
|
|
self.anonymous_client_registration.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::RequireClientRegistration,
|
|
self.require_client_registration.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::AuthCodeExpiry, self.auth_code_expiry.into_value());
|
|
map.insert_unchecked(
|
|
Property::RefreshTokenExpiry,
|
|
self.refresh_token_expiry.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::RefreshTokenRenewal,
|
|
self.refresh_token_renewal.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AccessTokenExpiry,
|
|
self.access_token_expiry.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::UserCodeExpiry, self.user_code_expiry.into_value());
|
|
map.insert_unchecked(Property::IdTokenExpiry, self.id_token_expiry.into_value());
|
|
map.insert_unchecked(Property::EncryptionKey, self.encryption_key.into_value());
|
|
map.insert_unchecked(
|
|
Property::SignatureAlgorithm,
|
|
self.signature_algorithm.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SignatureKey, self.signature_key.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for OidcProvider {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AuthCodeMaxAttempts) => {
|
|
self.auth_code_max_attempts.patch(pointer, value)
|
|
}
|
|
Some(Property::AnonymousClientRegistration) => {
|
|
self.anonymous_client_registration.patch(pointer, value)
|
|
}
|
|
Some(Property::RequireClientRegistration) => {
|
|
self.require_client_registration.patch(pointer, value)
|
|
}
|
|
Some(Property::AuthCodeExpiry) => self.auth_code_expiry.patch(pointer, value),
|
|
Some(Property::RefreshTokenExpiry) => self.refresh_token_expiry.patch(pointer, value),
|
|
Some(Property::RefreshTokenRenewal) => self.refresh_token_renewal.patch(pointer, value),
|
|
Some(Property::AccessTokenExpiry) => self.access_token_expiry.patch(pointer, value),
|
|
Some(Property::UserCodeExpiry) => self.user_code_expiry.patch(pointer, value),
|
|
Some(Property::IdTokenExpiry) => self.id_token_expiry.patch(pointer, value),
|
|
Some(Property::EncryptionKey) => self.encryption_key.patch(pointer, value),
|
|
Some(Property::SignatureAlgorithm) => self.signature_algorithm.patch(pointer, value),
|
|
Some(Property::SignatureKey) => self.signature_key.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl OtpAuth {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.otp_code {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OtpCode));
|
|
}
|
|
}
|
|
if let Some(value) = &self.otp_url {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OtpUrl));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for OtpAuth {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.otp_code.pickle(out);
|
|
self.otp_url.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.otp_code = Pickle::unpickle(stream)?;
|
|
this.otp_url = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for OtpAuth {
|
|
fn default() -> Self {
|
|
Self {
|
|
otp_code: Default::default(),
|
|
otp_url: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for OtpAuth {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
if self.otp_code.is_some() {
|
|
map.insert_unchecked(Property::OtpCode, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
}
|
|
if self.otp_url.is_some() {
|
|
map.insert_unchecked(Property::OtpUrl, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
}
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for OtpAuth {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::OtpCode) => self.otp_code.patch(pointer, value),
|
|
Some(Property::OtpUrl) => self.otp_url.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PasswordCredential {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.credential_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CredentialId, value));
|
|
}
|
|
let value = &self.secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
if let Some(value) = &self.otp_auth {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OtpAuth));
|
|
}
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
let value = &self.allowed_ips;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::AllowedIps, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for PasswordCredential {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.credential_id.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.otp_auth.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.allowed_ips.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.credential_id = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.otp_auth = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.allowed_ips = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for PasswordCredential {
|
|
fn default() -> Self {
|
|
Self {
|
|
credential_id: Default::default(),
|
|
secret: Default::default(),
|
|
otp_auth: Default::default(),
|
|
expires_at: Default::default(),
|
|
allowed_ips: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PasswordCredential {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::CredentialId, self.credential_id.into_value());
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
if self.otp_auth.is_some() {
|
|
map.insert_unchecked(Property::OtpAuth, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
}
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for PasswordCredential {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CredentialId) => pointer.assert_server_set(),
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::OtpAuth) => self.otp_auth.patch(pointer, value),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Permissions {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Permissions::Inherit => true,
|
|
Permissions::Merge(inner) => inner.validate(errors),
|
|
Permissions::Replace(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Permissions {
|
|
fn default() -> Self {
|
|
Permissions::Inherit
|
|
}
|
|
}
|
|
|
|
impl Pickle for Permissions {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Permissions::Inherit => {
|
|
0u16.pickle(out);
|
|
}
|
|
Permissions::Merge(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Permissions::Replace(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(Permissions::Inherit),
|
|
1 => Pickle::unpickle(stream).map(Permissions::Merge),
|
|
2 => Pickle::unpickle(stream).map(Permissions::Replace),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Permissions {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Permissions::Inherit => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Inherit".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Permissions::Merge(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Merge".into()));
|
|
obj
|
|
}
|
|
Permissions::Replace(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Replace".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Permissions {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
PermissionsType::Inherit => *self = Permissions::Inherit,
|
|
PermissionsType::Merge => *self = Permissions::Merge(Default::default()),
|
|
PermissionsType::Replace => *self = Permissions::Replace(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Permissions::Inherit => pointer.assert_eof(),
|
|
Permissions::Merge(inner) => inner.patch(pointer, value),
|
|
Permissions::Replace(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Permissions {
|
|
pub fn object_type(&self) -> PermissionsType {
|
|
match self {
|
|
Permissions::Inherit => PermissionsType::Inherit,
|
|
Permissions::Merge(_) => PermissionsType::Merge,
|
|
Permissions::Replace(_) => PermissionsType::Replace,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PermissionsList {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for PermissionsList {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enabled_permissions.pickle(out);
|
|
self.disabled_permissions.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enabled_permissions = Pickle::unpickle(stream)?;
|
|
this.disabled_permissions = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for PermissionsList {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled_permissions: Default::default(),
|
|
disabled_permissions: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PermissionsList {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(
|
|
Property::EnabledPermissions,
|
|
self.enabled_permissions.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DisabledPermissions,
|
|
self.disabled_permissions.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for PermissionsList {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::EnabledPermissions) => self.enabled_permissions.patch(pointer, value),
|
|
Some(Property::DisabledPermissions) => self.disabled_permissions.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PostgreSqlSettings {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.host;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Host));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.database;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Database));
|
|
}
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.options {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Options));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for PostgreSqlSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.database.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
self.options.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.database = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
this.options = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for PostgreSqlSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
host: Default::default(),
|
|
port: 5432u64,
|
|
database: "stalwart".to_string(),
|
|
auth_username: Some("stalwart".to_string()),
|
|
auth_secret: Default::default(),
|
|
options: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PostgreSqlSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Database, self.database.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
map.insert_unchecked(Property::Options, self.options.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for PostgreSqlSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Database) => self
|
|
.database
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::Options) => self
|
|
.options
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PostgreSqlStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.pool_max_connections {
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMaxConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1));
|
|
}
|
|
}
|
|
let value = &self.read_replicas;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.host;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Host));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Port, 1));
|
|
}
|
|
let value = &self.database;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Database));
|
|
}
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.options {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Options));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for PostgreSqlStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.timeout.pickle(out);
|
|
self.use_tls.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.pool_max_connections.pickle(out);
|
|
self.pool_recycling_method.pickle(out);
|
|
self.read_replicas.pickle(out);
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.database.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
self.options.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.use_tls = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.pool_max_connections = Pickle::unpickle(stream)?;
|
|
this.pool_recycling_method = Pickle::unpickle(stream)?;
|
|
this.read_replicas = Pickle::unpickle(stream)?;
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.database = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
this.options = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for PostgreSqlStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
timeout: Some(Duration::from_millis(15000)),
|
|
use_tls: false,
|
|
allow_invalid_certs: false,
|
|
pool_max_connections: Some(10u64),
|
|
pool_recycling_method: PostgreSqlRecyclingMethod::Fast,
|
|
read_replicas: Default::default(),
|
|
host: Default::default(),
|
|
port: 5432u64,
|
|
database: "stalwart".to_string(),
|
|
auth_username: Some("stalwart".to_string()),
|
|
auth_secret: Default::default(),
|
|
options: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PostgreSqlStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::UseTls, self.use_tls.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolMaxConnections,
|
|
self.pool_max_connections.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolRecyclingMethod,
|
|
self.pool_recycling_method.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ReadReplicas, self.read_replicas.into_value());
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Database, self.database.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
map.insert_unchecked(Property::Options, self.options.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for PostgreSqlStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::UseTls) => self.use_tls.patch(pointer, value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value),
|
|
Some(Property::PoolRecyclingMethod) => self.pool_recycling_method.patch(pointer, value),
|
|
Some(Property::ReadReplicas) => self.read_replicas.patch(pointer, value),
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Database) => self
|
|
.database
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::Options) => self
|
|
.options
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for PublicKey {
|
|
const FLAGS: u64 = OBJ_FILTER_ACCOUNT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::PublicKey;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.key;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Key));
|
|
}
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
let value = &self.email_addresses;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EmailAddresses));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.search(Property::AccountId, &self.account_id);
|
|
}
|
|
}
|
|
|
|
impl Pickle for PublicKey {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.account_id.pickle(out);
|
|
self.key.pickle(out);
|
|
self.description.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.email_addresses.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.email_addresses = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for PublicKey {
|
|
fn default() -> Self {
|
|
Self {
|
|
account_id: Default::default(),
|
|
key: Default::default(),
|
|
description: Default::default(),
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
email_addresses: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PublicKey {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::EmailAddresses, self.email_addresses.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for PublicKey {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::Key) => self
|
|
.key
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::EmailAddresses) => self
|
|
.email_addresses
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PublicText {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
PublicText::Text(inner) => inner.validate(errors),
|
|
PublicText::EnvironmentVariable(inner) => inner.validate(errors),
|
|
PublicText::File(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for PublicText {
|
|
fn default() -> Self {
|
|
PublicText::Text(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for PublicText {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
PublicText::Text(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
PublicText::EnvironmentVariable(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
PublicText::File(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(PublicText::Text),
|
|
1 => Pickle::unpickle(stream).map(PublicText::EnvironmentVariable),
|
|
2 => Pickle::unpickle(stream).map(PublicText::File),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PublicText {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
PublicText::Text(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Text".into()));
|
|
obj
|
|
}
|
|
PublicText::EnvironmentVariable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into()));
|
|
obj
|
|
}
|
|
PublicText::File(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("File".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for PublicText {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
PublicTextType::Text => *self = PublicText::Text(Default::default()),
|
|
PublicTextType::EnvironmentVariable => {
|
|
*self = PublicText::EnvironmentVariable(Default::default())
|
|
}
|
|
PublicTextType::File => *self = PublicText::File(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
PublicText::Text(inner) => inner.patch(pointer, value),
|
|
PublicText::EnvironmentVariable(inner) => inner.patch(pointer, value),
|
|
PublicText::File(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PublicText {
|
|
pub fn object_type(&self) -> PublicTextType {
|
|
match self {
|
|
PublicText::Text(_) => PublicTextType::Text,
|
|
PublicText::EnvironmentVariable(_) => PublicTextType::EnvironmentVariable,
|
|
PublicText::File(_) => PublicTextType::File,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PublicTextValue {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for PublicTextValue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for PublicTextValue {
|
|
fn default() -> Self {
|
|
Self {
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for PublicTextValue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for PublicTextValue {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QueueExpiry {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
QueueExpiry::Ttl(inner) => inner.validate(errors),
|
|
QueueExpiry::Attempts(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for QueueExpiry {
|
|
fn default() -> Self {
|
|
QueueExpiry::Ttl(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for QueueExpiry {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
QueueExpiry::Ttl(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
QueueExpiry::Attempts(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(QueueExpiry::Ttl),
|
|
1 => Pickle::unpickle(stream).map(QueueExpiry::Attempts),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for QueueExpiry {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
QueueExpiry::Ttl(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ttl".into()));
|
|
obj
|
|
}
|
|
QueueExpiry::Attempts(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Attempts".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for QueueExpiry {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
QueueExpiryType::Ttl => *self = QueueExpiry::Ttl(Default::default()),
|
|
QueueExpiryType::Attempts => *self = QueueExpiry::Attempts(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
QueueExpiry::Ttl(inner) => inner.patch(pointer, value),
|
|
QueueExpiry::Attempts(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QueueExpiry {
|
|
pub fn object_type(&self) -> QueueExpiryType {
|
|
match self {
|
|
QueueExpiry::Ttl(_) => QueueExpiryType::Ttl,
|
|
QueueExpiry::Attempts(_) => QueueExpiryType::Attempts,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QueueExpiryAttempts {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for QueueExpiryAttempts {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.expires_attempts.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.expires_attempts = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for QueueExpiryAttempts {
|
|
fn default() -> Self {
|
|
Self {
|
|
expires_attempts: 0u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for QueueExpiryAttempts {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(
|
|
Property::ExpiresAttempts,
|
|
self.expires_attempts.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for QueueExpiryAttempts {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ExpiresAttempts) => self.expires_attempts.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QueueExpiryTtl {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.expires_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for QueueExpiryTtl {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.expires_at.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for QueueExpiryTtl {
|
|
fn default() -> Self {
|
|
Self {
|
|
expires_at: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for QueueExpiryTtl {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for QueueExpiryTtl {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for QueuedMessage {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::QueuedMessage;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.next_retry {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::NextRetry, value));
|
|
}
|
|
}
|
|
if let Some(value) = &self.next_notify {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::NextNotify, value));
|
|
}
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
let value = &self.return_path;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReturnPath));
|
|
}
|
|
let value = &self.recipients;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.received_from_ip;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ReceivedFromIp, value));
|
|
}
|
|
let value = &self.received_via_port;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ReceivedViaPort, 1));
|
|
}
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::ReceivedViaPort, 65535));
|
|
}
|
|
if let Some(value) = &self.env_id {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EnvId));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value < (-100) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -100));
|
|
}
|
|
if *value > (100) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 100));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for QueuedMessage {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.created_at.pickle(out);
|
|
self.next_retry.pickle(out);
|
|
self.next_notify.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
self.return_path.pickle(out);
|
|
self.recipients.pickle(out);
|
|
self.received_from_ip.pickle(out);
|
|
self.received_via_port.pickle(out);
|
|
self.flags.pickle(out);
|
|
self.env_id.pickle(out);
|
|
self.priority.pickle(out);
|
|
self.size.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.next_retry = Pickle::unpickle(stream)?;
|
|
this.next_notify = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
this.return_path = Pickle::unpickle(stream)?;
|
|
this.recipients = Pickle::unpickle(stream)?;
|
|
this.received_from_ip = Pickle::unpickle(stream)?;
|
|
this.received_via_port = Pickle::unpickle(stream)?;
|
|
this.flags = Pickle::unpickle(stream)?;
|
|
this.env_id = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
this.size = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for QueuedMessage {
|
|
fn default() -> Self {
|
|
Self {
|
|
created_at: Default::default(),
|
|
next_retry: Default::default(),
|
|
next_notify: Default::default(),
|
|
blob_id: Default::default(),
|
|
return_path: Default::default(),
|
|
recipients: Default::default(),
|
|
received_from_ip: Default::default(),
|
|
received_via_port: 25u64,
|
|
flags: Default::default(),
|
|
env_id: Default::default(),
|
|
priority: 0i64,
|
|
size: 0u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for QueuedMessage {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::NextRetry, self.next_retry.into_value());
|
|
map.insert_unchecked(Property::NextNotify, self.next_notify.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
map.insert_unchecked(Property::ReturnPath, self.return_path.into_value());
|
|
map.insert_unchecked(Property::Recipients, self.recipients.into_value());
|
|
map.insert_unchecked(Property::ReceivedFromIp, self.received_from_ip.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReceivedViaPort,
|
|
self.received_via_port.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Flags, self.flags.into_value());
|
|
map.insert_unchecked(Property::EnvId, self.env_id.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
map.insert_unchecked(Property::Size, self.size.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for QueuedMessage {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::NextRetry) => self.next_retry.patch(pointer, value),
|
|
Some(Property::NextNotify) => pointer.assert_server_set(),
|
|
Some(Property::BlobId) => pointer.assert_server_set(),
|
|
Some(Property::ReturnPath) => pointer.assert_server_set(),
|
|
Some(Property::Recipients) => self.recipients.patch(pointer, value),
|
|
Some(Property::ReceivedFromIp) => pointer.assert_server_set(),
|
|
Some(Property::ReceivedViaPort) => pointer.assert_server_set(),
|
|
Some(Property::Flags) => pointer.assert_server_set(),
|
|
Some(Property::EnvId) => self.env_id.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Size) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QueuedRecipient {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.retry_due;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::RetryDue, value));
|
|
}
|
|
let value = &self.notify_due;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::NotifyDue, value));
|
|
}
|
|
let value = &self.expires;
|
|
value.validate(errors);
|
|
let value = &self.queue_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::QueueName));
|
|
}
|
|
if value.len() > 8 {
|
|
errors.push(ValidationError::max_length(Property::QueueName, 8));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.orcpt {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Orcpt));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for QueuedRecipient {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.retry_count.pickle(out);
|
|
self.retry_due.pickle(out);
|
|
self.notify_count.pickle(out);
|
|
self.notify_due.pickle(out);
|
|
self.expires.pickle(out);
|
|
self.queue_name.pickle(out);
|
|
self.status.pickle(out);
|
|
self.flags.pickle(out);
|
|
self.orcpt.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.retry_count = Pickle::unpickle(stream)?;
|
|
this.retry_due = Pickle::unpickle(stream)?;
|
|
this.notify_count = Pickle::unpickle(stream)?;
|
|
this.notify_due = Pickle::unpickle(stream)?;
|
|
this.expires = Pickle::unpickle(stream)?;
|
|
this.queue_name = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
this.flags = Pickle::unpickle(stream)?;
|
|
this.orcpt = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for QueuedRecipient {
|
|
fn default() -> Self {
|
|
Self {
|
|
retry_count: 0u64,
|
|
retry_due: Default::default(),
|
|
notify_count: 0u64,
|
|
notify_due: Default::default(),
|
|
expires: Default::default(),
|
|
queue_name: Default::default(),
|
|
status: Default::default(),
|
|
flags: Default::default(),
|
|
orcpt: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for QueuedRecipient {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::RetryCount, self.retry_count.into_value());
|
|
map.insert_unchecked(Property::RetryDue, self.retry_due.into_value());
|
|
map.insert_unchecked(Property::NotifyCount, self.notify_count.into_value());
|
|
map.insert_unchecked(Property::NotifyDue, self.notify_due.into_value());
|
|
map.insert_unchecked(Property::Expires, self.expires.into_value());
|
|
map.insert_unchecked(Property::QueueName, self.queue_name.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
map.insert_unchecked(Property::Flags, self.flags.into_value());
|
|
map.insert_unchecked(Property::Orcpt, self.orcpt.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for QueuedRecipient {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::RetryCount) => self.retry_count.patch(pointer, value),
|
|
Some(Property::RetryDue) => self.retry_due.patch(pointer, value),
|
|
Some(Property::NotifyCount) => self.notify_count.patch(pointer, value),
|
|
Some(Property::NotifyDue) => self.notify_due.patch(pointer, value),
|
|
Some(Property::Expires) => self.expires.patch(pointer, value),
|
|
Some(Property::QueueName) => pointer.assert_server_set(),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Flags) => pointer.assert_server_set(),
|
|
Some(Property::Orcpt) => self.orcpt.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Rate {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.count;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::Count, 1));
|
|
}
|
|
if *value > 1000000 {
|
|
errors.push(ValidationError::max_value(Property::Count, 1000000));
|
|
}
|
|
let value = &self.period;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Period, value));
|
|
}
|
|
if *value < Duration::from_millis(1) {
|
|
errors.push(ValidationError::min_value(Property::Period, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for Rate {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.count.pickle(out);
|
|
self.period.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.count = Pickle::unpickle(stream)?;
|
|
this.period = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Rate {
|
|
fn default() -> Self {
|
|
Self {
|
|
count: 0u64,
|
|
period: Duration::from_millis(0),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Rate {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Count, self.count.into_value());
|
|
map.insert_unchecked(Property::Period, self.period.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Rate {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Count) => self.count.patch(pointer, value),
|
|
Some(Property::Period) => self.period.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RecipientStatus {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
RecipientStatus::Scheduled => true,
|
|
RecipientStatus::Completed(inner) => inner.validate(errors),
|
|
RecipientStatus::TemporaryFailure(inner) => inner.validate(errors),
|
|
RecipientStatus::PermanentFailure(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for RecipientStatus {
|
|
fn default() -> Self {
|
|
RecipientStatus::Scheduled
|
|
}
|
|
}
|
|
|
|
impl Pickle for RecipientStatus {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
RecipientStatus::Scheduled => {
|
|
0u16.pickle(out);
|
|
}
|
|
RecipientStatus::Completed(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
RecipientStatus::TemporaryFailure(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
RecipientStatus::PermanentFailure(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(RecipientStatus::Scheduled),
|
|
1 => Pickle::unpickle(stream).map(RecipientStatus::Completed),
|
|
2 => Pickle::unpickle(stream).map(RecipientStatus::TemporaryFailure),
|
|
3 => Pickle::unpickle(stream).map(RecipientStatus::PermanentFailure),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for RecipientStatus {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
RecipientStatus::Scheduled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Scheduled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
RecipientStatus::Completed(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Completed".into()));
|
|
obj
|
|
}
|
|
RecipientStatus::TemporaryFailure(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("TemporaryFailure".into()));
|
|
obj
|
|
}
|
|
RecipientStatus::PermanentFailure(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PermanentFailure".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for RecipientStatus {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
RecipientStatusType::Scheduled => *self = RecipientStatus::Scheduled,
|
|
RecipientStatusType::Completed => {
|
|
*self = RecipientStatus::Completed(Default::default())
|
|
}
|
|
RecipientStatusType::TemporaryFailure => {
|
|
*self = RecipientStatus::TemporaryFailure(Default::default())
|
|
}
|
|
RecipientStatusType::PermanentFailure => {
|
|
*self = RecipientStatus::PermanentFailure(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
RecipientStatus::Scheduled => pointer.assert_eof(),
|
|
RecipientStatus::Completed(inner) => inner.patch(pointer, value),
|
|
RecipientStatus::TemporaryFailure(inner) => inner.patch(pointer, value),
|
|
RecipientStatus::PermanentFailure(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RecipientStatus {
|
|
pub fn object_type(&self) -> RecipientStatusType {
|
|
match self {
|
|
RecipientStatus::Scheduled => RecipientStatusType::Scheduled,
|
|
RecipientStatus::Completed(_) => RecipientStatusType::Completed,
|
|
RecipientStatus::TemporaryFailure(_) => RecipientStatusType::TemporaryFailure,
|
|
RecipientStatus::PermanentFailure(_) => RecipientStatusType::PermanentFailure,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RedisClusterStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.urls;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Urls));
|
|
}
|
|
}
|
|
if let Some(value) = &self.auth_username {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthUsername));
|
|
}
|
|
}
|
|
let value = &self.auth_secret;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.max_retry_wait {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::MaxRetryWait, value));
|
|
}
|
|
if *value > Duration::from_millis(1024) {
|
|
errors.push(ValidationError::max_value(Property::MaxRetryWait, 1024));
|
|
}
|
|
if *value < Duration::from_millis(1) {
|
|
errors.push(ValidationError::min_value(Property::MaxRetryWait, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.min_retry_wait {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::MinRetryWait, value));
|
|
}
|
|
if *value > Duration::from_millis(1024) {
|
|
errors.push(ValidationError::max_value(Property::MinRetryWait, 1024));
|
|
}
|
|
if *value < Duration::from_millis(1) {
|
|
errors.push(ValidationError::min_value(Property::MinRetryWait, 1));
|
|
}
|
|
}
|
|
if let Some(value) = &self.max_retries {
|
|
if *value > 1024 {
|
|
errors.push(ValidationError::max_value(Property::MaxRetries, 1024));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxRetries, 1));
|
|
}
|
|
}
|
|
let value = &self.pool_max_connections;
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMaxConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for RedisClusterStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.urls.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.auth_username.pickle(out);
|
|
self.auth_secret.pickle(out);
|
|
self.max_retry_wait.pickle(out);
|
|
self.min_retry_wait.pickle(out);
|
|
self.max_retries.pickle(out);
|
|
self.read_from_replicas.pickle(out);
|
|
self.protocol_version.pickle(out);
|
|
self.pool_max_connections.pickle(out);
|
|
self.pool_timeout_create.pickle(out);
|
|
self.pool_timeout_wait.pickle(out);
|
|
self.pool_timeout_recycle.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.urls = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.auth_username = Pickle::unpickle(stream)?;
|
|
this.auth_secret = Pickle::unpickle(stream)?;
|
|
this.max_retry_wait = Pickle::unpickle(stream)?;
|
|
this.min_retry_wait = Pickle::unpickle(stream)?;
|
|
this.max_retries = Pickle::unpickle(stream)?;
|
|
this.read_from_replicas = Pickle::unpickle(stream)?;
|
|
this.protocol_version = Pickle::unpickle(stream)?;
|
|
this.pool_max_connections = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_create = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_wait = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_recycle = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for RedisClusterStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
urls: Map::new(vec!["redis://127.0.0.1".to_string()]),
|
|
timeout: Duration::from_millis(10000),
|
|
auth_username: Some("stalwart".to_string()),
|
|
auth_secret: Default::default(),
|
|
max_retry_wait: Default::default(),
|
|
min_retry_wait: Default::default(),
|
|
max_retries: Default::default(),
|
|
read_from_replicas: true,
|
|
protocol_version: RedisProtocol::Resp2,
|
|
pool_max_connections: 10u64,
|
|
pool_timeout_create: Some(Duration::from_millis(30000)),
|
|
pool_timeout_wait: Some(Duration::from_millis(30000)),
|
|
pool_timeout_recycle: Some(Duration::from_millis(30000)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for RedisClusterStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(Property::Urls, self.urls.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value());
|
|
map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value());
|
|
map.insert_unchecked(Property::MaxRetryWait, self.max_retry_wait.into_value());
|
|
map.insert_unchecked(Property::MinRetryWait, self.min_retry_wait.into_value());
|
|
map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReadFromReplicas,
|
|
self.read_from_replicas.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ProtocolVersion,
|
|
self.protocol_version.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolMaxConnections,
|
|
self.pool_max_connections.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutCreate,
|
|
self.pool_timeout_create.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutWait,
|
|
self.pool_timeout_wait.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutRecycle,
|
|
self.pool_timeout_recycle.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for RedisClusterStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Urls) => self
|
|
.urls
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::AuthUsername) => self
|
|
.auth_username
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value),
|
|
Some(Property::MaxRetryWait) => self.max_retry_wait.patch(pointer, value),
|
|
Some(Property::MinRetryWait) => self.min_retry_wait.patch(pointer, value),
|
|
Some(Property::MaxRetries) => self.max_retries.patch(pointer, value),
|
|
Some(Property::ReadFromReplicas) => self.read_from_replicas.patch(pointer, value),
|
|
Some(Property::ProtocolVersion) => self.protocol_version.patch(pointer, value),
|
|
Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value),
|
|
Some(Property::PoolTimeoutCreate) => self.pool_timeout_create.patch(pointer, value),
|
|
Some(Property::PoolTimeoutWait) => self.pool_timeout_wait.patch(pointer, value),
|
|
Some(Property::PoolTimeoutRecycle) => self.pool_timeout_recycle.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RedisStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.pool_max_connections;
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMaxConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for RedisStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.url.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.pool_max_connections.pickle(out);
|
|
self.pool_timeout_create.pickle(out);
|
|
self.pool_timeout_wait.pickle(out);
|
|
self.pool_timeout_recycle.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.pool_max_connections = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_create = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_wait = Pickle::unpickle(stream)?;
|
|
this.pool_timeout_recycle = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for RedisStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
url: "redis://127.0.0.1".to_string(),
|
|
timeout: Duration::from_millis(10000),
|
|
pool_max_connections: 10u64,
|
|
pool_timeout_create: Some(Duration::from_millis(30000)),
|
|
pool_timeout_wait: Some(Duration::from_millis(30000)),
|
|
pool_timeout_recycle: Some(Duration::from_millis(30000)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for RedisStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(
|
|
Property::PoolMaxConnections,
|
|
self.pool_max_connections.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutCreate,
|
|
self.pool_timeout_create.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutWait,
|
|
self.pool_timeout_wait.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::PoolTimeoutRecycle,
|
|
self.pool_timeout_recycle.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for RedisStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value),
|
|
Some(Property::PoolTimeoutCreate) => self.pool_timeout_create.patch(pointer, value),
|
|
Some(Property::PoolTimeoutWait) => self.pool_timeout_wait.patch(pointer, value),
|
|
Some(Property::PoolTimeoutRecycle) => self.pool_timeout_recycle.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for ReportSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::ReportSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.inbound_report_addresses;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::InboundReportAddresses));
|
|
}
|
|
}
|
|
if let Some(value) = &self.outbound_report_domain {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OutboundReportDomain));
|
|
}
|
|
}
|
|
let value = &self.outbound_report_submitter;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl ReportSettings {
|
|
pub fn ctx_outbound_report_submitter(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.outbound_report_submitter,
|
|
default: Some(Expression {
|
|
else_: "system('hostname')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::OutboundReportSubmitter,
|
|
allowed_variables: MTA_RCPT_DOMAIN_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_outbound_report_submitter()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for ReportSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.inbound_report_addresses.pickle(out);
|
|
self.inbound_report_forwarding.pickle(out);
|
|
self.outbound_report_domain.pickle(out);
|
|
self.outbound_report_submitter.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.inbound_report_addresses = Pickle::unpickle(stream)?;
|
|
this.inbound_report_forwarding = Pickle::unpickle(stream)?;
|
|
this.outbound_report_domain = Pickle::unpickle(stream)?;
|
|
this.outbound_report_submitter = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ReportSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
inbound_report_addresses: Map::new(vec!["postmaster@*".to_string()]),
|
|
inbound_report_forwarding: true,
|
|
outbound_report_domain: Default::default(),
|
|
outbound_report_submitter: Expression {
|
|
else_: "system('hostname')".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ReportSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(
|
|
Property::InboundReportAddresses,
|
|
self.inbound_report_addresses.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::InboundReportForwarding,
|
|
self.inbound_report_forwarding.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::OutboundReportDomain,
|
|
self.outbound_report_domain.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::OutboundReportSubmitter,
|
|
self.outbound_report_submitter.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ReportSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::InboundReportAddresses) => self
|
|
.inbound_report_addresses
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::InboundReportForwarding) => {
|
|
self.inbound_report_forwarding.patch(pointer, value)
|
|
}
|
|
Some(Property::OutboundReportDomain) => self
|
|
.outbound_report_domain
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::OutboundReportSubmitter) => {
|
|
self.outbound_report_submitter.patch(pointer, value)
|
|
}
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RocksDbStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.path;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Path));
|
|
}
|
|
let value = &self.blob_size;
|
|
if *value > 1048576 {
|
|
errors.push(ValidationError::max_value(Property::BlobSize, 1048576));
|
|
}
|
|
if *value < 1024 {
|
|
errors.push(ValidationError::min_value(Property::BlobSize, 1024));
|
|
}
|
|
let value = &self.buffer_size;
|
|
if *value > 1073741824 {
|
|
errors.push(ValidationError::max_value(Property::BufferSize, 1073741824));
|
|
}
|
|
if *value < 8192 {
|
|
errors.push(ValidationError::min_value(Property::BufferSize, 8192));
|
|
}
|
|
if let Some(value) = &self.pool_workers {
|
|
if *value > 64 {
|
|
errors.push(ValidationError::max_value(Property::PoolWorkers, 64));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolWorkers, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for RocksDbStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.path.pickle(out);
|
|
self.blob_size.pickle(out);
|
|
self.buffer_size.pickle(out);
|
|
self.pool_workers.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.path = Pickle::unpickle(stream)?;
|
|
this.blob_size = Pickle::unpickle(stream)?;
|
|
this.buffer_size = Pickle::unpickle(stream)?;
|
|
this.pool_workers = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for RocksDbStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
path: Default::default(),
|
|
blob_size: 16834u64,
|
|
buffer_size: 134217728u64,
|
|
pool_workers: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for RocksDbStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Path, self.path.into_value());
|
|
map.insert_unchecked(Property::BlobSize, self.blob_size.into_value());
|
|
map.insert_unchecked(Property::BufferSize, self.buffer_size.into_value());
|
|
map.insert_unchecked(Property::PoolWorkers, self.pool_workers.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for RocksDbStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Path) => self
|
|
.path
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::BlobSize) => self.blob_size.patch(pointer, value),
|
|
Some(Property::BufferSize) => self.buffer_size.patch(pointer, value),
|
|
Some(Property::PoolWorkers) => self.pool_workers.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Role {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Role;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
let value = &self.role_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::RoleIds));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.text(Property::Description, &self.description);
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
for id in self.role_ids.iter() {
|
|
i.foreign_key(ObjectType::Role, Some(*id), None);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for Role {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.role_ids.pickle(out);
|
|
self.enabled_permissions.pickle(out);
|
|
self.disabled_permissions.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.role_ids = Pickle::unpickle(stream)?;
|
|
this.enabled_permissions = Pickle::unpickle(stream)?;
|
|
this.disabled_permissions = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Role {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
role_ids: Default::default(),
|
|
enabled_permissions: Default::default(),
|
|
disabled_permissions: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Role {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::RoleIds, self.role_ids.into_value());
|
|
map.insert_unchecked(
|
|
Property::EnabledPermissions,
|
|
self.enabled_permissions.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DisabledPermissions,
|
|
self.disabled_permissions.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Role {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::RoleIds) => self.role_ids.patch(pointer, value),
|
|
Some(Property::EnabledPermissions) => self.enabled_permissions.patch(pointer, value),
|
|
Some(Property::DisabledPermissions) => self.disabled_permissions.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Roles {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Roles::Default => true,
|
|
Roles::Custom(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
Roles::Default => {}
|
|
Roles::Custom(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Roles {
|
|
fn default() -> Self {
|
|
Roles::Default
|
|
}
|
|
}
|
|
|
|
impl Pickle for Roles {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Roles::Default => {
|
|
0u16.pickle(out);
|
|
}
|
|
Roles::Custom(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(Roles::Default),
|
|
1 => Pickle::unpickle(stream).map(Roles::Custom),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Roles {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Roles::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
Roles::Custom(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Custom".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Roles {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
RolesType::Default => *self = Roles::Default,
|
|
RolesType::Custom => *self = Roles::Custom(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Roles::Default => pointer.assert_eof(),
|
|
Roles::Custom(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Roles {
|
|
pub fn object_type(&self) -> RolesType {
|
|
match self {
|
|
Roles::Default => RolesType::Default,
|
|
Roles::Custom(_) => RolesType::Custom,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl S3Store {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.region;
|
|
value.validate(errors);
|
|
let value = &self.bucket;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Bucket));
|
|
}
|
|
if let Some(value) = &self.access_key {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AccessKey));
|
|
}
|
|
}
|
|
let value = &self.secret_key;
|
|
value.validate(errors);
|
|
let value = &self.security_token;
|
|
value.validate(errors);
|
|
let value = &self.session_token;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.profile {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Profile));
|
|
}
|
|
}
|
|
let value = &self.max_retries;
|
|
if *value > 10 {
|
|
errors.push(ValidationError::max_value(Property::MaxRetries, 10));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxRetries, 1));
|
|
}
|
|
if let Some(value) = &self.key_prefix {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::KeyPrefix));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for S3Store {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.region.pickle(out);
|
|
self.bucket.pickle(out);
|
|
self.access_key.pickle(out);
|
|
self.secret_key.pickle(out);
|
|
self.security_token.pickle(out);
|
|
self.session_token.pickle(out);
|
|
self.profile.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.max_retries.pickle(out);
|
|
self.key_prefix.pickle(out);
|
|
self.allow_invalid_certs.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.region = Pickle::unpickle(stream)?;
|
|
this.bucket = Pickle::unpickle(stream)?;
|
|
this.access_key = Pickle::unpickle(stream)?;
|
|
this.secret_key = Pickle::unpickle(stream)?;
|
|
this.security_token = Pickle::unpickle(stream)?;
|
|
this.session_token = Pickle::unpickle(stream)?;
|
|
this.profile = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.max_retries = Pickle::unpickle(stream)?;
|
|
this.key_prefix = Pickle::unpickle(stream)?;
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for S3Store {
|
|
fn default() -> Self {
|
|
Self {
|
|
region: Default::default(),
|
|
bucket: Default::default(),
|
|
access_key: Default::default(),
|
|
secret_key: Default::default(),
|
|
security_token: Default::default(),
|
|
session_token: Default::default(),
|
|
profile: Default::default(),
|
|
timeout: Duration::from_millis(30000),
|
|
max_retries: 3u64,
|
|
key_prefix: Default::default(),
|
|
allow_invalid_certs: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for S3Store {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::Region, self.region.into_value());
|
|
map.insert_unchecked(Property::Bucket, self.bucket.into_value());
|
|
map.insert_unchecked(Property::AccessKey, self.access_key.into_value());
|
|
map.insert_unchecked(Property::SecretKey, self.secret_key.into_value());
|
|
map.insert_unchecked(Property::SecurityToken, self.security_token.into_value());
|
|
map.insert_unchecked(Property::SessionToken, self.session_token.into_value());
|
|
map.insert_unchecked(Property::Profile, self.profile.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value());
|
|
map.insert_unchecked(Property::KeyPrefix, self.key_prefix.into_value());
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for S3Store {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Region) => self.region.patch(pointer, value),
|
|
Some(Property::Bucket) => self
|
|
.bucket
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AccessKey) => self
|
|
.access_key
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::SecretKey) => self.secret_key.patch(pointer, value),
|
|
Some(Property::SecurityToken) => self.security_token.patch(pointer, value),
|
|
Some(Property::SessionToken) => self.session_token.patch(pointer, value),
|
|
Some(Property::Profile) => self
|
|
.profile
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::MaxRetries) => self.max_retries.patch(pointer, value),
|
|
Some(Property::KeyPrefix) => self
|
|
.key_prefix
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl S3StoreCustomRegion {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.custom_endpoint;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::CustomEndpoint));
|
|
}
|
|
let value = &self.custom_region;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::CustomRegion));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for S3StoreCustomRegion {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.custom_endpoint.pickle(out);
|
|
self.custom_region.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.custom_endpoint = Pickle::unpickle(stream)?;
|
|
this.custom_region = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for S3StoreCustomRegion {
|
|
fn default() -> Self {
|
|
Self {
|
|
custom_endpoint: Default::default(),
|
|
custom_region: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for S3StoreCustomRegion {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::CustomEndpoint, self.custom_endpoint.into_value());
|
|
map.insert_unchecked(Property::CustomRegion, self.custom_region.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for S3StoreCustomRegion {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CustomEndpoint) => self
|
|
.custom_endpoint
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::CustomRegion) => self
|
|
.custom_region
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl S3StoreRegion {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
S3StoreRegion::UsEast1 => true,
|
|
S3StoreRegion::UsEast2 => true,
|
|
S3StoreRegion::UsWest1 => true,
|
|
S3StoreRegion::UsWest2 => true,
|
|
S3StoreRegion::CaCentral1 => true,
|
|
S3StoreRegion::AfSouth1 => true,
|
|
S3StoreRegion::ApEast1 => true,
|
|
S3StoreRegion::ApSouth1 => true,
|
|
S3StoreRegion::ApNortheast1 => true,
|
|
S3StoreRegion::ApNortheast2 => true,
|
|
S3StoreRegion::ApNortheast3 => true,
|
|
S3StoreRegion::ApSoutheast1 => true,
|
|
S3StoreRegion::ApSoutheast2 => true,
|
|
S3StoreRegion::CnNorth1 => true,
|
|
S3StoreRegion::CnNorthwest1 => true,
|
|
S3StoreRegion::EuNorth1 => true,
|
|
S3StoreRegion::EuCentral1 => true,
|
|
S3StoreRegion::EuCentral2 => true,
|
|
S3StoreRegion::EuWest1 => true,
|
|
S3StoreRegion::EuWest2 => true,
|
|
S3StoreRegion::EuWest3 => true,
|
|
S3StoreRegion::IlCentral1 => true,
|
|
S3StoreRegion::MeSouth1 => true,
|
|
S3StoreRegion::SaEast1 => true,
|
|
S3StoreRegion::DoNyc3 => true,
|
|
S3StoreRegion::DoAms3 => true,
|
|
S3StoreRegion::DoSgp1 => true,
|
|
S3StoreRegion::DoFra1 => true,
|
|
S3StoreRegion::Yandex => true,
|
|
S3StoreRegion::WaUsEast1 => true,
|
|
S3StoreRegion::WaUsEast2 => true,
|
|
S3StoreRegion::WaUsCentral1 => true,
|
|
S3StoreRegion::WaUsWest1 => true,
|
|
S3StoreRegion::WaCaCentral1 => true,
|
|
S3StoreRegion::WaEuCentral1 => true,
|
|
S3StoreRegion::WaEuCentral2 => true,
|
|
S3StoreRegion::WaEuWest1 => true,
|
|
S3StoreRegion::WaEuWest2 => true,
|
|
S3StoreRegion::WaApNortheast1 => true,
|
|
S3StoreRegion::WaApNortheast2 => true,
|
|
S3StoreRegion::WaApSoutheast1 => true,
|
|
S3StoreRegion::WaApSoutheast2 => true,
|
|
S3StoreRegion::Custom(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for S3StoreRegion {
|
|
fn default() -> Self {
|
|
S3StoreRegion::UsEast1
|
|
}
|
|
}
|
|
|
|
impl Pickle for S3StoreRegion {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
S3StoreRegion::UsEast1 => {
|
|
0u16.pickle(out);
|
|
}
|
|
S3StoreRegion::UsEast2 => {
|
|
1u16.pickle(out);
|
|
}
|
|
S3StoreRegion::UsWest1 => {
|
|
2u16.pickle(out);
|
|
}
|
|
S3StoreRegion::UsWest2 => {
|
|
3u16.pickle(out);
|
|
}
|
|
S3StoreRegion::CaCentral1 => {
|
|
4u16.pickle(out);
|
|
}
|
|
S3StoreRegion::AfSouth1 => {
|
|
5u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApEast1 => {
|
|
6u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApSouth1 => {
|
|
7u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApNortheast1 => {
|
|
8u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApNortheast2 => {
|
|
9u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApNortheast3 => {
|
|
10u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApSoutheast1 => {
|
|
11u16.pickle(out);
|
|
}
|
|
S3StoreRegion::ApSoutheast2 => {
|
|
12u16.pickle(out);
|
|
}
|
|
S3StoreRegion::CnNorth1 => {
|
|
13u16.pickle(out);
|
|
}
|
|
S3StoreRegion::CnNorthwest1 => {
|
|
14u16.pickle(out);
|
|
}
|
|
S3StoreRegion::EuNorth1 => {
|
|
15u16.pickle(out);
|
|
}
|
|
S3StoreRegion::EuCentral1 => {
|
|
16u16.pickle(out);
|
|
}
|
|
S3StoreRegion::EuCentral2 => {
|
|
17u16.pickle(out);
|
|
}
|
|
S3StoreRegion::EuWest1 => {
|
|
18u16.pickle(out);
|
|
}
|
|
S3StoreRegion::EuWest2 => {
|
|
19u16.pickle(out);
|
|
}
|
|
S3StoreRegion::EuWest3 => {
|
|
20u16.pickle(out);
|
|
}
|
|
S3StoreRegion::IlCentral1 => {
|
|
21u16.pickle(out);
|
|
}
|
|
S3StoreRegion::MeSouth1 => {
|
|
22u16.pickle(out);
|
|
}
|
|
S3StoreRegion::SaEast1 => {
|
|
23u16.pickle(out);
|
|
}
|
|
S3StoreRegion::DoNyc3 => {
|
|
24u16.pickle(out);
|
|
}
|
|
S3StoreRegion::DoAms3 => {
|
|
25u16.pickle(out);
|
|
}
|
|
S3StoreRegion::DoSgp1 => {
|
|
26u16.pickle(out);
|
|
}
|
|
S3StoreRegion::DoFra1 => {
|
|
27u16.pickle(out);
|
|
}
|
|
S3StoreRegion::Yandex => {
|
|
28u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaUsEast1 => {
|
|
29u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaUsEast2 => {
|
|
30u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaUsCentral1 => {
|
|
31u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaUsWest1 => {
|
|
32u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaCaCentral1 => {
|
|
33u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaEuCentral1 => {
|
|
34u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaEuCentral2 => {
|
|
35u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaEuWest1 => {
|
|
36u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaEuWest2 => {
|
|
37u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaApNortheast1 => {
|
|
38u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaApNortheast2 => {
|
|
39u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaApSoutheast1 => {
|
|
40u16.pickle(out);
|
|
}
|
|
S3StoreRegion::WaApSoutheast2 => {
|
|
41u16.pickle(out);
|
|
}
|
|
S3StoreRegion::Custom(inner) => {
|
|
42u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(S3StoreRegion::UsEast1),
|
|
1 => Some(S3StoreRegion::UsEast2),
|
|
2 => Some(S3StoreRegion::UsWest1),
|
|
3 => Some(S3StoreRegion::UsWest2),
|
|
4 => Some(S3StoreRegion::CaCentral1),
|
|
5 => Some(S3StoreRegion::AfSouth1),
|
|
6 => Some(S3StoreRegion::ApEast1),
|
|
7 => Some(S3StoreRegion::ApSouth1),
|
|
8 => Some(S3StoreRegion::ApNortheast1),
|
|
9 => Some(S3StoreRegion::ApNortheast2),
|
|
10 => Some(S3StoreRegion::ApNortheast3),
|
|
11 => Some(S3StoreRegion::ApSoutheast1),
|
|
12 => Some(S3StoreRegion::ApSoutheast2),
|
|
13 => Some(S3StoreRegion::CnNorth1),
|
|
14 => Some(S3StoreRegion::CnNorthwest1),
|
|
15 => Some(S3StoreRegion::EuNorth1),
|
|
16 => Some(S3StoreRegion::EuCentral1),
|
|
17 => Some(S3StoreRegion::EuCentral2),
|
|
18 => Some(S3StoreRegion::EuWest1),
|
|
19 => Some(S3StoreRegion::EuWest2),
|
|
20 => Some(S3StoreRegion::EuWest3),
|
|
21 => Some(S3StoreRegion::IlCentral1),
|
|
22 => Some(S3StoreRegion::MeSouth1),
|
|
23 => Some(S3StoreRegion::SaEast1),
|
|
24 => Some(S3StoreRegion::DoNyc3),
|
|
25 => Some(S3StoreRegion::DoAms3),
|
|
26 => Some(S3StoreRegion::DoSgp1),
|
|
27 => Some(S3StoreRegion::DoFra1),
|
|
28 => Some(S3StoreRegion::Yandex),
|
|
29 => Some(S3StoreRegion::WaUsEast1),
|
|
30 => Some(S3StoreRegion::WaUsEast2),
|
|
31 => Some(S3StoreRegion::WaUsCentral1),
|
|
32 => Some(S3StoreRegion::WaUsWest1),
|
|
33 => Some(S3StoreRegion::WaCaCentral1),
|
|
34 => Some(S3StoreRegion::WaEuCentral1),
|
|
35 => Some(S3StoreRegion::WaEuCentral2),
|
|
36 => Some(S3StoreRegion::WaEuWest1),
|
|
37 => Some(S3StoreRegion::WaEuWest2),
|
|
38 => Some(S3StoreRegion::WaApNortheast1),
|
|
39 => Some(S3StoreRegion::WaApNortheast2),
|
|
40 => Some(S3StoreRegion::WaApSoutheast1),
|
|
41 => Some(S3StoreRegion::WaApSoutheast2),
|
|
42 => Pickle::unpickle(stream).map(S3StoreRegion::Custom),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for S3StoreRegion {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
S3StoreRegion::UsEast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("UsEast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::UsEast2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("UsEast2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::UsWest1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("UsWest1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::UsWest2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("UsWest2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::CaCentral1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("CaCentral1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::AfSouth1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("AfSouth1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApEast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApEast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApSouth1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApSouth1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApNortheast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApNortheast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApNortheast2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApNortheast2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApNortheast3 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApNortheast3".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApSoutheast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApSoutheast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::ApSoutheast2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("ApSoutheast2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::CnNorth1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("CnNorth1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::CnNorthwest1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("CnNorthwest1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::EuNorth1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EuNorth1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::EuCentral1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EuCentral1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::EuCentral2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EuCentral2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::EuWest1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EuWest1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::EuWest2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EuWest2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::EuWest3 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("EuWest3".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::IlCentral1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("IlCentral1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::MeSouth1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("MeSouth1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::SaEast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("SaEast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::DoNyc3 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("DoNyc3".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::DoAms3 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("DoAms3".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::DoSgp1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("DoSgp1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::DoFra1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("DoFra1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::Yandex => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Yandex".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaUsEast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsEast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaUsEast2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsEast2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaUsCentral1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsCentral1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaUsWest1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsWest1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaCaCentral1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaCaCentral1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaEuCentral1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuCentral1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaEuCentral2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuCentral2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaEuWest1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuWest1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaEuWest2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuWest2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaApNortheast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaApNortheast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaApNortheast2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaApNortheast2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaApSoutheast1 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaApSoutheast1".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::WaApSoutheast2 => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("WaApSoutheast2".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
S3StoreRegion::Custom(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Custom".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for S3StoreRegion {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
S3StoreRegionType::UsEast1 => *self = S3StoreRegion::UsEast1,
|
|
S3StoreRegionType::UsEast2 => *self = S3StoreRegion::UsEast2,
|
|
S3StoreRegionType::UsWest1 => *self = S3StoreRegion::UsWest1,
|
|
S3StoreRegionType::UsWest2 => *self = S3StoreRegion::UsWest2,
|
|
S3StoreRegionType::CaCentral1 => *self = S3StoreRegion::CaCentral1,
|
|
S3StoreRegionType::AfSouth1 => *self = S3StoreRegion::AfSouth1,
|
|
S3StoreRegionType::ApEast1 => *self = S3StoreRegion::ApEast1,
|
|
S3StoreRegionType::ApSouth1 => *self = S3StoreRegion::ApSouth1,
|
|
S3StoreRegionType::ApNortheast1 => *self = S3StoreRegion::ApNortheast1,
|
|
S3StoreRegionType::ApNortheast2 => *self = S3StoreRegion::ApNortheast2,
|
|
S3StoreRegionType::ApNortheast3 => *self = S3StoreRegion::ApNortheast3,
|
|
S3StoreRegionType::ApSoutheast1 => *self = S3StoreRegion::ApSoutheast1,
|
|
S3StoreRegionType::ApSoutheast2 => *self = S3StoreRegion::ApSoutheast2,
|
|
S3StoreRegionType::CnNorth1 => *self = S3StoreRegion::CnNorth1,
|
|
S3StoreRegionType::CnNorthwest1 => *self = S3StoreRegion::CnNorthwest1,
|
|
S3StoreRegionType::EuNorth1 => *self = S3StoreRegion::EuNorth1,
|
|
S3StoreRegionType::EuCentral1 => *self = S3StoreRegion::EuCentral1,
|
|
S3StoreRegionType::EuCentral2 => *self = S3StoreRegion::EuCentral2,
|
|
S3StoreRegionType::EuWest1 => *self = S3StoreRegion::EuWest1,
|
|
S3StoreRegionType::EuWest2 => *self = S3StoreRegion::EuWest2,
|
|
S3StoreRegionType::EuWest3 => *self = S3StoreRegion::EuWest3,
|
|
S3StoreRegionType::IlCentral1 => *self = S3StoreRegion::IlCentral1,
|
|
S3StoreRegionType::MeSouth1 => *self = S3StoreRegion::MeSouth1,
|
|
S3StoreRegionType::SaEast1 => *self = S3StoreRegion::SaEast1,
|
|
S3StoreRegionType::DoNyc3 => *self = S3StoreRegion::DoNyc3,
|
|
S3StoreRegionType::DoAms3 => *self = S3StoreRegion::DoAms3,
|
|
S3StoreRegionType::DoSgp1 => *self = S3StoreRegion::DoSgp1,
|
|
S3StoreRegionType::DoFra1 => *self = S3StoreRegion::DoFra1,
|
|
S3StoreRegionType::Yandex => *self = S3StoreRegion::Yandex,
|
|
S3StoreRegionType::WaUsEast1 => *self = S3StoreRegion::WaUsEast1,
|
|
S3StoreRegionType::WaUsEast2 => *self = S3StoreRegion::WaUsEast2,
|
|
S3StoreRegionType::WaUsCentral1 => *self = S3StoreRegion::WaUsCentral1,
|
|
S3StoreRegionType::WaUsWest1 => *self = S3StoreRegion::WaUsWest1,
|
|
S3StoreRegionType::WaCaCentral1 => *self = S3StoreRegion::WaCaCentral1,
|
|
S3StoreRegionType::WaEuCentral1 => *self = S3StoreRegion::WaEuCentral1,
|
|
S3StoreRegionType::WaEuCentral2 => *self = S3StoreRegion::WaEuCentral2,
|
|
S3StoreRegionType::WaEuWest1 => *self = S3StoreRegion::WaEuWest1,
|
|
S3StoreRegionType::WaEuWest2 => *self = S3StoreRegion::WaEuWest2,
|
|
S3StoreRegionType::WaApNortheast1 => *self = S3StoreRegion::WaApNortheast1,
|
|
S3StoreRegionType::WaApNortheast2 => *self = S3StoreRegion::WaApNortheast2,
|
|
S3StoreRegionType::WaApSoutheast1 => *self = S3StoreRegion::WaApSoutheast1,
|
|
S3StoreRegionType::WaApSoutheast2 => *self = S3StoreRegion::WaApSoutheast2,
|
|
S3StoreRegionType::Custom => *self = S3StoreRegion::Custom(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
S3StoreRegion::UsEast1 => pointer.assert_eof(),
|
|
S3StoreRegion::UsEast2 => pointer.assert_eof(),
|
|
S3StoreRegion::UsWest1 => pointer.assert_eof(),
|
|
S3StoreRegion::UsWest2 => pointer.assert_eof(),
|
|
S3StoreRegion::CaCentral1 => pointer.assert_eof(),
|
|
S3StoreRegion::AfSouth1 => pointer.assert_eof(),
|
|
S3StoreRegion::ApEast1 => pointer.assert_eof(),
|
|
S3StoreRegion::ApSouth1 => pointer.assert_eof(),
|
|
S3StoreRegion::ApNortheast1 => pointer.assert_eof(),
|
|
S3StoreRegion::ApNortheast2 => pointer.assert_eof(),
|
|
S3StoreRegion::ApNortheast3 => pointer.assert_eof(),
|
|
S3StoreRegion::ApSoutheast1 => pointer.assert_eof(),
|
|
S3StoreRegion::ApSoutheast2 => pointer.assert_eof(),
|
|
S3StoreRegion::CnNorth1 => pointer.assert_eof(),
|
|
S3StoreRegion::CnNorthwest1 => pointer.assert_eof(),
|
|
S3StoreRegion::EuNorth1 => pointer.assert_eof(),
|
|
S3StoreRegion::EuCentral1 => pointer.assert_eof(),
|
|
S3StoreRegion::EuCentral2 => pointer.assert_eof(),
|
|
S3StoreRegion::EuWest1 => pointer.assert_eof(),
|
|
S3StoreRegion::EuWest2 => pointer.assert_eof(),
|
|
S3StoreRegion::EuWest3 => pointer.assert_eof(),
|
|
S3StoreRegion::IlCentral1 => pointer.assert_eof(),
|
|
S3StoreRegion::MeSouth1 => pointer.assert_eof(),
|
|
S3StoreRegion::SaEast1 => pointer.assert_eof(),
|
|
S3StoreRegion::DoNyc3 => pointer.assert_eof(),
|
|
S3StoreRegion::DoAms3 => pointer.assert_eof(),
|
|
S3StoreRegion::DoSgp1 => pointer.assert_eof(),
|
|
S3StoreRegion::DoFra1 => pointer.assert_eof(),
|
|
S3StoreRegion::Yandex => pointer.assert_eof(),
|
|
S3StoreRegion::WaUsEast1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaUsEast2 => pointer.assert_eof(),
|
|
S3StoreRegion::WaUsCentral1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaUsWest1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaCaCentral1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaEuCentral1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaEuCentral2 => pointer.assert_eof(),
|
|
S3StoreRegion::WaEuWest1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaEuWest2 => pointer.assert_eof(),
|
|
S3StoreRegion::WaApNortheast1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaApNortheast2 => pointer.assert_eof(),
|
|
S3StoreRegion::WaApSoutheast1 => pointer.assert_eof(),
|
|
S3StoreRegion::WaApSoutheast2 => pointer.assert_eof(),
|
|
S3StoreRegion::Custom(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl S3StoreRegion {
|
|
pub fn object_type(&self) -> S3StoreRegionType {
|
|
match self {
|
|
S3StoreRegion::UsEast1 => S3StoreRegionType::UsEast1,
|
|
S3StoreRegion::UsEast2 => S3StoreRegionType::UsEast2,
|
|
S3StoreRegion::UsWest1 => S3StoreRegionType::UsWest1,
|
|
S3StoreRegion::UsWest2 => S3StoreRegionType::UsWest2,
|
|
S3StoreRegion::CaCentral1 => S3StoreRegionType::CaCentral1,
|
|
S3StoreRegion::AfSouth1 => S3StoreRegionType::AfSouth1,
|
|
S3StoreRegion::ApEast1 => S3StoreRegionType::ApEast1,
|
|
S3StoreRegion::ApSouth1 => S3StoreRegionType::ApSouth1,
|
|
S3StoreRegion::ApNortheast1 => S3StoreRegionType::ApNortheast1,
|
|
S3StoreRegion::ApNortheast2 => S3StoreRegionType::ApNortheast2,
|
|
S3StoreRegion::ApNortheast3 => S3StoreRegionType::ApNortheast3,
|
|
S3StoreRegion::ApSoutheast1 => S3StoreRegionType::ApSoutheast1,
|
|
S3StoreRegion::ApSoutheast2 => S3StoreRegionType::ApSoutheast2,
|
|
S3StoreRegion::CnNorth1 => S3StoreRegionType::CnNorth1,
|
|
S3StoreRegion::CnNorthwest1 => S3StoreRegionType::CnNorthwest1,
|
|
S3StoreRegion::EuNorth1 => S3StoreRegionType::EuNorth1,
|
|
S3StoreRegion::EuCentral1 => S3StoreRegionType::EuCentral1,
|
|
S3StoreRegion::EuCentral2 => S3StoreRegionType::EuCentral2,
|
|
S3StoreRegion::EuWest1 => S3StoreRegionType::EuWest1,
|
|
S3StoreRegion::EuWest2 => S3StoreRegionType::EuWest2,
|
|
S3StoreRegion::EuWest3 => S3StoreRegionType::EuWest3,
|
|
S3StoreRegion::IlCentral1 => S3StoreRegionType::IlCentral1,
|
|
S3StoreRegion::MeSouth1 => S3StoreRegionType::MeSouth1,
|
|
S3StoreRegion::SaEast1 => S3StoreRegionType::SaEast1,
|
|
S3StoreRegion::DoNyc3 => S3StoreRegionType::DoNyc3,
|
|
S3StoreRegion::DoAms3 => S3StoreRegionType::DoAms3,
|
|
S3StoreRegion::DoSgp1 => S3StoreRegionType::DoSgp1,
|
|
S3StoreRegion::DoFra1 => S3StoreRegionType::DoFra1,
|
|
S3StoreRegion::Yandex => S3StoreRegionType::Yandex,
|
|
S3StoreRegion::WaUsEast1 => S3StoreRegionType::WaUsEast1,
|
|
S3StoreRegion::WaUsEast2 => S3StoreRegionType::WaUsEast2,
|
|
S3StoreRegion::WaUsCentral1 => S3StoreRegionType::WaUsCentral1,
|
|
S3StoreRegion::WaUsWest1 => S3StoreRegionType::WaUsWest1,
|
|
S3StoreRegion::WaCaCentral1 => S3StoreRegionType::WaCaCentral1,
|
|
S3StoreRegion::WaEuCentral1 => S3StoreRegionType::WaEuCentral1,
|
|
S3StoreRegion::WaEuCentral2 => S3StoreRegionType::WaEuCentral2,
|
|
S3StoreRegion::WaEuWest1 => S3StoreRegionType::WaEuWest1,
|
|
S3StoreRegion::WaEuWest2 => S3StoreRegionType::WaEuWest2,
|
|
S3StoreRegion::WaApNortheast1 => S3StoreRegionType::WaApNortheast1,
|
|
S3StoreRegion::WaApNortheast2 => S3StoreRegionType::WaApNortheast2,
|
|
S3StoreRegion::WaApSoutheast1 => S3StoreRegionType::WaApSoutheast1,
|
|
S3StoreRegion::WaApSoutheast2 => S3StoreRegionType::WaApSoutheast2,
|
|
S3StoreRegion::Custom(_) => S3StoreRegionType::Custom,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Search {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Search;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.index_batch_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::IndexBatchSize, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Search {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.index_batch_size.pickle(out);
|
|
self.default_language.pickle(out);
|
|
self.supported_languages.pickle(out);
|
|
self.index_calendar.pickle(out);
|
|
self.index_calendar_fields.pickle(out);
|
|
self.index_contacts.pickle(out);
|
|
self.index_contact_fields.pickle(out);
|
|
self.index_email.pickle(out);
|
|
self.index_email_fields.pickle(out);
|
|
self.index_telemetry.pickle(out);
|
|
self.index_tracing_fields.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.index_batch_size = Pickle::unpickle(stream)?;
|
|
this.default_language = Pickle::unpickle(stream)?;
|
|
this.supported_languages = Pickle::unpickle(stream)?;
|
|
this.index_calendar = Pickle::unpickle(stream)?;
|
|
this.index_calendar_fields = Pickle::unpickle(stream)?;
|
|
this.index_contacts = Pickle::unpickle(stream)?;
|
|
this.index_contact_fields = Pickle::unpickle(stream)?;
|
|
this.index_email = Pickle::unpickle(stream)?;
|
|
this.index_email_fields = Pickle::unpickle(stream)?;
|
|
this.index_telemetry = Pickle::unpickle(stream)?;
|
|
this.index_tracing_fields = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Search {
|
|
fn default() -> Self {
|
|
Self {
|
|
index_batch_size: 100u64,
|
|
default_language: Locale::EnUS,
|
|
supported_languages: Map::new(vec![Locale::EnUS]),
|
|
index_calendar: true,
|
|
index_calendar_fields: Map::new(vec![
|
|
SearchCalendarField::Title,
|
|
SearchCalendarField::Description,
|
|
SearchCalendarField::Location,
|
|
SearchCalendarField::Owner,
|
|
SearchCalendarField::Attendee,
|
|
SearchCalendarField::Start,
|
|
SearchCalendarField::Uid,
|
|
]),
|
|
index_contacts: true,
|
|
index_contact_fields: Map::new(vec![
|
|
SearchContactField::Member,
|
|
SearchContactField::Kind,
|
|
SearchContactField::Name,
|
|
SearchContactField::Nickname,
|
|
SearchContactField::Organization,
|
|
SearchContactField::Email,
|
|
SearchContactField::Phone,
|
|
SearchContactField::OnlineService,
|
|
SearchContactField::Address,
|
|
SearchContactField::Note,
|
|
SearchContactField::Uid,
|
|
]),
|
|
index_email: true,
|
|
index_email_fields: Map::new(vec![
|
|
SearchEmailField::From,
|
|
SearchEmailField::To,
|
|
SearchEmailField::Cc,
|
|
SearchEmailField::Bcc,
|
|
SearchEmailField::Subject,
|
|
SearchEmailField::Body,
|
|
SearchEmailField::Attachment,
|
|
SearchEmailField::ReceivedAt,
|
|
SearchEmailField::SentAt,
|
|
SearchEmailField::Size,
|
|
SearchEmailField::HasAttachment,
|
|
]),
|
|
index_telemetry: true,
|
|
index_tracing_fields: Map::new(vec![
|
|
SearchTracingField::EventType,
|
|
SearchTracingField::QueueId,
|
|
SearchTracingField::Keywords,
|
|
]),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Search {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::IndexBatchSize, self.index_batch_size.into_value());
|
|
map.insert_unchecked(
|
|
Property::DefaultLanguage,
|
|
self.default_language.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::SupportedLanguages,
|
|
self.supported_languages.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::IndexCalendar, self.index_calendar.into_value());
|
|
map.insert_unchecked(
|
|
Property::IndexCalendarFields,
|
|
self.index_calendar_fields.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::IndexContacts, self.index_contacts.into_value());
|
|
map.insert_unchecked(
|
|
Property::IndexContactFields,
|
|
self.index_contact_fields.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::IndexEmail, self.index_email.into_value());
|
|
map.insert_unchecked(
|
|
Property::IndexEmailFields,
|
|
self.index_email_fields.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::IndexTelemetry, self.index_telemetry.into_value());
|
|
map.insert_unchecked(
|
|
Property::IndexTracingFields,
|
|
self.index_tracing_fields.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Search {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::IndexBatchSize) => self.index_batch_size.patch(pointer, value),
|
|
Some(Property::DefaultLanguage) => self.default_language.patch(pointer, value),
|
|
Some(Property::SupportedLanguages) => self.supported_languages.patch(pointer, value),
|
|
Some(Property::IndexCalendar) => self.index_calendar.patch(pointer, value),
|
|
Some(Property::IndexCalendarFields) => self.index_calendar_fields.patch(pointer, value),
|
|
Some(Property::IndexContacts) => self.index_contacts.patch(pointer, value),
|
|
Some(Property::IndexContactFields) => self.index_contact_fields.patch(pointer, value),
|
|
Some(Property::IndexEmail) => self.index_email.patch(pointer, value),
|
|
Some(Property::IndexEmailFields) => self.index_email_fields.patch(pointer, value),
|
|
Some(Property::IndexTelemetry) => self.index_telemetry.patch(pointer, value),
|
|
Some(Property::IndexTracingFields) => self.index_tracing_fields.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SearchStore {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SearchStore;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SearchStore::Default => true,
|
|
SearchStore::ElasticSearch(inner) => inner.validate(errors),
|
|
SearchStore::Meilisearch(inner) => inner.validate(errors),
|
|
SearchStore::FoundationDb(inner) => inner.validate(errors),
|
|
SearchStore::PostgreSql(inner) => inner.validate(errors),
|
|
SearchStore::MySql(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for SearchStore {
|
|
fn default() -> Self {
|
|
SearchStore::Default
|
|
}
|
|
}
|
|
|
|
impl Pickle for SearchStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SearchStore::Default => {
|
|
0u16.pickle(out);
|
|
}
|
|
SearchStore::ElasticSearch(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SearchStore::Meilisearch(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SearchStore::FoundationDb(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SearchStore::PostgreSql(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SearchStore::MySql(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(SearchStore::Default),
|
|
1 => Pickle::unpickle(stream).map(SearchStore::ElasticSearch),
|
|
2 => Pickle::unpickle(stream).map(SearchStore::Meilisearch),
|
|
3 => Pickle::unpickle(stream).map(SearchStore::FoundationDb),
|
|
4 => Pickle::unpickle(stream).map(SearchStore::PostgreSql),
|
|
5 => Pickle::unpickle(stream).map(SearchStore::MySql),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SearchStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SearchStore::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
SearchStore::ElasticSearch(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("ElasticSearch".into()));
|
|
obj
|
|
}
|
|
SearchStore::Meilisearch(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Meilisearch".into()));
|
|
obj
|
|
}
|
|
SearchStore::FoundationDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into()));
|
|
obj
|
|
}
|
|
SearchStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
SearchStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SearchStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SearchStoreType::Default => *self = SearchStore::Default,
|
|
SearchStoreType::ElasticSearch => {
|
|
*self = SearchStore::ElasticSearch(Default::default())
|
|
}
|
|
SearchStoreType::Meilisearch => {
|
|
*self = SearchStore::Meilisearch(Default::default())
|
|
}
|
|
SearchStoreType::FoundationDb => {
|
|
*self = SearchStore::FoundationDb(Default::default())
|
|
}
|
|
SearchStoreType::PostgreSql => *self = SearchStore::PostgreSql(Default::default()),
|
|
SearchStoreType::MySql => *self = SearchStore::MySql(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SearchStore::Default => pointer.assert_eof(),
|
|
SearchStore::ElasticSearch(inner) => inner.patch(pointer, value),
|
|
SearchStore::Meilisearch(inner) => inner.patch(pointer, value),
|
|
SearchStore::FoundationDb(inner) => inner.patch(pointer, value),
|
|
SearchStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
SearchStore::MySql(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SearchStore {
|
|
pub fn object_type(&self) -> SearchStoreType {
|
|
match self {
|
|
SearchStore::Default => SearchStoreType::Default,
|
|
SearchStore::ElasticSearch(_) => SearchStoreType::ElasticSearch,
|
|
SearchStore::Meilisearch(_) => SearchStoreType::Meilisearch,
|
|
SearchStore::FoundationDb(_) => SearchStoreType::FoundationDb,
|
|
SearchStore::PostgreSql(_) => SearchStoreType::PostgreSql,
|
|
SearchStore::MySql(_) => SearchStoreType::MySql,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecondaryCredential {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.credential_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CredentialId, value));
|
|
}
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.expires_at {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
}
|
|
let value = &self.permissions;
|
|
value.validate(errors);
|
|
let value = &self.allowed_ips;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::AllowedIps, value));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecondaryCredential {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.credential_id.pickle(out);
|
|
self.description.pickle(out);
|
|
self.secret.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.permissions.pickle(out);
|
|
self.allowed_ips.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.credential_id = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
this.allowed_ips = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SecondaryCredential {
|
|
fn default() -> Self {
|
|
Self {
|
|
credential_id: Default::default(),
|
|
description: Default::default(),
|
|
secret: Default::default(),
|
|
created_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
permissions: Default::default(),
|
|
allowed_ips: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecondaryCredential {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::CredentialId, self.credential_id.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SecondaryCredential {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CredentialId) => pointer.assert_server_set(),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Secret) => pointer.assert_server_set(),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKey {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SecretKey::Value(inner) => inner.validate(errors),
|
|
SecretKey::EnvironmentVariable(inner) => inner.validate(errors),
|
|
SecretKey::File(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SecretKey {
|
|
fn default() -> Self {
|
|
SecretKey::Value(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretKey {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SecretKey::Value(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretKey::EnvironmentVariable(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretKey::File(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(SecretKey::Value),
|
|
1 => Pickle::unpickle(stream).map(SecretKey::EnvironmentVariable),
|
|
2 => Pickle::unpickle(stream).map(SecretKey::File),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretKey {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SecretKey::Value(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Value".into()));
|
|
obj
|
|
}
|
|
SecretKey::EnvironmentVariable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into()));
|
|
obj
|
|
}
|
|
SecretKey::File(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("File".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SecretKey {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SecretKeyType::Value => *self = SecretKey::Value(Default::default()),
|
|
SecretKeyType::EnvironmentVariable => {
|
|
*self = SecretKey::EnvironmentVariable(Default::default())
|
|
}
|
|
SecretKeyType::File => *self = SecretKey::File(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SecretKey::Value(inner) => inner.patch(pointer, value),
|
|
SecretKey::EnvironmentVariable(inner) => inner.patch(pointer, value),
|
|
SecretKey::File(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKey {
|
|
pub fn object_type(&self) -> SecretKeyType {
|
|
match self {
|
|
SecretKey::Value(_) => SecretKeyType::Value,
|
|
SecretKey::EnvironmentVariable(_) => SecretKeyType::EnvironmentVariable,
|
|
SecretKey::File(_) => SecretKeyType::File,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKeyEnvironmentVariable {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.variable_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::VariableName));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretKeyEnvironmentVariable {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.variable_name.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.variable_name = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SecretKeyEnvironmentVariable {
|
|
fn default() -> Self {
|
|
Self {
|
|
variable_name: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretKeyEnvironmentVariable {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::VariableName, self.variable_name.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SecretKeyEnvironmentVariable {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::VariableName) => self.variable_name.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKeyFile {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.file_path;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FilePath));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretKeyFile {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.file_path.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.file_path = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SecretKeyFile {
|
|
fn default() -> Self {
|
|
Self {
|
|
file_path: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretKeyFile {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::FilePath, self.file_path.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SecretKeyFile {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::FilePath) => self.file_path.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKeyOptional {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SecretKeyOptional::None => true,
|
|
SecretKeyOptional::Value(inner) => inner.validate(errors),
|
|
SecretKeyOptional::EnvironmentVariable(inner) => inner.validate(errors),
|
|
SecretKeyOptional::File(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SecretKeyOptional {
|
|
fn default() -> Self {
|
|
SecretKeyOptional::None
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretKeyOptional {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SecretKeyOptional::None => {
|
|
0u16.pickle(out);
|
|
}
|
|
SecretKeyOptional::Value(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretKeyOptional::EnvironmentVariable(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretKeyOptional::File(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(SecretKeyOptional::None),
|
|
1 => Pickle::unpickle(stream).map(SecretKeyOptional::Value),
|
|
2 => Pickle::unpickle(stream).map(SecretKeyOptional::EnvironmentVariable),
|
|
3 => Pickle::unpickle(stream).map(SecretKeyOptional::File),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretKeyOptional {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SecretKeyOptional::None => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("None".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
SecretKeyOptional::Value(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Value".into()));
|
|
obj
|
|
}
|
|
SecretKeyOptional::EnvironmentVariable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into()));
|
|
obj
|
|
}
|
|
SecretKeyOptional::File(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("File".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SecretKeyOptional {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SecretKeyOptionalType::None => *self = SecretKeyOptional::None,
|
|
SecretKeyOptionalType::Value => {
|
|
*self = SecretKeyOptional::Value(Default::default())
|
|
}
|
|
SecretKeyOptionalType::EnvironmentVariable => {
|
|
*self = SecretKeyOptional::EnvironmentVariable(Default::default())
|
|
}
|
|
SecretKeyOptionalType::File => *self = SecretKeyOptional::File(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SecretKeyOptional::None => pointer.assert_eof(),
|
|
SecretKeyOptional::Value(inner) => inner.patch(pointer, value),
|
|
SecretKeyOptional::EnvironmentVariable(inner) => inner.patch(pointer, value),
|
|
SecretKeyOptional::File(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKeyOptional {
|
|
pub fn object_type(&self) -> SecretKeyOptionalType {
|
|
match self {
|
|
SecretKeyOptional::None => SecretKeyOptionalType::None,
|
|
SecretKeyOptional::Value(_) => SecretKeyOptionalType::Value,
|
|
SecretKeyOptional::EnvironmentVariable(_) => SecretKeyOptionalType::EnvironmentVariable,
|
|
SecretKeyOptional::File(_) => SecretKeyOptionalType::File,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretKeyValue {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretKeyValue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.secret.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SecretKeyValue {
|
|
fn default() -> Self {
|
|
Self {
|
|
secret: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretKeyValue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SecretKeyValue {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretText {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SecretText::Text(inner) => inner.validate(errors),
|
|
SecretText::EnvironmentVariable(inner) => inner.validate(errors),
|
|
SecretText::File(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SecretText {
|
|
fn default() -> Self {
|
|
SecretText::Text(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretText {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SecretText::Text(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretText::EnvironmentVariable(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretText::File(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(SecretText::Text),
|
|
1 => Pickle::unpickle(stream).map(SecretText::EnvironmentVariable),
|
|
2 => Pickle::unpickle(stream).map(SecretText::File),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretText {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SecretText::Text(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Text".into()));
|
|
obj
|
|
}
|
|
SecretText::EnvironmentVariable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into()));
|
|
obj
|
|
}
|
|
SecretText::File(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("File".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SecretText {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SecretTextType::Text => *self = SecretText::Text(Default::default()),
|
|
SecretTextType::EnvironmentVariable => {
|
|
*self = SecretText::EnvironmentVariable(Default::default())
|
|
}
|
|
SecretTextType::File => *self = SecretText::File(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SecretText::Text(inner) => inner.patch(pointer, value),
|
|
SecretText::EnvironmentVariable(inner) => inner.patch(pointer, value),
|
|
SecretText::File(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretText {
|
|
pub fn object_type(&self) -> SecretTextType {
|
|
match self {
|
|
SecretText::Text(_) => SecretTextType::Text,
|
|
SecretText::EnvironmentVariable(_) => SecretTextType::EnvironmentVariable,
|
|
SecretText::File(_) => SecretTextType::File,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretTextOptional {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SecretTextOptional::None => true,
|
|
SecretTextOptional::Text(inner) => inner.validate(errors),
|
|
SecretTextOptional::EnvironmentVariable(inner) => inner.validate(errors),
|
|
SecretTextOptional::File(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SecretTextOptional {
|
|
fn default() -> Self {
|
|
SecretTextOptional::None
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretTextOptional {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SecretTextOptional::None => {
|
|
0u16.pickle(out);
|
|
}
|
|
SecretTextOptional::Text(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretTextOptional::EnvironmentVariable(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SecretTextOptional::File(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(SecretTextOptional::None),
|
|
1 => Pickle::unpickle(stream).map(SecretTextOptional::Text),
|
|
2 => Pickle::unpickle(stream).map(SecretTextOptional::EnvironmentVariable),
|
|
3 => Pickle::unpickle(stream).map(SecretTextOptional::File),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretTextOptional {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SecretTextOptional::None => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("None".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
SecretTextOptional::Text(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Text".into()));
|
|
obj
|
|
}
|
|
SecretTextOptional::EnvironmentVariable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into()));
|
|
obj
|
|
}
|
|
SecretTextOptional::File(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("File".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SecretTextOptional {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SecretTextOptionalType::None => *self = SecretTextOptional::None,
|
|
SecretTextOptionalType::Text => {
|
|
*self = SecretTextOptional::Text(Default::default())
|
|
}
|
|
SecretTextOptionalType::EnvironmentVariable => {
|
|
*self = SecretTextOptional::EnvironmentVariable(Default::default())
|
|
}
|
|
SecretTextOptionalType::File => {
|
|
*self = SecretTextOptional::File(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
SecretTextOptional::None => pointer.assert_eof(),
|
|
SecretTextOptional::Text(inner) => inner.patch(pointer, value),
|
|
SecretTextOptional::EnvironmentVariable(inner) => inner.patch(pointer, value),
|
|
SecretTextOptional::File(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretTextOptional {
|
|
pub fn object_type(&self) -> SecretTextOptionalType {
|
|
match self {
|
|
SecretTextOptional::None => SecretTextOptionalType::None,
|
|
SecretTextOptional::Text(_) => SecretTextOptionalType::Text,
|
|
SecretTextOptional::EnvironmentVariable(_) => {
|
|
SecretTextOptionalType::EnvironmentVariable
|
|
}
|
|
SecretTextOptional::File(_) => SecretTextOptionalType::File,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SecretTextValue {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Secret));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SecretTextValue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.secret.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.secret = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SecretTextValue {
|
|
fn default() -> Self {
|
|
Self {
|
|
secret: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SecretTextValue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into()));
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SecretTextValue {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Secret) => self.secret.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Security {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Security;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.abuse_ban_rate {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.auth_ban_rate {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.loiter_ban_rate {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.scan_ban_paths;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ScanBanPaths));
|
|
}
|
|
}
|
|
if let Some(value) = &self.scan_ban_rate {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Security {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.abuse_ban_rate.pickle(out);
|
|
self.abuse_ban_period.pickle(out);
|
|
self.auth_ban_rate.pickle(out);
|
|
self.auth_ban_period.pickle(out);
|
|
self.loiter_ban_rate.pickle(out);
|
|
self.loiter_ban_period.pickle(out);
|
|
self.scan_ban_paths.pickle(out);
|
|
self.scan_ban_rate.pickle(out);
|
|
self.scan_ban_period.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.abuse_ban_rate = Pickle::unpickle(stream)?;
|
|
this.abuse_ban_period = Pickle::unpickle(stream)?;
|
|
this.auth_ban_rate = Pickle::unpickle(stream)?;
|
|
this.auth_ban_period = Pickle::unpickle(stream)?;
|
|
this.loiter_ban_rate = Pickle::unpickle(stream)?;
|
|
this.loiter_ban_period = Pickle::unpickle(stream)?;
|
|
this.scan_ban_paths = Pickle::unpickle(stream)?;
|
|
this.scan_ban_rate = Pickle::unpickle(stream)?;
|
|
this.scan_ban_period = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Security {
|
|
fn default() -> Self {
|
|
Self {
|
|
abuse_ban_rate: Some(Rate {
|
|
count: 35u64,
|
|
period: Duration::from_millis(86400000),
|
|
}),
|
|
abuse_ban_period: Default::default(),
|
|
auth_ban_rate: Some(Rate {
|
|
count: 100u64,
|
|
period: Duration::from_millis(86400000),
|
|
}),
|
|
auth_ban_period: Default::default(),
|
|
loiter_ban_rate: Some(Rate {
|
|
count: 150u64,
|
|
period: Duration::from_millis(86400000),
|
|
}),
|
|
loiter_ban_period: Default::default(),
|
|
scan_ban_paths: Map::new(vec![
|
|
"*.php*".to_string(),
|
|
"*.cgi*".to_string(),
|
|
"*.asp*".to_string(),
|
|
"*/wp-*".to_string(),
|
|
"*/php*".to_string(),
|
|
"*/cgi-bin*".to_string(),
|
|
"*xmlrpc*".to_string(),
|
|
"*../*".to_string(),
|
|
"*/..*".to_string(),
|
|
"*joomla*".to_string(),
|
|
"*wordpress*".to_string(),
|
|
"*drupal*".to_string(),
|
|
]),
|
|
scan_ban_rate: Some(Rate {
|
|
count: 30u64,
|
|
period: Duration::from_millis(86400000),
|
|
}),
|
|
scan_ban_period: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Security {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::AbuseBanRate, self.abuse_ban_rate.into_value());
|
|
map.insert_unchecked(Property::AbuseBanPeriod, self.abuse_ban_period.into_value());
|
|
map.insert_unchecked(Property::AuthBanRate, self.auth_ban_rate.into_value());
|
|
map.insert_unchecked(Property::AuthBanPeriod, self.auth_ban_period.into_value());
|
|
map.insert_unchecked(Property::LoiterBanRate, self.loiter_ban_rate.into_value());
|
|
map.insert_unchecked(
|
|
Property::LoiterBanPeriod,
|
|
self.loiter_ban_period.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ScanBanPaths, self.scan_ban_paths.into_value());
|
|
map.insert_unchecked(Property::ScanBanRate, self.scan_ban_rate.into_value());
|
|
map.insert_unchecked(Property::ScanBanPeriod, self.scan_ban_period.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Security {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AbuseBanRate) => self.abuse_ban_rate.patch(pointer, value),
|
|
Some(Property::AbuseBanPeriod) => self.abuse_ban_period.patch(pointer, value),
|
|
Some(Property::AuthBanRate) => self.auth_ban_rate.patch(pointer, value),
|
|
Some(Property::AuthBanPeriod) => self.auth_ban_period.patch(pointer, value),
|
|
Some(Property::LoiterBanRate) => self.loiter_ban_rate.patch(pointer, value),
|
|
Some(Property::LoiterBanPeriod) => self.loiter_ban_period.patch(pointer, value),
|
|
Some(Property::ScanBanPaths) => self
|
|
.scan_ban_paths
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ScanBanRate) => self.scan_ban_rate.patch(pointer, value),
|
|
Some(Property::ScanBanPeriod) => self.scan_ban_period.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SenderAuth {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SenderAuth;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.dkim_verify;
|
|
value.validate(errors);
|
|
let value = &self.spf_ehlo_verify;
|
|
value.validate(errors);
|
|
let value = &self.spf_from_verify;
|
|
value.validate(errors);
|
|
let value = &self.arc_verify;
|
|
value.validate(errors);
|
|
let value = &self.dmarc_verify;
|
|
value.validate(errors);
|
|
let value = &self.reverse_ip_verify;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl SenderAuth {
|
|
pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "is_local_domain(sender_domain) && !is_empty(authenticated_as)"
|
|
.to_string(),
|
|
then: "sender_domain".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::DkimSignDomain,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dkim_verify(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_verify,
|
|
default: Some(Expression {
|
|
else_: "relaxed".to_string(),
|
|
match_: List::from_iter([]),
|
|
}),
|
|
property: Property::DkimVerify,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: MTA_VERIFY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_spf_ehlo_verify(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.spf_ehlo_verify,
|
|
default: Some(Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::SpfEhloVerify,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: MTA_VERIFY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_spf_from_verify(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.spf_from_verify,
|
|
default: Some(Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::SpfFromVerify,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: MTA_VERIFY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_arc_verify(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.arc_verify,
|
|
default: Some(Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([]),
|
|
}),
|
|
property: Property::ArcVerify,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: MTA_VERIFY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dmarc_verify(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dmarc_verify,
|
|
default: Some(Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::DmarcVerify,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: MTA_VERIFY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_reverse_ip_verify(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.reverse_ip_verify,
|
|
default: Some(Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
}),
|
|
property: Property::ReverseIpVerify,
|
|
allowed_variables: MTA_CONNECTION_VARIABLE,
|
|
allowed_constants: MTA_VERIFY_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_dkim_sign_domain(),
|
|
self.ctx_dkim_verify(),
|
|
self.ctx_spf_ehlo_verify(),
|
|
self.ctx_spf_from_verify(),
|
|
self.ctx_arc_verify(),
|
|
self.ctx_dmarc_verify(),
|
|
self.ctx_reverse_ip_verify(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SenderAuth {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.dkim_sign_domain.pickle(out);
|
|
self.dkim_strict.pickle(out);
|
|
self.dkim_verify.pickle(out);
|
|
self.spf_ehlo_verify.pickle(out);
|
|
self.spf_from_verify.pickle(out);
|
|
self.arc_verify.pickle(out);
|
|
self.dmarc_verify.pickle(out);
|
|
self.reverse_ip_verify.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.dkim_strict = Pickle::unpickle(stream)?;
|
|
this.dkim_verify = Pickle::unpickle(stream)?;
|
|
this.spf_ehlo_verify = Pickle::unpickle(stream)?;
|
|
this.spf_from_verify = Pickle::unpickle(stream)?;
|
|
this.arc_verify = Pickle::unpickle(stream)?;
|
|
this.dmarc_verify = Pickle::unpickle(stream)?;
|
|
this.reverse_ip_verify = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SenderAuth {
|
|
fn default() -> Self {
|
|
Self {
|
|
dkim_sign_domain: Expression {
|
|
else_: "false".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "is_local_domain(sender_domain) && !is_empty(authenticated_as)"
|
|
.to_string(),
|
|
then: "sender_domain".to_string(),
|
|
}]),
|
|
},
|
|
dkim_strict: true,
|
|
dkim_verify: Expression {
|
|
else_: "relaxed".to_string(),
|
|
match_: List::from_iter([]),
|
|
},
|
|
spf_ehlo_verify: Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
},
|
|
spf_from_verify: Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
},
|
|
arc_verify: Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([]),
|
|
},
|
|
dmarc_verify: Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
},
|
|
reverse_ip_verify: Expression {
|
|
else_: "disable".to_string(),
|
|
match_: List::from_iter([ExpressionMatch {
|
|
if_: "local_port == 25".to_string(),
|
|
then: "relaxed".to_string(),
|
|
}]),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SenderAuth {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value());
|
|
map.insert_unchecked(Property::DkimStrict, self.dkim_strict.into_value());
|
|
map.insert_unchecked(Property::DkimVerify, self.dkim_verify.into_value());
|
|
map.insert_unchecked(Property::SpfEhloVerify, self.spf_ehlo_verify.into_value());
|
|
map.insert_unchecked(Property::SpfFromVerify, self.spf_from_verify.into_value());
|
|
map.insert_unchecked(Property::ArcVerify, self.arc_verify.into_value());
|
|
map.insert_unchecked(Property::DmarcVerify, self.dmarc_verify.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReverseIpVerify,
|
|
self.reverse_ip_verify.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SenderAuth {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value),
|
|
Some(Property::DkimStrict) => self.dkim_strict.patch(pointer, value),
|
|
Some(Property::DkimVerify) => self.dkim_verify.patch(pointer, value),
|
|
Some(Property::SpfEhloVerify) => self.spf_ehlo_verify.patch(pointer, value),
|
|
Some(Property::SpfFromVerify) => self.spf_from_verify.patch(pointer, value),
|
|
Some(Property::ArcVerify) => self.arc_verify.patch(pointer, value),
|
|
Some(Property::DmarcVerify) => self.dmarc_verify.patch(pointer, value),
|
|
Some(Property::ReverseIpVerify) => self.reverse_ip_verify.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ServerResponse {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.response_hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseHostname));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_code {
|
|
if *value < 100 {
|
|
errors.push(ValidationError::min_value(Property::ResponseCode, 100));
|
|
}
|
|
if *value > 599 {
|
|
errors.push(ValidationError::max_value(Property::ResponseCode, 599));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_enhanced {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseEnhanced));
|
|
}
|
|
}
|
|
if let Some(value) = &self.response_message {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ResponseMessage));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ServerResponse {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.response_hostname.pickle(out);
|
|
self.response_code.pickle(out);
|
|
self.response_enhanced.pickle(out);
|
|
self.response_message.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.response_hostname = Pickle::unpickle(stream)?;
|
|
this.response_code = Pickle::unpickle(stream)?;
|
|
this.response_enhanced = Pickle::unpickle(stream)?;
|
|
this.response_message = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ServerResponse {
|
|
fn default() -> Self {
|
|
Self {
|
|
response_hostname: Default::default(),
|
|
response_code: Default::default(),
|
|
response_enhanced: Default::default(),
|
|
response_message: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ServerResponse {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(
|
|
Property::ResponseHostname,
|
|
self.response_hostname.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ResponseCode, self.response_code.into_value());
|
|
map.insert_unchecked(
|
|
Property::ResponseEnhanced,
|
|
self.response_enhanced.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ResponseMessage,
|
|
self.response_message.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ServerResponse {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ResponseHostname) => self.response_hostname.patch(pointer, value),
|
|
Some(Property::ResponseCode) => self.response_code.patch(pointer, value),
|
|
Some(Property::ResponseEnhanced) => self.response_enhanced.patch(pointer, value),
|
|
Some(Property::ResponseMessage) => self.response_message.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Service {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Hostname));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for Service {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.hostname.pickle(out);
|
|
self.cleartext.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.hostname = Pickle::unpickle(stream)?;
|
|
this.cleartext = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Service {
|
|
fn default() -> Self {
|
|
Self {
|
|
hostname: Default::default(),
|
|
cleartext: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Service {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Hostname, self.hostname.into_value());
|
|
map.insert_unchecked(Property::Cleartext, self.cleartext.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Service {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Hostname) => self
|
|
.hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Hostname]), value),
|
|
Some(Property::Cleartext) => self.cleartext.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ShardedBlobStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.stores;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if value.len() < 2 {
|
|
errors.push(ValidationError::min_items(Property::Stores, 2));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ShardedBlobStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.stores.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.stores = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ShardedBlobStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
stores: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ShardedBlobStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Stores, self.stores.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ShardedBlobStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Stores) => self.stores.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ShardedInMemoryStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.stores;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if value.len() < 2 {
|
|
errors.push(ValidationError::min_items(Property::Stores, 2));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ShardedInMemoryStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.stores.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.stores = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ShardedInMemoryStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
stores: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ShardedInMemoryStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Stores, self.stores.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ShardedInMemoryStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Stores) => self.stores.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Sharing {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Sharing;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_shares;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxShares, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Sharing {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.allow_directory_queries.pickle(out);
|
|
self.max_shares.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.allow_directory_queries = Pickle::unpickle(stream)?;
|
|
this.max_shares = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Sharing {
|
|
fn default() -> Self {
|
|
Self {
|
|
allow_directory_queries: false,
|
|
max_shares: 10u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Sharing {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(
|
|
Property::AllowDirectoryQueries,
|
|
self.allow_directory_queries.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxShares, self.max_shares.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Sharing {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AllowDirectoryQueries) => {
|
|
self.allow_directory_queries.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxShares) => self.max_shares.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SieveSystemInterpreter {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SieveSystemInterpreter;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.default_from_address;
|
|
value.validate(errors);
|
|
let value = &self.default_from_name;
|
|
value.validate(errors);
|
|
if let Some(value) = &self.message_id_hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MessageIdHostname));
|
|
}
|
|
}
|
|
let value = &self.default_return_path;
|
|
value.validate(errors);
|
|
let value = &self.dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.max_cpu_cycles;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxCpuCycles, 1));
|
|
}
|
|
let value = &self.max_nested_includes;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxNestedIncludes, 1));
|
|
}
|
|
let value = &self.max_received_headers;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxReceivedHeaders, 1));
|
|
}
|
|
let value = &self.max_var_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxVarSize, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl SieveSystemInterpreter {
|
|
pub fn ctx_default_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.default_from_address,
|
|
default: Some(Expression {
|
|
else_: "'MAILER-DAEMON@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DefaultFromAddress,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_default_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.default_from_name,
|
|
default: Some(Expression {
|
|
else_: "'Automated Message'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DefaultFromName,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_default_return_path(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.default_return_path,
|
|
default: None,
|
|
property: Property::DefaultReturnPath,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DkimSignDomain,
|
|
allowed_variables: MTA_RCPT_TO_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_default_from_address(),
|
|
self.ctx_default_from_name(),
|
|
self.ctx_default_return_path(),
|
|
self.ctx_dkim_sign_domain(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SieveSystemInterpreter {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.default_from_address.pickle(out);
|
|
self.default_from_name.pickle(out);
|
|
self.message_id_hostname.pickle(out);
|
|
self.duplicate_expiry.pickle(out);
|
|
self.no_capability_check.pickle(out);
|
|
self.default_return_path.pickle(out);
|
|
self.dkim_sign_domain.pickle(out);
|
|
self.max_cpu_cycles.pickle(out);
|
|
self.max_nested_includes.pickle(out);
|
|
self.max_out_messages.pickle(out);
|
|
self.max_received_headers.pickle(out);
|
|
self.max_redirects.pickle(out);
|
|
self.max_var_size.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.default_from_address = Pickle::unpickle(stream)?;
|
|
this.default_from_name = Pickle::unpickle(stream)?;
|
|
this.message_id_hostname = Pickle::unpickle(stream)?;
|
|
this.duplicate_expiry = Pickle::unpickle(stream)?;
|
|
this.no_capability_check = Pickle::unpickle(stream)?;
|
|
this.default_return_path = Pickle::unpickle(stream)?;
|
|
this.dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.max_cpu_cycles = Pickle::unpickle(stream)?;
|
|
this.max_nested_includes = Pickle::unpickle(stream)?;
|
|
this.max_out_messages = Pickle::unpickle(stream)?;
|
|
this.max_received_headers = Pickle::unpickle(stream)?;
|
|
this.max_redirects = Pickle::unpickle(stream)?;
|
|
this.max_var_size = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SieveSystemInterpreter {
|
|
fn default() -> Self {
|
|
Self {
|
|
default_from_address: Expression {
|
|
else_: "'MAILER-DAEMON@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
default_from_name: Expression {
|
|
else_: "'Automated Message'".to_string(),
|
|
..Default::default()
|
|
},
|
|
message_id_hostname: Default::default(),
|
|
duplicate_expiry: Duration::from_millis(604800000),
|
|
no_capability_check: true,
|
|
default_return_path: Default::default(),
|
|
dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
max_cpu_cycles: 1048576u64,
|
|
max_nested_includes: 5u64,
|
|
max_out_messages: 5u64,
|
|
max_received_headers: 50u64,
|
|
max_redirects: 3u64,
|
|
max_var_size: 52428800u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SieveSystemInterpreter {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(
|
|
Property::DefaultFromAddress,
|
|
self.default_from_address.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultFromName,
|
|
self.default_from_name.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MessageIdHostname,
|
|
self.message_id_hostname.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DuplicateExpiry,
|
|
self.duplicate_expiry.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::NoCapabilityCheck,
|
|
self.no_capability_check.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultReturnPath,
|
|
self.default_return_path.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value());
|
|
map.insert_unchecked(Property::MaxCpuCycles, self.max_cpu_cycles.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxNestedIncludes,
|
|
self.max_nested_includes.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxOutMessages, self.max_out_messages.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxReceivedHeaders,
|
|
self.max_received_headers.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxRedirects, self.max_redirects.into_value());
|
|
map.insert_unchecked(Property::MaxVarSize, self.max_var_size.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SieveSystemInterpreter {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DefaultFromAddress) => self.default_from_address.patch(pointer, value),
|
|
Some(Property::DefaultFromName) => self.default_from_name.patch(pointer, value),
|
|
Some(Property::MessageIdHostname) => self
|
|
.message_id_hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::DuplicateExpiry) => self.duplicate_expiry.patch(pointer, value),
|
|
Some(Property::NoCapabilityCheck) => self.no_capability_check.patch(pointer, value),
|
|
Some(Property::DefaultReturnPath) => self.default_return_path.patch(pointer, value),
|
|
Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value),
|
|
Some(Property::MaxCpuCycles) => self.max_cpu_cycles.patch(pointer, value),
|
|
Some(Property::MaxNestedIncludes) => self.max_nested_includes.patch(pointer, value),
|
|
Some(Property::MaxOutMessages) => self.max_out_messages.patch(pointer, value),
|
|
Some(Property::MaxReceivedHeaders) => self.max_received_headers.patch(pointer, value),
|
|
Some(Property::MaxRedirects) => self.max_redirects.patch(pointer, value),
|
|
Some(Property::MaxVarSize) => self.max_var_size.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SieveSystemScript {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SieveSystemScript;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.contents;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Contents));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SieveSystemScript {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.is_active.pickle(out);
|
|
self.contents.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.is_active = Pickle::unpickle(stream)?;
|
|
this.contents = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SieveSystemScript {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
is_active: false,
|
|
contents: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SieveSystemScript {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::IsActive, self.is_active.into_value());
|
|
map.insert_unchecked(Property::Contents, self.contents.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SieveSystemScript {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self
|
|
.name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::IsActive) => self.is_active.patch(pointer, value),
|
|
Some(Property::Contents) => self
|
|
.contents
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SieveUserInterpreter {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SieveUserInterpreter;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.allowed_notify_uris;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AllowedNotifyUris));
|
|
}
|
|
}
|
|
let value = &self.protected_headers;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ProtectedHeaders));
|
|
}
|
|
}
|
|
let value = &self.default_subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultSubject));
|
|
}
|
|
let value = &self.default_subject_prefix;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultSubjectPrefix));
|
|
}
|
|
let value = &self.max_cpu_cycles;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxCpuCycles, 1));
|
|
}
|
|
let value = &self.max_header_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxHeaderSize, 1));
|
|
}
|
|
let value = &self.max_includes;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxIncludes, 1));
|
|
}
|
|
let value = &self.max_local_vars;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxLocalVars, 1));
|
|
}
|
|
let value = &self.max_match_vars;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxMatchVars, 1));
|
|
}
|
|
let value = &self.max_script_name_length;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxScriptNameLength, 1));
|
|
}
|
|
let value = &self.max_nested_blocks;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxNestedBlocks, 1));
|
|
}
|
|
let value = &self.max_nested_for_every;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxNestedForEvery, 1));
|
|
}
|
|
let value = &self.max_nested_includes;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxNestedIncludes, 1));
|
|
}
|
|
let value = &self.max_nested_tests;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxNestedTests, 1));
|
|
}
|
|
let value = &self.max_received_headers;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxReceivedHeaders, 1));
|
|
}
|
|
let value = &self.max_script_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxScriptSize, 1));
|
|
}
|
|
let value = &self.max_string_length;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxStringLength, 1));
|
|
}
|
|
let value = &self.max_var_name_length;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxVarNameLength, 1));
|
|
}
|
|
let value = &self.max_var_size;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxVarSize, 1));
|
|
}
|
|
if let Some(value) = &self.max_scripts {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxScripts, 1));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for SieveUserInterpreter {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.default_expiry_duplicate.pickle(out);
|
|
self.default_expiry_vacation.pickle(out);
|
|
self.disable_capabilities.pickle(out);
|
|
self.allowed_notify_uris.pickle(out);
|
|
self.protected_headers.pickle(out);
|
|
self.default_subject.pickle(out);
|
|
self.default_subject_prefix.pickle(out);
|
|
self.max_cpu_cycles.pickle(out);
|
|
self.max_header_size.pickle(out);
|
|
self.max_includes.pickle(out);
|
|
self.max_local_vars.pickle(out);
|
|
self.max_match_vars.pickle(out);
|
|
self.max_script_name_length.pickle(out);
|
|
self.max_nested_blocks.pickle(out);
|
|
self.max_nested_for_every.pickle(out);
|
|
self.max_nested_includes.pickle(out);
|
|
self.max_nested_tests.pickle(out);
|
|
self.max_out_messages.pickle(out);
|
|
self.max_received_headers.pickle(out);
|
|
self.max_redirects.pickle(out);
|
|
self.max_script_size.pickle(out);
|
|
self.max_string_length.pickle(out);
|
|
self.max_var_name_length.pickle(out);
|
|
self.max_var_size.pickle(out);
|
|
self.max_scripts.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.default_expiry_duplicate = Pickle::unpickle(stream)?;
|
|
this.default_expiry_vacation = Pickle::unpickle(stream)?;
|
|
this.disable_capabilities = Pickle::unpickle(stream)?;
|
|
this.allowed_notify_uris = Pickle::unpickle(stream)?;
|
|
this.protected_headers = Pickle::unpickle(stream)?;
|
|
this.default_subject = Pickle::unpickle(stream)?;
|
|
this.default_subject_prefix = Pickle::unpickle(stream)?;
|
|
this.max_cpu_cycles = Pickle::unpickle(stream)?;
|
|
this.max_header_size = Pickle::unpickle(stream)?;
|
|
this.max_includes = Pickle::unpickle(stream)?;
|
|
this.max_local_vars = Pickle::unpickle(stream)?;
|
|
this.max_match_vars = Pickle::unpickle(stream)?;
|
|
this.max_script_name_length = Pickle::unpickle(stream)?;
|
|
this.max_nested_blocks = Pickle::unpickle(stream)?;
|
|
this.max_nested_for_every = Pickle::unpickle(stream)?;
|
|
this.max_nested_includes = Pickle::unpickle(stream)?;
|
|
this.max_nested_tests = Pickle::unpickle(stream)?;
|
|
this.max_out_messages = Pickle::unpickle(stream)?;
|
|
this.max_received_headers = Pickle::unpickle(stream)?;
|
|
this.max_redirects = Pickle::unpickle(stream)?;
|
|
this.max_script_size = Pickle::unpickle(stream)?;
|
|
this.max_string_length = Pickle::unpickle(stream)?;
|
|
this.max_var_name_length = Pickle::unpickle(stream)?;
|
|
this.max_var_size = Pickle::unpickle(stream)?;
|
|
this.max_scripts = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SieveUserInterpreter {
|
|
fn default() -> Self {
|
|
Self {
|
|
default_expiry_duplicate: Duration::from_millis(604800000),
|
|
default_expiry_vacation: Duration::from_millis(2592000000),
|
|
disable_capabilities: Default::default(),
|
|
allowed_notify_uris: Map::new(vec!["mailto".to_string()]),
|
|
protected_headers: Map::new(vec![
|
|
"Original-Subject".to_string(),
|
|
"Original-From".to_string(),
|
|
"Received".to_string(),
|
|
"Auto-Submitted".to_string(),
|
|
]),
|
|
default_subject: "Automated reply".to_string(),
|
|
default_subject_prefix: "Auto: ".to_string(),
|
|
max_cpu_cycles: 5000u64,
|
|
max_header_size: 1024u64,
|
|
max_includes: 3u64,
|
|
max_local_vars: 128u64,
|
|
max_match_vars: 30u64,
|
|
max_script_name_length: 512u64,
|
|
max_nested_blocks: 15u64,
|
|
max_nested_for_every: 3u64,
|
|
max_nested_includes: 3u64,
|
|
max_nested_tests: 15u64,
|
|
max_out_messages: 3u64,
|
|
max_received_headers: 10u64,
|
|
max_redirects: 1u64,
|
|
max_script_size: 102400,
|
|
max_string_length: 4096u64,
|
|
max_var_name_length: 32u64,
|
|
max_var_size: 4096u64,
|
|
max_scripts: Some(100u64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SieveUserInterpreter {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(27);
|
|
map.insert_unchecked(
|
|
Property::DefaultExpiryDuplicate,
|
|
self.default_expiry_duplicate.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultExpiryVacation,
|
|
self.default_expiry_vacation.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DisableCapabilities,
|
|
self.disable_capabilities.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AllowedNotifyUris,
|
|
self.allowed_notify_uris.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ProtectedHeaders,
|
|
self.protected_headers.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DefaultSubject, self.default_subject.into_value());
|
|
map.insert_unchecked(
|
|
Property::DefaultSubjectPrefix,
|
|
self.default_subject_prefix.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxCpuCycles, self.max_cpu_cycles.into_value());
|
|
map.insert_unchecked(Property::MaxHeaderSize, self.max_header_size.into_value());
|
|
map.insert_unchecked(Property::MaxIncludes, self.max_includes.into_value());
|
|
map.insert_unchecked(Property::MaxLocalVars, self.max_local_vars.into_value());
|
|
map.insert_unchecked(Property::MaxMatchVars, self.max_match_vars.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxScriptNameLength,
|
|
self.max_script_name_length.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxNestedBlocks,
|
|
self.max_nested_blocks.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxNestedForEvery,
|
|
self.max_nested_for_every.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxNestedIncludes,
|
|
self.max_nested_includes.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxNestedTests, self.max_nested_tests.into_value());
|
|
map.insert_unchecked(Property::MaxOutMessages, self.max_out_messages.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxReceivedHeaders,
|
|
self.max_received_headers.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxRedirects, self.max_redirects.into_value());
|
|
map.insert_unchecked(Property::MaxScriptSize, self.max_script_size.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaxStringLength,
|
|
self.max_string_length.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::MaxVarNameLength,
|
|
self.max_var_name_length.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxVarSize, self.max_var_size.into_value());
|
|
map.insert_unchecked(Property::MaxScripts, self.max_scripts.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SieveUserInterpreter {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DefaultExpiryDuplicate) => {
|
|
self.default_expiry_duplicate.patch(pointer, value)
|
|
}
|
|
Some(Property::DefaultExpiryVacation) => {
|
|
self.default_expiry_vacation.patch(pointer, value)
|
|
}
|
|
Some(Property::DisableCapabilities) => self.disable_capabilities.patch(pointer, value),
|
|
Some(Property::AllowedNotifyUris) => self
|
|
.allowed_notify_uris
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ProtectedHeaders) => self
|
|
.protected_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::DefaultSubject) => self
|
|
.default_subject
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::DefaultSubjectPrefix) => {
|
|
self.default_subject_prefix.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxCpuCycles) => self.max_cpu_cycles.patch(pointer, value),
|
|
Some(Property::MaxHeaderSize) => self.max_header_size.patch(pointer, value),
|
|
Some(Property::MaxIncludes) => self.max_includes.patch(pointer, value),
|
|
Some(Property::MaxLocalVars) => self.max_local_vars.patch(pointer, value),
|
|
Some(Property::MaxMatchVars) => self.max_match_vars.patch(pointer, value),
|
|
Some(Property::MaxScriptNameLength) => {
|
|
self.max_script_name_length.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxNestedBlocks) => self.max_nested_blocks.patch(pointer, value),
|
|
Some(Property::MaxNestedForEvery) => self.max_nested_for_every.patch(pointer, value),
|
|
Some(Property::MaxNestedIncludes) => self.max_nested_includes.patch(pointer, value),
|
|
Some(Property::MaxNestedTests) => self.max_nested_tests.patch(pointer, value),
|
|
Some(Property::MaxOutMessages) => self.max_out_messages.patch(pointer, value),
|
|
Some(Property::MaxReceivedHeaders) => self.max_received_headers.patch(pointer, value),
|
|
Some(Property::MaxRedirects) => self.max_redirects.patch(pointer, value),
|
|
Some(Property::MaxScriptSize) => self.max_script_size.patch(pointer, value),
|
|
Some(Property::MaxStringLength) => self.max_string_length.patch(pointer, value),
|
|
Some(Property::MaxVarNameLength) => self.max_var_name_length.patch(pointer, value),
|
|
Some(Property::MaxVarSize) => self.max_var_size.patch(pointer, value),
|
|
Some(Property::MaxScripts) => self.max_scripts.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SieveUserScript {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SieveUserScript;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.contents;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Contents));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SieveUserScript {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.is_active.pickle(out);
|
|
self.contents.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.is_active = Pickle::unpickle(stream)?;
|
|
this.contents = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SieveUserScript {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
is_active: false,
|
|
contents: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SieveUserScript {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::IsActive, self.is_active.into_value());
|
|
map.insert_unchecked(Property::Contents, self.contents.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SieveUserScript {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self
|
|
.name
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::IsActive) => self.is_active.patch(pointer, value),
|
|
Some(Property::Contents) => self
|
|
.contents
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamClassifier {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamClassifier;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.model;
|
|
value.validate(errors);
|
|
let value = &self.learn_spam_from_rbl_hits;
|
|
if *value > 100 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::LearnSpamFromRblHits,
|
|
100,
|
|
));
|
|
}
|
|
let value = &self.min_ham_samples;
|
|
if *value > 10000 {
|
|
errors.push(ValidationError::max_value(Property::MinHamSamples, 10000));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MinHamSamples, 1));
|
|
}
|
|
let value = &self.min_spam_samples;
|
|
if *value > 10000 {
|
|
errors.push(ValidationError::max_value(Property::MinSpamSamples, 10000));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MinSpamSamples, 1));
|
|
}
|
|
let value = &self.reservoir_capacity;
|
|
if *value > 100000 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::ReservoirCapacity,
|
|
100000,
|
|
));
|
|
}
|
|
if *value < 100 {
|
|
errors.push(ValidationError::min_value(Property::ReservoirCapacity, 100));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for SpamClassifier {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.model.pickle(out);
|
|
self.learn_ham_from_card.pickle(out);
|
|
self.learn_spam_from_rbl_hits.pickle(out);
|
|
self.learn_spam_from_traps.pickle(out);
|
|
self.hold_samples_for.pickle(out);
|
|
self.min_ham_samples.pickle(out);
|
|
self.min_spam_samples.pickle(out);
|
|
self.reservoir_capacity.pickle(out);
|
|
self.train_frequency.pickle(out);
|
|
self.learn_ham_from_reply.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.model = Pickle::unpickle(stream)?;
|
|
this.learn_ham_from_card = Pickle::unpickle(stream)?;
|
|
this.learn_spam_from_rbl_hits = Pickle::unpickle(stream)?;
|
|
this.learn_spam_from_traps = Pickle::unpickle(stream)?;
|
|
this.hold_samples_for = Pickle::unpickle(stream)?;
|
|
this.min_ham_samples = Pickle::unpickle(stream)?;
|
|
this.min_spam_samples = Pickle::unpickle(stream)?;
|
|
this.reservoir_capacity = Pickle::unpickle(stream)?;
|
|
this.train_frequency = Pickle::unpickle(stream)?;
|
|
this.learn_ham_from_reply = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamClassifier {
|
|
fn default() -> Self {
|
|
Self {
|
|
model: Default::default(),
|
|
learn_ham_from_card: true,
|
|
learn_spam_from_rbl_hits: 2u64,
|
|
learn_spam_from_traps: true,
|
|
hold_samples_for: Duration::from_millis(15552000000),
|
|
min_ham_samples: 100u64,
|
|
min_spam_samples: 100u64,
|
|
reservoir_capacity: 1024u64,
|
|
train_frequency: Some(Duration::from_millis(43200000)),
|
|
learn_ham_from_reply: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamClassifier {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(12);
|
|
map.insert_unchecked(Property::Model, self.model.into_value());
|
|
map.insert_unchecked(
|
|
Property::LearnHamFromCard,
|
|
self.learn_ham_from_card.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::LearnSpamFromRblHits,
|
|
self.learn_spam_from_rbl_hits.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::LearnSpamFromTraps,
|
|
self.learn_spam_from_traps.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::HoldSamplesFor, self.hold_samples_for.into_value());
|
|
map.insert_unchecked(Property::MinHamSamples, self.min_ham_samples.into_value());
|
|
map.insert_unchecked(Property::MinSpamSamples, self.min_spam_samples.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReservoirCapacity,
|
|
self.reservoir_capacity.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::TrainFrequency, self.train_frequency.into_value());
|
|
map.insert_unchecked(
|
|
Property::LearnHamFromReply,
|
|
self.learn_ham_from_reply.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamClassifier {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Model) => self.model.patch(pointer, value),
|
|
Some(Property::LearnHamFromCard) => self.learn_ham_from_card.patch(pointer, value),
|
|
Some(Property::LearnSpamFromRblHits) => {
|
|
self.learn_spam_from_rbl_hits.patch(pointer, value)
|
|
}
|
|
Some(Property::LearnSpamFromTraps) => self.learn_spam_from_traps.patch(pointer, value),
|
|
Some(Property::HoldSamplesFor) => self.hold_samples_for.patch(pointer, value),
|
|
Some(Property::MinHamSamples) => self.min_ham_samples.patch(pointer, value),
|
|
Some(Property::MinSpamSamples) => self.min_spam_samples.patch(pointer, value),
|
|
Some(Property::ReservoirCapacity) => self.reservoir_capacity.patch(pointer, value),
|
|
Some(Property::TrainFrequency) => self.train_frequency.patch(pointer, value),
|
|
Some(Property::LearnHamFromReply) => self.learn_ham_from_reply.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamClassifierFtrlCcfh {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.indicator_parameters;
|
|
value.validate(errors);
|
|
let value = &self.parameters;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamClassifierFtrlCcfh {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.indicator_parameters.pickle(out);
|
|
self.parameters.pickle(out);
|
|
self.feature_l2_normalize.pickle(out);
|
|
self.feature_log_scale.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.indicator_parameters = Pickle::unpickle(stream)?;
|
|
this.parameters = Pickle::unpickle(stream)?;
|
|
this.feature_l2_normalize = Pickle::unpickle(stream)?;
|
|
this.feature_log_scale = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamClassifierFtrlCcfh {
|
|
fn default() -> Self {
|
|
Self {
|
|
indicator_parameters: FtrlParameters {
|
|
num_features: ModelSize::V18,
|
|
..Default::default()
|
|
},
|
|
parameters: FtrlParameters {
|
|
num_features: ModelSize::V20,
|
|
..Default::default()
|
|
},
|
|
feature_l2_normalize: true,
|
|
feature_log_scale: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamClassifierFtrlCcfh {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(
|
|
Property::IndicatorParameters,
|
|
self.indicator_parameters.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Parameters, self.parameters.into_value());
|
|
map.insert_unchecked(
|
|
Property::FeatureL2Normalize,
|
|
self.feature_l2_normalize.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FeatureLogScale,
|
|
self.feature_log_scale.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamClassifierFtrlCcfh {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::IndicatorParameters) => self.indicator_parameters.patch(pointer, value),
|
|
Some(Property::Parameters) => self.parameters.patch(pointer, value),
|
|
Some(Property::FeatureL2Normalize) => self.feature_l2_normalize.patch(pointer, value),
|
|
Some(Property::FeatureLogScale) => self.feature_log_scale.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamClassifierFtrlFh {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.parameters;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamClassifierFtrlFh {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.parameters.pickle(out);
|
|
self.feature_l2_normalize.pickle(out);
|
|
self.feature_log_scale.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.parameters = Pickle::unpickle(stream)?;
|
|
this.feature_l2_normalize = Pickle::unpickle(stream)?;
|
|
this.feature_log_scale = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamClassifierFtrlFh {
|
|
fn default() -> Self {
|
|
Self {
|
|
parameters: FtrlParameters {
|
|
num_features: ModelSize::V20,
|
|
..Default::default()
|
|
},
|
|
feature_l2_normalize: true,
|
|
feature_log_scale: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamClassifierFtrlFh {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Parameters, self.parameters.into_value());
|
|
map.insert_unchecked(
|
|
Property::FeatureL2Normalize,
|
|
self.feature_l2_normalize.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FeatureLogScale,
|
|
self.feature_log_scale.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamClassifierFtrlFh {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Parameters) => self.parameters.patch(pointer, value),
|
|
Some(Property::FeatureL2Normalize) => self.feature_l2_normalize.patch(pointer, value),
|
|
Some(Property::FeatureLogScale) => self.feature_log_scale.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamClassifierModel {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SpamClassifierModel::FtrlFh(inner) => inner.validate(errors),
|
|
SpamClassifierModel::FtrlCcfh(inner) => inner.validate(errors),
|
|
SpamClassifierModel::Disabled => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SpamClassifierModel {
|
|
fn default() -> Self {
|
|
SpamClassifierModel::FtrlFh(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamClassifierModel {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SpamClassifierModel::FtrlFh(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamClassifierModel::FtrlCcfh(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamClassifierModel::Disabled => {
|
|
2u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(SpamClassifierModel::FtrlFh),
|
|
1 => Pickle::unpickle(stream).map(SpamClassifierModel::FtrlCcfh),
|
|
2 => Some(SpamClassifierModel::Disabled),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamClassifierModel {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SpamClassifierModel::FtrlFh(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FtrlFh".into()));
|
|
obj
|
|
}
|
|
SpamClassifierModel::FtrlCcfh(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FtrlCcfh".into()));
|
|
obj
|
|
}
|
|
SpamClassifierModel::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SpamClassifierModel {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SpamClassifierModelType::FtrlFh => {
|
|
*self = SpamClassifierModel::FtrlFh(Default::default())
|
|
}
|
|
SpamClassifierModelType::FtrlCcfh => {
|
|
*self = SpamClassifierModel::FtrlCcfh(Default::default())
|
|
}
|
|
SpamClassifierModelType::Disabled => *self = SpamClassifierModel::Disabled,
|
|
}
|
|
}
|
|
match self {
|
|
SpamClassifierModel::FtrlFh(inner) => inner.patch(pointer, value),
|
|
SpamClassifierModel::FtrlCcfh(inner) => inner.patch(pointer, value),
|
|
SpamClassifierModel::Disabled => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamClassifierModel {
|
|
pub fn object_type(&self) -> SpamClassifierModelType {
|
|
match self {
|
|
SpamClassifierModel::FtrlFh(_) => SpamClassifierModelType::FtrlFh,
|
|
SpamClassifierModel::FtrlCcfh(_) => SpamClassifierModelType::FtrlCcfh,
|
|
SpamClassifierModel::Disabled => SpamClassifierModelType::Disabled,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamClassify {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.message;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Message));
|
|
}
|
|
let value = &self.remote_ip;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::RemoteIp, value));
|
|
}
|
|
let value = &self.ehlo_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EhloDomain));
|
|
}
|
|
if let Some(value) = &self.authenticated_as {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AuthenticatedAs));
|
|
}
|
|
}
|
|
let value = &self.env_from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EnvFrom));
|
|
}
|
|
let value = &self.env_rcpt_to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::EnvRcptTo));
|
|
}
|
|
}
|
|
let value = &self.tags;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamClassify {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.message.pickle(out);
|
|
self.remote_ip.pickle(out);
|
|
self.ehlo_domain.pickle(out);
|
|
self.authenticated_as.pickle(out);
|
|
self.is_tls.pickle(out);
|
|
self.env_from.pickle(out);
|
|
self.env_from_parameters.pickle(out);
|
|
self.env_rcpt_to.pickle(out);
|
|
self.score.pickle(out);
|
|
self.tags.pickle(out);
|
|
self.result.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.message = Pickle::unpickle(stream)?;
|
|
this.remote_ip = Pickle::unpickle(stream)?;
|
|
this.ehlo_domain = Pickle::unpickle(stream)?;
|
|
this.authenticated_as = Pickle::unpickle(stream)?;
|
|
this.is_tls = Pickle::unpickle(stream)?;
|
|
this.env_from = Pickle::unpickle(stream)?;
|
|
this.env_from_parameters = Pickle::unpickle(stream)?;
|
|
this.env_rcpt_to = Pickle::unpickle(stream)?;
|
|
this.score = Pickle::unpickle(stream)?;
|
|
this.tags = Pickle::unpickle(stream)?;
|
|
this.result = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamClassify {
|
|
fn default() -> Self {
|
|
Self {
|
|
message: Default::default(),
|
|
remote_ip: Default::default(),
|
|
ehlo_domain: Default::default(),
|
|
authenticated_as: Default::default(),
|
|
is_tls: true,
|
|
env_from: Default::default(),
|
|
env_from_parameters: Default::default(),
|
|
env_rcpt_to: Default::default(),
|
|
score: Float::new(0.0f64),
|
|
tags: Default::default(),
|
|
result: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamClassify {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::Message, self.message.into_value());
|
|
map.insert_unchecked(Property::RemoteIp, self.remote_ip.into_value());
|
|
map.insert_unchecked(Property::EhloDomain, self.ehlo_domain.into_value());
|
|
map.insert_unchecked(
|
|
Property::AuthenticatedAs,
|
|
self.authenticated_as.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::IsTls, self.is_tls.into_value());
|
|
map.insert_unchecked(Property::EnvFrom, self.env_from.into_value());
|
|
map.insert_unchecked(
|
|
Property::EnvFromParameters,
|
|
self.env_from_parameters.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::EnvRcptTo, self.env_rcpt_to.into_value());
|
|
map.insert_unchecked(Property::Score, self.score.into_value());
|
|
map.insert_unchecked(Property::Tags, self.tags.into_value());
|
|
map.insert_unchecked(Property::Result, self.result.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamClassify {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Message) => self.message.patch(pointer, value),
|
|
Some(Property::RemoteIp) => self.remote_ip.patch(pointer, value),
|
|
Some(Property::EhloDomain) => self.ehlo_domain.patch(pointer, value),
|
|
Some(Property::AuthenticatedAs) => self.authenticated_as.patch(pointer, value),
|
|
Some(Property::IsTls) => self.is_tls.patch(pointer, value),
|
|
Some(Property::EnvFrom) => self
|
|
.env_from
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::EnvFromParameters) => self.env_from_parameters.patch(pointer, value),
|
|
Some(Property::EnvRcptTo) => self
|
|
.env_rcpt_to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Score) => pointer.assert_server_set(),
|
|
Some(Property::Tags) => pointer.assert_server_set(),
|
|
Some(Property::Result) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamClassifyTag {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamClassifyTag {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.score.pickle(out);
|
|
self.disposition.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.score = Pickle::unpickle(stream)?;
|
|
this.disposition = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamClassifyTag {
|
|
fn default() -> Self {
|
|
Self {
|
|
score: Float::new(0.0f64),
|
|
disposition: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamClassifyTag {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Score, self.score.into_value());
|
|
map.insert_unchecked(Property::Disposition, self.disposition.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamClassifyTag {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Score) => pointer.assert_server_set(),
|
|
Some(Property::Disposition) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamDnsblServer {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamDnsblServer;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SpamDnsblServer::Any(inner) => inner.validate(errors),
|
|
SpamDnsblServer::Url(inner) => inner.validate(errors),
|
|
SpamDnsblServer::Domain(inner) => inner.validate(errors),
|
|
SpamDnsblServer::Email(inner) => inner.validate(errors),
|
|
SpamDnsblServer::Ip(inner) => inner.validate(errors),
|
|
SpamDnsblServer::Header(inner) => inner.validate(errors),
|
|
SpamDnsblServer::Body(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
SpamDnsblServer::Any(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamDnsblServer::Url(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamDnsblServer::Domain(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamDnsblServer::Email(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamDnsblServer::Ip(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamDnsblServer::Header(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamDnsblServer::Body(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServer {
|
|
fn default() -> Self {
|
|
SpamDnsblServer::Any(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServer {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SpamDnsblServer::Any(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamDnsblServer::Url(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamDnsblServer::Domain(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamDnsblServer::Email(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamDnsblServer::Ip(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamDnsblServer::Header(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamDnsblServer::Body(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(SpamDnsblServer::Any),
|
|
1 => Pickle::unpickle(stream).map(SpamDnsblServer::Url),
|
|
2 => Pickle::unpickle(stream).map(SpamDnsblServer::Domain),
|
|
3 => Pickle::unpickle(stream).map(SpamDnsblServer::Email),
|
|
4 => Pickle::unpickle(stream).map(SpamDnsblServer::Ip),
|
|
5 => Pickle::unpickle(stream).map(SpamDnsblServer::Header),
|
|
6 => Pickle::unpickle(stream).map(SpamDnsblServer::Body),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServer {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SpamDnsblServer::Any(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Any".into()));
|
|
obj
|
|
}
|
|
SpamDnsblServer::Url(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Url".into()));
|
|
obj
|
|
}
|
|
SpamDnsblServer::Domain(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Domain".into()));
|
|
obj
|
|
}
|
|
SpamDnsblServer::Email(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Email".into()));
|
|
obj
|
|
}
|
|
SpamDnsblServer::Ip(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ip".into()));
|
|
obj
|
|
}
|
|
SpamDnsblServer::Header(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Header".into()));
|
|
obj
|
|
}
|
|
SpamDnsblServer::Body(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Body".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SpamDnsblServer {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SpamDnsblServerType::Any => *self = SpamDnsblServer::Any(Default::default()),
|
|
SpamDnsblServerType::Url => *self = SpamDnsblServer::Url(Default::default()),
|
|
SpamDnsblServerType::Domain => *self = SpamDnsblServer::Domain(Default::default()),
|
|
SpamDnsblServerType::Email => *self = SpamDnsblServer::Email(Default::default()),
|
|
SpamDnsblServerType::Ip => *self = SpamDnsblServer::Ip(Default::default()),
|
|
SpamDnsblServerType::Header => *self = SpamDnsblServer::Header(Default::default()),
|
|
SpamDnsblServerType::Body => *self = SpamDnsblServer::Body(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SpamDnsblServer::Any(inner) => inner.patch(pointer, value),
|
|
SpamDnsblServer::Url(inner) => inner.patch(pointer, value),
|
|
SpamDnsblServer::Domain(inner) => inner.patch(pointer, value),
|
|
SpamDnsblServer::Email(inner) => inner.patch(pointer, value),
|
|
SpamDnsblServer::Ip(inner) => inner.patch(pointer, value),
|
|
SpamDnsblServer::Header(inner) => inner.patch(pointer, value),
|
|
SpamDnsblServer::Body(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServer {
|
|
pub fn object_type(&self) -> SpamDnsblServerType {
|
|
match self {
|
|
SpamDnsblServer::Any(_) => SpamDnsblServerType::Any,
|
|
SpamDnsblServer::Url(_) => SpamDnsblServerType::Url,
|
|
SpamDnsblServer::Domain(_) => SpamDnsblServerType::Domain,
|
|
SpamDnsblServer::Email(_) => SpamDnsblServerType::Email,
|
|
SpamDnsblServer::Ip(_) => SpamDnsblServerType::Ip,
|
|
SpamDnsblServer::Header(_) => SpamDnsblServerType::Header,
|
|
SpamDnsblServer::Body(_) => SpamDnsblServerType::Body,
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
match self {
|
|
SpamDnsblServer::Any(obj) => obj.expression_ctxs(),
|
|
SpamDnsblServer::Url(obj) => obj.expression_ctxs(),
|
|
SpamDnsblServer::Domain(obj) => obj.expression_ctxs(),
|
|
SpamDnsblServer::Email(obj) => obj.expression_ctxs(),
|
|
SpamDnsblServer::Ip(obj) => obj.expression_ctxs(),
|
|
SpamDnsblServer::Header(obj) => obj.expression_ctxs(),
|
|
SpamDnsblServer::Body(obj) => obj.expression_ctxs(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerAny {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerAny {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_GENERIC_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerAny {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerAny {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerAny {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerAny {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerBody {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerBody {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_GENERIC_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerBody {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerBody {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerBody {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerBody {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerDomain {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerDomain {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_GENERIC_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerDomain {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerDomain {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerDomain {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerDomain {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerEmail {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerEmail {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_EMAIL_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerEmail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerEmail {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerEmail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerEmail {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerHeader {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerHeader {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_HEADER_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerHeader {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerHeader {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerHeader {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerHeader {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerIp {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerIp {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerIp {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerIp {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerIp {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerIp {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerUrl {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
value.validate(errors);
|
|
let value = &self.zone;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamDnsblServerUrl {
|
|
pub fn ctx_tag(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.tag,
|
|
default: None,
|
|
property: Property::Tag,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_zone(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.zone,
|
|
default: None,
|
|
property: Property::Zone,
|
|
allowed_variables: SPAM_URL_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_tag(), self.ctx_zone()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblServerUrl {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.zone.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.zone = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblServerUrl {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
zone: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblServerUrl {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Zone, self.zone.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblServerUrl {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(pointer, value),
|
|
Some(Property::Zone) => self.zone.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamDnsblSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamDnsblSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.domain_limit;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::DomainLimit, 1));
|
|
}
|
|
let value = &self.email_limit;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::EmailLimit, 1));
|
|
}
|
|
let value = &self.ip_limit;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::IpLimit, 1));
|
|
}
|
|
let value = &self.url_limit;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::UrlLimit, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for SpamDnsblSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.domain_limit.pickle(out);
|
|
self.email_limit.pickle(out);
|
|
self.ip_limit.pickle(out);
|
|
self.url_limit.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.domain_limit = Pickle::unpickle(stream)?;
|
|
this.email_limit = Pickle::unpickle(stream)?;
|
|
this.ip_limit = Pickle::unpickle(stream)?;
|
|
this.url_limit = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamDnsblSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
domain_limit: 50u64,
|
|
email_limit: 50u64,
|
|
ip_limit: 50u64,
|
|
url_limit: 50u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamDnsblSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::DomainLimit, self.domain_limit.into_value());
|
|
map.insert_unchecked(Property::EmailLimit, self.email_limit.into_value());
|
|
map.insert_unchecked(Property::IpLimit, self.ip_limit.into_value());
|
|
map.insert_unchecked(Property::UrlLimit, self.url_limit.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamDnsblSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DomainLimit) => self.domain_limit.patch(pointer, value),
|
|
Some(Property::EmailLimit) => self.email_limit.patch(pointer, value),
|
|
Some(Property::IpLimit) => self.ip_limit.patch(pointer, value),
|
|
Some(Property::UrlLimit) => self.url_limit.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamFileExtension {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamFileExtension;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.extension;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Extension));
|
|
}
|
|
let value = &self.content_types;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ContentTypes));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Extension, &self.extension);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamFileExtension {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.extension.pickle(out);
|
|
self.is_archive.pickle(out);
|
|
self.is_bad.pickle(out);
|
|
self.is_nz.pickle(out);
|
|
self.content_types.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.extension = Pickle::unpickle(stream)?;
|
|
this.is_archive = Pickle::unpickle(stream)?;
|
|
this.is_bad = Pickle::unpickle(stream)?;
|
|
this.is_nz = Pickle::unpickle(stream)?;
|
|
this.content_types = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamFileExtension {
|
|
fn default() -> Self {
|
|
Self {
|
|
extension: Default::default(),
|
|
is_archive: false,
|
|
is_bad: false,
|
|
is_nz: false,
|
|
content_types: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamFileExtension {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Extension, self.extension.into_value());
|
|
map.insert_unchecked(Property::IsArchive, self.is_archive.into_value());
|
|
map.insert_unchecked(Property::IsBad, self.is_bad.into_value());
|
|
map.insert_unchecked(Property::IsNz, self.is_nz.into_value());
|
|
map.insert_unchecked(Property::ContentTypes, self.content_types.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamFileExtension {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Extension) => self.extension.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Lowercase]),
|
|
value,
|
|
),
|
|
Some(Property::IsArchive) => self.is_archive.patch(pointer, value),
|
|
Some(Property::IsBad) => self.is_bad.patch(pointer, value),
|
|
Some(Property::IsNz) => self.is_nz.patch(pointer, value),
|
|
Some(Property::ContentTypes) => self
|
|
.content_types
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamLlm {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamLlm;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SpamLlm::Disable => true,
|
|
SpamLlm::Enable(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
SpamLlm::Disable => {}
|
|
SpamLlm::Enable(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SpamLlm {
|
|
fn default() -> Self {
|
|
SpamLlm::Disable
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamLlm {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SpamLlm::Disable => {
|
|
0u16.pickle(out);
|
|
}
|
|
SpamLlm::Enable(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(SpamLlm::Disable),
|
|
1 => Pickle::unpickle(stream).map(SpamLlm::Enable),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamLlm {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SpamLlm::Disable => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disable".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
SpamLlm::Enable(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Enable".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SpamLlm {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SpamLlmType::Disable => *self = SpamLlm::Disable,
|
|
SpamLlmType::Enable => *self = SpamLlm::Enable(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SpamLlm::Disable => pointer.assert_eof(),
|
|
SpamLlm::Enable(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamLlm {
|
|
pub fn object_type(&self) -> SpamLlmType {
|
|
match self {
|
|
SpamLlm::Disable => SpamLlmType::Disable,
|
|
SpamLlm::Enable(_) => SpamLlmType::Enable,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamLlmProperties {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.categories;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Categories));
|
|
}
|
|
}
|
|
if value.len() < 2 {
|
|
errors.push(ValidationError::min_items(Property::Categories, 2));
|
|
}
|
|
let value = &self.confidence;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Confidence));
|
|
}
|
|
}
|
|
let value = &self.model_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::ModelId));
|
|
}
|
|
let value = &self.prompt;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Prompt));
|
|
}
|
|
let value = &self.separator;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Separator));
|
|
}
|
|
let value = &self.temperature;
|
|
if *value > Float::new(1.0) {
|
|
errors.push(ValidationError::max_value(Property::Temperature, 1));
|
|
}
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::Temperature, 0));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::AiModel, self.model_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamLlmProperties {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.categories.pickle(out);
|
|
self.confidence.pickle(out);
|
|
self.response_pos_category.pickle(out);
|
|
self.response_pos_confidence.pickle(out);
|
|
self.response_pos_explanation.pickle(out);
|
|
self.model_id.pickle(out);
|
|
self.prompt.pickle(out);
|
|
self.separator.pickle(out);
|
|
self.temperature.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.categories = Pickle::unpickle(stream)?;
|
|
this.confidence = Pickle::unpickle(stream)?;
|
|
this.response_pos_category = Pickle::unpickle(stream)?;
|
|
this.response_pos_confidence = Pickle::unpickle(stream)?;
|
|
this.response_pos_explanation = Pickle::unpickle(stream)?;
|
|
this.model_id = Pickle::unpickle(stream)?;
|
|
this.prompt = Pickle::unpickle(stream)?;
|
|
this.separator = Pickle::unpickle(stream)?;
|
|
this.temperature = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamLlmProperties {
|
|
fn default() -> Self {
|
|
Self {
|
|
categories: Map::new(vec![
|
|
"Unsolicited".to_string(),
|
|
"Commercial".to_string(),
|
|
"Harmful".to_string(),
|
|
"Legitimate".to_string(),
|
|
]),
|
|
confidence: Map::new(vec![
|
|
"High".to_string(),
|
|
"Medium".to_string(),
|
|
"Low".to_string(),
|
|
]),
|
|
response_pos_category: 0u64,
|
|
response_pos_confidence: Some(1u64),
|
|
response_pos_explanation: Some(2u64),
|
|
model_id: Default::default(),
|
|
prompt: Default::default(),
|
|
separator: ",".to_string(),
|
|
temperature: Float::new(0.5f64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamLlmProperties {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::Categories, self.categories.into_value());
|
|
map.insert_unchecked(Property::Confidence, self.confidence.into_value());
|
|
map.insert_unchecked(
|
|
Property::ResponsePosCategory,
|
|
self.response_pos_category.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ResponsePosConfidence,
|
|
self.response_pos_confidence.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ResponsePosExplanation,
|
|
self.response_pos_explanation.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ModelId, self.model_id.into_value());
|
|
map.insert_unchecked(Property::Prompt, self.prompt.into_value());
|
|
map.insert_unchecked(Property::Separator, self.separator.into_value());
|
|
map.insert_unchecked(Property::Temperature, self.temperature.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamLlmProperties {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Categories) => self.categories.patch(pointer, value),
|
|
Some(Property::Confidence) => self.confidence.patch(pointer, value),
|
|
Some(Property::ResponsePosCategory) => self.response_pos_category.patch(pointer, value),
|
|
Some(Property::ResponsePosConfidence) => {
|
|
self.response_pos_confidence.patch(pointer, value)
|
|
}
|
|
Some(Property::ResponsePosExplanation) => {
|
|
self.response_pos_explanation.patch(pointer, value)
|
|
}
|
|
Some(Property::ModelId) => self.model_id.patch(pointer, value),
|
|
Some(Property::Prompt) => self.prompt.patch(pointer, value),
|
|
Some(Property::Separator) => self
|
|
.separator
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Temperature) => self.temperature.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamPyzor {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamPyzor;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.block_count;
|
|
if *value > 1000 {
|
|
errors.push(ValidationError::max_value(Property::BlockCount, 1000));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::BlockCount, 1));
|
|
}
|
|
let value = &self.host;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Host));
|
|
}
|
|
let value = &self.port;
|
|
if *value > 65535 {
|
|
errors.push(ValidationError::max_value(Property::Port, 65535));
|
|
}
|
|
if *value < 100 {
|
|
errors.push(ValidationError::min_value(Property::Port, 100));
|
|
}
|
|
let value = &self.ratio;
|
|
if *value > Float::new(1.0) {
|
|
errors.push(ValidationError::max_value(Property::Ratio, 1));
|
|
}
|
|
if *value < Float::new(0.0) {
|
|
errors.push(ValidationError::min_value(Property::Ratio, 0));
|
|
}
|
|
let value = &self.allow_count;
|
|
if *value > 1000 {
|
|
errors.push(ValidationError::max_value(Property::AllowCount, 1000));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::AllowCount, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for SpamPyzor {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.block_count.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.host.pickle(out);
|
|
self.port.pickle(out);
|
|
self.ratio.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.allow_count.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.block_count = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.host = Pickle::unpickle(stream)?;
|
|
this.port = Pickle::unpickle(stream)?;
|
|
this.ratio = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.allow_count = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamPyzor {
|
|
fn default() -> Self {
|
|
Self {
|
|
block_count: 5u64,
|
|
enable: true,
|
|
host: "public.pyzor.org".to_string(),
|
|
port: 24441u64,
|
|
ratio: Float::new(0.2f64),
|
|
timeout: Duration::from_millis(5000),
|
|
allow_count: 10u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamPyzor {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::BlockCount, self.block_count.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Host, self.host.into_value());
|
|
map.insert_unchecked(Property::Port, self.port.into_value());
|
|
map.insert_unchecked(Property::Ratio, self.ratio.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::AllowCount, self.allow_count.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamPyzor {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::BlockCount) => self.block_count.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Host) => self
|
|
.host
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Port) => self.port.patch(pointer, value),
|
|
Some(Property::Ratio) => self.ratio.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::AllowCount) => self.allow_count.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamRule {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamRule;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SpamRule::Any(inner) => inner.validate(errors),
|
|
SpamRule::Url(inner) => inner.validate(errors),
|
|
SpamRule::Domain(inner) => inner.validate(errors),
|
|
SpamRule::Email(inner) => inner.validate(errors),
|
|
SpamRule::Ip(inner) => inner.validate(errors),
|
|
SpamRule::Header(inner) => inner.validate(errors),
|
|
SpamRule::Body(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
SpamRule::Any(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamRule::Url(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamRule::Domain(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamRule::Email(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamRule::Ip(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamRule::Header(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamRule::Body(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRule {
|
|
fn default() -> Self {
|
|
SpamRule::Any(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRule {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SpamRule::Any(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamRule::Url(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamRule::Domain(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamRule::Email(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamRule::Ip(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamRule::Header(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamRule::Body(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(SpamRule::Any),
|
|
1 => Pickle::unpickle(stream).map(SpamRule::Url),
|
|
2 => Pickle::unpickle(stream).map(SpamRule::Domain),
|
|
3 => Pickle::unpickle(stream).map(SpamRule::Email),
|
|
4 => Pickle::unpickle(stream).map(SpamRule::Ip),
|
|
5 => Pickle::unpickle(stream).map(SpamRule::Header),
|
|
6 => Pickle::unpickle(stream).map(SpamRule::Body),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRule {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SpamRule::Any(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Any".into()));
|
|
obj
|
|
}
|
|
SpamRule::Url(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Url".into()));
|
|
obj
|
|
}
|
|
SpamRule::Domain(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Domain".into()));
|
|
obj
|
|
}
|
|
SpamRule::Email(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Email".into()));
|
|
obj
|
|
}
|
|
SpamRule::Ip(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Ip".into()));
|
|
obj
|
|
}
|
|
SpamRule::Header(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Header".into()));
|
|
obj
|
|
}
|
|
SpamRule::Body(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Body".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SpamRule {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SpamRuleType::Any => *self = SpamRule::Any(Default::default()),
|
|
SpamRuleType::Url => *self = SpamRule::Url(Default::default()),
|
|
SpamRuleType::Domain => *self = SpamRule::Domain(Default::default()),
|
|
SpamRuleType::Email => *self = SpamRule::Email(Default::default()),
|
|
SpamRuleType::Ip => *self = SpamRule::Ip(Default::default()),
|
|
SpamRuleType::Header => *self = SpamRule::Header(Default::default()),
|
|
SpamRuleType::Body => *self = SpamRule::Body(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SpamRule::Any(inner) => inner.patch(pointer, value),
|
|
SpamRule::Url(inner) => inner.patch(pointer, value),
|
|
SpamRule::Domain(inner) => inner.patch(pointer, value),
|
|
SpamRule::Email(inner) => inner.patch(pointer, value),
|
|
SpamRule::Ip(inner) => inner.patch(pointer, value),
|
|
SpamRule::Header(inner) => inner.patch(pointer, value),
|
|
SpamRule::Body(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRule {
|
|
pub fn object_type(&self) -> SpamRuleType {
|
|
match self {
|
|
SpamRule::Any(_) => SpamRuleType::Any,
|
|
SpamRule::Url(_) => SpamRuleType::Url,
|
|
SpamRule::Domain(_) => SpamRuleType::Domain,
|
|
SpamRule::Email(_) => SpamRuleType::Email,
|
|
SpamRule::Ip(_) => SpamRuleType::Ip,
|
|
SpamRule::Header(_) => SpamRuleType::Header,
|
|
SpamRule::Body(_) => SpamRuleType::Body,
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
match self {
|
|
SpamRule::Any(obj) => obj.expression_ctxs(),
|
|
SpamRule::Url(obj) => obj.expression_ctxs(),
|
|
SpamRule::Domain(obj) => obj.expression_ctxs(),
|
|
SpamRule::Email(obj) => obj.expression_ctxs(),
|
|
SpamRule::Ip(obj) => obj.expression_ctxs(),
|
|
SpamRule::Header(obj) => obj.expression_ctxs(),
|
|
SpamRule::Body(obj) => obj.expression_ctxs(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleAny {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleAny {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_GENERIC_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleAny {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleAny {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleAny {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleAny {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleBody {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleBody {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_GENERIC_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleBody {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleBody {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleBody {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleBody {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleDomain {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleDomain {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_GENERIC_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleDomain {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleDomain {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleDomain {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleDomain {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleEmail {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleEmail {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_EMAIL_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleEmail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleEmail {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleEmail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleEmail {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleHeader {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleHeader {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_HEADER_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleHeader {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleHeader {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleHeader {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleHeader {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleIp {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleIp {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_IP_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleIp {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleIp {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleIp {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleIp {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamRuleUrl {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.condition;
|
|
value.validate(errors);
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.priority;
|
|
if *value > (99999) {
|
|
errors.push(ValidationError::max_value(Property::Priority, 99999));
|
|
}
|
|
if *value < (-99999) {
|
|
errors.push(ValidationError::min_value(Property::Priority, -99999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Name, &self.name);
|
|
}
|
|
}
|
|
|
|
impl SpamRuleUrl {
|
|
pub fn ctx_condition(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.condition,
|
|
default: None,
|
|
property: Property::Condition,
|
|
allowed_variables: SPAM_URL_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_condition()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamRuleUrl {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.condition.pickle(out);
|
|
self.name.pickle(out);
|
|
self.description.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.priority.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.condition = Pickle::unpickle(stream)?;
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.priority = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamRuleUrl {
|
|
fn default() -> Self {
|
|
Self {
|
|
condition: Default::default(),
|
|
name: Default::default(),
|
|
description: Default::default(),
|
|
enable: true,
|
|
priority: 500i64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamRuleUrl {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Condition, self.condition.into_value());
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Priority, self.priority.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamRuleUrl {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Condition) => self.condition.patch(pointer, value),
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]),
|
|
value,
|
|
),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Priority) => self.priority.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.score_discard;
|
|
if *value > Float::new(100.0) {
|
|
errors.push(ValidationError::max_value(Property::ScoreDiscard, 100));
|
|
}
|
|
if *value < Float::new(-100.0) {
|
|
errors.push(ValidationError::min_value(Property::ScoreDiscard, -100));
|
|
}
|
|
let value = &self.score_reject;
|
|
if *value > Float::new(100.0) {
|
|
errors.push(ValidationError::max_value(Property::ScoreReject, 100));
|
|
}
|
|
if *value < Float::new(-100.0) {
|
|
errors.push(ValidationError::min_value(Property::ScoreReject, -100));
|
|
}
|
|
let value = &self.score_spam;
|
|
if *value > Float::new(100.0) {
|
|
errors.push(ValidationError::max_value(Property::ScoreSpam, 100));
|
|
}
|
|
if *value < Float::new(-100.0) {
|
|
errors.push(ValidationError::min_value(Property::ScoreSpam, -100));
|
|
}
|
|
if let Some(value) = &self.spam_filter_rules_url {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::SpamFilterRulesUrl));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for SpamSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.trust_contacts.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.greylist_for.pickle(out);
|
|
self.score_discard.pickle(out);
|
|
self.score_reject.pickle(out);
|
|
self.score_spam.pickle(out);
|
|
self.trust_replies.pickle(out);
|
|
self.spam_filter_rules_url.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.trust_contacts = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.greylist_for = Pickle::unpickle(stream)?;
|
|
this.score_discard = Pickle::unpickle(stream)?;
|
|
this.score_reject = Pickle::unpickle(stream)?;
|
|
this.score_spam = Pickle::unpickle(stream)?;
|
|
this.trust_replies = Pickle::unpickle(stream)?;
|
|
this.spam_filter_rules_url = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
trust_contacts: true,
|
|
enable: true,
|
|
greylist_for: Default::default(),
|
|
score_discard: Float::new(0.0f64),
|
|
score_reject: Float::new(0.0f64),
|
|
score_spam: Float::new(5.0f64),
|
|
trust_replies: true,
|
|
spam_filter_rules_url: Some("https://github.com/stalwartlabs/spam-filter/releases/latest/download/spam-filter-rules.json.gz".to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::TrustContacts, self.trust_contacts.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::GreylistFor, self.greylist_for.into_value());
|
|
map.insert_unchecked(Property::ScoreDiscard, self.score_discard.into_value());
|
|
map.insert_unchecked(Property::ScoreReject, self.score_reject.into_value());
|
|
map.insert_unchecked(Property::ScoreSpam, self.score_spam.into_value());
|
|
map.insert_unchecked(Property::TrustReplies, self.trust_replies.into_value());
|
|
map.insert_unchecked(
|
|
Property::SpamFilterRulesUrl,
|
|
self.spam_filter_rules_url.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::TrustContacts) => self.trust_contacts.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::GreylistFor) => self.greylist_for.patch(pointer, value),
|
|
Some(Property::ScoreDiscard) => self.score_discard.patch(pointer, value),
|
|
Some(Property::ScoreReject) => self.score_reject.patch(pointer, value),
|
|
Some(Property::ScoreSpam) => self.score_spam.patch(pointer, value),
|
|
Some(Property::TrustReplies) => self.trust_replies.patch(pointer, value),
|
|
Some(Property::SpamFilterRulesUrl) => self
|
|
.spam_filter_rules_url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamTag {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamTag;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SpamTag::Score(inner) => inner.validate(errors),
|
|
SpamTag::Discard(inner) => inner.validate(errors),
|
|
SpamTag::Reject(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
SpamTag::Score(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamTag::Discard(object) => {
|
|
object.index(i);
|
|
}
|
|
SpamTag::Reject(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SpamTag {
|
|
fn default() -> Self {
|
|
SpamTag::Score(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamTag {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SpamTag::Score(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamTag::Discard(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SpamTag::Reject(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(SpamTag::Score),
|
|
1 => Pickle::unpickle(stream).map(SpamTag::Discard),
|
|
2 => Pickle::unpickle(stream).map(SpamTag::Reject),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamTag {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SpamTag::Score(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Score".into()));
|
|
obj
|
|
}
|
|
SpamTag::Discard(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Discard".into()));
|
|
obj
|
|
}
|
|
SpamTag::Reject(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Reject".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SpamTag {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SpamTagType::Score => *self = SpamTag::Score(Default::default()),
|
|
SpamTagType::Discard => *self = SpamTag::Discard(Default::default()),
|
|
SpamTagType::Reject => *self = SpamTag::Reject(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SpamTag::Score(inner) => inner.patch(pointer, value),
|
|
SpamTag::Discard(inner) => inner.patch(pointer, value),
|
|
SpamTag::Reject(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamTag {
|
|
pub fn object_type(&self) -> SpamTagType {
|
|
match self {
|
|
SpamTag::Score(_) => SpamTagType::Score,
|
|
SpamTag::Discard(_) => SpamTagType::Discard,
|
|
SpamTag::Reject(_) => SpamTagType::Reject,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamTagAction {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Tag));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Tag, &self.tag);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamTagAction {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamTagAction {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamTagAction {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamTagAction {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(
|
|
pointer
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpamTagScore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tag;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Tag));
|
|
}
|
|
let value = &self.score;
|
|
if *value < Float::new(-999999.0) {
|
|
errors.push(ValidationError::min_value(Property::Score, -999999));
|
|
}
|
|
if *value > Float::new(999999.0) {
|
|
errors.push(ValidationError::max_value(Property::Score, 999999));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique(Property::Tag, &self.tag);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamTagScore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tag.pickle(out);
|
|
self.score.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tag = Pickle::unpickle(stream)?;
|
|
this.score = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamTagScore {
|
|
fn default() -> Self {
|
|
Self {
|
|
tag: Default::default(),
|
|
score: Float::new(0.0f64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamTagScore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Tag, self.tag.into_value());
|
|
map.insert_unchecked(Property::Score, self.score.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamTagScore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Tag) => self.tag.patch(
|
|
pointer
|
|
.with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]),
|
|
value,
|
|
),
|
|
Some(Property::Score) => self.score.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpamTrainingSample {
|
|
const FLAGS: u64 = OBJ_FILTER_ACCOUNT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpamTrainingSample;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::From));
|
|
}
|
|
let value = &self.subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Subject));
|
|
}
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
if let Some(value) = &self.account_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
}
|
|
let value = &self.expires_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id, None);
|
|
if let Some(value) = &self.account_id {
|
|
i.search(Property::AccountId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpamTrainingSample {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.from.pickle(out);
|
|
self.subject.pickle(out);
|
|
self.blob_id.pickle(out);
|
|
self.is_spam.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.delete_after_use.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.from = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
this.is_spam = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.delete_after_use = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpamTrainingSample {
|
|
fn default() -> Self {
|
|
Self {
|
|
from: Default::default(),
|
|
subject: Default::default(),
|
|
blob_id: Default::default(),
|
|
is_spam: false,
|
|
account_id: Default::default(),
|
|
expires_at: Default::default(),
|
|
delete_after_use: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpamTrainingSample {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::From, self.from.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
map.insert_unchecked(Property::IsSpam, self.is_spam.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::DeleteAfterUse, self.delete_after_use.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpamTrainingSample {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::From) => pointer.assert_server_set(),
|
|
Some(Property::Subject) => pointer.assert_server_set(),
|
|
Some(Property::BlobId) => self.blob_id.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::IsSpam) => self.is_spam.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::ExpiresAt) => pointer.assert_server_set(),
|
|
Some(Property::DeleteAfterUse) => self
|
|
.delete_after_use
|
|
.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SpfReportSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SpfReportSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.from_address;
|
|
value.validate(errors);
|
|
let value = &self.from_name;
|
|
value.validate(errors);
|
|
let value = &self.send_frequency;
|
|
value.validate(errors);
|
|
let value = &self.dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.subject;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl SpfReportSettings {
|
|
pub fn ctx_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_address,
|
|
default: Some(Expression {
|
|
else_: "'noreply-spf@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromAddress,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_name,
|
|
default: Some(Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromName,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_send_frequency(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.send_frequency,
|
|
default: Some(Expression {
|
|
else_: "[1, 1d]".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::SendFrequency,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DkimSignDomain,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_subject(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.subject,
|
|
default: Some(Expression {
|
|
else_: "'SPF Authentication Failure Report'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Subject,
|
|
allowed_variables: MTA_MAIL_FROM_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_from_address(),
|
|
self.ctx_from_name(),
|
|
self.ctx_send_frequency(),
|
|
self.ctx_dkim_sign_domain(),
|
|
self.ctx_subject(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SpfReportSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.from_address.pickle(out);
|
|
self.from_name.pickle(out);
|
|
self.send_frequency.pickle(out);
|
|
self.dkim_sign_domain.pickle(out);
|
|
self.subject.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.from_address = Pickle::unpickle(stream)?;
|
|
this.from_name = Pickle::unpickle(stream)?;
|
|
this.send_frequency = Pickle::unpickle(stream)?;
|
|
this.dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SpfReportSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
from_address: Expression {
|
|
else_: "'noreply-spf@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
from_name: Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
},
|
|
send_frequency: Expression {
|
|
else_: "[1, 1d]".to_string(),
|
|
..Default::default()
|
|
},
|
|
dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
subject: Expression {
|
|
else_: "'SPF Authentication Failure Report'".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SpfReportSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::FromAddress, self.from_address.into_value());
|
|
map.insert_unchecked(Property::FromName, self.from_name.into_value());
|
|
map.insert_unchecked(Property::SendFrequency, self.send_frequency.into_value());
|
|
map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SpfReportSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::FromAddress) => self.from_address.patch(pointer, value),
|
|
Some(Property::FromName) => self.from_name.patch(pointer, value),
|
|
Some(Property::SendFrequency) => self.send_frequency.patch(pointer, value),
|
|
Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SqlAuthStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SqlAuthStore::Default => true,
|
|
SqlAuthStore::PostgreSql(inner) => inner.validate(errors),
|
|
SqlAuthStore::MySql(inner) => inner.validate(errors),
|
|
SqlAuthStore::Sqlite(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SqlAuthStore {
|
|
fn default() -> Self {
|
|
SqlAuthStore::Default
|
|
}
|
|
}
|
|
|
|
impl Pickle for SqlAuthStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SqlAuthStore::Default => {
|
|
0u16.pickle(out);
|
|
}
|
|
SqlAuthStore::PostgreSql(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SqlAuthStore::MySql(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SqlAuthStore::Sqlite(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(SqlAuthStore::Default),
|
|
1 => Pickle::unpickle(stream).map(SqlAuthStore::PostgreSql),
|
|
2 => Pickle::unpickle(stream).map(SqlAuthStore::MySql),
|
|
3 => Pickle::unpickle(stream).map(SqlAuthStore::Sqlite),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SqlAuthStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SqlAuthStore::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
SqlAuthStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
SqlAuthStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
SqlAuthStore::Sqlite(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Sqlite".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SqlAuthStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SqlAuthStoreType::Default => *self = SqlAuthStore::Default,
|
|
SqlAuthStoreType::PostgreSql => {
|
|
*self = SqlAuthStore::PostgreSql(Default::default())
|
|
}
|
|
SqlAuthStoreType::MySql => *self = SqlAuthStore::MySql(Default::default()),
|
|
SqlAuthStoreType::Sqlite => *self = SqlAuthStore::Sqlite(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
SqlAuthStore::Default => pointer.assert_eof(),
|
|
SqlAuthStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
SqlAuthStore::MySql(inner) => inner.patch(pointer, value),
|
|
SqlAuthStore::Sqlite(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SqlAuthStore {
|
|
pub fn object_type(&self) -> SqlAuthStoreType {
|
|
match self {
|
|
SqlAuthStore::Default => SqlAuthStoreType::Default,
|
|
SqlAuthStore::PostgreSql(_) => SqlAuthStoreType::PostgreSql,
|
|
SqlAuthStore::MySql(_) => SqlAuthStoreType::MySql,
|
|
SqlAuthStore::Sqlite(_) => SqlAuthStoreType::Sqlite,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SqlDirectory {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.description;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
let value = &self.store;
|
|
value.validate(errors);
|
|
let value = &self.column_email;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ColumnEmail));
|
|
}
|
|
let value = &self.column_secret;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ColumnSecret));
|
|
}
|
|
if let Some(value) = &self.column_class {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ColumnClass));
|
|
}
|
|
}
|
|
if let Some(value) = &self.column_description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ColumnDescription));
|
|
}
|
|
}
|
|
let value = &self.query_login;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::QueryLogin));
|
|
}
|
|
let value = &self.query_recipient;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::QueryRecipient));
|
|
}
|
|
if let Some(value) = &self.query_member_of {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::QueryMemberOf));
|
|
}
|
|
}
|
|
if let Some(value) = &self.query_email_aliases {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::QueryEmailAliases));
|
|
}
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Pickle for SqlDirectory {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.description.pickle(out);
|
|
self.store.pickle(out);
|
|
self.column_email.pickle(out);
|
|
self.column_secret.pickle(out);
|
|
self.column_class.pickle(out);
|
|
self.column_description.pickle(out);
|
|
self.query_login.pickle(out);
|
|
self.query_recipient.pickle(out);
|
|
self.query_member_of.pickle(out);
|
|
self.query_email_aliases.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.store = Pickle::unpickle(stream)?;
|
|
this.column_email = Pickle::unpickle(stream)?;
|
|
this.column_secret = Pickle::unpickle(stream)?;
|
|
this.column_class = Pickle::unpickle(stream)?;
|
|
this.column_description = Pickle::unpickle(stream)?;
|
|
this.query_login = Pickle::unpickle(stream)?;
|
|
this.query_recipient = Pickle::unpickle(stream)?;
|
|
this.query_member_of = Pickle::unpickle(stream)?;
|
|
this.query_email_aliases = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SqlDirectory {
|
|
fn default() -> Self {
|
|
Self {
|
|
description: Default::default(),
|
|
store: Default::default(),
|
|
column_email: "name".to_string(),
|
|
column_secret: "secret".to_string(),
|
|
column_class: Some("type".to_string()),
|
|
column_description: Some("description".to_string()),
|
|
query_login: "SELECT name, secret, description, type FROM accounts WHERE name = $1".to_string(),
|
|
query_recipient: "SELECT name, secret, description, type FROM accounts WHERE name = $1 AND active = true".to_string(),
|
|
query_member_of: Some("SELECT member_of FROM group_members WHERE name = $1".to_string()),
|
|
query_email_aliases: Some("SELECT address FROM emails WHERE name = $1".to_string()),
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SqlDirectory {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(13);
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Store, self.store.into_value());
|
|
map.insert_unchecked(Property::ColumnEmail, self.column_email.into_value());
|
|
map.insert_unchecked(Property::ColumnSecret, self.column_secret.into_value());
|
|
map.insert_unchecked(Property::ColumnClass, self.column_class.into_value());
|
|
map.insert_unchecked(
|
|
Property::ColumnDescription,
|
|
self.column_description.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::QueryLogin, self.query_login.into_value());
|
|
map.insert_unchecked(Property::QueryRecipient, self.query_recipient.into_value());
|
|
map.insert_unchecked(Property::QueryMemberOf, self.query_member_of.into_value());
|
|
map.insert_unchecked(
|
|
Property::QueryEmailAliases,
|
|
self.query_email_aliases.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SqlDirectory {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Description) => self
|
|
.description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Store) => self.store.patch(pointer, value),
|
|
Some(Property::ColumnEmail) => self
|
|
.column_email
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ColumnSecret) => self
|
|
.column_secret
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ColumnClass) => self
|
|
.column_class
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::ColumnDescription) => self
|
|
.column_description
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::QueryLogin) => self
|
|
.query_login
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::QueryRecipient) => self
|
|
.query_recipient
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::QueryMemberOf) => self
|
|
.query_member_of
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::QueryEmailAliases) => self
|
|
.query_email_aliases
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SqliteStore {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.path;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Path));
|
|
}
|
|
if let Some(value) = &self.pool_workers {
|
|
if *value > 64 {
|
|
errors.push(ValidationError::max_value(Property::PoolWorkers, 64));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolWorkers, 1));
|
|
}
|
|
}
|
|
let value = &self.pool_max_connections;
|
|
if *value > 8192 {
|
|
errors.push(ValidationError::max_value(
|
|
Property::PoolMaxConnections,
|
|
8192,
|
|
));
|
|
}
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for SqliteStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.path.pickle(out);
|
|
self.pool_workers.pickle(out);
|
|
self.pool_max_connections.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.path = Pickle::unpickle(stream)?;
|
|
this.pool_workers = Pickle::unpickle(stream)?;
|
|
this.pool_max_connections = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SqliteStore {
|
|
fn default() -> Self {
|
|
Self {
|
|
path: Default::default(),
|
|
pool_workers: Default::default(),
|
|
pool_max_connections: 10u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SqliteStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Path, self.path.into_value());
|
|
map.insert_unchecked(Property::PoolWorkers, self.pool_workers.into_value());
|
|
map.insert_unchecked(
|
|
Property::PoolMaxConnections,
|
|
self.pool_max_connections.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SqliteStore {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Path) => self
|
|
.path
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::PoolWorkers) => self.pool_workers.patch(pointer, value),
|
|
Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for StoreLookup {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::StoreLookup;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.namespace;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Namespace));
|
|
}
|
|
let value = &self.store;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global(Property::Namespace, &self.namespace);
|
|
}
|
|
}
|
|
|
|
impl Pickle for StoreLookup {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.namespace.pickle(out);
|
|
self.store.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.namespace = Pickle::unpickle(stream)?;
|
|
this.store = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for StoreLookup {
|
|
fn default() -> Self {
|
|
Self {
|
|
namespace: Default::default(),
|
|
store: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for StoreLookup {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Namespace, self.namespace.into_value());
|
|
map.insert_unchecked(Property::Store, self.store.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for StoreLookup {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Namespace) => self.namespace.patch(
|
|
pointer
|
|
.assert_read_only()?
|
|
.with_validators(&[StringValidator::Trim]),
|
|
value,
|
|
),
|
|
Some(Property::Store) => self.store.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SubAddressing {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
SubAddressing::Enabled => true,
|
|
SubAddressing::Custom(inner) => inner.validate(errors),
|
|
SubAddressing::Disabled => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SubAddressing {
|
|
fn default() -> Self {
|
|
SubAddressing::Enabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for SubAddressing {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
SubAddressing::Enabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
SubAddressing::Custom(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
SubAddressing::Disabled => {
|
|
2u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(SubAddressing::Enabled),
|
|
1 => Pickle::unpickle(stream).map(SubAddressing::Custom),
|
|
2 => Some(SubAddressing::Disabled),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SubAddressing {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
SubAddressing::Enabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Enabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
SubAddressing::Custom(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Custom".into()));
|
|
obj
|
|
}
|
|
SubAddressing::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for SubAddressing {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
SubAddressingType::Enabled => *self = SubAddressing::Enabled,
|
|
SubAddressingType::Custom => *self = SubAddressing::Custom(Default::default()),
|
|
SubAddressingType::Disabled => *self = SubAddressing::Disabled,
|
|
}
|
|
}
|
|
match self {
|
|
SubAddressing::Enabled => pointer.assert_eof(),
|
|
SubAddressing::Custom(inner) => inner.patch(pointer, value),
|
|
SubAddressing::Disabled => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SubAddressing {
|
|
pub fn object_type(&self) -> SubAddressingType {
|
|
match self {
|
|
SubAddressing::Enabled => SubAddressingType::Enabled,
|
|
SubAddressing::Custom(_) => SubAddressingType::Custom,
|
|
SubAddressing::Disabled => SubAddressingType::Disabled,
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
match self {
|
|
SubAddressing::Custom(obj) => obj.expression_ctxs(),
|
|
_ => vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SubAddressingCustom {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.custom_rule;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl SubAddressingCustom {
|
|
pub fn ctx_custom_rule(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.custom_rule,
|
|
default: None,
|
|
property: Property::CustomRule,
|
|
allowed_variables: MTA_RCPT_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![self.ctx_custom_rule()]
|
|
}
|
|
}
|
|
|
|
impl Pickle for SubAddressingCustom {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.custom_rule.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.custom_rule = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SubAddressingCustom {
|
|
fn default() -> Self {
|
|
Self {
|
|
custom_rule: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SubAddressingCustom {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::CustomRule, self.custom_rule.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SubAddressingCustom {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CustomRule) => self.custom_rule.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for SystemSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::SystemSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.default_hostname;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::DefaultHostname));
|
|
}
|
|
let value = &self.default_domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DefaultDomainId));
|
|
}
|
|
if let Some(value) = &self.default_certificate_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DefaultCertificateId));
|
|
}
|
|
}
|
|
if let Some(value) = &self.thread_pool_size {
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::ThreadPoolSize, 1));
|
|
}
|
|
}
|
|
let value = &self.max_connections;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxConnections, 1));
|
|
}
|
|
let value = &self.proxy_trusted_networks;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(
|
|
Property::ProxyTrustedNetworks,
|
|
value,
|
|
));
|
|
}
|
|
}
|
|
let value = &self.mail_exchangers;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.services;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.provider_info;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ProviderInfo));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Domain, self.default_domain_id.into(), None);
|
|
i.foreign_key(ObjectType::Certificate, self.default_certificate_id, None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for SystemSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.default_hostname.pickle(out);
|
|
self.default_domain_id.pickle(out);
|
|
self.default_certificate_id.pickle(out);
|
|
self.thread_pool_size.pickle(out);
|
|
self.max_connections.pickle(out);
|
|
self.proxy_trusted_networks.pickle(out);
|
|
self.mail_exchangers.pickle(out);
|
|
self.services.pickle(out);
|
|
self.provider_info.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.default_hostname = Pickle::unpickle(stream)?;
|
|
this.default_domain_id = Pickle::unpickle(stream)?;
|
|
this.default_certificate_id = Pickle::unpickle(stream)?;
|
|
this.thread_pool_size = Pickle::unpickle(stream)?;
|
|
this.max_connections = Pickle::unpickle(stream)?;
|
|
this.proxy_trusted_networks = Pickle::unpickle(stream)?;
|
|
this.mail_exchangers = Pickle::unpickle(stream)?;
|
|
this.services = Pickle::unpickle(stream)?;
|
|
this.provider_info = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for SystemSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
default_hostname: Default::default(),
|
|
default_domain_id: Default::default(),
|
|
default_certificate_id: Default::default(),
|
|
thread_pool_size: Default::default(),
|
|
max_connections: 8192u64,
|
|
proxy_trusted_networks: Default::default(),
|
|
mail_exchangers: List::from_iter([MailExchanger {
|
|
priority: 10u64,
|
|
..Default::default()
|
|
}]),
|
|
services: VecMap::from_iter([
|
|
(
|
|
ServiceProtocol::Caldav,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Carddav,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Imap,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Jmap,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Managesieve,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Pop3,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Smtp,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
ServiceProtocol::Webdav,
|
|
Service {
|
|
cleartext: false,
|
|
..Default::default()
|
|
},
|
|
),
|
|
]),
|
|
provider_info: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for SystemSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(
|
|
Property::DefaultHostname,
|
|
self.default_hostname.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultDomainId,
|
|
self.default_domain_id.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::DefaultCertificateId,
|
|
self.default_certificate_id.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ThreadPoolSize, self.thread_pool_size.into_value());
|
|
map.insert_unchecked(Property::MaxConnections, self.max_connections.into_value());
|
|
map.insert_unchecked(
|
|
Property::ProxyTrustedNetworks,
|
|
self.proxy_trusted_networks.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MailExchangers, self.mail_exchangers.into_value());
|
|
map.insert_unchecked(Property::Services, self.services.into_value());
|
|
map.insert_unchecked(Property::ProviderInfo, self.provider_info.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for SystemSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DefaultHostname) => self
|
|
.default_hostname
|
|
.patch(pointer.with_validators(&[StringValidator::Hostname]), value),
|
|
Some(Property::DefaultDomainId) => self.default_domain_id.patch(pointer, value),
|
|
Some(Property::DefaultCertificateId) => {
|
|
self.default_certificate_id.patch(pointer, value)
|
|
}
|
|
Some(Property::ThreadPoolSize) => self.thread_pool_size.patch(pointer, value),
|
|
Some(Property::MaxConnections) => self.max_connections.patch(pointer, value),
|
|
Some(Property::ProxyTrustedNetworks) => self
|
|
.proxy_trusted_networks
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::MailExchangers) => self.mail_exchangers.patch(pointer, value),
|
|
Some(Property::Services) => self.services.patch(pointer, value),
|
|
Some(Property::ProviderInfo) => self.provider_info.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Task {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Task;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Task::IndexDocument(inner) => inner.validate(errors),
|
|
Task::UnindexDocument(inner) => inner.validate(errors),
|
|
Task::IndexTrace(inner) => inner.validate(errors),
|
|
Task::CalendarAlarmEmail(inner) => inner.validate(errors),
|
|
Task::CalendarAlarmNotification(inner) => inner.validate(errors),
|
|
Task::CalendarItipMessage(inner) => inner.validate(errors),
|
|
Task::MergeThreads(inner) => inner.validate(errors),
|
|
Task::DmarcReport(inner) => inner.validate(errors),
|
|
Task::TlsReport(inner) => inner.validate(errors),
|
|
Task::RestoreArchivedItem(inner) => inner.validate(errors),
|
|
Task::DestroyAccount(inner) => inner.validate(errors),
|
|
Task::AccountMaintenance(inner) => inner.validate(errors),
|
|
Task::TenantMaintenance(inner) => inner.validate(errors),
|
|
Task::StoreMaintenance(inner) => inner.validate(errors),
|
|
Task::SpamFilterMaintenance(inner) => inner.validate(errors),
|
|
Task::AcmeRenewal(inner) => inner.validate(errors),
|
|
Task::DkimManagement(inner) => inner.validate(errors),
|
|
Task::DnsManagement(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
Task::IndexDocument(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::UnindexDocument(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::IndexTrace(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::CalendarAlarmEmail(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::CalendarAlarmNotification(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::CalendarItipMessage(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::MergeThreads(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::DmarcReport(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::TlsReport(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::RestoreArchivedItem(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::DestroyAccount(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::AccountMaintenance(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::TenantMaintenance(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::StoreMaintenance(_) => {}
|
|
Task::SpamFilterMaintenance(_) => {}
|
|
Task::AcmeRenewal(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::DkimManagement(object) => {
|
|
object.index(i);
|
|
}
|
|
Task::DnsManagement(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Task {
|
|
fn default() -> Self {
|
|
Task::IndexDocument(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Task {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Task::IndexDocument(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::UnindexDocument(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::IndexTrace(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::CalendarAlarmEmail(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::CalendarAlarmNotification(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::CalendarItipMessage(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::MergeThreads(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::DmarcReport(inner) => {
|
|
7u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::TlsReport(inner) => {
|
|
8u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::RestoreArchivedItem(inner) => {
|
|
9u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::DestroyAccount(inner) => {
|
|
10u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::AccountMaintenance(inner) => {
|
|
11u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::TenantMaintenance(inner) => {
|
|
12u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::StoreMaintenance(inner) => {
|
|
13u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::SpamFilterMaintenance(inner) => {
|
|
14u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::AcmeRenewal(inner) => {
|
|
15u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::DkimManagement(inner) => {
|
|
16u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Task::DnsManagement(inner) => {
|
|
17u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Task::IndexDocument),
|
|
1 => Pickle::unpickle(stream).map(Task::UnindexDocument),
|
|
2 => Pickle::unpickle(stream).map(Task::IndexTrace),
|
|
3 => Pickle::unpickle(stream).map(Task::CalendarAlarmEmail),
|
|
4 => Pickle::unpickle(stream).map(Task::CalendarAlarmNotification),
|
|
5 => Pickle::unpickle(stream).map(Task::CalendarItipMessage),
|
|
6 => Pickle::unpickle(stream).map(Task::MergeThreads),
|
|
7 => Pickle::unpickle(stream).map(Task::DmarcReport),
|
|
8 => Pickle::unpickle(stream).map(Task::TlsReport),
|
|
9 => Pickle::unpickle(stream).map(Task::RestoreArchivedItem),
|
|
10 => Pickle::unpickle(stream).map(Task::DestroyAccount),
|
|
11 => Pickle::unpickle(stream).map(Task::AccountMaintenance),
|
|
12 => Pickle::unpickle(stream).map(Task::TenantMaintenance),
|
|
13 => Pickle::unpickle(stream).map(Task::StoreMaintenance),
|
|
14 => Pickle::unpickle(stream).map(Task::SpamFilterMaintenance),
|
|
15 => Pickle::unpickle(stream).map(Task::AcmeRenewal),
|
|
16 => Pickle::unpickle(stream).map(Task::DkimManagement),
|
|
17 => Pickle::unpickle(stream).map(Task::DnsManagement),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Task {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Task::IndexDocument(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("IndexDocument".into()));
|
|
obj
|
|
}
|
|
Task::UnindexDocument(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("UnindexDocument".into()));
|
|
obj
|
|
}
|
|
Task::IndexTrace(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("IndexTrace".into()));
|
|
obj
|
|
}
|
|
Task::CalendarAlarmEmail(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("CalendarAlarmEmail".into()));
|
|
obj
|
|
}
|
|
Task::CalendarAlarmNotification(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut().unwrap().insert_unchecked(
|
|
Property::Type,
|
|
JmapValue::Str("CalendarAlarmNotification".into()),
|
|
);
|
|
obj
|
|
}
|
|
Task::CalendarItipMessage(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("CalendarItipMessage".into()));
|
|
obj
|
|
}
|
|
Task::MergeThreads(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MergeThreads".into()));
|
|
obj
|
|
}
|
|
Task::DmarcReport(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DmarcReport".into()));
|
|
obj
|
|
}
|
|
Task::TlsReport(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("TlsReport".into()));
|
|
obj
|
|
}
|
|
Task::RestoreArchivedItem(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("RestoreArchivedItem".into()));
|
|
obj
|
|
}
|
|
Task::DestroyAccount(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DestroyAccount".into()));
|
|
obj
|
|
}
|
|
Task::AccountMaintenance(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("AccountMaintenance".into()));
|
|
obj
|
|
}
|
|
Task::TenantMaintenance(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("TenantMaintenance".into()));
|
|
obj
|
|
}
|
|
Task::StoreMaintenance(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("StoreMaintenance".into()));
|
|
obj
|
|
}
|
|
Task::SpamFilterMaintenance(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut().unwrap().insert_unchecked(
|
|
Property::Type,
|
|
JmapValue::Str("SpamFilterMaintenance".into()),
|
|
);
|
|
obj
|
|
}
|
|
Task::AcmeRenewal(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("AcmeRenewal".into()));
|
|
obj
|
|
}
|
|
Task::DkimManagement(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DkimManagement".into()));
|
|
obj
|
|
}
|
|
Task::DnsManagement(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("DnsManagement".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Task {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
TaskType::IndexDocument => *self = Task::IndexDocument(Default::default()),
|
|
TaskType::UnindexDocument => *self = Task::UnindexDocument(Default::default()),
|
|
TaskType::IndexTrace => *self = Task::IndexTrace(Default::default()),
|
|
TaskType::CalendarAlarmEmail => {
|
|
*self = Task::CalendarAlarmEmail(Default::default())
|
|
}
|
|
TaskType::CalendarAlarmNotification => {
|
|
*self = Task::CalendarAlarmNotification(Default::default())
|
|
}
|
|
TaskType::CalendarItipMessage => {
|
|
*self = Task::CalendarItipMessage(Default::default())
|
|
}
|
|
TaskType::MergeThreads => *self = Task::MergeThreads(Default::default()),
|
|
TaskType::DmarcReport => *self = Task::DmarcReport(Default::default()),
|
|
TaskType::TlsReport => *self = Task::TlsReport(Default::default()),
|
|
TaskType::RestoreArchivedItem => {
|
|
*self = Task::RestoreArchivedItem(Default::default())
|
|
}
|
|
TaskType::DestroyAccount => *self = Task::DestroyAccount(Default::default()),
|
|
TaskType::AccountMaintenance => {
|
|
*self = Task::AccountMaintenance(Default::default())
|
|
}
|
|
TaskType::TenantMaintenance => *self = Task::TenantMaintenance(Default::default()),
|
|
TaskType::StoreMaintenance => *self = Task::StoreMaintenance(Default::default()),
|
|
TaskType::SpamFilterMaintenance => {
|
|
*self = Task::SpamFilterMaintenance(Default::default())
|
|
}
|
|
TaskType::AcmeRenewal => *self = Task::AcmeRenewal(Default::default()),
|
|
TaskType::DkimManagement => *self = Task::DkimManagement(Default::default()),
|
|
TaskType::DnsManagement => *self = Task::DnsManagement(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Task::IndexDocument(inner) => inner.patch(pointer, value),
|
|
Task::UnindexDocument(inner) => inner.patch(pointer, value),
|
|
Task::IndexTrace(inner) => inner.patch(pointer, value),
|
|
Task::CalendarAlarmEmail(inner) => inner.patch(pointer, value),
|
|
Task::CalendarAlarmNotification(inner) => inner.patch(pointer, value),
|
|
Task::CalendarItipMessage(inner) => inner.patch(pointer, value),
|
|
Task::MergeThreads(inner) => inner.patch(pointer, value),
|
|
Task::DmarcReport(inner) => inner.patch(pointer, value),
|
|
Task::TlsReport(inner) => inner.patch(pointer, value),
|
|
Task::RestoreArchivedItem(inner) => inner.patch(pointer, value),
|
|
Task::DestroyAccount(inner) => inner.patch(pointer, value),
|
|
Task::AccountMaintenance(inner) => inner.patch(pointer, value),
|
|
Task::TenantMaintenance(inner) => inner.patch(pointer, value),
|
|
Task::StoreMaintenance(inner) => inner.patch(pointer, value),
|
|
Task::SpamFilterMaintenance(inner) => inner.patch(pointer, value),
|
|
Task::AcmeRenewal(inner) => inner.patch(pointer, value),
|
|
Task::DkimManagement(inner) => inner.patch(pointer, value),
|
|
Task::DnsManagement(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Task {
|
|
pub fn object_type(&self) -> TaskType {
|
|
match self {
|
|
Task::IndexDocument(_) => TaskType::IndexDocument,
|
|
Task::UnindexDocument(_) => TaskType::UnindexDocument,
|
|
Task::IndexTrace(_) => TaskType::IndexTrace,
|
|
Task::CalendarAlarmEmail(_) => TaskType::CalendarAlarmEmail,
|
|
Task::CalendarAlarmNotification(_) => TaskType::CalendarAlarmNotification,
|
|
Task::CalendarItipMessage(_) => TaskType::CalendarItipMessage,
|
|
Task::MergeThreads(_) => TaskType::MergeThreads,
|
|
Task::DmarcReport(_) => TaskType::DmarcReport,
|
|
Task::TlsReport(_) => TaskType::TlsReport,
|
|
Task::RestoreArchivedItem(_) => TaskType::RestoreArchivedItem,
|
|
Task::DestroyAccount(_) => TaskType::DestroyAccount,
|
|
Task::AccountMaintenance(_) => TaskType::AccountMaintenance,
|
|
Task::TenantMaintenance(_) => TaskType::TenantMaintenance,
|
|
Task::StoreMaintenance(_) => TaskType::StoreMaintenance,
|
|
Task::SpamFilterMaintenance(_) => TaskType::SpamFilterMaintenance,
|
|
Task::AcmeRenewal(_) => TaskType::AcmeRenewal,
|
|
Task::DkimManagement(_) => TaskType::DkimManagement,
|
|
Task::DnsManagement(_) => TaskType::DnsManagement,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskAccountMaintenance {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskAccountMaintenance {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.account_id.pickle(out);
|
|
self.maintenance_type.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.maintenance_type = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskAccountMaintenance {
|
|
fn default() -> Self {
|
|
Self {
|
|
account_id: Default::default(),
|
|
maintenance_type: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskAccountMaintenance {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaintenanceType,
|
|
self.maintenance_type.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskAccountMaintenance {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::MaintenanceType) => self
|
|
.maintenance_type
|
|
.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskCalendarAlarmEmail {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.event_start;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::EventStart, value));
|
|
}
|
|
let value = &self.event_end;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::EventEnd, value));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.document_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DocumentId, value));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskCalendarAlarmEmail {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.alarm_id.pickle(out);
|
|
self.event_id.pickle(out);
|
|
self.event_start.pickle(out);
|
|
self.event_end.pickle(out);
|
|
self.event_start_tz.pickle(out);
|
|
self.event_end_tz.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.document_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.alarm_id = Pickle::unpickle(stream)?;
|
|
this.event_id = Pickle::unpickle(stream)?;
|
|
this.event_start = Pickle::unpickle(stream)?;
|
|
this.event_end = Pickle::unpickle(stream)?;
|
|
this.event_start_tz = Pickle::unpickle(stream)?;
|
|
this.event_end_tz = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.document_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskCalendarAlarmEmail {
|
|
fn default() -> Self {
|
|
Self {
|
|
alarm_id: 0u64,
|
|
event_id: 0u64,
|
|
event_start: Default::default(),
|
|
event_end: Default::default(),
|
|
event_start_tz: 0u64,
|
|
event_end_tz: 0u64,
|
|
account_id: Default::default(),
|
|
document_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskCalendarAlarmEmail {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(11);
|
|
map.insert_unchecked(Property::AlarmId, self.alarm_id.into_value());
|
|
map.insert_unchecked(Property::EventId, self.event_id.into_value());
|
|
map.insert_unchecked(Property::EventStart, self.event_start.into_value());
|
|
map.insert_unchecked(Property::EventEnd, self.event_end.into_value());
|
|
map.insert_unchecked(Property::EventStartTz, self.event_start_tz.into_value());
|
|
map.insert_unchecked(Property::EventEndTz, self.event_end_tz.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::DocumentId, self.document_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskCalendarAlarmEmail {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AlarmId) => pointer.assert_server_set(),
|
|
Some(Property::EventId) => pointer.assert_server_set(),
|
|
Some(Property::EventStart) => pointer.assert_server_set(),
|
|
Some(Property::EventEnd) => pointer.assert_server_set(),
|
|
Some(Property::EventStartTz) => pointer.assert_server_set(),
|
|
Some(Property::EventEndTz) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::DocumentId) => {
|
|
self.document_id.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskCalendarAlarmNotification {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.document_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DocumentId, value));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskCalendarAlarmNotification {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.alarm_id.pickle(out);
|
|
self.event_id.pickle(out);
|
|
self.recurrence_id.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.document_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.alarm_id = Pickle::unpickle(stream)?;
|
|
this.event_id = Pickle::unpickle(stream)?;
|
|
this.recurrence_id = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.document_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskCalendarAlarmNotification {
|
|
fn default() -> Self {
|
|
Self {
|
|
alarm_id: 0u64,
|
|
event_id: 0u64,
|
|
recurrence_id: Default::default(),
|
|
account_id: Default::default(),
|
|
document_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskCalendarAlarmNotification {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::AlarmId, self.alarm_id.into_value());
|
|
map.insert_unchecked(Property::EventId, self.event_id.into_value());
|
|
map.insert_unchecked(Property::RecurrenceId, self.recurrence_id.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::DocumentId, self.document_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskCalendarAlarmNotification {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AlarmId) => pointer.assert_server_set(),
|
|
Some(Property::EventId) => pointer.assert_server_set(),
|
|
Some(Property::RecurrenceId) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::DocumentId) => {
|
|
self.document_id.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskCalendarItipContents {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::From));
|
|
}
|
|
let value = &self.to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::To));
|
|
}
|
|
}
|
|
let value = &self.i_calendar_data;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ICalendarData));
|
|
}
|
|
let value = &self.summary;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Summary));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskCalendarItipContents {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.from.pickle(out);
|
|
self.to.pickle(out);
|
|
self.is_from_organizer.pickle(out);
|
|
self.i_calendar_data.pickle(out);
|
|
self.summary.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.from = Pickle::unpickle(stream)?;
|
|
this.to = Pickle::unpickle(stream)?;
|
|
this.is_from_organizer = Pickle::unpickle(stream)?;
|
|
this.i_calendar_data = Pickle::unpickle(stream)?;
|
|
this.summary = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskCalendarItipContents {
|
|
fn default() -> Self {
|
|
Self {
|
|
from: Default::default(),
|
|
to: Default::default(),
|
|
is_from_organizer: false,
|
|
i_calendar_data: Default::default(),
|
|
summary: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskCalendarItipContents {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::From, self.from.into_value());
|
|
map.insert_unchecked(Property::To, self.to.into_value());
|
|
map.insert_unchecked(
|
|
Property::IsFromOrganizer,
|
|
self.is_from_organizer.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ICalendarData, self.i_calendar_data.into_value());
|
|
map.insert_unchecked(Property::Summary, self.summary.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskCalendarItipContents {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::From) => pointer.assert_server_set(),
|
|
Some(Property::To) => pointer.assert_server_set(),
|
|
Some(Property::IsFromOrganizer) => pointer.assert_server_set(),
|
|
Some(Property::ICalendarData) => pointer.assert_server_set(),
|
|
Some(Property::Summary) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskCalendarItipMessage {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.messages;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.document_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DocumentId, value));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskCalendarItipMessage {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.messages.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.document_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.messages = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.document_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskCalendarItipMessage {
|
|
fn default() -> Self {
|
|
Self {
|
|
messages: Default::default(),
|
|
account_id: Default::default(),
|
|
document_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskCalendarItipMessage {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Messages, self.messages.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::DocumentId, self.document_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskCalendarItipMessage {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Messages) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::DocumentId) => {
|
|
self.document_id.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskDestroyAccount {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.account_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AccountName));
|
|
}
|
|
let value = &self.account_domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountDomainId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
i.foreign_key(ObjectType::Domain, self.account_domain_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskDestroyAccount {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.account_id.pickle(out);
|
|
self.account_name.pickle(out);
|
|
self.account_domain_id.pickle(out);
|
|
self.account_type.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.account_name = Pickle::unpickle(stream)?;
|
|
this.account_domain_id = Pickle::unpickle(stream)?;
|
|
this.account_type = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskDestroyAccount {
|
|
fn default() -> Self {
|
|
Self {
|
|
account_id: Default::default(),
|
|
account_name: Default::default(),
|
|
account_domain_id: Default::default(),
|
|
account_type: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskDestroyAccount {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::AccountName, self.account_name.into_value());
|
|
map.insert_unchecked(
|
|
Property::AccountDomainId,
|
|
self.account_domain_id.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::AccountType, self.account_type.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskDestroyAccount {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AccountId) => pointer.assert_server_set(),
|
|
Some(Property::AccountName) => self.account_name.patch(pointer, value),
|
|
Some(Property::AccountDomainId) => self.account_domain_id.patch(pointer, value),
|
|
Some(Property::AccountType) => pointer.assert_server_set(),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskDmarcReport {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.report_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::ReportId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::DmarcInternalReport, self.report_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskDmarcReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.report_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.report_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskDmarcReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
report_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskDmarcReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::ReportId, self.report_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskDmarcReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ReportId) => pointer.assert_server_set(),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskDnsManagement {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskDnsManagement {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.update_records.pickle(out);
|
|
self.on_success_renew_certificate.pickle(out);
|
|
self.domain_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.update_records = Pickle::unpickle(stream)?;
|
|
this.on_success_renew_certificate = Pickle::unpickle(stream)?;
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskDnsManagement {
|
|
fn default() -> Self {
|
|
Self {
|
|
update_records: Default::default(),
|
|
on_success_renew_certificate: false,
|
|
domain_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskDnsManagement {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::UpdateRecords, self.update_records.into_value());
|
|
map.insert_unchecked(
|
|
Property::OnSuccessRenewCertificate,
|
|
self.on_success_renew_certificate.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskDnsManagement {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::UpdateRecords) => self.update_records.patch(pointer, value),
|
|
Some(Property::OnSuccessRenewCertificate) => {
|
|
self.on_success_renew_certificate.patch(pointer, value)
|
|
}
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskDomainManagement {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskDomainManagement {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.domain_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskDomainManagement {
|
|
fn default() -> Self {
|
|
Self {
|
|
domain_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskDomainManagement {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskDomainManagement {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskIndexDocument {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.document_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DocumentId, value));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskIndexDocument {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.document_type.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.document_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.document_type = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.document_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskIndexDocument {
|
|
fn default() -> Self {
|
|
Self {
|
|
document_type: Default::default(),
|
|
account_id: Default::default(),
|
|
document_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskIndexDocument {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::DocumentType, self.document_type.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::DocumentId, self.document_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskIndexDocument {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::DocumentType) => {
|
|
self.document_type.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::AccountId) => self
|
|
.account_id
|
|
.patch(pointer.assert_read_only()?.assert_can_set_account()?, value),
|
|
Some(Property::DocumentId) => {
|
|
self.document_id.patch(pointer.assert_read_only()?, value)
|
|
}
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskIndexTrace {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.trace_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::TraceId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Trace, self.trace_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskIndexTrace {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.trace_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.trace_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskIndexTrace {
|
|
fn default() -> Self {
|
|
Self {
|
|
trace_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskIndexTrace {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::TraceId, self.trace_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskIndexTrace {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::TraceId) => self.trace_id.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for TaskManager {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::TaskManager;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.max_attempts;
|
|
if *value < 1 {
|
|
errors.push(ValidationError::min_value(Property::MaxAttempts, 1));
|
|
}
|
|
let value = &self.strategy;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for TaskManager {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.max_attempts.pickle(out);
|
|
self.strategy.pickle(out);
|
|
self.total_deadline.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.max_attempts = Pickle::unpickle(stream)?;
|
|
this.strategy = Pickle::unpickle(stream)?;
|
|
this.total_deadline = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskManager {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_attempts: 3u64,
|
|
strategy: Default::default(),
|
|
total_deadline: Duration::from_millis(21600000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskManager {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::MaxAttempts, self.max_attempts.into_value());
|
|
map.insert_unchecked(Property::Strategy, self.strategy.into_value());
|
|
map.insert_unchecked(Property::TotalDeadline, self.total_deadline.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskManager {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaxAttempts) => self.max_attempts.patch(pointer, value),
|
|
Some(Property::Strategy) => self.strategy.patch(pointer, value),
|
|
Some(Property::TotalDeadline) => self.total_deadline.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskMergeThreads {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.thread_name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ThreadName));
|
|
}
|
|
let value = &self.message_ids;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MessageIds));
|
|
}
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskMergeThreads {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.account_id.pickle(out);
|
|
self.thread_name.pickle(out);
|
|
self.message_ids.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.thread_name = Pickle::unpickle(stream)?;
|
|
this.message_ids = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskMergeThreads {
|
|
fn default() -> Self {
|
|
Self {
|
|
account_id: Default::default(),
|
|
thread_name: Default::default(),
|
|
message_ids: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskMergeThreads {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::ThreadName, self.thread_name.into_value());
|
|
map.insert_unchecked(Property::MessageIds, self.message_ids.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskMergeThreads {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AccountId) => pointer.assert_server_set(),
|
|
Some(Property::ThreadName) => pointer.assert_server_set(),
|
|
Some(Property::MessageIds) => pointer.assert_server_set(),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskRestoreArchivedItem {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.blob_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::BlobId));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.archived_until;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ArchivedUntil, value));
|
|
}
|
|
let value = &self.account_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::AccountId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Account, self.account_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskRestoreArchivedItem {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.blob_id.pickle(out);
|
|
self.archived_item_type.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.archived_until.pickle(out);
|
|
self.account_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.blob_id = Pickle::unpickle(stream)?;
|
|
this.archived_item_type = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.archived_until = Pickle::unpickle(stream)?;
|
|
this.account_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskRestoreArchivedItem {
|
|
fn default() -> Self {
|
|
Self {
|
|
blob_id: Default::default(),
|
|
archived_item_type: Default::default(),
|
|
created_at: Default::default(),
|
|
archived_until: Default::default(),
|
|
account_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskRestoreArchivedItem {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::BlobId, self.blob_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::ArchivedItemType,
|
|
self.archived_item_type.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value());
|
|
map.insert_unchecked(Property::AccountId, self.account_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskRestoreArchivedItem {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::BlobId) => pointer.assert_server_set(),
|
|
Some(Property::ArchivedItemType) => pointer.assert_server_set(),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::ArchivedUntil) => pointer.assert_server_set(),
|
|
Some(Property::AccountId) => pointer.assert_server_set(),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskRetryStrategy {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
TaskRetryStrategy::ExponentialBackoff(inner) => inner.validate(errors),
|
|
TaskRetryStrategy::FixedDelay(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for TaskRetryStrategy {
|
|
fn default() -> Self {
|
|
TaskRetryStrategy::ExponentialBackoff(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskRetryStrategy {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
TaskRetryStrategy::ExponentialBackoff(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TaskRetryStrategy::FixedDelay(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(TaskRetryStrategy::ExponentialBackoff),
|
|
1 => Pickle::unpickle(stream).map(TaskRetryStrategy::FixedDelay),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskRetryStrategy {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
TaskRetryStrategy::ExponentialBackoff(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("ExponentialBackoff".into()));
|
|
obj
|
|
}
|
|
TaskRetryStrategy::FixedDelay(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FixedDelay".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for TaskRetryStrategy {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
TaskRetryStrategyType::ExponentialBackoff => {
|
|
*self = TaskRetryStrategy::ExponentialBackoff(Default::default())
|
|
}
|
|
TaskRetryStrategyType::FixedDelay => {
|
|
*self = TaskRetryStrategy::FixedDelay(Default::default())
|
|
}
|
|
}
|
|
}
|
|
match self {
|
|
TaskRetryStrategy::ExponentialBackoff(inner) => inner.patch(pointer, value),
|
|
TaskRetryStrategy::FixedDelay(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskRetryStrategy {
|
|
pub fn object_type(&self) -> TaskRetryStrategyType {
|
|
match self {
|
|
TaskRetryStrategy::ExponentialBackoff(_) => TaskRetryStrategyType::ExponentialBackoff,
|
|
TaskRetryStrategy::FixedDelay(_) => TaskRetryStrategyType::FixedDelay,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskRetryStrategyBackoff {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.factor;
|
|
if *value < Float::new(1.0) {
|
|
errors.push(ValidationError::min_value(Property::Factor, 1));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskRetryStrategyBackoff {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.factor.pickle(out);
|
|
self.initial_delay.pickle(out);
|
|
self.max_delay.pickle(out);
|
|
self.jitter.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.factor = Pickle::unpickle(stream)?;
|
|
this.initial_delay = Pickle::unpickle(stream)?;
|
|
this.max_delay = Pickle::unpickle(stream)?;
|
|
this.jitter = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskRetryStrategyBackoff {
|
|
fn default() -> Self {
|
|
Self {
|
|
factor: Float::new(2.0f64),
|
|
initial_delay: Duration::from_millis(60000),
|
|
max_delay: Duration::from_millis(1800000),
|
|
jitter: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskRetryStrategyBackoff {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::Factor, self.factor.into_value());
|
|
map.insert_unchecked(Property::InitialDelay, self.initial_delay.into_value());
|
|
map.insert_unchecked(Property::MaxDelay, self.max_delay.into_value());
|
|
map.insert_unchecked(Property::Jitter, self.jitter.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskRetryStrategyBackoff {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Factor) => self.factor.patch(pointer, value),
|
|
Some(Property::InitialDelay) => self.initial_delay.patch(pointer, value),
|
|
Some(Property::MaxDelay) => self.max_delay.patch(pointer, value),
|
|
Some(Property::Jitter) => self.jitter.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskRetryStrategyFixed {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskRetryStrategyFixed {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.delay.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.delay = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskRetryStrategyFixed {
|
|
fn default() -> Self {
|
|
Self {
|
|
delay: Duration::from_millis(300000),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskRetryStrategyFixed {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Delay, self.delay.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskRetryStrategyFixed {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Delay) => self.delay.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskSpamFilterMaintenance {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskSpamFilterMaintenance {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.maintenance_type.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.maintenance_type = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskSpamFilterMaintenance {
|
|
fn default() -> Self {
|
|
Self {
|
|
maintenance_type: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskSpamFilterMaintenance {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(
|
|
Property::MaintenanceType,
|
|
self.maintenance_type.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskSpamFilterMaintenance {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaintenanceType) => self
|
|
.maintenance_type
|
|
.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskStatus {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
TaskStatus::Pending(inner) => inner.validate(errors),
|
|
TaskStatus::Retry(inner) => inner.validate(errors),
|
|
TaskStatus::Failed(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for TaskStatus {
|
|
fn default() -> Self {
|
|
TaskStatus::Pending(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskStatus {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
TaskStatus::Pending(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TaskStatus::Retry(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TaskStatus::Failed(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(TaskStatus::Pending),
|
|
1 => Pickle::unpickle(stream).map(TaskStatus::Retry),
|
|
2 => Pickle::unpickle(stream).map(TaskStatus::Failed),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskStatus {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
TaskStatus::Pending(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Pending".into()));
|
|
obj
|
|
}
|
|
TaskStatus::Retry(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Retry".into()));
|
|
obj
|
|
}
|
|
TaskStatus::Failed(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Failed".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for TaskStatus {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
TaskStatusType::Pending => *self = TaskStatus::Pending(Default::default()),
|
|
TaskStatusType::Retry => *self = TaskStatus::Retry(Default::default()),
|
|
TaskStatusType::Failed => *self = TaskStatus::Failed(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
TaskStatus::Pending(inner) => inner.patch(pointer, value),
|
|
TaskStatus::Retry(inner) => inner.patch(pointer, value),
|
|
TaskStatus::Failed(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskStatus {
|
|
pub fn object_type(&self) -> TaskStatusType {
|
|
match self {
|
|
TaskStatus::Pending(_) => TaskStatusType::Pending,
|
|
TaskStatus::Retry(_) => TaskStatusType::Retry,
|
|
TaskStatus::Failed(_) => TaskStatusType::Failed,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskStatusFailed {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.failed_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::FailedAt, value));
|
|
}
|
|
let value = &self.failure_reason;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FailureReason));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskStatusFailed {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.created_at.pickle(out);
|
|
self.failed_at.pickle(out);
|
|
self.failed_attempt_number.pickle(out);
|
|
self.failure_reason.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.failed_at = Pickle::unpickle(stream)?;
|
|
this.failed_attempt_number = Pickle::unpickle(stream)?;
|
|
this.failure_reason = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskStatusFailed {
|
|
fn default() -> Self {
|
|
Self {
|
|
created_at: Default::default(),
|
|
failed_at: Default::default(),
|
|
failed_attempt_number: 0u64,
|
|
failure_reason: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskStatusFailed {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::FailedAt, self.failed_at.into_value());
|
|
map.insert_unchecked(
|
|
Property::FailedAttemptNumber,
|
|
self.failed_attempt_number.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::FailureReason, self.failure_reason.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskStatusFailed {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::FailedAt) => self.failed_at.patch(pointer, value),
|
|
Some(Property::FailedAttemptNumber) => self.failed_attempt_number.patch(pointer, value),
|
|
Some(Property::FailureReason) => self.failure_reason.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskStatusPending {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.due;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Due, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskStatusPending {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.created_at.pickle(out);
|
|
self.due.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.due = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskStatusPending {
|
|
fn default() -> Self {
|
|
Self {
|
|
created_at: Default::default(),
|
|
due: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskStatusPending {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::Due, self.due.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskStatusPending {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::Due) => self.due.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskStatusRetry {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.due;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Due, value));
|
|
}
|
|
let value = &self.failure_reason;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FailureReason));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskStatusRetry {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.created_at.pickle(out);
|
|
self.due.pickle(out);
|
|
self.attempt_number.pickle(out);
|
|
self.failure_reason.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.due = Pickle::unpickle(stream)?;
|
|
this.attempt_number = Pickle::unpickle(stream)?;
|
|
this.failure_reason = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskStatusRetry {
|
|
fn default() -> Self {
|
|
Self {
|
|
created_at: Default::default(),
|
|
due: Default::default(),
|
|
attempt_number: 1u64,
|
|
failure_reason: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskStatusRetry {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(6);
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::Due, self.due.into_value());
|
|
map.insert_unchecked(Property::AttemptNumber, self.attempt_number.into_value());
|
|
map.insert_unchecked(Property::FailureReason, self.failure_reason.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskStatusRetry {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::Due) => self.due.patch(pointer, value),
|
|
Some(Property::AttemptNumber) => self.attempt_number.patch(pointer, value),
|
|
Some(Property::FailureReason) => self.failure_reason.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskStoreMaintenance {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskStoreMaintenance {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.maintenance_type.pickle(out);
|
|
self.shard_index.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.maintenance_type = Pickle::unpickle(stream)?;
|
|
this.shard_index = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskStoreMaintenance {
|
|
fn default() -> Self {
|
|
Self {
|
|
maintenance_type: Default::default(),
|
|
shard_index: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskStoreMaintenance {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(
|
|
Property::MaintenanceType,
|
|
self.maintenance_type.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ShardIndex, self.shard_index.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskStoreMaintenance {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::MaintenanceType) => self
|
|
.maintenance_type
|
|
.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::ShardIndex) => self.shard_index.patch(pointer, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskTenantMaintenance {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.tenant_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::TenantId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.tenant_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskTenantMaintenance {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.tenant_id.pickle(out);
|
|
self.maintenance_type.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.tenant_id = Pickle::unpickle(stream)?;
|
|
this.maintenance_type = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskTenantMaintenance {
|
|
fn default() -> Self {
|
|
Self {
|
|
tenant_id: Default::default(),
|
|
maintenance_type: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskTenantMaintenance {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::TenantId, self.tenant_id.into_value());
|
|
map.insert_unchecked(
|
|
Property::MaintenanceType,
|
|
self.maintenance_type.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskTenantMaintenance {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::TenantId) => self.tenant_id.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::MaintenanceType) => self
|
|
.maintenance_type
|
|
.patch(pointer.assert_read_only()?, value),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TaskTlsReport {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.report_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::ReportId));
|
|
}
|
|
let value = &self.status;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::TlsInternalReport, self.report_id.into(), None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TaskTlsReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.report_id.pickle(out);
|
|
self.status.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.report_id = Pickle::unpickle(stream)?;
|
|
this.status = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TaskTlsReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
report_id: Default::default(),
|
|
status: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TaskTlsReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::ReportId, self.report_id.into_value());
|
|
map.insert_unchecked(Property::Status, self.status.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TaskTlsReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ReportId) => pointer.assert_server_set(),
|
|
Some(Property::Status) => self.status.patch(pointer, value),
|
|
Some(Property::Due) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Tenant {
|
|
const FLAGS: u64 = OBJ_SEQ_ID;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Tenant;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
if let Some(value) = &self.logo {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Logo));
|
|
}
|
|
}
|
|
let value = &self.roles;
|
|
value.validate(errors);
|
|
let value = &self.permissions;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.text(Property::Text, &self.name);
|
|
self.roles.index(i);
|
|
}
|
|
}
|
|
|
|
impl Pickle for Tenant {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.logo.pickle(out);
|
|
self.roles.pickle(out);
|
|
self.permissions.pickle(out);
|
|
self.quotas.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.logo = Pickle::unpickle(stream)?;
|
|
this.roles = Pickle::unpickle(stream)?;
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
this.quotas = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Tenant {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
created_at: Default::default(),
|
|
logo: Default::default(),
|
|
roles: Default::default(),
|
|
permissions: Default::default(),
|
|
quotas: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Tenant {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::Logo, self.logo.into_value());
|
|
map.insert_unchecked(Property::Roles, self.roles.into_value());
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
map.insert_unchecked(Property::Quotas, self.quotas.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Tenant {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::Logo) => self.logo.patch(pointer, value),
|
|
Some(Property::Roles) => self.roles.patch(pointer, value),
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::Quotas) => self.quotas.patch(pointer, value),
|
|
Some(Property::UsedDiskQuota) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for TlsExternalReport {
|
|
const FLAGS: u64 = OBJ_FILTER_TENANT;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::TlsExternalReport;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.report;
|
|
value.validate(errors);
|
|
let value = &self.from;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::From));
|
|
}
|
|
let value = &self.subject;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Subject));
|
|
}
|
|
let value = &self.to;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::To));
|
|
}
|
|
}
|
|
let value = &self.received_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ReceivedAt, value));
|
|
}
|
|
let value = &self.expires_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ExpiresAt, value));
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
}
|
|
}
|
|
|
|
impl Pickle for TlsExternalReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.report.pickle(out);
|
|
self.from.pickle(out);
|
|
self.subject.pickle(out);
|
|
self.to.pickle(out);
|
|
self.received_at.pickle(out);
|
|
self.expires_at.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.report = Pickle::unpickle(stream)?;
|
|
this.from = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
this.to = Pickle::unpickle(stream)?;
|
|
this.received_at = Pickle::unpickle(stream)?;
|
|
this.expires_at = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TlsExternalReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
report: Default::default(),
|
|
from: Default::default(),
|
|
subject: Default::default(),
|
|
to: Default::default(),
|
|
received_at: Default::default(),
|
|
expires_at: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TlsExternalReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::Report, self.report.into_value());
|
|
map.insert_unchecked(Property::From, self.from.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
map.insert_unchecked(Property::To, self.to.into_value());
|
|
map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value());
|
|
map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TlsExternalReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Report) => self.report.patch(pointer, value),
|
|
Some(Property::From) => self
|
|
.from
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::To) => self
|
|
.to
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::ReceivedAt) => self.received_at.patch(pointer, value),
|
|
Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TlsFailureDetails {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.sending_mta_ip {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::SendingMtaIp, value));
|
|
}
|
|
}
|
|
if let Some(value) = &self.receiving_mx_hostname {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReceivingMxHostname));
|
|
}
|
|
}
|
|
if let Some(value) = &self.receiving_mx_helo {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReceivingMxHelo));
|
|
}
|
|
}
|
|
if let Some(value) = &self.receiving_ip {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::ReceivingIp, value));
|
|
}
|
|
}
|
|
if let Some(value) = &self.additional_information {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::AdditionalInformation));
|
|
}
|
|
}
|
|
if let Some(value) = &self.failure_reason_code {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::FailureReasonCode));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TlsFailureDetails {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.result_type.pickle(out);
|
|
self.sending_mta_ip.pickle(out);
|
|
self.receiving_mx_hostname.pickle(out);
|
|
self.receiving_mx_helo.pickle(out);
|
|
self.receiving_ip.pickle(out);
|
|
self.failed_session_count.pickle(out);
|
|
self.additional_information.pickle(out);
|
|
self.failure_reason_code.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.result_type = Pickle::unpickle(stream)?;
|
|
this.sending_mta_ip = Pickle::unpickle(stream)?;
|
|
this.receiving_mx_hostname = Pickle::unpickle(stream)?;
|
|
this.receiving_mx_helo = Pickle::unpickle(stream)?;
|
|
this.receiving_ip = Pickle::unpickle(stream)?;
|
|
this.failed_session_count = Pickle::unpickle(stream)?;
|
|
this.additional_information = Pickle::unpickle(stream)?;
|
|
this.failure_reason_code = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TlsFailureDetails {
|
|
fn default() -> Self {
|
|
Self {
|
|
result_type: Default::default(),
|
|
sending_mta_ip: Default::default(),
|
|
receiving_mx_hostname: Default::default(),
|
|
receiving_mx_helo: Default::default(),
|
|
receiving_ip: Default::default(),
|
|
failed_session_count: 0u64,
|
|
additional_information: Default::default(),
|
|
failure_reason_code: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TlsFailureDetails {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::ResultType, self.result_type.into_value());
|
|
map.insert_unchecked(Property::SendingMtaIp, self.sending_mta_ip.into_value());
|
|
map.insert_unchecked(
|
|
Property::ReceivingMxHostname,
|
|
self.receiving_mx_hostname.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::ReceivingMxHelo,
|
|
self.receiving_mx_helo.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ReceivingIp, self.receiving_ip.into_value());
|
|
map.insert_unchecked(
|
|
Property::FailedSessionCount,
|
|
self.failed_session_count.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::AdditionalInformation,
|
|
self.additional_information.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::FailureReasonCode,
|
|
self.failure_reason_code.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TlsFailureDetails {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ResultType) => self.result_type.patch(pointer, value),
|
|
Some(Property::SendingMtaIp) => self.sending_mta_ip.patch(pointer, value),
|
|
Some(Property::ReceivingMxHostname) => self.receiving_mx_hostname.patch(pointer, value),
|
|
Some(Property::ReceivingMxHelo) => self.receiving_mx_helo.patch(pointer, value),
|
|
Some(Property::ReceivingIp) => self.receiving_ip.patch(pointer, value),
|
|
Some(Property::FailedSessionCount) => self.failed_session_count.patch(pointer, value),
|
|
Some(Property::AdditionalInformation) => {
|
|
self.additional_information.patch(pointer, value)
|
|
}
|
|
Some(Property::FailureReasonCode) => self.failure_reason_code.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for TlsInternalReport {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::TlsInternalReport;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.mail_rua;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MailRua));
|
|
}
|
|
}
|
|
let value = &self.http_rua;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpRua));
|
|
}
|
|
}
|
|
let value = &self.report;
|
|
value.validate(errors);
|
|
let value = &self.domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Domain));
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.deliver_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DeliverAt, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for TlsInternalReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.policy_identifiers.pickle(out);
|
|
self.mail_rua.pickle(out);
|
|
self.http_rua.pickle(out);
|
|
self.report.pickle(out);
|
|
self.domain.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.deliver_at.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.policy_identifiers = Pickle::unpickle(stream)?;
|
|
this.mail_rua = Pickle::unpickle(stream)?;
|
|
this.http_rua = Pickle::unpickle(stream)?;
|
|
this.report = Pickle::unpickle(stream)?;
|
|
this.domain = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.deliver_at = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TlsInternalReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
policy_identifiers: Default::default(),
|
|
mail_rua: Default::default(),
|
|
http_rua: Default::default(),
|
|
report: Default::default(),
|
|
domain: Default::default(),
|
|
created_at: Default::default(),
|
|
deliver_at: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TlsInternalReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(
|
|
Property::PolicyIdentifiers,
|
|
self.policy_identifiers.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MailRua, self.mail_rua.into_value());
|
|
map.insert_unchecked(Property::HttpRua, self.http_rua.into_value());
|
|
map.insert_unchecked(Property::Report, self.report.into_value());
|
|
map.insert_unchecked(Property::Domain, self.domain.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::DeliverAt, self.deliver_at.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TlsInternalReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::PolicyIdentifiers) => self.policy_identifiers.patch(pointer, value),
|
|
Some(Property::MailRua) => self
|
|
.mail_rua
|
|
.patch(pointer.with_validators(&[StringValidator::Email]), value),
|
|
Some(Property::HttpRua) => self.http_rua.patch(pointer, value),
|
|
Some(Property::Report) => self.report.patch(pointer, value),
|
|
Some(Property::Domain) => self
|
|
.domain
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::CreatedAt) => self.created_at.patch(pointer, value),
|
|
Some(Property::DeliverAt) => self.deliver_at.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TlsReport {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.organization_name {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::OrganizationName));
|
|
}
|
|
}
|
|
if let Some(value) = &self.contact_info {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ContactInfo));
|
|
}
|
|
}
|
|
let value = &self.report_id;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::ReportId));
|
|
}
|
|
let value = &self.date_range_start;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DateRangeStart, value));
|
|
}
|
|
let value = &self.date_range_end;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::DateRangeEnd, value));
|
|
}
|
|
let value = &self.policies;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TlsReport {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.organization_name.pickle(out);
|
|
self.contact_info.pickle(out);
|
|
self.report_id.pickle(out);
|
|
self.date_range_start.pickle(out);
|
|
self.date_range_end.pickle(out);
|
|
self.policies.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.organization_name = Pickle::unpickle(stream)?;
|
|
this.contact_info = Pickle::unpickle(stream)?;
|
|
this.report_id = Pickle::unpickle(stream)?;
|
|
this.date_range_start = Pickle::unpickle(stream)?;
|
|
this.date_range_end = Pickle::unpickle(stream)?;
|
|
this.policies = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TlsReport {
|
|
fn default() -> Self {
|
|
Self {
|
|
organization_name: Default::default(),
|
|
contact_info: Default::default(),
|
|
report_id: Default::default(),
|
|
date_range_start: Default::default(),
|
|
date_range_end: Default::default(),
|
|
policies: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TlsReport {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(8);
|
|
map.insert_unchecked(
|
|
Property::OrganizationName,
|
|
self.organization_name.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::ContactInfo, self.contact_info.into_value());
|
|
map.insert_unchecked(Property::ReportId, self.report_id.into_value());
|
|
map.insert_unchecked(Property::DateRangeStart, self.date_range_start.into_value());
|
|
map.insert_unchecked(Property::DateRangeEnd, self.date_range_end.into_value());
|
|
map.insert_unchecked(Property::Policies, self.policies.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TlsReport {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::OrganizationName) => self.organization_name.patch(pointer, value),
|
|
Some(Property::ContactInfo) => self.contact_info.patch(pointer, value),
|
|
Some(Property::ReportId) => self.report_id.patch(pointer, value),
|
|
Some(Property::DateRangeStart) => self.date_range_start.patch(pointer, value),
|
|
Some(Property::DateRangeEnd) => self.date_range_end.patch(pointer, value),
|
|
Some(Property::Policies) => self.policies.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TlsReportPolicy {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.policy_strings;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::PolicyStrings));
|
|
}
|
|
}
|
|
let value = &self.policy_domain;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::PolicyDomain));
|
|
}
|
|
let value = &self.mx_hosts;
|
|
for value in value.iter() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::MxHosts));
|
|
}
|
|
}
|
|
let value = &self.failure_details;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TlsReportPolicy {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.policy_type.pickle(out);
|
|
self.policy_strings.pickle(out);
|
|
self.policy_domain.pickle(out);
|
|
self.mx_hosts.pickle(out);
|
|
self.total_successful_sessions.pickle(out);
|
|
self.total_failed_sessions.pickle(out);
|
|
self.failure_details.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.policy_type = Pickle::unpickle(stream)?;
|
|
this.policy_strings = Pickle::unpickle(stream)?;
|
|
this.policy_domain = Pickle::unpickle(stream)?;
|
|
this.mx_hosts = Pickle::unpickle(stream)?;
|
|
this.total_successful_sessions = Pickle::unpickle(stream)?;
|
|
this.total_failed_sessions = Pickle::unpickle(stream)?;
|
|
this.failure_details = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TlsReportPolicy {
|
|
fn default() -> Self {
|
|
Self {
|
|
policy_type: Default::default(),
|
|
policy_strings: Default::default(),
|
|
policy_domain: Default::default(),
|
|
mx_hosts: Default::default(),
|
|
total_successful_sessions: 0u64,
|
|
total_failed_sessions: 0u64,
|
|
failure_details: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TlsReportPolicy {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(Property::PolicyType, self.policy_type.into_value());
|
|
map.insert_unchecked(Property::PolicyStrings, self.policy_strings.into_value());
|
|
map.insert_unchecked(Property::PolicyDomain, self.policy_domain.into_value());
|
|
map.insert_unchecked(Property::MxHosts, self.mx_hosts.into_value());
|
|
map.insert_unchecked(
|
|
Property::TotalSuccessfulSessions,
|
|
self.total_successful_sessions.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::TotalFailedSessions,
|
|
self.total_failed_sessions.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::FailureDetails, self.failure_details.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TlsReportPolicy {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::PolicyType) => self.policy_type.patch(pointer, value),
|
|
Some(Property::PolicyStrings) => self.policy_strings.patch(pointer, value),
|
|
Some(Property::PolicyDomain) => self
|
|
.policy_domain
|
|
.patch(pointer.with_validators(&[StringValidator::Domain]), value),
|
|
Some(Property::MxHosts) => self.mx_hosts.patch(pointer, value),
|
|
Some(Property::TotalSuccessfulSessions) => {
|
|
self.total_successful_sessions.patch(pointer, value)
|
|
}
|
|
Some(Property::TotalFailedSessions) => self.total_failed_sessions.patch(pointer, value),
|
|
Some(Property::FailureDetails) => self.failure_details.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for TlsReportSettings {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::TlsReportSettings;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.contact_info;
|
|
value.validate(errors);
|
|
let value = &self.from_address;
|
|
value.validate(errors);
|
|
let value = &self.from_name;
|
|
value.validate(errors);
|
|
let value = &self.max_report_size;
|
|
value.validate(errors);
|
|
let value = &self.org_name;
|
|
value.validate(errors);
|
|
let value = &self.send_frequency;
|
|
value.validate(errors);
|
|
let value = &self.dkim_sign_domain;
|
|
value.validate(errors);
|
|
let value = &self.subject;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl TlsReportSettings {
|
|
pub fn ctx_contact_info(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.contact_info,
|
|
default: Some(Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::ContactInfo,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_from_address(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_address,
|
|
default: Some(Expression {
|
|
else_: "'noreply-tls@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromAddress,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_from_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.from_name,
|
|
default: Some(Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::FromName,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_max_report_size(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.max_report_size,
|
|
default: Some(Expression {
|
|
else_: "5242880".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::MaxReportSize,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_org_name(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.org_name,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::OrgName,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_send_frequency(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.send_frequency,
|
|
default: Some(Expression {
|
|
else_: "daily".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::SendFrequency,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: MTA_AGGREGATE_CONSTANT,
|
|
}
|
|
}
|
|
|
|
pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.dkim_sign_domain,
|
|
default: Some(Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::DkimSignDomain,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn ctx_subject(&self) -> ExpressionContext<'_> {
|
|
ExpressionContext {
|
|
expr: &self.subject,
|
|
default: Some(Expression {
|
|
else_: "'TLS Aggregate Report'".to_string(),
|
|
..Default::default()
|
|
}),
|
|
property: Property::Subject,
|
|
allowed_variables: MTA_QUEUE_HOST_VARIABLE,
|
|
allowed_constants: &[],
|
|
}
|
|
}
|
|
|
|
pub fn expression_ctxs(&self) -> Vec<ExpressionContext<'_>> {
|
|
vec![
|
|
self.ctx_contact_info(),
|
|
self.ctx_from_address(),
|
|
self.ctx_from_name(),
|
|
self.ctx_max_report_size(),
|
|
self.ctx_org_name(),
|
|
self.ctx_send_frequency(),
|
|
self.ctx_dkim_sign_domain(),
|
|
self.ctx_subject(),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Pickle for TlsReportSettings {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.contact_info.pickle(out);
|
|
self.from_address.pickle(out);
|
|
self.from_name.pickle(out);
|
|
self.max_report_size.pickle(out);
|
|
self.org_name.pickle(out);
|
|
self.send_frequency.pickle(out);
|
|
self.dkim_sign_domain.pickle(out);
|
|
self.subject.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.contact_info = Pickle::unpickle(stream)?;
|
|
this.from_address = Pickle::unpickle(stream)?;
|
|
this.from_name = Pickle::unpickle(stream)?;
|
|
this.max_report_size = Pickle::unpickle(stream)?;
|
|
this.org_name = Pickle::unpickle(stream)?;
|
|
this.send_frequency = Pickle::unpickle(stream)?;
|
|
this.dkim_sign_domain = Pickle::unpickle(stream)?;
|
|
this.subject = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TlsReportSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
contact_info: Expression {
|
|
else_: "false".to_string(),
|
|
..Default::default()
|
|
},
|
|
from_address: Expression {
|
|
else_: "'noreply-tls@' + system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
from_name: Expression {
|
|
else_: "'Report Subsystem'".to_string(),
|
|
..Default::default()
|
|
},
|
|
max_report_size: Expression {
|
|
else_: "5242880".to_string(),
|
|
..Default::default()
|
|
},
|
|
org_name: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
send_frequency: Expression {
|
|
else_: "daily".to_string(),
|
|
..Default::default()
|
|
},
|
|
dkim_sign_domain: Expression {
|
|
else_: "system('domain')".to_string(),
|
|
..Default::default()
|
|
},
|
|
subject: Expression {
|
|
else_: "'TLS Aggregate Report'".to_string(),
|
|
..Default::default()
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TlsReportSettings {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::ContactInfo, self.contact_info.into_value());
|
|
map.insert_unchecked(Property::FromAddress, self.from_address.into_value());
|
|
map.insert_unchecked(Property::FromName, self.from_name.into_value());
|
|
map.insert_unchecked(Property::MaxReportSize, self.max_report_size.into_value());
|
|
map.insert_unchecked(Property::OrgName, self.org_name.into_value());
|
|
map.insert_unchecked(Property::SendFrequency, self.send_frequency.into_value());
|
|
map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value());
|
|
map.insert_unchecked(Property::Subject, self.subject.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TlsReportSettings {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::ContactInfo) => self.contact_info.patch(pointer, value),
|
|
Some(Property::FromAddress) => self.from_address.patch(pointer, value),
|
|
Some(Property::FromName) => self.from_name.patch(pointer, value),
|
|
Some(Property::MaxReportSize) => self.max_report_size.patch(pointer, value),
|
|
Some(Property::OrgName) => self.org_name.patch(pointer, value),
|
|
Some(Property::SendFrequency) => self.send_frequency.patch(pointer, value),
|
|
Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value),
|
|
Some(Property::Subject) => self.subject.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Trace {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Trace;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.events;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for Trace {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.events.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.events = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for Trace {
|
|
fn default() -> Self {
|
|
Self {
|
|
events: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Trace {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for Trace {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::Timestamp) => pointer.assert_server_set(),
|
|
Some(Property::From) => pointer.assert_server_set(),
|
|
Some(Property::To) => pointer.assert_server_set(),
|
|
Some(Property::Size) => pointer.assert_server_set(),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceEvent {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.timestamp;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Timestamp, value));
|
|
}
|
|
let value = &self.key_values;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceEvent {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.event.pickle(out);
|
|
self.timestamp.pickle(out);
|
|
self.key_values.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.event = Pickle::unpickle(stream)?;
|
|
this.timestamp = Pickle::unpickle(stream)?;
|
|
this.key_values = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceEvent {
|
|
fn default() -> Self {
|
|
Self {
|
|
event: Default::default(),
|
|
timestamp: Default::default(),
|
|
key_values: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceEvent {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(5);
|
|
map.insert_unchecked(Property::Event, self.event.into_value());
|
|
map.insert_unchecked(Property::Timestamp, self.timestamp.into_value());
|
|
map.insert_unchecked(Property::KeyValues, self.key_values.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceEvent {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Event) => self.event.patch(pointer, value),
|
|
Some(Property::Timestamp) => self.timestamp.patch(pointer, value),
|
|
Some(Property::KeyValues) => self.key_values.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceKeyValue {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceKeyValue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.key.pickle(out);
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.key = Pickle::unpickle(stream)?;
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceKeyValue {
|
|
fn default() -> Self {
|
|
Self {
|
|
key: Default::default(),
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceKeyValue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Key, self.key.into_value());
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceKeyValue {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Key) => self.key.patch(pointer, value),
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValue {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
TraceValue::String(inner) => inner.validate(errors),
|
|
TraceValue::UnsignedInt(inner) => inner.validate(errors),
|
|
TraceValue::Integer(inner) => inner.validate(errors),
|
|
TraceValue::Boolean(inner) => inner.validate(errors),
|
|
TraceValue::Float(inner) => inner.validate(errors),
|
|
TraceValue::UTCDateTime(inner) => inner.validate(errors),
|
|
TraceValue::Duration(inner) => inner.validate(errors),
|
|
TraceValue::IpAddr(inner) => inner.validate(errors),
|
|
TraceValue::List(inner) => inner.validate(errors),
|
|
TraceValue::Event(inner) => inner.validate(errors),
|
|
TraceValue::Null => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValue {
|
|
fn default() -> Self {
|
|
TraceValue::String(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValue {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
TraceValue::String(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::UnsignedInt(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::Integer(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::Boolean(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::Float(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::UTCDateTime(inner) => {
|
|
5u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::Duration(inner) => {
|
|
6u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::IpAddr(inner) => {
|
|
7u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::List(inner) => {
|
|
8u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::Event(inner) => {
|
|
9u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TraceValue::Null => {
|
|
10u16.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(TraceValue::String),
|
|
1 => Pickle::unpickle(stream).map(TraceValue::UnsignedInt),
|
|
2 => Pickle::unpickle(stream).map(TraceValue::Integer),
|
|
3 => Pickle::unpickle(stream).map(TraceValue::Boolean),
|
|
4 => Pickle::unpickle(stream).map(TraceValue::Float),
|
|
5 => Pickle::unpickle(stream).map(TraceValue::UTCDateTime),
|
|
6 => Pickle::unpickle(stream).map(TraceValue::Duration),
|
|
7 => Pickle::unpickle(stream).map(TraceValue::IpAddr),
|
|
8 => Pickle::unpickle(stream).map(TraceValue::List),
|
|
9 => Pickle::unpickle(stream).map(TraceValue::Event),
|
|
10 => Some(TraceValue::Null),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValue {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
TraceValue::String(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("String".into()));
|
|
obj
|
|
}
|
|
TraceValue::UnsignedInt(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("UnsignedInt".into()));
|
|
obj
|
|
}
|
|
TraceValue::Integer(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Integer".into()));
|
|
obj
|
|
}
|
|
TraceValue::Boolean(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Boolean".into()));
|
|
obj
|
|
}
|
|
TraceValue::Float(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Float".into()));
|
|
obj
|
|
}
|
|
TraceValue::UTCDateTime(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("UTCDateTime".into()));
|
|
obj
|
|
}
|
|
TraceValue::Duration(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Duration".into()));
|
|
obj
|
|
}
|
|
TraceValue::IpAddr(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("IpAddr".into()));
|
|
obj
|
|
}
|
|
TraceValue::List(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("List".into()));
|
|
obj
|
|
}
|
|
TraceValue::Event(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Event".into()));
|
|
obj
|
|
}
|
|
TraceValue::Null => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Null".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for TraceValue {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
TraceValueType::String => *self = TraceValue::String(Default::default()),
|
|
TraceValueType::UnsignedInt => *self = TraceValue::UnsignedInt(Default::default()),
|
|
TraceValueType::Integer => *self = TraceValue::Integer(Default::default()),
|
|
TraceValueType::Boolean => *self = TraceValue::Boolean(Default::default()),
|
|
TraceValueType::Float => *self = TraceValue::Float(Default::default()),
|
|
TraceValueType::UTCDateTime => *self = TraceValue::UTCDateTime(Default::default()),
|
|
TraceValueType::Duration => *self = TraceValue::Duration(Default::default()),
|
|
TraceValueType::IpAddr => *self = TraceValue::IpAddr(Default::default()),
|
|
TraceValueType::List => *self = TraceValue::List(Default::default()),
|
|
TraceValueType::Event => *self = TraceValue::Event(Default::default()),
|
|
TraceValueType::Null => *self = TraceValue::Null,
|
|
}
|
|
}
|
|
match self {
|
|
TraceValue::String(inner) => inner.patch(pointer, value),
|
|
TraceValue::UnsignedInt(inner) => inner.patch(pointer, value),
|
|
TraceValue::Integer(inner) => inner.patch(pointer, value),
|
|
TraceValue::Boolean(inner) => inner.patch(pointer, value),
|
|
TraceValue::Float(inner) => inner.patch(pointer, value),
|
|
TraceValue::UTCDateTime(inner) => inner.patch(pointer, value),
|
|
TraceValue::Duration(inner) => inner.patch(pointer, value),
|
|
TraceValue::IpAddr(inner) => inner.patch(pointer, value),
|
|
TraceValue::List(inner) => inner.patch(pointer, value),
|
|
TraceValue::Event(inner) => inner.patch(pointer, value),
|
|
TraceValue::Null => pointer.assert_eof(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValue {
|
|
pub fn object_type(&self) -> TraceValueType {
|
|
match self {
|
|
TraceValue::String(_) => TraceValueType::String,
|
|
TraceValue::UnsignedInt(_) => TraceValueType::UnsignedInt,
|
|
TraceValue::Integer(_) => TraceValueType::Integer,
|
|
TraceValue::Boolean(_) => TraceValueType::Boolean,
|
|
TraceValue::Float(_) => TraceValueType::Float,
|
|
TraceValue::UTCDateTime(_) => TraceValueType::UTCDateTime,
|
|
TraceValue::Duration(_) => TraceValueType::Duration,
|
|
TraceValue::IpAddr(_) => TraceValueType::IpAddr,
|
|
TraceValue::List(_) => TraceValueType::List,
|
|
TraceValue::Event(_) => TraceValueType::Event,
|
|
TraceValue::Null => TraceValueType::Null,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueBoolean {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueBoolean {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueBoolean {
|
|
fn default() -> Self {
|
|
Self { value: false }
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueBoolean {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueBoolean {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueDuration {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueDuration {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueDuration {
|
|
fn default() -> Self {
|
|
Self { value: 0u64 }
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueDuration {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueDuration {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueEvent {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueEvent {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.event.pickle(out);
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.event = Pickle::unpickle(stream)?;
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueEvent {
|
|
fn default() -> Self {
|
|
Self {
|
|
event: Default::default(),
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueEvent {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(4);
|
|
map.insert_unchecked(Property::Event, self.event.into_value());
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueEvent {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Event) => self.event.patch(pointer, value),
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueFloat {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueFloat {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueFloat {
|
|
fn default() -> Self {
|
|
Self {
|
|
value: Float::new(0.0f64),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueFloat {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueFloat {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueInteger {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueInteger {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueInteger {
|
|
fn default() -> Self {
|
|
Self { value: 0i64 }
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueInteger {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueInteger {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueIpAddr {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Value, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueIpAddr {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueIpAddr {
|
|
fn default() -> Self {
|
|
Self {
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueIpAddr {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueIpAddr {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueList {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueList {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueList {
|
|
fn default() -> Self {
|
|
Self {
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueList {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueList {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueString {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueString {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueString {
|
|
fn default() -> Self {
|
|
Self {
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueString {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueString {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueUTCDateTime {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.value;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::Value, value));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueUTCDateTime {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueUTCDateTime {
|
|
fn default() -> Self {
|
|
Self {
|
|
value: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueUTCDateTime {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueUTCDateTime {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceValueUnsignedInt {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TraceValueUnsignedInt {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.value.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.value = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TraceValueUnsignedInt {
|
|
fn default() -> Self {
|
|
Self { value: 0u64 }
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TraceValueUnsignedInt {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Value, self.value.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TraceValueUnsignedInt {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Value) => self.value.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for Tracer {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::Tracer;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
Tracer::Log(inner) => inner.validate(errors),
|
|
Tracer::Stdout(inner) => inner.validate(errors),
|
|
Tracer::Journal(inner) => inner.validate(errors),
|
|
Tracer::OtelHttp(inner) => inner.validate(errors),
|
|
Tracer::OtelGrpc(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for Tracer {
|
|
fn default() -> Self {
|
|
Tracer::Log(Default::default())
|
|
}
|
|
}
|
|
|
|
impl Pickle for Tracer {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
Tracer::Log(inner) => {
|
|
0u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Tracer::Stdout(inner) => {
|
|
1u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Tracer::Journal(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Tracer::OtelHttp(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
Tracer::OtelGrpc(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Pickle::unpickle(stream).map(Tracer::Log),
|
|
1 => Pickle::unpickle(stream).map(Tracer::Stdout),
|
|
2 => Pickle::unpickle(stream).map(Tracer::Journal),
|
|
3 => Pickle::unpickle(stream).map(Tracer::OtelHttp),
|
|
4 => Pickle::unpickle(stream).map(Tracer::OtelGrpc),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for Tracer {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
Tracer::Log(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Log".into()));
|
|
obj
|
|
}
|
|
Tracer::Stdout(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Stdout".into()));
|
|
obj
|
|
}
|
|
Tracer::Journal(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Journal".into()));
|
|
obj
|
|
}
|
|
Tracer::OtelHttp(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("OtelHttp".into()));
|
|
obj
|
|
}
|
|
Tracer::OtelGrpc(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("OtelGrpc".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for Tracer {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
TracerType::Log => *self = Tracer::Log(Default::default()),
|
|
TracerType::Stdout => *self = Tracer::Stdout(Default::default()),
|
|
TracerType::Journal => *self = Tracer::Journal(Default::default()),
|
|
TracerType::OtelHttp => *self = Tracer::OtelHttp(Default::default()),
|
|
TracerType::OtelGrpc => *self = Tracer::OtelGrpc(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
Tracer::Log(inner) => inner.patch(pointer, value),
|
|
Tracer::Stdout(inner) => inner.patch(pointer, value),
|
|
Tracer::Journal(inner) => inner.patch(pointer, value),
|
|
Tracer::OtelHttp(inner) => inner.patch(pointer, value),
|
|
Tracer::OtelGrpc(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Tracer {
|
|
pub fn object_type(&self) -> TracerType {
|
|
match self {
|
|
Tracer::Log(_) => TracerType::Log,
|
|
Tracer::Stdout(_) => TracerType::Stdout,
|
|
Tracer::Journal(_) => TracerType::Journal,
|
|
Tracer::OtelHttp(_) => TracerType::OtelHttp,
|
|
Tracer::OtelGrpc(_) => TracerType::OtelGrpc,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TracerCommon {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TracerCommon {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enable.pickle(out);
|
|
self.level.pickle(out);
|
|
self.lossy.pickle(out);
|
|
self.events.pickle(out);
|
|
self.events_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.lossy = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.events_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TracerCommon {
|
|
fn default() -> Self {
|
|
Self {
|
|
enable: true,
|
|
level: TracingLevel::Info,
|
|
lossy: false,
|
|
events: Default::default(),
|
|
events_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TracerCommon {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(7);
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Lossy, self.lossy.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TracerCommon {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Lossy) => self.lossy.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TracerLog {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.path;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Path));
|
|
}
|
|
let value = &self.prefix;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Prefix));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TracerLog {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.path.pickle(out);
|
|
self.prefix.pickle(out);
|
|
self.rotate.pickle(out);
|
|
self.ansi.pickle(out);
|
|
self.multiline.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.level.pickle(out);
|
|
self.lossy.pickle(out);
|
|
self.events.pickle(out);
|
|
self.events_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.path = Pickle::unpickle(stream)?;
|
|
this.prefix = Pickle::unpickle(stream)?;
|
|
this.rotate = Pickle::unpickle(stream)?;
|
|
this.ansi = Pickle::unpickle(stream)?;
|
|
this.multiline = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.lossy = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.events_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TracerLog {
|
|
fn default() -> Self {
|
|
Self {
|
|
path: Default::default(),
|
|
prefix: "stalwart".to_string(),
|
|
rotate: LogRotateFrequency::Daily,
|
|
ansi: true,
|
|
multiline: false,
|
|
enable: true,
|
|
level: TracingLevel::Info,
|
|
lossy: false,
|
|
events: Default::default(),
|
|
events_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TracerLog {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(12);
|
|
map.insert_unchecked(Property::Path, self.path.into_value());
|
|
map.insert_unchecked(Property::Prefix, self.prefix.into_value());
|
|
map.insert_unchecked(Property::Rotate, self.rotate.into_value());
|
|
map.insert_unchecked(Property::Ansi, self.ansi.into_value());
|
|
map.insert_unchecked(Property::Multiline, self.multiline.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Lossy, self.lossy.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TracerLog {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Path) => self
|
|
.path
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Prefix) => self
|
|
.prefix
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Rotate) => self.rotate.patch(pointer, value),
|
|
Some(Property::Ansi) => self.ansi.patch(pointer, value),
|
|
Some(Property::Multiline) => self.multiline.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Lossy) => self.lossy.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TracerOtelGrpc {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
if let Some(value) = &self.endpoint {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Endpoint));
|
|
}
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TracerOtelGrpc {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.endpoint.pickle(out);
|
|
self.enable_log_exporter.pickle(out);
|
|
self.enable_span_exporter.pickle(out);
|
|
self.throttle.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.level.pickle(out);
|
|
self.lossy.pickle(out);
|
|
self.events.pickle(out);
|
|
self.events_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.endpoint = Pickle::unpickle(stream)?;
|
|
this.enable_log_exporter = Pickle::unpickle(stream)?;
|
|
this.enable_span_exporter = Pickle::unpickle(stream)?;
|
|
this.throttle = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.lossy = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.events_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TracerOtelGrpc {
|
|
fn default() -> Self {
|
|
Self {
|
|
endpoint: Default::default(),
|
|
enable_log_exporter: true,
|
|
enable_span_exporter: true,
|
|
throttle: Duration::from_millis(1000),
|
|
timeout: Duration::from_millis(10000),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
enable: true,
|
|
level: TracingLevel::Info,
|
|
lossy: false,
|
|
events: Default::default(),
|
|
events_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TracerOtelGrpc {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::Endpoint, self.endpoint.into_value());
|
|
map.insert_unchecked(
|
|
Property::EnableLogExporter,
|
|
self.enable_log_exporter.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::EnableSpanExporter,
|
|
self.enable_span_exporter.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Throttle, self.throttle.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Lossy, self.lossy.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TracerOtelGrpc {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Endpoint) => self
|
|
.endpoint
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::EnableLogExporter) => self.enable_log_exporter.patch(pointer, value),
|
|
Some(Property::EnableSpanExporter) => self.enable_span_exporter.patch(pointer, value),
|
|
Some(Property::Throttle) => self.throttle.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Lossy) => self.lossy.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TracerOtelHttp {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.endpoint;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Endpoint));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for TracerOtelHttp {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.endpoint.pickle(out);
|
|
self.enable_log_exporter.pickle(out);
|
|
self.enable_span_exporter.pickle(out);
|
|
self.throttle.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.level.pickle(out);
|
|
self.lossy.pickle(out);
|
|
self.events.pickle(out);
|
|
self.events_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.endpoint = Pickle::unpickle(stream)?;
|
|
this.enable_log_exporter = Pickle::unpickle(stream)?;
|
|
this.enable_span_exporter = Pickle::unpickle(stream)?;
|
|
this.throttle = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.lossy = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.events_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TracerOtelHttp {
|
|
fn default() -> Self {
|
|
Self {
|
|
endpoint: Default::default(),
|
|
enable_log_exporter: true,
|
|
enable_span_exporter: true,
|
|
throttle: Duration::from_millis(1000),
|
|
timeout: Duration::from_millis(10000),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
enable: true,
|
|
level: TracingLevel::Info,
|
|
lossy: false,
|
|
events: Default::default(),
|
|
events_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TracerOtelHttp {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(14);
|
|
map.insert_unchecked(Property::Endpoint, self.endpoint.into_value());
|
|
map.insert_unchecked(
|
|
Property::EnableLogExporter,
|
|
self.enable_log_exporter.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::EnableSpanExporter,
|
|
self.enable_span_exporter.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::Throttle, self.throttle.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Lossy, self.lossy.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TracerOtelHttp {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Endpoint) => self
|
|
.endpoint
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::EnableLogExporter) => self.enable_log_exporter.patch(pointer, value),
|
|
Some(Property::EnableSpanExporter) => self.enable_span_exporter.patch(pointer, value),
|
|
Some(Property::Throttle) => self.throttle.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Lossy) => self.lossy.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TracerStdout {
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Pickle for TracerStdout {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.buffered.pickle(out);
|
|
self.ansi.pickle(out);
|
|
self.multiline.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.level.pickle(out);
|
|
self.lossy.pickle(out);
|
|
self.events.pickle(out);
|
|
self.events_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.buffered = Pickle::unpickle(stream)?;
|
|
this.ansi = Pickle::unpickle(stream)?;
|
|
this.multiline = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.lossy = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.events_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for TracerStdout {
|
|
fn default() -> Self {
|
|
Self {
|
|
buffered: true,
|
|
ansi: false,
|
|
multiline: false,
|
|
enable: true,
|
|
level: TracingLevel::Info,
|
|
lossy: false,
|
|
events: Default::default(),
|
|
events_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TracerStdout {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(10);
|
|
map.insert_unchecked(Property::Buffered, self.buffered.into_value());
|
|
map.insert_unchecked(Property::Ansi, self.ansi.into_value());
|
|
map.insert_unchecked(Property::Multiline, self.multiline.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Lossy, self.lossy.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for TracerStdout {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Buffered) => self.buffered.patch(pointer, value),
|
|
Some(Property::Ansi) => self.ansi.patch(pointer, value),
|
|
Some(Property::Multiline) => self.multiline.patch(pointer, value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Lossy) => self.lossy.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for TracingStore {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::TracingStore;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
TracingStore::Disabled => true,
|
|
TracingStore::Default => true,
|
|
TracingStore::FoundationDb(inner) => inner.validate(errors),
|
|
TracingStore::PostgreSql(inner) => inner.validate(errors),
|
|
TracingStore::MySql(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Default for TracingStore {
|
|
fn default() -> Self {
|
|
TracingStore::Disabled
|
|
}
|
|
}
|
|
|
|
impl Pickle for TracingStore {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
TracingStore::Disabled => {
|
|
0u16.pickle(out);
|
|
}
|
|
TracingStore::Default => {
|
|
1u16.pickle(out);
|
|
}
|
|
TracingStore::FoundationDb(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TracingStore::PostgreSql(inner) => {
|
|
3u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
TracingStore::MySql(inner) => {
|
|
4u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(TracingStore::Disabled),
|
|
1 => Some(TracingStore::Default),
|
|
2 => Pickle::unpickle(stream).map(TracingStore::FoundationDb),
|
|
3 => Pickle::unpickle(stream).map(TracingStore::PostgreSql),
|
|
4 => Pickle::unpickle(stream).map(TracingStore::MySql),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for TracingStore {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
TracingStore::Disabled => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
TracingStore::Default => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
TracingStore::FoundationDb(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into()));
|
|
obj
|
|
}
|
|
TracingStore::PostgreSql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into()));
|
|
obj
|
|
}
|
|
TracingStore::MySql(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("MySql".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for TracingStore {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
TracingStoreType::Disabled => *self = TracingStore::Disabled,
|
|
TracingStoreType::Default => *self = TracingStore::Default,
|
|
TracingStoreType::FoundationDb => {
|
|
*self = TracingStore::FoundationDb(Default::default())
|
|
}
|
|
TracingStoreType::PostgreSql => {
|
|
*self = TracingStore::PostgreSql(Default::default())
|
|
}
|
|
TracingStoreType::MySql => *self = TracingStore::MySql(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
TracingStore::Disabled => pointer.assert_eof(),
|
|
TracingStore::Default => pointer.assert_eof(),
|
|
TracingStore::FoundationDb(inner) => inner.patch(pointer, value),
|
|
TracingStore::PostgreSql(inner) => inner.patch(pointer, value),
|
|
TracingStore::MySql(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TracingStore {
|
|
pub fn object_type(&self) -> TracingStoreType {
|
|
match self {
|
|
TracingStore::Disabled => TracingStoreType::Disabled,
|
|
TracingStore::Default => TracingStoreType::Default,
|
|
TracingStore::FoundationDb(_) => TracingStoreType::FoundationDb,
|
|
TracingStore::PostgreSql(_) => TracingStoreType::PostgreSql,
|
|
TracingStore::MySql(_) => TracingStoreType::MySql,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl UserAccount {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.name;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Name));
|
|
}
|
|
let value = &self.domain_id;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::DomainId));
|
|
}
|
|
let value = &self.credentials;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
let value = &self.created_at;
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::invalid(Property::CreatedAt, value));
|
|
}
|
|
let value = &self.member_group_ids;
|
|
for value in value.iter() {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberGroupIds));
|
|
}
|
|
}
|
|
if let Some(value) = &self.member_tenant_id {
|
|
if !value.is_valid() {
|
|
errors.push(ValidationError::required(Property::MemberTenantId));
|
|
}
|
|
}
|
|
let value = &self.roles;
|
|
value.validate(errors);
|
|
let value = &self.permissions;
|
|
value.validate(errors);
|
|
let value = &self.aliases;
|
|
for value in value.values() {
|
|
value.validate(errors);
|
|
}
|
|
if let Some(value) = &self.description {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Description));
|
|
}
|
|
}
|
|
let value = &self.encryption_at_rest;
|
|
value.validate(errors);
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
i.unique_global_composite(Property::Email, &self.name, &self.domain_id);
|
|
i.text(Property::Text, &self.name);
|
|
i.search(Property::Name, &self.name);
|
|
i.foreign_key(ObjectType::Domain, self.domain_id.into(), None);
|
|
i.search(Property::DomainId, &self.domain_id);
|
|
for id in self.member_group_ids.iter() {
|
|
i.foreign_key(
|
|
ObjectType::Account,
|
|
Some(*id),
|
|
Some(AccountType::Group.to_id()),
|
|
);
|
|
}
|
|
for value in self.member_group_ids.iter() {
|
|
i.search(Property::MemberGroupIds, value);
|
|
}
|
|
i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None);
|
|
if let Some(value) = &self.member_tenant_id {
|
|
i.search(Property::MemberTenantId, value);
|
|
}
|
|
self.roles.index(i);
|
|
for item in self.aliases.values() {
|
|
item.index(i);
|
|
}
|
|
if let Some(value) = &self.description {
|
|
i.text(Property::Text, value);
|
|
}
|
|
self.encryption_at_rest.index(i);
|
|
}
|
|
}
|
|
|
|
impl Pickle for UserAccount {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.name.pickle(out);
|
|
self.domain_id.pickle(out);
|
|
self.credentials.pickle(out);
|
|
self.created_at.pickle(out);
|
|
self.member_group_ids.pickle(out);
|
|
self.member_tenant_id.pickle(out);
|
|
self.roles.pickle(out);
|
|
self.permissions.pickle(out);
|
|
self.quotas.pickle(out);
|
|
self.aliases.pickle(out);
|
|
self.description.pickle(out);
|
|
self.locale.pickle(out);
|
|
self.time_zone.pickle(out);
|
|
self.encryption_at_rest.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.name = Pickle::unpickle(stream)?;
|
|
this.domain_id = Pickle::unpickle(stream)?;
|
|
this.credentials = Pickle::unpickle(stream)?;
|
|
this.created_at = Pickle::unpickle(stream)?;
|
|
this.member_group_ids = Pickle::unpickle(stream)?;
|
|
this.member_tenant_id = Pickle::unpickle(stream)?;
|
|
this.roles = Pickle::unpickle(stream)?;
|
|
this.permissions = Pickle::unpickle(stream)?;
|
|
this.quotas = Pickle::unpickle(stream)?;
|
|
this.aliases = Pickle::unpickle(stream)?;
|
|
this.description = Pickle::unpickle(stream)?;
|
|
this.locale = Pickle::unpickle(stream)?;
|
|
this.time_zone = Pickle::unpickle(stream)?;
|
|
this.encryption_at_rest = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for UserAccount {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
domain_id: Default::default(),
|
|
credentials: Default::default(),
|
|
created_at: Default::default(),
|
|
member_group_ids: Default::default(),
|
|
member_tenant_id: Default::default(),
|
|
roles: Default::default(),
|
|
permissions: Default::default(),
|
|
quotas: Default::default(),
|
|
aliases: Default::default(),
|
|
description: Default::default(),
|
|
locale: Locale::EnUS,
|
|
time_zone: Default::default(),
|
|
encryption_at_rest: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for UserAccount {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(16);
|
|
map.insert_unchecked(Property::Name, self.name.into_value());
|
|
map.insert_unchecked(Property::DomainId, self.domain_id.into_value());
|
|
map.insert_unchecked(Property::Credentials, self.credentials.into_value());
|
|
map.insert_unchecked(Property::CreatedAt, self.created_at.into_value());
|
|
map.insert_unchecked(Property::MemberGroupIds, self.member_group_ids.into_value());
|
|
map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value());
|
|
map.insert_unchecked(Property::Roles, self.roles.into_value());
|
|
map.insert_unchecked(Property::Permissions, self.permissions.into_value());
|
|
map.insert_unchecked(Property::Quotas, self.quotas.into_value());
|
|
map.insert_unchecked(Property::Aliases, self.aliases.into_value());
|
|
map.insert_unchecked(Property::Description, self.description.into_value());
|
|
map.insert_unchecked(Property::Locale, self.locale.into_value());
|
|
map.insert_unchecked(Property::TimeZone, self.time_zone.into_value());
|
|
map.insert_unchecked(
|
|
Property::EncryptionAtRest,
|
|
self.encryption_at_rest.into_value(),
|
|
);
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for UserAccount {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Name) => self.name.patch(
|
|
pointer.with_validators(&[StringValidator::EmailLocalPart]),
|
|
value,
|
|
),
|
|
Some(Property::DomainId) => self.domain_id.patch(pointer, value),
|
|
Some(Property::EmailAddress) => pointer.assert_server_set(),
|
|
Some(Property::Credentials) => self.credentials.patch(pointer, value),
|
|
Some(Property::CreatedAt) => pointer.assert_server_set(),
|
|
Some(Property::MemberGroupIds) => self.member_group_ids.patch(pointer, value),
|
|
Some(Property::MemberTenantId) => self
|
|
.member_tenant_id
|
|
.patch(pointer.assert_can_set_tenant()?, value),
|
|
Some(Property::Roles) => self.roles.patch(pointer, value),
|
|
Some(Property::Permissions) => self.permissions.patch(pointer, value),
|
|
Some(Property::Quotas) => self.quotas.patch(pointer, value),
|
|
Some(Property::UsedDiskQuota) => pointer.assert_server_set(),
|
|
Some(Property::Aliases) => self.aliases.patch(pointer, value),
|
|
Some(Property::Description) => self.description.patch(pointer, value),
|
|
Some(Property::Locale) => self.locale.patch(pointer, value),
|
|
Some(Property::TimeZone) => self.time_zone.patch(pointer, value),
|
|
Some(Property::EncryptionAtRest) => self.encryption_at_rest.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl UserRoles {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
match self {
|
|
UserRoles::User => true,
|
|
UserRoles::Admin => true,
|
|
UserRoles::Custom(inner) => inner.validate(errors),
|
|
}
|
|
}
|
|
|
|
fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) {
|
|
match self {
|
|
UserRoles::User => {}
|
|
UserRoles::Admin => {}
|
|
UserRoles::Custom(object) => {
|
|
object.index(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for UserRoles {
|
|
fn default() -> Self {
|
|
UserRoles::User
|
|
}
|
|
}
|
|
|
|
impl Pickle for UserRoles {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
match self {
|
|
UserRoles::User => {
|
|
0u16.pickle(out);
|
|
}
|
|
UserRoles::Admin => {
|
|
1u16.pickle(out);
|
|
}
|
|
UserRoles::Custom(inner) => {
|
|
2u16.pickle(out);
|
|
inner.pickle(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
match u16::unpickle(stream)? {
|
|
0 => Some(UserRoles::User),
|
|
1 => Some(UserRoles::Admin),
|
|
2 => Pickle::unpickle(stream).map(UserRoles::Custom),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for UserRoles {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
match self {
|
|
UserRoles::User => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("User".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
UserRoles::Admin => {
|
|
let mut obj = jmap_tools::Map::new();
|
|
obj.insert_unchecked(Property::Type, JmapValue::Str("Admin".into()));
|
|
JmapValue::Object(obj)
|
|
}
|
|
UserRoles::Custom(obj) => {
|
|
let mut obj = obj.into_value();
|
|
obj.as_object_mut()
|
|
.unwrap()
|
|
.insert_unchecked(Property::Type, JmapValue::Str("Custom".into()));
|
|
obj
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPatch for UserRoles {
|
|
fn patch<'x>(
|
|
&mut self,
|
|
pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
if !pointer.has_next() {
|
|
match object_type(&pointer, &value)? {
|
|
UserRolesType::User => *self = UserRoles::User,
|
|
UserRolesType::Admin => *self = UserRoles::Admin,
|
|
UserRolesType::Custom => *self = UserRoles::Custom(Default::default()),
|
|
}
|
|
}
|
|
match self {
|
|
UserRoles::User => pointer.assert_eof(),
|
|
UserRoles::Admin => pointer.assert_eof(),
|
|
UserRoles::Custom(inner) => inner.patch(pointer, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl UserRoles {
|
|
pub fn object_type(&self) -> UserRolesType {
|
|
match self {
|
|
UserRoles::User => UserRolesType::User,
|
|
UserRoles::Admin => UserRolesType::Admin,
|
|
UserRoles::Custom(_) => UserRolesType::Custom,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for WebDav {
|
|
const FLAGS: u64 = OBJ_SINGLETON;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::WebDav;
|
|
|
|
fn validate(&self, _: &mut Vec<ValidationError>) -> bool {
|
|
true
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for WebDav {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.enable_assisted_discovery.pickle(out);
|
|
self.max_lock_timeout.pickle(out);
|
|
self.max_locks.pickle(out);
|
|
self.dead_property_max_size.pickle(out);
|
|
self.live_property_max_size.pickle(out);
|
|
self.request_max_size.pickle(out);
|
|
self.max_results.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.enable_assisted_discovery = Pickle::unpickle(stream)?;
|
|
this.max_lock_timeout = Pickle::unpickle(stream)?;
|
|
this.max_locks = Pickle::unpickle(stream)?;
|
|
this.dead_property_max_size = Pickle::unpickle(stream)?;
|
|
this.live_property_max_size = Pickle::unpickle(stream)?;
|
|
this.request_max_size = Pickle::unpickle(stream)?;
|
|
this.max_results = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for WebDav {
|
|
fn default() -> Self {
|
|
Self {
|
|
enable_assisted_discovery: true,
|
|
max_lock_timeout: Duration::from_millis(3600000),
|
|
max_locks: 10u64,
|
|
dead_property_max_size: Some(1024u64),
|
|
live_property_max_size: 250u64,
|
|
request_max_size: 26214400,
|
|
max_results: 2000u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for WebDav {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(9);
|
|
map.insert_unchecked(
|
|
Property::EnableAssistedDiscovery,
|
|
self.enable_assisted_discovery.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::MaxLockTimeout, self.max_lock_timeout.into_value());
|
|
map.insert_unchecked(Property::MaxLocks, self.max_locks.into_value());
|
|
map.insert_unchecked(
|
|
Property::DeadPropertyMaxSize,
|
|
self.dead_property_max_size.into_value(),
|
|
);
|
|
map.insert_unchecked(
|
|
Property::LivePropertyMaxSize,
|
|
self.live_property_max_size.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::RequestMaxSize, self.request_max_size.into_value());
|
|
map.insert_unchecked(Property::MaxResults, self.max_results.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for WebDav {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::EnableAssistedDiscovery) => {
|
|
self.enable_assisted_discovery.patch(pointer, value)
|
|
}
|
|
Some(Property::MaxLockTimeout) => self.max_lock_timeout.patch(pointer, value),
|
|
Some(Property::MaxLocks) => self.max_locks.patch(pointer, value),
|
|
Some(Property::DeadPropertyMaxSize) => {
|
|
self.dead_property_max_size.patch(pointer, value)
|
|
}
|
|
Some(Property::LivePropertyMaxSize) => {
|
|
self.live_property_max_size.patch(pointer, value)
|
|
}
|
|
Some(Property::RequestMaxSize) => self.request_max_size.patch(pointer, value),
|
|
Some(Property::MaxResults) => self.max_results.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ObjectImpl for WebHook {
|
|
const FLAGS: u64 = 0;
|
|
const VERSION: u8 = 0;
|
|
const OBJECT: ObjectType = ObjectType::WebHook;
|
|
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.signature_key;
|
|
value.validate(errors);
|
|
let value = &self.url;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Url));
|
|
}
|
|
let value = &self.http_auth;
|
|
value.validate(errors);
|
|
let value = &self.http_headers;
|
|
for value in value.values() {
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::HttpHeaders));
|
|
}
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
|
|
fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {}
|
|
}
|
|
|
|
impl Pickle for WebHook {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.allow_invalid_certs.pickle(out);
|
|
self.signature_key.pickle(out);
|
|
self.throttle.pickle(out);
|
|
self.timeout.pickle(out);
|
|
self.discard_after.pickle(out);
|
|
self.url.pickle(out);
|
|
self.http_auth.pickle(out);
|
|
self.http_headers.pickle(out);
|
|
self.enable.pickle(out);
|
|
self.level.pickle(out);
|
|
self.lossy.pickle(out);
|
|
self.events.pickle(out);
|
|
self.events_policy.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.allow_invalid_certs = Pickle::unpickle(stream)?;
|
|
this.signature_key = Pickle::unpickle(stream)?;
|
|
this.throttle = Pickle::unpickle(stream)?;
|
|
this.timeout = Pickle::unpickle(stream)?;
|
|
this.discard_after = Pickle::unpickle(stream)?;
|
|
this.url = Pickle::unpickle(stream)?;
|
|
this.http_auth = Pickle::unpickle(stream)?;
|
|
this.http_headers = Pickle::unpickle(stream)?;
|
|
this.enable = Pickle::unpickle(stream)?;
|
|
this.level = Pickle::unpickle(stream)?;
|
|
this.lossy = Pickle::unpickle(stream)?;
|
|
this.events = Pickle::unpickle(stream)?;
|
|
this.events_policy = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for WebHook {
|
|
fn default() -> Self {
|
|
Self {
|
|
allow_invalid_certs: false,
|
|
signature_key: Default::default(),
|
|
throttle: Duration::from_millis(1000),
|
|
timeout: Duration::from_millis(30000),
|
|
discard_after: Duration::from_millis(300000),
|
|
url: Default::default(),
|
|
http_auth: Default::default(),
|
|
http_headers: Default::default(),
|
|
enable: true,
|
|
level: TracingLevel::Info,
|
|
lossy: false,
|
|
events: Default::default(),
|
|
events_policy: EventPolicy::Exclude,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for WebHook {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(15);
|
|
map.insert_unchecked(
|
|
Property::AllowInvalidCerts,
|
|
self.allow_invalid_certs.into_value(),
|
|
);
|
|
map.insert_unchecked(Property::SignatureKey, self.signature_key.into_value());
|
|
map.insert_unchecked(Property::Throttle, self.throttle.into_value());
|
|
map.insert_unchecked(Property::Timeout, self.timeout.into_value());
|
|
map.insert_unchecked(Property::DiscardAfter, self.discard_after.into_value());
|
|
map.insert_unchecked(Property::Url, self.url.into_value());
|
|
map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value());
|
|
map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value());
|
|
map.insert_unchecked(Property::Enable, self.enable.into_value());
|
|
map.insert_unchecked(Property::Level, self.level.into_value());
|
|
map.insert_unchecked(Property::Lossy, self.lossy.into_value());
|
|
map.insert_unchecked(Property::Events, self.events.into_value());
|
|
map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for WebHook {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value),
|
|
Some(Property::SignatureKey) => self.signature_key.patch(pointer, value),
|
|
Some(Property::Throttle) => self.throttle.patch(pointer, value),
|
|
Some(Property::Timeout) => self.timeout.patch(pointer, value),
|
|
Some(Property::DiscardAfter) => self.discard_after.patch(pointer, value),
|
|
Some(Property::Url) => self
|
|
.url
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::HttpAuth) => self.http_auth.patch(pointer, value),
|
|
Some(Property::HttpHeaders) => self
|
|
.http_headers
|
|
.patch(pointer.with_validators(&[StringValidator::Trim]), value),
|
|
Some(Property::Enable) => self.enable.patch(pointer, value),
|
|
Some(Property::Level) => self.level.patch(pointer, value),
|
|
Some(Property::Lossy) => self.lossy.patch(pointer, value),
|
|
Some(Property::Events) => self.events.patch(pointer, value),
|
|
Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ZenohCoordinator {
|
|
fn validate(&self, errors: &mut Vec<ValidationError>) -> bool {
|
|
let neb = errors.len();
|
|
let value = &self.config;
|
|
if value.is_empty() {
|
|
errors.push(ValidationError::required(Property::Config));
|
|
}
|
|
errors.len() == neb
|
|
}
|
|
}
|
|
|
|
impl Pickle for ZenohCoordinator {
|
|
fn pickle(&self, out: &mut Vec<u8>) {
|
|
self.config.pickle(out);
|
|
}
|
|
|
|
fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option<Self> {
|
|
let mut this = Self::default();
|
|
this.config = Pickle::unpickle(stream)?;
|
|
Some(this)
|
|
}
|
|
}
|
|
|
|
impl Default for ZenohCoordinator {
|
|
fn default() -> Self {
|
|
Self {
|
|
config: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoValue for ZenohCoordinator {
|
|
fn into_value(self) -> JmapValue<'static> {
|
|
let mut map = jmap_tools::Map::with_capacity(3);
|
|
map.insert_unchecked(Property::Config, self.config.into_value());
|
|
JmapValue::Object(map)
|
|
}
|
|
}
|
|
|
|
impl RegistryJsonPropertyPatch for ZenohCoordinator {
|
|
fn patch_property<'x>(
|
|
&mut self,
|
|
mut pointer: JsonPointerPatch<'_>,
|
|
value: JmapValue<'x>,
|
|
) -> PatchResult<'x> {
|
|
match pointer.next_property() {
|
|
Some(Property::Config) => self.config.patch(pointer, value),
|
|
Some(Property::Type) => Ok(MaybeUnpatched::Unpatched {
|
|
property: Property::Type,
|
|
value,
|
|
}),
|
|
_ => Err(PatchError::new(pointer, "Invalid property")),
|
|
}
|
|
}
|
|
}
|