Use actor address regexp for parsing acct: URI

This commit is contained in:
silverpill 2022-10-03 22:42:53 +00:00
parent 8b6aef2b7a
commit 0c00dca7d3
2 changed files with 33 additions and 19 deletions

View file

@ -197,7 +197,7 @@ impl ActorAddress {
} }
// See also: USERNAME_RE in models::profiles::validators // See also: USERNAME_RE in models::profiles::validators
const ACTOR_ADDRESS_RE: &str = r"(?P<username>[\w\.-]+)@(?P<instance>[\w\.-]+)"; pub const ACTOR_ADDRESS_RE: &str = r"(?P<username>[\w\.-]+)@(?P<instance>[\w\.-]+)";
impl FromStr for ActorAddress { impl FromStr for ActorAddress {
type Err = ValidationError; type Err = ValidationError;

View file

@ -2,6 +2,7 @@ use actix_web::{get, web, HttpResponse};
use regex::Regex; use regex::Regex;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::activitypub::actors::types::{ActorAddress, ACTOR_ADDRESS_RE};
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,
@ -18,35 +19,35 @@ use super::types::{
JsonResourceDescriptor, JsonResourceDescriptor,
}; };
// https://datatracker.ietf.org/doc/html/rfc7565#section-7
fn parse_acct_uri(uri: &str) -> Result<ActorAddress, ValidationError> {
let uri_regexp = Regex::new(&format!("acct:{}", ACTOR_ADDRESS_RE)).unwrap();
let uri_caps = uri_regexp.captures(uri)
.ok_or(ValidationError("invalid query target"))?;
let actor_address = ActorAddress {
username: uri_caps["username"].to_string(),
instance: uri_caps["instance"].to_string(),
};
Ok(actor_address)
}
async fn get_user_info( async fn get_user_info(
db_client: &impl GenericClient, db_client: &impl GenericClient,
instance: Instance, instance: Instance,
query_params: WebfingerQueryParams, query_params: WebfingerQueryParams,
) -> Result<JsonResourceDescriptor, HttpError> { ) -> Result<JsonResourceDescriptor, HttpError> {
// Parse 'acct' URI let actor_address = parse_acct_uri(&query_params.resource)?;
// https://datatracker.ietf.org/doc/html/rfc7565#section-7 if !actor_address.is_local(&instance.host()) {
// See also: ACTOR_ADDRESS_RE in activitypub::actors::types
let uri_regexp = Regex::new(r"acct:(?P<user>[\w\.-]+)@(?P<instance>.+)").unwrap();
let uri_caps = uri_regexp.captures(&query_params.resource)
.ok_or(ValidationError("invalid query target"))?;
let username = uri_caps.name("user")
.ok_or(ValidationError("invalid query target"))?
.as_str();
let instance_host = uri_caps.name("instance")
.ok_or(ValidationError("invalid query target"))?
.as_str();
if instance_host != instance.host() {
// Wrong instance // Wrong instance
return Err(HttpError::NotFoundError("user")); return Err(HttpError::NotFoundError("user"));
} };
let actor_url = if username == instance.host() { let actor_url = if actor_address.username == instance.host() {
local_instance_actor_id(&instance.url()) local_instance_actor_id(&instance.url())
} else { } else {
if !is_registered_user(db_client, username).await? { if !is_registered_user(db_client, &actor_address.username).await? {
return Err(HttpError::NotFoundError("user")); return Err(HttpError::NotFoundError("user"));
}; };
local_actor_id(&instance.url(), username) local_actor_id(&instance.url(), &actor_address.username)
}; };
let link = Link { let link = Link {
rel: "self".to_string(), rel: "self".to_string(),
@ -77,3 +78,16 @@ pub async fn get_descriptor(
.json(jrd); .json(jrd);
Ok(response) Ok(response)
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_acct_uri() {
let uri = "acct:user_1@example.com";
let actor_address = parse_acct_uri(uri).unwrap();
assert_eq!(actor_address.username, "user_1");
assert_eq!(actor_address.instance, "example.com");
}
}