feat(calendar,addressbook): migrate share to authz engine
migrate DB entries to authz engine
and wire authz engine to caldav and carddav
This commit is contained in:
@@ -7,10 +7,100 @@ use crate::application::dtos::contact_dto::{
|
||||
GroupMembershipDto, UpdateContactDto, UpdateContactGroupDto,
|
||||
};
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::domain::entities::contact::{AddressBook, Contact, ContactGroup};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub type CardDavRepositoryError = DomainError;
|
||||
|
||||
/// Low-level storage port for CardDAV resources. Post-Round-3 the
|
||||
/// port covers ONLY raw storage operations — everything that used
|
||||
/// to be routed through it for sharing (`share_address_book`,
|
||||
/// `unshare_address_book`, `get_address_book_shares`) or
|
||||
/// scope-listing (`get_address_books_by_owner`,
|
||||
/// `get_shared_address_books`) is gone. Access decisions live in
|
||||
/// `AuthorizationEngine`; sharing state lives in
|
||||
/// `storage.role_grants`. The service layer (`ContactService`) gates
|
||||
/// each call, then reaches through this port for storage.
|
||||
///
|
||||
/// Symmetric with `CalendarStoragePort`. Implemented by
|
||||
/// `ContactStorageAdapter` against Postgres today; a future backend
|
||||
/// (external CardDAV, LDAP directory, in-memory test mock) would
|
||||
/// implement the same trait and swap in via DI.
|
||||
pub trait ContactStoragePort: Send + Sync + 'static {
|
||||
// ── Address books ────────────────────────────────────────────
|
||||
async fn create_address_book(
|
||||
&self,
|
||||
address_book: AddressBook,
|
||||
) -> Result<AddressBook, DomainError>;
|
||||
async fn update_address_book(
|
||||
&self,
|
||||
address_book: AddressBook,
|
||||
) -> Result<AddressBook, DomainError>;
|
||||
async fn delete_address_book(&self, id: &Uuid) -> Result<(), DomainError>;
|
||||
async fn get_address_book_by_id(&self, id: &Uuid) -> Result<Option<AddressBook>, DomainError>;
|
||||
async fn get_public_address_books(&self) -> Result<Vec<AddressBook>, DomainError>;
|
||||
|
||||
// ── Contacts ─────────────────────────────────────────────────
|
||||
async fn create_contact(&self, contact: Contact) -> Result<Contact, DomainError>;
|
||||
async fn update_contact(&self, contact: Contact) -> Result<Contact, DomainError>;
|
||||
async fn delete_contact(&self, id: &Uuid) -> Result<(), DomainError>;
|
||||
async fn get_contact_by_id(&self, id: &Uuid) -> Result<Option<Contact>, DomainError>;
|
||||
/// Indexed single-row lookup by vCard UID within a specific book.
|
||||
async fn get_contact_by_uid(
|
||||
&self,
|
||||
address_book_id: &Uuid,
|
||||
uid: &str,
|
||||
) -> Result<Option<Contact>, DomainError>;
|
||||
/// Indexed batch lookup by vCard UID within a specific book.
|
||||
async fn get_contacts_by_uids(
|
||||
&self,
|
||||
address_book_id: &Uuid,
|
||||
uids: &[String],
|
||||
) -> Result<Vec<Contact>, DomainError>;
|
||||
async fn get_contacts_by_address_book(
|
||||
&self,
|
||||
address_book_id: &Uuid,
|
||||
) -> Result<Vec<Contact>, DomainError>;
|
||||
async fn get_contacts_by_address_book_paginated(
|
||||
&self,
|
||||
address_book_id: &Uuid,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> Result<Vec<Contact>, DomainError>;
|
||||
async fn search_contacts(
|
||||
&self,
|
||||
address_book_id: &Uuid,
|
||||
query: &str,
|
||||
) -> Result<Vec<Contact>, DomainError>;
|
||||
|
||||
// ── Contact groups ───────────────────────────────────────────
|
||||
async fn create_group(&self, group: ContactGroup) -> Result<ContactGroup, DomainError>;
|
||||
async fn update_group(&self, group: ContactGroup) -> Result<ContactGroup, DomainError>;
|
||||
async fn delete_group(&self, id: &Uuid) -> Result<(), DomainError>;
|
||||
async fn get_group_by_id(&self, id: &Uuid) -> Result<Option<ContactGroup>, DomainError>;
|
||||
async fn get_groups_by_address_book(
|
||||
&self,
|
||||
address_book_id: &Uuid,
|
||||
) -> Result<Vec<ContactGroup>, DomainError>;
|
||||
|
||||
// ── Group membership ─────────────────────────────────────────
|
||||
async fn add_contact_to_group(
|
||||
&self,
|
||||
group_id: &Uuid,
|
||||
contact_id: &Uuid,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn remove_contact_from_group(
|
||||
&self,
|
||||
group_id: &Uuid,
|
||||
contact_id: &Uuid,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_contacts_in_group(&self, group_id: &Uuid) -> Result<Vec<Contact>, DomainError>;
|
||||
async fn get_groups_for_contact(
|
||||
&self,
|
||||
contact_id: &Uuid,
|
||||
) -> Result<Vec<ContactGroup>, DomainError>;
|
||||
}
|
||||
|
||||
pub trait AddressBookUseCase: Send + Sync + 'static {
|
||||
// Address Book operations
|
||||
async fn create_address_book(
|
||||
|
||||
Reference in New Issue
Block a user