forked from alemi/upub
feat: db model for activity and object + routes
This commit is contained in:
parent
40cee0fc87
commit
85c9b363f6
14 changed files with 365 additions and 73 deletions
|
@ -1,4 +1,11 @@
|
||||||
pub trait Activity : super::Object {
|
pub trait Activity : super::Object {
|
||||||
fn actor(&self) -> Option<&super::ObjectOrLink> { None }
|
fn activity_type(&self) -> Option<super::types::ActivityType> { None }
|
||||||
fn object(&self) -> Option<&super::ObjectOrLink> { None }
|
|
||||||
|
fn actor_id(&self) -> Option<&str> { None }
|
||||||
|
fn actor(&self) -> Option<&impl super::Object> { None::<&()> }
|
||||||
|
|
||||||
|
fn object_id(&self) -> Option<&str> { None }
|
||||||
|
fn object(&self) -> Option<&impl super::Object> { None::<&()> }
|
||||||
|
|
||||||
|
fn target(&self) -> Option<&str> { None }
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub trait Link {
|
||||||
|
|
||||||
pub trait Object {
|
pub trait Object {
|
||||||
fn id(&self) -> Option<&str> { None }
|
fn id(&self) -> Option<&str> { None }
|
||||||
fn object_type(&self) -> Option<super::Type> { None }
|
fn full_type(&self) -> Option<super::Type> { None }
|
||||||
fn attachment (&self) -> Option<&str> { None }
|
fn attachment (&self) -> Option<&str> { None }
|
||||||
fn attributed_to (&self) -> Option<&str> { None }
|
fn attributed_to (&self) -> Option<&str> { None }
|
||||||
fn audience (&self) -> Option<&str> { None }
|
fn audience (&self) -> Option<&str> { None }
|
||||||
|
@ -41,7 +41,7 @@ pub trait Object {
|
||||||
fn in_reply_to (&self) -> Option<&str> { None }
|
fn in_reply_to (&self) -> Option<&str> { None }
|
||||||
fn location (&self) -> Option<&str> { None }
|
fn location (&self) -> Option<&str> { None }
|
||||||
fn preview (&self) -> Option<&str> { None }
|
fn preview (&self) -> Option<&str> { None }
|
||||||
fn published (&self) -> Option<&str> { None }
|
fn published (&self) -> Option<chrono::DateTime<chrono::Utc>> { None }
|
||||||
fn replies (&self) -> Option<&str> { None }
|
fn replies (&self) -> Option<&str> { None }
|
||||||
fn start_time (&self) -> Option<&str> { None }
|
fn start_time (&self) -> Option<&str> { None }
|
||||||
fn summary (&self) -> Option<&str> { None }
|
fn summary (&self) -> Option<&str> { None }
|
||||||
|
@ -66,7 +66,7 @@ impl Object for serde_json::Value {
|
||||||
self.get("id")?.as_str()
|
self.get("id")?.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_type(&self) -> Option<super::Type> {
|
fn full_type(&self) -> Option<super::Type> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +88,25 @@ pub trait ToJson : Object {
|
||||||
impl<T> ToJson for T where T : Object {
|
impl<T> ToJson for T where T : Object {
|
||||||
fn json(&self) -> serde_json::Value {
|
fn json(&self) -> serde_json::Value {
|
||||||
let mut map = serde_json::Map::new();
|
let mut map = serde_json::Map::new();
|
||||||
|
let mp = &mut map;
|
||||||
|
|
||||||
if let Some(id) = self.id() {
|
put_str(mp, "id", self.id());
|
||||||
|
put_str(mp, "attributedTo", self.attributed_to());
|
||||||
|
put_str(mp, "name", self.name());
|
||||||
|
put_str(mp, "summary", self.summary());
|
||||||
|
put_str(mp, "content", self.content());
|
||||||
|
|
||||||
|
if let Some(t) = self.full_type() {
|
||||||
map.insert(
|
map.insert(
|
||||||
"id".to_string(),
|
"type".to_string(),
|
||||||
serde_json::Value::String(id.to_string())
|
serde_json::Value::String(format!("{t}")),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(published) = self.published() {
|
||||||
|
map.insert(
|
||||||
|
"published".to_string(),
|
||||||
|
serde_json::Value::String(published.to_rfc3339()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,3 +115,12 @@ impl<T> ToJson for T where T : Object {
|
||||||
serde_json::Value::Object(map)
|
serde_json::Value::Object(map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn put_str(map: &mut serde_json::Map<String, serde_json::Value>, k: &str, v: Option<&str>) {
|
||||||
|
if let Some(v) = v {
|
||||||
|
map.insert(
|
||||||
|
k.to_string(),
|
||||||
|
serde_json::Value::String(v.to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// TODO merge these flat maybe?
|
||||||
|
// but then db could theoretically hold an actor with type "Like" ... idk!
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Object,
|
Object,
|
||||||
ObjectType(ObjectType),
|
ObjectType(ObjectType),
|
||||||
|
@ -13,56 +16,73 @@ pub enum Type {
|
||||||
ActorType(ActorType),
|
ActorType(ActorType),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Type {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::ObjectType(x) => write!(f, "{:?}", x),
|
||||||
|
Self::ActivityType(x) => write!(f, "{:?}", x),
|
||||||
|
Self::ActorType(x) => write!(f, "{:?}", x),
|
||||||
|
_ => write!(f, "{:?}", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(sea_orm::EnumIter, sea_orm::DeriveActiveEnum, PartialEq, Eq, Debug, Clone, Copy)]
|
||||||
|
#[sea_orm(rs_type = "i32", db_type = "Integer")]
|
||||||
pub enum ActivityType {
|
pub enum ActivityType {
|
||||||
Accept,
|
Accept = 1,
|
||||||
Add,
|
Add = 2,
|
||||||
Announce,
|
Announce = 3,
|
||||||
Arrive,
|
Arrive = 4,
|
||||||
Block,
|
Block = 5,
|
||||||
Create,
|
Create = 6,
|
||||||
Delete,
|
Delete = 7,
|
||||||
Dislike,
|
Dislike = 8,
|
||||||
Flag,
|
Flag = 9,
|
||||||
Follow,
|
Follow = 10,
|
||||||
Ignore,
|
Ignore = 11,
|
||||||
Invite,
|
Invite = 12,
|
||||||
Join,
|
Join = 13,
|
||||||
Leave,
|
Leave = 14,
|
||||||
Like,
|
Like = 15,
|
||||||
Listen,
|
Listen = 16,
|
||||||
Move,
|
Move = 17,
|
||||||
Offer,
|
Offer = 18,
|
||||||
Question,
|
Question = 19,
|
||||||
Reject,
|
Reject = 20,
|
||||||
Read,
|
Read = 21,
|
||||||
Remove,
|
Remove = 22,
|
||||||
TentativeReject,
|
TentativeReject = 23,
|
||||||
TentativeAccept,
|
TentativeAccept = 24,
|
||||||
Travel,
|
Travel = 25,
|
||||||
Undo,
|
Undo = 26,
|
||||||
Update,
|
Update = 27,
|
||||||
View,
|
View = 28,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(sea_orm::EnumIter, sea_orm::DeriveActiveEnum, PartialEq, Eq, Debug, Clone, Copy)]
|
||||||
|
#[sea_orm(rs_type = "i32", db_type = "Integer")]
|
||||||
pub enum ActorType {
|
pub enum ActorType {
|
||||||
Application,
|
Application = 1,
|
||||||
Group,
|
Group = 2,
|
||||||
Organization,
|
Organization = 3,
|
||||||
Person,
|
Person = 4,
|
||||||
Service,
|
Service = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(sea_orm::EnumIter, sea_orm::DeriveActiveEnum, PartialEq, Eq, Debug, Clone, Copy)]
|
||||||
|
#[sea_orm(rs_type = "i32", db_type = "Integer")]
|
||||||
pub enum ObjectType {
|
pub enum ObjectType {
|
||||||
Article,
|
Article = 1,
|
||||||
Audio,
|
Audio = 2,
|
||||||
Document,
|
Document = 3,
|
||||||
Event,
|
Event = 4,
|
||||||
Image,
|
Image = 5,
|
||||||
Note,
|
Note = 6,
|
||||||
Page,
|
Page = 7,
|
||||||
Place,
|
Place = 8,
|
||||||
Profile,
|
Profile = 9,
|
||||||
Relationship,
|
Relationship = 10,
|
||||||
Tombstone,
|
Tombstone = 11,
|
||||||
Video,
|
Video = 12,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod migrations;
|
pub mod migrations;
|
||||||
pub mod activitystream;
|
pub mod activitystream;
|
||||||
pub mod activitypub;
|
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use sea_orm::Database;
|
use sea_orm::{ConnectOptions, Database};
|
||||||
use sea_orm_migration::MigratorTrait;
|
use sea_orm_migration::MigratorTrait;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -43,7 +42,11 @@ async fn main() {
|
||||||
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO })
|
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO })
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let db = Database::connect(&args.database)
|
let mut opts = ConnectOptions::new(&args.database);
|
||||||
|
opts
|
||||||
|
.max_connections(1);
|
||||||
|
|
||||||
|
let db = Database::connect(opts)
|
||||||
.await.expect("error connecting to db");
|
.await.expect("error connecting to db");
|
||||||
|
|
||||||
match args.command {
|
match args.command {
|
||||||
|
|
|
@ -6,8 +6,8 @@ pub struct Migration;
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl MigrationTrait for Migration {
|
impl MigrationTrait for Migration {
|
||||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
manager.
|
manager
|
||||||
create_table(
|
.create_table(
|
||||||
Table::create()
|
Table::create()
|
||||||
.table(Users::Table)
|
.table(Users::Table)
|
||||||
.if_not_exists()
|
.if_not_exists()
|
||||||
|
@ -17,17 +17,65 @@ impl MigrationTrait for Migration {
|
||||||
.not_null()
|
.not_null()
|
||||||
.primary_key()
|
.primary_key()
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(Users::Name).string().null())
|
.col(ColumnDef::new(Users::ActorType).integer().not_null())
|
||||||
|
.col(ColumnDef::new(Users::Name).string().not_null())
|
||||||
.to_owned()
|
.to_owned()
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Activities::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Activities::Id)
|
||||||
|
.string()
|
||||||
|
.not_null()
|
||||||
|
.primary_key()
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Activities::ActivityType).integer().not_null())
|
||||||
|
.col(ColumnDef::new(Activities::Actor).string().not_null())
|
||||||
|
.col(ColumnDef::new(Activities::Object).string().null())
|
||||||
|
.col(ColumnDef::new(Activities::Target).string().null())
|
||||||
|
.col(ColumnDef::new(Activities::Published).string().null())
|
||||||
|
.to_owned()
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Objects::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Objects::Id)
|
||||||
|
.string()
|
||||||
|
.not_null()
|
||||||
|
.primary_key()
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Objects::ObjectType).integer().not_null())
|
||||||
|
.col(ColumnDef::new(Objects::AttributedTo).string().null())
|
||||||
|
.col(ColumnDef::new(Objects::Name).string().null())
|
||||||
|
.col(ColumnDef::new(Objects::Summary).string().null())
|
||||||
|
.col(ColumnDef::new(Objects::Content).string().null())
|
||||||
|
.col(ColumnDef::new(Objects::Published).string().null())
|
||||||
|
.to_owned()
|
||||||
|
).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
manager.
|
manager
|
||||||
drop_table(Table::drop().table(Users::Table).to_owned())
|
.drop_table(Table::drop().table(Users::Table).to_owned())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Activities::Table).to_owned())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Objects::Table).to_owned())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -38,5 +86,29 @@ impl MigrationTrait for Migration {
|
||||||
enum Users {
|
enum Users {
|
||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
|
ActorType,
|
||||||
Name,
|
Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Activities {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
ActivityType,
|
||||||
|
Actor,
|
||||||
|
Object,
|
||||||
|
Target,
|
||||||
|
Published
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Objects {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
ObjectType,
|
||||||
|
Name,
|
||||||
|
Summary,
|
||||||
|
AttributedTo,
|
||||||
|
Content,
|
||||||
|
Published,
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
use crate::activitystream;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
|
#[sea_orm(table_name = "activities")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
/// must be https://instance.org/users/:user , even if local! TODO bad design...
|
||||||
|
pub id: String,
|
||||||
|
|
||||||
|
pub activity_type: activitystream::types::ActivityType,
|
||||||
|
pub actor: String, // TODO relates to USER
|
||||||
|
pub object: Option<String>, // TODO relates to NOTES maybe????? maybe other tables??????
|
||||||
|
pub target: Option<String>, // TODO relates to USER maybe??
|
||||||
|
pub published: ChronoDateTimeUtc,
|
||||||
|
|
||||||
|
// TODO: origin, result, instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl activitystream::Object for Model {
|
||||||
|
fn id(&self) -> Option<&str> {
|
||||||
|
Some(&self.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_type(&self) -> Option<activitystream::Type> {
|
||||||
|
Some(activitystream::Type::ActivityType(self.activity_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn published(&self) -> Option<chrono::DateTime<chrono::Utc>> {
|
||||||
|
Some(self.published)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl activitystream::Activity for Model {
|
||||||
|
fn activity_type(&self) -> Option<activitystream::types::ActivityType> {
|
||||||
|
Some(self.activity_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn actor_id(&self) -> Option<&str> {
|
||||||
|
Some(&self.actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn object_id(&self) -> Option<&str> {
|
||||||
|
self.object.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn target(&self) -> Option<&str> {
|
||||||
|
self.target.as_deref()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,34 @@
|
||||||
|
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod status;
|
pub mod object;
|
||||||
pub mod activity;
|
pub mod activity;
|
||||||
pub mod like;
|
|
||||||
pub mod relation;
|
pub async fn faker(db: &sea_orm::DatabaseConnection) -> Result<(), sea_orm::DbErr> {
|
||||||
|
use sea_orm::EntityTrait;
|
||||||
|
|
||||||
|
user::Entity::insert(user::ActiveModel {
|
||||||
|
id: sea_orm::Set("http://localhost:3000/users/root".into()),
|
||||||
|
name: sea_orm::Set("root".into()),
|
||||||
|
actor_type: sea_orm::Set(super::activitystream::types::ActorType::Person),
|
||||||
|
}).exec(db).await?;
|
||||||
|
|
||||||
|
object::Entity::insert(object::ActiveModel {
|
||||||
|
id: sea_orm::Set("http://localhost:3000/objects/4e28d30b-33c1-4336-918b-6fbe592bdd44".into()),
|
||||||
|
name: sea_orm::Set(None),
|
||||||
|
object_type: sea_orm::Set(crate::activitystream::types::ObjectType::Note),
|
||||||
|
attributed_to: sea_orm::Set(Some("http://localhost:3000/users/root".into())),
|
||||||
|
summary: sea_orm::Set(None),
|
||||||
|
content: sea_orm::Set(Some("Hello world!".into())),
|
||||||
|
published: sea_orm::Set(chrono::Utc::now()),
|
||||||
|
}).exec(db).await?;
|
||||||
|
|
||||||
|
activity::Entity::insert(activity::ActiveModel {
|
||||||
|
id: sea_orm::Set("http://localhost:3000/activities/ebac57e1-9828-438c-be34-a44a52de7641".into()),
|
||||||
|
activity_type: sea_orm::Set(crate::activitystream::types::ActivityType::Create),
|
||||||
|
actor: sea_orm::Set("http://localhost:3000/users/root".into()),
|
||||||
|
object: sea_orm::Set(Some("http://localhost:3000/obkects/4e28d30b-33c1-4336-918b-6fbe592bdd44".into())),
|
||||||
|
target: sea_orm::Set(None),
|
||||||
|
published: sea_orm::Set(chrono::Utc::now()),
|
||||||
|
}).exec(db).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
52
src/model/object.rs
Normal file
52
src/model/object.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
use crate::activitystream::types::ObjectType;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
|
#[sea_orm(table_name = "objects")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
/// must be full uri!!! maybe not great?
|
||||||
|
pub id: String,
|
||||||
|
pub object_type: ObjectType,
|
||||||
|
pub attributed_to: Option<String>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub summary: Option<String>,
|
||||||
|
pub content: Option<String>,
|
||||||
|
pub published: ChronoDateTimeUtc,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl crate::activitystream::Object for Model {
|
||||||
|
fn id(&self) -> Option<&str> {
|
||||||
|
Some(&self.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_type(&self) -> Option<crate::activitystream::Type> {
|
||||||
|
Some(crate::activitystream::Type::ObjectType(self.object_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attributed_to (&self) -> Option<&str> {
|
||||||
|
self.attributed_to.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name (&self) -> Option<&str> {
|
||||||
|
self.name.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn summary (&self) -> Option<&str> {
|
||||||
|
self.summary.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn content(&self) -> Option<&str> {
|
||||||
|
self.content.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn published (&self) -> Option<chrono::DateTime<chrono::Utc>> {
|
||||||
|
Some(self.published)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,18 @@
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
use crate::activitystream::{self, types::ActorType};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "users")]
|
#[sea_orm(table_name = "users")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
/// must be user@instance.org, even if local! TODO bad design...
|
/// must be user@instance.org, even if local! TODO bad design...
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: Option<String>,
|
|
||||||
|
pub actor_type: ActorType,
|
||||||
|
|
||||||
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -15,12 +20,16 @@ pub enum Relation {}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
impl crate::activitystream::Object for Model {
|
impl activitystream::Object for Model {
|
||||||
fn id(&self) -> Option<&str> {
|
fn id(&self) -> Option<&str> {
|
||||||
Some(&self.id)
|
Some(&self.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn full_type(&self) -> Option<activitystream::Type> {
|
||||||
|
Some(activitystream::Type::ActorType(self.actor_type))
|
||||||
|
}
|
||||||
|
|
||||||
fn name (&self) -> Option<&str> {
|
fn name (&self) -> Option<&str> {
|
||||||
self.name.as_deref()
|
Some(&self.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use crate::activitystream::object::ToJson;
|
use crate::activitystream::object::ToJson;
|
||||||
use crate::activitystream::{types::ActivityType, Object, Type};
|
use crate::activitystream::{types::ActivityType, Object, Type};
|
||||||
use crate::model::user;
|
use crate::model::{activity, object, user};
|
||||||
use axum::{extract::{Path, State}, http::StatusCode, routing::{get, post}, Json, Router};
|
use axum::{extract::{Path, State}, http::StatusCode, routing::{get, post}, Json, Router};
|
||||||
use sea_orm::{DatabaseConnection, EntityTrait};
|
use sea_orm::{DatabaseConnection, EntityTrait};
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ pub async fn serve(db: DatabaseConnection) {
|
||||||
.route("/inbox", post(inbox))
|
.route("/inbox", post(inbox))
|
||||||
.route("/outbox", get(|| async { todo!() }))
|
.route("/outbox", get(|| async { todo!() }))
|
||||||
.route("/users/:id", get(user))
|
.route("/users/:id", get(user))
|
||||||
|
.route("/activities/:id", get(activity))
|
||||||
.route("/objects/:id", get(object))
|
.route("/objects/:id", get(object))
|
||||||
.with_state(Arc::new(db));
|
.with_state(Arc::new(db));
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ pub async fn serve(db: DatabaseConnection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inbox(State(_db) : State<Arc<DatabaseConnection>>, Json(object): Json<serde_json::Value>) -> Result<Json<serde_json::Value>, StatusCode> {
|
async fn inbox(State(_db) : State<Arc<DatabaseConnection>>, Json(object): Json<serde_json::Value>) -> Result<Json<serde_json::Value>, StatusCode> {
|
||||||
match object.object_type() {
|
match object.full_type() {
|
||||||
None => { Err(StatusCode::BAD_REQUEST) },
|
None => { Err(StatusCode::BAD_REQUEST) },
|
||||||
Some(Type::Activity) => { Err(StatusCode::UNPROCESSABLE_ENTITY) },
|
Some(Type::Activity) => { Err(StatusCode::UNPROCESSABLE_ENTITY) },
|
||||||
Some(Type::ActivityType(ActivityType::Follow)) => { todo!() },
|
Some(Type::ActivityType(ActivityType::Follow)) => { todo!() },
|
||||||
|
@ -37,7 +38,8 @@ async fn inbox(State(_db) : State<Arc<DatabaseConnection>>, Json(object): Json<s
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn user(State(db) : State<Arc<DatabaseConnection>>, Path(id): Path<String>) -> Result<Json<serde_json::Value>, StatusCode> {
|
async fn user(State(db) : State<Arc<DatabaseConnection>>, Path(id): Path<String>) -> Result<Json<serde_json::Value>, StatusCode> {
|
||||||
match user::Entity::find_by_id(id).one(db.deref()).await {
|
let uri = format!("http://localhost:3000/users/{id}");
|
||||||
|
match user::Entity::find_by_id(uri).one(db.deref()).await {
|
||||||
Ok(Some(user)) => Ok(Json(user.json())),
|
Ok(Some(user)) => Ok(Json(user.json())),
|
||||||
Ok(None) => Err(StatusCode::NOT_FOUND),
|
Ok(None) => Err(StatusCode::NOT_FOUND),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -47,6 +49,26 @@ async fn user(State(db) : State<Arc<DatabaseConnection>>, Path(id): Path<String>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn object(State(_db) : State<Arc<DatabaseConnection>>, Path(_id): Path<String>) -> Result<Json<serde_json::Value>, StatusCode> {
|
async fn activity(State(db) : State<Arc<DatabaseConnection>>, Path(id): Path<String>) -> Result<Json<serde_json::Value>, StatusCode> {
|
||||||
todo!()
|
let uri = format!("http://localhost:3000/activities/{id}");
|
||||||
|
match activity::Entity::find_by_id(uri).one(db.deref()).await {
|
||||||
|
Ok(Some(activity)) => Ok(Json(activity.json())),
|
||||||
|
Ok(None) => Err(StatusCode::NOT_FOUND),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("error querying for activity: {e}");
|
||||||
|
Err(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn object(State(db) : State<Arc<DatabaseConnection>>, Path(id): Path<String>) -> Result<Json<serde_json::Value>, StatusCode> {
|
||||||
|
let uri = format!("http://localhost:3000/objects/{id}");
|
||||||
|
match object::Entity::find_by_id(uri).one(db.deref()).await {
|
||||||
|
Ok(Some(object)) => Ok(Json(object.json())),
|
||||||
|
Ok(None) => Err(StatusCode::NOT_FOUND),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("error querying for object: {e}");
|
||||||
|
Err(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue