Compare commits
2 commits
e0c60945cb
...
8635755856
Author | SHA1 | Date | |
---|---|---|---|
8635755856 | |||
49a779e943 |
3 changed files with 620 additions and 0 deletions
428
src/federation/adapter/input/web/hostmeta.rs
Normal file
428
src/federation/adapter/input/web/hostmeta.rs
Normal file
|
@ -0,0 +1,428 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::{get, web, HttpRequest, Responder};
|
||||
#[cfg(not(test))]
|
||||
use log::{error, info};
|
||||
#[cfg(test)]
|
||||
use println as info;
|
||||
#[cfg(test)]
|
||||
use println as error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use super::types;
|
||||
use super::{person, repository};
|
||||
use crate::federation::adapter::input::web::errors::WebError;
|
||||
use crate::federation::adapter::input::web::WebJsonRepsonse;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(handler);
|
||||
}
|
||||
|
||||
#[get("/.well-known/host-meta")]
|
||||
#[tracing::instrument(name = "host meta handler", skip(settings))]
|
||||
async fn handler(settings: crate::WebSettings) -> WebJsonRepsonse<impl Responder> {
|
||||
let resp = format!("<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||
<XRD xmlns=\"http://docs.oasis-open.org/ns/xri/xrd-1.0\">
|
||||
<Link rel=\"lrdd\" type=\"application/xrd+xml\" template=\"https://{}/.well-known/webfinger?resource={{uri}}\"></Link></XRD>", settings.server.domain,
|
||||
);
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/xrd+xml")
|
||||
.body(resp))
|
||||
}
|
||||
//
|
||||
//#[cfg(test)]
|
||||
//pub mod tests {
|
||||
// use std::sync::Arc;
|
||||
//
|
||||
// use super::*;
|
||||
// use activitypub_federation::fetch::webfinger::{Webfinger, WebfingerLink};
|
||||
// use actix_identity::IdentityMiddleware;
|
||||
// use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
// use actix_web::http::{header, StatusCode};
|
||||
// use actix_web::{cookie::Key, http::header::ContentType, test, App};
|
||||
//
|
||||
// use crate::federation::adapter::input::web::routes::RoutesRepository;
|
||||
// use crate::federation::application::port::out::db::get_repository::mock_get_repository;
|
||||
// use crate::federation::application::port::out::db::save_repository::mock_save_repository;
|
||||
// use crate::federation::application::port::out::forge::get_repository::mock_forge_get_repository;
|
||||
// use crate::federation::domain::{Person, Repository};
|
||||
// use crate::federation::{
|
||||
// adapter::out::forge::forge_factory::{
|
||||
// FederationForgeAdapterFactoryInterface, MockFederationForgeAdapterFactoryInterface,
|
||||
// },
|
||||
// application::port::out::{
|
||||
// db::{get_person::*, save_person::*},
|
||||
// forge::{get_person::*, parse_repository_from_url::*, parse_username_from_url::*},
|
||||
// },
|
||||
// };
|
||||
// use crate::settings::Settings;
|
||||
// use crate::tests::bdd::*;
|
||||
// use crate::utils::absolute_url::absolute_url;
|
||||
// use crate::utils::forges::forge_repository::MockForgeRepositoryInterface;
|
||||
// use crate::utils::forges::SupportedForges;
|
||||
//
|
||||
// pub fn configure_forge_url(s: &mut Settings) {
|
||||
// let p = Person::default();
|
||||
// let mut forge_url = p.html_url().clone();
|
||||
// forge_url.set_path("");
|
||||
//
|
||||
// s.forges.forgejo.url = forge_url.clone();
|
||||
// s.forges.github.url = forge_url.clone();
|
||||
// }
|
||||
//
|
||||
// fn configure_forges() -> types::WebFederationForgeRepositoryInterface {
|
||||
// let mut mock_forge_factory = MockFederationForgeAdapterFactoryInterface::default();
|
||||
// mock_forge_factory
|
||||
// .expect_get_person_adapter()
|
||||
// .returning(|| mock_forge_get_person(IGNORE_CALL_COUNT));
|
||||
//
|
||||
// mock_forge_factory
|
||||
// .expect_get_parse_username_from_url()
|
||||
// .returning(|| mock_forge_parse_username_from_url(IGNORE_CALL_COUNT));
|
||||
//
|
||||
// mock_forge_factory
|
||||
// .expect_get_repository()
|
||||
// .returning(|| mock_forge_get_repository(IGNORE_CALL_COUNT));
|
||||
//
|
||||
// mock_forge_factory
|
||||
// .expect_get_parse_repository_from_url()
|
||||
// .returning(|| mock_forge_parse_repository_from_url(IGNORE_CALL_COUNT));
|
||||
//
|
||||
// let mock_forge_factory: Arc<dyn FederationForgeAdapterFactoryInterface> =
|
||||
// Arc::new(mock_forge_factory);
|
||||
//
|
||||
// let mut mock_forges = MockForgeRepositoryInterface::default();
|
||||
// mock_forges
|
||||
// .expect_get_forge_factory()
|
||||
// .returning(move |_| Some(mock_forge_factory.clone()));
|
||||
//
|
||||
// types::WebFederationForgeRepositoryInterface::new(Arc::new(mock_forges))
|
||||
// }
|
||||
//
|
||||
// macro_rules! init_webfinger_app {
|
||||
// ($s:ident) => {
|
||||
// test::init_service(
|
||||
// App::new()
|
||||
// .wrap(IdentityMiddleware::default())
|
||||
// .wrap(SessionMiddleware::new(
|
||||
// CookieSessionStore::default(),
|
||||
// Key::from($s.server.cookie_secret.as_bytes()),
|
||||
// ))
|
||||
// .wrap(tracing_actix_web::TracingLogger::default())
|
||||
// .app_data(types::WebFederationOutDBGetPersonObj::new(
|
||||
// mock_get_person_from_preferred_username(IGNORE_CALL_COUNT),
|
||||
// ))
|
||||
// .app_data(types::WebFederationOutDBSavePersonObj::new(
|
||||
// mock_save_person(IGNORE_CALL_COUNT),
|
||||
// ))
|
||||
// .app_data(types::WebFederationOutDBGetRepositoryObj::new(
|
||||
// mock_get_repository(IGNORE_CALL_COUNT),
|
||||
// ))
|
||||
// .app_data(types::WebFederationOutDBSaveRepositoryObj::new(
|
||||
// mock_save_repository(IGNORE_CALL_COUNT),
|
||||
// ))
|
||||
// .app_data(configure_forges())
|
||||
// .app_data(web::Data::new(Arc::new(RoutesRepository::default())))
|
||||
// .app_data(web::Data::new($s.clone()))
|
||||
// .service(handler),
|
||||
// )
|
||||
// .await
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// #[actix_web::test]
|
||||
// async fn test_webfinger_hander_person_web_query() {
|
||||
// let mut settings = Settings::new().unwrap();
|
||||
// configure_forge_url(&mut settings);
|
||||
//
|
||||
// let s = settings.clone();
|
||||
// let app = init_webfinger_app!(s);
|
||||
// let routes = RoutesRepository::default();
|
||||
//
|
||||
// let path = {
|
||||
// let p = Person::default();
|
||||
// routes.webfinger(p.html_url())
|
||||
// };
|
||||
//
|
||||
// let req = test::TestRequest::get().uri(&path).to_request();
|
||||
// let resp = test::call_service(&app, req).await;
|
||||
// let status = resp.status();
|
||||
// assert_eq!(status, StatusCode::OK);
|
||||
//
|
||||
// assert_eq!(
|
||||
// resp.headers().get("Content-Type").unwrap(),
|
||||
// "application/jrd+json"
|
||||
// );
|
||||
//
|
||||
// let data: Webfinger = test::read_body_json(resp).await;
|
||||
// let person = Person::default();
|
||||
//
|
||||
// assert_eq!(data.subject, person.html_url().to_string());
|
||||
// println!("{:#?}", data.links);
|
||||
// assert_eq!(data.links.len(), 3);
|
||||
//
|
||||
// let profile_photo_link = data
|
||||
// .links
|
||||
// .iter()
|
||||
// .find(|l| l.rel == Some("http://webfinger.net/rel/avatar".into()))
|
||||
// .unwrap();
|
||||
// assert_eq!(
|
||||
// profile_photo_link.href,
|
||||
// person.profile_photo().as_ref().map(|u| u.clone())
|
||||
// );
|
||||
//
|
||||
// let profile_page_link = data
|
||||
// .links
|
||||
// .iter()
|
||||
// .find(|l| l.rel == Some("http://webfinger.net/rel/profile-page".into()))
|
||||
// .unwrap();
|
||||
// let expected_profile_page_link =
|
||||
// routes
|
||||
// .person
|
||||
// .actor(person.username(), SupportedForges::Forgejo, &settings);
|
||||
//
|
||||
// assert_eq!(
|
||||
// profile_page_link.href.as_ref().unwrap().path(),
|
||||
// // any SupportedForges should work, since all hostnames are == example.com in tests
|
||||
// expected_profile_page_link
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[actix_web::test]
|
||||
// async fn test_webfinger_hander_person_web_query_forgeflux_hostname() {
|
||||
// let mut settings = Settings::new().unwrap();
|
||||
// configure_forge_url(&mut settings);
|
||||
//
|
||||
// let s = settings.clone();
|
||||
// let app = init_webfinger_app!(s);
|
||||
// let routes = RoutesRepository::default();
|
||||
// let p = Person::default();
|
||||
//
|
||||
// // test webfinger lookup with hostname = settings.server.domain
|
||||
// let path = {
|
||||
// let p = Person::default();
|
||||
// let u = absolute_url(
|
||||
// &settings,
|
||||
// &routes
|
||||
// .person
|
||||
// .actor(&p.username(), SupportedForges::Forgejo, &settings),
|
||||
// )
|
||||
// .unwrap();
|
||||
//
|
||||
// routes.webfinger(&u)
|
||||
// };
|
||||
// let req = test::TestRequest::get().uri(&path).to_request();
|
||||
// let resp = test::call_service(&app, req).await;
|
||||
// let status = resp.status();
|
||||
// assert_eq!(status, StatusCode::OK);
|
||||
// let x: Webfinger = test::read_body_json(resp).await;
|
||||
// assert_eq!(
|
||||
// x.subject,
|
||||
// crate::utils::absolute_url::absolute_url(
|
||||
// &settings,
|
||||
// &routes
|
||||
// .person
|
||||
// .actor(p.username(), SupportedForges::Forgejo, &settings)
|
||||
// )
|
||||
// .unwrap()
|
||||
// .to_string()
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[actix_web::test]
|
||||
// async fn test_webfinger_hander_person_acct_query() {
|
||||
// let mut settings = Settings::new().unwrap();
|
||||
// configure_forge_url(&mut settings);
|
||||
//
|
||||
// let s = settings.clone();
|
||||
// let app = init_webfinger_app!(s);
|
||||
// let routes = RoutesRepository::default();
|
||||
//
|
||||
// let webfinger_resource = {
|
||||
// Url::parse(&format!(
|
||||
// "acct:{}@{}",
|
||||
// Person::default().preferred_username(),
|
||||
// &settings.server.domain,
|
||||
// ))
|
||||
// .unwrap()
|
||||
// };
|
||||
//
|
||||
// println!("{}", webfinger_resource.to_string());
|
||||
// let path = routes.webfinger(&webfinger_resource);
|
||||
// let req = test::TestRequest::get().uri(&path).to_request();
|
||||
// let resp = test::call_service(&app, req).await;
|
||||
// let status = resp.status();
|
||||
// assert_eq!(status, StatusCode::OK);
|
||||
// let x: Webfinger = test::read_body_json(resp).await;
|
||||
// assert_eq!(x.subject, webfinger_resource.to_string());
|
||||
//
|
||||
// let profile_page_link = x
|
||||
// .links
|
||||
// .iter()
|
||||
// .find(|l| l.rel == Some("http://webfinger.net/rel/profile-page".into()))
|
||||
// .unwrap();
|
||||
// let expected_profile_page_link = routes.person.actor(
|
||||
// Person::default().username(),
|
||||
// SupportedForges::Forgejo,
|
||||
// &settings,
|
||||
// );
|
||||
//
|
||||
// assert_eq!(
|
||||
// profile_page_link.href.as_ref().unwrap().path(),
|
||||
// // any SupportedForges should work, since all hostnames are == example.com in tests
|
||||
// expected_profile_page_link
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[actix_web::test]
|
||||
// async fn test_webfinger_hander_repository_acct_query() {
|
||||
// let mut settings = Settings::new().unwrap();
|
||||
// configure_forge_url(&mut settings);
|
||||
//
|
||||
// let s = settings.clone();
|
||||
// let app = init_webfinger_app!(s);
|
||||
// let routes = RoutesRepository::default();
|
||||
// let repo = Repository::default();
|
||||
//
|
||||
// let webfinger_resource = {
|
||||
// Url::parse(&format!(
|
||||
// "acct:{}@{}",
|
||||
// repo.preferred_username(),
|
||||
// &settings.server.domain,
|
||||
// ))
|
||||
// .unwrap()
|
||||
// };
|
||||
//
|
||||
// println!("{}", webfinger_resource.to_string());
|
||||
// let path = routes.webfinger(&webfinger_resource);
|
||||
// let req = test::TestRequest::get().uri(&path).to_request();
|
||||
// let resp = test::call_service(&app, req).await;
|
||||
// let status = resp.status();
|
||||
// assert_eq!(status, StatusCode::OK);
|
||||
// let x: Webfinger = test::read_body_json(resp).await;
|
||||
// assert_eq!(x.subject, webfinger_resource.to_string());
|
||||
//
|
||||
// let profile_page_link = x
|
||||
// .links
|
||||
// .iter()
|
||||
// .find(|l| l.rel == Some("http://webfinger.net/rel/profile-page".into()))
|
||||
// .unwrap();
|
||||
// let expected_profile_page_link = routes.repository.actor(
|
||||
// repo.owner(),
|
||||
// repo.name(),
|
||||
// SupportedForges::Forgejo,
|
||||
// &settings,
|
||||
// );
|
||||
//
|
||||
// assert_eq!(
|
||||
// profile_page_link.href.as_ref().unwrap().path(),
|
||||
// // any SupportedForges should work, since all hostnames are == example.com in tests
|
||||
// expected_profile_page_link
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[actix_web::test]
|
||||
// async fn test_webfinger_hander_repository_web_query() {
|
||||
// let mut settings = Settings::new().unwrap();
|
||||
// configure_forge_url(&mut settings);
|
||||
//
|
||||
// let s = settings.clone();
|
||||
// let app = init_webfinger_app!(s);
|
||||
// let routes = RoutesRepository::default();
|
||||
//
|
||||
// let repository = Repository::default();
|
||||
//
|
||||
// let path = { routes.webfinger(repository.html_url()) };
|
||||
//
|
||||
// let req = test::TestRequest::get().uri(&path).to_request();
|
||||
// let resp = test::call_service(&app, req).await;
|
||||
// let status = resp.status();
|
||||
// assert_eq!(status, StatusCode::OK);
|
||||
//
|
||||
// assert_eq!(
|
||||
// resp.headers().get("Content-Type").unwrap(),
|
||||
// "application/jrd+json"
|
||||
// );
|
||||
//
|
||||
// let data: Webfinger = test::read_body_json(resp).await;
|
||||
//
|
||||
// assert_eq!(data.subject, repository.html_url().to_string());
|
||||
// println!("{:#?}", data.links);
|
||||
// assert_eq!(data.links.len(), 2);
|
||||
//
|
||||
// assert!(data
|
||||
// .links
|
||||
// .iter()
|
||||
// .find(|l| l.rel == Some("http://webfinger.net/rel/avatar".into()))
|
||||
// .is_none());
|
||||
//
|
||||
// let profile_page_link = data
|
||||
// .links
|
||||
// .iter()
|
||||
// .find(|l| l.rel == Some("http://webfinger.net/rel/profile-page".into()))
|
||||
// .unwrap();
|
||||
// let expected_profile_page_link = routes.repository.actor(
|
||||
// repository.owner(),
|
||||
// repository.name(),
|
||||
// SupportedForges::Forgejo,
|
||||
// &settings,
|
||||
// );
|
||||
//
|
||||
// assert_eq!(
|
||||
// profile_page_link.href.as_ref().unwrap().path(),
|
||||
// // any SupportedForges should work, since all hostnames are == example.com in tests
|
||||
// expected_profile_page_link
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[actix_web::test]
|
||||
// async fn test_webfinger_hander_repository_web_query_forgeflux_hostname() {
|
||||
// let mut settings = Settings::new().unwrap();
|
||||
// configure_forge_url(&mut settings);
|
||||
//
|
||||
// let s = settings.clone();
|
||||
// let app = init_webfinger_app!(s);
|
||||
// let routes = RoutesRepository::default();
|
||||
// let repository = Repository::default();
|
||||
//
|
||||
// // test webfinger lookup with hostname = settings.server.domain
|
||||
// let path = {
|
||||
// let u = absolute_url(
|
||||
// &settings,
|
||||
// &routes.repository.actor(
|
||||
// repository.owner(),
|
||||
// repository.name(),
|
||||
// SupportedForges::Forgejo,
|
||||
// &settings,
|
||||
// ),
|
||||
// )
|
||||
// .unwrap();
|
||||
//
|
||||
// routes.webfinger(&u)
|
||||
// };
|
||||
// let req = test::TestRequest::get().uri(&path).to_request();
|
||||
// let resp = test::call_service(&app, req).await;
|
||||
// let status = resp.status();
|
||||
// assert_eq!(status, StatusCode::OK);
|
||||
// let x: Webfinger = test::read_body_json(resp).await;
|
||||
// assert_eq!(
|
||||
// x.subject,
|
||||
// crate::utils::absolute_url::absolute_url(
|
||||
// &settings,
|
||||
// &routes.repository.actor(
|
||||
// repository.owner(),
|
||||
// repository.name(),
|
||||
// SupportedForges::Forgejo,
|
||||
// &settings
|
||||
// )
|
||||
// )
|
||||
// .unwrap()
|
||||
// .to_string()
|
||||
// );
|
||||
// }
|
||||
//}
|
|
@ -7,6 +7,7 @@ use std::sync::Arc;
|
|||
use actix_web::web;
|
||||
|
||||
mod errors;
|
||||
mod nodeinfo;
|
||||
mod person;
|
||||
mod repository;
|
||||
mod routes;
|
||||
|
@ -22,6 +23,7 @@ pub fn load_ctx() -> impl FnOnce(&mut web::ServiceConfig) {
|
|||
let f = move |cfg: &mut web::ServiceConfig| {
|
||||
cfg.app_data(routes);
|
||||
cfg.configure(webfinger::services);
|
||||
cfg.configure(nodeinfo::services);
|
||||
cfg.configure(repository::services);
|
||||
cfg.configure(person::services);
|
||||
};
|
||||
|
|
190
src/federation/adapter/input/web/nodeinfo.rs
Normal file
190
src/federation/adapter/input/web/nodeinfo.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::{get, web, HttpRequest, Responder};
|
||||
#[cfg(not(test))]
|
||||
use log::{error, info};
|
||||
#[cfg(test)]
|
||||
use println as info;
|
||||
#[cfg(test)]
|
||||
use println as error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
//use super::types;
|
||||
use crate::federation::adapter::input::web::WebJsonRepsonse;
|
||||
use crate::utils::absolute_url;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct NodeinfoMeta {
|
||||
links: Vec<Link>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Link {
|
||||
rel: Url,
|
||||
href: Url,
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(list_nodeinfos);
|
||||
cfg.service(nodeinfo);
|
||||
}
|
||||
|
||||
#[get("/.well-known/nodeinfo")]
|
||||
#[tracing::instrument(name = "nodeinfo well-known route", skip(settings))]
|
||||
async fn list_nodeinfos(settings: crate::WebSettings) -> WebJsonRepsonse<impl Responder> {
|
||||
println!("entry");
|
||||
let resp = NodeinfoMeta {
|
||||
links: vec![Link {
|
||||
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0").unwrap(),
|
||||
href: absolute_url::absolute_url(&settings, "/nodeinfo/2.0").unwrap(),
|
||||
}],
|
||||
};
|
||||
println!("all good");
|
||||
|
||||
Ok(HttpResponse::Ok().json(resp))
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Nodeinfo {
|
||||
version: String,
|
||||
software: Software,
|
||||
protocols: Vec<String>,
|
||||
services: Services,
|
||||
open_registrations: bool,
|
||||
metadata: HashMap<String, serde_json::Value>,
|
||||
usage: Usage,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Software {
|
||||
name: String,
|
||||
version: String,
|
||||
}
|
||||
|
||||
impl Default for Software {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: "forgeflux".to_string(),
|
||||
version: "0.0.0".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Services {
|
||||
inbound: Vec<String>,
|
||||
outbound: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Usage {
|
||||
users: Users,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Users {
|
||||
total: usize,
|
||||
}
|
||||
|
||||
#[get("/nodeinfo/2.0")]
|
||||
#[tracing::instrument(
|
||||
name = "nodeinfo handler",
|
||||
// skip(settings)
|
||||
)]
|
||||
async fn nodeinfo(// settings: crate::WebSettings,
|
||||
) -> WebJsonRepsonse<impl Responder> {
|
||||
let resp = Nodeinfo {
|
||||
version: "2.0".to_string(),
|
||||
software: Software::default(),
|
||||
protocols: vec!["activitypub".to_string(), "forgefed".to_string()],
|
||||
services: Services::default(),
|
||||
usage: Usage {
|
||||
users: Users { total: 0 },
|
||||
},
|
||||
open_registrations: false,
|
||||
metadata: HashMap::default(),
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().json(resp))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
|
||||
use super::*;
|
||||
use actix_identity::IdentityMiddleware;
|
||||
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{cookie::Key, test, App};
|
||||
|
||||
use crate::settings::Settings;
|
||||
|
||||
macro_rules! init_nodeinfo_app {
|
||||
($s:ident) => {
|
||||
test::init_service(
|
||||
App::new()
|
||||
.wrap(IdentityMiddleware::default())
|
||||
.wrap(SessionMiddleware::new(
|
||||
CookieSessionStore::default(),
|
||||
Key::from($s.server.cookie_secret.as_bytes()),
|
||||
))
|
||||
.wrap(tracing_actix_web::TracingLogger::default())
|
||||
.app_data(web::Data::new($s.clone()))
|
||||
.configure(services),
|
||||
)
|
||||
.await
|
||||
};
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn test_nodeinfo_list() {
|
||||
let settings = Settings::new().unwrap();
|
||||
|
||||
let s = settings.clone();
|
||||
let app = init_nodeinfo_app!(s);
|
||||
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/.well-known/nodeinfo")
|
||||
.to_request();
|
||||
let resp = test::call_service(&app, req).await;
|
||||
let status = resp.status();
|
||||
assert_eq!(status, StatusCode::OK);
|
||||
|
||||
let data: NodeinfoMeta = test::read_body_json(resp).await;
|
||||
assert_eq!(data.links.len(), 1);
|
||||
let link = data.links.get(0).unwrap();
|
||||
assert_eq!(
|
||||
link.rel,
|
||||
Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0").unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
link.href,
|
||||
absolute_url::absolute_url(&settings, "/nodeinfo/2.0").unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn test_nodeinfo() {
|
||||
let settings = Settings::new().unwrap();
|
||||
|
||||
let s = settings.clone();
|
||||
let app = init_nodeinfo_app!(s);
|
||||
|
||||
let req = test::TestRequest::get().uri("/nodeinfo/2.0").to_request();
|
||||
let resp = test::call_service(&app, req).await;
|
||||
let status = resp.status();
|
||||
assert_eq!(status, StatusCode::OK);
|
||||
|
||||
let data: Nodeinfo = test::read_body_json(resp).await;
|
||||
assert_eq!(data.version, "2.0");
|
||||
assert_eq!(data.software.name, "forgeflux");
|
||||
assert!(data.protocols.iter().any(|p| p == "activitypub"));
|
||||
assert!(data.protocols.iter().any(|p| p == "forgefed"));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue