forked from alemi/upub
feat: process and store remote attachment urls
This commit is contained in:
parent
cd9d3f9db4
commit
c595f5f5e3
7 changed files with 154 additions and 2 deletions
66
src/migrations/m20240421_000001_add_attachments.rs
Normal file
66
src/migrations/m20240421_000001_add_attachments.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Attachments::Table)
|
||||
.col(
|
||||
ColumnDef::new(Attachments::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key()
|
||||
)
|
||||
.col(ColumnDef::new(Attachments::Url).string().not_null())
|
||||
.col(ColumnDef::new(Attachments::Object).string().not_null())
|
||||
.col(ColumnDef::new(Attachments::DocumentType).string().not_null())
|
||||
.col(ColumnDef::new(Attachments::Name).string().null())
|
||||
.col(ColumnDef::new(Attachments::MediaType).string().not_null())
|
||||
.col(ColumnDef::new(Attachments::Created).date_time().not_null())
|
||||
.to_owned()
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("attachment-object-index")
|
||||
.table(Attachments::Table)
|
||||
.col(Attachments::Object)
|
||||
.to_owned()
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Attachments::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_index(Index::drop().name("attachment-object-index").to_owned())
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Attachments {
|
||||
Table,
|
||||
Id,
|
||||
Url,
|
||||
Object,
|
||||
DocumentType,
|
||||
Name,
|
||||
MediaType,
|
||||
Created,
|
||||
}
|
|
@ -10,6 +10,7 @@ mod m20240324_000001_add_addressing;
|
|||
mod m20240325_000001_add_deliveries;
|
||||
mod m20240325_000002_add_system_key;
|
||||
mod m20240418_000001_add_statuses_and_reply_to;
|
||||
mod m20240421_000001_add_attachments;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
|
@ -27,6 +28,7 @@ impl MigratorTrait for Migrator {
|
|||
Box::new(m20240325_000001_add_deliveries::Migration),
|
||||
Box::new(m20240325_000002_add_system_key::Migration),
|
||||
Box::new(m20240418_000001_add_statuses_and_reply_to::Migration),
|
||||
Box::new(m20240421_000001_add_attachments::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
61
src/model/attachment.rs
Normal file
61
src/model/attachment.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use apb::{DocumentMut, ObjectMut};
|
||||
use sea_orm::{entity::prelude::*, Set};
|
||||
|
||||
use crate::routes::activitypub::jsonld::LD;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "attachments")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i64,
|
||||
|
||||
pub url: String,
|
||||
pub object: String,
|
||||
pub document_type: apb::DocumentType,
|
||||
pub name: Option<String>,
|
||||
pub media_type: String,
|
||||
pub created: ChronoDateTimeUtc,
|
||||
}
|
||||
|
||||
impl ActiveModel {
|
||||
pub fn new(document: &impl apb::Document, object: String) -> Result<ActiveModel, super::FieldError> {
|
||||
Ok(ActiveModel {
|
||||
id: sea_orm::ActiveValue::NotSet,
|
||||
object: Set(object),
|
||||
url: Set(document.url().id().ok_or(super::FieldError("url"))?),
|
||||
document_type: Set(document.document_type().ok_or(super::FieldError("type"))?),
|
||||
media_type: Set(document.media_type().ok_or(super::FieldError("mediaType"))?.to_string()),
|
||||
name: Set(document.name().map(|x| x.to_string())),
|
||||
created: Set(document.published().unwrap_or(chrono::Utc::now())),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Model {
|
||||
pub fn ap(self) -> serde_json::Value {
|
||||
serde_json::Value::new_object()
|
||||
.set_url(apb::Node::link(self.url))
|
||||
.set_document_type(Some(self.document_type))
|
||||
.set_media_type(Some(&self.media_type))
|
||||
.set_name(self.name.as_deref())
|
||||
.set_published(Some(self.created))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(
|
||||
belongs_to = "super::object::Entity",
|
||||
from = "Column::Object",
|
||||
to = "super::object::Column::Id"
|
||||
)]
|
||||
Object,
|
||||
}
|
||||
|
||||
impl Related<super::object::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Object.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -10,6 +10,7 @@ pub mod like;
|
|||
pub mod credential;
|
||||
pub mod session;
|
||||
pub mod delivery;
|
||||
pub mod attachment;
|
||||
pub mod application;
|
||||
|
||||
#[cfg(feature = "faker")]
|
||||
|
|
|
@ -48,7 +48,7 @@ impl Model {
|
|||
bcc: object.bcc().into(),
|
||||
})
|
||||
}
|
||||
// TODO this is used outside /routes, maybe move in model?
|
||||
|
||||
pub fn ap(self) -> serde_json::Value {
|
||||
serde_json::Value::new_object()
|
||||
.set_id(Some(&self.id))
|
||||
|
@ -81,6 +81,9 @@ pub enum Relation {
|
|||
|
||||
#[sea_orm(has_many = "super::addressing::Entity")]
|
||||
Addressing,
|
||||
|
||||
#[sea_orm(has_many = "super::attachment::Entity")]
|
||||
Attachment,
|
||||
}
|
||||
|
||||
impl Related<super::activity::Entity> for Entity {
|
||||
|
@ -101,4 +104,10 @@ impl Related<super::addressing::Entity> for Entity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Related<super::attachment::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Attachment.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use apb::target::Addressed;
|
||||
use apb::{target::Addressed, Object};
|
||||
use base64::Engine;
|
||||
use reqwest::{header::{ACCEPT, CONTENT_TYPE, USER_AGENT}, Method, Response};
|
||||
use sea_orm::{EntityTrait, IntoActiveModel};
|
||||
|
@ -131,6 +131,13 @@ impl Fetcher for Context {
|
|||
let addressed = object.addressed();
|
||||
let object_model = model::object::Model::new(&object)?;
|
||||
|
||||
for attachment in object.attachment() {
|
||||
let attachment_model = model::attachment::ActiveModel::new(&attachment, object_model.id.clone())?;
|
||||
model::attachment::Entity::insert(attachment_model)
|
||||
.exec(self.db())
|
||||
.await?;
|
||||
}
|
||||
|
||||
let expanded_addresses = self.expand_addressing(addressed).await?;
|
||||
self.address_to(None, Some(&object_model.id), &expanded_addresses).await?;
|
||||
|
||||
|
|
|
@ -33,6 +33,12 @@ impl apb::server::Inbox for Context {
|
|||
let oid = object_model.id.clone();
|
||||
model::object::Entity::insert(object_model.into_active_model()).exec(self.db()).await?;
|
||||
model::activity::Entity::insert(activity_model.into_active_model()).exec(self.db()).await?;
|
||||
for attachment in object_node.attachment() {
|
||||
let attachment_model = model::attachment::ActiveModel::new(&attachment, oid.clone())?;
|
||||
model::attachment::Entity::insert(attachment_model)
|
||||
.exec(self.db())
|
||||
.await?;
|
||||
}
|
||||
let expanded_addressing = self.expand_addressing(activity.addressed()).await?;
|
||||
self.address_to(Some(&aid), Some(&oid), &expanded_addressing).await?;
|
||||
tracing::info!("{} posted {}", aid, oid);
|
||||
|
|
Loading…
Reference in a new issue