mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 22:52:22 +00:00
Checkpoint: Migration to axum
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
use crate::Error;
|
||||
use actix_web::web::Path;
|
||||
use actix_web::{HttpResponse, web::Data};
|
||||
use rustical_store::{Addressbook, AddressbookStore, auth::User};
|
||||
use crate::{Error, addressbook::resource::AddressbookResourceService};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use http::StatusCode;
|
||||
use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore, auth::User};
|
||||
use rustical_xml::{XmlDeserialize, XmlDocument, XmlRootTag};
|
||||
use tracing::instrument;
|
||||
use tracing_actix_web::RootSpan;
|
||||
|
||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||
pub struct Resourcetype {
|
||||
@@ -39,15 +41,13 @@ struct MkcolRequest {
|
||||
set: PropElement<MkcolAddressbookProp>,
|
||||
}
|
||||
|
||||
#[instrument(parent = root_span.id(), skip(store, root_span))]
|
||||
pub async fn route_mkcol<AS: AddressbookStore>(
|
||||
path: Path<(String, String)>,
|
||||
body: String,
|
||||
#[instrument(skip(addr_store))]
|
||||
pub async fn route_mkcol<AS: AddressbookStore, S: SubscriptionStore>(
|
||||
Path((principal, addressbook_id)): Path<(String, String)>,
|
||||
user: User,
|
||||
store: Data<AS>,
|
||||
root_span: RootSpan,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let (principal, addressbook_id) = path.into_inner();
|
||||
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
||||
body: String,
|
||||
) -> Result<Response, Error> {
|
||||
if !user.is_principal(&principal) {
|
||||
return Err(Error::Unauthorized);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ pub async fn route_mkcol<AS: AddressbookStore>(
|
||||
push_topic: uuid::Uuid::new_v4().to_string(),
|
||||
};
|
||||
|
||||
match store
|
||||
match addr_store
|
||||
.get_addressbook(&principal, &addressbook_id, true)
|
||||
.await
|
||||
{
|
||||
@@ -74,7 +74,11 @@ pub async fn route_mkcol<AS: AddressbookStore>(
|
||||
}
|
||||
Ok(_) => {
|
||||
// oh no, there's a conflict
|
||||
return Ok(HttpResponse::Conflict().body("An addressbook already exists at this URI"));
|
||||
return Ok((
|
||||
StatusCode::CONFLICT,
|
||||
"An addressbook already exists at this URI",
|
||||
)
|
||||
.into_response());
|
||||
}
|
||||
Err(err) => {
|
||||
// some other error
|
||||
@@ -82,12 +86,10 @@ pub async fn route_mkcol<AS: AddressbookStore>(
|
||||
}
|
||||
}
|
||||
|
||||
match store.insert_addressbook(addressbook).await {
|
||||
match addr_store.insert_addressbook(addressbook).await {
|
||||
// TODO: The spec says we should return a mkcol-response.
|
||||
// However, it works without one but breaks on iPadOS when using an empty one :)
|
||||
Ok(()) => Ok(HttpResponse::Created()
|
||||
.insert_header(("Cache-Control", "no-cache"))
|
||||
.body("")),
|
||||
Ok(()) => Ok(StatusCode::CREATED.into_response()),
|
||||
Err(err) => {
|
||||
dbg!(err.to_string());
|
||||
Err(err.into())
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub mod mkcol;
|
||||
pub mod post;
|
||||
// pub mod post;
|
||||
pub mod report;
|
||||
|
||||
@@ -4,8 +4,6 @@ use crate::{
|
||||
AddressObjectPropWrapper, AddressObjectPropWrapperName, AddressObjectResource,
|
||||
},
|
||||
};
|
||||
use actix_web::dev::{Path, ResourceDef};
|
||||
|
||||
use http::StatusCode;
|
||||
use rustical_dav::{
|
||||
resource::{PrincipalUri, Resource},
|
||||
@@ -32,27 +30,28 @@ pub async fn get_objects_addressbook_multiget<AS: AddressbookStore>(
|
||||
addressbook_id: &str,
|
||||
store: &AS,
|
||||
) -> Result<(Vec<AddressObject>, Vec<String>), Error> {
|
||||
let resource_def = ResourceDef::prefix(path).join(&ResourceDef::new("/{object_id}.vcf"));
|
||||
|
||||
let mut result = vec![];
|
||||
let mut not_found = vec![];
|
||||
|
||||
for href in &addressbook_multiget.href {
|
||||
let mut path = Path::new(href.as_str());
|
||||
if !resource_def.capture_match_info(&mut path) {
|
||||
if let Some(filename) = href.strip_prefix(path) {
|
||||
if let Some(object_id) = filename.strip_suffix(".vcf") {
|
||||
match store
|
||||
.get_object(principal, addressbook_id, object_id, false)
|
||||
.await
|
||||
{
|
||||
Ok(object) => result.push(object),
|
||||
Err(rustical_store::Error::NotFound) => not_found.push(href.to_owned()),
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
} else {
|
||||
not_found.push(href.to_owned());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
not_found.push(href.to_owned());
|
||||
continue;
|
||||
};
|
||||
let object_id = path.get("object_id").unwrap();
|
||||
match store
|
||||
.get_object(principal, addressbook_id, object_id, false)
|
||||
.await
|
||||
{
|
||||
Ok(object) => result.push(object),
|
||||
Err(rustical_store::Error::NotFound) => not_found.push(href.to_owned()),
|
||||
// TODO: Maybe add error handling on a per-object basis
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Ok((result, not_found))
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use crate::{CardDavPrincipalUri, Error, address_object::resource::AddressObjectPropWrapperName};
|
||||
use actix_web::{
|
||||
HttpRequest, Responder,
|
||||
web::{Data, Path},
|
||||
use crate::{
|
||||
CardDavPrincipalUri, Error, address_object::resource::AddressObjectPropWrapperName,
|
||||
addressbook::resource::AddressbookResourceService,
|
||||
};
|
||||
use addressbook_multiget::{AddressbookMultigetRequest, handle_addressbook_multiget};
|
||||
use axum::{
|
||||
Extension,
|
||||
extract::{OriginalUri, Path, State},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use rustical_dav::xml::{PropfindType, sync_collection::SyncCollectionRequest};
|
||||
use rustical_store::{AddressbookStore, auth::User};
|
||||
use rustical_store::{AddressbookStore, SubscriptionStore, auth::User};
|
||||
use rustical_xml::{XmlDeserialize, XmlDocument};
|
||||
use sync_collection::handle_sync_collection;
|
||||
use tracing::instrument;
|
||||
@@ -30,16 +34,15 @@ impl ReportRequest {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(req, addr_store))]
|
||||
pub async fn route_report_addressbook<AS: AddressbookStore>(
|
||||
path: Path<(String, String)>,
|
||||
body: String,
|
||||
#[instrument(skip(addr_store))]
|
||||
pub async fn route_report_addressbook<AS: AddressbookStore, S: SubscriptionStore>(
|
||||
Path((principal, addressbook_id)): Path<(String, String)>,
|
||||
user: User,
|
||||
req: HttpRequest,
|
||||
puri: Data<CardDavPrincipalUri>,
|
||||
addr_store: Data<AS>,
|
||||
) -> Result<impl Responder, Error> {
|
||||
let (principal, addressbook_id) = path.into_inner();
|
||||
OriginalUri(uri): OriginalUri,
|
||||
Extension(puri): Extension<CardDavPrincipalUri>,
|
||||
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
||||
body: String,
|
||||
) -> Result<impl IntoResponse, Error> {
|
||||
if !user.is_principal(&principal) {
|
||||
return Err(Error::Unauthorized);
|
||||
}
|
||||
@@ -51,8 +54,8 @@ pub async fn route_report_addressbook<AS: AddressbookStore>(
|
||||
handle_addressbook_multiget(
|
||||
addr_multiget,
|
||||
request.props(),
|
||||
req.path(),
|
||||
puri.as_ref(),
|
||||
uri.path(),
|
||||
&puri,
|
||||
&user,
|
||||
&principal,
|
||||
&addressbook_id,
|
||||
@@ -63,8 +66,8 @@ pub async fn route_report_addressbook<AS: AddressbookStore>(
|
||||
ReportRequest::SyncCollection(sync_collection) => {
|
||||
handle_sync_collection(
|
||||
sync_collection,
|
||||
req.path(),
|
||||
puri.as_ref(),
|
||||
uri.path(),
|
||||
&puri,
|
||||
&user,
|
||||
&principal,
|
||||
&addressbook_id,
|
||||
|
||||
Reference in New Issue
Block a user