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::{
ap_url, instance::*, medias::Media, posts::Post, safe_string::SafeString, schema::blogs,
users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE,
ap_url, db_conn::DbConn, instance::*, medias::Media, posts::Post, safe_string::SafeString,
schema::blogs, users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE,
};
use activitypub::{
actor::Group,
@ -131,25 +131,25 @@ impl Blog {
.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
.filter(blogs::fqn.eq(fqn))
.first(&*c.conn)
.first(&**conn)
.optional()?;
if let Some(from_db) = from_db {
Ok(from_db)
} 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)?
.links
.into_iter()
.find(|l| l.mime_type == Some(String::from("application/activity+json")))
.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> {
@ -334,20 +334,20 @@ impl IntoId for Blog {
}
}
impl FromId<PlumeRocket> for Blog {
impl FromId<DbConn> for Blog {
type Error = Error;
type Object = CustomGroup;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> {
Self::find_by_ap_url(&c.conn, id)
fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
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 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(
&c.conn,
conn,
NewInstance {
public_domain: inst.to_owned(),
name: inst.to_owned(),
@ -370,9 +370,9 @@ impl FromId<PlumeRocket> for Blog {
.and_then(|icon| {
let owner = icon.object_props.attributed_to_link::<Id>().ok()?;
Media::save_remote(
&c.conn,
conn,
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()
})
@ -386,9 +386,9 @@ impl FromId<PlumeRocket> for Blog {
.and_then(|banner| {
let owner = banner.object_props.attributed_to_link::<Id>().ok()?;
Media::save_remote(
&c.conn,
conn,
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()
})
@ -400,7 +400,7 @@ impl FromId<PlumeRocket> for Blog {
}
Blog::insert(
&c.conn,
conn,
NewBlog {
actor_id: name.clone(),
title: acct.object.object_props.name_string().unwrap_or(name),

View File

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

View File

@ -1,6 +1,6 @@
use crate::{
ap_url, notifications::*, schema::follows, users::User, Connection, Error, PlumeRocket, Result,
CONFIG,
ap_url, db_conn::DbConn, notifications::*, schema::follows, users::User, Connection, Error,
Result, CONFIG,
};
use activitypub::activity::{Accept, Follow as FollowAct, Undo};
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 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,
// so we rebuilt it here
let mut follow = FollowAct::default();
@ -153,21 +153,21 @@ impl AsObject<User, FollowAct, &PlumeRocket> for User {
follow
.follow_props
.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 Object = FollowAct;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> {
Follow::find_by_ap_url(&c.conn, id)
fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
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(
c,
conn,
&follow.follow_props.actor_link::<Id>()?,
None,
CONFIG.proxy(),
@ -175,28 +175,28 @@ impl FromId<PlumeRocket> for Follow {
.map_err(|(_, e)| e)?;
let target = User::from_id(
c,
conn,
&follow.follow_props.object_link::<Id>()?,
None,
CONFIG.proxy(),
)
.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 Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> {
let conn = &*c.conn;
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
let conn = conn;
if self.follower_id == actor.id {
diesel::delete(&self).execute(conn)?;
diesel::delete(&self).execute(&**conn)?;
// delete associated notification if any
if let Ok(notif) = Notification::find(conn, notification_kind::FOLLOW, self.id) {
diesel::delete(&notif).execute(conn)?;
if let Ok(notif) = Notification::find(&conn, notification_kind::FOLLOW, self.id) {
diesel::delete(&notif).execute(&**conn)?;
}
Ok(())

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,9 @@
use crate::{
db_conn::DbConn,
lists::List,
posts::Post,
schema::{posts, timeline, timeline_definition},
Connection, Error, PlumeRocket, Result,
Connection, Error, Result,
};
use diesel::{self, BoolExpressionMethods, ExpressionMethods, QueryDsl, RunQueryDsl};
use std::ops::Deref;
@ -208,14 +209,14 @@ impl Timeline {
.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
.load::<Self>(rocket.conn.deref())
.load::<Self>(conn.deref())
.map_err(Error::from)?;
for t in timelines {
if t.matches(rocket, post, kind)? {
t.add_post(&rocket.conn, post)?;
if t.matches(conn, post, kind)? {
t.add_post(conn, post)?;
}
}
Ok(())
@ -231,9 +232,9 @@ impl Timeline {
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)?;
query.matches(rocket, self, post, kind)
query.matches(conn, self, post, kind)
}
}

View File

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

View File

@ -1,8 +1,8 @@
use crate::{
ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, db_conn::DbConn, follows::Follow,
instance::*, medias::Media, notifications::Notification, post_authors::PostAuthor, posts::Post,
safe_string::SafeString, schema::users, timeline::Timeline, Connection, Error, PlumeRocket,
Result, CONFIG, ITEMS_PER_PAGE,
safe_string::SafeString, schema::users, timeline::Timeline, Connection, Error, Result, CONFIG,
ITEMS_PER_PAGE,
};
use activitypub::{
activity::Delete,
@ -186,29 +186,29 @@ impl User {
users::table
.filter(users::instance_id.eq(Instance::get_local()?.id))
.count()
.get_result(conn)
.get_result(&*conn)
.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
.filter(users::fqn.eq(fqn))
.first(&*c.conn)
.first(&**conn)
.optional()?;
if let Some(from_db) = from_db {
Ok(from_db)
} 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)?
.links
.into_iter()
.find(|l| l.mime_type == Some(String::from("application/activity+json")))
.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> {
@ -243,8 +243,8 @@ impl User {
Ok(json)
}
pub fn fetch_from_url(c: &PlumeRocket, url: &str) -> Result<User> {
User::fetch(url).and_then(|json| User::from_activity(c, json))
pub fn fetch_from_url(conn: &DbConn, url: &str) -> Result<User> {
User::fetch(url).and_then(|json| User::from_activity(conn, json))
}
pub fn refetch(&self, conn: &Connection) -> Result<()> {
@ -915,20 +915,20 @@ impl IntoId for User {
impl Eq for User {}
impl FromId<PlumeRocket> for User {
impl FromId<DbConn> for User {
type Error = Error;
type Object = CustomPerson;
fn from_db(c: &PlumeRocket, id: &str) -> Result<Self> {
Self::find_by_ap_url(&c.conn, id)
fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
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 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(
&c.conn,
conn,
NewInstance {
name: inst.to_owned(),
public_domain: inst.to_owned(),
@ -957,7 +957,7 @@ impl FromId<PlumeRocket> for User {
};
let user = User::insert(
&c.conn,
conn,
NewUser {
display_name: acct
.object
@ -1003,10 +1003,10 @@ impl FromId<PlumeRocket> for User {
if let Ok(icon) = acct.object.object_props.icon_image() {
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 {
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 {
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 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 {
self.delete(&c.conn).map(|_| ())
self.delete(conn).map(|_| ())
} else {
Err(Error::Unauthorized)
}