]> Untitled Git - lemmy.git/commitdiff
Use Url type for ap_id fields in database (fixes #1364) (#1371)
authorNutomic <me@nutomic.com>
Wed, 27 Jan 2021 16:42:23 +0000 (16:42 +0000)
committerGitHub <noreply@github.com>
Wed, 27 Jan 2021 16:42:23 +0000 (11:42 -0500)
48 files changed:
Cargo.lock
crates/api/src/community.rs
crates/api/src/user.rs
crates/apub/src/activities/receive/comment.rs
crates/apub/src/activities/receive/community.rs
crates/apub/src/activities/receive/post.rs
crates/apub/src/activities/send/comment.rs
crates/apub/src/activities/send/community.rs
crates/apub/src/activities/send/post.rs
crates/apub/src/activities/send/private_message.rs
crates/apub/src/activities/send/user.rs
crates/apub/src/activity_queue.rs
crates/apub/src/extensions/signatures.rs
crates/apub/src/fetcher/community.rs
crates/apub/src/fetcher/objects.rs
crates/apub/src/fetcher/user.rs
crates/apub/src/http/user.rs
crates/apub/src/inbox/community_inbox.rs
crates/apub/src/inbox/mod.rs
crates/apub/src/inbox/shared_inbox.rs
crates/apub/src/inbox/user_inbox.rs
crates/apub/src/lib.rs
crates/apub/src/objects/comment.rs
crates/apub/src/objects/community.rs
crates/apub/src/objects/mod.rs
crates/apub/src/objects/post.rs
crates/apub/src/objects/private_message.rs
crates/apub/src/objects/user.rs
crates/db_queries/src/lib.rs
crates/db_queries/src/source/comment.rs
crates/db_queries/src/source/community.rs
crates/db_queries/src/source/post.rs
crates/db_queries/src/source/private_message.rs
crates/db_queries/src/source/user.rs
crates/db_schema/src/lib.rs
crates/db_schema/src/source/comment.rs
crates/db_schema/src/source/community.rs
crates/db_schema/src/source/post.rs
crates/db_schema/src/source/private_message.rs
crates/db_schema/src/source/user.rs
crates/structs/Cargo.toml
crates/structs/src/lib.rs
migrations/2021-01-26-173850_default_actor_id/down.sql [new file with mode: 0644]
migrations/2021-01-26-173850_default_actor_id/up.sql [new file with mode: 0644]
src/code_migrations.rs
src/routes/feeds.rs
src/routes/webfinger.rs
tests/integration_test.rs

index 70f9ec5b64697a53e861e8b50423f0e56d47a881..e43b9219cf7fcba85aeff9e4dee115ed53d91f39 100644 (file)
@@ -1908,6 +1908,7 @@ dependencies = [
  "log",
  "serde 1.0.118",
  "serde_json",
+ "url",
 ]
 
 [[package]]
index 055f9bfd5b3f19c1a86a69fa2ecffa040acec938..26687b98bf932de3edfa9818d885141ed0525b1e 100644 (file)
@@ -136,10 +136,10 @@ impl Perform for CreateCommunity {
     }
 
     // Double check for duplicate community actor_ids
-    let actor_id = make_apub_endpoint(EndpointType::Community, &data.name).to_string();
+    let actor_id = make_apub_endpoint(EndpointType::Community, &data.name);
     let actor_id_cloned = actor_id.to_owned();
     let community_dupe = blocking(context.pool(), move |conn| {
-      Community::read_from_apub_id(conn, &actor_id_cloned)
+      Community::read_from_apub_id(conn, &actor_id_cloned.into())
     })
     .await?;
     if community_dupe.is_ok() {
@@ -168,7 +168,7 @@ impl Perform for CreateCommunity {
       deleted: None,
       nsfw: data.nsfw,
       updated: None,
-      actor_id: Some(actor_id),
+      actor_id: Some(actor_id.into()),
       local: true,
       private_key: Some(keypair.private_key),
       public_key: Some(keypair.public_key),
@@ -509,9 +509,9 @@ impl Perform for FollowCommunity {
     } else if data.follow {
       // Dont actually add to the community followers here, because you need
       // to wait for the accept
-      user.send_follow(&community.actor_id()?, context).await?;
+      user.send_follow(&community.actor_id(), context).await?;
     } else {
-      user.send_unfollow(&community.actor_id()?, context).await?;
+      user.send_unfollow(&community.actor_id(), context).await?;
       let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
       if blocking(context.pool(), unfollow).await?.is_err() {
         return Err(APIError::err("community_follower_already_exists").into());
index 16d390c59b07be265247dbc08574aed4bacc148d..4ec930542832d243accca6bbc437b65fdae902b9 100644 (file)
@@ -200,7 +200,7 @@ impl Perform for Register {
       lang: "browser".into(),
       show_avatars: true,
       send_notifications_to_email: false,
-      actor_id: Some(make_apub_endpoint(EndpointType::User, &data.username).to_string()),
+      actor_id: Some(make_apub_endpoint(EndpointType::User, &data.username).into()),
       bio: None,
       local: true,
       private_key: Some(user_keypair.private_key),
@@ -247,7 +247,7 @@ impl Perform for Register {
             deleted: None,
             updated: None,
             actor_id: Some(
-              make_apub_endpoint(EndpointType::Community, default_community_name).to_string(),
+              make_apub_endpoint(EndpointType::Community, default_community_name).into(),
             ),
             local: true,
             private_key: Some(main_community_keypair.private_key),
index 7ba3a05ca9d5d34de792dcfaa856b4cbaf006d4a..6136f63bbeeeedf8e05f8c2f66222b38149448ce 100644 (file)
@@ -23,7 +23,7 @@ pub(crate) async fn receive_create_comment(
   let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
     .context(location_info!())?;
 
-  let comment = Comment::from_apub(&note, context, user.actor_id()?, request_counter).await?;
+  let comment = Comment::from_apub(&note, context, user.actor_id(), request_counter).await?;
 
   let post_id = comment.post_id;
   let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@@ -66,7 +66,7 @@ pub(crate) async fn receive_update_comment(
     .context(location_info!())?;
   let user = get_actor_as_user(&update, context, request_counter).await?;
 
-  let comment = Comment::from_apub(&note, context, user.actor_id()?, request_counter).await?;
+  let comment = Comment::from_apub(&note, context, user.actor_id(), request_counter).await?;
 
   let comment_id = comment.id;
   let post_id = comment.post_id;
index 7f5523773cc5f5effd6aea09e0ef4ca30c9ccbd1..54a8cdb7a9150788c5758a08a1dfa8e206417445 100644 (file)
@@ -55,7 +55,7 @@ pub(crate) async fn receive_remove_community(
     .single_xsd_any_uri()
     .context(location_info!())?;
   let community = blocking(context.pool(), move |conn| {
-    Community::read_from_apub_id(conn, community_uri.as_str())
+    Community::read_from_apub_id(conn, &community_uri.into())
   })
   .await??;
 
@@ -137,7 +137,7 @@ pub(crate) async fn receive_undo_remove_community(
     .single_xsd_any_uri()
     .context(location_info!())?;
   let community = blocking(context.pool(), move |conn| {
-    Community::read_from_apub_id(conn, community_uri.as_str())
+    Community::read_from_apub_id(conn, &community_uri.into())
   })
   .await??;
 
index c35a02818dbc9611ad6e0e1585c8957c972c8c01..42635864643160c418a792819eb43c7446fdcdc3 100644 (file)
@@ -20,7 +20,7 @@ pub(crate) async fn receive_create_post(
   let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
     .context(location_info!())?;
 
-  let post = Post::from_apub(&page, context, user.actor_id()?, request_counter).await?;
+  let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?;
 
   // Refetch the view
   let post_id = post.id;
@@ -49,7 +49,7 @@ pub(crate) async fn receive_update_post(
   let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
     .context(location_info!())?;
 
-  let post = Post::from_apub(&page, context, user.actor_id()?, request_counter).await?;
+  let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?;
 
   let post_id = post.id;
   // Refetch the view
index e3c622edbae3c54ca18e69dec89e29969ade0649..323b851f55fe6d1b896f5c578ee484e40c2acf27 100644 (file)
@@ -59,7 +59,10 @@ impl ApubObjectType for Comment {
 
     let maa = collect_non_local_mentions(&self, &community, context).await?;
 
-    let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
+    let mut create = Create::new(
+      creator.actor_id.to_owned().into_inner(),
+      note.into_any_base()?,
+    );
     create
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(CreateType::Create)?)
@@ -89,7 +92,10 @@ impl ApubObjectType for Comment {
 
     let maa = collect_non_local_mentions(&self, &community, context).await?;
 
-    let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
+    let mut update = Update::new(
+      creator.actor_id.to_owned().into_inner(),
+      note.into_any_base()?,
+    );
     update
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UpdateType::Update)?)
@@ -113,12 +119,15 @@ impl ApubObjectType for Comment {
     })
     .await??;
 
-    let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut delete = Delete::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(delete, &creator, &community, context).await?;
     Ok(())
@@ -139,20 +148,26 @@ impl ApubObjectType for Comment {
     .await??;
 
     // Generate a fake delete activity, with the correct object
-    let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut delete = Delete::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
+    let mut undo = Undo::new(
+      creator.actor_id.to_owned().into_inner(),
+      delete.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(undo, &creator, &community, context).await?;
     Ok(())
@@ -168,12 +183,15 @@ impl ApubObjectType for Comment {
     })
     .await??;
 
-    let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut remove = Remove::new(
+      mod_.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     remove
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(RemoveType::Remove)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(remove, &mod_, &community, context).await?;
     Ok(())
@@ -190,20 +208,26 @@ impl ApubObjectType for Comment {
     .await??;
 
     // Generate a fake delete activity, with the correct object
-    let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut remove = Remove::new(
+      mod_.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     remove
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(RemoveType::Remove)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?);
+    let mut undo = Undo::new(
+      mod_.actor_id.to_owned().into_inner(),
+      remove.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(undo, &mod_, &community, context).await?;
     Ok(())
@@ -222,12 +246,15 @@ impl ApubLikeableType for Comment {
     })
     .await??;
 
-    let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut like = Like::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     like
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(LikeType::Like)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(like, &creator, &community, context).await?;
     Ok(())
@@ -243,12 +270,15 @@ impl ApubLikeableType for Comment {
     })
     .await??;
 
-    let mut dislike = Dislike::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut dislike = Dislike::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     dislike
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DislikeType::Dislike)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(dislike, &creator, &community, context).await?;
     Ok(())
@@ -268,20 +298,26 @@ impl ApubLikeableType for Comment {
     })
     .await??;
 
-    let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut like = Like::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     like
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DislikeType::Dislike)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?);
+    let mut undo = Undo::new(
+      creator.actor_id.to_owned().into_inner(),
+      like.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(undo, &creator, &community, context).await?;
     Ok(())
@@ -313,7 +349,7 @@ async fn collect_non_local_mentions(
   context: &LemmyContext,
 ) -> Result<MentionsAndAddresses, LemmyError> {
   let parent_creator = get_comment_parent_creator(context.pool(), comment).await?;
-  let mut addressed_ccs = vec![community.actor_id()?, parent_creator.actor_id()?];
+  let mut addressed_ccs = vec![community.actor_id(), parent_creator.actor_id()];
   // Note: dont include community inbox here, as we send to it separately with `send_to_community()`
   let mut inboxes = vec![parent_creator.get_shared_inbox_url()?];
 
@@ -393,7 +429,5 @@ async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result<U
   link
     .href
     .to_owned()
-    .map(|u| Url::parse(&u))
-    .transpose()?
     .ok_or_else(|| anyhow!("No href found.").into())
 }
index c2f22fa2dc35193c668b0c03c7b853774352776c..d79cfe062511566365ee0d4987a164d51e96cc7c 100644 (file)
@@ -33,8 +33,8 @@ use url::Url;
 
 #[async_trait::async_trait(?Send)]
 impl ActorType for Community {
-  fn actor_id_str(&self) -> String {
-    self.actor_id.to_owned()
+  fn actor_id(&self) -> Url {
+    self.actor_id.to_owned().into_inner()
   }
 
   fn public_key(&self) -> Option<String> {
@@ -72,11 +72,14 @@ impl ActorType for Community {
       .context(location_info!())?;
     let user = get_or_fetch_and_upsert_user(actor_uri, context, &mut 0).await?;
 
-    let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?);
+    let mut accept = Accept::new(
+      self.actor_id.to_owned().into_inner(),
+      follow.into_any_base()?,
+    );
     accept
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(AcceptType::Accept)?)
-      .set_to(user.actor_id()?);
+      .set_to(user.actor_id());
 
     send_activity_single_dest(accept, self, user.get_inbox_url()?, context).await?;
     Ok(())
@@ -84,7 +87,7 @@ impl ActorType for Community {
 
   /// If the creator of a community deletes the community, send this to all followers.
   async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
-    let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
+    let mut delete = Delete::new(self.actor_id(), self.actor_id());
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
@@ -97,14 +100,14 @@ impl ActorType for Community {
 
   /// If the creator of a community reverts the deletion of a community, send this to all followers.
   async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
-    let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
+    let mut delete = Delete::new(self.actor_id(), self.actor_id());
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
       .set_to(public())
       .set_many_ccs(vec![self.get_followers_url()?]);
 
-    let mut undo = Undo::new(self.actor_id()?, delete.into_any_base()?);
+    let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?);
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
@@ -117,7 +120,7 @@ impl ActorType for Community {
 
   /// If an admin removes a community, send this to all followers.
   async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
-    let mut remove = Remove::new(self.actor_id()?, self.actor_id()?);
+    let mut remove = Remove::new(self.actor_id(), self.actor_id());
     remove
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(RemoveType::Remove)?)
@@ -130,7 +133,7 @@ impl ActorType for Community {
 
   /// If an admin reverts the removal of a community, send this to all followers.
   async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
-    let mut remove = Remove::new(self.actor_id()?, self.actor_id()?);
+    let mut remove = Remove::new(self.actor_id(), self.actor_id());
     remove
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(RemoveType::Remove)?)
@@ -138,7 +141,7 @@ impl ActorType for Community {
       .set_many_ccs(vec![self.get_followers_url()?]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(self.actor_id()?, remove.into_any_base()?);
+    let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?);
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(LikeType::Like)?)
@@ -156,7 +159,7 @@ impl ActorType for Community {
     activity: AnyBase,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let mut announce = Announce::new(self.actor_id.to_owned(), activity);
+    let mut announce = Announce::new(self.actor_id.to_owned().into_inner(), activity);
     announce
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(AnnounceType::Announce)?)
@@ -183,7 +186,7 @@ impl ActorType for Community {
       .into_iter()
       .filter(|i| !i.follower.local)
       .map(|u| -> Result<Url, LemmyError> {
-        let url = Url::parse(&u.follower.actor_id)?;
+        let url = u.follower.actor_id.into_inner();
         let domain = url.domain().context(location_info!())?;
         let port = if let Some(port) = url.port() {
           format!(":{}", port)
index 4af40de28b2d58206a92c1c1eaa2c683a47dbda1..ce74d20a5e746f5a936923c325e989312c5b719b 100644 (file)
@@ -26,7 +26,6 @@ use lemmy_db_schema::source::{community::Community, post::Post, user::User_};
 use lemmy_structs::blocking;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
-use url::Url;
 
 #[async_trait::async_trait(?Send)]
 impl ApubObjectType for Post {
@@ -40,12 +39,15 @@ impl ApubObjectType for Post {
     })
     .await??;
 
-    let mut create = Create::new(creator.actor_id.to_owned(), page.into_any_base()?);
+    let mut create = Create::new(
+      creator.actor_id.to_owned().into_inner(),
+      page.into_any_base()?,
+    );
     create
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(CreateType::Create)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(create, creator, &community, context).await?;
     Ok(())
@@ -61,12 +63,15 @@ impl ApubObjectType for Post {
     })
     .await??;
 
-    let mut update = Update::new(creator.actor_id.to_owned(), page.into_any_base()?);
+    let mut update = Update::new(
+      creator.actor_id.to_owned().into_inner(),
+      page.into_any_base()?,
+    );
     update
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UpdateType::Update)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(update, creator, &community, context).await?;
     Ok(())
@@ -79,12 +84,15 @@ impl ApubObjectType for Post {
     })
     .await??;
 
-    let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut delete = Delete::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(delete, creator, &community, context).await?;
     Ok(())
@@ -101,20 +109,26 @@ impl ApubObjectType for Post {
     })
     .await??;
 
-    let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut delete = Delete::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
+    let mut undo = Undo::new(
+      creator.actor_id.to_owned().into_inner(),
+      delete.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(undo, creator, &community, context).await?;
     Ok(())
@@ -127,12 +141,15 @@ impl ApubObjectType for Post {
     })
     .await??;
 
-    let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut remove = Remove::new(
+      mod_.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     remove
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(RemoveType::Remove)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(remove, mod_, &community, context).await?;
     Ok(())
@@ -145,20 +162,26 @@ impl ApubObjectType for Post {
     })
     .await??;
 
-    let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut remove = Remove::new(
+      mod_.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     remove
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(RemoveType::Remove)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?);
+    let mut undo = Undo::new(
+      mod_.actor_id.to_owned().into_inner(),
+      remove.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(undo, mod_, &community, context).await?;
     Ok(())
@@ -174,12 +197,15 @@ impl ApubLikeableType for Post {
     })
     .await??;
 
-    let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut like = Like::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     like
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(LikeType::Like)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(like, &creator, &community, context).await?;
     Ok(())
@@ -192,12 +218,15 @@ impl ApubLikeableType for Post {
     })
     .await??;
 
-    let mut dislike = Dislike::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut dislike = Dislike::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     dislike
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DislikeType::Dislike)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(dislike, &creator, &community, context).await?;
     Ok(())
@@ -214,20 +243,26 @@ impl ApubLikeableType for Post {
     })
     .await??;
 
-    let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut like = Like::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     like
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(LikeType::Like)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     // Undo that fake activity
-    let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?);
+    let mut undo = Undo::new(
+      creator.actor_id.to_owned().into_inner(),
+      like.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
       .set_to(public())
-      .set_many_ccs(vec![community.actor_id()?]);
+      .set_many_ccs(vec![community.actor_id()]);
 
     send_to_community(undo, &creator, &community, context).await?;
     Ok(())
index d920f3decc511c781d971f11a92d9cbbab07266c..6bff815a4a47d35c9090b29e229d6a8ffff1bdf2 100644 (file)
@@ -21,7 +21,6 @@ use lemmy_db_schema::source::{private_message::PrivateMessage, user::User_};
 use lemmy_structs::blocking;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
-use url::Url;
 
 #[async_trait::async_trait(?Send)]
 impl ApubObjectType for PrivateMessage {
@@ -32,12 +31,15 @@ impl ApubObjectType for PrivateMessage {
     let recipient_id = self.recipient_id;
     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
 
-    let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
+    let mut create = Create::new(
+      creator.actor_id.to_owned().into_inner(),
+      note.into_any_base()?,
+    );
 
     create
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(CreateType::Create)?)
-      .set_to(recipient.actor_id()?);
+      .set_to(recipient.actor_id());
 
     send_activity_single_dest(create, creator, recipient.get_inbox_url()?, context).await?;
     Ok(())
@@ -50,11 +52,14 @@ impl ApubObjectType for PrivateMessage {
     let recipient_id = self.recipient_id;
     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
 
-    let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
+    let mut update = Update::new(
+      creator.actor_id.to_owned().into_inner(),
+      note.into_any_base()?,
+    );
     update
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UpdateType::Update)?)
-      .set_to(recipient.actor_id()?);
+      .set_to(recipient.actor_id());
 
     send_activity_single_dest(update, creator, recipient.get_inbox_url()?, context).await?;
     Ok(())
@@ -64,11 +69,14 @@ impl ApubObjectType for PrivateMessage {
     let recipient_id = self.recipient_id;
     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
 
-    let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut delete = Delete::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
-      .set_to(recipient.actor_id()?);
+      .set_to(recipient.actor_id());
 
     send_activity_single_dest(delete, creator, recipient.get_inbox_url()?, context).await?;
     Ok(())
@@ -82,18 +90,24 @@ impl ApubObjectType for PrivateMessage {
     let recipient_id = self.recipient_id;
     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
 
-    let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
+    let mut delete = Delete::new(
+      creator.actor_id.to_owned().into_inner(),
+      self.ap_id.to_owned().into_inner(),
+    );
     delete
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(DeleteType::Delete)?)
-      .set_to(recipient.actor_id()?);
+      .set_to(recipient.actor_id());
 
     // Undo that fake activity
-    let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
+    let mut undo = Undo::new(
+      creator.actor_id.to_owned().into_inner(),
+      delete.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
-      .set_to(recipient.actor_id()?);
+      .set_to(recipient.actor_id());
 
     send_activity_single_dest(undo, creator, recipient.get_inbox_url()?, context).await?;
     Ok(())
index 049496f73689634255bb1c0a0e1dab2e3f540eed..3eac6f2df5d186b81402121d824a0ca90624f246 100644 (file)
@@ -25,8 +25,8 @@ use url::Url;
 
 #[async_trait::async_trait(?Send)]
 impl ActorType for User_ {
-  fn actor_id_str(&self) -> String {
-    self.actor_id.to_owned()
+  fn actor_id(&self) -> Url {
+    self.actor_id.to_owned().into_inner()
   }
 
   fn public_key(&self) -> Option<String> {
@@ -43,9 +43,9 @@ impl ActorType for User_ {
     follow_actor_id: &Url,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let follow_actor_id = follow_actor_id.to_string();
+    let follow_actor_id = follow_actor_id.to_owned();
     let community = blocking(context.pool(), move |conn| {
-      Community::read_from_apub_id(conn, &follow_actor_id)
+      Community::read_from_apub_id(conn, &follow_actor_id.into())
     })
     .await??;
 
@@ -59,11 +59,11 @@ impl ActorType for User_ {
     })
     .await?;
 
-    let mut follow = Follow::new(self.actor_id.to_owned(), community.actor_id()?);
+    let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id());
     follow
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(FollowType::Follow)?)
-      .set_to(community.actor_id()?);
+      .set_to(community.actor_id());
 
     send_activity_single_dest(follow, self, community.get_inbox_url()?, context).await?;
     Ok(())
@@ -74,24 +74,27 @@ impl ActorType for User_ {
     follow_actor_id: &Url,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let follow_actor_id = follow_actor_id.to_string();
+    let follow_actor_id = follow_actor_id.to_owned();
     let community = blocking(context.pool(), move |conn| {
-      Community::read_from_apub_id(conn, &follow_actor_id)
+      Community::read_from_apub_id(conn, &follow_actor_id.into())
     })
     .await??;
 
-    let mut follow = Follow::new(self.actor_id.to_owned(), community.actor_id()?);
+    let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id());
     follow
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(FollowType::Follow)?)
-      .set_to(community.actor_id()?);
+      .set_to(community.actor_id());
 
     // Undo that fake activity
-    let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?);
+    let mut undo = Undo::new(
+      self.actor_id.to_owned().into_inner(),
+      follow.into_any_base()?,
+    );
     undo
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(UndoType::Undo)?)
-      .set_to(community.actor_id()?);
+      .set_to(community.actor_id());
 
     send_activity_single_dest(undo, self, community.get_inbox_url()?, context).await?;
     Ok(())
index ff792c4dac94d8ae43cc779a7f041f9f7ac9715b..d7246384a717fdd08f7f3e64f9b1f269494c46f7 100644 (file)
@@ -240,7 +240,7 @@ where
     let message = SendActivityTask {
       activity: serialised_activity.to_owned(),
       inbox: i.to_owned(),
-      actor_id: actor.actor_id()?,
+      actor_id: actor.actor_id(),
       private_key: actor.private_key().context(location_info!())?,
     };
     if env::var("LEMMY_TEST_SEND_SYNC").is_ok() {
index 67fe4b1cd3a9c910cecf461ee536476973044e94..ebbf9a0a484fa54b4a7f7879bb1bf9865354972e 100644 (file)
@@ -98,17 +98,17 @@ pub(crate) fn verify_signature(
 /// Extension for actor public key, which is needed on user and community for HTTP signatures.
 ///
 /// Taken from: https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
-#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct PublicKeyExtension {
   pub public_key: PublicKey,
 }
 
-#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct PublicKey {
   pub id: String,
-  pub owner: String,
+  pub owner: Url,
   pub public_key_pem: String,
 }
 
index 2a2564122031e071596894e0bf329d2d62e5913e..0249dee1ebecbe931c45de6a958b2c62c50b40ad 100644 (file)
@@ -40,7 +40,7 @@ pub(crate) async fn get_or_fetch_and_upsert_community(
 ) -> Result<Community, LemmyError> {
   let apub_id_owned = apub_id.to_owned();
   let community = blocking(context.pool(), move |conn| {
-    Community::read_from_apub_id(conn, apub_id_owned.as_str())
+    Community::read_from_apub_id(conn, &apub_id_owned.into())
   })
   .await?;
 
index 269b27ef8438f466661b24ae07201a3595747244..df33bf74096d342279641b0b0c02130146c70ba2 100644 (file)
@@ -20,7 +20,7 @@ pub(crate) async fn get_or_fetch_and_insert_post(
 ) -> Result<Post, LemmyError> {
   let post_ap_id_owned = post_ap_id.to_owned();
   let post = blocking(context.pool(), move |conn| {
-    Post::read_from_apub_id(conn, post_ap_id_owned.as_str())
+    Post::read_from_apub_id(conn, &post_ap_id_owned.into())
   })
   .await?;
 
@@ -49,7 +49,7 @@ pub(crate) async fn get_or_fetch_and_insert_comment(
 ) -> Result<Comment, LemmyError> {
   let comment_ap_id_owned = comment_ap_id.to_owned();
   let comment = blocking(context.pool(), move |conn| {
-    Comment::read_from_apub_id(conn, comment_ap_id_owned.as_str())
+    Comment::read_from_apub_id(conn, &comment_ap_id_owned.into())
   })
   .await?;
 
index 8442519f7b29c0a4e19d1fd29e5393652c98eca1..21cdfb3489913dde2d286f325c732a6cc24657dc 100644 (file)
@@ -24,7 +24,7 @@ pub(crate) async fn get_or_fetch_and_upsert_user(
 ) -> Result<User_, LemmyError> {
   let apub_id_owned = apub_id.to_owned();
   let user = blocking(context.pool(), move |conn| {
-    User_::read_from_apub_id(conn, apub_id_owned.as_ref())
+    User_::read_from_apub_id(conn, &apub_id_owned.into())
   })
   .await?;
 
index 3005b8b59bccc3e6608b26372636281334e203a7..7c7653e575e9be4869a15f972b1db2475000fc50 100644 (file)
@@ -72,7 +72,7 @@ pub async fn get_apub_user_inbox(
 
   let mut collection = OrderedCollection::new();
   collection
-    .set_id(format!("{}/inbox", user.actor_id).parse()?)
+    .set_id(format!("{}/inbox", user.actor_id.into_inner()).parse()?)
     .set_many_contexts(lemmy_context()?);
   Ok(create_apub_response(&collection))
 }
index 1e44254c2b8c2d83b9d0d0a34b858e038ee84af5..45e7ab43cc2bfce4de833323770098a47934b2ba 100644 (file)
@@ -69,7 +69,7 @@ pub async fn community_inbox(
   let actor = inbox_verify_http_signature(&activity, &context, request, request_counter).await?;
 
   // Do nothing if we received the same activity before
-  let activity_id = get_activity_id(&activity, &actor.actor_id()?)?;
+  let activity_id = get_activity_id(&activity, &actor.actor_id())?;
   if is_activity_already_known(context.pool(), &activity_id).await? {
     return Ok(HttpResponse::Ok().finish());
   }
@@ -81,7 +81,7 @@ pub async fn community_inbox(
   })
   .await??;
   let to_and_cc = get_activity_to_and_cc(&activity);
-  if !to_and_cc.contains(&&community.actor_id()?) {
+  if !to_and_cc.contains(&&community.actor_id()) {
     return Err(anyhow!("Activity delivered to wrong community").into());
   }
 
@@ -92,7 +92,7 @@ pub async fn community_inbox(
     "Community {} received activity {:?} from {}",
     community.name,
     &activity.id_unchecked(),
-    &actor.actor_id_str()
+    &actor.actor_id()
   );
 
   community_receive_message(
@@ -115,15 +115,15 @@ pub(crate) async fn community_receive_message(
 ) -> Result<HttpResponse, LemmyError> {
   // Only users can send activities to the community, so we can get the actor as user
   // unconditionally.
-  let actor_id = actor.actor_id_str();
+  let actor_id = actor.actor_id();
   let user = blocking(&context.pool(), move |conn| {
-    User_::read_from_apub_id(&conn, &actor_id)
+    User_::read_from_apub_id(&conn, &actor_id.into())
   })
   .await??;
   check_community_or_site_ban(&user, &to_community, context.pool()).await?;
 
   let any_base = activity.clone().into_any_base()?;
-  let actor_url = actor.actor_id()?;
+  let actor_url = actor.actor_id();
   let activity_kind = activity.kind().context(location_info!())?;
   let do_announce = match activity_kind {
     CommunityValidTypes::Follow => {
@@ -187,7 +187,7 @@ async fn handle_follow(
   context: &LemmyContext,
 ) -> Result<HttpResponse, LemmyError> {
   let follow = Follow::from_any_base(activity)?.context(location_info!())?;
-  verify_activity_domains_valid(&follow, &user.actor_id()?, false)?;
+  verify_activity_domains_valid(&follow, &user.actor_id(), false)?;
 
   let community_follower_form = CommunityFollowerForm {
     community_id: community.id,
@@ -241,7 +241,7 @@ async fn handle_undo_follow(
   verify_activity_domains_valid(&follow, &user_url, false)?;
 
   let user = blocking(&context.pool(), move |conn| {
-    User_::read_from_apub_id(&conn, user_url.as_str())
+    User_::read_from_apub_id(&conn, &user_url.into())
   })
   .await??;
   let community_follower_form = CommunityFollowerForm {
index a91dd48eb3bfc19f3c16a61d3c013c3fb64d7445..65e476e51c30183c8f547cb6402655a74358eb54 100644 (file)
@@ -119,8 +119,11 @@ pub(crate) async fn is_addressed_to_local_user(
   pool: &DbPool,
 ) -> Result<bool, LemmyError> {
   for url in to_and_cc {
-    let url = url.to_string();
-    let user = blocking(&pool, move |conn| User_::read_from_apub_id(&conn, &url)).await?;
+    let url = url.to_owned();
+    let user = blocking(&pool, move |conn| {
+      User_::read_from_apub_id(&conn, &url.into())
+    })
+    .await?;
     if let Ok(u) = user {
       if u.local {
         return Ok(true);
@@ -140,9 +143,9 @@ pub(crate) async fn is_addressed_to_community_followers(
     let url = url.to_string();
     // TODO: extremely hacky, we should just store the followers url for each community in the db
     if url.ends_with("/followers") {
-      let community_url = url.replace("/followers", "");
+      let community_url = Url::parse(&url.replace("/followers", ""))?;
       let community = blocking(&pool, move |conn| {
-        Community::read_from_apub_id(&conn, &community_url)
+        Community::read_from_apub_id(&conn, &community_url.into())
       })
       .await??;
       if !community.local {
index f9b9bfc01a00b620f1bb4f9f2983b260a92df70e..93df6e7284fda380b91f9cad13f2892374772582 100644 (file)
@@ -54,7 +54,7 @@ pub async fn shared_inbox(
   let actor = inbox_verify_http_signature(&activity, &context, request, request_counter).await?;
 
   // Do nothing if we received the same activity before
-  let actor_id = actor.actor_id()?;
+  let actor_id = actor.actor_id();
   let activity_id = get_activity_id(&activity, &actor_id)?;
   if is_activity_already_known(context.pool(), &activity_id).await? {
     return Ok(HttpResponse::Ok().finish());
@@ -137,8 +137,11 @@ async fn extract_local_community_from_destinations(
   pool: &DbPool,
 ) -> Result<Option<Community>, LemmyError> {
   for url in to_and_cc {
-    let url = url.to_string();
-    let community = blocking(&pool, move |conn| Community::read_from_apub_id(&conn, &url)).await?;
+    let url = url.to_owned();
+    let community = blocking(&pool, move |conn| {
+      Community::read_from_apub_id(&conn, &url.into())
+    })
+    .await?;
     if let Ok(c) = community {
       if c.local {
         return Ok(Some(c));
index 353a296e31fcedb4f64ed146a1a265c8e48939be..6496a60a019c6f44628949698ef7e568fda392eb 100644 (file)
@@ -90,7 +90,7 @@ pub async fn user_inbox(
   let actor = inbox_verify_http_signature(&activity, &context, request, request_counter).await?;
 
   // Do nothing if we received the same activity before
-  let activity_id = get_activity_id(&activity, &actor.actor_id()?)?;
+  let activity_id = get_activity_id(&activity, &actor.actor_id())?;
   if is_activity_already_known(context.pool(), &activity_id).await? {
     return Ok(HttpResponse::Ok().finish());
   }
@@ -103,7 +103,7 @@ pub async fn user_inbox(
   .await??;
   let to_and_cc = get_activity_to_and_cc(&activity);
   // TODO: we should also accept activities that are sent to community followers
-  if !to_and_cc.contains(&&user.actor_id()?) {
+  if !to_and_cc.contains(&&user.actor_id()) {
     return Err(anyhow!("Activity delivered to wrong user").into());
   }
 
@@ -114,7 +114,7 @@ pub async fn user_inbox(
     "User {} received activity {:?} from {}",
     user.name,
     &activity.id_unchecked(),
-    &actor.actor_id_str()
+    &actor.actor_id()
   );
 
   user_receive_message(
@@ -139,7 +139,7 @@ pub(crate) async fn user_receive_message(
 
   let any_base = activity.clone().into_any_base()?;
   let kind = activity.kind().context(location_info!())?;
-  let actor_url = actor.actor_id()?;
+  let actor_url = actor.actor_id();
   match kind {
     UserValidTypes::Accept => {
       receive_accept(&context, any_base, actor, to_user.unwrap(), request_counter).await?;
@@ -209,11 +209,11 @@ async fn receive_accept(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let accept = Accept::from_any_base(activity)?.context(location_info!())?;
-  verify_activity_domains_valid(&accept, &actor.actor_id()?, false)?;
+  verify_activity_domains_valid(&accept, &actor.actor_id(), false)?;
 
   let object = accept.object().to_owned().one().context(location_info!())?;
   let follow = Follow::from_any_base(object)?.context(location_info!())?;
-  verify_activity_domains_valid(&follow, &user.actor_id()?, false)?;
+  verify_activity_domains_valid(&follow, &user.actor_id(), false)?;
 
   let community_uri = accept
     .actor()?
@@ -243,7 +243,7 @@ async fn receive_announce(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let announce = Announce::from_any_base(activity)?.context(location_info!())?;
-  verify_activity_domains_valid(&announce, &actor.actor_id()?, false)?;
+  verify_activity_domains_valid(&announce, &actor.actor_id(), false)?;
   is_addressed_to_public(&announce)?;
 
   let kind = announce.object().as_single_kind_str();
@@ -375,18 +375,18 @@ async fn find_community_or_private_message_by_id(
   context: &LemmyContext,
   apub_id: Url,
 ) -> Result<CommunityOrPrivateMessage, LemmyError> {
-  let ap_id = apub_id.to_string();
+  let ap_id = apub_id.to_owned();
   let community = blocking(context.pool(), move |conn| {
-    Community::read_from_apub_id(conn, &ap_id)
+    Community::read_from_apub_id(conn, &ap_id.into())
   })
   .await?;
   if let Ok(c) = community {
     return Ok(CommunityOrPrivateMessage::Community(c));
   }
 
-  let ap_id = apub_id.to_string();
+  let ap_id = apub_id.to_owned();
   let private_message = blocking(context.pool(), move |conn| {
-    PrivateMessage::read_from_apub_id(conn, &ap_id)
+    PrivateMessage::read_from_apub_id(conn, &ap_id.into())
   })
   .await?;
   if let Ok(p) = private_message {
index d5d682a7d006dc34d4219b2a46cad9a56289c717..f76a0b8ff308e1b955e280a6e278adc089aced52 100644 (file)
@@ -140,7 +140,7 @@ pub trait ApubLikeableType {
 /// implemented by all actors.
 #[async_trait::async_trait(?Send)]
 pub trait ActorType {
-  fn actor_id_str(&self) -> String;
+  fn actor_id(&self) -> Url;
 
   // TODO: every actor should have a public key, so this shouldnt be an option (needs to be fixed in db)
   fn public_key(&self) -> Option<String>;
@@ -178,17 +178,13 @@ pub trait ActorType {
   /// For a given community, returns the inboxes of all followers.
   async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
 
-  fn actor_id(&self) -> Result<Url, ParseError> {
-    Url::parse(&self.actor_id_str())
-  }
-
   // TODO move these to the db rows
   fn get_inbox_url(&self) -> Result<Url, ParseError> {
-    Url::parse(&format!("{}/inbox", &self.actor_id_str()))
+    Url::parse(&format!("{}/inbox", &self.actor_id()))
   }
 
   fn get_shared_inbox_url(&self) -> Result<Url, LemmyError> {
-    let actor_id = self.actor_id()?;
+    let actor_id = self.actor_id();
     let url = format!(
       "{}://{}{}/inbox",
       &actor_id.scheme(),
@@ -203,18 +199,18 @@ pub trait ActorType {
   }
 
   fn get_outbox_url(&self) -> Result<Url, ParseError> {
-    Url::parse(&format!("{}/outbox", &self.actor_id_str()))
+    Url::parse(&format!("{}/outbox", &self.actor_id()))
   }
 
   fn get_followers_url(&self) -> Result<Url, ParseError> {
-    Url::parse(&format!("{}/followers", &self.actor_id_str()))
+    Url::parse(&format!("{}/followers", &self.actor_id()))
   }
 
   fn get_public_key_ext(&self) -> Result<PublicKeyExtension, LemmyError> {
     Ok(
       PublicKey {
-        id: format!("{}#main-key", self.actor_id_str()),
-        owner: self.actor_id_str(),
+        id: format!("{}#main-key", self.actor_id()),
+        owner: self.actor_id(),
         public_key_pem: self.public_key().context(location_info!())?,
       }
       .to_ext(),
@@ -254,18 +250,18 @@ pub(crate) async fn find_post_or_comment_by_id(
   context: &LemmyContext,
   apub_id: Url,
 ) -> Result<PostOrComment, LemmyError> {
-  let ap_id = apub_id.to_string();
+  let ap_id = apub_id.clone();
   let post = blocking(context.pool(), move |conn| {
-    Post::read_from_apub_id(conn, &ap_id)
+    Post::read_from_apub_id(conn, &ap_id.into())
   })
   .await?;
   if let Ok(p) = post {
     return Ok(PostOrComment::Post(p));
   }
 
-  let ap_id = apub_id.to_string();
+  let ap_id = apub_id.clone();
   let comment = blocking(context.pool(), move |conn| {
-    Comment::read_from_apub_id(conn, &ap_id)
+    Comment::read_from_apub_id(conn, &ap_id.into())
   })
   .await?;
   if let Ok(c) = comment {
@@ -287,34 +283,34 @@ pub(crate) async fn find_object_by_id(
   context: &LemmyContext,
   apub_id: Url,
 ) -> Result<Object, LemmyError> {
-  if let Ok(pc) = find_post_or_comment_by_id(context, apub_id.to_owned()).await {
+  let ap_id = apub_id.clone();
+  if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
     return Ok(match pc {
       PostOrComment::Post(p) => Object::Post(p),
       PostOrComment::Comment(c) => Object::Comment(c),
     });
   }
 
-  let ap_id = apub_id.to_string();
+  let ap_id = apub_id.clone();
   let user = blocking(context.pool(), move |conn| {
-    User_::read_from_apub_id(conn, &ap_id)
+    User_::read_from_apub_id(conn, &ap_id.into())
   })
   .await?;
   if let Ok(u) = user {
     return Ok(Object::User(u));
   }
 
-  let ap_id = apub_id.to_string();
+  let ap_id = apub_id.clone();
   let community = blocking(context.pool(), move |conn| {
-    Community::read_from_apub_id(conn, &ap_id)
+    Community::read_from_apub_id(conn, &ap_id.into())
   })
   .await?;
   if let Ok(c) = community {
     return Ok(Object::Community(c));
   }
 
-  let ap_id = apub_id.to_string();
   let private_message = blocking(context.pool(), move |conn| {
-    PrivateMessage::read_from_apub_id(conn, &ap_id)
+    PrivateMessage::read_from_apub_id(conn, &apub_id.into())
   })
   .await?;
   if let Ok(pm) = private_message {
index 5dba4149bda4614890b98f46ff34af84c45fc9ee..f20da66f989577b6c2e1262689904c86dde65a16 100644 (file)
@@ -54,22 +54,22 @@ impl ToApub for Comment {
 
     // Add a vector containing some important info to the "in_reply_to" field
     // [post_ap_id, Option(parent_comment_ap_id)]
-    let mut in_reply_to_vec = vec![post.ap_id];
+    let mut in_reply_to_vec = vec![post.ap_id.into_inner()];
 
     if let Some(parent_id) = self.parent_id {
       let parent_comment = blocking(pool, move |conn| Comment::read(conn, parent_id)).await??;
 
-      in_reply_to_vec.push(parent_comment.ap_id);
+      in_reply_to_vec.push(parent_comment.ap_id.into_inner());
     }
 
     comment
       // Not needed when the Post is embedded in a collection (like for community outbox)
       .set_many_contexts(lemmy_context()?)
-      .set_id(Url::parse(&self.ap_id)?)
+      .set_id(self.ap_id.to_owned().into_inner())
       .set_published(convert_datetime(self.published))
-      .set_to(community.actor_id)
+      .set_to(community.actor_id.into_inner())
       .set_many_in_reply_tos(in_reply_to_vec)
-      .set_attributed_to(creator.actor_id);
+      .set_attributed_to(creator.actor_id.into_inner());
 
     set_content_and_source(&mut comment, &self.content)?;
 
@@ -81,7 +81,12 @@ impl ToApub for Comment {
   }
 
   fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    create_tombstone(self.deleted, &self.ap_id, self.updated, NoteType::Note)
+    create_tombstone(
+      self.deleted,
+      self.ap_id.to_owned().into(),
+      self.updated,
+      NoteType::Note,
+    )
   }
 }
 
index 4d7a235cce7018d1807ec18a642332273add4909..566e4714af28879ba085c09a58100274ae50f191 100644 (file)
@@ -51,15 +51,15 @@ impl ToApub for Community {
       CommunityModeratorView::for_community(&conn, id)
     })
     .await??;
-    let moderators: Vec<String> = moderators
+    let moderators: Vec<Url> = moderators
       .into_iter()
-      .map(|m| m.moderator.actor_id)
+      .map(|m| m.moderator.actor_id.into_inner())
       .collect();
 
     let mut group = ApObject::new(Group::new());
     group
       .set_many_contexts(lemmy_context()?)
-      .set_id(Url::parse(&self.actor_id)?)
+      .set_id(self.actor_id.to_owned().into())
       .set_name(self.title.to_owned())
       .set_published(convert_datetime(self.published))
       .set_many_attributed_tos(moderators);
@@ -108,7 +108,12 @@ impl ToApub for Community {
   }
 
   fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    create_tombstone(self.deleted, &self.actor_id, self.updated, GroupType::Group)
+    create_tombstone(
+      self.deleted,
+      self.actor_id.to_owned().into(),
+      self.updated,
+      GroupType::Group,
+    )
   }
 }
 
index d9eea762e0191076cebd7d3e80c0e10852a46c0c..e32bfe72f3cbbc7ad682f96b3ab5f6f0c692fb12 100644 (file)
@@ -64,7 +64,7 @@ pub(in crate::objects) trait FromApubToForm<ApubType> {
 /// Updated is actually the deletion time
 fn create_tombstone<T>(
   deleted: bool,
-  object_id: &str,
+  object_id: Url,
   updated: Option<NaiveDateTime>,
   former_type: T,
 ) -> Result<Tombstone, LemmyError>
@@ -74,7 +74,7 @@ where
   if deleted {
     if let Some(updated) = updated {
       let mut tombstone = Tombstone::new();
-      tombstone.set_id(object_id.parse()?);
+      tombstone.set_id(object_id);
       tombstone.set_former_type(former_type.to_string());
       tombstone.set_deleted(convert_datetime(updated));
       Ok(tombstone)
@@ -89,14 +89,14 @@ where
 pub(in crate::objects) fn check_object_domain<T, Kind>(
   apub: &T,
   expected_domain: Url,
-) -> Result<String, LemmyError>
+) -> Result<lemmy_db_schema::Url, LemmyError>
 where
   T: Base + AsBase<Kind>,
 {
   let domain = expected_domain.domain().context(location_info!())?;
   let object_id = apub.id(domain)?.context(location_info!())?;
-  check_is_apub_id_valid(&object_id)?;
-  Ok(object_id.to_string())
+  check_is_apub_id_valid(object_id)?;
+  Ok(object_id.to_owned().into())
 }
 
 pub(in crate::objects) fn set_content_and_source<T, Kind1, Kind2>(
@@ -189,7 +189,7 @@ where
   // if its a local object, return it directly from the database
   if Settings::get().hostname == domain {
     let object = blocking(context.pool(), move |conn| {
-      To::read_from_apub_id(conn, object_id.as_str())
+      To::read_from_apub_id(conn, &object_id.into())
     })
     .await??;
     Ok(object)
index 6d5ed8e23eaf2dcf572d6f8dbaca439552180b7e..31f848a4dacac3e14a1cd1c62bf92bce7c7c86f7 100644 (file)
@@ -55,13 +55,13 @@ impl ToApub for Post {
       // TODO: need to set proper context defining sensitive/commentsEnabled fields
       // https://git.asonix.dog/Aardwolf/activitystreams/issues/5
       .set_many_contexts(lemmy_context()?)
-      .set_id(self.ap_id.parse::<Url>()?)
+      .set_id(self.ap_id.to_owned().into_inner())
       // Use summary field to be consistent with mastodon content warning.
       // https://mastodon.xyz/@Louisa/103987265222901387.json
       .set_summary(self.name.to_owned())
       .set_published(convert_datetime(self.published))
-      .set_to(community.actor_id)
-      .set_attributed_to(creator.actor_id);
+      .set_to(community.actor_id.into_inner())
+      .set_attributed_to(creator.actor_id.into_inner());
 
     if let Some(body) = &self.body {
       set_content_and_source(&mut page, &body)?;
@@ -93,7 +93,12 @@ impl ToApub for Post {
   }
 
   fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    create_tombstone(self.deleted, &self.ap_id, self.updated, PageType::Page)
+    create_tombstone(
+      self.deleted,
+      self.ap_id.to_owned().into(),
+      self.updated,
+      PageType::Page,
+    )
   }
 }
 
index 1a7b5e32752c6bd98def477a638add54d06e055a..df91b03f0ebdf1ab49c0bfee2956ba7f26bb0b73 100644 (file)
@@ -44,10 +44,10 @@ impl ToApub for PrivateMessage {
 
     private_message
       .set_many_contexts(lemmy_context()?)
-      .set_id(Url::parse(&self.ap_id.to_owned())?)
+      .set_id(self.ap_id.to_owned().into_inner())
       .set_published(convert_datetime(self.published))
-      .set_to(recipient.actor_id)
-      .set_attributed_to(creator.actor_id);
+      .set_to(recipient.actor_id.into_inner())
+      .set_attributed_to(creator.actor_id.into_inner());
 
     set_content_and_source(&mut private_message, &self.content)?;
 
@@ -59,7 +59,12 @@ impl ToApub for PrivateMessage {
   }
 
   fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    create_tombstone(self.deleted, &self.ap_id, self.updated, NoteType::Note)
+    create_tombstone(
+      self.deleted,
+      self.ap_id.to_owned().into(),
+      self.updated,
+      NoteType::Note,
+    )
   }
 }
 
index aad407f30bdf5dc6f27bcbea2eb53619fe9bd1d1..a0bd5173ce3a20ac7c5359595578d21e51d7711c 100644 (file)
@@ -41,7 +41,7 @@ impl ToApub for User_ {
     let mut person = ApObject::new(Person::new());
     person
       .set_many_contexts(lemmy_context()?)
-      .set_id(Url::parse(&self.actor_id)?)
+      .set_id(self.actor_id.to_owned().into_inner())
       .set_published(convert_datetime(self.published));
 
     if let Some(u) = self.updated {
@@ -101,7 +101,7 @@ impl FromApub for User_ {
     let domain = user_id.domain().context(location_info!())?;
     if domain == Settings::get().hostname {
       let user = blocking(context.pool(), move |conn| {
-        User_::read_from_apub_id(conn, user_id.as_str())
+        User_::read_from_apub_id(conn, &user_id.into())
       })
       .await??;
       Ok(user)
index 997f4f9644ef426041eb259c2b5c9369b0760025..b0a73b7ba95068ba2e3433cdc32a9ee0b71591ff 100644 (file)
@@ -10,6 +10,7 @@ extern crate lazy_static;
 extern crate diesel_migrations;
 
 use diesel::{result::Error, *};
+use lemmy_db_schema::Url;
 use regex::Regex;
 use serde::{Deserialize, Serialize};
 use std::{env, env::VarError};
@@ -108,7 +109,7 @@ pub trait Reportable<T> {
 }
 
 pub trait ApubObject<T> {
-  fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error>
+  fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error>
   where
     Self: Sized;
   fn upsert(conn: &PgConnection, user_form: &T) -> Result<Self, Error>
index 6e99bf36e2fad795b2c0b51c284e49acb8c79261..28d52e89c316ed38e97860ff44732bfed5205b0b 100644 (file)
@@ -10,6 +10,7 @@ use lemmy_db_schema::{
     CommentSaved,
     CommentSavedForm,
   },
+  Url,
 };
 
 pub trait Comment_ {
@@ -144,7 +145,7 @@ impl Crud<CommentForm> for Comment {
 }
 
 impl ApubObject<CommentForm> for Comment {
-  fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error> {
+  fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
     use lemmy_db_schema::schema::comment::dsl::*;
     comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
   }
index 28245d8dc358f2db41a8181101c2f52d221a1902..bb7a9c240cb3f7a121b141f74bb757c10057983d 100644 (file)
@@ -12,6 +12,7 @@ use lemmy_db_schema::{
     CommunityUserBan,
     CommunityUserBanForm,
   },
+  Url,
 };
 
 mod safe_type {
@@ -91,7 +92,7 @@ impl Crud<CommunityForm> for Community {
 }
 
 impl ApubObject<CommunityForm> for Community {
-  fn read_from_apub_id(conn: &PgConnection, for_actor_id: &str) -> Result<Self, Error> {
+  fn read_from_apub_id(conn: &PgConnection, for_actor_id: &Url) -> Result<Self, Error> {
     use lemmy_db_schema::schema::community::dsl::*;
     community
       .filter(actor_id.eq(for_actor_id))
index bca848cad2af96369aa0d0841053d6e75703fc96..7816d4a11e9d12afef3d65fa798549893eee66aa 100644 (file)
@@ -12,6 +12,7 @@ use lemmy_db_schema::{
     PostSaved,
     PostSavedForm,
   },
+  Url,
 };
 
 impl Crud<PostForm> for Post {
@@ -146,7 +147,7 @@ impl Post_ for Post {
 }
 
 impl ApubObject<PostForm> for Post {
-  fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error> {
+  fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
     use lemmy_db_schema::schema::post::dsl::*;
     post.filter(ap_id.eq(object_id)).first::<Self>(conn)
   }
index d63f698d90709b9fa0ac06cb001e49f75a3f393c..4e0f66b6510612cb06d444a5b6145ca213b138d8 100644 (file)
@@ -1,6 +1,6 @@
 use crate::{ApubObject, Crud};
 use diesel::{dsl::*, result::Error, *};
-use lemmy_db_schema::{naive_now, source::private_message::*};
+use lemmy_db_schema::{naive_now, source::private_message::*, Url};
 
 impl Crud<PrivateMessageForm> for PrivateMessage {
   fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> {
@@ -28,7 +28,7 @@ impl Crud<PrivateMessageForm> for PrivateMessage {
 }
 
 impl ApubObject<PrivateMessageForm> for PrivateMessage {
-  fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error>
+  fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error>
   where
     Self: Sized,
   {
index 6e285f99bf9bacaea918d0a82dec41e5f6dec304..b7db3e2d1fe18675d8b9e829a87c5ca06889c02f 100644 (file)
@@ -5,6 +5,7 @@ use lemmy_db_schema::{
   naive_now,
   schema::user_::dsl::*,
   source::user::{UserForm, UserSafeSettings, User_},
+  Url,
 };
 use lemmy_utils::settings::Settings;
 
@@ -237,7 +238,7 @@ impl Crud<UserForm> for User_ {
 }
 
 impl ApubObject<UserForm> for User_ {
-  fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error> {
+  fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
     use lemmy_db_schema::schema::user_::dsl::*;
     user_
       .filter(deleted.eq(false))
index 981ecba27f0e0e217f59c2e35f7f8e280cf28246..b0733884ecd2b9269e3c79e1d7608d649e07274d 100644 (file)
@@ -2,10 +2,69 @@
 extern crate diesel;
 
 use chrono::NaiveDateTime;
+use diesel::{
+  backend::Backend,
+  deserialize::FromSql,
+  serialize::{Output, ToSql},
+  sql_types::Text,
+};
+use serde::Serialize;
+use std::{
+  fmt::{Display, Formatter},
+  io::Write,
+};
 
 pub mod schema;
 pub mod source;
 
+#[repr(transparent)]
+#[derive(Clone, PartialEq, Serialize, Debug, AsExpression, FromSqlRow)]
+#[sql_type = "Text"]
+pub struct Url(url::Url);
+
+impl<DB: Backend> ToSql<Text, DB> for Url
+where
+  String: ToSql<Text, DB>,
+{
+  fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> diesel::serialize::Result {
+    self.0.to_string().to_sql(out)
+  }
+}
+
+impl<DB: Backend> FromSql<Text, DB> for Url
+where
+  String: FromSql<Text, DB>,
+{
+  fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
+    let str = String::from_sql(bytes)?;
+    Ok(Url(url::Url::parse(&str)?))
+  }
+}
+
+impl Url {
+  pub fn into_inner(self) -> url::Url {
+    self.0
+  }
+}
+
+impl Display for Url {
+  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+    self.to_owned().into_inner().fmt(f)
+  }
+}
+
+impl From<Url> for url::Url {
+  fn from(url: Url) -> Self {
+    url.0
+  }
+}
+
+impl From<url::Url> for Url {
+  fn from(url: url::Url) -> Self {
+    Url(url)
+  }
+}
+
 // TODO: can probably move this back to lemmy_db_queries
 pub fn naive_now() -> NaiveDateTime {
   chrono::prelude::Utc::now().naive_utc()
index 8c553a51a4812b35034d8e2dd68325212a4f5bca..72b9e740a1dd8b4d99bc1a3707579c1de579fc17 100644 (file)
@@ -1,9 +1,9 @@
 use crate::{
   schema::{comment, comment_alias_1, comment_like, comment_saved},
   source::post::Post,
+  Url,
 };
 use serde::Serialize;
-use url::{ParseError, Url};
 
 // WITH RECURSIVE MyTree AS (
 //     SELECT * FROM comment WHERE parent_id IS NULL
@@ -26,7 +26,7 @@ pub struct Comment {
   pub published: chrono::NaiveDateTime,
   pub updated: Option<chrono::NaiveDateTime>,
   pub deleted: bool,
-  pub ap_id: String,
+  pub ap_id: Url,
   pub local: bool,
 }
 
@@ -44,7 +44,7 @@ pub struct CommentAlias1 {
   pub published: chrono::NaiveDateTime,
   pub updated: Option<chrono::NaiveDateTime>,
   pub deleted: bool,
-  pub ap_id: String,
+  pub ap_id: Url,
   pub local: bool,
 }
 
@@ -60,16 +60,10 @@ pub struct CommentForm {
   pub published: Option<chrono::NaiveDateTime>,
   pub updated: Option<chrono::NaiveDateTime>,
   pub deleted: Option<bool>,
-  pub ap_id: Option<String>,
+  pub ap_id: Option<Url>,
   pub local: bool,
 }
 
-impl CommentForm {
-  pub fn get_ap_id(&self) -> Result<Url, ParseError> {
-    Url::parse(&self.ap_id.as_ref().unwrap_or(&"not_a_url".to_string()))
-  }
-}
-
 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)]
 #[belongs_to(Comment)]
 #[table_name = "comment_like"]
index af7fce0c930dec8581880c12d83ad23f3fc47163..d938d265efc150a395c3676e3d72a9b395377993 100644 (file)
@@ -1,4 +1,7 @@
-use crate::schema::{community, community_follower, community_moderator, community_user_ban};
+use crate::{
+  schema::{community, community_follower, community_moderator, community_user_ban},
+  Url,
+};
 use serde::Serialize;
 
 #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
@@ -15,7 +18,7 @@ pub struct Community {
   pub updated: Option<chrono::NaiveDateTime>,
   pub deleted: bool,
   pub nsfw: bool,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub local: bool,
   pub private_key: Option<String>,
   pub public_key: Option<String>,
@@ -39,7 +42,7 @@ pub struct CommunitySafe {
   pub updated: Option<chrono::NaiveDateTime>,
   pub deleted: bool,
   pub nsfw: bool,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub local: bool,
   pub icon: Option<String>,
   pub banner: Option<String>,
@@ -58,7 +61,7 @@ pub struct CommunityForm {
   pub updated: Option<chrono::NaiveDateTime>,
   pub deleted: Option<bool>,
   pub nsfw: bool,
-  pub actor_id: Option<String>,
+  pub actor_id: Option<Url>,
   pub local: bool,
   pub private_key: Option<String>,
   pub public_key: Option<String>,
index b0cc78e0e2d84381f9c74ef7af66377664a95823..4ec6b56d01d4530f618fce574710e34650daf241 100644 (file)
@@ -1,6 +1,8 @@
-use crate::schema::{post, post_like, post_read, post_saved};
+use crate::{
+  schema::{post, post_like, post_read, post_saved},
+  Url,
+};
 use serde::Serialize;
-use url::{ParseError, Url};
 
 #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
 #[table_name = "post"]
@@ -22,7 +24,7 @@ pub struct Post {
   pub embed_description: Option<String>,
   pub embed_html: Option<String>,
   pub thumbnail_url: Option<String>,
-  pub ap_id: String,
+  pub ap_id: Url,
   pub local: bool,
 }
 
@@ -45,16 +47,10 @@ pub struct PostForm {
   pub embed_description: Option<String>,
   pub embed_html: Option<String>,
   pub thumbnail_url: Option<String>,
-  pub ap_id: Option<String>,
+  pub ap_id: Option<Url>,
   pub local: bool,
 }
 
-impl PostForm {
-  pub fn get_ap_id(&self) -> Result<Url, ParseError> {
-    Url::parse(&self.ap_id.as_ref().unwrap_or(&"not_a_url".to_string()))
-  }
-}
-
 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
 #[belongs_to(Post)]
 #[table_name = "post_like"]
index 3410406929716da67531096373eab4360c1d071c..376728a1bc2e57c88f79f64297042a31d1651e78 100644 (file)
@@ -1,4 +1,4 @@
-use crate::schema::private_message;
+use crate::{schema::private_message, Url};
 use serde::Serialize;
 
 #[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
@@ -12,7 +12,7 @@ pub struct PrivateMessage {
   pub read: bool,
   pub published: chrono::NaiveDateTime,
   pub updated: Option<chrono::NaiveDateTime>,
-  pub ap_id: String,
+  pub ap_id: Url,
   pub local: bool,
 }
 
@@ -26,6 +26,6 @@ pub struct PrivateMessageForm {
   pub read: Option<bool>,
   pub published: Option<chrono::NaiveDateTime>,
   pub updated: Option<chrono::NaiveDateTime>,
-  pub ap_id: Option<String>,
+  pub ap_id: Option<Url>,
   pub local: bool,
 }
index f9dc0a59ad3be37479003b2e45b9ff5b661f7321..f702c84bbe65757bb325babd7bb012540cd160f1 100644 (file)
@@ -1,4 +1,7 @@
-use crate::schema::{user_, user_alias_1, user_alias_2};
+use crate::{
+  schema::{user_, user_alias_1, user_alias_2},
+  Url,
+};
 use serde::Serialize;
 
 #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
@@ -22,7 +25,7 @@ pub struct User_ {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub private_key: Option<String>,
@@ -45,7 +48,7 @@ pub struct UserSafe {
   pub published: chrono::NaiveDateTime,
   pub updated: Option<chrono::NaiveDateTime>,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub banner: Option<String>,
@@ -73,7 +76,7 @@ pub struct UserSafeSettings {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub last_refreshed_at: chrono::NaiveDateTime,
@@ -102,7 +105,7 @@ pub struct UserAlias1 {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub private_key: Option<String>,
@@ -124,7 +127,7 @@ pub struct UserSafeAlias1 {
   pub published: chrono::NaiveDateTime,
   pub updated: Option<chrono::NaiveDateTime>,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub banner: Option<String>,
@@ -152,7 +155,7 @@ pub struct UserAlias2 {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub private_key: Option<String>,
@@ -174,7 +177,7 @@ pub struct UserSafeAlias2 {
   pub published: chrono::NaiveDateTime,
   pub updated: Option<chrono::NaiveDateTime>,
   pub matrix_user_id: Option<String>,
-  pub actor_id: String,
+  pub actor_id: Url,
   pub bio: Option<String>,
   pub local: bool,
   pub banner: Option<String>,
@@ -201,7 +204,7 @@ pub struct UserForm {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub matrix_user_id: Option<Option<String>>,
-  pub actor_id: Option<String>,
+  pub actor_id: Option<Url>,
   pub bio: Option<Option<String>>,
   pub local: bool,
   pub private_key: Option<String>,
index 36a47772f6a916e3ce7ab9c024ed3f6112c6ae2e..75d107c8e270decb971675cbaab4f8fbf47ba187 100644 (file)
@@ -21,3 +21,4 @@ diesel = "1.4.5"
 actix-web = "3.3.2"
 chrono = { version = "0.4.19", features = ["serde"] }
 serde_json = { version = "1.0.60", features = ["preserve_order"] }
+url = "2.2.0"
index f91b5fcb0b1f943b996a9e8c9594c6fe3a6c6d76..8b56fab6b9c970c63e3dea3810a079b049ac9a06 100644 (file)
@@ -16,13 +16,14 @@ use lemmy_db_schema::source::{
 use lemmy_utils::{email::send_email, settings::Settings, utils::MentionData, LemmyError};
 use log::error;
 use serde::{Deserialize, Serialize};
+use url::Url;
 
 #[derive(Serialize, Deserialize, Debug)]
 pub struct WebFingerLink {
   pub rel: Option<String>,
   #[serde(rename(serialize = "type", deserialize = "type"))]
   pub type_: Option<String>,
-  pub href: Option<String>,
+  pub href: Option<Url>,
   #[serde(skip_serializing_if = "Option::is_none")]
   pub template: Option<String>,
 }
@@ -30,7 +31,7 @@ pub struct WebFingerLink {
 #[derive(Serialize, Deserialize, Debug)]
 pub struct WebFingerResponse {
   pub subject: String,
-  pub aliases: Vec<String>,
+  pub aliases: Vec<Url>,
   pub links: Vec<WebFingerLink>,
 }
 
diff --git a/migrations/2021-01-26-173850_default_actor_id/down.sql b/migrations/2021-01-26-173850_default_actor_id/down.sql
new file mode 100644 (file)
index 0000000..fb61274
--- /dev/null
@@ -0,0 +1,6 @@
+create or replace function generate_unique_changeme() 
+returns text language sql 
+as $$
+  select 'changeme_' || string_agg (substr('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789', ceil (random() * 62)::integer, 1), '')
+  from generate_series(1, 20)
+$$;
\ No newline at end of file
diff --git a/migrations/2021-01-26-173850_default_actor_id/up.sql b/migrations/2021-01-26-173850_default_actor_id/up.sql
new file mode 100644 (file)
index 0000000..4370c4a
--- /dev/null
@@ -0,0 +1,6 @@
+create or replace function generate_unique_changeme() 
+returns text language sql 
+as $$
+  select 'http://changeme_' || string_agg (substr('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789', ceil (random() * 62)::integer, 1), '')
+  from generate_series(1, 20)
+$$;
\ No newline at end of file
index d2928244e46586a3872f0a6a7431d848b0e79802..a6586ae73ff5c605f6d67c2f1ec3c9cffd4de75a 100644 (file)
@@ -42,7 +42,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
 
   // Update the actor_id, private_key, and public_key, last_refreshed_at
   let incorrect_users = user_
-    .filter(actor_id.like("changeme_%"))
+    .filter(actor_id.like("http://changeme_%"))
     .filter(local.eq(true))
     .load::<User_>(conn)?;
 
@@ -68,7 +68,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
       lang: cuser.lang.to_owned(),
       show_avatars: cuser.show_avatars,
       send_notifications_to_email: cuser.send_notifications_to_email,
-      actor_id: Some(make_apub_endpoint(EndpointType::User, &cuser.name).to_string()),
+      actor_id: Some(make_apub_endpoint(EndpointType::User, &cuser.name).into()),
       bio: Some(cuser.bio.to_owned()),
       local: cuser.local,
       private_key: Some(keypair.private_key),
@@ -91,7 +91,7 @@ fn community_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
 
   // Update the actor_id, private_key, and public_key, last_refreshed_at
   let incorrect_communities = community
-    .filter(actor_id.like("changeme_%"))
+    .filter(actor_id.like("http://changeme_%"))
     .filter(local.eq(true))
     .load::<Community>(conn)?;
 
@@ -108,7 +108,7 @@ fn community_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
       deleted: None,
       nsfw: ccommunity.nsfw,
       updated: None,
-      actor_id: Some(make_apub_endpoint(EndpointType::Community, &ccommunity.name).to_string()),
+      actor_id: Some(make_apub_endpoint(EndpointType::Community, &ccommunity.name).into()),
       local: ccommunity.local,
       private_key: Some(keypair.private_key),
       public_key: Some(keypair.public_key),
@@ -133,7 +133,7 @@ fn post_updates_2020_04_03(conn: &PgConnection) -> Result<(), LemmyError> {
 
   // Update the ap_id
   let incorrect_posts = post
-    .filter(ap_id.eq("changeme_%"))
+    .filter(ap_id.eq("http://changeme_%"))
     .filter(local.eq(true))
     .load::<Post>(conn)?;
 
@@ -154,7 +154,7 @@ fn comment_updates_2020_04_03(conn: &PgConnection) -> Result<(), LemmyError> {
 
   // Update the ap_id
   let incorrect_comments = comment
-    .filter(ap_id.eq("changeme_%"))
+    .filter(ap_id.eq("http://changeme_%"))
     .filter(local.eq(true))
     .load::<Comment>(conn)?;
 
@@ -175,7 +175,7 @@ fn private_message_updates_2020_05_05(conn: &PgConnection) -> Result<(), LemmyEr
 
   // Update the ap_id
   let incorrect_pms = private_message
-    .filter(ap_id.eq("changeme_%"))
+    .filter(ap_id.eq("http://changeme_%"))
     .filter(local.eq(true))
     .load::<PrivateMessage>(conn)?;
 
index 5065390c2eb1457ce88880ce50e07df2d282998f..864670527812bca8f870bdd88fec012d3c761beb 100644 (file)
@@ -204,7 +204,7 @@ fn get_feed_community(
   channel_builder
     .namespaces(RSS_NAMESPACE.to_owned())
     .title(&format!("{} - {}", site_view.site.name, community.name))
-    .link(community.actor_id)
+    .link(community.actor_id.to_string())
     .items(items);
 
   if let Some(community_desc) = community.description {
@@ -367,7 +367,7 @@ fn create_post_items(posts: Vec<PostView>) -> Result<Vec<Item>, LemmyError> {
 
     i.title(p.post.name);
 
-    dc_extension.creators(vec![p.creator.actor_id.to_owned()]);
+    dc_extension.creators(vec![p.creator.actor_id.to_string()]);
 
     let dt = DateTime::<Utc>::from_utc(p.post.published, Utc);
     i.pub_date(dt.to_rfc2822());
index 0e4d7f948629373ed5821e82e526a62f4eb3fd84..4059e0f893d0491e774c22fa4d76e9f0c87df70b 100644 (file)
@@ -70,18 +70,18 @@ async fn get_webfinger_response(
 
   let json = WebFingerResponse {
     subject: info.resource.to_owned(),
-    aliases: vec![url.to_owned()],
+    aliases: vec![url.to_owned().into()],
     links: vec![
       WebFingerLink {
         rel: Some("http://webfinger.net/rel/profile-page".to_string()),
         type_: Some("text/html".to_string()),
-        href: Some(url.to_owned()),
+        href: Some(url.to_owned().into()),
         template: None,
       },
       WebFingerLink {
         rel: Some("self".to_string()),
         type_: Some("application/activity+json".to_string()),
-        href: Some(url),
+        href: Some(url.into()),
         template: None,
       }, // TODO: this also needs to return the subscribe link once that's implemented
          //{
index 5e6964e440d914cfe3bc08402006e8a0da56bdbd..28e67a71a22747884501e3724a9da413083a3ba1 100644 (file)
@@ -104,7 +104,11 @@ fn create_user(conn: &PgConnection, name: &str) -> User_ {
     lang: "browser".into(),
     show_avatars: true,
     send_notifications_to_email: false,
-    actor_id: Some(format!("http://localhost:8536/u/{}", name)),
+    actor_id: Some(
+      Url::parse(&format!("http://localhost:8536/u/{}", name))
+        .unwrap()
+        .into(),
+    ),
     bio: None,
     local: true,
     private_key: Some(user_keypair.private_key),
@@ -137,7 +141,7 @@ fn create_community(conn: &PgConnection, creator_id: i32) -> Community {
   };
   Community::create(&conn, &new_community).unwrap()
 }
-fn create_activity<'a, Activity, Return>(user_id: String) -> web::Json<Return>
+fn create_activity<'a, Activity, Return>(user_id: Url) -> web::Json<Return>
 where
   for<'de> Return: Deserialize<'de> + 'a,
   Activity: std::default::Default + Serialize,
@@ -173,7 +177,7 @@ async fn test_shared_inbox_expired_signature() {
   let connection = &context.pool().get().unwrap();
   let user = create_user(connection, "shared_inbox_rvgfd");
   let activity =
-    create_activity::<CreateType, ActorAndObject<shared_inbox::ValidTypes>>(user.actor_id);
+    create_activity::<CreateType, ActorAndObject<shared_inbox::ValidTypes>>(user.actor_id.into());
   let response = shared_inbox(request, activity, web::Data::new(context)).await;
   assert_eq!(
     format!("{}", response.err().unwrap()),
@@ -189,7 +193,7 @@ async fn test_user_inbox_expired_signature() {
   let connection = &context.pool().get().unwrap();
   let user = create_user(connection, "user_inbox_cgsax");
   let activity =
-    create_activity::<CreateType, ActorAndObject<user_inbox::UserValidTypes>>(user.actor_id);
+    create_activity::<CreateType, ActorAndObject<user_inbox::UserValidTypes>>(user.actor_id.into());
   let path = Path::<String> {
     0: "username".to_string(),
   };
@@ -209,7 +213,7 @@ async fn test_community_inbox_expired_signature() {
   let community = create_community(connection, user.id);
   let request = create_http_request();
   let activity = create_activity::<FollowType, ActorAndObject<community_inbox::CommunityValidTypes>>(
-    user.actor_id,
+    user.actor_id.into(),
   );
   let path = Path::<String> { 0: community.name };
   let response = community_inbox(request, activity, path, web::Data::new(context)).await;