Move ActorAddress type to webfinger::types module
This commit is contained in:
parent
c953d66c95
commit
af332283ed
9 changed files with 74 additions and 68 deletions
|
@ -1,7 +1,3 @@
|
||||||
use std::fmt;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use regex::Regex;
|
|
||||||
use serde::{
|
use serde::{
|
||||||
Deserialize,
|
Deserialize,
|
||||||
Deserializer,
|
Deserializer,
|
||||||
|
@ -26,6 +22,7 @@ use crate::models::users::types::User;
|
||||||
use crate::utils::crypto_rsa::{deserialize_private_key, get_public_key_pem};
|
use crate::utils::crypto_rsa::{deserialize_private_key, get_public_key_pem};
|
||||||
use crate::utils::files::get_file_url;
|
use crate::utils::files::get_file_url;
|
||||||
use crate::utils::urls::get_hostname;
|
use crate::utils::urls::get_hostname;
|
||||||
|
use crate::webfinger::types::ActorAddress;
|
||||||
use super::attachments::{
|
use super::attachments::{
|
||||||
attach_extra_field,
|
attach_extra_field,
|
||||||
attach_identity_proof,
|
attach_identity_proof,
|
||||||
|
@ -217,46 +214,6 @@ impl Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See also: USERNAME_RE in models::profiles::validators
|
|
||||||
const ACTOR_ADDRESS_RE: &str = r"(?P<username>[\w\.-]+)@(?P<hostname>[\w\.-]+)";
|
|
||||||
|
|
||||||
pub struct ActorAddress {
|
|
||||||
pub username: String,
|
|
||||||
pub hostname: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActorAddress {
|
|
||||||
/// Returns acct string, as used in Mastodon
|
|
||||||
pub fn acct(&self, local_hostname: &str) -> String {
|
|
||||||
if self.hostname == local_hostname {
|
|
||||||
self.username.clone()
|
|
||||||
} else {
|
|
||||||
self.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ActorAddress {
|
|
||||||
type Err = ValidationError;
|
|
||||||
|
|
||||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
|
||||||
let actor_address_re = Regex::new(ACTOR_ADDRESS_RE).unwrap();
|
|
||||||
let caps = actor_address_re.captures(value)
|
|
||||||
.ok_or(ValidationError("invalid actor address"))?;
|
|
||||||
let actor_address = Self {
|
|
||||||
username: caps["username"].to_string(),
|
|
||||||
hostname: caps["hostname"].to_string(),
|
|
||||||
};
|
|
||||||
Ok(actor_address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for ActorAddress {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(formatter, "{}@{}", self.username, self.hostname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type ActorKeyError = rsa::pkcs8::Error;
|
pub type ActorKeyError = rsa::pkcs8::Error;
|
||||||
|
|
||||||
pub fn get_local_actor(
|
pub fn get_local_actor(
|
||||||
|
@ -394,15 +351,6 @@ mod tests {
|
||||||
const INSTANCE_HOSTNAME: &str = "example.com";
|
const INSTANCE_HOSTNAME: &str = "example.com";
|
||||||
const INSTANCE_URL: &str = "https://example.com";
|
const INSTANCE_URL: &str = "https://example.com";
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_actor_address_parse_address() {
|
|
||||||
let value = "user_1@example.com";
|
|
||||||
let actor_address: ActorAddress = value.parse().unwrap();
|
|
||||||
assert_eq!(actor_address.username, "user_1");
|
|
||||||
assert_eq!(actor_address.hostname, "example.com");
|
|
||||||
assert_eq!(actor_address.to_string(), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_actor_address() {
|
fn test_get_actor_address() {
|
||||||
let actor = Actor {
|
let actor = Actor {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use reqwest::{Client, Method, Proxy, RequestBuilder};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::activitypub::activity::Object;
|
use crate::activitypub::activity::Object;
|
||||||
use crate::activitypub::actors::types::{Actor, ActorAddress};
|
use crate::activitypub::actors::types::Actor;
|
||||||
use crate::activitypub::constants::AP_MEDIA_TYPE;
|
use crate::activitypub::constants::AP_MEDIA_TYPE;
|
||||||
use crate::config::Instance;
|
use crate::config::Instance;
|
||||||
use crate::http_signatures::create::{
|
use crate::http_signatures::create::{
|
||||||
|
@ -14,7 +14,7 @@ use crate::http_signatures::create::{
|
||||||
};
|
};
|
||||||
use crate::utils::files::{save_file, sniff_media_type};
|
use crate::utils::files::{save_file, sniff_media_type};
|
||||||
use crate::utils::urls::guess_protocol;
|
use crate::utils::urls::guess_protocol;
|
||||||
use crate::webfinger::types::JsonResourceDescriptor;
|
use crate::webfinger::types::{ActorAddress, JsonResourceDescriptor};
|
||||||
|
|
||||||
const FETCHER_CONNECTION_TIMEOUT: u64 = 30;
|
const FETCHER_CONNECTION_TIMEOUT: u64 = 30;
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,7 @@ use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
activity::Object,
|
activity::Object,
|
||||||
actors::{
|
actors::helpers::{create_remote_profile, update_remote_profile},
|
||||||
helpers::{create_remote_profile, update_remote_profile},
|
|
||||||
types::ActorAddress,
|
|
||||||
},
|
|
||||||
handlers::create::handle_note,
|
handlers::create::handle_note,
|
||||||
identifiers::parse_local_object_id,
|
identifiers::parse_local_object_id,
|
||||||
receiver::HandlerError,
|
receiver::HandlerError,
|
||||||
|
@ -24,6 +21,7 @@ use crate::models::profiles::queries::{
|
||||||
get_profile_by_remote_actor_id,
|
get_profile_by_remote_actor_id,
|
||||||
};
|
};
|
||||||
use crate::models::profiles::types::DbActorProfile;
|
use crate::models::profiles::types::DbActorProfile;
|
||||||
|
use crate::webfinger::types::ActorAddress;
|
||||||
use super::fetchers::{
|
use super::fetchers::{
|
||||||
fetch_actor,
|
fetch_actor,
|
||||||
fetch_object,
|
fetch_object,
|
||||||
|
|
|
@ -5,7 +5,6 @@ use tokio_postgres::GenericClient;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
actors::types::ActorAddress,
|
|
||||||
fetcher::helpers::{
|
fetcher::helpers::{
|
||||||
get_or_import_profile_by_actor_id,
|
get_or_import_profile_by_actor_id,
|
||||||
import_post,
|
import_post,
|
||||||
|
@ -36,6 +35,7 @@ use crate::models::users::{
|
||||||
types::User,
|
types::User,
|
||||||
};
|
};
|
||||||
use crate::utils::currencies::{validate_wallet_address, Currency};
|
use crate::utils::currencies::{validate_wallet_address, Currency};
|
||||||
|
use crate::webfinger::types::ActorAddress;
|
||||||
use super::types::SearchResults;
|
use super::types::SearchResults;
|
||||||
|
|
||||||
enum SearchQuery {
|
enum SearchQuery {
|
||||||
|
@ -50,7 +50,7 @@ enum SearchQuery {
|
||||||
fn parse_profile_query(query: &str) ->
|
fn parse_profile_query(query: &str) ->
|
||||||
Result<(String, Option<String>), ValidationError>
|
Result<(String, Option<String>), ValidationError>
|
||||||
{
|
{
|
||||||
// See also: ACTOR_ADDRESS_RE in activitypub::actors::types
|
// See also: ACTOR_ADDRESS_RE in webfinger::types
|
||||||
let acct_query_re =
|
let acct_query_re =
|
||||||
Regex::new(r"^(@|!)?(?P<username>[\w\.-]+)(@(?P<hostname>[\w\.-]+))?$").unwrap();
|
Regex::new(r"^(@|!)?(?P<username>[\w\.-]+)(@(?P<hostname>[\w\.-]+))?$").unwrap();
|
||||||
let acct_query_caps = acct_query_re.captures(query)
|
let acct_query_caps = acct_query_re.captures(query)
|
||||||
|
|
|
@ -4,7 +4,6 @@ use actix_web::{get, post, web, HttpResponse, Scope};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
actors::types::ActorAddress,
|
|
||||||
builders::{
|
builders::{
|
||||||
move_person::prepare_move_person,
|
move_person::prepare_move_person,
|
||||||
undo_follow::prepare_undo_follow,
|
undo_follow::prepare_undo_follow,
|
||||||
|
@ -24,6 +23,7 @@ use crate::models::{
|
||||||
users::queries::set_user_password,
|
users::queries::set_user_password,
|
||||||
};
|
};
|
||||||
use crate::utils::passwords::hash_password;
|
use crate::utils::passwords::hash_password;
|
||||||
|
use crate::webfinger::types::ActorAddress;
|
||||||
use super::helpers::{export_followers, export_follows};
|
use super::helpers::{export_followers, export_follows};
|
||||||
use super::types::{MoveFollowersRequest, PasswordChangeRequest};
|
use super::types::{MoveFollowersRequest, PasswordChangeRequest};
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@ use std::collections::HashMap;
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
use tokio_postgres::GenericClient;
|
use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::actors::types::ActorAddress;
|
|
||||||
use crate::database::DatabaseError;
|
use crate::database::DatabaseError;
|
||||||
use crate::errors::ValidationError;
|
use crate::errors::ValidationError;
|
||||||
use crate::models::profiles::queries::get_profiles_by_accts;
|
use crate::models::profiles::queries::get_profiles_by_accts;
|
||||||
use crate::models::profiles::types::DbActorProfile;
|
use crate::models::profiles::types::DbActorProfile;
|
||||||
|
use crate::webfinger::types::ActorAddress;
|
||||||
use super::links::is_inside_code_block;
|
use super::links::is_inside_code_block;
|
||||||
|
|
||||||
// See also: ACTOR_ADDRESS_RE in activitypub::actors::types
|
// See also: ACTOR_ADDRESS_RE in webfinger::types
|
||||||
const MENTION_SEARCH_RE: &str = r"(?m)(?P<before>^|\s|>|[\(])@(?P<mention>[^\s<]+)";
|
const MENTION_SEARCH_RE: &str = r"(?m)(?P<before>^|\s|>|[\(])@(?P<mention>[^\s<]+)";
|
||||||
const MENTION_SEARCH_SECONDARY_RE: &str = r"^(?P<username>[\w\.-]+)(@(?P<hostname>[\w\.-]+\w))?(?P<after>[\.,:?\)]?)$";
|
const MENTION_SEARCH_SECONDARY_RE: &str = r"^(?P<username>[\w\.-]+)(@(?P<hostname>[\w\.-]+\w))?(?P<after>[\.,:?\)]?)$";
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use serde::{
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::activitypub::actors::types::{Actor, ActorAddress};
|
use crate::activitypub::actors::types::Actor;
|
||||||
use crate::activitypub::identifiers::local_actor_id;
|
use crate::activitypub::identifiers::local_actor_id;
|
||||||
use crate::database::{
|
use crate::database::{
|
||||||
json_macro::{json_from_sql, json_to_sql},
|
json_macro::{json_from_sql, json_to_sql},
|
||||||
|
@ -23,6 +23,7 @@ use crate::identity::{
|
||||||
signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN},
|
signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN},
|
||||||
};
|
};
|
||||||
use crate::utils::caip2::ChainId;
|
use crate::utils::caip2::ChainId;
|
||||||
|
use crate::webfinger::types::ActorAddress;
|
||||||
use super::validators::{
|
use super::validators::{
|
||||||
validate_username,
|
validate_username,
|
||||||
validate_display_name,
|
validate_display_name,
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
/// https://webfinger.net/
|
/// https://webfinger.net/
|
||||||
|
use std::fmt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use crate::errors::ValidationError;
|
||||||
|
|
||||||
|
// See also: USERNAME_RE in models::profiles::validators
|
||||||
|
const ACTOR_ADDRESS_RE: &str = r"(?P<username>[\w\.-]+)@(?P<hostname>[\w\.-]+)";
|
||||||
|
|
||||||
pub const JRD_CONTENT_TYPE: &str = "application/jrd+json";
|
pub const JRD_CONTENT_TYPE: &str = "application/jrd+json";
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -9,6 +17,43 @@ pub struct WebfingerQueryParams {
|
||||||
pub resource: String,
|
pub resource: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ActorAddress {
|
||||||
|
pub username: String,
|
||||||
|
pub hostname: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActorAddress {
|
||||||
|
/// Returns acct string, as used in Mastodon
|
||||||
|
pub fn acct(&self, local_hostname: &str) -> String {
|
||||||
|
if self.hostname == local_hostname {
|
||||||
|
self.username.clone()
|
||||||
|
} else {
|
||||||
|
self.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for ActorAddress {
|
||||||
|
type Err = ValidationError;
|
||||||
|
|
||||||
|
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||||
|
let actor_address_re = Regex::new(ACTOR_ADDRESS_RE).unwrap();
|
||||||
|
let caps = actor_address_re.captures(value)
|
||||||
|
.ok_or(ValidationError("invalid actor address"))?;
|
||||||
|
let actor_address = Self {
|
||||||
|
username: caps["username"].to_string(),
|
||||||
|
hostname: caps["hostname"].to_string(),
|
||||||
|
};
|
||||||
|
Ok(actor_address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ActorAddress {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(formatter, "{}@{}", self.username, self.hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
pub rel: String,
|
pub rel: String,
|
||||||
|
@ -25,3 +70,17 @@ pub struct JsonResourceDescriptor {
|
||||||
pub subject: String,
|
pub subject: String,
|
||||||
pub links: Vec<Link>,
|
pub links: Vec<Link>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_actor_address_parse_address() {
|
||||||
|
let value = "user_1@example.com";
|
||||||
|
let actor_address: ActorAddress = value.parse().unwrap();
|
||||||
|
assert_eq!(actor_address.username, "user_1");
|
||||||
|
assert_eq!(actor_address.hostname, "example.com");
|
||||||
|
assert_eq!(actor_address.to_string(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use actix_web::{get, web, HttpResponse};
|
use actix_web::{get, web, HttpResponse};
|
||||||
use tokio_postgres::GenericClient;
|
use tokio_postgres::GenericClient;
|
||||||
|
|
||||||
use crate::activitypub::actors::types::ActorAddress;
|
|
||||||
use crate::activitypub::constants::AP_MEDIA_TYPE;
|
use crate::activitypub::constants::AP_MEDIA_TYPE;
|
||||||
use crate::activitypub::identifiers::{
|
use crate::activitypub::identifiers::{
|
||||||
local_actor_id,
|
local_actor_id,
|
||||||
|
@ -12,10 +11,11 @@ use crate::database::{get_database_client, DbPool};
|
||||||
use crate::errors::{HttpError, ValidationError};
|
use crate::errors::{HttpError, ValidationError};
|
||||||
use crate::models::users::queries::is_registered_user;
|
use crate::models::users::queries::is_registered_user;
|
||||||
use super::types::{
|
use super::types::{
|
||||||
JRD_CONTENT_TYPE,
|
ActorAddress,
|
||||||
WebfingerQueryParams,
|
|
||||||
Link,
|
Link,
|
||||||
JsonResourceDescriptor,
|
JsonResourceDescriptor,
|
||||||
|
WebfingerQueryParams,
|
||||||
|
JRD_CONTENT_TYPE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc7565#section-7
|
// https://datatracker.ietf.org/doc/html/rfc7565#section-7
|
||||||
|
|
Loading…
Reference in a new issue