/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use common::{Server, auth::AccessToken}; use jmap_proto::{ method::get::{GetRequest, GetResponse}, object::quota::{Quota, QuotaProperty, QuotaValue}, types::state::State, }; use jmap_tools::{Map, Value}; use std::{borrow::Cow, future::Future}; use trc::AddContext; use types::{id::Id, type_state::DataType}; pub trait QuotaGet: Sync + Send { fn quota_get( &self, request: GetRequest, access_token: &AccessToken, ) -> impl Future>> + Send; } impl QuotaGet for Server { async fn quota_get( &self, mut request: GetRequest, access_token: &AccessToken, ) -> trc::Result> { let (ids, not_found_ids) = request.unwrap_ids(self.core.jmap.get_max_objects)?; let properties = request.unwrap_properties(&[ QuotaProperty::Id, QuotaProperty::ResourceType, QuotaProperty::Used, QuotaProperty::WarnLimit, QuotaProperty::SoftLimit, QuotaProperty::HardLimit, QuotaProperty::Scope, QuotaProperty::Name, QuotaProperty::Description, QuotaProperty::Types, ]); let account_id = request.account_id.document_id(); let account = self.account(account_id).await.caused_by(trc::location!())?; let quota_ids = if account.disk_quota() > 0 { vec![0u32] } else { vec![] }; let ids = if let Some(ids) = ids { ids } else { quota_ids.iter().map(|id| Id::from(*id)).collect() }; let mut response = GetResponse { account_id: request.account_id.into(), state: State::Initial.into(), list: Vec::with_capacity(ids.len()), not_found: not_found_ids, }; let account = if account_id == access_token.account_id() { Cow::Borrowed(&account) } else { Cow::Owned(self.account(account_id).await.caused_by(trc::location!())?) }; for id in ids { // Obtain the sieve script object let document_id = id.document_id(); if !quota_ids.contains(&document_id) { response.push_not_found(id); continue; } let mut result = Map::with_capacity(properties.len()); for property in &properties { let value = match property { QuotaProperty::Id => Value::Element(id.into()), QuotaProperty::ResourceType => "octets".to_string().into(), QuotaProperty::Used => { (self.get_used_quota_account(account_id).await?.max(0) as u64).into() } QuotaProperty::HardLimit => account.as_ref().disk_quota().into(), QuotaProperty::Scope => "account".to_string().into(), QuotaProperty::Name => account.as_ref().name().to_string().into(), QuotaProperty::Description => account .as_ref() .description .as_ref() .map(|s| s.to_string()) .into(), QuotaProperty::Types => vec![ Value::Element(QuotaValue::Types(DataType::Email)), Value::Element(QuotaValue::Types(DataType::SieveScript)), Value::Element(QuotaValue::Types(DataType::FileNode)), Value::Element(QuotaValue::Types(DataType::CalendarEvent)), Value::Element(QuotaValue::Types(DataType::ContactCard)), ] .into(), _ => Value::Null, }; result.insert_unchecked(property.clone(), value); } response.list.push(result.into()); } Ok(response) } }