mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 16:31:10 +00:00
edits federating, need tests and api adjustments
This commit is contained in:
parent
c48f26c908
commit
afbb81c0d1
9 changed files with 60 additions and 21 deletions
|
@ -6,7 +6,6 @@ use crate::federation::activities::create_or_update_article::{
|
||||||
};
|
};
|
||||||
use crate::federation::objects::article::DbArticle;
|
use crate::federation::objects::article::DbArticle;
|
||||||
use crate::federation::objects::instance::DbInstance;
|
use crate::federation::objects::instance::DbInstance;
|
||||||
use crate::utils::generate_object_id;
|
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
use activitypub_federation::fetch::object_id::ObjectId;
|
use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
@ -41,7 +40,13 @@ async fn create_article(
|
||||||
Form(create_article): Form<CreateArticle>,
|
Form(create_article): Form<CreateArticle>,
|
||||||
) -> MyResult<Json<DbArticle>> {
|
) -> MyResult<Json<DbArticle>> {
|
||||||
let local_instance_id = data.local_instance().ap_id;
|
let local_instance_id = data.local_instance().ap_id;
|
||||||
let ap_id = generate_object_id(local_instance_id.inner())?.into();
|
let ap_id = Url::parse(&format!(
|
||||||
|
"http://{}:{}/article/{}",
|
||||||
|
local_instance_id.inner().domain().unwrap(),
|
||||||
|
local_instance_id.inner().port().unwrap(),
|
||||||
|
create_article.title
|
||||||
|
))?
|
||||||
|
.into();
|
||||||
let article = DbArticle {
|
let article = DbArticle {
|
||||||
title: create_article.title,
|
title: create_article.title,
|
||||||
text: create_article.text,
|
text: create_article.text,
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub mod routes;
|
||||||
|
|
||||||
pub async fn federation_config(hostname: &str) -> Result<FederationConfig<DatabaseHandle>, Error> {
|
pub async fn federation_config(hostname: &str) -> Result<FederationConfig<DatabaseHandle>, Error> {
|
||||||
let ap_id = Url::parse(&format!("http://{}", hostname))?.into();
|
let ap_id = Url::parse(&format!("http://{}", hostname))?.into();
|
||||||
let articles_id = Url::parse(&format!("http://{}/articles", hostname))?.into();
|
let articles_id = Url::parse(&format!("http://{}/all_articles", hostname))?.into();
|
||||||
let inbox = Url::parse(&format!("http://{}/inbox", hostname))?;
|
let inbox = Url::parse(&format!("http://{}/inbox", hostname))?;
|
||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
let local_instance = DbInstance {
|
let local_instance = DbInstance {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::MyResult;
|
use crate::error::MyResult;
|
||||||
use crate::federation::objects::edit::DbEdit;
|
use crate::federation::objects::edit::DbEdit;
|
||||||
use crate::federation::objects::edits_collection::{ApubEditCollection, DbEditCollection};
|
use crate::federation::objects::edits_collection::DbEditCollection;
|
||||||
use crate::federation::objects::instance::DbInstance;
|
use crate::federation::objects::instance::DbInstance;
|
||||||
use crate::{database::DatabaseHandle, error::Error};
|
use crate::{database::DatabaseHandle, error::Error};
|
||||||
use activitypub_federation::fetch::collection_id::CollectionId;
|
use activitypub_federation::fetch::collection_id::CollectionId;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::database::DatabaseHandle;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::federation::objects::article::{ApubArticle, DbArticle};
|
use crate::federation::objects::article::{ApubArticle, DbArticle};
|
||||||
use crate::federation::objects::instance::DbInstance;
|
use crate::federation::objects::instance::DbInstance;
|
||||||
use crate::utils::generate_object_id;
|
|
||||||
use activitypub_federation::kinds::collection::CollectionType;
|
use activitypub_federation::kinds::collection::CollectionType;
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -37,25 +37,28 @@ impl Object for DbEdit {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
object_id: Url,
|
_object_id: Url,
|
||||||
data: &Data<Self::DataType>,
|
_data: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
_json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
_expected_domain: &Url,
|
||||||
data: &Data<Self::DataType>,
|
_data: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(
|
||||||
|
_json: Self::Kind,
|
||||||
|
_data: &Data<Self::DataType>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use crate::database::DatabaseHandle;
|
use crate::database::DatabaseHandle;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::federation::objects::article::{ApubArticle, DbArticle};
|
use crate::federation::objects::article::DbArticle;
|
||||||
use crate::federation::objects::edit::{ApubEdit, DbEdit};
|
use crate::federation::objects::edit::{ApubEdit, DbEdit};
|
||||||
use crate::federation::objects::instance::DbInstance;
|
|
||||||
use crate::utils::generate_object_id;
|
use activitypub_federation::kinds::collection::OrderedCollectionType;
|
||||||
use activitypub_federation::kinds::collection::{CollectionType, OrderedCollectionType};
|
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
traits::{Collection, Object},
|
traits::{Collection, Object},
|
||||||
|
@ -75,7 +74,7 @@ impl Collection for DbEditCollection {
|
||||||
let edits =
|
let edits =
|
||||||
try_join_all(apub.items.into_iter().map(|i| DbEdit::from_json(i, data))).await?;
|
try_join_all(apub.items.into_iter().map(|i| DbEdit::from_json(i, data))).await?;
|
||||||
let mut articles = data.articles.lock().unwrap();
|
let mut articles = data.articles.lock().unwrap();
|
||||||
let mut article = articles.get_mut(owner.ap_id.inner()).unwrap();
|
let article = articles.get_mut(owner.ap_id.inner()).unwrap();
|
||||||
for e in edits.clone() {
|
for e in edits.clone() {
|
||||||
// TODO: edits need a unique id to avoid pushing duplicates
|
// TODO: edits need a unique id to avoid pushing duplicates
|
||||||
article.edits.push(e);
|
article.edits.push(e);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::error::{Error, MyResult};
|
use crate::error::Error;
|
||||||
use crate::federation::objects::articles_collection::DbArticleCollection;
|
use crate::federation::objects::articles_collection::DbArticleCollection;
|
||||||
use crate::{database::DatabaseHandle, federation::activities::follow::Follow};
|
use crate::{database::DatabaseHandle, federation::activities::follow::Follow};
|
||||||
use activitypub_federation::activity_sending::SendActivityTask;
|
use activitypub_federation::activity_sending::SendActivityTask;
|
||||||
|
|
|
@ -10,9 +10,12 @@ use activitypub_federation::config::Data;
|
||||||
use activitypub_federation::protocol::context::WithContext;
|
use activitypub_federation::protocol::context::WithContext;
|
||||||
use activitypub_federation::traits::Object;
|
use activitypub_federation::traits::Object;
|
||||||
use activitypub_federation::traits::{ActivityHandler, Collection};
|
use activitypub_federation::traits::{ActivityHandler, Collection};
|
||||||
|
use axum::extract::Path;
|
||||||
|
|
||||||
use crate::federation::activities::create_or_update_article::CreateOrUpdateArticle;
|
use crate::federation::activities::create_or_update_article::CreateOrUpdateArticle;
|
||||||
|
use crate::federation::objects::article::ApubArticle;
|
||||||
use crate::federation::objects::articles_collection::{ArticleCollection, DbArticleCollection};
|
use crate::federation::objects::articles_collection::{ArticleCollection, DbArticleCollection};
|
||||||
|
use crate::federation::objects::edits_collection::{ApubEditCollection, DbEditCollection};
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::routing::{get, post};
|
use axum::routing::{get, post};
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
@ -23,7 +26,9 @@ use url::Url;
|
||||||
pub fn federation_routes() -> Router {
|
pub fn federation_routes() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", get(http_get_instance))
|
.route("/", get(http_get_instance))
|
||||||
.route("/articles", get(http_get_articles))
|
.route("/all_articles", get(http_get_all_articles))
|
||||||
|
.route("/article/:title", get(http_get_article))
|
||||||
|
.route("/article/:title/edits", get(http_get_article_edits))
|
||||||
.route("/inbox", post(http_post_inbox))
|
.route("/inbox", post(http_post_inbox))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +42,39 @@ async fn http_get_instance(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_articles(
|
async fn http_get_all_articles(
|
||||||
data: Data<DatabaseHandle>,
|
data: Data<DatabaseHandle>,
|
||||||
) -> MyResult<FederationJson<WithContext<ArticleCollection>>> {
|
) -> MyResult<FederationJson<WithContext<ArticleCollection>>> {
|
||||||
let collection = DbArticleCollection::read_local(&data.local_instance(), &data).await?;
|
let collection = DbArticleCollection::read_local(&data.local_instance(), &data).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(collection)))
|
Ok(FederationJson(WithContext::new_default(collection)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn http_get_article(
|
||||||
|
Path(title): Path<String>,
|
||||||
|
data: Data<DatabaseHandle>,
|
||||||
|
) -> MyResult<FederationJson<WithContext<ApubArticle>>> {
|
||||||
|
let article = {
|
||||||
|
let lock = data.articles.lock().unwrap();
|
||||||
|
lock.values().find(|a| a.title == title).unwrap().clone()
|
||||||
|
};
|
||||||
|
let json = article.into_json(&data).await?;
|
||||||
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn http_get_article_edits(
|
||||||
|
Path(title): Path<String>,
|
||||||
|
data: Data<DatabaseHandle>,
|
||||||
|
) -> MyResult<FederationJson<WithContext<ApubEditCollection>>> {
|
||||||
|
let article = {
|
||||||
|
let lock = data.articles.lock().unwrap();
|
||||||
|
lock.values().find(|a| a.title == title).unwrap().clone()
|
||||||
|
};
|
||||||
|
let json = DbEditCollection::read_local(&article, &data).await?;
|
||||||
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
|
}
|
||||||
|
|
||||||
/// List of all activities which this actor can receive.
|
/// List of all activities which this actor can receive.
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
|
|
@ -4,11 +4,12 @@ use url::{ParseError, Url};
|
||||||
/// Just generate random url as object id. In a real project, you probably want to use
|
/// Just generate random url as object id. In a real project, you probably want to use
|
||||||
/// an url which contains the database id for easy retrieval (or store the random id in db).
|
/// an url which contains the database id for easy retrieval (or store the random id in db).
|
||||||
pub fn generate_object_id(domain: &Url) -> Result<Url, ParseError> {
|
pub fn generate_object_id(domain: &Url) -> Result<Url, ParseError> {
|
||||||
|
let port = domain.port().unwrap();
|
||||||
let domain = domain.domain().unwrap();
|
let domain = domain.domain().unwrap();
|
||||||
let id: String = thread_rng()
|
let id: String = thread_rng()
|
||||||
.sample_iter(&Alphanumeric)
|
.sample_iter(&Alphanumeric)
|
||||||
.take(7)
|
.take(7)
|
||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect();
|
.collect();
|
||||||
Url::parse(&format!("http://{}/objects/{}", domain, id))
|
Url::parse(&format!("http://{}:{}/objects/{}", domain,port, id))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue