From f2180e5e0b6483fc8e1f1f7d82db8228e9dc8e7a Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 1 Feb 2024 16:46:36 +0100 Subject: [PATCH] add basic instance details page (untested) --- .../2023-11-28-150402_ibis_setup/up.sql | 4 +- src/backend/api/user.rs | 3 +- src/backend/database/instance.rs | 1 + src/backend/database/schema.rs | 2 + src/backend/database/user.rs | 3 ++ src/backend/federation/objects/instance.rs | 3 ++ src/backend/mod.rs | 1 + src/common/mod.rs | 2 + src/frontend/app.rs | 22 ++++++-- src/frontend/components/article_nav.rs | 2 +- src/frontend/pages/article/edit.rs | 4 +- src/frontend/pages/article/history.rs | 4 +- src/frontend/pages/article/read.rs | 6 +-- src/frontend/pages/diff.rs | 2 +- src/frontend/pages/instance_details.rs | 33 ++++++++++++ src/frontend/pages/mod.rs | 51 +++++++------------ 16 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 src/frontend/pages/instance_details.rs diff --git a/migrations/2023-11-28-150402_ibis_setup/up.sql b/migrations/2023-11-28-150402_ibis_setup/up.sql index 392f1d0..642a43c 100644 --- a/migrations/2023-11-28-150402_ibis_setup/up.sql +++ b/migrations/2023-11-28-150402_ibis_setup/up.sql @@ -1,6 +1,7 @@ create table instance ( id serial primary key, ap_id varchar(255) not null unique, + description text, inbox_url text not null, articles_url varchar(255) not null unique, public_key text not null, @@ -23,7 +24,8 @@ create table person ( create table local_user ( id serial primary key, password_encrypted text not null, - person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + admin bool not null ); create table instance_follow ( diff --git a/src/backend/api/user.rs b/src/backend/api/user.rs index 9598c03..8c86416 100644 --- a/src/backend/api/user.rs +++ b/src/backend/api/user.rs @@ -58,7 +58,8 @@ pub(in crate::backend::api) async fn register_user( jar: CookieJar, Form(form): Form, ) -> MyResult<(CookieJar, Json)> { - let user = DbPerson::create_local(form.username, form.password, &data)?; + // TODO: make admin if its the first user account + let user = DbPerson::create_local(form.username, form.password, false, &data)?; let token = generate_login_token(&user.local_user, &data)?; let jar = jar.add(create_cookie(token, &data)); Ok((jar, Json(user))) diff --git a/src/backend/database/instance.rs b/src/backend/database/instance.rs index f0439b6..b4ca59a 100644 --- a/src/backend/database/instance.rs +++ b/src/backend/database/instance.rs @@ -19,6 +19,7 @@ use std::sync::Mutex; #[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))] pub struct DbInstanceForm { pub ap_id: ObjectId, + pub description: Option, pub articles_url: CollectionId, pub inbox_url: String, pub public_key: String, diff --git a/src/backend/database/schema.rs b/src/backend/database/schema.rs index f3e1968..d4ea8ce 100644 --- a/src/backend/database/schema.rs +++ b/src/backend/database/schema.rs @@ -43,6 +43,7 @@ diesel::table! { id -> Int4, #[max_length = 255] ap_id -> Varchar, + description -> Nullable, inbox_url -> Text, #[max_length = 255] articles_url -> Varchar, @@ -74,6 +75,7 @@ diesel::table! { id -> Int4, password_encrypted -> Text, person_id -> Int4, + admin -> Bool, } } diff --git a/src/backend/database/user.rs b/src/backend/database/user.rs index 70b8356..4702170 100644 --- a/src/backend/database/user.rs +++ b/src/backend/database/user.rs @@ -19,6 +19,7 @@ use std::sync::Mutex; pub struct DbLocalUserForm { pub password_encrypted: String, pub person_id: i32, + pub admin: bool, } #[derive(Debug, Clone, Insertable, AsChangeset)] @@ -52,6 +53,7 @@ impl DbPerson { pub fn create_local( username: String, password: String, + admin: bool, data: &Data, ) -> MyResult { let mut conn = data.db_connection.lock().unwrap(); @@ -76,6 +78,7 @@ impl DbPerson { let local_user_form = DbLocalUserForm { password_encrypted: hash(password, DEFAULT_COST)?, person_id: person.id, + admin, }; let local_user = insert_into(local_user::table) diff --git a/src/backend/federation/objects/instance.rs b/src/backend/federation/objects/instance.rs index 48bee38..c18fbe0 100644 --- a/src/backend/federation/objects/instance.rs +++ b/src/backend/federation/objects/instance.rs @@ -27,6 +27,7 @@ pub struct ApubInstance { #[serde(rename = "type")] kind: ServiceType, id: ObjectId, + content: Option, articles: CollectionId, inbox: Url, public_key: PublicKey, @@ -90,6 +91,7 @@ impl Object for DbInstance { Ok(ApubInstance { kind: Default::default(), id: self.ap_id.clone(), + content: self.description.clone(), articles: self.articles_url.clone(), inbox: Url::parse(&self.inbox_url)?, public_key: self.public_key(), @@ -108,6 +110,7 @@ impl Object for DbInstance { async fn from_json(json: Self::Kind, data: &Data) -> Result { let form = DbInstanceForm { ap_id: json.id, + description: json.content, articles_url: json.articles, inbox_url: json.inbox.to_string(), public_key: json.public_key.public_key_pem, diff --git a/src/backend/mod.rs b/src/backend/mod.rs index e3cfdcf..961c69a 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -65,6 +65,7 @@ pub async fn start(hostname: &str, database_url: &str) -> MyResult<()> { let keypair = generate_actor_keypair()?; let form = DbInstanceForm { ap_id, + description: Some("New Ibis instance".to_string()), articles_url, inbox_url, public_key: keypair.public_key, diff --git a/src/common/mod.rs b/src/common/mod.rs index 862a4c7..aae0a0f 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -133,6 +133,7 @@ pub struct DbLocalUser { pub id: i32, pub password_encrypted: String, pub person_id: i32, + pub admin: bool, } /// Federation related data from a local or remote user. @@ -219,6 +220,7 @@ pub struct DbInstance { pub ap_id: ObjectId, #[cfg(not(feature = "ssr"))] pub ap_id: String, + pub description: Option, #[cfg(feature = "ssr")] pub articles_url: CollectionId, #[cfg(not(feature = "ssr"))] diff --git a/src/frontend/app.rs b/src/frontend/app.rs index 928c05c..8e3c7c2 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -7,13 +7,13 @@ use crate::frontend::pages::article::history::ArticleHistory; use crate::frontend::pages::article::list::ListArticles; use crate::frontend::pages::article::read::ReadArticle; use crate::frontend::pages::diff::EditDiff; +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::Page; use leptos::{ component, create_local_resource, create_rw_signal, expect_context, provide_context, - use_context, view, IntoView, RwSignal, SignalGetUntracked, SignalUpdate, + use_context, view, IntoView, RwSignal, SignalGet, SignalGetUntracked, SignalUpdate, }; use leptos_meta::provide_meta_context; use leptos_meta::*; @@ -47,6 +47,17 @@ impl GlobalState { }, ); } + + pub fn is_admin() -> fn() -> bool { + move || { + use_context::>() + .expect("global state is provided") + .get() + .my_profile + .map(|p| p.local_user.admin) + .unwrap_or(false) + } + } } #[component] @@ -71,15 +82,16 @@ pub fn App() -> impl IntoView {