1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2024-11-26 12:11:10 +00:00
This commit is contained in:
Felix Ableitner 2024-11-13 14:30:43 +01:00
parent 7772585ffc
commit 72d123aab1
8 changed files with 55 additions and 40 deletions

View file

@ -64,7 +64,7 @@ axum-extra = { version = "0.9.4", features = ["cookie"], optional = true }
leptos = "0.6.15" leptos = "0.6.15"
leptos_meta = "0.6.15" leptos_meta = "0.6.15"
leptos_router = "0.6.15" leptos_router = "0.6.15"
leptos_axum = { version = "0.6.15", optional = true } leptos_axum = { version = "0.6.15", features = ["wasm"], optional = true }
bcrypt = "0.15.1" bcrypt = "0.15.1"
chrono = { version = "0.4.38", features = ["serde"] } chrono = { version = "0.4.38", features = ["serde"] }
diesel = { version = "2.2.4", features = [ diesel = { version = "2.2.4", features = [

View file

@ -68,7 +68,7 @@ pub(in crate::backend::api) async fn create_article(
instance_id: local_instance.id, instance_id: local_instance.id,
local: true, local: true,
protected: false, protected: false,
approved: !data.config.article_approval, approved: !data.config.config.article_approval,
}; };
let article = DbArticle::create(form, &data)?; let article = DbArticle::create(form, &data)?;
@ -214,7 +214,7 @@ pub(in crate::backend::api) async fn fork_article(
instance_id: local_instance.id, instance_id: local_instance.id,
local: true, local: true,
protected: false, protected: false,
approved: !data.config.article_approval, approved: !data.config.config.article_approval,
}; };
let article = DbArticle::create(form, &data)?; let article = DbArticle::create(form, &data)?;

View file

@ -12,20 +12,12 @@ use crate::{
search_article, search_article,
}, },
instance::{follow_instance, get_instance, resolve_instance}, instance::{follow_instance, get_instance, resolve_instance},
user::{ user::{get_user, login_user, logout_user, register_user, validate, AUTH_COOKIE},
get_user,
login_user,
logout_user,
my_profile,
register_user,
validate,
AUTH_COOKIE,
},
}, },
database::IbisData, database::IbisData,
error::MyResult, error::MyResult,
}, },
common::LocalUserView, common::{LocalUserView, SiteView},
}; };
use activitypub_federation::config::Data; use activitypub_federation::config::Data;
use anyhow::anyhow; use anyhow::anyhow;
@ -36,9 +28,11 @@ use axum::{
middleware::{self, Next}, middleware::{self, Next},
response::Response, response::Response,
routing::{get, post}, routing::{get, post},
Json,
Router, Router,
}; };
use axum_extra::extract::CookieJar; use axum_extra::extract::CookieJar;
use axum_macros::debug_handler;
use instance::list_remote_instances; use instance::list_remote_instances;
use user::{count_notifications, list_notifications}; use user::{count_notifications, list_notifications};
@ -67,8 +61,8 @@ pub fn api_routes() -> Router<()> {
.route("/user/notifications/count", get(count_notifications)) .route("/user/notifications/count", get(count_notifications))
.route("/account/register", post(register_user)) .route("/account/register", post(register_user))
.route("/account/login", post(login_user)) .route("/account/login", post(login_user))
.route("/account/my_profile", get(my_profile))
.route("/account/logout", get(logout_user)) .route("/account/logout", get(logout_user))
.route("/site", get(site_view))
.route_layer(middleware::from_fn(auth)) .route_layer(middleware::from_fn(auth))
} }
@ -93,3 +87,20 @@ fn check_is_admin(user: &LocalUserView) -> MyResult<()> {
} }
Ok(()) Ok(())
} }
#[debug_handler]
pub(in crate::backend::api) async fn site_view(
data: Data<IbisData>,
jar: CookieJar,
) -> MyResult<Json<SiteView>> {
let jwt = jar.get(AUTH_COOKIE).map(|c| c.value());
let my_profile = if let Some(jwt) = jwt {
Some(validate(jwt, &data).await?)
} else {
None
};
Ok(Json(SiteView {
my_profile,
config: data.config.config.clone(),
}))
}

View file

@ -77,7 +77,7 @@ pub(in crate::backend::api) async fn register_user(
jar: CookieJar, jar: CookieJar,
Form(form): Form<RegisterUserForm>, Form(form): Form<RegisterUserForm>,
) -> MyResult<(CookieJar, Json<LocalUserView>)> { ) -> MyResult<(CookieJar, Json<LocalUserView>)> {
if !data.config.registration_open { if !data.config.config.registration_open {
return Err(anyhow!("Registration is closed").into()); return Err(anyhow!("Registration is closed").into());
} }
let user = DbPerson::create_local(form.username, form.password, false, &data)?; let user = DbPerson::create_local(form.username, form.password, false, &data)?;
@ -122,19 +122,6 @@ fn create_cookie(jwt: String, data: &Data<IbisData>) -> Cookie<'static> {
.build() .build()
} }
#[debug_handler]
pub(in crate::backend::api) async fn my_profile(
data: Data<IbisData>,
jar: CookieJar,
) -> MyResult<Json<LocalUserView>> {
let jwt = jar.get(AUTH_COOKIE).map(|c| c.value());
if let Some(jwt) = jwt {
Ok(Json(validate(jwt, &data).await?))
} else {
Err(anyhow!("invalid/missing auth").into())
}
}
#[debug_handler] #[debug_handler]
pub(in crate::backend::api) async fn logout_user( pub(in crate::backend::api) async fn logout_user(
data: Data<IbisData>, data: Data<IbisData>,

View file

@ -1,4 +1,4 @@
use crate::backend::error::MyResult; use crate::{backend::error::MyResult, common::SharedConfig};
use config::Config; use config::Config;
use doku::Document; use doku::Document;
use serde::Deserialize; use serde::Deserialize;
@ -10,17 +10,10 @@ use smart_default::SmartDefault;
pub struct IbisConfig { pub struct IbisConfig {
/// Details about the PostgreSQL database connection /// Details about the PostgreSQL database connection
pub database: IbisConfigDatabase, pub database: IbisConfigDatabase,
/// Whether users can create new accounts
#[default = true]
#[doku(example = "true")]
pub registration_open: bool,
/// Whether admins need to approve new articles
#[default = false]
#[doku(example = "false")]
pub article_approval: bool,
/// Details of the initial admin account /// Details of the initial admin account
pub setup: IbisConfigSetup, pub setup: IbisConfigSetup,
pub federation: IbisConfigFederation, pub federation: IbisConfigFederation,
pub config: SharedConfig,
} }
impl IbisConfig { impl IbisConfig {

View file

@ -86,7 +86,6 @@ impl DbInstance {
Ok(InstanceView { Ok(InstanceView {
instance, instance,
followers, followers,
registration_open: data.config.registration_open,
}) })
} }

View file

@ -34,7 +34,7 @@ async fn node_info(data: Data<IbisData>) -> MyResult<Json<NodeInfo>> {
version: env!("CARGO_PKG_VERSION").to_string(), version: env!("CARGO_PKG_VERSION").to_string(),
}, },
protocols: vec!["activitypub".to_string()], protocols: vec!["activitypub".to_string()],
open_registrations: data.config.registration_open, open_registrations: data.config.config.registration_open,
})) }))
} }

View file

@ -6,6 +6,7 @@ use chrono::{DateTime, Utc};
use newtypes::{ArticleId, ConflictId, EditId, InstanceId, PersonId}; use newtypes::{ArticleId, ConflictId, EditId, InstanceId, PersonId};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use smart_default::SmartDefault;
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
@ -17,6 +18,7 @@ use {
}, },
activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId}, activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId},
diesel::{Identifiable, Queryable, Selectable}, diesel::{Identifiable, Queryable, Selectable},
doku::Document,
}; };
pub const MAIN_PAGE_NAME: &str = "Main_Page"; pub const MAIN_PAGE_NAME: &str = "Main_Page";
@ -133,6 +135,30 @@ pub struct LoginUserForm {
pub password: String, pub password: String,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(default)]
#[serde(deny_unknown_fields)]
#[cfg_attr(feature = "ssr", derive(Queryable, Document))]
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
pub struct SharedConfig {
/// Whether users can create new accounts
#[default = true]
#[cfg_attr(feature = "ssr", doku(example = "true"))]
pub registration_open: bool,
/// Whether admins need to approve new articles
#[default = false]
#[cfg_attr(feature = "ssr", doku(example = "false"))]
pub article_approval: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "ssr", derive(Queryable))]
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
pub struct SiteView {
pub my_profile: Option<LocalUserView>,
pub config: SharedConfig,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "ssr", derive(Queryable))] #[cfg_attr(feature = "ssr", derive(Queryable))]
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))] #[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
@ -306,7 +332,6 @@ impl DbInstance {
pub struct InstanceView { pub struct InstanceView {
pub instance: DbInstance, pub instance: DbInstance,
pub followers: Vec<DbPerson>, pub followers: Vec<DbPerson>,
pub registration_open: bool,
} }
#[derive(Deserialize, Serialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]