]> Untitled Git - lemmy.git/commitdiff
Remove boilerplate code
authorFelix Ableitner <me@nutomic.com>
Mon, 16 Mar 2020 17:30:25 +0000 (18:30 +0100)
committerFelix Ableitner <me@nutomic.com>
Mon, 16 Mar 2020 17:30:25 +0000 (18:30 +0100)
server/Cargo.lock
server/Cargo.toml
server/src/apub/community.rs
server/src/apub/mod.rs
server/src/apub/puller.rs
server/src/apub/user.rs

index a645d56e846a9e57d3e33d7b891a4a277916e4b0..db4b0fbbc3843f0b422fa87f52a7fcfef787adc3 100644 (file)
@@ -2,7 +2,7 @@
 # It is not intended for manual editing.
 [[package]]
 name = "activitystreams"
-version = "0.5.0-alpha.4"
+version = "0.5.0-alpha.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "activitystreams-derive 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1562,7 +1562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "lemmy_server"
 version = "0.0.1"
 dependencies = [
- "activitystreams 0.5.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "activitystreams 0.5.0-alpha.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3282,7 +3282,7 @@ dependencies = [
 ]
 
 [metadata]
-"checksum activitystreams 0.5.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1f5d1db7f182bc74c9a6d2002cb7a5eb99b001ef41ddc8df1c21750ccc3638fa"
+"checksum activitystreams 0.5.0-alpha.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a9e82b6649331396e8bd17547a3b775ba7f530a30d574d43cf1d373899dafd94"
 "checksum activitystreams-derive 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f95c948a832a0b7b230b28369bafe79477bb8ebe7306dc97bcaff43832d3cc4d"
 "checksum actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf"
 "checksum actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380"
index 6aa9adc238c1cd38698384cdd40a4cae1c2545d1..e039b7b5f7017324c035f00e8f9d1b401a6e5632 100644 (file)
@@ -9,7 +9,7 @@ diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-colum
 diesel_migrations = "1.4.0"
 dotenv = "0.15.0"
 bcrypt = "0.6.1"
-activitystreams = "0.5.0-alpha.4"
+activitystreams = "0.5.0-alpha.7"
 chrono = { version = "0.4.7", features = ["serde"] }
 failure = "0.1.5"
 serde_json = { version = "1.0.45", features = ["preserve_order"]}
index 61b0b2ce2e5442866b3d7f811036a571d91a7e45..8c0fb16065e70e43906a28729b53d2e46a7bd965 100644 (file)
@@ -1,4 +1,4 @@
-use crate::apub::make_apub_endpoint;
+use crate::apub::{create_apub_response, make_apub_endpoint};
 use crate::convert_datetime;
 use crate::db::community::Community;
 use crate::db::community_view::CommunityFollowerView;
@@ -12,134 +12,101 @@ use activitystreams::{
 use actix_web::body::Body;
 use actix_web::web::Path;
 use actix_web::HttpResponse;
+use actix_web::{web, Result};
+use diesel::r2d2::{ConnectionManager, Pool};
+use diesel::PgConnection;
 use failure::Error;
 use serde::Deserialize;
 
-impl Community {
-  pub fn as_group(&self) -> Result<Group, Error> {
-    let base_url = make_apub_endpoint("c", &self.name);
-
-    let mut group = Group::default();
-    let oprops: &mut ObjectProperties = group.as_mut();
+#[derive(Deserialize)]
+pub struct CommunityQuery {
+  community_name: String,
+}
 
-    oprops
-      .set_context_xsd_any_uri(context())?
-      .set_id(base_url.to_owned())?
-      .set_name_xsd_string(self.title.to_owned())?
-      .set_published(convert_datetime(self.published))?
-      .set_attributed_to_xsd_any_uri(make_apub_endpoint("u", &self.creator_id))?;
+pub async fn get_apub_community(
+  info: Path<CommunityQuery>,
+  db: web::Data<Pool<ConnectionManager<PgConnection>>>,
+) -> Result<HttpResponse<Body>, Error> {
+  let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
+  let base_url = make_apub_endpoint("c", &community.name);
 
-    if let Some(u) = self.updated.to_owned() {
-      oprops.set_updated(convert_datetime(u))?;
-    }
-    if let Some(d) = self.description.to_owned() {
-      oprops.set_summary_xsd_string(d)?;
-    }
+  let mut group = Group::default();
+  let oprops: &mut ObjectProperties = group.as_mut();
 
-    group
-      .ap_actor_props
-      .set_inbox(format!("{}/inbox", &base_url))?
-      .set_outbox(format!("{}/outbox", &base_url))?
-      .set_followers(format!("{}/followers", &base_url))?;
+  oprops
+    .set_context_xsd_any_uri(context())?
+    .set_id(base_url.to_owned())?
+    .set_name_xsd_string(community.title.to_owned())?
+    .set_published(convert_datetime(community.published))?
+    .set_attributed_to_xsd_any_uri(make_apub_endpoint("u", &community.creator_id))?;
 
-    Ok(group)
+  if let Some(u) = community.updated.to_owned() {
+    oprops.set_updated(convert_datetime(u))?;
   }
-
-  pub fn get_followers(&self) -> Result<UnorderedCollection, Error> {
-    let base_url = make_apub_endpoint("c", &self.name);
-
-    let connection = establish_unpooled_connection();
-    //As we are an object, we validated that the community id was valid
-    let community_followers = CommunityFollowerView::for_community(&connection, self.id).unwrap();
-
-    let mut collection = UnorderedCollection::default();
-    let oprops: &mut ObjectProperties = collection.as_mut();
-    oprops
-      .set_context_xsd_any_uri(context())?
-      .set_id(base_url)?;
-    collection
-      .collection_props
-      .set_total_items(community_followers.len() as u64)?;
-    Ok(collection)
+  if let Some(d) = community.description {
+    oprops.set_summary_xsd_string(d)?;
   }
 
-  pub fn get_outbox(&self) -> Result<OrderedCollection, Error> {
-    let base_url = make_apub_endpoint("c", &self.name);
-
-    let connection = establish_unpooled_connection();
-    //As we are an object, we validated that the community id was valid
-    let community_posts: Vec<PostView> = PostQueryBuilder::create(&connection)
-      .for_community_id(self.id)
-      .list()
-      .unwrap();
-
-    let mut collection = OrderedCollection::default();
-    let oprops: &mut ObjectProperties = collection.as_mut();
-    oprops
-      .set_context_xsd_any_uri(context())?
-      .set_id(base_url)?;
-    collection
-      .collection_props
-      .set_many_items_object_boxs(
-        community_posts
-          .iter()
-          .map(|c| c.as_page().unwrap())
-          .collect(),
-      )?
-      .set_total_items(community_posts.len() as u64)?;
+  group
+    .ap_actor_props
+    .set_inbox(format!("{}/inbox", &base_url))?
+    .set_outbox(format!("{}/outbox", &base_url))?
+    .set_followers(format!("{}/followers", &base_url))?;
 
-    Ok(collection)
-  }
-}
-
-#[derive(Deserialize)]
-pub struct CommunityQuery {
-  community_name: String,
-}
-
-// TODO: move all this boilerplate code to routes::federation or such
-pub async fn get_apub_community(info: Path<CommunityQuery>) -> Result<HttpResponse<Body>, Error> {
-  let connection = establish_unpooled_connection();
-
-  if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
-    Ok(
-      HttpResponse::Ok()
-        .content_type("application/activity+json")
-        .body(serde_json::to_string(&community.as_group()?).unwrap()),
-    )
-  } else {
-    Ok(HttpResponse::NotFound().finish())
-  }
+  Ok(create_apub_response(serde_json::to_string(&group)?))
 }
 
 pub async fn get_apub_community_followers(
   info: Path<CommunityQuery>,
+  db: web::Data<Pool<ConnectionManager<PgConnection>>>,
 ) -> Result<HttpResponse<Body>, Error> {
-  let connection = establish_unpooled_connection();
+  let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
+  let base_url = make_apub_endpoint("c", &community.name);
 
-  if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
-    Ok(
-      HttpResponse::Ok()
-        .content_type("application/activity+json")
-        .body(serde_json::to_string(&community.get_followers()?).unwrap()),
-    )
-  } else {
-    Ok(HttpResponse::NotFound().finish())
-  }
+  let connection = establish_unpooled_connection();
+  //As we are an object, we validated that the community id was valid
+  let community_followers =
+    CommunityFollowerView::for_community(&connection, community.id).unwrap();
+
+  let mut collection = UnorderedCollection::default();
+  let oprops: &mut ObjectProperties = collection.as_mut();
+  oprops
+    .set_context_xsd_any_uri(context())?
+    .set_id(base_url)?;
+  collection
+    .collection_props
+    .set_total_items(community_followers.len() as u64)?;
+  Ok(create_apub_response(serde_json::to_string(&collection)?))
 }
 
 pub async fn get_apub_community_outbox(
   info: Path<CommunityQuery>,
+  db: web::Data<Pool<ConnectionManager<PgConnection>>>,
 ) -> Result<HttpResponse<Body>, Error> {
-  let connection = establish_unpooled_connection();
+  let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
+  let base_url = make_apub_endpoint("c", &community.name);
 
-  if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
-    Ok(
-      HttpResponse::Ok()
-        .content_type("application/activity+json")
-        .body(serde_json::to_string(&community.get_outbox()?).unwrap()),
-    )
-  } else {
-    Ok(HttpResponse::NotFound().finish())
-  }
+  let connection = establish_unpooled_connection();
+  //As we are an object, we validated that the community id was valid
+  let community_posts: Vec<PostView> = PostQueryBuilder::create(&connection)
+    .for_community_id(community.id)
+    .list()
+    .unwrap();
+
+  let mut collection = OrderedCollection::default();
+  let oprops: &mut ObjectProperties = collection.as_mut();
+  oprops
+    .set_context_xsd_any_uri(context())?
+    .set_id(base_url)?;
+  collection
+    .collection_props
+    .set_many_items_object_boxs(
+      community_posts
+        .iter()
+        .map(|c| c.as_page().unwrap())
+        .collect(),
+    )?
+    .set_total_items(community_posts.len() as u64)?;
+
+  Ok(create_apub_response(serde_json::to_string(&collection)?))
 }
index 6ce599929c6a5abcf53ed9e6aeaefb161a4f762e..d648e902c4d34afe2a5aec290c92c3cfd144494e 100644 (file)
@@ -3,76 +3,21 @@ pub mod post;
 pub mod puller;
 pub mod user;
 use crate::Settings;
-use failure::Error;
 
+use actix_web::body::Body;
+use actix_web::HttpResponse;
 use std::fmt::Display;
 use url::Url;
 
-#[cfg(test)]
-mod tests {
-  use crate::db::community::Community;
-  use crate::db::user::User_;
-  use crate::db::{ListingType, SortType};
-  use crate::{naive_now, Settings};
-
-  #[test]
-  fn test_person() {
-    let user = User_ {
-      id: 52,
-      name: "thom".into(),
-      fedi_name: "rrf".into(),
-      preferred_username: None,
-      password_encrypted: "here".into(),
-      email: None,
-      matrix_user_id: None,
-      avatar: None,
-      published: naive_now(),
-      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,
-    };
-
-    let person = user.as_person();
-    assert_eq!(
-      format!("https://{}/federation/u/thom", Settings::get().hostname),
-      person.unwrap().object_props.get_id().unwrap().to_string()
-    );
-  }
-
-  #[test]
-  fn test_community() {
-    let community = Community {
-      id: 42,
-      name: "Test".into(),
-      title: "Test Title".into(),
-      description: Some("Test community".into()),
-      category_id: 32,
-      creator_id: 52,
-      removed: false,
-      published: naive_now(),
-      updated: Some(naive_now()),
-      deleted: false,
-      nsfw: false,
-    };
-
-    let group = community.as_group();
-    assert_eq!(
-      format!("https://{}/federation/c/Test", Settings::get().hostname),
-      group.unwrap().object_props.get_id().unwrap().to_string()
-    );
-  }
+fn create_apub_response(json_data: String) -> HttpResponse<Body> {
+  HttpResponse::Ok()
+    .content_type("application/activity+json")
+    .body(json_data)
 }
 
 // TODO: this should take an enum community/user/post for `point`
 // TODO: also not sure what exactly `value` should be (numeric id, name string, ...)
-pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> Url {
+fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> Url {
   Url::parse(&format!(
     "{}://{}/federation/{}/{}",
     get_apub_protocol_string(),
@@ -83,13 +28,6 @@ pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> Url {
   .unwrap()
 }
 
-/// Parses an ID generated by `make_apub_endpoint()`. Will break when federating with anything
-/// that is not Lemmy. This is just a crutch until we change the database to store URLs as ID.
-pub fn parse_apub_endpoint(id: &str) -> Result<(&str, &str), Error> {
-  let split = id.split('/').collect::<Vec<&str>>();
-  Ok((split[4], split[5]))
-}
-
-pub fn get_apub_protocol_string() -> &'static str {
+fn get_apub_protocol_string() -> &'static str {
   "http"
 }
index 50a6cd69dc00bb98eb146c04b5ded15907760e0c..7ae0696ec71328375012fce794a82ce06bd72a9f 100644 (file)
@@ -44,6 +44,7 @@ where
 {
   // TODO: should cache responses here when we are in production
   // TODO: this function should return a future
+  // TODO: in production mode, fail if protocol is not https
   let x: Response = reqwest::get(uri)?.json()?;
   Ok(x)
 }
index c1ffcedd42373a2767e2f3a9185ed0b2e78f6d85..005ca9de74ee43ff072dc1fdce755a4ef23b156a 100644 (file)
@@ -1,6 +1,5 @@
-use crate::apub::make_apub_endpoint;
+use crate::apub::{make_apub_endpoint, create_apub_response};
 use crate::convert_datetime;
-use crate::db::establish_unpooled_connection;
 use crate::db::user::User_;
 use activitystreams::{actor::apub::Person, context, object::properties::ObjectProperties};
 use actix_web::body::Body;
@@ -8,52 +7,42 @@ use actix_web::web::Path;
 use actix_web::HttpResponse;
 use failure::Error;
 use serde::Deserialize;
+use diesel::r2d2::{ConnectionManager, Pool};
+use diesel::PgConnection;
+use actix_web::{web, Result};
 
-impl User_ {
-  pub fn as_person(&self) -> Result<Person, Error> {
-    let base_url = make_apub_endpoint("u", &self.name);
+#[derive(Deserialize)]
+pub struct UserQuery {
+  user_name: String,
+}
+
+pub async fn get_apub_user(
+  info: Path<UserQuery>,
+  db: web::Data<Pool<ConnectionManager<PgConnection>>>,) -> Result<HttpResponse<Body>, Error> {
+  let user = User_::find_by_email_or_username(&&db.get()?, &info.user_name)?;
+  let base_url = make_apub_endpoint("u", &user.name);
 
-    let mut person = Person::default();
-    let oprops: &mut ObjectProperties = person.as_mut();
-    oprops
+  let mut person = Person::default();
+  let oprops: &mut ObjectProperties = person.as_mut();
+  oprops
       .set_context_xsd_any_uri(context())?
       .set_id(base_url.to_string())?
-      .set_published(convert_datetime(self.published))?;
+      .set_published(convert_datetime(user.published))?;
 
-    if let Some(u) = self.updated {
-      oprops.set_updated(convert_datetime(u))?;
-    }
+  if let Some(u) = user.updated {
+    oprops.set_updated(convert_datetime(u))?;
+  }
 
-    if let Some(i) = &self.preferred_username {
-      oprops.set_name_xsd_string(i.to_owned())?;
-    }
+  if let Some(i) = &user.preferred_username {
+    oprops.set_name_xsd_string(i.to_owned())?;
+  }
 
-    person
+  person
       .ap_actor_props
       .set_inbox(format!("{}/inbox", &base_url))?
       .set_outbox(format!("{}/outbox", &base_url))?
       .set_following(format!("{}/following", &base_url))?
       .set_liked(format!("{}/liked", &base_url))?;
 
-    Ok(person)
-  }
-}
-
-#[derive(Deserialize)]
-pub struct UserQuery {
-  user_name: String,
-}
-
-pub async fn get_apub_user(info: Path<UserQuery>) -> Result<HttpResponse<Body>, Error> {
-  let connection = establish_unpooled_connection();
-
-  if let Ok(user) = User_::find_by_email_or_username(&connection, &info.user_name) {
-    Ok(
-      HttpResponse::Ok()
-        .content_type("application/activity+json")
-        .body(serde_json::to_string(&user.as_person()?).unwrap()),
-    )
-  } else {
-    Ok(HttpResponse::NotFound().finish())
-  }
+  Ok(create_apub_response(serde_json::to_string(&person)?))
 }