fedimovies/src/webfinger/views.rs

80 lines
2.5 KiB
Rust
Raw Normal View History

2021-04-09 00:22:17 +00:00
use actix_web::{get, web, HttpResponse};
use regex::Regex;
use tokio_postgres::GenericClient;
2021-04-09 00:22:17 +00:00
2022-10-01 16:56:57 +00:00
use crate::activitypub::constants::AP_MEDIA_TYPE;
use crate::activitypub::identifiers::{
local_actor_id,
local_instance_actor_id,
};
use crate::config::{Config, Instance};
2021-04-09 00:22:17 +00:00
use crate::database::{Pool, get_database_client};
2021-11-13 17:37:31 +00:00
use crate::errors::{HttpError, ValidationError};
2021-04-09 00:22:17 +00:00
use crate::models::users::queries::is_registered_user;
use super::types::{
JRD_CONTENT_TYPE,
WebfingerQueryParams,
Link,
JsonResourceDescriptor,
};
2021-11-07 08:52:57 +00:00
async fn get_user_info(
db_client: &impl GenericClient,
instance: Instance,
2021-04-09 00:22:17 +00:00
query_params: WebfingerQueryParams,
) -> Result<JsonResourceDescriptor, HttpError> {
// Parse 'acct' URI
// https://datatracker.ietf.org/doc/html/rfc7565#section-7
2022-10-03 21:44:04 +00:00
// See also: ACTOR_ADDRESS_RE in activitypub::actors::types
let uri_regexp = Regex::new(r"acct:(?P<user>[\w\.-]+)@(?P<instance>.+)").unwrap();
2021-04-09 00:22:17 +00:00
let uri_caps = uri_regexp.captures(&query_params.resource)
2021-11-13 17:37:31 +00:00
.ok_or(ValidationError("invalid query target"))?;
2021-04-09 00:22:17 +00:00
let username = uri_caps.name("user")
2021-11-13 17:37:31 +00:00
.ok_or(ValidationError("invalid query target"))?
2021-04-09 00:22:17 +00:00
.as_str();
let instance_host = uri_caps.name("instance")
2021-11-13 17:37:31 +00:00
.ok_or(ValidationError("invalid query target"))?
2021-04-09 00:22:17 +00:00
.as_str();
if instance_host != instance.host() {
// Wrong instance
2021-04-09 00:22:17 +00:00
return Err(HttpError::NotFoundError("user"));
}
2021-11-18 00:51:56 +00:00
let actor_url = if username == instance.host() {
local_instance_actor_id(&instance.url())
2021-11-18 00:51:56 +00:00
} else {
if !is_registered_user(db_client, username).await? {
return Err(HttpError::NotFoundError("user"));
};
local_actor_id(&instance.url(), username)
2021-11-18 00:51:56 +00:00
};
2021-04-09 00:22:17 +00:00
let link = Link {
rel: "self".to_string(),
2022-10-01 16:56:57 +00:00
link_type: Some(AP_MEDIA_TYPE.to_string()),
2021-04-09 00:22:17 +00:00
href: Some(actor_url),
};
let jrd = JsonResourceDescriptor {
subject: query_params.resource,
links: vec![link],
};
Ok(jrd)
}
#[get("/.well-known/webfinger")]
2021-11-07 08:52:57 +00:00
pub async fn get_descriptor(
2021-04-09 00:22:17 +00:00
config: web::Data<Config>,
db_pool: web::Data<Pool>,
2021-04-09 00:22:17 +00:00
query_params: web::Query<WebfingerQueryParams>,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let jrd = get_user_info(
db_client,
config.instance(),
query_params.into_inner(),
).await?;
2021-04-09 00:22:17 +00:00
let response = HttpResponse::Ok()
.content_type(JRD_CONTENT_TYPE)
.json(jrd);
Ok(response)
}