Replace PlumeRocket with DbConn where possible

This commit is contained in:
Kitaiti Makoto 2021-01-30 19:24:16 +09:00
parent 5d25a64f13
commit 25e52788c5
12 changed files with 205 additions and 212 deletions

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
ap_url, instance::*, medias::Media, posts::Post, safe_string::SafeString, schema::blogs, ap_url, db_conn::DbConn, instance::*, medias::Media, posts::Post, safe_string::SafeString,
users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE, schema::blogs, users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE,
}; };
use activitypub::{ use activitypub::{
actor::Group, actor::Group,
@ -131,25 +131,25 @@ impl Blog {
.map_err(Error::from) .map_err(Error::from)
} }
pub fn find_by_fqn(c: &PlumeRocket, fqn: &str) -> Result<Blog> { pub fn find_by_fqn(conn: &DbConn, fqn: &str) -> Result<Blog> {
let from_db = blogs::table let from_db = blogs::table
.filter(blogs::fqn.eq(fqn)) .filter(blogs::fqn.eq(fqn))
.first(&*c.conn) .first(&**conn)
.optional()?; .optional()?;
if let Some(from_db) = from_db { if let Some(from_db) = from_db {
Ok(from_db) Ok(from_db)
} else { } else {
Blog::fetch_from_webfinger(c, fqn) Blog::fetch_from_webfinger(conn, fqn)
} }
} }
fn fetch_from_webfinger(c: &PlumeRocket, acct: &str) -> Result<Blog> { fn fetch_from_webfinger(conn: &DbConn, acct: &str) -> Result<Blog> {
resolve_with_prefix(Prefix::Group, acct.to_owned(), true)? resolve_with_prefix(Prefix::Group, acct.to_owned(), true)?
.links .links
.into_iter() .into_iter()
.find(|l| l.mime_type == Some(String::from("application/activity+json"))) .find(|l| l.mime_type == Some(String::from("application/activity+json")))
.ok_or(Error::Webfinger) .ok_or(Error::Webfinger)
.and_then(|l| Blog::from_id(c, &l.href?, None, CONFIG.proxy()).map_err(|(_, e)| e)) .and_then(|l| Blog::from_id(conn, &l.href?, None, CONFIG.proxy()).map_err(|(_, e)| e))
} }
pub fn to_activity(&self, conn: &Connection) -> Result<CustomGroup> { pub fn to_activity(&self, conn: &Connection) -> Result<CustomGroup> {
@ -334,20 +334,20 @@ impl IntoId for Blog {
} }
} }
impl FromId<PlumeRocket> for Blog { impl FromId<DbConn> for Blog {
type Error = Error; type Error = Error;
type Object = CustomGroup; type Object = CustomGroup;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Self::find_by_ap_url(&c.conn, id) Self::find_by_ap_url(&conn, id)
} }
fn from_activity(c: &PlumeRocket, acct: CustomGroup) -> Result<Self> { fn from_activity(conn: &DbConn, acct: CustomGroup) -> Result<Self> {
let url = Url::parse(&acct.object.object_props.id_string()?)?; let url = Url::parse(&acct.object.object_props.id_string()?)?;
let inst = url.host_str()?; let inst = url.host_str()?;
let instance = Instance::find_by_domain(&c.conn, inst).or_else(|_| { let instance = Instance::find_by_domain(conn, inst).or_else(|_| {
Instance::insert( Instance::insert(
&c.conn, conn,
NewInstance { NewInstance {
public_domain: inst.to_owned(), public_domain: inst.to_owned(),
name: inst.to_owned(), name: inst.to_owned(),
@ -370,9 +370,9 @@ impl FromId<PlumeRocket> for Blog {
.and_then(|icon| { .and_then(|icon| {
let owner = icon.object_props.attributed_to_link::<Id>().ok()?; let owner = icon.object_props.attributed_to_link::<Id>().ok()?;
Media::save_remote( Media::save_remote(
&c.conn, conn,
icon.object_props.url_string().ok()?, icon.object_props.url_string().ok()?,
&User::from_id(c, &owner, None, CONFIG.proxy()).ok()?, &User::from_id(conn, &owner, None, CONFIG.proxy()).ok()?,
) )
.ok() .ok()
}) })
@ -386,9 +386,9 @@ impl FromId<PlumeRocket> for Blog {
.and_then(|banner| { .and_then(|banner| {
let owner = banner.object_props.attributed_to_link::<Id>().ok()?; let owner = banner.object_props.attributed_to_link::<Id>().ok()?;
Media::save_remote( Media::save_remote(
&c.conn, conn,
banner.object_props.url_string().ok()?, banner.object_props.url_string().ok()?,
&User::from_id(c, &owner, None, CONFIG.proxy()).ok()?, &User::from_id(conn, &owner, None, CONFIG.proxy()).ok()?,
) )
.ok() .ok()
}) })
@ -400,7 +400,7 @@ impl FromId<PlumeRocket> for Blog {
} }
Blog::insert( Blog::insert(
&c.conn, conn,
NewBlog { NewBlog {
actor_id: name.clone(), actor_id: name.clone(),
title: acct.object.object_props.name_string().unwrap_or(name), title: acct.object.object_props.name_string().unwrap_or(name),

View File

@ -1,5 +1,6 @@
use crate::{ use crate::{
comment_seers::{CommentSeers, NewCommentSeers}, comment_seers::{CommentSeers, NewCommentSeers},
db_conn::DbConn,
instance::Instance, instance::Instance,
medias::Media, medias::Media,
mentions::Mention, mentions::Mention,
@ -8,7 +9,7 @@ use crate::{
safe_string::SafeString, safe_string::SafeString,
schema::comments, schema::comments,
users::User, users::User,
Connection, Error, PlumeRocket, Result, CONFIG, Connection, Error, Result, CONFIG,
}; };
use activitypub::{ use activitypub::{
activity::{Create, Delete}, activity::{Create, Delete},
@ -104,13 +105,13 @@ impl Comment {
.unwrap_or(false) .unwrap_or(false)
} }
pub fn to_activity(&self, c: &PlumeRocket) -> Result<Note> { pub fn to_activity(&self, conn: &DbConn) -> Result<Note> {
let author = User::get(&c.conn, self.author_id)?; let author = User::get(conn, self.author_id)?;
let (html, mentions, _hashtags) = utils::md_to_html( let (html, mentions, _hashtags) = utils::md_to_html(
self.content.get().as_ref(), self.content.get().as_ref(),
Some(&Instance::get_local()?.public_domain), Some(&Instance::get_local()?.public_domain),
true, true,
Some(Media::get_media_processor(&c.conn, vec![&author])), Some(Media::get_media_processor(conn, vec![&author])),
); );
let mut note = Note::default(); let mut note = Note::default();
@ -123,8 +124,8 @@ impl Comment {
note.object_props.set_content_string(html)?; note.object_props.set_content_string(html)?;
note.object_props note.object_props
.set_in_reply_to_link(Id::new(self.in_response_to_id.map_or_else( .set_in_reply_to_link(Id::new(self.in_response_to_id.map_or_else(
|| Ok(Post::get(&c.conn, self.post_id)?.ap_url), || Ok(Post::get(conn, self.post_id)?.ap_url),
|id| Ok(Comment::get(&c.conn, id)?.ap_url.unwrap_or_default()) as Result<String>, |id| Ok(Comment::get(conn, id)?.ap_url.unwrap_or_default()) as Result<String>,
)?))?; )?))?;
note.object_props note.object_props
.set_published_string(chrono::Utc::now().to_rfc3339())?; .set_published_string(chrono::Utc::now().to_rfc3339())?;
@ -133,16 +134,16 @@ impl Comment {
note.object_props.set_tag_link_vec( note.object_props.set_tag_link_vec(
mentions mentions
.into_iter() .into_iter()
.filter_map(|m| Mention::build_activity(c, &m).ok()) .filter_map(|m| Mention::build_activity(conn, &m).ok())
.collect::<Vec<link::Mention>>(), .collect::<Vec<link::Mention>>(),
)?; )?;
Ok(note) Ok(note)
} }
pub fn create_activity(&self, c: &PlumeRocket) -> Result<Create> { pub fn create_activity(&self, conn: &DbConn) -> Result<Create> {
let author = User::get(&c.conn, self.author_id)?; let author = User::get(&conn, self.author_id)?;
let note = self.to_activity(c)?; let note = self.to_activity(conn)?;
let mut act = Create::default(); let mut act = Create::default();
act.create_props.set_actor_link(author.into_id())?; act.create_props.set_actor_link(author.into_id())?;
act.create_props.set_object_object(note.clone())?; act.create_props.set_object_object(note.clone())?;
@ -151,7 +152,7 @@ impl Comment {
act.object_props act.object_props
.set_to_link_vec(note.object_props.to_link_vec::<Id>()?)?; .set_to_link_vec(note.object_props.to_link_vec::<Id>()?)?;
act.object_props act.object_props
.set_cc_link_vec(vec![Id::new(self.get_author(&c.conn)?.followers_endpoint)])?; .set_cc_link_vec(vec![Id::new(self.get_author(&conn)?.followers_endpoint)])?;
Ok(act) Ok(act)
} }
@ -193,16 +194,15 @@ impl Comment {
} }
} }
impl FromId<PlumeRocket> for Comment { impl FromId<DbConn> for Comment {
type Error = Error; type Error = Error;
type Object = Note; type Object = Note;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Self::find_by_ap_url(&c.conn, id) Self::find_by_ap_url(conn, id)
} }
fn from_activity(c: &PlumeRocket, note: Note) -> Result<Self> { fn from_activity(conn: &DbConn, note: Note) -> Result<Self> {
let conn = &*c.conn;
let comm = { let comm = {
let previous_url = note.object_props.in_reply_to.as_ref()?.as_str()?; let previous_url = note.object_props.in_reply_to.as_ref()?.as_str()?;
let previous_comment = Comment::find_by_ap_url(conn, previous_url); let previous_comment = Comment::find_by_ap_url(conn, previous_url);
@ -235,7 +235,7 @@ impl FromId<PlumeRocket> for Comment {
Ok(Post::find_by_ap_url(conn, previous_url)?.id) as Result<i32> Ok(Post::find_by_ap_url(conn, previous_url)?.id) as Result<i32>
})?, })?,
author_id: User::from_id( author_id: User::from_id(
c, conn,
&note.object_props.attributed_to_link::<Id>()?, &note.object_props.attributed_to_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
@ -296,7 +296,7 @@ impl FromId<PlumeRocket> for Comment {
.collect::<HashSet<_>>() // remove duplicates (don't do a query more than once) .collect::<HashSet<_>>() // remove duplicates (don't do a query more than once)
.into_iter() .into_iter()
.map(|v| { .map(|v| {
if let Ok(user) = User::from_id(c, &v, None, CONFIG.proxy()) { if let Ok(user) = User::from_id(conn, &v, None, CONFIG.proxy()) {
vec![user] vec![user]
} else { } else {
vec![] // TODO try to fetch collection vec![] // TODO try to fetch collection
@ -322,41 +322,41 @@ impl FromId<PlumeRocket> for Comment {
} }
} }
impl AsObject<User, Create, &PlumeRocket> for Comment { impl AsObject<User, Create, &DbConn> for Comment {
type Error = Error; type Error = Error;
type Output = Self; type Output = Self;
fn activity(self, _c: &PlumeRocket, _actor: User, _id: &str) -> Result<Self> { fn activity(self, _conn: &DbConn, _actor: User, _id: &str) -> Result<Self> {
// The actual creation takes place in the FromId impl // The actual creation takes place in the FromId impl
Ok(self) Ok(self)
} }
} }
impl AsObject<User, Delete, &PlumeRocket> for Comment { impl AsObject<User, Delete, &DbConn> for Comment {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
if self.author_id != actor.id { if self.author_id != actor.id {
return Err(Error::Unauthorized); return Err(Error::Unauthorized);
} }
for m in Mention::list_for_comment(&c.conn, self.id)? { for m in Mention::list_for_comment(conn, self.id)? {
for n in Notification::find_for_mention(&c.conn, &m)? { for n in Notification::find_for_mention(conn, &m)? {
n.delete(&c.conn)?; n.delete(conn)?;
} }
m.delete(&c.conn)?; m.delete(conn)?;
} }
for n in Notification::find_for_comment(&c.conn, &self)? { for n in Notification::find_for_comment(&conn, &self)? {
n.delete(&c.conn)?; n.delete(&**conn)?;
} }
diesel::update(comments::table) diesel::update(comments::table)
.filter(comments::in_response_to_id.eq(self.id)) .filter(comments::in_response_to_id.eq(self.id))
.set(comments::in_response_to_id.eq(self.in_response_to_id)) .set(comments::in_response_to_id.eq(self.in_response_to_id))
.execute(&*c.conn)?; .execute(&**conn)?;
diesel::delete(&self).execute(&*c.conn)?; diesel::delete(&self).execute(&**conn)?;
Ok(()) Ok(())
} }
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
ap_url, notifications::*, schema::follows, users::User, Connection, Error, PlumeRocket, Result, ap_url, db_conn::DbConn, notifications::*, schema::follows, users::User, Connection, Error,
CONFIG, Result, CONFIG,
}; };
use activitypub::activity::{Accept, Follow as FollowAct, Undo}; use activitypub::activity::{Accept, Follow as FollowAct, Undo};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl}; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
@ -141,11 +141,11 @@ impl Follow {
} }
} }
impl AsObject<User, FollowAct, &PlumeRocket> for User { impl AsObject<User, FollowAct, &DbConn> for User {
type Error = Error; type Error = Error;
type Output = Follow; type Output = Follow;
fn activity(self, c: &PlumeRocket, actor: User, id: &str) -> Result<Follow> { fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Follow> {
// Mastodon (at least) requires the full Follow object when accepting it, // Mastodon (at least) requires the full Follow object when accepting it,
// so we rebuilt it here // so we rebuilt it here
let mut follow = FollowAct::default(); let mut follow = FollowAct::default();
@ -153,21 +153,21 @@ impl AsObject<User, FollowAct, &PlumeRocket> for User {
follow follow
.follow_props .follow_props
.set_actor_link::<Id>(actor.clone().into_id())?; .set_actor_link::<Id>(actor.clone().into_id())?;
Follow::accept_follow(&c.conn, &actor, &self, follow, actor.id, self.id) Follow::accept_follow(conn, &actor, &self, follow, actor.id, self.id)
} }
} }
impl FromId<PlumeRocket> for Follow { impl FromId<DbConn> for Follow {
type Error = Error; type Error = Error;
type Object = FollowAct; type Object = FollowAct;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Follow::find_by_ap_url(&c.conn, id) Follow::find_by_ap_url(conn, id)
} }
fn from_activity(c: &PlumeRocket, follow: FollowAct) -> Result<Self> { fn from_activity(conn: &DbConn, follow: FollowAct) -> Result<Self> {
let actor = User::from_id( let actor = User::from_id(
c, conn,
&follow.follow_props.actor_link::<Id>()?, &follow.follow_props.actor_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
@ -175,28 +175,28 @@ impl FromId<PlumeRocket> for Follow {
.map_err(|(_, e)| e)?; .map_err(|(_, e)| e)?;
let target = User::from_id( let target = User::from_id(
c, conn,
&follow.follow_props.object_link::<Id>()?, &follow.follow_props.object_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
) )
.map_err(|(_, e)| e)?; .map_err(|(_, e)| e)?;
Follow::accept_follow(&c.conn, &actor, &target, follow, actor.id, target.id) Follow::accept_follow(conn, &actor, &target, follow, actor.id, target.id)
} }
} }
impl AsObject<User, Undo, &PlumeRocket> for Follow { impl AsObject<User, Undo, &DbConn> for Follow {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
let conn = &*c.conn; let conn = conn;
if self.follower_id == actor.id { if self.follower_id == actor.id {
diesel::delete(&self).execute(conn)?; diesel::delete(&self).execute(&**conn)?;
// delete associated notification if any // delete associated notification if any
if let Ok(notif) = Notification::find(conn, notification_kind::FOLLOW, self.id) { if let Ok(notif) = Notification::find(&conn, notification_kind::FOLLOW, self.id) {
diesel::delete(&notif).execute(conn)?; diesel::delete(&notif).execute(&**conn)?;
} }
Ok(()) Ok(())

View File

@ -2,11 +2,12 @@ use activitypub::activity::*;
use crate::{ use crate::{
comments::Comment, comments::Comment,
db_conn::DbConn,
follows, likes, follows, likes,
posts::{Post, PostUpdate}, posts::{Post, PostUpdate},
reshares::Reshare, reshares::Reshare,
users::User, users::User,
Error, PlumeRocket, CONFIG, Error, CONFIG,
}; };
use plume_common::activity_pub::inbox::Inbox; use plume_common::activity_pub::inbox::Inbox;
@ -45,8 +46,8 @@ impl_into_inbox_result! {
Reshare => Reshared Reshare => Reshared
} }
pub fn inbox(ctx: &PlumeRocket, act: serde_json::Value) -> Result<InboxResult, Error> { pub fn inbox(conn: DbConn, act: serde_json::Value) -> Result<InboxResult, Error> {
Inbox::handle(ctx, act) Inbox::handle(&conn, act)
.with::<User, Announce, Post>(CONFIG.proxy()) .with::<User, Announce, Post>(CONFIG.proxy())
.with::<User, Create, Comment>(CONFIG.proxy()) .with::<User, Create, Comment>(CONFIG.proxy())
.with::<User, Create, Post>(CONFIG.proxy()) .with::<User, Create, Post>(CONFIG.proxy())

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
notifications::*, posts::Post, schema::likes, timeline::*, users::User, Connection, Error, db_conn::DbConn, notifications::*, posts::Post, schema::likes, timeline::*, users::User,
PlumeRocket, Result, CONFIG, Connection, Error, Result, CONFIG,
}; };
use activitypub::activity; use activitypub::activity;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
@ -83,40 +83,40 @@ impl Like {
} }
} }
impl AsObject<User, activity::Like, &PlumeRocket> for Post { impl AsObject<User, activity::Like, &DbConn> for Post {
type Error = Error; type Error = Error;
type Output = Like; type Output = Like;
fn activity(self, c: &PlumeRocket, actor: User, id: &str) -> Result<Like> { fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Like> {
let res = Like::insert( let res = Like::insert(
&c.conn, conn,
NewLike { NewLike {
post_id: self.id, post_id: self.id,
user_id: actor.id, user_id: actor.id,
ap_url: id.to_string(), ap_url: id.to_string(),
}, },
)?; )?;
res.notify(&c.conn)?; res.notify(conn)?;
Timeline::add_to_all_timelines(c, &self, Kind::Like(&actor))?; Timeline::add_to_all_timelines(conn, &self, Kind::Like(&actor))?;
Ok(res) Ok(res)
} }
} }
impl FromId<PlumeRocket> for Like { impl FromId<DbConn> for Like {
type Error = Error; type Error = Error;
type Object = activity::Like; type Object = activity::Like;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Like::find_by_ap_url(&c.conn, id) Like::find_by_ap_url(conn, id)
} }
fn from_activity(c: &PlumeRocket, act: activity::Like) -> Result<Self> { fn from_activity(conn: &DbConn, act: activity::Like) -> Result<Self> {
let res = Like::insert( let res = Like::insert(
&c.conn, conn,
NewLike { NewLike {
post_id: Post::from_id( post_id: Post::from_id(
c, conn,
&act.like_props.object_link::<Id>()?, &act.like_props.object_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
@ -124,7 +124,7 @@ impl FromId<PlumeRocket> for Like {
.map_err(|(_, e)| e)? .map_err(|(_, e)| e)?
.id, .id,
user_id: User::from_id( user_id: User::from_id(
c, conn,
&act.like_props.actor_link::<Id>()?, &act.like_props.actor_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
@ -134,23 +134,22 @@ impl FromId<PlumeRocket> for Like {
ap_url: act.object_props.id_string()?, ap_url: act.object_props.id_string()?,
}, },
)?; )?;
res.notify(&c.conn)?; res.notify(conn)?;
Ok(res) Ok(res)
} }
} }
impl AsObject<User, activity::Undo, &PlumeRocket> for Like { impl AsObject<User, activity::Undo, &DbConn> for Like {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
let conn = &*c.conn;
if actor.id == self.user_id { if actor.id == self.user_id {
diesel::delete(&self).execute(conn)?; diesel::delete(&self).execute(&**conn)?;
// delete associated notification if any // delete associated notification if any
if let Ok(notif) = Notification::find(conn, notification_kind::LIKE, self.id) { if let Ok(notif) = Notification::find(&conn, notification_kind::LIKE, self.id) {
diesel::delete(&notif).execute(conn)?; diesel::delete(&notif).execute(&**conn)?;
} }
Ok(()) Ok(())
} else { } else {

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
ap_url, instance::Instance, safe_string::SafeString, schema::medias, users::User, Connection, ap_url, db_conn::DbConn, instance::Instance, safe_string::SafeString, schema::medias,
Error, PlumeRocket, Result, CONFIG, users::User, Connection, Error, Result, CONFIG,
}; };
use activitypub::object::Image; use activitypub::object::Image;
use askama_escape::escape; use askama_escape::escape;
@ -196,8 +196,7 @@ impl Media {
} }
// TODO: merge with save_remote? // TODO: merge with save_remote?
pub fn from_activity(c: &PlumeRocket, image: &Image) -> Result<Media> { pub fn from_activity(conn: &DbConn, image: &Image) -> Result<Media> {
let conn = &*c.conn;
let remote_url = image.object_props.url_string().ok()?; let remote_url = image.object_props.url_string().ok()?;
let ext = remote_url let ext = remote_url
.rsplit('.') .rsplit('.')
@ -232,7 +231,7 @@ impl Media {
sensitive: image.object_props.summary_string().is_ok(), sensitive: image.object_props.summary_string().is_ok(),
content_warning: image.object_props.summary_string().ok(), content_warning: image.object_props.summary_string().ok(),
owner_id: User::from_id( owner_id: User::from_id(
c, conn,
image image
.object_props .object_props
.attributed_to_link_vec::<Id>() .attributed_to_link_vec::<Id>()

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
comments::Comment, notifications::*, posts::Post, schema::mentions, users::User, Connection, comments::Comment, db_conn::DbConn, notifications::*, posts::Post, schema::mentions,
Error, PlumeRocket, Result, users::User, Connection, Error, Result,
}; };
use activitypub::link; use activitypub::link;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
@ -52,8 +52,8 @@ impl Mention {
} }
} }
pub fn build_activity(c: &PlumeRocket, ment: &str) -> Result<link::Mention> { pub fn build_activity(conn: &DbConn, ment: &str) -> Result<link::Mention> {
let user = User::find_by_fqn(c, ment)?; let user = User::find_by_fqn(conn, ment)?;
let mut mention = link::Mention::default(); let mut mention = link::Mention::default();
mention.link_props.set_href_string(user.ap_url)?; mention.link_props.set_href_string(user.ap_url)?;
mention.link_props.set_name_string(format!("@{}", ment))?; mention.link_props.set_name_string(format!("@{}", ment))?;

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
ap_url, blogs::Blog, instance::Instance, medias::Media, mentions::Mention, post_authors::*, ap_url, blogs::Blog, db_conn::DbConn, instance::Instance, medias::Media, mentions::Mention,
safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User, Connection, Error, post_authors::*, safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User,
PlumeRocket, PostEvent::*, Result, CONFIG, POST_CHAN, Connection, Error, PostEvent::*, Result, CONFIG, POST_CHAN,
}; };
use activitypub::{ use activitypub::{
activity::{Create, Delete, Update}, activity::{Create, Delete, Update},
@ -606,16 +606,16 @@ impl Post {
} }
} }
impl FromId<PlumeRocket> for Post { impl FromId<DbConn> for Post {
type Error = Error; type Error = Error;
type Object = LicensedArticle; type Object = LicensedArticle;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Self::find_by_ap_url(&c.conn, id) Self::find_by_ap_url(conn, id)
} }
fn from_activity(c: &PlumeRocket, article: LicensedArticle) -> Result<Self> { fn from_activity(conn: &DbConn, article: LicensedArticle) -> Result<Self> {
let conn = &*c.conn; let conn = conn;
let license = article.custom_props.license_string().unwrap_or_default(); let license = article.custom_props.license_string().unwrap_or_default();
let article = article.object; let article = article.object;
@ -625,13 +625,13 @@ impl FromId<PlumeRocket> for Post {
.into_iter() .into_iter()
.fold((None, vec![]), |(blog, mut authors), link| { .fold((None, vec![]), |(blog, mut authors), link| {
let url = link; let url = link;
match User::from_id(&c, &url, None, CONFIG.proxy()) { match User::from_id(conn, &url, None, CONFIG.proxy()) {
Ok(u) => { Ok(u) => {
authors.push(u); authors.push(u);
(blog, authors) (blog, authors)
} }
Err(_) => ( Err(_) => (
blog.or_else(|| Blog::from_id(&c, &url, None, CONFIG.proxy()).ok()), blog.or_else(|| Blog::from_id(conn, &url, None, CONFIG.proxy()).ok()),
authors, authors,
), ),
} }
@ -641,7 +641,7 @@ impl FromId<PlumeRocket> for Post {
.object_props .object_props
.icon_object::<Image>() .icon_object::<Image>()
.ok() .ok()
.and_then(|img| Media::from_activity(&c, &img).ok().map(|m| m.id)); .and_then(|img| Media::from_activity(conn, &img).ok().map(|m| m.id));
let title = article.object_props.name_string()?; let title = article.object_props.name_string()?;
let post = Post::insert( let post = Post::insert(
@ -701,33 +701,33 @@ impl FromId<PlumeRocket> for Post {
} }
} }
Timeline::add_to_all_timelines(c, &post, Kind::Original)?; Timeline::add_to_all_timelines(conn, &post, Kind::Original)?;
Ok(post) Ok(post)
} }
} }
impl AsObject<User, Create, &PlumeRocket> for Post { impl AsObject<User, Create, &DbConn> for Post {
type Error = Error; type Error = Error;
type Output = Post; type Output = Post;
fn activity(self, _c: &PlumeRocket, _actor: User, _id: &str) -> Result<Post> { fn activity(self, _conn: &DbConn, _actor: User, _id: &str) -> Result<Post> {
// TODO: check that _actor is actually one of the author? // TODO: check that _actor is actually one of the author?
Ok(self) Ok(self)
} }
} }
impl AsObject<User, Delete, &PlumeRocket> for Post { impl AsObject<User, Delete, &DbConn> for Post {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
let can_delete = self let can_delete = self
.get_authors(&c.conn)? .get_authors(conn)?
.into_iter() .into_iter()
.any(|a| actor.id == a.id); .any(|a| actor.id == a.id);
if can_delete { if can_delete {
self.delete(&c.conn).map(|_| ()) self.delete(conn).map(|_| ())
} else { } else {
Err(Error::Unauthorized) Err(Error::Unauthorized)
} }
@ -745,16 +745,16 @@ pub struct PostUpdate {
pub tags: Option<serde_json::Value>, pub tags: Option<serde_json::Value>,
} }
impl FromId<PlumeRocket> for PostUpdate { impl FromId<DbConn> for PostUpdate {
type Error = Error; type Error = Error;
type Object = LicensedArticle; type Object = LicensedArticle;
fn from_db(_: &PlumeRocket, _: &str) -> Result<Self> { fn from_db(_: &DbConn, _: &str) -> Result<Self> {
// Always fail because we always want to deserialize the AP object // Always fail because we always want to deserialize the AP object
Err(Error::NotFound) Err(Error::NotFound)
} }
fn from_activity(c: &PlumeRocket, updated: LicensedArticle) -> Result<Self> { fn from_activity(conn: &DbConn, updated: LicensedArticle) -> Result<Self> {
Ok(PostUpdate { Ok(PostUpdate {
ap_url: updated.object.object_props.id_string()?, ap_url: updated.object.object_props.id_string()?,
title: updated.object.object_props.name_string().ok(), title: updated.object.object_props.name_string().ok(),
@ -765,7 +765,7 @@ impl FromId<PlumeRocket> for PostUpdate {
.object_props .object_props
.icon_object::<Image>() .icon_object::<Image>()
.ok() .ok()
.and_then(|img| Media::from_activity(&c, &img).ok().map(|m| m.id)), .and_then(|img| Media::from_activity(conn, &img).ok().map(|m| m.id)),
source: updated source: updated
.object .object
.ap_object_props .ap_object_props
@ -778,13 +778,13 @@ impl FromId<PlumeRocket> for PostUpdate {
} }
} }
impl AsObject<User, Update, &PlumeRocket> for PostUpdate { impl AsObject<User, Update, &DbConn> for PostUpdate {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
let conn = &*c.conn; let mut post =
let mut post = Post::from_id(c, &self.ap_url, None, CONFIG.proxy()).map_err(|(_, e)| e)?; Post::from_id(conn, &self.ap_url, None, CONFIG.proxy()).map_err(|(_, e)| e)?;
if !post.is_author(conn, actor.id)? { if !post.is_author(conn, actor.id)? {
// TODO: maybe the author was added in the meantime // TODO: maybe the author was added in the meantime

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
notifications::*, posts::Post, schema::reshares, timeline::*, users::User, Connection, Error, db_conn::DbConn, notifications::*, posts::Post, schema::reshares, timeline::*, users::User,
PlumeRocket, Result, CONFIG, Connection, Error, Result, CONFIG,
}; };
use activitypub::activity::{Announce, Undo}; use activitypub::activity::{Announce, Undo};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
@ -107,12 +107,12 @@ impl Reshare {
} }
} }
impl AsObject<User, Announce, &PlumeRocket> for Post { impl AsObject<User, Announce, &DbConn> for Post {
type Error = Error; type Error = Error;
type Output = Reshare; type Output = Reshare;
fn activity(self, c: &PlumeRocket, actor: User, id: &str) -> Result<Reshare> { fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Reshare> {
let conn = &*c.conn; let conn = conn;
let reshare = Reshare::insert( let reshare = Reshare::insert(
conn, conn,
NewReshare { NewReshare {
@ -123,25 +123,25 @@ impl AsObject<User, Announce, &PlumeRocket> for Post {
)?; )?;
reshare.notify(conn)?; reshare.notify(conn)?;
Timeline::add_to_all_timelines(c, &self, Kind::Reshare(&actor))?; Timeline::add_to_all_timelines(conn, &self, Kind::Reshare(&actor))?;
Ok(reshare) Ok(reshare)
} }
} }
impl FromId<PlumeRocket> for Reshare { impl FromId<DbConn> for Reshare {
type Error = Error; type Error = Error;
type Object = Announce; type Object = Announce;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Reshare::find_by_ap_url(&c.conn, id) Reshare::find_by_ap_url(conn, id)
} }
fn from_activity(c: &PlumeRocket, act: Announce) -> Result<Self> { fn from_activity(conn: &DbConn, act: Announce) -> Result<Self> {
let res = Reshare::insert( let res = Reshare::insert(
&c.conn, conn,
NewReshare { NewReshare {
post_id: Post::from_id( post_id: Post::from_id(
c, conn,
&act.announce_props.object_link::<Id>()?, &act.announce_props.object_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
@ -149,7 +149,7 @@ impl FromId<PlumeRocket> for Reshare {
.map_err(|(_, e)| e)? .map_err(|(_, e)| e)?
.id, .id,
user_id: User::from_id( user_id: User::from_id(
c, conn,
&act.announce_props.actor_link::<Id>()?, &act.announce_props.actor_link::<Id>()?,
None, None,
CONFIG.proxy(), CONFIG.proxy(),
@ -159,23 +159,22 @@ impl FromId<PlumeRocket> for Reshare {
ap_url: act.object_props.id_string()?, ap_url: act.object_props.id_string()?,
}, },
)?; )?;
res.notify(&c.conn)?; res.notify(conn)?;
Ok(res) Ok(res)
} }
} }
impl AsObject<User, Undo, &PlumeRocket> for Reshare { impl AsObject<User, Undo, &DbConn> for Reshare {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
let conn = &*c.conn;
if actor.id == self.user_id { if actor.id == self.user_id {
diesel::delete(&self).execute(conn)?; diesel::delete(&self).execute(&**conn)?;
// delete associated notification if any // delete associated notification if any
if let Ok(notif) = Notification::find(&conn, notification_kind::RESHARE, self.id) { if let Ok(notif) = Notification::find(&conn, notification_kind::RESHARE, self.id) {
diesel::delete(&notif).execute(conn)?; diesel::delete(&notif).execute(&**conn)?;
} }
Ok(()) Ok(())

View File

@ -1,8 +1,9 @@
use crate::{ use crate::{
db_conn::DbConn,
lists::List, lists::List,
posts::Post, posts::Post,
schema::{posts, timeline, timeline_definition}, schema::{posts, timeline, timeline_definition},
Connection, Error, PlumeRocket, Result, Connection, Error, Result,
}; };
use diesel::{self, BoolExpressionMethods, ExpressionMethods, QueryDsl, RunQueryDsl}; use diesel::{self, BoolExpressionMethods, ExpressionMethods, QueryDsl, RunQueryDsl};
use std::ops::Deref; use std::ops::Deref;
@ -208,14 +209,14 @@ impl Timeline {
.map_err(Error::from) .map_err(Error::from)
} }
pub fn add_to_all_timelines(rocket: &PlumeRocket, post: &Post, kind: Kind<'_>) -> Result<()> { pub fn add_to_all_timelines(conn: &DbConn, post: &Post, kind: Kind<'_>) -> Result<()> {
let timelines = timeline_definition::table let timelines = timeline_definition::table
.load::<Self>(rocket.conn.deref()) .load::<Self>(conn.deref())
.map_err(Error::from)?; .map_err(Error::from)?;
for t in timelines { for t in timelines {
if t.matches(rocket, post, kind)? { if t.matches(conn, post, kind)? {
t.add_post(&rocket.conn, post)?; t.add_post(conn, post)?;
} }
} }
Ok(()) Ok(())
@ -231,9 +232,9 @@ impl Timeline {
Ok(()) Ok(())
} }
pub fn matches(&self, rocket: &PlumeRocket, post: &Post, kind: Kind<'_>) -> Result<bool> { pub fn matches(&self, conn: &DbConn, post: &Post, kind: Kind<'_>) -> Result<bool> {
let query = TimelineQuery::parse(&self.query)?; let query = TimelineQuery::parse(&self.query)?;
query.matches(rocket, self, post, kind) query.matches(conn, self, post, kind)
} }
} }

View File

@ -1,11 +1,12 @@
use crate::{ use crate::{
blogs::Blog, blogs::Blog,
db_conn::DbConn,
lists::{self, ListType}, lists::{self, ListType},
posts::Post, posts::Post,
tags::Tag, tags::Tag,
timeline::Timeline, timeline::Timeline,
users::User, users::User,
PlumeRocket, Result, Result,
}; };
use plume_common::activity_pub::inbox::AsActor; use plume_common::activity_pub::inbox::AsActor;
use whatlang::{self, Lang}; use whatlang::{self, Lang};
@ -160,19 +161,19 @@ enum TQ<'a> {
impl<'a> TQ<'a> { impl<'a> TQ<'a> {
fn matches( fn matches(
&self, &self,
rocket: &PlumeRocket, conn: &DbConn,
timeline: &Timeline, timeline: &Timeline,
post: &Post, post: &Post,
kind: Kind<'_>, kind: Kind<'_>,
) -> Result<bool> { ) -> Result<bool> {
match self { match self {
TQ::Or(inner) => inner.iter().try_fold(false, |s, e| { TQ::Or(inner) => inner.iter().try_fold(false, |s, e| {
e.matches(rocket, timeline, post, kind).map(|r| s || r) e.matches(conn, timeline, post, kind).map(|r| s || r)
}), }),
TQ::And(inner) => inner.iter().try_fold(true, |s, e| { TQ::And(inner) => inner.iter().try_fold(true, |s, e| {
e.matches(rocket, timeline, post, kind).map(|r| s && r) e.matches(conn, timeline, post, kind).map(|r| s && r)
}), }),
TQ::Arg(inner, invert) => Ok(inner.matches(rocket, timeline, post, kind)? ^ invert), TQ::Arg(inner, invert) => Ok(inner.matches(conn, timeline, post, kind)? ^ invert),
} }
} }
@ -205,15 +206,15 @@ enum Arg<'a> {
impl<'a> Arg<'a> { impl<'a> Arg<'a> {
pub fn matches( pub fn matches(
&self, &self,
rocket: &PlumeRocket, conn: &DbConn,
timeline: &Timeline, timeline: &Timeline,
post: &Post, post: &Post,
kind: Kind<'_>, kind: Kind<'_>,
) -> Result<bool> { ) -> Result<bool> {
match self { match self {
Arg::In(t, l) => t.matches(rocket, timeline, post, l, kind), Arg::In(t, l) => t.matches(conn, timeline, post, l, kind),
Arg::Contains(t, v) => t.matches(post, v), Arg::Contains(t, v) => t.matches(post, v),
Arg::Boolean(t) => t.matches(rocket, timeline, post, kind), Arg::Boolean(t) => t.matches(conn, timeline, post, kind),
} }
} }
} }
@ -230,7 +231,7 @@ enum WithList {
impl WithList { impl WithList {
pub fn matches( pub fn matches(
&self, &self,
rocket: &PlumeRocket, conn: &DbConn,
timeline: &Timeline, timeline: &Timeline,
post: &Post, post: &Post,
list: &List<'_>, list: &List<'_>,
@ -238,39 +239,34 @@ impl WithList {
) -> Result<bool> { ) -> Result<bool> {
match list { match list {
List::List(name) => { List::List(name) => {
let list = let list = lists::List::find_for_user_by_name(conn, timeline.user_id, &name)?;
lists::List::find_for_user_by_name(&rocket.conn, timeline.user_id, &name)?;
match (self, list.kind()) { match (self, list.kind()) {
(WithList::Blog, ListType::Blog) => { (WithList::Blog, ListType::Blog) => list.contains_blog(conn, post.blog_id),
list.contains_blog(&rocket.conn, post.blog_id)
}
(WithList::Author { boosts, likes }, ListType::User) => match kind { (WithList::Author { boosts, likes }, ListType::User) => match kind {
Kind::Original => Ok(list Kind::Original => Ok(list
.list_users(&rocket.conn)? .list_users(conn)?
.iter() .iter()
.any(|a| post.is_author(&rocket.conn, a.id).unwrap_or(false))), .any(|a| post.is_author(conn, a.id).unwrap_or(false))),
Kind::Reshare(u) => { Kind::Reshare(u) => {
if *boosts { if *boosts {
list.contains_user(&rocket.conn, u.id) list.contains_user(conn, u.id)
} else { } else {
Ok(false) Ok(false)
} }
} }
Kind::Like(u) => { Kind::Like(u) => {
if *likes { if *likes {
list.contains_user(&rocket.conn, u.id) list.contains_user(conn, u.id)
} else { } else {
Ok(false) Ok(false)
} }
} }
}, },
(WithList::License, ListType::Word) => { (WithList::License, ListType::Word) => list.contains_word(conn, &post.license),
list.contains_word(&rocket.conn, &post.license)
}
(WithList::Tags, ListType::Word) => { (WithList::Tags, ListType::Word) => {
let tags = Tag::for_post(&rocket.conn, post.id)?; let tags = Tag::for_post(conn, post.id)?;
Ok(list Ok(list
.list_words(&rocket.conn)? .list_words(conn)?
.iter() .iter()
.any(|s| tags.iter().any(|t| s == &t.tag))) .any(|s| tags.iter().any(|t| s == &t.tag)))
} }
@ -285,7 +281,7 @@ impl WithList {
}) })
.unwrap_or(Lang::Eng) .unwrap_or(Lang::Eng)
.name(); .name();
list.contains_prefix(&rocket.conn, lang) list.contains_prefix(conn, lang)
} }
(_, _) => Err(QueryError::RuntimeError(format!( (_, _) => Err(QueryError::RuntimeError(format!(
"The list '{}' is of the wrong type for this usage", "The list '{}' is of the wrong type for this usage",
@ -297,13 +293,13 @@ impl WithList {
List::Array(list) => match self { List::Array(list) => match self {
WithList::Blog => Ok(list WithList::Blog => Ok(list
.iter() .iter()
.filter_map(|b| Blog::find_by_fqn(rocket, b).ok()) .filter_map(|b| Blog::find_by_fqn(conn, b).ok())
.any(|b| b.id == post.blog_id)), .any(|b| b.id == post.blog_id)),
WithList::Author { boosts, likes } => match kind { WithList::Author { boosts, likes } => match kind {
Kind::Original => Ok(list Kind::Original => Ok(list
.iter() .iter()
.filter_map(|a| User::find_by_fqn(rocket, a).ok()) .filter_map(|a| User::find_by_fqn(&*conn, a).ok())
.any(|a| post.is_author(&rocket.conn, a.id).unwrap_or(false))), .any(|a| post.is_author(conn, a.id).unwrap_or(false))),
Kind::Reshare(u) => { Kind::Reshare(u) => {
if *boosts { if *boosts {
Ok(list.iter().any(|user| &u.fqn == user)) Ok(list.iter().any(|user| &u.fqn == user))
@ -321,7 +317,7 @@ impl WithList {
}, },
WithList::License => Ok(list.iter().any(|s| s == &post.license)), WithList::License => Ok(list.iter().any(|s| s == &post.license)),
WithList::Tags => { WithList::Tags => {
let tags = Tag::for_post(&rocket.conn, post.id)?; let tags = Tag::for_post(conn, post.id)?;
Ok(list.iter().any(|s| tags.iter().any(|t| s == &t.tag))) Ok(list.iter().any(|s| tags.iter().any(|t| s == &t.tag)))
} }
WithList::Lang => { WithList::Lang => {
@ -371,7 +367,7 @@ enum Bool {
impl Bool { impl Bool {
pub fn matches( pub fn matches(
&self, &self,
rocket: &PlumeRocket, conn: &DbConn,
timeline: &Timeline, timeline: &Timeline,
post: &Post, post: &Post,
kind: Kind<'_>, kind: Kind<'_>,
@ -384,21 +380,19 @@ impl Bool {
let user = timeline.user_id.unwrap(); let user = timeline.user_id.unwrap();
match kind { match kind {
Kind::Original => post Kind::Original => post
.get_authors(&rocket.conn)? .get_authors(conn)?
.iter() .iter()
.try_fold(false, |s, a| { .try_fold(false, |s, a| a.is_followed_by(conn, user).map(|r| s || r)),
a.is_followed_by(&rocket.conn, user).map(|r| s || r)
}),
Kind::Reshare(u) => { Kind::Reshare(u) => {
if *boosts { if *boosts {
u.is_followed_by(&rocket.conn, user) u.is_followed_by(conn, user)
} else { } else {
Ok(false) Ok(false)
} }
} }
Kind::Like(u) => { Kind::Like(u) => {
if *likes { if *likes {
u.is_followed_by(&rocket.conn, user) u.is_followed_by(conn, user)
} else { } else {
Ok(false) Ok(false)
} }
@ -406,7 +400,7 @@ impl Bool {
} }
} }
Bool::HasCover => Ok(post.cover_id.is_some()), Bool::HasCover => Ok(post.cover_id.is_some()),
Bool::Local => Ok(post.get_blog(&rocket.conn)?.is_local() && kind == Kind::Original), Bool::Local => Ok(post.get_blog(conn)?.is_local() && kind == Kind::Original),
Bool::All => Ok(kind == Kind::Original), Bool::All => Ok(kind == Kind::Original),
} }
} }
@ -642,12 +636,12 @@ impl<'a> TimelineQuery<'a> {
pub fn matches( pub fn matches(
&self, &self,
rocket: &PlumeRocket, conn: &DbConn,
timeline: &Timeline, timeline: &Timeline,
post: &Post, post: &Post,
kind: Kind<'_>, kind: Kind<'_>,
) -> Result<bool> { ) -> Result<bool> {
self.0.matches(rocket, timeline, post, kind) self.0.matches(conn, timeline, post, kind)
} }
pub fn list_used_lists(&self) -> Vec<(String, ListType)> { pub fn list_used_lists(&self) -> Vec<(String, ListType)> {

View File

@ -1,8 +1,8 @@
use crate::{ use crate::{
ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, db_conn::DbConn, follows::Follow, ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, db_conn::DbConn, follows::Follow,
instance::*, medias::Media, notifications::Notification, post_authors::PostAuthor, posts::Post, instance::*, medias::Media, notifications::Notification, post_authors::PostAuthor, posts::Post,
safe_string::SafeString, schema::users, timeline::Timeline, Connection, Error, PlumeRocket, safe_string::SafeString, schema::users, timeline::Timeline, Connection, Error, Result, CONFIG,
Result, CONFIG, ITEMS_PER_PAGE, ITEMS_PER_PAGE,
}; };
use activitypub::{ use activitypub::{
activity::Delete, activity::Delete,
@ -186,29 +186,29 @@ impl User {
users::table users::table
.filter(users::instance_id.eq(Instance::get_local()?.id)) .filter(users::instance_id.eq(Instance::get_local()?.id))
.count() .count()
.get_result(conn) .get_result(&*conn)
.map_err(Error::from) .map_err(Error::from)
} }
pub fn find_by_fqn(c: &PlumeRocket, fqn: &str) -> Result<User> { pub fn find_by_fqn(conn: &DbConn, fqn: &str) -> Result<User> {
let from_db = users::table let from_db = users::table
.filter(users::fqn.eq(fqn)) .filter(users::fqn.eq(fqn))
.first(&*c.conn) .first(&**conn)
.optional()?; .optional()?;
if let Some(from_db) = from_db { if let Some(from_db) = from_db {
Ok(from_db) Ok(from_db)
} else { } else {
User::fetch_from_webfinger(c, fqn) User::fetch_from_webfinger(conn, fqn)
} }
} }
fn fetch_from_webfinger(c: &PlumeRocket, acct: &str) -> Result<User> { fn fetch_from_webfinger(conn: &DbConn, acct: &str) -> Result<User> {
let link = resolve(acct.to_owned(), true)? let link = resolve(acct.to_owned(), true)?
.links .links
.into_iter() .into_iter()
.find(|l| l.mime_type == Some(String::from("application/activity+json"))) .find(|l| l.mime_type == Some(String::from("application/activity+json")))
.ok_or(Error::Webfinger)?; .ok_or(Error::Webfinger)?;
User::from_id(c, link.href.as_ref()?, None, CONFIG.proxy()).map_err(|(_, e)| e) User::from_id(conn, link.href.as_ref()?, None, CONFIG.proxy()).map_err(|(_, e)| e)
} }
pub fn fetch_remote_interact_uri(acct: &str) -> Result<String> { pub fn fetch_remote_interact_uri(acct: &str) -> Result<String> {
@ -243,8 +243,8 @@ impl User {
Ok(json) Ok(json)
} }
pub fn fetch_from_url(c: &PlumeRocket, url: &str) -> Result<User> { pub fn fetch_from_url(conn: &DbConn, url: &str) -> Result<User> {
User::fetch(url).and_then(|json| User::from_activity(c, json)) User::fetch(url).and_then(|json| User::from_activity(conn, json))
} }
pub fn refetch(&self, conn: &Connection) -> Result<()> { pub fn refetch(&self, conn: &Connection) -> Result<()> {
@ -915,20 +915,20 @@ impl IntoId for User {
impl Eq for User {} impl Eq for User {}
impl FromId<PlumeRocket> for User { impl FromId<DbConn> for User {
type Error = Error; type Error = Error;
type Object = CustomPerson; type Object = CustomPerson;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> { fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
Self::find_by_ap_url(&c.conn, id) Self::find_by_ap_url(conn, id)
} }
fn from_activity(c: &PlumeRocket, acct: CustomPerson) -> Result<Self> { fn from_activity(conn: &DbConn, acct: CustomPerson) -> Result<Self> {
let url = Url::parse(&acct.object.object_props.id_string()?)?; let url = Url::parse(&acct.object.object_props.id_string()?)?;
let inst = url.host_str()?; let inst = url.host_str()?;
let instance = Instance::find_by_domain(&c.conn, inst).or_else(|_| { let instance = Instance::find_by_domain(conn, inst).or_else(|_| {
Instance::insert( Instance::insert(
&c.conn, conn,
NewInstance { NewInstance {
name: inst.to_owned(), name: inst.to_owned(),
public_domain: inst.to_owned(), public_domain: inst.to_owned(),
@ -957,7 +957,7 @@ impl FromId<PlumeRocket> for User {
}; };
let user = User::insert( let user = User::insert(
&c.conn, conn,
NewUser { NewUser {
display_name: acct display_name: acct
.object .object
@ -1003,10 +1003,10 @@ impl FromId<PlumeRocket> for User {
if let Ok(icon) = acct.object.object_props.icon_image() { if let Ok(icon) = acct.object.object_props.icon_image() {
if let Ok(url) = icon.object_props.url_string() { if let Ok(url) = icon.object_props.url_string() {
let avatar = Media::save_remote(&c.conn, url, &user); let avatar = Media::save_remote(conn, url, &user);
if let Ok(avatar) = avatar { if let Ok(avatar) = avatar {
user.set_avatar(&c.conn, avatar.id)?; user.set_avatar(conn, avatar.id)?;
} }
} }
} }
@ -1015,7 +1015,7 @@ impl FromId<PlumeRocket> for User {
} }
} }
impl AsActor<&PlumeRocket> for User { impl AsActor<&DbConn> for User {
fn get_inbox_url(&self) -> String { fn get_inbox_url(&self) -> String {
self.inbox_url.clone() self.inbox_url.clone()
} }
@ -1031,13 +1031,13 @@ impl AsActor<&PlumeRocket> for User {
} }
} }
impl AsObject<User, Delete, &PlumeRocket> for User { impl AsObject<User, Delete, &DbConn> for User {
type Error = Error; type Error = Error;
type Output = (); type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
if self.id == actor.id { if self.id == actor.id {
self.delete(&c.conn).map(|_| ()) self.delete(conn).map(|_| ())
} else { } else {
Err(Error::Unauthorized) Err(Error::Unauthorized)
} }