Move AP ID parsers to activitypub::identifiers module
This commit is contained in:
parent
d2ba86315c
commit
9a38fb25bf
11 changed files with 156 additions and 117 deletions
|
@ -9,7 +9,7 @@ use crate::activitypub::handlers::{
|
||||||
create_note::handle_note,
|
create_note::handle_note,
|
||||||
update_person::update_remote_profile,
|
update_person::update_remote_profile,
|
||||||
};
|
};
|
||||||
use crate::activitypub::receiver::parse_object_id;
|
use crate::activitypub::identifiers::parse_local_object_id;
|
||||||
use crate::config::{Config, Instance};
|
use crate::config::{Config, Instance};
|
||||||
use crate::errors::{DatabaseError, HttpError, ValidationError};
|
use crate::errors::{DatabaseError, HttpError, ValidationError};
|
||||||
use crate::models::posts::queries::get_post_by_object_id;
|
use crate::models::posts::queries::get_post_by_object_id;
|
||||||
|
@ -193,7 +193,7 @@ pub async fn import_post(
|
||||||
loop {
|
loop {
|
||||||
let object_id = match maybe_object_id_to_fetch {
|
let object_id = match maybe_object_id_to_fetch {
|
||||||
Some(object_id) => {
|
Some(object_id) => {
|
||||||
if parse_object_id(&instance.url(), &object_id).is_ok() {
|
if parse_local_object_id(&instance.url(), &object_id).is_ok() {
|
||||||
// Object is a local post
|
// Object is a local post
|
||||||
assert!(objects.len() > 0);
|
assert!(objects.len() > 0);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -2,7 +2,8 @@ use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
activity::Activity,
|
activity::Activity,
|
||||||
receiver::{find_object_id, parse_object_id},
|
identifiers::parse_local_object_id,
|
||||||
|
receiver::find_object_id,
|
||||||
vocabulary::FOLLOW,
|
vocabulary::FOLLOW,
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
@ -21,7 +22,10 @@ pub async fn handle_accept_follow(
|
||||||
) -> HandlerResult {
|
) -> HandlerResult {
|
||||||
let actor_profile = get_profile_by_actor_id(db_client, &activity.actor).await?;
|
let actor_profile = get_profile_by_actor_id(db_client, &activity.actor).await?;
|
||||||
let object_id = find_object_id(&activity.object)?;
|
let object_id = find_object_id(&activity.object)?;
|
||||||
let follow_request_id = parse_object_id(&config.instance_url(), &object_id)?;
|
let follow_request_id = parse_local_object_id(
|
||||||
|
&config.instance_url(),
|
||||||
|
&object_id,
|
||||||
|
)?;
|
||||||
let follow_request = get_follow_request_by_id(db_client, &follow_request_id).await?;
|
let follow_request = get_follow_request_by_id(db_client, &follow_request_id).await?;
|
||||||
if follow_request.target_id != actor_profile.id {
|
if follow_request.target_id != actor_profile.id {
|
||||||
return Err(ValidationError("actor is not a target").into());
|
return Err(ValidationError("actor is not a target").into());
|
||||||
|
|
|
@ -3,7 +3,8 @@ use tokio_postgres::GenericClient;
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
activity::Activity,
|
activity::Activity,
|
||||||
fetcher::helpers::{get_or_import_profile_by_actor_id, import_post},
|
fetcher::helpers::{get_or_import_profile_by_actor_id, import_post},
|
||||||
receiver::{find_object_id, parse_object_id},
|
identifiers::parse_local_object_id,
|
||||||
|
receiver::find_object_id,
|
||||||
vocabulary::NOTE,
|
vocabulary::NOTE,
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
@ -30,7 +31,7 @@ pub async fn handle_announce(
|
||||||
&activity.actor,
|
&activity.actor,
|
||||||
).await?;
|
).await?;
|
||||||
let object_id = find_object_id(&activity.object)?;
|
let object_id = find_object_id(&activity.object)?;
|
||||||
let post_id = match parse_object_id(&config.instance_url(), &object_id) {
|
let post_id = match parse_local_object_id(&config.instance_url(), &object_id) {
|
||||||
Ok(post_id) => post_id,
|
Ok(post_id) => post_id,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Try to get remote post
|
// Try to get remote post
|
||||||
|
|
|
@ -4,21 +4,19 @@ use std::path::Path;
|
||||||
use tokio_postgres::GenericClient;
|
use tokio_postgres::GenericClient;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::activitypub::activity::{Attachment, Object};
|
use crate::activitypub::{
|
||||||
use crate::activitypub::constants::AP_PUBLIC;
|
activity::{Attachment, Object},
|
||||||
use crate::activitypub::fetcher::fetchers::fetch_file;
|
constants::AP_PUBLIC,
|
||||||
use crate::activitypub::fetcher::helpers::{
|
fetcher::fetchers::fetch_file,
|
||||||
get_or_import_profile_by_actor_id,
|
fetcher::helpers::{
|
||||||
import_profile_by_actor_address,
|
get_or_import_profile_by_actor_id,
|
||||||
ImportError,
|
import_profile_by_actor_address,
|
||||||
|
ImportError,
|
||||||
|
},
|
||||||
|
identifiers::{parse_local_actor_id, parse_local_object_id},
|
||||||
|
receiver::{parse_array, parse_property_value},
|
||||||
|
vocabulary::{DOCUMENT, HASHTAG, IMAGE, MENTION, NOTE},
|
||||||
};
|
};
|
||||||
use crate::activitypub::receiver::{
|
|
||||||
parse_actor_id,
|
|
||||||
parse_array,
|
|
||||||
parse_object_id,
|
|
||||||
parse_property_value,
|
|
||||||
};
|
|
||||||
use crate::activitypub::vocabulary::{DOCUMENT, HASHTAG, IMAGE, MENTION, NOTE};
|
|
||||||
use crate::config::Instance;
|
use crate::config::Instance;
|
||||||
use crate::errors::{DatabaseError, ValidationError};
|
use crate::errors::{DatabaseError, ValidationError};
|
||||||
use crate::models::attachments::queries::create_attachment;
|
use crate::models::attachments::queries::create_attachment;
|
||||||
|
@ -163,7 +161,7 @@ pub async fn handle_note(
|
||||||
} else if tag.tag_type == MENTION {
|
} else if tag.tag_type == MENTION {
|
||||||
// Try to find profile by actor ID.
|
// Try to find profile by actor ID.
|
||||||
if let Some(href) = tag.href {
|
if let Some(href) = tag.href {
|
||||||
if let Ok(username) = parse_actor_id(&instance.url(), &href) {
|
if let Ok(username) = parse_local_actor_id(&instance.url(), &href) {
|
||||||
let user = get_user_by_name(db_client, &username).await?;
|
let user = get_user_by_name(db_client, &username).await?;
|
||||||
if !mentions.contains(&user.id) {
|
if !mentions.contains(&user.id) {
|
||||||
mentions.push(user.id);
|
mentions.push(user.id);
|
||||||
|
@ -245,7 +243,7 @@ pub async fn handle_note(
|
||||||
};
|
};
|
||||||
let in_reply_to_id = match object.in_reply_to {
|
let in_reply_to_id = match object.in_reply_to {
|
||||||
Some(object_id) => {
|
Some(object_id) => {
|
||||||
match parse_object_id(&instance.url(), &object_id) {
|
match parse_local_object_id(&instance.url(), &object_id) {
|
||||||
Ok(post_id) => {
|
Ok(post_id) => {
|
||||||
// Local post
|
// Local post
|
||||||
let post = get_post_by_id(db_client, &post_id).await?;
|
let post = get_post_by_id(db_client, &post_id).await?;
|
||||||
|
|
|
@ -4,7 +4,8 @@ use crate::activitypub::{
|
||||||
activity::Activity,
|
activity::Activity,
|
||||||
builders::accept_follow::prepare_accept_follow,
|
builders::accept_follow::prepare_accept_follow,
|
||||||
fetcher::helpers::{get_or_import_profile_by_actor_id, ImportError},
|
fetcher::helpers::{get_or_import_profile_by_actor_id, ImportError},
|
||||||
receiver::{find_object_id, parse_actor_id},
|
identifiers::parse_local_actor_id,
|
||||||
|
receiver::find_object_id,
|
||||||
vocabulary::PERSON,
|
vocabulary::PERSON,
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
@ -27,7 +28,10 @@ pub async fn handle_follow(
|
||||||
let source_actor = source_profile.actor_json
|
let source_actor = source_profile.actor_json
|
||||||
.ok_or(ImportError::LocalObject)?;
|
.ok_or(ImportError::LocalObject)?;
|
||||||
let target_actor_id = find_object_id(&activity.object)?;
|
let target_actor_id = find_object_id(&activity.object)?;
|
||||||
let target_username = parse_actor_id(&config.instance_url(), &target_actor_id)?;
|
let target_username = parse_local_actor_id(
|
||||||
|
&config.instance_url(),
|
||||||
|
&target_actor_id,
|
||||||
|
)?;
|
||||||
let target_user = get_user_by_name(db_client, &target_username).await?;
|
let target_user = get_user_by_name(db_client, &target_username).await?;
|
||||||
match follow(db_client, &source_profile.id, &target_user.profile.id).await {
|
match follow(db_client, &source_profile.id, &target_user.profile.id).await {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
|
|
|
@ -3,7 +3,8 @@ use tokio_postgres::GenericClient;
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
activity::Activity,
|
activity::Activity,
|
||||||
fetcher::helpers::get_or_import_profile_by_actor_id,
|
fetcher::helpers::get_or_import_profile_by_actor_id,
|
||||||
receiver::{find_object_id, parse_object_id},
|
identifiers::parse_local_object_id,
|
||||||
|
receiver::find_object_id,
|
||||||
vocabulary::NOTE,
|
vocabulary::NOTE,
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
@ -24,7 +25,7 @@ pub async fn handle_like(
|
||||||
&activity.actor,
|
&activity.actor,
|
||||||
).await?;
|
).await?;
|
||||||
let object_id = find_object_id(&activity.object)?;
|
let object_id = find_object_id(&activity.object)?;
|
||||||
let post_id = match parse_object_id(&config.instance_url(), &object_id) {
|
let post_id = match parse_local_object_id(&config.instance_url(), &object_id) {
|
||||||
Ok(post_id) => post_id,
|
Ok(post_id) => post_id,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let post = match get_post_by_object_id(db_client, &object_id).await {
|
let post = match get_post_by_object_id(db_client, &object_id).await {
|
||||||
|
|
|
@ -2,7 +2,8 @@ use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
activity::Activity,
|
activity::Activity,
|
||||||
receiver::{find_object_id, parse_object_id},
|
identifiers::parse_local_object_id,
|
||||||
|
receiver::find_object_id,
|
||||||
vocabulary::FOLLOW,
|
vocabulary::FOLLOW,
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
@ -21,7 +22,10 @@ pub async fn handle_reject_follow(
|
||||||
) -> HandlerResult {
|
) -> HandlerResult {
|
||||||
let actor_profile = get_profile_by_actor_id(db_client, &activity.actor).await?;
|
let actor_profile = get_profile_by_actor_id(db_client, &activity.actor).await?;
|
||||||
let object_id = find_object_id(&activity.object)?;
|
let object_id = find_object_id(&activity.object)?;
|
||||||
let follow_request_id = parse_object_id(&config.instance_url(), &object_id)?;
|
let follow_request_id = parse_local_object_id(
|
||||||
|
&config.instance_url(),
|
||||||
|
&object_id,
|
||||||
|
)?;
|
||||||
let follow_request = get_follow_request_by_id(db_client, &follow_request_id).await?;
|
let follow_request = get_follow_request_by_id(db_client, &follow_request_id).await?;
|
||||||
if follow_request.target_id != actor_profile.id {
|
if follow_request.target_id != actor_profile.id {
|
||||||
return Err(ValidationError("actor is not a target").into());
|
return Err(ValidationError("actor is not a target").into());
|
||||||
|
|
|
@ -2,7 +2,7 @@ use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
activity::{Activity, Object},
|
activity::{Activity, Object},
|
||||||
receiver::parse_actor_id,
|
identifiers::parse_local_actor_id,
|
||||||
vocabulary::FOLLOW,
|
vocabulary::FOLLOW,
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
@ -24,7 +24,10 @@ pub async fn handle_undo_follow(
|
||||||
let source_profile = get_profile_by_actor_id(db_client, &activity.actor).await?;
|
let source_profile = get_profile_by_actor_id(db_client, &activity.actor).await?;
|
||||||
let target_actor_id = object.object
|
let target_actor_id = object.object
|
||||||
.ok_or(ValidationError("invalid object"))?;
|
.ok_or(ValidationError("invalid object"))?;
|
||||||
let target_username = parse_actor_id(&config.instance_url(), &target_actor_id)?;
|
let target_username = parse_local_actor_id(
|
||||||
|
&config.instance_url(),
|
||||||
|
&target_actor_id,
|
||||||
|
)?;
|
||||||
// acct equals username if profile is local
|
// acct equals username if profile is local
|
||||||
let target_profile = get_profile_by_acct(db_client, &target_username).await?;
|
let target_profile = get_profile_by_acct(db_client, &target_username).await?;
|
||||||
match unfollow(db_client, &source_profile.id, &target_profile.id).await {
|
match unfollow(db_client, &source_profile.id, &target_profile.id).await {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use chrono::Utc;
|
||||||
use tokio_postgres::GenericClient;
|
use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::activity::Object;
|
use crate::activitypub::activity::Object;
|
||||||
use crate::activitypub::receiver::parse_object_id;
|
use crate::activitypub::identifiers::parse_local_object_id;
|
||||||
use crate::activitypub::vocabulary::NOTE;
|
use crate::activitypub::vocabulary::NOTE;
|
||||||
use crate::errors::DatabaseError;
|
use crate::errors::DatabaseError;
|
||||||
use crate::models::posts::queries::{
|
use crate::models::posts::queries::{
|
||||||
|
@ -18,7 +18,7 @@ pub async fn handle_update_note(
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
object: Object,
|
object: Object,
|
||||||
) -> HandlerResult {
|
) -> HandlerResult {
|
||||||
let post_id = match parse_object_id(instance_url, &object.id) {
|
let post_id = match parse_local_object_id(instance_url, &object.id) {
|
||||||
Ok(post_id) => post_id,
|
Ok(post_id) => post_id,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let post = match get_post_by_object_id(db_client, &object.id).await {
|
let post = match get_post_by_object_id(db_client, &object.id).await {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use regex::Regex;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::errors::ValidationError;
|
||||||
|
|
||||||
pub enum LocalActorCollection {
|
pub enum LocalActorCollection {
|
||||||
Inbox,
|
Inbox,
|
||||||
Outbox,
|
Outbox,
|
||||||
|
@ -57,3 +60,109 @@ pub fn local_instance_actor_id(instance_url: &str) -> String {
|
||||||
pub fn local_object_id(instance_url: &str, internal_object_id: &Uuid) -> String {
|
pub fn local_object_id(instance_url: &str, internal_object_id: &Uuid) -> String {
|
||||||
format!("{}/objects/{}", instance_url, internal_object_id)
|
format!("{}/objects/{}", instance_url, internal_object_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_local_actor_id(
|
||||||
|
instance_url: &str,
|
||||||
|
actor_id: &str,
|
||||||
|
) -> Result<String, ValidationError> {
|
||||||
|
let url_regexp_str = format!(
|
||||||
|
"^{}/users/(?P<username>[0-9a-z_]+)$",
|
||||||
|
instance_url.replace('.', r"\."),
|
||||||
|
);
|
||||||
|
let url_regexp = Regex::new(&url_regexp_str)
|
||||||
|
.map_err(|_| ValidationError("error"))?;
|
||||||
|
let url_caps = url_regexp.captures(actor_id)
|
||||||
|
.ok_or(ValidationError("invalid actor ID"))?;
|
||||||
|
let username = url_caps.name("username")
|
||||||
|
.ok_or(ValidationError("invalid actor ID"))?
|
||||||
|
.as_str()
|
||||||
|
.to_owned();
|
||||||
|
Ok(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_local_object_id(
|
||||||
|
instance_url: &str,
|
||||||
|
object_id: &str,
|
||||||
|
) -> Result<Uuid, ValidationError> {
|
||||||
|
let url_regexp_str = format!(
|
||||||
|
"^{}/objects/(?P<uuid>[0-9a-f-]+)$",
|
||||||
|
instance_url.replace('.', r"\."),
|
||||||
|
);
|
||||||
|
let url_regexp = Regex::new(&url_regexp_str)
|
||||||
|
.map_err(|_| ValidationError("error"))?;
|
||||||
|
let url_caps = url_regexp.captures(object_id)
|
||||||
|
.ok_or(ValidationError("invalid object ID"))?;
|
||||||
|
let internal_object_id: Uuid = url_caps.name("uuid")
|
||||||
|
.ok_or(ValidationError("invalid object ID"))?
|
||||||
|
.as_str().parse()
|
||||||
|
.map_err(|_| ValidationError("invalid object ID"))?;
|
||||||
|
Ok(internal_object_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::utils::id::new_uuid;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INSTANCE_URL: &str = "https://example.org";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_local_actor_id() {
|
||||||
|
let username = parse_local_actor_id(
|
||||||
|
INSTANCE_URL,
|
||||||
|
"https://example.org/users/test",
|
||||||
|
).unwrap();
|
||||||
|
assert_eq!(username, "test".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_local_actor_id_wrong_path() {
|
||||||
|
let error = parse_local_actor_id(
|
||||||
|
INSTANCE_URL,
|
||||||
|
"https://example.org/user/test",
|
||||||
|
).unwrap_err();
|
||||||
|
assert_eq!(error.to_string(), "invalid actor ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_local_actor_id_invalid_username() {
|
||||||
|
let error = parse_local_actor_id(
|
||||||
|
INSTANCE_URL,
|
||||||
|
"https://example.org/users/tes-t",
|
||||||
|
).unwrap_err();
|
||||||
|
assert_eq!(error.to_string(), "invalid actor ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_local_actor_id_invalid_instance_url() {
|
||||||
|
let error = parse_local_actor_id(
|
||||||
|
INSTANCE_URL,
|
||||||
|
"https://example.gov/users/test",
|
||||||
|
).unwrap_err();
|
||||||
|
assert_eq!(error.to_string(), "invalid actor ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_local_object_id() {
|
||||||
|
let expected_uuid = new_uuid();
|
||||||
|
let object_id = format!(
|
||||||
|
"https://example.org/objects/{}",
|
||||||
|
expected_uuid,
|
||||||
|
);
|
||||||
|
let internal_object_id = parse_local_object_id(
|
||||||
|
INSTANCE_URL,
|
||||||
|
&object_id,
|
||||||
|
).unwrap();
|
||||||
|
assert_eq!(internal_object_id, expected_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_local_object_id_invalid_uuid() {
|
||||||
|
let object_id = "https://example.org/objects/1234";
|
||||||
|
let error = parse_local_object_id(
|
||||||
|
INSTANCE_URL,
|
||||||
|
object_id,
|
||||||
|
).unwrap_err();
|
||||||
|
assert_eq!(error.to_string(), "invalid object ID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use actix_web::HttpRequest;
|
use actix_web::HttpRequest;
|
||||||
use regex::Regex;
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tokio_postgres::GenericClient;
|
use tokio_postgres::GenericClient;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::errors::{ConversionError, HttpError, ValidationError};
|
use crate::errors::{ConversionError, HttpError, ValidationError};
|
||||||
|
@ -24,44 +22,6 @@ use super::handlers::{
|
||||||
};
|
};
|
||||||
use super::vocabulary::*;
|
use super::vocabulary::*;
|
||||||
|
|
||||||
pub fn parse_actor_id(
|
|
||||||
instance_url: &str,
|
|
||||||
actor_id: &str,
|
|
||||||
) -> Result<String, ValidationError> {
|
|
||||||
let url_regexp_str = format!(
|
|
||||||
"^{}/users/(?P<username>[0-9a-z_]+)$",
|
|
||||||
instance_url.replace('.', r"\."),
|
|
||||||
);
|
|
||||||
let url_regexp = Regex::new(&url_regexp_str)
|
|
||||||
.map_err(|_| ValidationError("error"))?;
|
|
||||||
let url_caps = url_regexp.captures(actor_id)
|
|
||||||
.ok_or(ValidationError("invalid actor ID"))?;
|
|
||||||
let username = url_caps.name("username")
|
|
||||||
.ok_or(ValidationError("invalid actor ID"))?
|
|
||||||
.as_str()
|
|
||||||
.to_owned();
|
|
||||||
Ok(username)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_object_id(
|
|
||||||
instance_url: &str,
|
|
||||||
object_id: &str,
|
|
||||||
) -> Result<Uuid, ValidationError> {
|
|
||||||
let url_regexp_str = format!(
|
|
||||||
"^{}/objects/(?P<uuid>[0-9a-f-]+)$",
|
|
||||||
instance_url.replace('.', r"\."),
|
|
||||||
);
|
|
||||||
let url_regexp = Regex::new(&url_regexp_str)
|
|
||||||
.map_err(|_| ValidationError("error"))?;
|
|
||||||
let url_caps = url_regexp.captures(object_id)
|
|
||||||
.ok_or(ValidationError("invalid object ID"))?;
|
|
||||||
let internal_object_id: Uuid = url_caps.name("uuid")
|
|
||||||
.ok_or(ValidationError("invalid object ID"))?
|
|
||||||
.as_str().parse()
|
|
||||||
.map_err(|_| ValidationError("invalid object ID"))?;
|
|
||||||
Ok(internal_object_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transforms arbitrary property value into array of strings
|
/// Transforms arbitrary property value into array of strings
|
||||||
pub fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> {
|
pub fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> {
|
||||||
let result = match value {
|
let result = match value {
|
||||||
|
@ -252,53 +212,8 @@ pub async fn receive_activity(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use crate::utils::id::new_uuid;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const INSTANCE_URL: &str = "https://example.org";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_actor_id() {
|
|
||||||
let username = parse_actor_id(INSTANCE_URL, "https://example.org/users/test").unwrap();
|
|
||||||
assert_eq!(username, "test".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_actor_id_wrong_path() {
|
|
||||||
let error = parse_actor_id(INSTANCE_URL, "https://example.org/user/test").unwrap_err();
|
|
||||||
assert_eq!(error.to_string(), "invalid actor ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_actor_id_invalid_username() {
|
|
||||||
let error = parse_actor_id(INSTANCE_URL, "https://example.org/users/tes-t").unwrap_err();
|
|
||||||
assert_eq!(error.to_string(), "invalid actor ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_actor_id_invalid_instance_url() {
|
|
||||||
let error = parse_actor_id(INSTANCE_URL, "https://example.gov/users/test").unwrap_err();
|
|
||||||
assert_eq!(error.to_string(), "invalid actor ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_object_id() {
|
|
||||||
let expected_uuid = new_uuid();
|
|
||||||
let object_id = format!(
|
|
||||||
"https://example.org/objects/{}",
|
|
||||||
expected_uuid,
|
|
||||||
);
|
|
||||||
let internal_object_id = parse_object_id(INSTANCE_URL, &object_id).unwrap();
|
|
||||||
assert_eq!(internal_object_id, expected_uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_object_id_invalid_uuid() {
|
|
||||||
let object_id = "https://example.org/objects/1234";
|
|
||||||
let error = parse_object_id(INSTANCE_URL, object_id).unwrap_err();
|
|
||||||
assert_eq!(error.to_string(), "invalid object ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_array_with_string() {
|
fn test_parse_array_with_string() {
|
||||||
let value = json!("test");
|
let value = json!("test");
|
||||||
|
|
Loading…
Reference in a new issue