Skip to content

Commit

Permalink
fix panic (#314)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit


- **Improvements**
  - Enhanced dropdown menus in notification and user list templates by adding explicit `value` attributes to role selection options.
  - Improved form data submission clarity by defining specific values for roles like "Pending", "Rejected", "Intern", "Fellow", "Mod", and "Super".
- **Bug Fixes**
  - Updated validation logic across various forms to enhance error handling and ensure secure password reset processes.
- **Refactor**
  - Transitioned from `garde` to `validator` library for form validation, updating relevant attributes and imports throughout the application.
  - Standardized route parameter syntax across the application for consistency.
- **Documentation**
  - Minor adjustments made to permissions table documentation for clarity regarding user roles and permissions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
freedit-dev authored Jan 3, 2025
1 parent 42b8823 commit 422cffa
Show file tree
Hide file tree
Showing 17 changed files with 408 additions and 369 deletions.
409 changes: 205 additions & 204 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 6 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
[package]
name = "freedit"
version = "0.7.6-rc.0"
version = "0.7.6-rc.1"
edition = "2021"
license = "MIT License"

[dependencies]
ammonia = "4.0.0"
atom_syndication = { version = "0.12", default-features = false }
axum = { version = "0.7.5", features = ["http1", "http2", "form", "query", "multipart", "tokio"], default-features = false }
axum-extra = { version = "0.9", features = ["typed-header"] }
axum_garde = { version = "0.20.0", default-features = false, features = ["form"] }
axum = { version = "0.8.1", features = ["http1", "http2", "form", "query", "multipart", "tokio"], default-features = false }
axum-extra = { version = "0.10.0", features = ["typed-header"] }
basic-toml = "*"
bincode = "2.0.0-rc.3"
cached = { version = "0.54.0", default-features = false, features = ["proc_macro", "ahash"] }
captcha = { git = "https://github.com/freedit-dev/captcha.git", default-features = false }
data-encoding = "*"
fast2s = "0.3"
garde = { version = "0.20.0", features = ["derive"] }
http = "1.2.0"
identicon = { git = "https://github.com/freedit-dev/identicon.git", default-features = false }
image = { version = "0.25.2", default-features = false, features = ["jpeg", "png", "gif"] }
img-parts = "0.3.0"
indexmap = "2"
jieba-rs = { git = "https://github.com/messense/jieba-rs.git", rev = "b39957e" }
jiff = { version = "0.1.15", default-features = false, features = ["std"] }
jiff = { version = "0.1.19", default-features = false, features = ["std"] }
latex2mathml = "0.2.3"
mozjpeg = "0.10.11"
nanoid = "0.4.0"
Expand All @@ -33,13 +31,12 @@ regex = "1"
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "socks"] }
ring = { version = "0.17", default-features = false }
rinja = { version = "0.3.4", default-features = false }
rinja_axum = { version = "0.3.4", default-features = false }
rss = { version = "2.0", default-features = false }
rust-stemmers = "1.2.0"
serde = { version = "1.0", features = ["derive"] }
sled = "0.34.7"
snailquote = "0.3.1"
stop-words = "0.8.0"
stop-words = "0.8.1"
syntect = { version = "5", features = ["regex-fancy", "default-syntaxes", "default-themes", "html"], default-features = false }
tantivy = "0.22.0"
thiserror = "2"
Expand All @@ -49,6 +46,7 @@ tower-http = { version = "0.6.1", features = ["fs", "compression-zstd", "trace"]
tracing = { version = "0.1", features = ["release_max_level_info", "max_level_info"], default-features = false }
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "smallvec"], default-features = false }
unicode-segmentation = "1"
validator = { version = "0.19.0", features = ["derive"] }
whichlang = "0.1.0"

[target.'cfg(not(target_os = "windows"))'.dependencies]
Expand Down
68 changes: 34 additions & 34 deletions src/app_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,64 +53,64 @@ pub async fn router() -> Router {
.route("/signup", get(signup).post(signup_post))
.route("/signin", get(signin).post(signin_post))
.route("/signout", get(signout))
.route("/user/:u", get(user))
.route("/user/:u/follow", get(user_follow))
.route("/user/{u}", get(user))
.route("/user/{u}/follow", get(user_follow))
.route("/user/setting", get(user_setting).post(user_setting_post))
.route("/user/avatar", get(user_setting).post(upload_pic_post))
.route("/user/password", get(user_setting).post(user_password_post))
.route("/user/recovery", get(user_setting).post(user_recovery_code))
.route("/user/reset", get(reset).post(reset_post))
.route("/user/list", get(user_list))
.route("/user/remove/:session_id", get(remove_session))
.route("/role/:id/:uid", get(user_list).post(role_post))
.route("/user/remove/{session_id}", get(remove_session))
.route("/role/{id}/{uid}", get(user_list).post(role_post))
.route("/notification", get(notification))
.route("/admin", get(admin).post(admin_post))
.route("/admin/view", get(admin_view))
.route("/admin/gallery", get(admin_gallery))
.route("/image/delete/:uid/:img_id", get(image_delete))
.route("/mod/:iid", get(mod_inn).post(mod_inn_post))
.route("/mod/feed/:iid", get(mod_inn).post(mod_feed_post))
.route("/image/delete/{uid}/{img_id}", get(image_delete))
.route("/mod/{iid}", get(mod_inn).post(mod_inn_post))
.route("/mod/feed/{iid}", get(mod_inn).post(mod_feed_post))
.route(
"/mod/inn_icon",
get(mod_inn).post(upload_pic_post.layer(DefaultBodyLimit::max(UPLOAD_LIMIT))),
)
.route("/mod/:iid/:pid/lock", get(post_lock))
.route("/mod/:iid/:pid/hide", get(post_hide))
.route("/mod/:iid/:pid/pin", get(post_pin))
.route("/mod/{iid}/{pid}/lock", get(post_lock))
.route("/mod/{iid}/{pid}/hide", get(post_hide))
.route("/mod/{iid}/{pid}/pin", get(post_pin))
.route("/inn/list", get(inn_list))
.route("/inn/tag/:tag", get(tag))
.route("/inn/:i", get(inn))
.route("/inn/:i/join", get(inn_join))
.route("/inn/:i/atom.xml", get(inn_feed))
.route("/post/:iid/:pid", get(post).post(comment_post))
.route("/post/:iid/:pid/:cid/delete", get(comment_delete))
.route("/post/:iid/:pid/:cid/hide", get(comment_hide))
.route("/post/edit/:pid", get(edit_post).post(edit_post_post))
.route("/post/:iid/:pid/upvote", get(post_upvote))
.route("/post/:iid/:pid/downvote", get(post_downvote))
.route("/post/:iid/:pid/delete", get(post_delete))
.route("/post/:iid/:pid/:cid/upvote", get(comment_upvote))
.route("/post/:iid/:pid/:cid/downvote", get(comment_downvote))
.route("/inn/tag/{tag}", get(tag))
.route("/inn/{i}", get(inn))
.route("/inn/{i}/join", get(inn_join))
.route("/inn/{i}/atom.xml", get(inn_feed))
.route("/post/{iid}/{pid}", get(post).post(comment_post))
.route("/post/{iid}/{pid}/{cid}/delete", get(comment_delete))
.route("/post/{iid}/{pid}/{cid}/hide", get(comment_hide))
.route("/post/edit/{pid}", get(edit_post).post(edit_post_post))
.route("/post/{iid}/{pid}/upvote", get(post_upvote))
.route("/post/{iid}/{pid}/downvote", get(post_downvote))
.route("/post/{iid}/{pid}/delete", get(post_delete))
.route("/post/{iid}/{pid}/{cid}/upvote", get(comment_upvote))
.route("/post/{iid}/{pid}/{cid}/downvote", get(comment_downvote))
.route("/preview", get(post).post(preview))
.route("/solo/user/:u", get(solo_list).post(solo_post))
.route("/solo/:sid/like", get(solo_like))
.route("/solo/:sid/delete", get(solo_delete))
.route("/solo/:sid", get(solo))
.route("/solo/user/{u}", get(solo_list).post(solo_post))
.route("/solo/{sid}/like", get(solo_like))
.route("/solo/{sid}/delete", get(solo_delete))
.route("/solo/{sid}", get(solo))
.route(
"/upload",
get(upload).post(upload_post.layer(DefaultBodyLimit::max(UPLOAD_LIMIT))),
)
.route("/gallery/:uid", get(gallery))
.route("/feed/:uid", get(feed))
.route("/gallery/{uid}", get(gallery))
.route("/feed/{uid}", get(feed))
.route("/feed/add", get(feed_add).post(feed_add_post))
.route("/feed/update", get(feed_update))
.route("/feed/star/:item_id", get(feed_star))
.route("/feed/subscribe/:uid/:item_id", get(feed_subscribe))
.route("/feed/read/:item_id", get(feed_read))
.route("/feed/star/{item_id}", get(feed_star))
.route("/feed/subscribe/{uid}/{item_id}", get(feed_subscribe))
.route("/feed/read/{item_id}", get(feed_read))
.route("/search", get(search))
.route("/message/:uid", get(message).post(message_post))
.route("/message/{uid}", get(message).post(message_post))
.route("/key", get(key).post(key_post))
.route("/inbox/:mid", get(inbox));
.route("/inbox/{mid}", get(inbox));

let router_static = Router::new()
.route("/static/style.css", get(style))
Expand Down
10 changes: 4 additions & 6 deletions src/controller/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{
db_utils::{get_range, ivec_to_u32, set_one_with_key, u8_slice_to_u32, IterType},
fmt::{clean_html, ts_to_date},
inn::ParamsTag,
meta_handler::{PageData, ParamsPage},
meta_handler::{into_response, PageData, ParamsPage, ValidatedForm},
user::Role,
Claim, Feed, FormPost, Item, SiteConfig,
};
Expand All @@ -14,12 +14,10 @@ use crate::{
use axum::{
extract::Query,
response::{IntoResponse, Redirect},
Form,
};
use axum_extra::{headers::Cookie, TypedHeader};
use axum_garde::WithValidation;
use bincode::config::standard;
use rinja_axum::{into_response, Template};
use rinja::Template;
use serde::Deserialize;
use snailquote::unescape;

Expand Down Expand Up @@ -350,15 +348,15 @@ pub(crate) async fn admin(
/// `POST /admin`
pub(crate) async fn admin_post(
cookie: Option<TypedHeader<Cookie>>,
WithValidation(input): WithValidation<Form<SiteConfig>>,
ValidatedForm(input): ValidatedForm<SiteConfig>,
) -> Result<impl IntoResponse, AppError> {
let cookie = cookie.ok_or(AppError::NonLogin)?;
let claim = Claim::get(&DB, &cookie, &input).ok_or(AppError::NonLogin)?;
if Role::from(claim.role) != Role::Admin {
return Err(AppError::Unauthorized);
}

let mut site_config = input.into_inner();
let mut site_config = input;
site_config.spam_regex = match site_config.spam_regex {
Some(s) if !s.is_empty() => {
if let Err(e) = regex::Regex::new(&s) {
Expand Down
14 changes: 7 additions & 7 deletions src/controller/feed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::{
},
fmt::{clean_html, ts_to_date},
inn::inn_add_index,
meta_handler::{get_referer, PageData, ParamsPage},
meta_handler::{get_referer, into_response, PageData, ParamsPage},
Claim, Inn, Post, PostContent, PostStatus, SiteConfig, User,
};
use crate::{
Expand All @@ -24,10 +24,9 @@ use axum_extra::{
TypedHeader,
};
use cached::proc_macro::cached;
use garde::Validate;
use jiff::{fmt::rfc2822, Timestamp};
use reqwest::Client;
use rinja_axum::{into_response, Template};
use rinja::Template;
use serde::Deserialize;
use sled::Db;
use std::{collections::HashSet, time::Duration};
Expand All @@ -36,6 +35,7 @@ use std::{
sync::LazyLock,
};
use tracing::{error, warn};
use validator::Validate;

struct SourceItem {
link: String,
Expand Down Expand Up @@ -477,13 +477,13 @@ pub(crate) async fn feed_add(
/// Form data: `/feed/add`
#[derive(Deserialize, Validate)]
pub(crate) struct FormFeedAdd {
#[garde(length(max = 256))]
#[validate(length(max = 256))]
url: String,
#[garde(length(max = 256))]
#[validate(length(max = 256))]
folder: String,
#[garde(length(max = 256))]
#[validate(length(max = 256))]
new_folder: String,
#[garde(skip)]
#[validate(skip)]
is_public: bool,
}

Expand Down
37 changes: 18 additions & 19 deletions src/controller/inn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::{
feed::{inn_feed_to_post, update},
fmt::{clean_html, md2html, ts_to_date},
incr_id,
meta_handler::{PageData, ParamsPage},
meta_handler::{into_response, PageData, ParamsPage, ValidatedForm},
notification::{add_notification, mark_read, NtType},
user::{InnRole, Role},
Claim, Comment, Feed, FormPost, Inn, InnType, Post, PostContent, PostStatus, SiteConfig, User,
Expand All @@ -33,17 +33,18 @@ use axum::{
Form,
};
use axum_extra::{headers::Cookie, TypedHeader};
use axum_garde::WithValidation;
use bincode::config::standard;
use cached::proc_macro::cached;
use garde::Validate;
use jiff::Timestamp;
use rinja::filters::{escape, Html};
use rinja_axum::{into_response, Template};
use rinja::{
filters::{escape, Html},
Template,
};
use serde::Deserialize;
use sled::{transaction::ConflictableTransactionError, Transactional};
use sled::{Batch, Db};
use std::collections::{BTreeSet, HashMap, HashSet};
use validator::Validate;

/// Page data: `inn_create.html`
#[derive(Template)]
Expand Down Expand Up @@ -115,19 +116,19 @@ pub(crate) async fn mod_inn(
/// Form data: `/mod/:iid` inn create/edit page
#[derive(Deserialize, Validate)]
pub(crate) struct FormInn {
#[garde(length(min = 1, max = 64))]
#[validate(length(min = 1, max = 64))]
inn_name: String,
#[garde(length(min = 1, max = 512))]
#[validate(length(min = 1, max = 512))]
about: String,
#[garde(length(min = 1, max = 65535))]
#[validate(length(min = 1, max = 65535))]
description: String,
#[garde(length(min = 1, max = 128))]
#[validate(length(min = 1, max = 128))]
topics: String,
#[garde(skip)]
#[validate(skip)]
inn_type: u8,
#[garde(skip)]
#[validate(skip)]
early_birds: u32,
#[garde(skip)]
#[validate(skip)]
limit_edit_seconds: u32,
}

Expand All @@ -137,7 +138,7 @@ pub(crate) struct FormInn {
pub(crate) async fn mod_inn_post(
cookie: Option<TypedHeader<Cookie>>,
Path(mut iid): Path<u32>,
WithValidation(input): WithValidation<Form<FormInn>>,
ValidatedForm(input): ValidatedForm<FormInn>,
) -> Result<impl IntoResponse, AppError> {
let inn_name = clean_html(&input.inn_name);
if !is_valid_name(&inn_name) {
Expand Down Expand Up @@ -650,12 +651,11 @@ fn inn_rm_index(db: &Db, iid: u32, pid: u32) -> Result<u8, AppError> {
pub(crate) async fn edit_post_post(
cookie: Option<TypedHeader<Cookie>>,
Path(old_pid): Path<u32>,
WithValidation(input): WithValidation<Form<FormPost>>,
ValidatedForm(input): ValidatedForm<FormPost>,
) -> Result<impl IntoResponse, AppError> {
let cookie = cookie.ok_or(AppError::NonLogin)?;
let site_config = SiteConfig::get(&DB)?;
let claim = Claim::get(&DB, &cookie, &site_config).ok_or(AppError::NonLogin)?;
let input = input.into_inner();

let is_draft = input.is_draft.unwrap_or_default();
let delete_draft = input.delete_draft.unwrap_or_default();
Expand Down Expand Up @@ -1746,21 +1746,20 @@ pub(crate) async fn post(
/// Form data: `/inn/:iid/:pid/` comment create
#[derive(Deserialize, Validate)]
pub(crate) struct FormComment {
#[garde(length(min = 1, max = 10000))]
#[validate(length(min = 1, max = 10000))]
content: String,
}

/// `POST /post/:iid/:pid/` comment create
pub(crate) async fn comment_post(
cookie: Option<TypedHeader<Cookie>>,
Path((iid, pid)): Path<(u32, u32)>,
WithValidation(input): WithValidation<Form<FormComment>>,
ValidatedForm(input): ValidatedForm<FormComment>,
) -> Result<impl IntoResponse, AppError> {
let site_config = SiteConfig::get(&DB)?;
let claim = cookie
.and_then(|cookie| Claim::get(&DB, &cookie, &site_config))
.ok_or(AppError::NonLogin)?;
let input = input.into_inner();

if let Some(spam_regex) = &site_config.spam_regex {
let re = regex::Regex::new(spam_regex).unwrap();
Expand Down Expand Up @@ -1896,7 +1895,7 @@ struct PagePreview<'a> {

/// `POST /preview`
pub(crate) async fn preview(
WithValidation(input): WithValidation<Form<FormComment>>,
ValidatedForm(input): ValidatedForm<FormComment>,
) -> Result<impl IntoResponse, AppError> {
let site_config = SiteConfig::get(&DB)?;
let page_data = PageData::new("preview", &site_config, None, false);
Expand Down
4 changes: 2 additions & 2 deletions src/controller/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use axum::{
Form,
};
use axum_extra::{headers::Cookie, TypedHeader};
use rinja_axum::{into_response, Template};
use rinja::Template;
use serde::Deserialize;

use crate::controller::filters;
use crate::{controller::fmt::clean_html, error::AppError, DB};

use super::{
db_utils::{get_one, incr_id, u32_to_ivec, u8_slice_to_u32},
meta_handler::PageData,
meta_handler::{into_response, PageData},
notification::{add_notification, mark_read, NtType},
Claim, SiteConfig, User,
};
Expand Down
Loading

0 comments on commit 422cffa

Please sign in to comment.