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()
+}