Replace PlumeRocket with DbConn where possible
This commit is contained in:
parent
5d25a64f13
commit
25e52788c5
@ -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),
|
||||||
|
@ -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,
|
||||||
¬e.object_props.attributed_to_link::<Id>()?,
|
¬e.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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(¬if).execute(conn)?;
|
diesel::delete(¬if).execute(&**conn)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -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())
|
||||||
|
@ -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(¬if).execute(conn)?;
|
diesel::delete(¬if).execute(&**conn)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -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>()
|
||||||
|
@ -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))?;
|
||||||
|
@ -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
|
||||||
|
@ -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(¬if).execute(conn)?;
|
diesel::delete(¬if).execute(&**conn)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)> {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user