diff --git a/src/backend/api/article.rs b/src/backend/api/article.rs index 4b208a6..1b57dc9 100644 --- a/src/backend/api/article.rs +++ b/src/backend/api/article.rs @@ -140,11 +140,11 @@ pub(in crate::backend::api) async fn get_article( match (query.title, query.id) { (Some(title), None) => Ok(Json(DbArticle::read_view_title( &title, - query.instance_domain, + query.domain, &data.db_connection, )?)), (None, Some(id)) => { - if query.instance_domain.is_some() { + if query.domain.is_some() { return Err(anyhow!("Cant combine id and instance_domain").into()); } Ok(Json(DbArticle::read_view(id, &data.db_connection)?)) diff --git a/src/backend/api/mod.rs b/src/backend/api/mod.rs index 2b1197a..240e7f4 100644 --- a/src/backend/api/mod.rs +++ b/src/backend/api/mod.rs @@ -4,8 +4,8 @@ use crate::backend::api::article::{ use crate::backend::api::article::{edit_article, fork_article, get_article}; use crate::backend::api::instance::get_local_instance; use crate::backend::api::instance::{follow_instance, resolve_instance}; -use crate::backend::api::user::register_user; use crate::backend::api::user::validate; +use crate::backend::api::user::{get_user, register_user}; use crate::backend::api::user::{login_user, logout_user}; use crate::backend::api::user::{my_profile, AUTH_COOKIE}; use crate::backend::database::conflict::DbConflict; @@ -45,6 +45,7 @@ pub fn api_routes() -> Router { .route("/instance/follow", post(follow_instance)) .route("/instance/resolve", get(resolve_instance)) .route("/search", get(search_article)) + .route("/user", get(get_user)) .route("/account/register", post(register_user)) .route("/account/login", post(login_user)) .route("/account/my_profile", get(my_profile)) diff --git a/src/backend/api/user.rs b/src/backend/api/user.rs index 8eabe78..19f7bee 100644 --- a/src/backend/api/user.rs +++ b/src/backend/api/user.rs @@ -1,8 +1,9 @@ use crate::backend::database::{read_jwt_secret, IbisData}; use crate::backend::error::MyResult; -use crate::common::{DbLocalUser, DbPerson, LocalUserView, LoginUserData, RegisterUserData}; +use crate::common::{DbPerson, GetUserData, LocalUserView, LoginUserData, RegisterUserData}; use activitypub_federation::config::Data; use anyhow::anyhow; +use axum::extract::Query; use axum::{Form, Json}; use axum_extra::extract::cookie::{Cookie, CookieJar, Expiration, SameSite}; use axum_macros::debug_handler; @@ -19,7 +20,7 @@ pub static AUTH_COOKIE: &str = "auth"; #[derive(Debug, Serialize, Deserialize)] struct Claims { - /// local_user.id + /// person.username pub sub: String, /// hostname pub iss: String, @@ -29,10 +30,10 @@ struct Claims { pub exp: u64, } -fn generate_login_token(local_user: &DbLocalUser, data: &Data) -> MyResult { +fn generate_login_token(person: &DbPerson, data: &Data) -> MyResult { let hostname = data.domain().to_string(); let claims = Claims { - sub: local_user.id.to_string(), + sub: person.username.clone(), iss: hostname, iat: Utc::now().timestamp(), exp: get_current_timestamp() + 60 * 60 * 24 * 365, @@ -49,7 +50,7 @@ pub async fn validate(jwt: &str, data: &Data) -> MyResult(jwt, &key, &validation)?; - DbPerson::read_local_from_id(claims.claims.sub.parse()?, data) + DbPerson::read_local_from_name(&claims.claims.sub, data) } #[debug_handler] @@ -62,7 +63,7 @@ pub(in crate::backend::api) async fn register_user( return Err(anyhow!("Registration is closed").into()); } let user = DbPerson::create_local(form.username, form.password, false, &data)?; - let token = generate_login_token(&user.local_user, &data)?; + let token = generate_login_token(&user.person, &data)?; let jar = jar.add(create_cookie(token, &data)); Ok((jar, Json(user))) } @@ -78,7 +79,7 @@ pub(in crate::backend::api) async fn login_user( if !valid { return Err(anyhow!("Invalid login").into()); } - let token = generate_login_token(&user.local_user, &data)?; + let token = generate_login_token(&user.person, &data)?; let jar = jar.add(create_cookie(token, &data)); Ok((jar, Json(user))) } @@ -122,3 +123,15 @@ pub(in crate::backend::api) async fn logout_user( let jar = jar.remove(create_cookie(String::new(), &data)); Ok(jar) } + +#[debug_handler] +pub(in crate::backend::api) async fn get_user( + params: Query, + data: Data, +) -> MyResult> { + Ok(Json(DbPerson::read_from_name( + ¶ms.name, + ¶ms.domain, + &data, + )?)) +} diff --git a/src/backend/database/article.rs b/src/backend/database/article.rs index d1c14d0..54ccb2b 100644 --- a/src/backend/database/article.rs +++ b/src/backend/database/article.rs @@ -77,7 +77,7 @@ impl DbArticle { pub fn read_view_title( title: &str, - instance_domain: Option, + domain: Option, conn: &Mutex, ) -> MyResult { let article: DbArticle = { @@ -86,9 +86,9 @@ impl DbArticle { .inner_join(instance::table) .filter(article::dsl::title.eq(title)) .into_boxed(); - let query = if let Some(instance_domain) = instance_domain { + let query = if let Some(domain) = domain { query - .filter(instance::dsl::domain.eq(instance_domain)) + .filter(instance::dsl::domain.eq(domain)) .filter(instance::dsl::local.eq(false)) } else { query.filter(article::dsl::local.eq(true)) diff --git a/src/backend/database/instance.rs b/src/backend/database/instance.rs index 90eb6c5..52ef0db 100644 --- a/src/backend/database/instance.rs +++ b/src/backend/database/instance.rs @@ -34,7 +34,7 @@ impl DbInstance { let mut conn = conn.lock().unwrap(); Ok(insert_into(instance::table) .values(form) - .on_conflict(instance::dsl::ap_id) + .on_conflict(instance::ap_id) .do_update() .set(form) .get_result(conn.deref_mut())?) @@ -51,14 +51,14 @@ impl DbInstance { ) -> MyResult { let mut conn = data.db_connection.lock().unwrap(); Ok(instance::table - .filter(instance::dsl::ap_id.eq(ap_id)) + .filter(instance::ap_id.eq(ap_id)) .get_result(conn.deref_mut())?) } pub fn read_local_instance(conn: &Mutex) -> MyResult { let mut conn = conn.lock().unwrap(); Ok(instance::table - .filter(instance::dsl::local.eq(true)) + .filter(instance::local.eq(true)) .get_result(conn.deref_mut())?) } @@ -101,7 +101,7 @@ impl DbInstance { use instance_follow::dsl::{follower_id, instance_id}; let mut conn = conn.lock().unwrap(); Ok(instance_follow::table - .inner_join(person::table.on(follower_id.eq(person::dsl::id))) + .inner_join(person::table.on(follower_id.eq(person::id))) .filter(instance_id.eq(id_)) .select(person::all_columns) .get_results(conn.deref_mut())?) diff --git a/src/backend/database/user.rs b/src/backend/database/user.rs index 9fbbb79..008d060 100644 --- a/src/backend/database/user.rs +++ b/src/backend/database/user.rs @@ -9,9 +9,9 @@ use activitypub_federation::http_signatures::generate_actor_keypair; use bcrypt::hash; use bcrypt::DEFAULT_COST; use chrono::{DateTime, Local, Utc}; -use diesel::QueryDsl; use diesel::{insert_into, AsChangeset, Insertable, PgConnection, RunQueryDsl}; use diesel::{ExpressionMethods, JoinOnDsl}; +use diesel::{PgTextExpressionMethods, QueryDsl}; use std::ops::DerefMut; use std::sync::{Mutex, MutexGuard}; @@ -103,6 +103,27 @@ impl DbPerson { .get_result(conn.deref_mut())?) } + pub fn read_from_name( + username: &str, + domain: &Option, + data: &Data, + ) -> MyResult { + let mut conn = data.db_connection.lock().unwrap(); + let mut query = person::table + .filter(person::username.eq(username)) + .select(person::all_columns) + .into_boxed(); + query = if let Some(domain) = domain { + let domain_pattern = format!("http://{domain}/%"); + query + .filter(person::ap_id.ilike(domain_pattern)) + .filter(person::local.eq(false)) + } else { + query.filter(person::local.eq(true)) + }; + Ok(query.get_result(conn.deref_mut())?) + } + pub fn read_local_from_name(username: &str, data: &Data) -> MyResult { let mut conn = data.db_connection.lock().unwrap(); let (person, local_user) = person::table @@ -119,22 +140,6 @@ impl DbPerson { }) } - pub fn read_local_from_id(id: i32, data: &Data) -> MyResult { - let mut conn = data.db_connection.lock().unwrap(); - let (person, local_user) = person::table - .inner_join(local_user::table) - .filter(person::dsl::local) - .filter(person::dsl::id.eq(id)) - .get_result::<(DbPerson, DbLocalUser)>(conn.deref_mut())?; - // TODO: handle this in single query - let following = Self::read_following(person.id, conn)?; - Ok(LocalUserView { - person, - local_user, - following, - }) - } - fn read_following(id_: i32, mut conn: MutexGuard) -> MyResult> { use instance_follow::dsl::{follower_id, instance_id}; Ok(instance_follow::table diff --git a/src/backend/federation/activities/accept.rs b/src/backend/federation/activities/accept.rs index 4da47c6..f3ec534 100644 --- a/src/backend/federation/activities/accept.rs +++ b/src/backend/federation/activities/accept.rs @@ -26,7 +26,7 @@ impl Accept { object: Follow, data: &Data, ) -> MyResult<()> { - let id = generate_activity_id(local_instance.ap_id.inner())?; + let id = generate_activity_id(&local_instance.ap_id)?; let follower = object.actor.dereference(data).await?; let accept = Accept { actor: local_instance.ap_id.clone(), diff --git a/src/backend/federation/activities/create_article.rs b/src/backend/federation/activities/create_article.rs index 676477c..23cd4ec 100644 --- a/src/backend/federation/activities/create_article.rs +++ b/src/backend/federation/activities/create_article.rs @@ -30,7 +30,7 @@ impl CreateArticle { pub async fn send_to_followers(article: DbArticle, data: &Data) -> MyResult<()> { let local_instance = DbInstance::read_local_instance(&data.db_connection)?; let object = article.clone().into_json(data).await?; - let id = generate_activity_id(local_instance.ap_id.inner())?; + let id = generate_activity_id(&local_instance.ap_id)?; let to = local_instance.follower_ids(data)?; let create = CreateArticle { actor: local_instance.ap_id.clone(), diff --git a/src/backend/federation/activities/follow.rs b/src/backend/federation/activities/follow.rs index 3215557..9b3a66a 100644 --- a/src/backend/federation/activities/follow.rs +++ b/src/backend/federation/activities/follow.rs @@ -27,7 +27,7 @@ pub struct Follow { impl Follow { pub async fn send(actor: DbPerson, to: &DbInstance, data: &Data) -> MyResult<()> { - let id = generate_activity_id(actor.ap_id.inner())?; + let id = generate_activity_id(&actor.ap_id)?; let follow = Follow { actor: actor.ap_id.clone(), object: to.ap_id.clone(), diff --git a/src/backend/federation/activities/reject.rs b/src/backend/federation/activities/reject.rs index 1c0d9a8..c8e7e10 100644 --- a/src/backend/federation/activities/reject.rs +++ b/src/backend/federation/activities/reject.rs @@ -34,7 +34,7 @@ impl RejectEdit { data: &Data, ) -> MyResult<()> { let local_instance = DbInstance::read_local_instance(&data.db_connection)?; - let id = generate_activity_id(local_instance.ap_id.inner())?; + let id = generate_activity_id(&local_instance.ap_id)?; let reject = RejectEdit { actor: local_instance.ap_id.clone(), to: vec![user_instance.ap_id.into_inner()], diff --git a/src/backend/federation/activities/update_local_article.rs b/src/backend/federation/activities/update_local_article.rs index 2aaf13f..a2349c2 100644 --- a/src/backend/federation/activities/update_local_article.rs +++ b/src/backend/federation/activities/update_local_article.rs @@ -38,7 +38,7 @@ impl UpdateLocalArticle { ) -> MyResult<()> { debug_assert!(article.local); let local_instance = DbInstance::read_local_instance(&data.db_connection)?; - let id = generate_activity_id(local_instance.ap_id.inner())?; + let id = generate_activity_id(&local_instance.ap_id)?; let mut to = local_instance.follower_ids(data)?; to.extend(extra_recipients.iter().map(|i| i.ap_id.inner().clone())); let update = UpdateLocalArticle { diff --git a/src/backend/federation/activities/update_remote_article.rs b/src/backend/federation/activities/update_remote_article.rs index 1507a9f..7000eec 100644 --- a/src/backend/federation/activities/update_remote_article.rs +++ b/src/backend/federation/activities/update_remote_article.rs @@ -40,7 +40,7 @@ impl UpdateRemoteArticle { data: &Data, ) -> MyResult<()> { let local_instance = DbInstance::read_local_instance(&data.db_connection)?; - let id = generate_activity_id(local_instance.ap_id.inner())?; + let id = generate_activity_id(&local_instance.ap_id)?; let update = UpdateRemoteArticle { actor: local_instance.ap_id.clone(), to: vec![article_instance.ap_id.into_inner()], diff --git a/src/backend/federation/objects/instance.rs b/src/backend/federation/objects/instance.rs index 7c1c74e..35c7979 100644 --- a/src/backend/federation/objects/instance.rs +++ b/src/backend/federation/objects/instance.rs @@ -1,14 +1,13 @@ use crate::backend::database::instance::DbInstanceForm; use crate::backend::database::IbisData; use crate::backend::error::Error; +use crate::backend::error::MyResult; use crate::backend::federation::objects::articles_collection::DbArticleCollection; use crate::backend::federation::send_activity; - +use crate::common::utils::extract_domain; +use crate::common::DbInstance; use activitypub_federation::fetch::collection_id::CollectionId; use activitypub_federation::kinds::actor::ServiceType; - -use crate::backend::error::MyResult; -use crate::common::DbInstance; use activitypub_federation::traits::ActivityHandler; use activitypub_federation::{ config::Data, @@ -108,10 +107,7 @@ impl Object for DbInstance { } async fn from_json(json: Self::Kind, data: &Data) -> Result { - let mut domain = json.id.inner().host_str().unwrap().to_string(); - if let Some(port) = json.id.inner().port() { - domain = format!("{domain}:{port}"); - } + let domain = extract_domain(&json.id); let form = DbInstanceForm { domain, ap_id: json.id, diff --git a/src/backend/utils.rs b/src/backend/utils.rs index d1f9238..7f053a0 100644 --- a/src/backend/utils.rs +++ b/src/backend/utils.rs @@ -1,24 +1,28 @@ use crate::backend::error::MyResult; use crate::common::DbEdit; use crate::common::EditVersion; +use activitypub_federation::fetch::object_id::ObjectId; +use activitypub_federation::traits::Object; use anyhow::anyhow; use diffy::{apply, Patch}; use rand::{distributions::Alphanumeric, thread_rng, Rng}; +use serde::Deserialize; +use crate::common::utils::extract_domain; use url::{ParseError, Url}; -pub fn generate_activity_id(domain: &Url) -> Result { - let port = match domain.port() { - Some(p) => format!(":{p}"), - None => String::new(), - }; - let domain = domain.host_str().unwrap(); +pub fn generate_activity_id(for_url: &ObjectId) -> Result +where + T: Object + Send + 'static, + for<'de2> ::Kind: Deserialize<'de2>, +{ + let domain = extract_domain(for_url); let id: String = thread_rng() .sample_iter(&Alphanumeric) .take(7) .map(char::from) .collect(); - Url::parse(&format!("http://{}{}/objects/{}", domain, port, id)) + Url::parse(&format!("http://{}/objects/{}", domain, id)) } /// Starting from empty string, apply edits until the specified version is reached. If no version is diff --git a/src/common/mod.rs b/src/common/mod.rs index 7b6b471..2aa98ee 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,3 +1,4 @@ +pub mod utils; pub mod validation; use chrono::{DateTime, Utc}; @@ -21,7 +22,7 @@ pub const MAIN_PAGE_NAME: &str = "Main_Page"; #[derive(Deserialize, Serialize, Clone, Debug)] pub struct GetArticleData { pub title: Option, - pub instance_domain: Option, + pub domain: Option, pub id: Option, } @@ -245,6 +246,12 @@ pub struct InstanceView { pub registration_open: bool, } +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct GetUserData { + pub name: String, + pub domain: Option, +} + #[test] fn test_edit_versions() { let default = EditVersion::default(); diff --git a/src/common/utils.rs b/src/common/utils.rs new file mode 100644 index 0000000..fb1b881 --- /dev/null +++ b/src/common/utils.rs @@ -0,0 +1,22 @@ +#[cfg(feature = "ssr")] +pub fn extract_domain(url: &activitypub_federation::fetch::object_id::ObjectId) -> String +where + T: activitypub_federation::traits::Object + Send + 'static, + for<'de2> ::Kind: serde::Deserialize<'de2>, +{ + let mut port = String::new(); + if let Some(port_) = url.inner().port() { + port = format!(":{port_}"); + } + format!("{}{port}", url.inner().host_str().unwrap()) +} + +#[cfg(not(feature = "ssr"))] +pub fn extract_domain(url: &String) -> String { + let url = url::Url::parse(url).unwrap(); + let mut port = String::new(); + if let Some(port_) = url.port() { + port = format!(":{port_}"); + } + format!("{}{port}", url.host_str().unwrap()) +} diff --git a/src/frontend/api.rs b/src/frontend/api.rs index 7da6b54..1fcb5ad 100644 --- a/src/frontend/api.rs +++ b/src/frontend/api.rs @@ -1,9 +1,9 @@ -use crate::common::ResolveObject; use crate::common::{ApiConflict, ListArticlesData}; use crate::common::{ArticleView, LoginUserData, RegisterUserData}; use crate::common::{CreateArticleData, EditArticleData, ForkArticleData, LocalUserView}; use crate::common::{DbArticle, GetArticleData}; use crate::common::{DbInstance, FollowInstance, InstanceView, SearchArticleData}; +use crate::common::{DbPerson, GetUserData, ResolveObject}; use crate::frontend::error::MyResult; use anyhow::anyhow; use reqwest::{Client, RequestBuilder, StatusCode}; @@ -84,7 +84,7 @@ impl ApiClient { self.get_article(GetArticleData { title: None, - instance_domain: None, + domain: None, id: Some(edit_form.article_id), }) .await @@ -175,6 +175,9 @@ impl ApiClient { self.get_query("instance/resolve", Some(resolve_object)) .await } + pub async fn get_user(&self, data: GetUserData) -> MyResult { + self.get_query("user", Some(data)).await + } } async fn handle_json_res(#[allow(unused_mut)] mut req: RequestBuilder) -> MyResult diff --git a/src/frontend/app.rs b/src/frontend/app.rs index b77c7e4..bc0e33e 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -11,6 +11,7 @@ use crate::frontend::pages::instance_details::InstanceDetails; use crate::frontend::pages::login::Login; use crate::frontend::pages::register::Register; use crate::frontend::pages::search::Search; +use crate::frontend::pages::user_profile::UserProfile; use leptos::{ component, create_local_resource, create_rw_signal, expect_context, provide_context, use_context, view, IntoView, RwSignal, SignalGet, SignalGetUntracked, SignalUpdate, @@ -97,6 +98,7 @@ pub fn App() -> impl IntoView { + diff --git a/src/frontend/components/nav.rs b/src/frontend/components/nav.rs index 9cf269b..bbfc076 100644 --- a/src/frontend/components/nav.rs +++ b/src/frontend/components/nav.rs @@ -55,29 +55,35 @@ pub fn Nav() -> impl IntoView { "Logged in as: " - { - move || global_state.with(|state| state.my_profile.clone().unwrap().person.username) - } - -

+
  • + "Login" +
  • + +
  • + "Register" +
  • +
    } } > -
  • - "Login" -
  • - -
  • - "Register" -
  • + { + let my_profile = global_state.with(|state| state.my_profile.clone().unwrap()); + let profile_link = format!("/user/{}", my_profile.person.username); + view ! { +

    "Logged in as " + + {my_profile.person.username} + +

    + + } + }
    -
    } } diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 2685bdb..d0a11e1 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -1,5 +1,5 @@ +use crate::common::utils::extract_domain; use crate::common::DbArticle; -use url::Url; pub mod api; pub mod app; @@ -11,28 +11,15 @@ pub mod pages; #[wasm_bindgen::prelude::wasm_bindgen] pub fn hydrate() {} -fn extract_hostname(article: &DbArticle) -> String { - let ap_id: Url; - #[cfg(not(feature = "ssr"))] - { - ap_id = article.ap_id.parse().unwrap(); - } - #[cfg(feature = "ssr")] - { - ap_id = article.ap_id.inner().clone(); - } - let mut port = String::new(); - if let Some(port_) = ap_id.port() { - port = format!(":{port_}"); - } - format!("{}{port}", ap_id.host_str().unwrap()) -} - fn article_link(article: &DbArticle) -> String { if article.local { format!("/article/{}", article.title) } else { - format!("/article/{}@{}", article.title, extract_hostname(article)) + format!( + "/article/{}@{}", + article.title, + extract_domain(&article.ap_id) + ) } } @@ -41,6 +28,6 @@ fn article_title(article: &DbArticle) -> String { if article.local { title } else { - format!("{}@{}", title, extract_hostname(article)) + format!("{}@{}", title, extract_domain(&article.ap_id)) } } diff --git a/src/frontend/pages/mod.rs b/src/frontend/pages/mod.rs index 962a72d..0e29716 100644 --- a/src/frontend/pages/mod.rs +++ b/src/frontend/pages/mod.rs @@ -8,6 +8,7 @@ pub(crate) mod instance_details; pub(crate) mod login; pub(crate) mod register; pub(crate) mod search; +pub(crate) mod user_profile; fn article_resource( title: impl Fn() -> Option + 'static, @@ -22,7 +23,7 @@ fn article_resource( GlobalState::api_client() .get_article(GetArticleData { title: Some(title), - instance_domain: domain, + domain, id: None, }) .await diff --git a/src/frontend/pages/user_profile.rs b/src/frontend/pages/user_profile.rs new file mode 100644 index 0000000..96e09a1 --- /dev/null +++ b/src/frontend/pages/user_profile.rs @@ -0,0 +1,45 @@ +use crate::common::{DbPerson, GetUserData}; +use crate::frontend::app::GlobalState; +use crate::frontend::extract_domain; +use leptos::*; +use leptos_router::use_params_map; + +#[component] +pub fn UserProfile() -> impl IntoView { + let params = use_params_map(); + let name = move || params.get().get("name").cloned().unwrap(); + let (error, set_error) = create_signal(None::); + let user_profile = create_resource(name, move |mut name| async move { + set_error.set(None); + let mut domain = None; + if let Some((title_, domain_)) = name.clone().split_once('@') { + name = title_.to_string(); + domain = Some(domain_.to_string()); + } + let params = GetUserData { name, domain }; + GlobalState::api_client().get_user(params).await.unwrap() + }); + + view! { + {move || { + error + .get() + .map(|err| { + view! {

    {err}

    } + }) + }} + { + move || user_profile.get().map(|person: DbPerson| { + let name = + if person.local { + person.username + } else { + format!("{}@{}", person.username, extract_domain(&person.ap_id)) + }; + view! { +

    {name}

    + } + }) + }
    + } +} diff --git a/tests/common.rs b/tests/common.rs index 6eb0917..40f0a84 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -56,6 +56,7 @@ impl TestData { ] { j.join().unwrap(); } + dbg!(&alpha_db_path); Self { alpha: IbisInstance::start(alpha_db_path, port_alpha, "alpha").await, diff --git a/tests/test.rs b/tests/test.rs index 045c3ed..51381df 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -4,7 +4,7 @@ mod common; use crate::common::{TestData, TEST_ARTICLE_DEFAULT_TEXT}; use ibis_lib::common::{ - ArticleView, EditArticleData, ForkArticleData, GetArticleData, ListArticlesData, + ArticleView, EditArticleData, ForkArticleData, GetArticleData, GetUserData, ListArticlesData, }; use ibis_lib::common::{CreateArticleData, SearchArticleData}; use ibis_lib::common::{LoginUserData, RegisterUserData}; @@ -29,7 +29,7 @@ async fn test_create_read_and_edit_local_article() -> MyResult<()> { // now article can be read let get_article_data = GetArticleData { title: Some(create_res.article.title.clone()), - instance_domain: None, + domain: None, id: None, }; let get_res = data.alpha.get_article(get_article_data.clone()).await?; @@ -152,7 +152,7 @@ async fn test_synchronize_articles() -> MyResult<()> { let mut get_article_data = GetArticleData { title: Some(create_res.article.title), - instance_domain: None, + domain: None, id: None, }; @@ -161,7 +161,7 @@ async fn test_synchronize_articles() -> MyResult<()> { assert!(get_res.is_err()); // get the article with instance id and compare - get_article_data.instance_domain = Some(instance.domain); + get_article_data.domain = Some(instance.domain); let get_res = data.beta.get_article(get_article_data).await?; assert_eq!(create_res.article.ap_id, get_res.article.ap_id); assert_eq!(create_form.title, get_res.article.title); @@ -194,7 +194,7 @@ async fn test_edit_local_article() -> MyResult<()> { // article should be federated to alpha let get_article_data = GetArticleData { title: Some(create_res.article.title.to_string()), - instance_domain: Some(beta_instance.domain), + domain: Some(beta_instance.domain), id: None, }; let get_res = data.alpha.get_article(get_article_data.clone()).await?; @@ -254,7 +254,7 @@ async fn test_edit_remote_article() -> MyResult<()> { // article should be federated to alpha and gamma let get_article_data_alpha = GetArticleData { title: Some(create_res.article.title.to_string()), - instance_domain: Some(beta_id_on_alpha.domain), + domain: Some(beta_id_on_alpha.domain), id: None, }; let get_res = data @@ -267,7 +267,7 @@ async fn test_edit_remote_article() -> MyResult<()> { let get_article_data_gamma = GetArticleData { title: Some(create_res.article.title.to_string()), - instance_domain: Some(beta_id_on_gamma.domain), + domain: Some(beta_id_on_gamma.domain), id: None, }; let get_res = data @@ -397,7 +397,7 @@ async fn test_federated_edit_conflict() -> MyResult<()> { // alpha edits article let get_article_data = GetArticleData { title: Some(create_form.title.to_string()), - instance_domain: Some(beta_id_on_alpha.domain), + domain: Some(beta_id_on_alpha.domain), id: None, }; let get_res = data.alpha.get_article(get_article_data).await?; @@ -582,3 +582,30 @@ async fn test_user_registration_login() -> MyResult<()> { data.stop() } + +#[tokio::test] +async fn test_user_profile() -> MyResult<()> { + let data = TestData::start().await; + + // Create an article and federate it, in order to federate the user who created it + let create_form = CreateArticleData { + title: "Manu_Chao".to_string(), + text: TEST_ARTICLE_DEFAULT_TEXT.to_string(), + summary: "create article".to_string(), + }; + let create_res = data.alpha.create_article(&create_form).await?; + data.beta + .resolve_article(create_res.article.ap_id.into_inner()) + .await?; + + // Now we can fetch the remote user from local api + let params = GetUserData { + name: "alpha".to_string(), + domain: Some("localhost:8100".to_string()), + }; + let user = data.beta.get_user(params).await?; + assert_eq!("alpha", user.username); + assert!(!user.local); + + data.stop() +}