Introduce features to choose between SQlite or Postgres

This commit is contained in:
Bat 2018-09-26 16:22:42 +01:00 committed by Igor Galić
parent 88456faf84
commit 38d737ed0c
No known key found for this signature in database
GPG key ID: ACFEFF7F6A123A86
20 changed files with 265 additions and 239 deletions

View file

@ -62,5 +62,10 @@ rev = "b326a9893a1849c9abdb39cab9fd7c4a52eb9674"
git = "https://github.com/BaptisteGelez/rocket_i18n"
rev = "75a3bfd7b847324c078a355a7f101f8241a9f59b"
[features]
default = ["postgres"]
postgres = ["plume-models/postgres"]
sqlite = ["plume-models/sqlite"]
[workspace]
members = ["plume-api", "plume-models", "plume-common"]

View file

@ -3,6 +3,6 @@ CREATE TABLE likes (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
ap_url VARCHAR NOT NULL default '',
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR NOT NULL default ''
)

View file

@ -23,7 +23,7 @@ features = ["serde"]
version = "0.4"
[dependencies.diesel]
features = ["postgres", "sqlite", "r2d2", "chrono"]
features = ["r2d2", "chrono"]
version = "1.3.2"
[dependencies.plume-api]
@ -35,3 +35,8 @@ path = "../plume-common"
[dependencies.rocket]
git = "https://github.com/SergioBenitez/Rocket"
rev = "55459db7732b9a240826a5c120c650f87e3372ce"
[features]
default = ["postgres"]
postgres = ["diesel/postgres"]
sqlite = ["diesel/sqlite"]

View file

@ -1,4 +1,4 @@
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods, PgConnection};
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods};
use schema::blog_authors;

View file

@ -6,8 +6,7 @@ use reqwest::{
};
use serde_json;
use url::Url;
use chrono::NaiveDateTime;
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods, PgConnection, dsl::any};
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods, dsl::any};
use openssl::{
hash::MessageDigest,
pkey::{PKey, Private},
@ -16,7 +15,7 @@ use openssl::{
};
use webfinger::*;
use {BASE_URL, USE_HTTPS};
use {BASE_URL, USE_HTTPS, Connection, SqlDateTime};
use plume_common::activity_pub::{
ap_accept_header, ApSignature, ActivityStream, Id, IntoId, PublicKey,
inbox::WithInbox,
@ -38,7 +37,7 @@ pub struct Blog {
pub outbox_url: String,
pub inbox_url: String,
pub instance_id: i32,
pub creation_date: NaiveDateTime,
pub creation_date: SqlDateTime,
pub ap_url: String,
pub private_key: Option<String>,
pub public_key: String
@ -66,11 +65,11 @@ impl Blog {
find_by!(blogs, find_by_ap_url, ap_url as String);
find_by!(blogs, find_by_name, actor_id as String, instance_id as i32);
pub fn get_instance(&self, conn: &PgConnection) -> Instance {
pub fn get_instance(&self, conn: &Connection) -> Instance {
Instance::get(conn, self.instance_id).expect("Couldn't find instance")
}
pub fn list_authors(&self, conn: &PgConnection) -> Vec<User> {
pub fn list_authors(&self, conn: &Connection) -> Vec<User> {
use schema::blog_authors;
use schema::users;
let authors_ids = blog_authors::table.filter(blog_authors::blog_id.eq(self.id)).select(blog_authors::author_id);
@ -79,7 +78,7 @@ impl Blog {
.expect("Couldn't load authors of a blog")
}
pub fn find_for_author(conn: &PgConnection, author_id: i32) -> Vec<Blog> {
pub fn find_for_author(conn: &Connection, author_id: i32) -> Vec<Blog> {
use schema::blog_authors;
let author_ids = blog_authors::table.filter(blog_authors::author_id.eq(author_id)).select(blog_authors::blog_id);
blogs::table.filter(blogs::id.eq(any(author_ids)))
@ -87,11 +86,11 @@ impl Blog {
.expect("Couldn't load blogs ")
}
pub fn find_local(conn: &PgConnection, name: String) -> Option<Blog> {
pub fn find_local(conn: &Connection, name: String) -> Option<Blog> {
Blog::find_by_name(conn, name, Instance::local_id(conn))
}
pub fn find_by_fqn(conn: &PgConnection, fqn: String) -> Option<Blog> {
pub fn find_by_fqn(conn: &Connection, fqn: String) -> Option<Blog> {
if fqn.contains("@") { // remote blog
match Instance::find_by_domain(conn, String::from(fqn.split("@").last().unwrap())) {
Some(instance) => {
@ -107,7 +106,7 @@ impl Blog {
}
}
fn fetch_from_webfinger(conn: &PgConnection, acct: String) -> Option<Blog> {
fn fetch_from_webfinger(conn: &Connection, acct: String) -> Option<Blog> {
match resolve(acct.clone(), *USE_HTTPS) {
Ok(wf) => wf.links.into_iter().find(|l| l.mime_type == Some(String::from("application/activity+json"))).and_then(|l| Blog::fetch_from_url(conn, l.href.expect("No href for AP WF link"))),
Err(details) => {
@ -117,7 +116,7 @@ impl Blog {
}
}
fn fetch_from_url(conn: &PgConnection, url: String) -> Option<Blog> {
fn fetch_from_url(conn: &Connection, url: String) -> Option<Blog> {
let req = Client::new()
.get(&url[..])
.header(Accept(ap_accept_header().into_iter().map(|h| qitem(h.parse::<Mime>().expect("Invalid Content-Type"))).collect()))
@ -134,7 +133,7 @@ impl Blog {
}
}
fn from_activity(conn: &PgConnection, acct: CustomGroup, inst: String) -> Blog {
fn from_activity(conn: &Connection, acct: CustomGroup, inst: String) -> Blog {
let instance = match Instance::find_by_domain(conn, inst.clone()) {
Some(instance) => instance,
None => {
@ -166,7 +165,7 @@ impl Blog {
})
}
pub fn into_activity(&self, _conn: &PgConnection) -> CustomGroup {
pub fn into_activity(&self, _conn: &Connection) -> CustomGroup {
let mut blog = Group::default();
blog.ap_actor_props.set_preferred_username_string(self.actor_id.clone()).expect("Blog::into_activity: preferredUsername error");
blog.object_props.set_name_string(self.title.clone()).expect("Blog::into_activity: name error");
@ -185,7 +184,7 @@ impl Blog {
CustomGroup::new(blog, ap_signature)
}
pub fn update_boxes(&self, conn: &PgConnection) {
pub fn update_boxes(&self, conn: &Connection) {
let instance = self.get_instance(conn);
if self.outbox_url.len() == 0 {
diesel::update(self)
@ -206,14 +205,14 @@ impl Blog {
}
}
pub fn outbox(&self, conn: &PgConnection) -> ActivityStream<OrderedCollection> {
pub fn outbox(&self, conn: &Connection) -> ActivityStream<OrderedCollection> {
let mut coll = OrderedCollection::default();
coll.collection_props.items = serde_json::to_value(self.get_activities(conn)).unwrap();
coll.collection_props.set_total_items_u64(self.get_activities(conn).len() as u64).unwrap();
ActivityStream::new(coll)
}
fn get_activities(&self, _conn: &PgConnection) -> Vec<serde_json::Value> {
fn get_activities(&self, _conn: &Connection) -> Vec<serde_json::Value> {
vec![]
}
@ -221,7 +220,7 @@ impl Blog {
PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.clone().unwrap().as_ref()).unwrap()).unwrap()
}
pub fn webfinger(&self, conn: &PgConnection) -> Webfinger {
pub fn webfinger(&self, conn: &Connection) -> Webfinger {
Webfinger {
subject: format!("acct:{}@{}", self.actor_id, self.get_instance(conn).public_domain),
aliases: vec![self.ap_url.clone()],
@ -248,7 +247,7 @@ impl Blog {
}
}
pub fn from_url(conn: &PgConnection, url: String) -> Option<Blog> {
pub fn from_url(conn: &Connection, url: String) -> Option<Blog> {
Blog::find_by_ap_url(conn, url.clone()).or_else(|| {
// The requested user was not in the DB
// We try to fetch it if it is remote
@ -260,7 +259,7 @@ impl Blog {
})
}
pub fn get_fqn(&self, conn: &PgConnection) -> String {
pub fn get_fqn(&self, conn: &Connection) -> String {
if self.instance_id == Instance::local_id(conn) {
self.actor_id.clone()
} else {
@ -268,7 +267,7 @@ impl Blog {
}
}
pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value {
pub fn to_json(&self, conn: &Connection) -> serde_json::Value {
let mut json = serde_json::to_value(self).unwrap();
json["fqn"] = json!(self.get_fqn(conn));
json

View file

@ -12,6 +12,7 @@ use plume_common::activity_pub::{
inbox::{FromActivity, Notify}
};
use plume_common::utils;
use {Connection, SqlDateTime};
use instance::Instance;
use mentions::Mention;
use notifications::*;
@ -27,7 +28,7 @@ pub struct Comment {
pub in_response_to_id: Option<i32>,
pub post_id: i32,
pub author_id: i32,
pub creation_date: chrono::NaiveDateTime,
pub creation_date: SqlDateTime,
pub ap_url: Option<String>,
pub sensitive: bool,
pub spoiler_text: String
@ -51,15 +52,15 @@ impl Comment {
list_by!(comments, list_by_post, post_id as i32);
find_by!(comments, find_by_ap_url, ap_url as String);
pub fn get_author(&self, conn: &PgConnection) -> User {
pub fn get_author(&self, conn: &Connection) -> User {
User::get(conn, self.author_id).unwrap()
}
pub fn get_post(&self, conn: &PgConnection) -> Post {
pub fn get_post(&self, conn: &Connection) -> Post {
Post::get(conn, self.post_id).unwrap()
}
pub fn count_local(conn: &PgConnection) -> usize {
pub fn count_local(conn: &Connection) -> usize {
use schema::users;
let local_authors = users::table.filter(users::instance_id.eq(Instance::local_id(conn))).select(users::id);
comments::table.filter(comments::author_id.eq(any(local_authors)))
@ -68,7 +69,7 @@ impl Comment {
.len()
}
pub fn to_json(&self, conn: &PgConnection, others: &Vec<Comment>) -> serde_json::Value {
pub fn to_json(&self, conn: &Connection, others: &Vec<Comment>) -> serde_json::Value {
let mut json = serde_json::to_value(self).unwrap();
json["author"] = self.get_author(conn).to_json(conn);
let mentions = Mention::list_for_comment(conn, self.id).into_iter()
@ -82,7 +83,7 @@ impl Comment {
json
}
pub fn update_ap_url(&self, conn: &PgConnection) -> Comment {
pub fn update_ap_url(&self, conn: &Connection) -> Comment {
if self.ap_url.is_none() {
diesel::update(self)
.set(comments::ap_url.eq(self.compute_id(conn)))
@ -93,11 +94,11 @@ impl Comment {
}
}
pub fn compute_id(&self, conn: &PgConnection) -> String {
pub fn compute_id(&self, conn: &Connection) -> String {
format!("{}comment/{}", self.get_post(conn).ap_url, self.id)
}
pub fn into_activity(&self, conn: &PgConnection) -> Note {
pub fn into_activity(&self, conn: &Connection) -> Note {
let (html, mentions) = utils::md_to_html(self.content.get().as_ref());
let author = User::get(conn, self.author_id).unwrap();
@ -119,7 +120,7 @@ impl Comment {
note
}
pub fn create_activity(&self, conn: &PgConnection) -> Create {
pub fn create_activity(&self, conn: &Connection) -> Create {
let author = User::get(conn, self.author_id).unwrap();
let note = self.into_activity(conn);
@ -134,7 +135,7 @@ impl Comment {
}
impl FromActivity<Note, PgConnection> for Comment {
fn from_activity(conn: &PgConnection, note: Note, actor: Id) -> Comment {
fn from_activity(conn: &Connection, note: Note, actor: Id) -> Comment {
let previous_url = note.object_props.in_reply_to.clone().unwrap().as_str().unwrap().to_string();
let previous_comment = Comment::find_by_ap_url(conn, previous_url.clone());
@ -168,7 +169,7 @@ impl FromActivity<Note, PgConnection> for Comment {
}
impl Notify<PgConnection> for Comment {
fn notify(&self, conn: &PgConnection) {
fn notify(&self, conn: &Connection) {
for author in self.get_post(conn).get_authors(conn) {
Notification::insert(conn, NewNotification {
kind: notification_kind::COMMENT.to_string(),

View file

@ -27,7 +27,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
}
}
// For the convenience of using an &DbConn as an &PgConnection.
// For the convenience of using an &DbConn as an &Connection.
impl Deref for DbConn {
type Target = PgConnection;

View file

@ -2,6 +2,7 @@ use activitypub::{Actor, activity::{Accept, Follow as FollowAct, Undo}, actor::P
use diesel::{self, PgConnection, ExpressionMethods, QueryDsl, RunQueryDsl};
use plume_common::activity_pub::{broadcast, Id, IntoId, inbox::{FromActivity, Notify, WithInbox, Deletable}, sign::Signer};
use Connection;
use blogs::Blog;
use notifications::*;
use users::User;
@ -29,14 +30,14 @@ impl Follow {
get!(follows);
find_by!(follows, find_by_ap_url, ap_url as String);
pub fn find(conn: &PgConnection, from: i32, to: i32) -> Option<Follow> {
pub fn find(conn: &Connection, from: i32, to: i32) -> Option<Follow> {
follows::table.filter(follows::follower_id.eq(from))
.filter(follows::following_id.eq(to))
.get_result(conn)
.ok()
}
pub fn into_activity(&self, conn: &PgConnection) -> FollowAct {
pub fn into_activity(&self, conn: &Connection) -> FollowAct {
let user = User::get(conn, self.follower_id).unwrap();
let target = User::get(conn, self.following_id).unwrap();
@ -52,7 +53,7 @@ impl Follow {
/// from -> The one sending the follow request
/// target -> The target of the request, responding with Accept
pub fn accept_follow<A: Signer + IntoId + Clone, B: Clone + WithInbox + Actor + IntoId>(
conn: &PgConnection,
conn: &Connection,
from: &B,
target: &A,
follow: FollowAct,
@ -80,7 +81,7 @@ impl Follow {
}
impl FromActivity<FollowAct, PgConnection> for Follow {
fn from_activity(conn: &PgConnection, follow: FollowAct, _actor: Id) -> Follow {
fn from_activity(conn: &Connection, follow: FollowAct, _actor: Id) -> Follow {
let from_id = follow.follow_props.actor_link::<Id>().map(|l| l.into())
.unwrap_or_else(|_| follow.follow_props.actor_object::<Person>().expect("No actor object (nor ID) on Follow").object_props.id_string().expect("No ID on actor on Follow"));
let from = User::from_url(conn, from_id).unwrap();
@ -95,7 +96,7 @@ impl FromActivity<FollowAct, PgConnection> for Follow {
}
impl Notify<PgConnection> for Follow {
fn notify(&self, conn: &PgConnection) {
fn notify(&self, conn: &Connection) {
Notification::insert(conn, NewNotification {
kind: notification_kind::FOLLOW.to_string(),
object_id: self.id,
@ -105,7 +106,7 @@ impl Notify<PgConnection> for Follow {
}
impl Deletable<PgConnection, Undo> for Follow {
fn delete(&self, conn: &PgConnection) -> Undo {
fn delete(&self, conn: &Connection) -> Undo {
diesel::delete(self).execute(conn).expect("Coudn't delete follow");
// delete associated notification if any
@ -120,7 +121,7 @@ impl Deletable<PgConnection, Undo> for Follow {
undo
}
fn delete_id(id: String, conn: &PgConnection) {
fn delete_id(id: String, conn: &Connection) {
if let Some(follow) = Follow::find_by_ap_url(conn, id) {
follow.delete(conn);
}

View file

@ -1,8 +1,8 @@
use chrono::NaiveDateTime;
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods, PgConnection};
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods};
use std::iter::Iterator;
use plume_common::utils::md_to_html;
use {Connection, SqlDateTime};
use safe_string::SafeString;
use ap_url;
use users::User;
@ -15,7 +15,7 @@ pub struct Instance {
pub name: String,
pub local: bool,
pub blocked: bool,
pub creation_date: NaiveDateTime,
pub creation_date: SqlDateTime,
pub open_registrations: bool,
pub short_description: SafeString,
pub long_description: SafeString,
@ -39,7 +39,7 @@ pub struct NewInstance {
}
impl Instance {
pub fn get_local(conn: &PgConnection) -> Option<Instance> {
pub fn get_local(conn: &Connection) -> Option<Instance> {
instances::table.filter(instances::local.eq(true))
.limit(1)
.load::<Instance>(conn)
@ -47,13 +47,13 @@ impl Instance {
.into_iter().nth(0)
}
pub fn get_remotes(conn: &PgConnection) -> Vec<Instance> {
pub fn get_remotes(conn: &Connection) -> Vec<Instance> {
instances::table.filter(instances::local.eq(false))
.load::<Instance>(conn)
.expect("Error loading remote instances infos")
}
pub fn page(conn: &PgConnection, (min, max): (i32, i32)) -> Vec<Instance> {
pub fn page(conn: &Connection, (min, max): (i32, i32)) -> Vec<Instance> {
instances::table.order(instances::public_domain.asc())
.offset(min.into())
.limit((max - min).into())
@ -61,7 +61,7 @@ impl Instance {
.expect("Error loading a page of instances")
}
pub fn local_id(conn: &PgConnection) -> i32 {
pub fn local_id(conn: &Connection) -> i32 {
Instance::get_local(conn).unwrap().id
}
@ -69,7 +69,7 @@ impl Instance {
get!(instances);
find_by!(instances, find_by_domain, public_domain as String);
pub fn toggle_block(&self, conn: &PgConnection) {
pub fn toggle_block(&self, conn: &Connection) {
diesel::update(self)
.set(instances::blocked.eq(!self.blocked))
.get_result::<Instance>(conn)
@ -77,7 +77,7 @@ impl Instance {
}
/// id: AP object id
pub fn is_blocked(conn: &PgConnection, id: String) -> bool {
pub fn is_blocked(conn: &Connection, id: String) -> bool {
for block in instances::table.filter(instances::blocked.eq(true))
.get_results::<Instance>(conn)
.expect("Error listing blocked instances") {
@ -89,7 +89,7 @@ impl Instance {
false
}
pub fn has_admin(&self, conn: &PgConnection) -> bool {
pub fn has_admin(&self, conn: &Connection) -> bool {
users::table.filter(users::instance_id.eq(self.id))
.filter(users::is_admin.eq(true))
.load::<User>(conn)
@ -97,7 +97,7 @@ impl Instance {
.len() > 0
}
pub fn main_admin(&self, conn: &PgConnection) -> User {
pub fn main_admin(&self, conn: &Connection) -> User {
users::table.filter(users::instance_id.eq(self.id))
.filter(users::is_admin.eq(true))
.limit(1)
@ -115,7 +115,7 @@ impl Instance {
))
}
pub fn update(&self, conn: &PgConnection, name: String, open_registrations: bool, short_description: SafeString, long_description: SafeString) -> Instance {
pub fn update(&self, conn: &Connection, name: String, open_registrations: bool, short_description: SafeString, long_description: SafeString) -> Instance {
let (sd, _) = md_to_html(short_description.as_ref());
let (ld, _) = md_to_html(long_description.as_ref());
diesel::update(self)
@ -130,7 +130,7 @@ impl Instance {
.expect("Couldn't update instance")
}
pub fn count(conn: &PgConnection) -> i64 {
pub fn count(conn: &Connection) -> i64 {
instances::table.count().get_result(conn).expect("Couldn't count instances")
}
}

View file

@ -1,4 +1,5 @@
#![allow(proc_macro_derive_resolution_fallback)] // This can be removed after diesel-1.4
#![feature(crate_in_paths)]
extern crate activitypub;
extern crate ammonia;
@ -28,7 +29,7 @@ use std::env;
macro_rules! find_by {
($table:ident, $fn:ident, $($col:ident as $type:ident),+) => {
/// Try to find a $table with a given $col
pub fn $fn(conn: &PgConnection, $($col: $type),+) -> Option<Self> {
pub fn $fn(conn: &crate::Connection, $($col: $type),+) -> Option<Self> {
$table::table
$(.filter($table::$col.eq($col)))+
.limit(1)
@ -42,7 +43,7 @@ macro_rules! find_by {
macro_rules! list_by {
($table:ident, $fn:ident, $($col:ident as $type:ident),+) => {
/// Try to find a $table with a given $col
pub fn $fn(conn: &PgConnection, $($col: $type),+) -> Vec<Self> {
pub fn $fn(conn: &crate::Connection, $($col: $type),+) -> Vec<Self> {
$table::table
$(.filter($table::$col.eq($col)))+
.load::<Self>(conn)
@ -53,7 +54,7 @@ macro_rules! list_by {
macro_rules! get {
($table:ident) => {
pub fn get(conn: &PgConnection, id: i32) -> Option<Self> {
pub fn get(conn: &crate::Connection, id: i32) -> Option<Self> {
$table::table.filter($table::id.eq(id))
.limit(1)
.load::<Self>(conn)
@ -65,7 +66,7 @@ macro_rules! get {
macro_rules! insert {
($table:ident, $from:ident) => {
pub fn insert(conn: &PgConnection, new: $from) -> Self {
pub fn insert(conn: &crate::Connection, new: $from) -> Self {
diesel::insert_into($table::table)
.values(new)
.get_result(conn)
@ -76,7 +77,7 @@ macro_rules! insert {
macro_rules! update {
($table:ident) => {
pub fn update(&self, conn: &PgConnection) -> Self {
pub fn update(&self, conn: &crate::Connection) -> Self {
diesel::update(self)
.set(self)
.get_result(conn)
@ -104,6 +105,18 @@ pub fn ap_url(url: String) -> String {
format!("{}://{}", scheme, url)
}
#[cfg(all(not(feature = "postgres"), feature = "sqlite"))]
pub type SqlDateTime = chrono::NaiveDateTime;
#[cfg(all(not(feature = "postgres"), feature = "sqlite"))]
pub type Connection = diesel::SqliteConnection;
#[cfg(all(not(feature = "sqlite"), feature = "postgres"))]
pub type SqlDateTime = chrono::NaiveDateTime;
#[cfg(all(not(feature = "sqlite"), feature = "postgres"))]
pub type Connection = diesel::PgConnection;
pub mod admin;
pub mod blog_authors;
pub mod blogs;

View file

@ -1,6 +1,6 @@
use activitypub::activity;
use chrono;
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
use chrono::NaiveDateTime;
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods};
use plume_common::activity_pub::{
PUBLIC_VISIBILTY,
@ -8,6 +8,7 @@ use plume_common::activity_pub::{
IntoId,
inbox::{FromActivity, Deletable, Notify}
};
use Connection;
use notifications::*;
use posts::Post;
use users::User;
@ -18,7 +19,7 @@ pub struct Like {
pub id: i32,
pub user_id: i32,
pub post_id: i32,
pub creation_date: chrono::NaiveDateTime,
pub creation_date: NaiveDateTime,
pub ap_url: String
}
@ -36,7 +37,7 @@ impl Like {
find_by!(likes, find_by_ap_url, ap_url as String);
find_by!(likes, find_by_user_on_post, user_id as i32, post_id as i32);
pub fn update_ap_url(&self, conn: &PgConnection) {
pub fn update_ap_url(&self, conn: &Connection) {
if self.ap_url.len() == 0 {
diesel::update(self)
.set(likes::ap_url.eq(format!(
@ -48,7 +49,7 @@ impl Like {
}
}
pub fn into_activity(&self, conn: &PgConnection) -> activity::Like {
pub fn into_activity(&self, conn: &Connection) -> activity::Like {
let mut act = activity::Like::default();
act.like_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::into_activity: actor error");
act.like_props.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).expect("Like::into_activity: object error");
@ -60,8 +61,8 @@ impl Like {
}
}
impl FromActivity<activity::Like, PgConnection> for Like {
fn from_activity(conn: &PgConnection, like: activity::Like, _actor: Id) -> Like {
impl FromActivity<activity::Like, Connection> for Like {
fn from_activity(conn: &Connection, like: activity::Like, _actor: Id) -> Like {
let liker = User::from_url(conn, like.like_props.actor.as_str().unwrap().to_string());
let post = Post::find_by_ap_url(conn, like.like_props.object.as_str().unwrap().to_string());
let res = Like::insert(conn, NewLike {
@ -74,8 +75,8 @@ impl FromActivity<activity::Like, PgConnection> for Like {
}
}
impl Notify<PgConnection> for Like {
fn notify(&self, conn: &PgConnection) {
impl Notify<Connection> for Like {
fn notify(&self, conn: &Connection) {
let post = Post::get(conn, self.post_id).unwrap();
for author in post.get_authors(conn) {
Notification::insert(conn, NewNotification {
@ -87,8 +88,8 @@ impl Notify<PgConnection> for Like {
}
}
impl Deletable<PgConnection, activity::Undo> for Like {
fn delete(&self, conn: &PgConnection) -> activity::Undo {
impl Deletable<Connection, activity::Undo> for Like {
fn delete(&self, conn: &Connection) -> activity::Undo {
diesel::delete(self).execute(conn).unwrap();
// delete associated notification if any
@ -106,7 +107,7 @@ impl Deletable<PgConnection, activity::Undo> for Like {
act
}
fn delete_id(id: String, conn: &PgConnection) {
fn delete_id(id: String, conn: &Connection) {
if let Some(like) = Like::find_by_ap_url(conn, id.into()) {
like.delete(conn);
}

View file

@ -1,8 +1,8 @@
use diesel::{self, PgConnection, QueryDsl, ExpressionMethods, RunQueryDsl};
use diesel::{self, QueryDsl, ExpressionMethods, RunQueryDsl};
use serde_json;
use std::fs;
use ap_url;
use {ap_url, Connection};
use instance::Instance;
use schema::medias;
@ -35,7 +35,7 @@ impl Media {
get!(medias);
list_by!(medias, for_user, owner_id as i32);
pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value {
pub fn to_json(&self, conn: &Connection) -> serde_json::Value {
let mut json = serde_json::to_value(self).unwrap();
let url = self.url(conn);
let (preview, html, md) = match self.file_path.rsplitn(2, '.').next().unwrap() {
@ -63,7 +63,7 @@ impl Media {
json
}
pub fn url(&self, conn: &PgConnection) -> String {
pub fn url(&self, conn: &Connection) -> String {
if self.is_remote {
self.remote_url.clone().unwrap_or(String::new())
} else {
@ -71,12 +71,12 @@ impl Media {
}
}
pub fn delete(&self, conn: &PgConnection) {
pub fn delete(&self, conn: &Connection) {
fs::remove_file(self.file_path.as_str()).expect("Couldn't delete media from disk");
diesel::delete(self).execute(conn).expect("Couldn't remove media from DB");
}
pub fn save_remote(conn: &PgConnection, url: String) -> Media {
pub fn save_remote(conn: &Connection, url: String) -> Media {
Media::insert(conn, NewMedia {
file_path: String::new(),
alt_text: String::new(),
@ -88,7 +88,7 @@ impl Media {
})
}
pub fn set_owner(&self, conn: &PgConnection, id: i32) {
pub fn set_owner(&self, conn: &Connection, id: i32) {
diesel::update(self)
.set(medias::owner_id.eq(id))
.execute(conn)

View file

@ -2,6 +2,7 @@ use activitypub::link;
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
use plume_common::activity_pub::inbox::Notify;
use Connection;
use comments::Comment;
use notifications::*;
use posts::Post;
@ -34,26 +35,26 @@ impl Mention {
list_by!(mentions, list_for_post, post_id as i32);
list_by!(mentions, list_for_comment, comment_id as i32);
pub fn get_mentioned(&self, conn: &PgConnection) -> Option<User> {
pub fn get_mentioned(&self, conn: &Connection) -> Option<User> {
User::get(conn, self.mentioned_id)
}
pub fn get_post(&self, conn: &PgConnection) -> Option<Post> {
pub fn get_post(&self, conn: &Connection) -> Option<Post> {
self.post_id.and_then(|id| Post::get(conn, id))
}
pub fn get_comment(&self, conn: &PgConnection) -> Option<Comment> {
pub fn get_comment(&self, conn: &Connection) -> Option<Comment> {
self.comment_id.and_then(|id| Comment::get(conn, id))
}
pub fn get_user(&self, conn: &PgConnection) -> Option<User> {
pub fn get_user(&self, conn: &Connection) -> Option<User> {
match self.get_post(conn) {
Some(p) => p.get_authors(conn).into_iter().next(),
None => self.get_comment(conn).map(|c| c.get_author(conn))
}
}
pub fn build_activity(conn: &PgConnection, ment: String) -> link::Mention {
pub fn build_activity(conn: &Connection, ment: String) -> link::Mention {
let user = User::find_by_fqn(conn, ment.clone());
let mut mention = link::Mention::default();
mention.link_props.set_href_string(user.clone().map(|u| u.ap_url).unwrap_or(String::new())).expect("Error setting mention's href");
@ -61,7 +62,7 @@ impl Mention {
mention
}
pub fn to_activity(&self, conn: &PgConnection) -> link::Mention {
pub fn to_activity(&self, conn: &Connection) -> link::Mention {
let user = self.get_mentioned(conn);
let mut mention = link::Mention::default();
mention.link_props.set_href_string(user.clone().map(|u| u.ap_url).unwrap_or(String::new())).expect("Error setting mention's href");
@ -69,7 +70,7 @@ impl Mention {
mention
}
pub fn from_activity(conn: &PgConnection, ment: link::Mention, inside: i32, in_post: bool, notify: bool) -> Option<Self> {
pub fn from_activity(conn: &Connection, ment: link::Mention, inside: i32, in_post: bool, notify: bool) -> Option<Self> {
let ap_url = ment.link_props.href_string().ok()?;
let mentioned = User::find_by_ap_url(conn, ap_url)?;
@ -104,7 +105,7 @@ impl Mention {
}
impl Notify<PgConnection> for Mention {
fn notify(&self, conn: &PgConnection) {
fn notify(&self, conn: &Connection) {
self.get_mentioned(conn).map(|m| {
Notification::insert(conn, NewNotification {
kind: notification_kind::MENTION.to_string(),

View file

@ -1,7 +1,7 @@
use chrono::NaiveDateTime;
use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods};
use diesel::{self, RunQueryDsl, QueryDsl, ExpressionMethods};
use serde_json;
use {Connection, SqlDateTime};
use comments::Comment;
use follows::Follow;
use likes::Like;
@ -23,7 +23,7 @@ pub mod notification_kind {
pub struct Notification {
pub id: i32,
pub user_id: i32,
pub creation_date: NaiveDateTime,
pub creation_date: SqlDateTime,
pub kind: String,
pub object_id: i32
}
@ -40,14 +40,14 @@ impl Notification {
insert!(notifications, NewNotification);
get!(notifications);
pub fn find_for_user(conn: &PgConnection, user: &User) -> Vec<Notification> {
pub fn find_for_user(conn: &Connection, user: &User) -> Vec<Notification> {
notifications::table.filter(notifications::user_id.eq(user.id))
.order_by(notifications::creation_date.desc())
.load::<Notification>(conn)
.expect("Couldn't load user notifications")
}
pub fn page_for_user(conn: &PgConnection, user: &User, (min, max): (i32, i32)) -> Vec<Notification> {
pub fn page_for_user(conn: &Connection, user: &User, (min, max): (i32, i32)) -> Vec<Notification> {
notifications::table.filter(notifications::user_id.eq(user.id))
.order_by(notifications::creation_date.desc())
.offset(min.into())
@ -56,14 +56,14 @@ impl Notification {
.expect("Couldn't load user notifications page")
}
pub fn find<S: Into<String>>(conn: &PgConnection, kind: S, obj: i32) -> Option<Notification> {
pub fn find<S: Into<String>>(conn: &Connection, kind: S, obj: i32) -> Option<Notification> {
notifications::table.filter(notifications::kind.eq(kind.into()))
.filter(notifications::object_id.eq(obj))
.get_result::<Notification>(conn)
.ok()
}
pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value {
pub fn to_json(&self, conn: &Connection) -> serde_json::Value {
let mut json = json!(self);
json["object"] = json!(match self.kind.as_ref() {
notification_kind::COMMENT => Comment::get(conn, self.object_id).map(|comment|

View file

@ -1,4 +1,4 @@
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods};
use posts::Post;
use users::User;

View file

@ -5,7 +5,7 @@ use activitypub::{
};
use canapi::{Error, Provider};
use chrono::{NaiveDateTime, TimeZone, Utc};
use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl, dsl::any};
use diesel::{self, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl, dsl::any};
use heck::KebabCase;
use serde_json;
@ -15,7 +15,7 @@ use plume_common::activity_pub::{
PUBLIC_VISIBILTY, Id, IntoId,
inbox::{Deletable, FromActivity}
};
use {BASE_URL, ap_url};
use {BASE_URL, ap_url, Connection, SqlDateTime};
use blogs::Blog;
use instance::Instance;
use likes::Like;
@ -36,7 +36,7 @@ pub struct Post {
pub content: SafeString,
pub published: bool,
pub license: String,
pub creation_date: NaiveDateTime,
pub creation_date: SqlDateTime,
pub ap_url: String,
pub subtitle: String,
pub source: String,
@ -112,7 +112,7 @@ impl Post {
find_by!(posts, find_by_slug, slug as String, blog_id as i32);
find_by!(posts, find_by_ap_url, ap_url as String);
pub fn list_by_tag(conn: &PgConnection, tag: String, (min, max): (i32, i32)) -> Vec<Post> {
pub fn list_by_tag(conn: &Connection, tag: String, (min, max): (i32, i32)) -> Vec<Post> {
use schema::tags;
let ids = tags::table.filter(tags::tag.eq(tag)).select(tags::post_id);
@ -125,7 +125,7 @@ impl Post {
.expect("Error loading posts by tag")
}
pub fn count_for_tag(conn: &PgConnection, tag: String) -> i64 {
pub fn count_for_tag(conn: &Connection, tag: String) -> i64 {
use schema::tags;
let ids = tags::table.filter(tags::tag.eq(tag)).select(tags::post_id);
posts::table.filter(posts::id.eq(any(ids)))
@ -135,7 +135,7 @@ impl Post {
.expect("Error counting posts by tag")
}
pub fn count_local(conn: &PgConnection) -> usize {
pub fn count_local(conn: &Connection) -> usize {
use schema::post_authors;
use schema::users;
let local_authors = users::table.filter(users::instance_id.eq(Instance::local_id(conn))).select(users::id);
@ -147,11 +147,11 @@ impl Post {
.len()
}
pub fn count(conn: &PgConnection) -> i64 {
pub fn count(conn: &Connection) -> i64 {
posts::table.filter(posts::published.eq(true)).count().get_result(conn).expect("Couldn't count posts")
}
pub fn get_recents(conn: &PgConnection, limit: i64) -> Vec<Post> {
pub fn get_recents(conn: &Connection, limit: i64) -> Vec<Post> {
posts::table.order(posts::creation_date.desc())
.filter(posts::published.eq(true))
.limit(limit)
@ -159,7 +159,7 @@ impl Post {
.expect("Error loading recent posts")
}
pub fn get_recents_for_author(conn: &PgConnection, author: &User, limit: i64) -> Vec<Post> {
pub fn get_recents_for_author(conn: &Connection, author: &User, limit: i64) -> Vec<Post> {
use schema::post_authors;
let posts = PostAuthor::belonging_to(author).select(post_authors::post_id);
@ -171,7 +171,7 @@ impl Post {
.expect("Error loading recent posts for author")
}
pub fn get_recents_for_blog(conn: &PgConnection, blog: &Blog, limit: i64) -> Vec<Post> {
pub fn get_recents_for_blog(conn: &Connection, blog: &Blog, limit: i64) -> Vec<Post> {
posts::table.filter(posts::blog_id.eq(blog.id))
.filter(posts::published.eq(true))
.order(posts::creation_date.desc())
@ -180,14 +180,14 @@ impl Post {
.expect("Error loading recent posts for blog")
}
pub fn get_for_blog(conn: &PgConnection, blog:&Blog) -> Vec<Post> {
pub fn get_for_blog(conn: &Connection, blog:&Blog) -> Vec<Post> {
posts::table.filter(posts::blog_id.eq(blog.id))
.filter(posts::published.eq(true))
.load::<Post>(conn)
.expect("Error loading posts for blog")
}
pub fn blog_page(conn: &PgConnection, blog: &Blog, (min, max): (i32, i32)) -> Vec<Post> {
pub fn blog_page(conn: &Connection, blog: &Blog, (min, max): (i32, i32)) -> Vec<Post> {
posts::table.filter(posts::blog_id.eq(blog.id))
.filter(posts::published.eq(true))
.order(posts::creation_date.desc())
@ -198,7 +198,7 @@ impl Post {
}
/// Give a page of all the recent posts known to this instance (= federated timeline)
pub fn get_recents_page(conn: &PgConnection, (min, max): (i32, i32)) -> Vec<Post> {
pub fn get_recents_page(conn: &Connection, (min, max): (i32, i32)) -> Vec<Post> {
posts::table.order(posts::creation_date.desc())
.filter(posts::published.eq(true))
.offset(min.into())
@ -208,7 +208,7 @@ impl Post {
}
/// Give a page of posts from a specific instance
pub fn get_instance_page(conn: &PgConnection, instance_id: i32, (min, max): (i32, i32)) -> Vec<Post> {
pub fn get_instance_page(conn: &Connection, instance_id: i32, (min, max): (i32, i32)) -> Vec<Post> {
use schema::blogs;
let blog_ids = blogs::table.filter(blogs::instance_id.eq(instance_id)).select(blogs::id);
@ -223,7 +223,7 @@ impl Post {
}
/// Give a page of customized user feed, based on a list of followed users
pub fn user_feed_page(conn: &PgConnection, followed: Vec<i32>, (min, max): (i32, i32)) -> Vec<Post> {
pub fn user_feed_page(conn: &Connection, followed: Vec<i32>, (min, max): (i32, i32)) -> Vec<Post> {
use schema::post_authors;
let post_ids = post_authors::table.filter(post_authors::author_id.eq(any(followed)))
.select(post_authors::post_id);
@ -237,7 +237,7 @@ impl Post {
.expect("Error loading user feed page")
}
pub fn drafts_by_author(conn: &PgConnection, author: &User) -> Vec<Post> {
pub fn drafts_by_author(conn: &Connection, author: &User) -> Vec<Post> {
use schema::post_authors;
let posts = PostAuthor::belonging_to(author).select(post_authors::post_id);
@ -248,14 +248,14 @@ impl Post {
.expect("Error listing drafts")
}
pub fn get_authors(&self, conn: &PgConnection) -> Vec<User> {
pub fn get_authors(&self, conn: &Connection) -> Vec<User> {
use schema::users;
use schema::post_authors;
let author_list = PostAuthor::belonging_to(self).select(post_authors::author_id);
users::table.filter(users::id.eq(any(author_list))).load::<User>(conn).unwrap()
}
pub fn get_blog(&self, conn: &PgConnection) -> Blog {
pub fn get_blog(&self, conn: &Connection) -> Blog {
use schema::blogs;
blogs::table.filter(blogs::id.eq(self.blog_id))
.limit(1)
@ -264,21 +264,21 @@ impl Post {
.into_iter().nth(0).unwrap()
}
pub fn get_likes(&self, conn: &PgConnection) -> Vec<Like> {
pub fn get_likes(&self, conn: &Connection) -> Vec<Like> {
use schema::likes;
likes::table.filter(likes::post_id.eq(self.id))
.load::<Like>(conn)
.expect("Couldn't load likes associted to post")
}
pub fn get_reshares(&self, conn: &PgConnection) -> Vec<Reshare> {
pub fn get_reshares(&self, conn: &Connection) -> Vec<Reshare> {
use schema::reshares;
reshares::table.filter(reshares::post_id.eq(self.id))
.load::<Reshare>(conn)
.expect("Couldn't load reshares associted to post")
}
pub fn update_ap_url(&self, conn: &PgConnection) -> Post {
pub fn update_ap_url(&self, conn: &Connection) -> Post {
if self.ap_url.len() == 0 {
diesel::update(self)
.set(posts::ap_url.eq(self.compute_id(conn)))
@ -288,7 +288,7 @@ impl Post {
}
}
pub fn get_receivers_urls(&self, conn: &PgConnection) -> Vec<String> {
pub fn get_receivers_urls(&self, conn: &Connection) -> Vec<String> {
let followers = self.get_authors(conn).into_iter().map(|a| a.get_followers(conn)).collect::<Vec<Vec<User>>>();
let to = followers.into_iter().fold(vec![], |mut acc, f| {
for x in f {
@ -299,7 +299,7 @@ impl Post {
to
}
pub fn into_activity(&self, conn: &PgConnection) -> Article {
pub fn into_activity(&self, conn: &Connection) -> Article {
let mut to = self.get_receivers_urls(conn);
to.push(PUBLIC_VISIBILTY.to_string());
@ -328,7 +328,7 @@ impl Post {
article
}
pub fn create_activity(&self, conn: &PgConnection) -> Create {
pub fn create_activity(&self, conn: &Connection) -> Create {
let article = self.into_activity(conn);
let mut act = Create::default();
act.object_props.set_id_string(format!("{}activity", self.ap_url)).expect("Post::create_activity: id error");
@ -341,7 +341,7 @@ impl Post {
act
}
pub fn update_activity(&self, conn: &PgConnection) -> Update {
pub fn update_activity(&self, conn: &Connection) -> Update {
let article = self.into_activity(conn);
let mut act = Update::default();
act.object_props.set_id_string(format!("{}/update-{}", self.ap_url, Utc::now().timestamp())).expect("Post::update_activity: id error");
@ -354,7 +354,7 @@ impl Post {
act
}
pub fn handle_update(conn: &PgConnection, updated: Article) {
pub fn handle_update(conn: &Connection, updated: Article) {
let id = updated.object_props.id_string().expect("Post::handle_update: id error");
let mut post = Post::find_by_ap_url(conn, id).unwrap();
@ -382,7 +382,7 @@ impl Post {
post.update(conn);
}
pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value {
pub fn to_json(&self, conn: &Connection) -> serde_json::Value {
let blog = self.get_blog(conn);
json!({
"post": self,
@ -394,13 +394,13 @@ impl Post {
})
}
pub fn compute_id(&self, conn: &PgConnection) -> String {
pub fn compute_id(&self, conn: &Connection) -> String {
ap_url(format!("{}/~/{}/{}/", BASE_URL.as_str(), self.get_blog(conn).get_fqn(conn), self.slug))
}
}
impl FromActivity<Article, PgConnection> for Post {
fn from_activity(conn: &PgConnection, article: Article, _actor: Id) -> Post {
impl FromActivity<Article, Connection> for Post {
fn from_activity(conn: &Connection, article: Article, _actor: Id) -> Post {
if let Some(post) = Post::find_by_ap_url(conn, article.object_props.id_string().unwrap_or(String::new())) {
post
} else {
@ -457,8 +457,8 @@ impl FromActivity<Article, PgConnection> for Post {
}
}
impl Deletable<PgConnection, Delete> for Post {
fn delete(&self, conn: &PgConnection) -> Delete {
impl Deletable<Connection, Delete> for Post {
fn delete(&self, conn: &Connection) -> Delete {
let mut act = Delete::default();
act.delete_props.set_actor_link(self.get_authors(conn)[0].clone().into_id()).expect("Post::delete: actor error");
@ -473,7 +473,7 @@ impl Deletable<PgConnection, Delete> for Post {
act
}
fn delete_id(id: String, conn: &PgConnection) {
fn delete_id(id: String, conn: &Connection) {
Post::find_by_ap_url(conn, id).map(|p| p.delete(conn));
}
}

View file

@ -1,8 +1,8 @@
use activitypub::activity::{Announce, Undo};
use chrono::NaiveDateTime;
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
use plume_common::activity_pub::{Id, IntoId, inbox::{FromActivity, Notify, Deletable}, PUBLIC_VISIBILTY};
use {Connection, SqlDateTime};
use notifications::*;
use posts::Post;
use users::User;
@ -14,7 +14,7 @@ pub struct Reshare {
pub user_id: i32,
pub post_id: i32,
pub ap_url: String,
pub creation_date: NaiveDateTime
pub creation_date: SqlDateTime
}
#[derive(Insertable)]
@ -31,7 +31,7 @@ impl Reshare {
find_by!(reshares, find_by_ap_url, ap_url as String);
find_by!(reshares, find_by_user_on_post, user_id as i32, post_id as i32);
pub fn update_ap_url(&self, conn: &PgConnection) {
pub fn update_ap_url(&self, conn: &Connection) {
if self.ap_url.len() == 0 {
diesel::update(self)
.set(reshares::ap_url.eq(format!(
@ -43,7 +43,7 @@ impl Reshare {
}
}
pub fn get_recents_for_author(conn: &PgConnection, user: &User, limit: i64) -> Vec<Reshare> {
pub fn get_recents_for_author(conn: &Connection, user: &User, limit: i64) -> Vec<Reshare> {
reshares::table.filter(reshares::user_id.eq(user.id))
.order(reshares::creation_date.desc())
.limit(limit)
@ -51,15 +51,15 @@ impl Reshare {
.expect("Error loading recent reshares for user")
}
pub fn get_post(&self, conn: &PgConnection) -> Option<Post> {
pub fn get_post(&self, conn: &Connection) -> Option<Post> {
Post::get(conn, self.post_id)
}
pub fn get_user(&self, conn: &PgConnection) -> Option<User> {
pub fn get_user(&self, conn: &Connection) -> Option<User> {
User::get(conn, self.user_id)
}
pub fn into_activity(&self, conn: &PgConnection) -> Announce {
pub fn into_activity(&self, conn: &Connection) -> Announce {
let mut act = Announce::default();
act.announce_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.announce_props.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap();
@ -72,7 +72,7 @@ impl Reshare {
}
impl FromActivity<Announce, PgConnection> for Reshare {
fn from_activity(conn: &PgConnection, announce: Announce, _actor: Id) -> Reshare {
fn from_activity(conn: &Connection, announce: Announce, _actor: Id) -> Reshare {
let user = User::from_url(conn, announce.announce_props.actor_link::<Id>().expect("Reshare::from_activity: actor error").into());
let post = Post::find_by_ap_url(conn, announce.announce_props.object_link::<Id>().expect("Reshare::from_activity: object error").into());
let reshare = Reshare::insert(conn, NewReshare {
@ -86,7 +86,7 @@ impl FromActivity<Announce, PgConnection> for Reshare {
}
impl Notify<PgConnection> for Reshare {
fn notify(&self, conn: &PgConnection) {
fn notify(&self, conn: &Connection) {
let post = self.get_post(conn).unwrap();
for author in post.get_authors(conn) {
Notification::insert(conn, NewNotification {
@ -99,7 +99,7 @@ impl Notify<PgConnection> for Reshare {
}
impl Deletable<PgConnection, Undo> for Reshare {
fn delete(&self, conn: &PgConnection) -> Undo {
fn delete(&self, conn: &Connection) -> Undo {
diesel::delete(self).execute(conn).unwrap();
// delete associated notification if any
@ -117,7 +117,7 @@ impl Deletable<PgConnection, Undo> for Reshare {
act
}
fn delete_id(id: String, conn: &PgConnection) {
fn delete_id(id: String, conn: &Connection) {
if let Some(reshare) = Reshare::find_by_ap_url(conn, id) {
reshare.delete(conn);
}

View file

@ -1,21 +1,21 @@
table! {
blog_authors (id) {
id -> Integer,
blog_id -> Integer,
author_id -> Integer,
id -> Int4,
blog_id -> Int4,
author_id -> Int4,
is_owner -> Bool,
}
}
table! {
blogs (id) {
id -> Integer,
actor_id -> Text,
title -> Text,
id -> Int4,
actor_id -> Varchar,
title -> Varchar,
summary -> Text,
outbox_url -> Text,
inbox_url -> Text,
instance_id -> Integer,
outbox_url -> Varchar,
inbox_url -> Varchar,
instance_id -> Int4,
creation_date -> Timestamp,
ap_url -> Text,
private_key -> Nullable<Text>,
@ -25,13 +25,13 @@ table! {
table! {
comments (id) {
id -> Integer,
id -> Int4,
content -> Text,
in_response_to_id -> Nullable<Integer>,
post_id -> Integer,
author_id -> Integer,
in_response_to_id -> Nullable<Int4>,
post_id -> Int4,
author_id -> Int4,
creation_date -> Timestamp,
ap_url -> Nullable<Text>,
ap_url -> Nullable<Varchar>,
sensitive -> Bool,
spoiler_text -> Text,
}
@ -39,18 +39,18 @@ table! {
table! {
follows (id) {
id -> Integer,
follower_id -> Integer,
following_id -> Integer,
id -> Int4,
follower_id -> Int4,
following_id -> Int4,
ap_url -> Text,
}
}
table! {
instances (id) {
id -> Integer,
public_domain -> Text,
name -> Text,
id -> Int4,
public_domain -> Varchar,
name -> Varchar,
local -> Bool,
blocked -> Bool,
creation_date -> Timestamp,
@ -58,73 +58,73 @@ table! {
short_description -> Text,
long_description -> Text,
default_license -> Text,
long_description_html -> Text,
short_description_html -> Text,
long_description_html -> Varchar,
short_description_html -> Varchar,
}
}
table! {
likes (id) {
id -> Integer,
user_id -> Integer,
post_id -> Integer,
ap_url -> Text,
id -> Int4,
user_id -> Int4,
post_id -> Int4,
creation_date -> Timestamp,
ap_url -> Varchar,
}
}
table! {
medias (id) {
id -> Integer,
id -> Int4,
file_path -> Text,
alt_text -> Text,
is_remote -> Bool,
remote_url -> Nullable<Text>,
sensitive -> Bool,
content_warning -> Nullable<Text>,
owner_id -> Integer,
owner_id -> Int4,
}
}
table! {
mentions (id) {
id -> Integer,
mentioned_id -> Integer,
post_id -> Nullable<Integer>,
comment_id -> Nullable<Integer>,
ap_url -> Text,
id -> Int4,
mentioned_id -> Int4,
post_id -> Nullable<Int4>,
comment_id -> Nullable<Int4>,
ap_url -> Varchar,
}
}
table! {
notifications (id) {
id -> Integer,
user_id -> Integer,
id -> Int4,
user_id -> Int4,
creation_date -> Timestamp,
kind -> Text,
object_id -> Integer,
kind -> Varchar,
object_id -> Int4,
}
}
table! {
post_authors (id) {
id -> Integer,
post_id -> Integer,
author_id -> Integer,
id -> Int4,
post_id -> Int4,
author_id -> Int4,
}
}
table! {
posts (id) {
id -> Integer,
blog_id -> Integer,
slug -> Text,
title -> Text,
id -> Int4,
blog_id -> Int4,
slug -> Varchar,
title -> Varchar,
content -> Text,
published -> Bool,
license -> Text,
license -> Varchar,
creation_date -> Timestamp,
ap_url -> Text,
ap_url -> Varchar,
subtitle -> Text,
source -> Text,
}
@ -132,42 +132,42 @@ table! {
table! {
reshares (id) {
id -> Integer,
user_id -> Integer,
post_id -> Integer,
ap_url -> Text,
id -> Int4,
user_id -> Int4,
post_id -> Int4,
ap_url -> Varchar,
creation_date -> Timestamp,
}
}
table! {
tags (id) {
id -> Integer,
id -> Int4,
tag -> Text,
is_hastag -> Bool,
post_id -> Integer,
post_id -> Int4,
}
}
table! {
users (id) {
id -> Integer,
username -> Text,
display_name -> Text,
outbox_url -> Text,
inbox_url -> Text,
id -> Int4,
username -> Varchar,
display_name -> Varchar,
outbox_url -> Varchar,
inbox_url -> Varchar,
is_admin -> Bool,
summary -> Text,
email -> Nullable<Text>,
hashed_password -> Nullable<Text>,
instance_id -> Integer,
instance_id -> Int4,
creation_date -> Timestamp,
ap_url -> Text,
private_key -> Nullable<Text>,
public_key -> Text,
shared_inbox_url -> Nullable<Text>,
followers_endpoint -> Text,
avatar_id -> Nullable<Integer>,
shared_inbox_url -> Nullable<Varchar>,
followers_endpoint -> Varchar,
avatar_id -> Nullable<Int4>,
last_fetched_date -> Timestamp,
}
}

View file

@ -1,7 +1,7 @@
use diesel::{self, PgConnection, ExpressionMethods, RunQueryDsl, QueryDsl};
use diesel::{self, ExpressionMethods, RunQueryDsl, QueryDsl};
use plume_common::activity_pub::Hashtag;
use ap_url;
use {ap_url, Connection};
use instance::Instance;
use schema::tags;
@ -27,14 +27,14 @@ impl Tag {
find_by!(tags, find_by_name, tag as String);
list_by!(tags, for_post, post_id as i32);
pub fn into_activity(&self, conn: &PgConnection) -> Hashtag {
pub fn into_activity(&self, conn: &Connection) -> Hashtag {
let mut ht = Hashtag::default();
ht.set_href_string(ap_url(format!("{}/tag/{}", Instance::get_local(conn).unwrap().public_domain, self.tag))).expect("Tag::into_activity: href error");
ht.set_name_string(self.tag.clone()).expect("Tag::into_activity: name error");
ht
}
pub fn from_activity(conn: &PgConnection, tag: Hashtag, post: i32) -> Tag {
pub fn from_activity(conn: &Connection, tag: Hashtag, post: i32) -> Tag {
Tag::insert(conn, NewTag {
tag: tag.name_string().expect("Tag::from_activity: name error"),
is_hastag: false,

View file

@ -5,8 +5,8 @@ use activitypub::{
object::Image,
};
use bcrypt;
use chrono::{NaiveDateTime, Utc};
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods, BelongingToDsl, PgConnection, dsl::any};
use chrono::{Utc, NaiveDateTime};
use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods, BelongingToDsl, dsl::any};
use openssl::{
hash::MessageDigest,
pkey::{PKey, Private},
@ -31,7 +31,7 @@ use serde_json;
use url::Url;
use webfinger::*;
use {BASE_URL, USE_HTTPS, ap_url};
use {BASE_URL, USE_HTTPS, ap_url, Connection};
use db_conn::DbConn;
use blogs::Blog;
use blog_authors::BlogAuthor;
@ -100,28 +100,28 @@ impl User {
find_by!(users, find_by_name, username as String, instance_id as i32);
find_by!(users, find_by_ap_url, ap_url as String);
pub fn one_by_instance(conn: &PgConnection) -> Vec<User> {
pub fn one_by_instance(conn: &Connection) -> Vec<User> {
users::table.distinct_on(users::instance_id)
.get_results::<User>(conn)
.expect("Error in User::on_by_instance")
}
pub fn delete(&self, conn: &PgConnection) {
pub fn delete(&self, conn: &Connection) {
diesel::delete(self).execute(conn).expect("Couldn't remove user from DB");
}
pub fn get_instance(&self, conn: &PgConnection) -> Instance {
pub fn get_instance(&self, conn: &Connection) -> Instance {
Instance::get(conn, self.instance_id).expect("Couldn't find instance")
}
pub fn grant_admin_rights(&self, conn: &PgConnection) {
pub fn grant_admin_rights(&self, conn: &Connection) {
diesel::update(self)
.set(users::is_admin.eq(true))
.load::<User>(conn)
.expect("Couldn't grant admin rights");
}
pub fn update(&self, conn: &PgConnection, name: String, email: String, summary: String) -> User {
pub fn update(&self, conn: &Connection, name: String, email: String, summary: String) -> User {
diesel::update(self)
.set((
users::display_name.eq(name),
@ -132,18 +132,18 @@ impl User {
.into_iter().nth(0).unwrap()
}
pub fn count_local(conn: &PgConnection) -> usize {
pub fn count_local(conn: &Connection) -> usize {
users::table.filter(users::instance_id.eq(Instance::local_id(conn)))
.load::<User>(conn)
.expect("Couldn't load local users")
.len()
}
pub fn find_local(conn: &PgConnection, username: String) -> Option<User> {
pub fn find_local(conn: &Connection, username: String) -> Option<User> {
User::find_by_name(conn, username, Instance::local_id(conn))
}
pub fn find_by_fqn(conn: &PgConnection, fqn: String) -> Option<User> {
pub fn find_by_fqn(conn: &Connection, fqn: String) -> Option<User> {
if fqn.contains("@") { // remote user
match Instance::find_by_domain(conn, String::from(fqn.split("@").last().unwrap())) {
Some(instance) => {
@ -159,7 +159,7 @@ impl User {
}
}
fn fetch_from_webfinger(conn: &PgConnection, acct: String) -> Option<User> {
fn fetch_from_webfinger(conn: &Connection, acct: String) -> Option<User> {
match resolve(acct.clone(), *USE_HTTPS) {
Ok(wf) => wf.links.into_iter().find(|l| l.mime_type == Some(String::from("application/activity+json"))).and_then(|l| User::fetch_from_url(conn, l.href.expect("No href for AP WF link"))),
Err(details) => {
@ -192,11 +192,11 @@ impl User {
}
}
pub fn fetch_from_url(conn: &PgConnection, url: String) -> Option<User> {
pub fn fetch_from_url(conn: &Connection, url: String) -> Option<User> {
User::fetch(url.clone()).map(|json| (User::from_activity(conn, json, Url::parse(url.as_ref()).unwrap().host_str().unwrap().to_string())))
}
fn from_activity(conn: &PgConnection, acct: CustomPerson, inst: String) -> User {
fn from_activity(conn: &Connection, acct: CustomPerson, inst: String) -> User {
let instance = match Instance::find_by_domain(conn, inst.clone()) {
Some(instance) => instance,
None => {
@ -242,7 +242,7 @@ impl User {
user
}
pub fn refetch(&self, conn: &PgConnection) {
pub fn refetch(&self, conn: &Connection) {
User::fetch(self.ap_url.clone()).map(|json| {
let avatar = Media::save_remote(conn, json.object.object_props.icon_image().expect("User::refetch: icon error")
.object_props.url_string().expect("User::refetch: icon.url error"));
@ -274,7 +274,7 @@ impl User {
}
}
pub fn update_boxes(&self, conn: &PgConnection) {
pub fn update_boxes(&self, conn: &Connection) {
let instance = self.get_instance(conn);
if self.outbox_url.len() == 0 {
diesel::update(self)
@ -307,7 +307,7 @@ impl User {
}
}
pub fn get_local_page(conn: &PgConnection, (min, max): (i32, i32)) -> Vec<User> {
pub fn get_local_page(conn: &Connection, (min, max): (i32, i32)) -> Vec<User> {
users::table.filter(users::instance_id.eq(1))
.order(users::username.asc())
.offset(min.into())
@ -316,7 +316,7 @@ impl User {
.expect("Error getting local users page")
}
pub fn outbox(&self, conn: &PgConnection) -> ActivityStream<OrderedCollection> {
pub fn outbox(&self, conn: &Connection) -> ActivityStream<OrderedCollection> {
let acts = self.get_activities(conn);
let n_acts = acts.len();
let mut coll = OrderedCollection::default();
@ -369,7 +369,7 @@ impl User {
}
}
fn get_activities(&self, conn: &PgConnection) -> Vec<serde_json::Value> {
fn get_activities(&self, conn: &Connection) -> Vec<serde_json::Value> {
use schema::posts;
use schema::post_authors;
let posts_by_self = PostAuthor::belonging_to(self).select(post_authors::post_id);
@ -382,7 +382,7 @@ impl User {
}).collect::<Vec<serde_json::Value>>()
}
pub fn get_fqn(&self, conn: &PgConnection) -> String {
pub fn get_fqn(&self, conn: &Connection) -> String {
if self.instance_id == Instance::local_id(conn) {
self.username.clone()
} else {
@ -390,13 +390,13 @@ impl User {
}
}
pub fn get_followers(&self, conn: &PgConnection) -> Vec<User> {
pub fn get_followers(&self, conn: &Connection) -> Vec<User> {
use schema::follows;
let follows = Follow::belonging_to(self).select(follows::follower_id);
users::table.filter(users::id.eq(any(follows))).load::<User>(conn).unwrap()
}
pub fn get_followers_page(&self, conn: &PgConnection, (min, max): (i32, i32)) -> Vec<User> {
pub fn get_followers_page(&self, conn: &Connection, (min, max): (i32, i32)) -> Vec<User> {
use schema::follows;
let follows = Follow::belonging_to(self).select(follows::follower_id);
users::table.filter(users::id.eq(any(follows)))
@ -405,13 +405,13 @@ impl User {
.load::<User>(conn).unwrap()
}
pub fn get_following(&self, conn: &PgConnection) -> Vec<User> {
pub fn get_following(&self, conn: &Connection) -> Vec<User> {
use schema::follows;
let follows = follows::table.filter(follows::follower_id.eq(self.id)).select(follows::following_id);
users::table.filter(users::id.eq(any(follows))).load::<User>(conn).unwrap()
}
pub fn is_followed_by(&self, conn: &PgConnection, other_id: i32) -> bool {
pub fn is_followed_by(&self, conn: &Connection, other_id: i32) -> bool {
use schema::follows;
follows::table
.filter(follows::follower_id.eq(other_id))
@ -421,7 +421,7 @@ impl User {
.len() > 0
}
pub fn is_following(&self, conn: &PgConnection, other_id: i32) -> bool {
pub fn is_following(&self, conn: &Connection, other_id: i32) -> bool {
use schema::follows;
follows::table
.filter(follows::follower_id.eq(self.id))
@ -431,7 +431,7 @@ impl User {
.len() > 0
}
pub fn has_liked(&self, conn: &PgConnection, post: &Post) -> bool {
pub fn has_liked(&self, conn: &Connection, post: &Post) -> bool {
use schema::likes;
likes::table
.filter(likes::post_id.eq(post.id))
@ -441,7 +441,7 @@ impl User {
.len() > 0
}
pub fn has_reshared(&self, conn: &PgConnection, post: &Post) -> bool {
pub fn has_reshared(&self, conn: &Connection, post: &Post) -> bool {
use schema::reshares;
reshares::table
.filter(reshares::post_id.eq(post.id))
@ -451,7 +451,7 @@ impl User {
.len() > 0
}
pub fn is_author_in(&self, conn: &PgConnection, blog: Blog) -> bool {
pub fn is_author_in(&self, conn: &Connection, blog: Blog) -> bool {
use schema::blog_authors;
blog_authors::table.filter(blog_authors::author_id.eq(self.id))
.filter(blog_authors::blog_id.eq(blog.id))
@ -464,7 +464,7 @@ impl User {
PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.clone().unwrap().as_ref()).unwrap()).unwrap()
}
pub fn into_activity(&self, conn: &PgConnection) -> CustomPerson {
pub fn into_activity(&self, conn: &Connection) -> CustomPerson {
let mut actor = Person::default();
actor.object_props.set_id_string(self.ap_url.clone()).expect("User::into_activity: id error");
actor.object_props.set_name_string(self.display_name.clone()).expect("User::into_activity: name error");
@ -494,7 +494,7 @@ impl User {
CustomPerson::new(actor, ap_signature)
}
pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value {
pub fn to_json(&self, conn: &Connection) -> serde_json::Value {
let mut json = serde_json::to_value(self).unwrap();
json["fqn"] = serde_json::Value::String(self.get_fqn(conn));
json["name"] = if self.display_name.len() > 0 {
@ -506,7 +506,7 @@ impl User {
json
}
pub fn webfinger(&self, conn: &PgConnection) -> Webfinger {
pub fn webfinger(&self, conn: &Connection) -> Webfinger {
Webfinger {
subject: format!("acct:{}@{}", self.username, self.get_instance(conn).public_domain),
aliases: vec![self.ap_url.clone()],
@ -533,7 +533,7 @@ impl User {
}
}
pub fn from_url(conn: &PgConnection, url: String) -> Option<User> {
pub fn from_url(conn: &Connection, url: String) -> Option<User> {
User::find_by_ap_url(conn, url.clone()).or_else(|| {
// The requested user was not in the DB
// We try to fetch it if it is remote
@ -545,7 +545,7 @@ impl User {
})
}
pub fn set_avatar(&self, conn: &PgConnection, id: i32) {
pub fn set_avatar(&self, conn: &Connection, id: i32) {
diesel::update(self)
.set(users::avatar_id.eq(id))
.execute(conn)
@ -609,7 +609,7 @@ impl Signer for User {
impl NewUser {
/// Creates a new local user
pub fn new_local(
conn: &PgConnection,
conn: &Connection,
username: String,
display_name: String,
is_admin: bool,