[[package]]
name = "arc-swap"
-version = "0.4.5"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
+checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62"
[[package]]
name = "arrayvec"
"libc",
]
+[[package]]
+name = "base64"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
+dependencies = [
+ "byteorder",
+ "safemem",
+]
+
[[package]]
name = "base64"
version = "0.10.1"
[[package]]
name = "cc"
-version = "1.0.50"
+version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
[[package]]
name = "cfg-if"
"diesel_derives",
"pq-sys",
"r2d2",
+ "serde_json 1.0.51",
]
[[package]]
[[package]]
name = "email"
-version = "0.0.21"
+version = "0.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65360503b8831670969621be3d3814c4c7be44c642de11f8c0f5aaa01f057b3e"
+checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
dependencies = [
- "base64 0.11.0",
+ "base64 0.9.3",
"chrono",
"encoding",
"lazy_static 1.4.0",
- "rand 0.7.3",
- "version_check 0.9.1",
+ "rand 0.4.6",
+ "time",
+ "version_check 0.1.5",
]
[[package]]
[[package]]
name = "hermit-abi"
-version = "0.1.11"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
+checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
dependencies = [
"libc",
]
[[package]]
name = "http-signature-normalization"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "257835255b5d40c6de712d90e56dc874ca5da2816121e7b9f3cfc7b3a55a5714"
+checksum = "fde6b0321d465ea2cdc18b5d5ec73eee2ff20177ecee126cd8dd997f6c49e088"
dependencies = [
"chrono",
"thiserror",
"strum_macros",
"tokio",
"url",
+ "uuid 0.8.1",
]
[[package]]
[[package]]
name = "lettre_email"
-version = "0.9.3"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1c03656b85bea745db40d9e82a8a0c7236e0171dcdf1b98e95916956ec993f1"
+checksum = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5"
dependencies = [
"base64 0.10.1",
"email",
"lettre",
"mime",
"time",
- "uuid",
+ "uuid 0.7.4",
]
[[package]]
[[package]]
name = "parking_lot_core"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
+checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
dependencies = [
"cfg-if",
"cloudabi",
[[package]]
name = "pin-utils"
-version = "0.1.0-alpha.4"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
"scheduled-thread-pool",
]
+[[package]]
+name = "rand"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
+dependencies = [
+ "fuchsia-cprng",
+ "libc",
+ "rand_core 0.3.1",
+ "rdrand",
+ "winapi 0.3.8",
+]
+
[[package]]
name = "rand"
version = "0.6.5"
[[package]]
name = "ryu"
-version = "1.0.3"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
+checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
+
+[[package]]
+name = "safemem"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
[[package]]
name = "schannel"
[[package]]
name = "security-framework"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a"
+checksum = "3f331b9025654145cd425b9ded0caf8f5ae0df80d418b326e2dc1c3dc5eb0620"
dependencies = [
"bitflags",
"core-foundation",
[[package]]
name = "security-framework-sys"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f"
+checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405"
dependencies = [
"core-foundation-sys",
"libc",
[[package]]
name = "smallvec"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
+checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
[[package]]
name = "socket2"
[[package]]
name = "syn"
-version = "1.0.17"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
+checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
dependencies = [
"proc-macro2",
"quote",
[[package]]
name = "threadpool"
-version = "1.7.1"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
+checksum = "e8dae184447c15d5a6916d973c642aec485105a13cd238192a6927ae3e077d66"
dependencies = [
"num_cpus",
]
[[package]]
name = "tokio"
-version = "0.2.18"
+version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713"
+checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c"
dependencies = [
"bytes",
"fnv",
"rand 0.6.5",
]
+[[package]]
+name = "uuid"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
+dependencies = [
+ "rand 0.7.3",
+ "serde 1.0.106",
+]
+
[[package]]
name = "v_escape"
version = "0.7.4"
edition = "2018"
[dependencies]
-diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-column-tables"] }
+diesel = { version = "1.4.4", features = ["postgres","chrono","r2d2","64-column-tables","serde_json"] }
diesel_migrations = "1.4.0"
dotenv = "0.15.0"
activitystreams = "0.5.0-alpha.16"
tokio = "0.2.18"
futures = "0.3.4"
itertools = "0.9.0"
+uuid = { version = "0.8", features = ["serde", "v4"] }
} else {
// TODO: still have to implement unfollow
let user = User_::read(&conn, user_id)?;
- user.send_follow(&community.actor_id)?;
+ user.send_follow(&community.actor_id, &conn)?;
// TODO: this needs to return a "pending" state, until Accept is received from the remote server
}
.create_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
.set_object_base_box(note)?;
+
+ // Insert the sent activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: creator.id,
+ data: serde_json::to_value(&create)?,
+ local: true,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
send_activity(
&create,
&creator.private_key.as_ref().unwrap(),
.update_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
.set_object_base_box(note)?;
+
+ // Insert the sent activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: creator.id,
+ data: serde_json::to_value(&update)?,
+ local: true,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
send_activity(
&update,
&creator.private_key.as_ref().unwrap(),
}
/// As a local community, accept the follow request from a remote user.
- fn send_accept_follow(&self, follow: &Follow) -> Result<(), Error> {
+ fn send_accept_follow(&self, follow: &Follow, conn: &PgConnection) -> Result<(), Error> {
let actor_uri = follow
.follow_props
.get_actor_xsd_any_uri()
.to_string();
let mut accept = Accept::new();
+ // TODO using a fake accept id
+ let id = format!("{}/accept/{}", self.actor_id, uuid::Uuid::new_v4());
+ //follow
accept
.object_props
.set_context_xsd_any_uri(context())?
- // TODO: needs proper id
- .set_id(
- follow
- .follow_props
- .get_actor_xsd_any_uri()
- .unwrap()
- .to_string(),
- )?;
+ .set_id(id)?;
accept
.accept_props
.set_actor_xsd_any_uri(self.actor_id.to_owned())?
.set_object_base_box(BaseBox::from_concrete(follow.clone())?)?;
let to = format!("{}/inbox", actor_uri);
+
+ // Insert the sent activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: self.creator_id,
+ data: serde_json::to_value(&accept)?,
+ local: true,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
send_activity(
&accept,
&self.private_key.to_owned().unwrap(),
verify(&request, &user.public_key.unwrap())?;
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&follow)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
user_id: user.id,
// This will fail if they're already a follower, but ignore the error.
CommunityFollower::follow(&conn, &community_follower_form).ok();
- community.send_accept_follow(&follow)?;
+ community.send_accept_follow(&follow, &conn)?;
Ok(HttpResponse::Ok().finish())
}
use crate::api::comment::CommentResponse;
use crate::api::post::PostResponse;
use crate::api::site::SearchResponse;
+use crate::db::activity;
use crate::db::comment::{Comment, CommentForm};
use crate::db::comment_view::CommentView;
use crate::db::community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm};
// These two have default impls, since currently a community can't follow anything,
// and a user can't be followed (yet)
#[allow(unused_variables)]
- fn send_follow(&self, follow_actor_id: &str) -> Result<(), Error> {
+ fn send_follow(&self, follow_actor_id: &str, conn: &PgConnection) -> Result<(), Error> {
Ok(())
}
#[allow(unused_variables)]
- fn send_accept_follow(&self, follow: &Follow) -> Result<(), Error> {
+ fn send_accept_follow(&self, follow: &Follow, conn: &PgConnection) -> Result<(), Error> {
Ok(())
}
.create_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
.set_object_base_box(page)?;
+
+ // Insert the sent activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: creator.id,
+ data: serde_json::to_value(&create)?,
+ local: true,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
send_activity(
&create,
&creator.private_key.as_ref().unwrap(),
.update_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
.set_object_base_box(page)?;
+
+ // Insert the sent activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: creator.id,
+ data: serde_json::to_value(&update)?,
+ local: true,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
send_activity(
&update,
&creator.private_key.as_ref().unwrap(),
let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
verify(request, &user.public_key.unwrap())?;
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&create)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
let post = PostForm::from_apub(&page, &conn)?;
let inserted_post = Post::create(conn, &post)?;
let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
verify(request, &user.public_key.unwrap())?;
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&create)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
let comment = CommentForm::from_apub(¬e, &conn)?;
let inserted_comment = Comment::create(conn, &comment)?;
let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
verify(request, &user.public_key.unwrap())?;
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&update)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
let post = PostForm::from_apub(&page, conn)?;
let post_id = Post::read_from_apub_id(conn, &post.ap_id)?.id;
Post::update(conn, post_id, &post)?;
let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
verify(request, &user.public_key.unwrap())?;
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&update)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
let comment = CommentForm::from_apub(¬e, &conn)?;
let comment_id = Comment::read_from_apub_id(conn, &comment.ap_id)?.id;
Comment::update(conn, comment_id, &comment)?;
self.public_key.to_owned().unwrap()
}
- // TODO might be able to move this to a default trait fn
/// As a given local user, send out a follow request to a remote community.
- fn send_follow(&self, follow_actor_id: &str) -> Result<(), Error> {
+ fn send_follow(&self, follow_actor_id: &str, conn: &PgConnection) -> Result<(), Error> {
let mut follow = Follow::new();
+
+ // TODO using a fake accept id
+ let id = format!("{}/follow/{}", self.actor_id, uuid::Uuid::new_v4());
+
follow
.object_props
.set_context_xsd_any_uri(context())?
- // TODO: needs proper id
- .set_id(self.actor_id.to_owned())?;
+ .set_id(id)?;
follow
.follow_props
.set_actor_xsd_any_uri(self.actor_id.to_owned())?
.set_object_xsd_any_uri(follow_actor_id)?;
let to = format!("{}/inbox", follow_actor_id);
+
+ // Insert the sent activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: self.id,
+ data: serde_json::to_value(&follow)?,
+ local: true,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
send_activity(
&follow,
&self.private_key.as_ref().unwrap(),
let user = User_::read_from_name(&conn, username)?;
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: community.creator_id,
+ data: serde_json::to_value(&accept)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
// Now you need to add this to the community follower
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
--- /dev/null
+use super::*;
+use crate::schema::activity;
+use crate::schema::activity::dsl::*;
+use serde_json::Value;
+
+#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
+#[table_name = "activity"]
+pub struct Activity {
+ pub id: i32,
+ pub user_id: i32,
+ pub data: Value,
+ pub local: bool,
+ pub published: chrono::NaiveDateTime,
+ pub updated: Option<chrono::NaiveDateTime>,
+}
+
+#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize)]
+#[table_name = "activity"]
+pub struct ActivityForm {
+ pub user_id: i32,
+ pub data: Value,
+ pub local: bool,
+ pub updated: Option<chrono::NaiveDateTime>,
+}
+
+impl Crud<ActivityForm> for Activity {
+ fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
+ activity.find(activity_id).first::<Self>(conn)
+ }
+
+ fn delete(conn: &PgConnection, activity_id: i32) -> Result<usize, Error> {
+ diesel::delete(activity.find(activity_id)).execute(conn)
+ }
+
+ fn create(conn: &PgConnection, new_activity: &ActivityForm) -> Result<Self, Error> {
+ insert_into(activity)
+ .values(new_activity)
+ .get_result::<Self>(conn)
+ }
+
+ fn update(
+ conn: &PgConnection,
+ activity_id: i32,
+ new_activity: &ActivityForm,
+ ) -> Result<Self, Error> {
+ diesel::update(activity.find(activity_id))
+ .set(new_activity)
+ .get_result::<Self>(conn)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::super::user::*;
+ use super::*;
+
+ #[test]
+ fn test_crud() {
+ let conn = establish_unpooled_connection();
+
+ let creator_form = UserForm {
+ name: "activity_creator_pm".into(),
+ preferred_username: None,
+ password_encrypted: "nope".into(),
+ email: None,
+ matrix_user_id: None,
+ avatar: None,
+ admin: false,
+ banned: false,
+ updated: None,
+ show_nsfw: false,
+ theme: "darkly".into(),
+ default_sort_type: SortType::Hot as i16,
+ default_listing_type: ListingType::Subscribed as i16,
+ lang: "browser".into(),
+ show_avatars: true,
+ send_notifications_to_email: false,
+ actor_id: "changeme".into(),
+ bio: None,
+ local: true,
+ private_key: None,
+ public_key: None,
+ last_refreshed_at: None,
+ };
+
+ let inserted_creator = User_::create(&conn, &creator_form).unwrap();
+
+ let test_json: Value = serde_json::from_str(
+ r#"{
+ "street": "Article Circle Expressway 1",
+ "city": "North Pole",
+ "postcode": "99705",
+ "state": "Alaska"
+}"#,
+ )
+ .unwrap();
+ let activity_form = ActivityForm {
+ user_id: inserted_creator.id,
+ data: test_json.to_owned(),
+ local: true,
+ updated: None,
+ };
+
+ let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
+
+ let expected_activity = Activity {
+ id: inserted_activity.id,
+ user_id: inserted_creator.id,
+ data: test_json,
+ local: true,
+ published: inserted_activity.published,
+ updated: None,
+ };
+
+ let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
+ let num_deleted = Activity::delete(&conn, inserted_activity.id).unwrap();
+ User_::delete(&conn, inserted_creator.id).unwrap();
+
+ assert_eq!(expected_activity, read_activity);
+ assert_eq!(expected_activity, inserted_activity);
+ assert_eq!(1, num_deleted);
+ }
+}
use diesel::*;
use serde::{Deserialize, Serialize};
+pub mod activity;
pub mod category;
pub mod code_migrations;
pub mod comment;
.route("/feeds/all.xml", web::get().to(feeds::get_all_feed));
}
-async fn get_all_feed(
- info: web::Query<Params>,
- db: DbPoolParam,
-) -> Result<HttpResponse, Error> {
+async fn get_all_feed(info: web::Query<Params>, db: DbPoolParam) -> Result<HttpResponse, Error> {
let res = web::block(move || {
let conn = db.get()?;
get_feed_all_data(&conn, &get_sort_type(info)?)
Ok(HttpResponse::Ok().json(node_info))
}
-async fn node_info(
- db: DbPoolParam,
-) -> Result<HttpResponse, Error> {
+async fn node_info(db: DbPoolParam) -> Result<HttpResponse, Error> {
let res = web::block(move || {
let conn = db.get()?;
let site_view = match SiteView::read(&conn) {