feat(server): add config for enabling public signup view

main
Jef Roosens 2025-08-28 13:46:43 +02:00
parent 5017bfb710
commit 69e84b4266
Signed by: Jef Roosens
GPG Key ID: 02D4C0997E74717B
9 changed files with 37 additions and 12 deletions

View File

@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://git.rustybever.be/Chewing_Bever/otter)
* CLI command to add new users
* Added public sign-up page (disabled by default)
## [0.2.1](https://git.rustybever.be/Chewing_Bever/otter/src/tag/0.2.1)

View File

@ -1,6 +1,8 @@
data_dir = "./data"
log_level = "debug"
allow_public_signup = true
[net]
type = "tcp"
domain = "127.0.0.1"

View File

@ -23,6 +23,7 @@ pub fn serve(config: &crate::config::Config) -> Result<(), CliError> {
let ctx = server::Context {
store,
tera: Arc::new(tera),
config: config.clone(),
};
let app = server::app(ctx.clone());

View File

@ -23,7 +23,7 @@ impl From<LogLevel> for tracing::Level {
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
#[serde(tag = "type")]
pub enum NetConfig {
@ -31,12 +31,13 @@ pub enum NetConfig {
Unix { path: PathBuf },
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone)]
pub struct Config {
pub net: NetConfig,
pub data_dir: PathBuf,
pub session_cleanup_interval: u64,
pub log_level: LogLevel,
pub allow_public_signup: bool,
}
impl Default for Config {
@ -50,6 +51,7 @@ impl Default for Config {
// Once per day
session_cleanup_interval: 60 * 60 * 24,
log_level: LogLevel::Warn,
allow_public_signup: false,
}
}
}

View File

@ -20,6 +20,7 @@ use tower_http::trace::TraceLayer;
pub struct Context {
pub store: ::gpodder::GpodderRepository,
pub tera: Arc<tera::Tera>,
pub config: crate::config::Config,
}
pub fn app(ctx: Context) -> Router {

View File

@ -21,7 +21,7 @@ use crate::{
};
pub fn router(ctx: Context) -> Router<Context> {
Router::new()
let mut router = Router::new()
// .layer(middleware::from_fn_with_state(
// ctx.clone(),
// auth_web_middleware,
@ -29,8 +29,15 @@ pub fn router(ctx: Context) -> Router<Context> {
// Login route needs to be handled differently, as the middleware turns it into a redirect
// loop
.route("/login", get(get_login).post(post_login))
.route("/logout", post(post_logout))
.route("/signup", get(get_signup).post(post_signup))
.route("/logout", post(post_logout));
// If public signups aren't allowed, we don't even register the route to prevent any dumb
// security mistakes
if ctx.config.allow_public_signup {
router = router.route("/signup", get(get_signup).post(post_signup))
}
router
}
/// Middleware that authenticates the current user via the session token. If the credentials are
@ -87,10 +94,12 @@ async fn get_login(State(ctx): State<Context>, headers: HeaderMap, jar: CookieJa
{
Redirect::to("/").into_response()
} else {
View::Login
.page(&headers)
.response(&ctx.tera)
.into_response()
View::Login {
signup_note: ctx.config.allow_public_signup,
}
.page(&headers)
.response(&ctx.tera)
.into_response()
}
}

View File

@ -78,7 +78,7 @@ pub fn initialize_tera() -> tera::Result<tera::Tera> {
include_str!("templates/views/index.html"),
),
(
View::Login.template(),
View::Login { signup_note: false }.template(),
include_str!("templates/views/login.html"),
),
(

View File

@ -6,4 +6,8 @@
<input type="password" id="password" name="password">
<input type="submit" value="Login">
</form>
{% if signup_note %}
<p>Don't have an account yet? <a hx-get="/signup" hx-target="#inner" hx-push-url="/signup">Create one here</a>!</p>
{% endif %}
</article>

View File

@ -5,7 +5,9 @@ use super::{Query, Template};
pub enum View {
Index,
Login,
Login {
signup_note: bool,
},
Sessions(Vec<gpodder::Session>, i64, Option<Query>),
Users(Vec<gpodder::User>, i64, Option<Query>),
Signup {
@ -32,7 +34,7 @@ impl Template for View {
fn template(&self) -> &'static str {
match self {
Self::Index => "views/index.html",
Self::Login => "views/login.html",
Self::Login { .. } => "views/login.html",
Self::Sessions(..) => "views/sessions.html",
Self::Users(..) => "views/users.html",
Self::Signup { .. } => "views/signup.html",
@ -76,6 +78,9 @@ impl Template for View {
ctx.insert("username_available", &username_available);
ctx.insert("passwords_match", &passwords_match);
}
Self::Login { signup_note } => {
ctx.insert("signup_note", &signup_note);
}
_ => {}
};