-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;
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)?))
}
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(),
.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"
}
-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;
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)?))
}