Sanitize html (#3708)
* HTML sanitization in apub code * Sanitize API inputs * fmt * Dont allow html a, img tags --------- Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
parent
2de994797e
commit
3471f3533c
41 changed files with 339 additions and 151 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -386,6 +386,19 @@ dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ammonia"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64e6d1c7838db705c9b756557ee27c384ce695a1c51a6fe528784cb1c6840170"
|
||||||
|
dependencies = [
|
||||||
|
"html5ever 0.26.0",
|
||||||
|
"maplit",
|
||||||
|
"once_cell",
|
||||||
|
"tendril",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -2574,6 +2587,7 @@ version = "0.18.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitypub_federation",
|
"activitypub_federation",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"encoding",
|
"encoding",
|
||||||
|
@ -2988,6 +3002,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maplit"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markdown-it"
|
name = "markdown-it"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {
|
||||||
resolveCommunity,
|
resolveCommunity,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
import { PostView } from "lemmy-js-client/dist/types/PostView";
|
import { PostView } from "lemmy-js-client/dist/types/PostView";
|
||||||
|
import { CreatePost } from "lemmy-js-client/dist/types/CreatePost";
|
||||||
|
|
||||||
let betaCommunity: CommunityView | undefined;
|
let betaCommunity: CommunityView | undefined;
|
||||||
|
|
||||||
|
@ -504,3 +505,21 @@ test("Report a post", async () => {
|
||||||
expect(betaReport.original_post_body).toBe(alphaReport.original_post_body);
|
expect(betaReport.original_post_body).toBe(alphaReport.original_post_body);
|
||||||
expect(betaReport.reason).toBe(alphaReport.reason);
|
expect(betaReport.reason).toBe(alphaReport.reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Sanitize HTML", async () => {
|
||||||
|
let betaCommunity = (await resolveBetaCommunity(beta)).community;
|
||||||
|
if (!betaCommunity) {
|
||||||
|
throw "Missing beta community";
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = randomString(5);
|
||||||
|
let body = "<script>alert('xss');</script> hello";
|
||||||
|
let form: CreatePost = {
|
||||||
|
name,
|
||||||
|
body,
|
||||||
|
auth: beta.auth,
|
||||||
|
community_id: betaCommunity.community.id,
|
||||||
|
};
|
||||||
|
let post = await beta.client.createPost(form);
|
||||||
|
expect(post.post_view.post.body).toBe(" hello");
|
||||||
|
});
|
||||||
|
|
|
@ -3,7 +3,12 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
comment::{CommentReportResponse, CreateCommentReport},
|
comment::{CommentReportResponse, CreateCommentReport},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{check_community_ban, local_user_view_from_jwt, send_new_report_email_to_admins},
|
utils::{
|
||||||
|
check_community_ban,
|
||||||
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html,
|
||||||
|
send_new_report_email_to_admins,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -29,8 +34,8 @@ impl Perform for CreateCommentReport {
|
||||||
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let reason = self.reason.trim();
|
let reason = sanitize_html(self.reason.trim());
|
||||||
check_report_reason(reason, &local_site)?;
|
check_report_reason(&reason, &local_site)?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
|
@ -42,7 +47,7 @@ impl Perform for CreateCommentReport {
|
||||||
creator_id: person_id,
|
creator_id: person_id,
|
||||||
comment_id,
|
comment_id,
|
||||||
original_comment_text: comment_view.comment.content,
|
original_comment_text: comment_view.comment.content,
|
||||||
reason: reason.to_owned(),
|
reason,
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = CommentReport::report(&mut context.pool(), &report_form)
|
let report = CommentReport::report(&mut context.pool(), &report_form)
|
||||||
|
|
|
@ -3,7 +3,12 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
community::{BanFromCommunity, BanFromCommunityResponse},
|
community::{BanFromCommunity, BanFromCommunityResponse},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{is_mod_or_admin, local_user_view_from_jwt, remove_user_data_in_community},
|
utils::{
|
||||||
|
is_mod_or_admin,
|
||||||
|
local_user_view_from_jwt,
|
||||||
|
remove_user_data_in_community,
|
||||||
|
sanitize_html_opt,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -81,7 +86,7 @@ impl Perform for BanFromCommunity {
|
||||||
mod_person_id: local_user_view.person.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_person_id: data.person_id,
|
other_person_id: data.person_id,
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
reason: data.reason.clone(),
|
reason: sanitize_html_opt(&data.reason),
|
||||||
banned: Some(data.ban),
|
banned: Some(data.ban),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
||||||
build_response::build_community_response,
|
build_response::build_community_response,
|
||||||
community::{CommunityResponse, HideCommunity},
|
community::{CommunityResponse, HideCommunity},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{is_admin, local_user_view_from_jwt},
|
utils::{is_admin, local_user_view_from_jwt, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -34,7 +34,7 @@ impl Perform for HideCommunity {
|
||||||
let mod_hide_community_form = ModHideCommunityForm {
|
let mod_hide_community_form = ModHideCommunityForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
mod_person_id: local_user_view.person.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
reason: data.reason.clone(),
|
reason: sanitize_html_opt(&data.reason),
|
||||||
hidden: Some(data.hidden),
|
hidden: Some(data.hidden),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> Result<String, LemmyEr
|
||||||
Ok(base64.encode(output_buffer.into_inner()))
|
Ok(base64.encode(output_buffer.into_inner()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check size of report and remove whitespace
|
/// Check size of report
|
||||||
pub(crate) fn check_report_reason(reason: &str, local_site: &LocalSite) -> Result<(), LemmyError> {
|
pub(crate) fn check_report_reason(reason: &str, local_site: &LocalSite) -> Result<(), LemmyError> {
|
||||||
let slur_regex = &local_site_to_slur_regex(local_site);
|
let slur_regex = &local_site_to_slur_regex(local_site);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
person::{BanPerson, BanPersonResponse},
|
person::{BanPerson, BanPersonResponse},
|
||||||
utils::{is_admin, local_user_view_from_jwt, remove_user_data},
|
utils::{is_admin, local_user_view_from_jwt, remove_user_data, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -63,7 +63,7 @@ impl Perform for BanPerson {
|
||||||
let form = ModBanForm {
|
let form = ModBanForm {
|
||||||
mod_person_id: local_user_view.person.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_person_id: data.person_id,
|
other_person_id: data.person_id,
|
||||||
reason: data.reason.clone(),
|
reason: sanitize_html_opt(&data.reason),
|
||||||
banned: Some(data.ban),
|
banned: Some(data.ban),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
person::{LoginResponse, SaveUserSettings},
|
person::{LoginResponse, SaveUserSettings},
|
||||||
utils::{local_user_view_from_jwt, send_verification_email},
|
utils::{local_user_view_from_jwt, sanitize_html_opt, send_verification_email},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -37,13 +37,16 @@ impl Perform for SaveUserSettings {
|
||||||
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
||||||
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
||||||
|
|
||||||
|
let bio = sanitize_html_opt(&data.bio);
|
||||||
|
let display_name = sanitize_html_opt(&data.display_name);
|
||||||
|
|
||||||
let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
|
let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
|
||||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
let bio = diesel_option_overwrite(&data.bio);
|
let bio = diesel_option_overwrite(bio);
|
||||||
let display_name = diesel_option_overwrite(&data.display_name);
|
let display_name = diesel_option_overwrite(display_name);
|
||||||
let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id);
|
let matrix_user_id = diesel_option_overwrite(data.matrix_user_id.clone());
|
||||||
let email_deref = data.email.as_deref().map(str::to_lowercase);
|
let email_deref = data.email.as_deref().map(str::to_lowercase);
|
||||||
let email = diesel_option_overwrite(&email_deref);
|
let email = diesel_option_overwrite(email_deref.clone());
|
||||||
|
|
||||||
if let Some(Some(email)) = &email {
|
if let Some(Some(email)) = &email {
|
||||||
let previous_email = local_user_view.local_user.email.clone().unwrap_or_default();
|
let previous_email = local_user_view.local_user.email.clone().unwrap_or_default();
|
||||||
|
@ -85,6 +88,7 @@ impl Perform for SaveUserSettings {
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
let default_listing_type = data.default_listing_type;
|
let default_listing_type = data.default_listing_type;
|
||||||
let default_sort_type = data.default_sort_type;
|
let default_sort_type = data.default_sort_type;
|
||||||
|
let theme = sanitize_html_opt(&data.theme);
|
||||||
|
|
||||||
let person_form = PersonUpdateForm::builder()
|
let person_form = PersonUpdateForm::builder()
|
||||||
.display_name(display_name)
|
.display_name(display_name)
|
||||||
|
@ -130,7 +134,7 @@ impl Perform for SaveUserSettings {
|
||||||
.show_scores(data.show_scores)
|
.show_scores(data.show_scores)
|
||||||
.default_sort_type(default_sort_type)
|
.default_sort_type(default_sort_type)
|
||||||
.default_listing_type(default_listing_type)
|
.default_listing_type(default_listing_type)
|
||||||
.theme(data.theme.clone())
|
.theme(theme)
|
||||||
.interface_language(data.interface_language.clone())
|
.interface_language(data.interface_language.clone())
|
||||||
.totp_2fa_secret(totp_2fa_secret)
|
.totp_2fa_secret(totp_2fa_secret)
|
||||||
.totp_2fa_url(totp_2fa_url)
|
.totp_2fa_url(totp_2fa_url)
|
||||||
|
|
|
@ -3,7 +3,12 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
post::{CreatePostReport, PostReportResponse},
|
post::{CreatePostReport, PostReportResponse},
|
||||||
utils::{check_community_ban, local_user_view_from_jwt, send_new_report_email_to_admins},
|
utils::{
|
||||||
|
check_community_ban,
|
||||||
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html,
|
||||||
|
send_new_report_email_to_admins,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -26,8 +31,8 @@ impl Perform for CreatePostReport {
|
||||||
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let reason = self.reason.trim();
|
let reason = sanitize_html(self.reason.trim());
|
||||||
check_report_reason(reason, &local_site)?;
|
check_report_reason(&reason, &local_site)?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
@ -41,7 +46,7 @@ impl Perform for CreatePostReport {
|
||||||
original_post_name: post_view.post.name,
|
original_post_name: post_view.post.name,
|
||||||
original_post_url: post_view.post.url,
|
original_post_url: post_view.post.url,
|
||||||
original_post_body: post_view.post.body,
|
original_post_body: post_view.post.body,
|
||||||
reason: reason.to_owned(),
|
reason,
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = PostReport::report(&mut context.pool(), &report_form)
|
let report = PostReport::report(&mut context.pool(), &report_form)
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
|
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
|
||||||
utils::{local_user_view_from_jwt, send_new_report_email_to_admins},
|
utils::{local_user_view_from_jwt, sanitize_html, send_new_report_email_to_admins},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -25,8 +25,8 @@ impl Perform for CreatePrivateMessageReport {
|
||||||
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?;
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let reason = self.reason.trim();
|
let reason = sanitize_html(self.reason.trim());
|
||||||
check_report_reason(reason, &local_site)?;
|
check_report_reason(&reason, &local_site)?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
let private_message_id = self.private_message_id;
|
let private_message_id = self.private_message_id;
|
||||||
|
@ -36,7 +36,7 @@ impl Perform for CreatePrivateMessageReport {
|
||||||
creator_id: person_id,
|
creator_id: person_id,
|
||||||
private_message_id,
|
private_message_id,
|
||||||
original_pm_text: private_message.content,
|
original_pm_text: private_message.content,
|
||||||
reason: reason.to_owned(),
|
reason: reason.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = PrivateMessageReport::report(&mut context.pool(), &report_form)
|
let report = PrivateMessageReport::report(&mut context.pool(), &report_form)
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{PurgeComment, PurgeItemResponse},
|
site::{PurgeComment, PurgeItemResponse},
|
||||||
utils::{is_admin, local_user_view_from_jwt},
|
utils::{is_admin, local_user_view_from_jwt, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -38,7 +38,7 @@ impl Perform for PurgeComment {
|
||||||
Comment::delete(&mut context.pool(), comment_id).await?;
|
Comment::delete(&mut context.pool(), comment_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = data.reason.clone();
|
let reason = sanitize_html_opt(&data.reason);
|
||||||
let form = AdminPurgeCommentForm {
|
let form = AdminPurgeCommentForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::purge_image_from_pictrs,
|
request::purge_image_from_pictrs,
|
||||||
site::{PurgeCommunity, PurgeItemResponse},
|
site::{PurgeCommunity, PurgeItemResponse},
|
||||||
utils::{is_admin, local_user_view_from_jwt, purge_image_posts_for_community},
|
utils::{is_admin, local_user_view_from_jwt, purge_image_posts_for_community, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -55,7 +55,7 @@ impl Perform for PurgeCommunity {
|
||||||
Community::delete(&mut context.pool(), community_id).await?;
|
Community::delete(&mut context.pool(), community_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = data.reason.clone();
|
let reason = sanitize_html_opt(&data.reason);
|
||||||
let form = AdminPurgeCommunityForm {
|
let form = AdminPurgeCommunityForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::purge_image_from_pictrs,
|
request::purge_image_from_pictrs,
|
||||||
site::{PurgeItemResponse, PurgePerson},
|
site::{PurgeItemResponse, PurgePerson},
|
||||||
utils::{is_admin, local_user_view_from_jwt, purge_image_posts_for_person},
|
utils::{is_admin, local_user_view_from_jwt, purge_image_posts_for_person, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -54,7 +54,7 @@ impl Perform for PurgePerson {
|
||||||
Person::delete(&mut context.pool(), person_id).await?;
|
Person::delete(&mut context.pool(), person_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = data.reason.clone();
|
let reason = sanitize_html_opt(&data.reason);
|
||||||
let form = AdminPurgePersonForm {
|
let form = AdminPurgePersonForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::purge_image_from_pictrs,
|
request::purge_image_from_pictrs,
|
||||||
site::{PurgeItemResponse, PurgePost},
|
site::{PurgeItemResponse, PurgePost},
|
||||||
utils::{is_admin, local_user_view_from_jwt},
|
utils::{is_admin, local_user_view_from_jwt, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -50,7 +50,7 @@ impl Perform for PurgePost {
|
||||||
Post::delete(&mut context.pool(), post_id).await?;
|
Post::delete(&mut context.pool(), post_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = data.reason.clone();
|
let reason = sanitize_html_opt(&data.reason);
|
||||||
let form = AdminPurgePostForm {
|
let form = AdminPurgePostForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason,
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl Perform for ApproveRegistrationApplication {
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
// Update the registration with reason, admin_id
|
// Update the registration with reason, admin_id
|
||||||
let deny_reason = diesel_option_overwrite(&data.deny_reason);
|
let deny_reason = diesel_option_overwrite(data.deny_reason.clone());
|
||||||
let app_form = RegistrationApplicationUpdateForm {
|
let app_form = RegistrationApplicationUpdateForm {
|
||||||
admin_id: Some(Some(local_user_view.person.id)),
|
admin_id: Some(Some(local_user_view.person.id)),
|
||||||
deny_reason,
|
deny_reason,
|
||||||
|
|
|
@ -34,6 +34,7 @@ full = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"futures",
|
"futures",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"ammonia",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -66,3 +67,4 @@ once_cell = { workspace = true, optional = true }
|
||||||
actix-web = { workspace = true, optional = true }
|
actix-web = { workspace = true, optional = true }
|
||||||
# necessary for wasmt compilation
|
# necessary for wasmt compilation
|
||||||
getrandom = { version = "0.2.10", features = ["js"] }
|
getrandom = { version = "0.2.10", features = ["js"] }
|
||||||
|
ammonia = { version = "3.3.0", optional = true }
|
||||||
|
|
|
@ -729,31 +729,6 @@ pub async fn delete_user_account(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::utils::{honeypot_check, password_length_check};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn password_length() {
|
|
||||||
assert!(password_length_check("Õ¼¾°3yË,o¸ãtÌÈú|ÇÁÙAøüÒI©·¤(T]/ð>æºWæ[C¤bªWöaÃÎñ·{=û³&§½K/c").is_ok());
|
|
||||||
assert!(password_length_check("1234567890").is_ok());
|
|
||||||
assert!(password_length_check("short").is_err());
|
|
||||||
assert!(password_length_check("looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn honeypot() {
|
|
||||||
assert!(honeypot_check(&None).is_ok());
|
|
||||||
assert!(honeypot_check(&Some(String::new())).is_ok());
|
|
||||||
assert!(honeypot_check(&Some("1".to_string())).is_err());
|
|
||||||
assert!(honeypot_check(&Some("message".to_string())).is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum EndpointType {
|
pub enum EndpointType {
|
||||||
Community,
|
Community,
|
||||||
Person,
|
Person,
|
||||||
|
@ -819,3 +794,49 @@ pub fn generate_featured_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||||
pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
||||||
Ok(Url::parse(&format!("{community_id}/moderators"))?.into())
|
Ok(Url::parse(&format!("{community_id}/moderators"))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sanitize HTML with default options. Additionally, dont allow bypassing markdown
|
||||||
|
/// links and images
|
||||||
|
pub fn sanitize_html(data: &str) -> String {
|
||||||
|
ammonia::Builder::default()
|
||||||
|
.rm_tags(&["a", "img"])
|
||||||
|
.clean(data)
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sanitize_html_opt(data: &Option<String>) -> Option<String> {
|
||||||
|
data.as_ref().map(|d| sanitize_html(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
#![allow(clippy::indexing_slicing)]
|
||||||
|
|
||||||
|
use crate::utils::{honeypot_check, password_length_check, sanitize_html};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn password_length() {
|
||||||
|
assert!(password_length_check("Õ¼¾°3yË,o¸ãtÌÈú|ÇÁÙAøüÒI©·¤(T]/ð>æºWæ[C¤bªWöaÃÎñ·{=û³&§½K/c").is_ok());
|
||||||
|
assert!(password_length_check("1234567890").is_ok());
|
||||||
|
assert!(password_length_check("short").is_err());
|
||||||
|
assert!(password_length_check("looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn honeypot() {
|
||||||
|
assert!(honeypot_check(&None).is_ok());
|
||||||
|
assert!(honeypot_check(&Some(String::new())).is_ok());
|
||||||
|
assert!(honeypot_check(&Some("1".to_string())).is_err());
|
||||||
|
assert!(honeypot_check(&Some("message".to_string())).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sanitize_html() {
|
||||||
|
let sanitized = sanitize_html("<script>alert(1);</script> hello");
|
||||||
|
assert_eq!(sanitized, " hello");
|
||||||
|
let sanitized = sanitize_html("<img src='http://example.com'> test");
|
||||||
|
assert_eq!(sanitized, " test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use lemmy_api_common::{
|
||||||
get_post,
|
get_post,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
local_user_view_from_jwt,
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -47,11 +48,12 @@ impl PerformCrud for CreateComment {
|
||||||
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let content_slurs_removed = remove_slurs(
|
let content = remove_slurs(
|
||||||
&data.content.clone(),
|
&data.content.clone(),
|
||||||
&local_site_to_slur_regex(&local_site),
|
&local_site_to_slur_regex(&local_site),
|
||||||
);
|
);
|
||||||
is_valid_body_field(&Some(content_slurs_removed.clone()), false)?;
|
is_valid_body_field(&Some(content.clone()), false)?;
|
||||||
|
let content = sanitize_html(&content);
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
@ -104,7 +106,7 @@ impl PerformCrud for CreateComment {
|
||||||
};
|
};
|
||||||
|
|
||||||
let comment_form = CommentInsertForm::builder()
|
let comment_form = CommentInsertForm::builder()
|
||||||
.content(content_slurs_removed.clone())
|
.content(content.clone())
|
||||||
.post_id(data.post_id)
|
.post_id(data.post_id)
|
||||||
.creator_id(local_user_view.person.id)
|
.creator_id(local_user_view.person.id)
|
||||||
.language_id(language_id)
|
.language_id(language_id)
|
||||||
|
@ -135,7 +137,7 @@ impl PerformCrud for CreateComment {
|
||||||
.with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
|
.with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
|
||||||
|
|
||||||
// Scan the comment for user mentions, add those rows
|
// Scan the comment for user mentions, add those rows
|
||||||
let mentions = scrape_text_for_mentions(&content_slurs_removed);
|
let mentions = scrape_text_for_mentions(&content);
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
&updated_comment,
|
&updated_comment,
|
||||||
|
|
|
@ -4,7 +4,12 @@ use lemmy_api_common::{
|
||||||
build_response::{build_comment_response, send_local_notifs},
|
build_response::{build_comment_response, send_local_notifs},
|
||||||
comment::{CommentResponse, EditComment},
|
comment::{CommentResponse, EditComment},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{check_community_ban, local_site_to_slur_regex, local_user_view_from_jwt},
|
utils::{
|
||||||
|
check_community_ban,
|
||||||
|
local_site_to_slur_regex,
|
||||||
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html_opt,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -59,16 +64,16 @@ impl PerformCrud for EditComment {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Update the Content
|
// Update the Content
|
||||||
let content_slurs_removed = data
|
let content = data
|
||||||
.content
|
.content
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|c| remove_slurs(c, &local_site_to_slur_regex(&local_site)));
|
.map(|c| remove_slurs(c, &local_site_to_slur_regex(&local_site)));
|
||||||
|
is_valid_body_field(&content, false)?;
|
||||||
is_valid_body_field(&content_slurs_removed, false)?;
|
let content = sanitize_html_opt(&content);
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let form = CommentUpdateForm::builder()
|
let form = CommentUpdateForm::builder()
|
||||||
.content(content_slurs_removed)
|
.content(content)
|
||||||
.language_id(data.language_id)
|
.language_id(data.language_id)
|
||||||
.updated(Some(Some(naive_now())))
|
.updated(Some(Some(naive_now())))
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -13,6 +13,8 @@ use lemmy_api_common::{
|
||||||
is_admin,
|
is_admin,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
local_user_view_from_jwt,
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html,
|
||||||
|
sanitize_html_opt,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -59,10 +61,14 @@ impl PerformCrud for CreateCommunity {
|
||||||
let icon = diesel_option_overwrite_to_url_create(&data.icon)?;
|
let icon = diesel_option_overwrite_to_url_create(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite_to_url_create(&data.banner)?;
|
let banner = diesel_option_overwrite_to_url_create(&data.banner)?;
|
||||||
|
|
||||||
|
let name = sanitize_html(&data.name);
|
||||||
|
let title = sanitize_html(&data.title);
|
||||||
|
let description = sanitize_html_opt(&data.description);
|
||||||
|
|
||||||
let slur_regex = local_site_to_slur_regex(&local_site);
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
check_slurs(&data.name, &slur_regex)?;
|
check_slurs(&name, &slur_regex)?;
|
||||||
check_slurs(&data.title, &slur_regex)?;
|
check_slurs(&title, &slur_regex)?;
|
||||||
check_slurs_opt(&data.description, &slur_regex)?;
|
check_slurs_opt(&description, &slur_regex)?;
|
||||||
|
|
||||||
is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
|
is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
|
||||||
is_valid_body_field(&data.description, false)?;
|
is_valid_body_field(&data.description, false)?;
|
||||||
|
@ -83,9 +89,9 @@ impl PerformCrud for CreateCommunity {
|
||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
|
|
||||||
let community_form = CommunityInsertForm::builder()
|
let community_form = CommunityInsertForm::builder()
|
||||||
.name(data.name.clone())
|
.name(name)
|
||||||
.title(data.title.clone())
|
.title(title)
|
||||||
.description(data.description.clone())
|
.description(description)
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
.banner(banner)
|
.banner(banner)
|
||||||
.nsfw(data.nsfw)
|
.nsfw(data.nsfw)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
||||||
build_response::build_community_response,
|
build_response::build_community_response,
|
||||||
community::{CommunityResponse, EditCommunity},
|
community::{CommunityResponse, EditCommunity},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{local_site_to_slur_regex, local_user_view_from_jwt},
|
utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::PersonId,
|
newtypes::PersonId,
|
||||||
|
@ -32,15 +32,18 @@ impl PerformCrud for EditCommunity {
|
||||||
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
|
||||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
|
||||||
let description = diesel_option_overwrite(&data.description);
|
|
||||||
|
|
||||||
let slur_regex = local_site_to_slur_regex(&local_site);
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
check_slurs_opt(&data.title, &slur_regex)?;
|
check_slurs_opt(&data.title, &slur_regex)?;
|
||||||
check_slurs_opt(&data.description, &slur_regex)?;
|
check_slurs_opt(&data.description, &slur_regex)?;
|
||||||
is_valid_body_field(&data.description, false)?;
|
is_valid_body_field(&data.description, false)?;
|
||||||
|
|
||||||
|
let title = sanitize_html_opt(&data.title);
|
||||||
|
let description = sanitize_html_opt(&data.description);
|
||||||
|
|
||||||
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
let description = diesel_option_overwrite(description);
|
||||||
|
|
||||||
// Verify its a mod (only mods can edit it)
|
// Verify its a mod (only mods can edit it)
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let mods: Vec<PersonId> =
|
let mods: Vec<PersonId> =
|
||||||
|
@ -64,7 +67,7 @@ impl PerformCrud for EditCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
let community_form = CommunityUpdateForm::builder()
|
let community_form = CommunityUpdateForm::builder()
|
||||||
.title(data.title.clone())
|
.title(title)
|
||||||
.description(description)
|
.description(description)
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
.banner(banner)
|
.banner(banner)
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
|
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
|
||||||
utils::{is_admin, local_user_view_from_jwt},
|
utils::{is_admin, local_user_view_from_jwt, sanitize_html},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiInsertForm},
|
custom_emoji::{CustomEmoji, CustomEmojiInsertForm},
|
||||||
|
@ -26,11 +26,15 @@ impl PerformCrud for CreateCustomEmoji {
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let shortcode = sanitize_html(data.shortcode.to_lowercase().trim());
|
||||||
|
let alt_text = sanitize_html(&data.alt_text);
|
||||||
|
let category = sanitize_html(&data.category);
|
||||||
|
|
||||||
let emoji_form = CustomEmojiInsertForm::builder()
|
let emoji_form = CustomEmojiInsertForm::builder()
|
||||||
.local_site_id(local_site.id)
|
.local_site_id(local_site.id)
|
||||||
.shortcode(data.shortcode.to_lowercase().trim().to_string())
|
.shortcode(shortcode)
|
||||||
.alt_text(data.alt_text.to_string())
|
.alt_text(alt_text)
|
||||||
.category(data.category.to_string())
|
.category(category)
|
||||||
.image_url(data.clone().image_url.into())
|
.image_url(data.clone().image_url.into())
|
||||||
.build();
|
.build();
|
||||||
let emoji = CustomEmoji::create(&mut context.pool(), &emoji_form).await?;
|
let emoji = CustomEmoji::create(&mut context.pool(), &emoji_form).await?;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
|
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
|
||||||
utils::{is_admin, local_user_view_from_jwt},
|
utils::{is_admin, local_user_view_from_jwt, sanitize_html},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiUpdateForm},
|
custom_emoji::{CustomEmoji, CustomEmojiUpdateForm},
|
||||||
|
@ -26,10 +26,13 @@ impl PerformCrud for EditCustomEmoji {
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let alt_text = sanitize_html(&data.alt_text);
|
||||||
|
let category = sanitize_html(&data.category);
|
||||||
|
|
||||||
let emoji_form = CustomEmojiUpdateForm::builder()
|
let emoji_form = CustomEmojiUpdateForm::builder()
|
||||||
.local_site_id(local_site.id)
|
.local_site_id(local_site.id)
|
||||||
.alt_text(data.alt_text.to_string())
|
.alt_text(alt_text)
|
||||||
.category(data.category.to_string())
|
.category(category)
|
||||||
.image_url(data.clone().image_url.into())
|
.image_url(data.clone().image_url.into())
|
||||||
.build();
|
.build();
|
||||||
let emoji = CustomEmoji::update(&mut context.pool(), data.id, &emoji_form).await?;
|
let emoji = CustomEmoji::update(&mut context.pool(), data.id, &emoji_form).await?;
|
||||||
|
|
|
@ -14,6 +14,8 @@ use lemmy_api_common::{
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
local_user_view_from_jwt,
|
local_user_view_from_jwt,
|
||||||
mark_post_as_read,
|
mark_post_as_read,
|
||||||
|
sanitize_html,
|
||||||
|
sanitize_html_opt,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -91,6 +93,11 @@ pub async fn create_post(
|
||||||
.map(|u| (u.title, u.description, u.embed_video_url))
|
.map(|u| (u.title, u.description, u.embed_video_url))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let name = sanitize_html(data.name.trim());
|
||||||
|
let body = sanitize_html_opt(&data.body);
|
||||||
|
let embed_title = sanitize_html_opt(&embed_title);
|
||||||
|
let embed_description = sanitize_html_opt(&embed_description);
|
||||||
|
|
||||||
// Only need to check if language is allowed in case user set it explicitly. When using default
|
// Only need to check if language is allowed in case user set it explicitly. When using default
|
||||||
// language, it already only returns allowed languages.
|
// language, it already only returns allowed languages.
|
||||||
CommunityLanguage::is_allowed_community_language(
|
CommunityLanguage::is_allowed_community_language(
|
||||||
|
@ -114,9 +121,9 @@ pub async fn create_post(
|
||||||
};
|
};
|
||||||
|
|
||||||
let post_form = PostInsertForm::builder()
|
let post_form = PostInsertForm::builder()
|
||||||
.name(data.name.trim().to_owned())
|
.name(name)
|
||||||
.url(url)
|
.url(url)
|
||||||
.body(data.body.clone())
|
.body(body)
|
||||||
.community_id(data.community_id)
|
.community_id(data.community_id)
|
||||||
.creator_id(local_user_view.person.id)
|
.creator_id(local_user_view.person.id)
|
||||||
.nsfw(data.nsfw)
|
.nsfw(data.nsfw)
|
||||||
|
|
|
@ -5,7 +5,12 @@ use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
post::{EditPost, PostResponse},
|
post::{EditPost, PostResponse},
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
utils::{check_community_ban, local_site_to_slur_regex, local_user_view_from_jwt},
|
utils::{
|
||||||
|
check_community_ban,
|
||||||
|
local_site_to_slur_regex,
|
||||||
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html_opt,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -39,7 +44,6 @@ impl PerformCrud for EditPost {
|
||||||
// TODO No good way to handle a clear.
|
// TODO No good way to handle a clear.
|
||||||
// Issue link: https://github.com/LemmyNet/lemmy/issues/2287
|
// Issue link: https://github.com/LemmyNet/lemmy/issues/2287
|
||||||
let url = Some(data_url.map(clean_url_params).map(Into::into));
|
let url = Some(data_url.map(clean_url_params).map(Into::into));
|
||||||
let body = diesel_option_overwrite(&data.body);
|
|
||||||
|
|
||||||
let slur_regex = local_site_to_slur_regex(&local_site);
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
check_slurs_opt(&data.name, &slur_regex)?;
|
check_slurs_opt(&data.name, &slur_regex)?;
|
||||||
|
@ -75,6 +79,12 @@ impl PerformCrud for EditPost {
|
||||||
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
|
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let name = sanitize_html_opt(&data.name);
|
||||||
|
let body = sanitize_html_opt(&data.body);
|
||||||
|
let body = diesel_option_overwrite(body);
|
||||||
|
let embed_title = embed_title.map(|e| sanitize_html_opt(&e));
|
||||||
|
let embed_description = embed_description.map(|e| sanitize_html_opt(&e));
|
||||||
|
|
||||||
let language_id = self.language_id;
|
let language_id = self.language_id;
|
||||||
CommunityLanguage::is_allowed_community_language(
|
CommunityLanguage::is_allowed_community_language(
|
||||||
&mut context.pool(),
|
&mut context.pool(),
|
||||||
|
@ -84,7 +94,7 @@ impl PerformCrud for EditPost {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let post_form = PostUpdateForm::builder()
|
let post_form = PostUpdateForm::builder()
|
||||||
.name(data.name.clone())
|
.name(name)
|
||||||
.url(url)
|
.url(url)
|
||||||
.body(body)
|
.body(body)
|
||||||
.nsfw(data.nsfw)
|
.nsfw(data.nsfw)
|
||||||
|
|
|
@ -9,6 +9,7 @@ use lemmy_api_common::{
|
||||||
get_interface_language,
|
get_interface_language,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
local_user_view_from_jwt,
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html,
|
||||||
send_email_to_user,
|
send_email_to_user,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
|
@ -39,11 +40,9 @@ impl PerformCrud for CreatePrivateMessage {
|
||||||
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let content_slurs_removed = remove_slurs(
|
let content = sanitize_html(&data.content);
|
||||||
&data.content.clone(),
|
let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
|
||||||
&local_site_to_slur_regex(&local_site),
|
is_valid_body_field(&Some(content.clone()), false)?;
|
||||||
);
|
|
||||||
is_valid_body_field(&Some(content_slurs_removed.clone()), false)?;
|
|
||||||
|
|
||||||
check_person_block(
|
check_person_block(
|
||||||
local_user_view.person.id,
|
local_user_view.person.id,
|
||||||
|
@ -53,7 +52,7 @@ impl PerformCrud for CreatePrivateMessage {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let private_message_form = PrivateMessageInsertForm::builder()
|
let private_message_form = PrivateMessageInsertForm::builder()
|
||||||
.content(content_slurs_removed.clone())
|
.content(content.clone())
|
||||||
.creator_id(local_user_view.person.id)
|
.creator_id(local_user_view.person.id)
|
||||||
.recipient_id(data.recipient_id)
|
.recipient_id(data.recipient_id)
|
||||||
.build();
|
.build();
|
||||||
|
@ -92,7 +91,7 @@ impl PerformCrud for CreatePrivateMessage {
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
&local_recipient,
|
&local_recipient,
|
||||||
&lang.notification_private_message_subject(sender_name),
|
&lang.notification_private_message_subject(sender_name),
|
||||||
&lang.notification_private_message_body(inbox_link, &content_slurs_removed, sender_name),
|
&lang.notification_private_message_body(inbox_link, &content, sender_name),
|
||||||
context.settings(),
|
context.settings(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
private_message::{EditPrivateMessage, PrivateMessageResponse},
|
private_message::{EditPrivateMessage, PrivateMessageResponse},
|
||||||
utils::{local_site_to_slur_regex, local_user_view_from_jwt},
|
utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -41,15 +41,16 @@ impl PerformCrud for EditPrivateMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doing the update
|
// Doing the update
|
||||||
let content_slurs_removed = remove_slurs(&data.content, &local_site_to_slur_regex(&local_site));
|
let content = sanitize_html(&data.content);
|
||||||
is_valid_body_field(&Some(content_slurs_removed.clone()), false)?;
|
let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
|
||||||
|
is_valid_body_field(&Some(content.clone()), false)?;
|
||||||
|
|
||||||
let private_message_id = data.private_message_id;
|
let private_message_id = data.private_message_id;
|
||||||
PrivateMessage::update(
|
PrivateMessage::update(
|
||||||
&mut context.pool(),
|
&mut context.pool(),
|
||||||
private_message_id,
|
private_message_id,
|
||||||
&PrivateMessageUpdateForm::builder()
|
&PrivateMessageUpdateForm::builder()
|
||||||
.content(Some(content_slurs_removed))
|
.content(Some(content))
|
||||||
.updated(Some(Some(naive_now())))
|
.updated(Some(Some(naive_now())))
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,8 @@ use lemmy_api_common::{
|
||||||
is_admin,
|
is_admin,
|
||||||
local_site_rate_limit_to_rate_limit_config,
|
local_site_rate_limit_to_rate_limit_config,
|
||||||
local_user_view_from_jwt,
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html,
|
||||||
|
sanitize_html_opt,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
@ -59,10 +61,14 @@ impl PerformCrud for CreateSite {
|
||||||
let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
|
let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
|
||||||
let inbox_url = Some(generate_site_inbox_url(&actor_id)?);
|
let inbox_url = Some(generate_site_inbox_url(&actor_id)?);
|
||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
|
let name = sanitize_html(&data.name);
|
||||||
|
let sidebar = sanitize_html_opt(&data.sidebar);
|
||||||
|
let description = sanitize_html_opt(&data.description);
|
||||||
|
|
||||||
let site_form = SiteUpdateForm::builder()
|
let site_form = SiteUpdateForm::builder()
|
||||||
.name(Some(data.name.clone()))
|
.name(Some(name))
|
||||||
.sidebar(diesel_option_overwrite(&data.sidebar))
|
.sidebar(diesel_option_overwrite(sidebar))
|
||||||
.description(diesel_option_overwrite(&data.description))
|
.description(diesel_option_overwrite(description))
|
||||||
.icon(diesel_option_overwrite_to_url(&data.icon)?)
|
.icon(diesel_option_overwrite_to_url(&data.icon)?)
|
||||||
.banner(diesel_option_overwrite_to_url(&data.banner)?)
|
.banner(diesel_option_overwrite_to_url(&data.banner)?)
|
||||||
.actor_id(Some(actor_id))
|
.actor_id(Some(actor_id))
|
||||||
|
@ -76,6 +82,10 @@ impl PerformCrud for CreateSite {
|
||||||
|
|
||||||
Site::update(&mut context.pool(), site_id, &site_form).await?;
|
Site::update(&mut context.pool(), site_id, &site_form).await?;
|
||||||
|
|
||||||
|
let application_question = sanitize_html_opt(&data.application_question);
|
||||||
|
let default_theme = sanitize_html_opt(&data.default_theme);
|
||||||
|
let legal_information = sanitize_html_opt(&data.legal_information);
|
||||||
|
|
||||||
let local_site_form = LocalSiteUpdateForm::builder()
|
let local_site_form = LocalSiteUpdateForm::builder()
|
||||||
// Set the site setup to true
|
// Set the site setup to true
|
||||||
.site_setup(Some(true))
|
.site_setup(Some(true))
|
||||||
|
@ -84,15 +94,15 @@ impl PerformCrud for CreateSite {
|
||||||
.enable_nsfw(data.enable_nsfw)
|
.enable_nsfw(data.enable_nsfw)
|
||||||
.community_creation_admin_only(data.community_creation_admin_only)
|
.community_creation_admin_only(data.community_creation_admin_only)
|
||||||
.require_email_verification(data.require_email_verification)
|
.require_email_verification(data.require_email_verification)
|
||||||
.application_question(diesel_option_overwrite(&data.application_question))
|
.application_question(diesel_option_overwrite(application_question))
|
||||||
.private_instance(data.private_instance)
|
.private_instance(data.private_instance)
|
||||||
.default_theme(data.default_theme.clone())
|
.default_theme(default_theme)
|
||||||
.default_post_listing_type(data.default_post_listing_type)
|
.default_post_listing_type(data.default_post_listing_type)
|
||||||
.legal_information(diesel_option_overwrite(&data.legal_information))
|
.legal_information(diesel_option_overwrite(legal_information))
|
||||||
.application_email_admins(data.application_email_admins)
|
.application_email_admins(data.application_email_admins)
|
||||||
.hide_modlog_mod_names(data.hide_modlog_mod_names)
|
.hide_modlog_mod_names(data.hide_modlog_mod_names)
|
||||||
.updated(Some(Some(naive_now())))
|
.updated(Some(Some(naive_now())))
|
||||||
.slur_filter_regex(diesel_option_overwrite(&data.slur_filter_regex))
|
.slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone()))
|
||||||
.actor_name_max_length(data.actor_name_max_length)
|
.actor_name_max_length(data.actor_name_max_length)
|
||||||
.federation_enabled(data.federation_enabled)
|
.federation_enabled(data.federation_enabled)
|
||||||
.captcha_enabled(data.captcha_enabled)
|
.captcha_enabled(data.captcha_enabled)
|
||||||
|
|
|
@ -6,7 +6,12 @@ use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{EditSite, SiteResponse},
|
site::{EditSite, SiteResponse},
|
||||||
utils::{is_admin, local_site_rate_limit_to_rate_limit_config, local_user_view_from_jwt},
|
utils::{
|
||||||
|
is_admin,
|
||||||
|
local_site_rate_limit_to_rate_limit_config,
|
||||||
|
local_user_view_from_jwt,
|
||||||
|
sanitize_html_opt,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -59,10 +64,14 @@ impl PerformCrud for EditSite {
|
||||||
SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
|
SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let name = sanitize_html_opt(&data.name);
|
||||||
|
let sidebar = sanitize_html_opt(&data.sidebar);
|
||||||
|
let description = sanitize_html_opt(&data.description);
|
||||||
|
|
||||||
let site_form = SiteUpdateForm::builder()
|
let site_form = SiteUpdateForm::builder()
|
||||||
.name(data.name.clone())
|
.name(name)
|
||||||
.sidebar(diesel_option_overwrite(&data.sidebar))
|
.sidebar(diesel_option_overwrite(sidebar))
|
||||||
.description(diesel_option_overwrite(&data.description))
|
.description(diesel_option_overwrite(description))
|
||||||
.icon(diesel_option_overwrite_to_url(&data.icon)?)
|
.icon(diesel_option_overwrite_to_url(&data.icon)?)
|
||||||
.banner(diesel_option_overwrite_to_url(&data.banner)?)
|
.banner(diesel_option_overwrite_to_url(&data.banner)?)
|
||||||
.updated(Some(Some(naive_now())))
|
.updated(Some(Some(naive_now())))
|
||||||
|
@ -74,21 +83,25 @@ impl PerformCrud for EditSite {
|
||||||
// Diesel will throw an error for empty update forms
|
// Diesel will throw an error for empty update forms
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
let application_question = sanitize_html_opt(&data.application_question);
|
||||||
|
let default_theme = sanitize_html_opt(&data.default_theme);
|
||||||
|
let legal_information = sanitize_html_opt(&data.legal_information);
|
||||||
|
|
||||||
let local_site_form = LocalSiteUpdateForm::builder()
|
let local_site_form = LocalSiteUpdateForm::builder()
|
||||||
.enable_downvotes(data.enable_downvotes)
|
.enable_downvotes(data.enable_downvotes)
|
||||||
.registration_mode(data.registration_mode)
|
.registration_mode(data.registration_mode)
|
||||||
.enable_nsfw(data.enable_nsfw)
|
.enable_nsfw(data.enable_nsfw)
|
||||||
.community_creation_admin_only(data.community_creation_admin_only)
|
.community_creation_admin_only(data.community_creation_admin_only)
|
||||||
.require_email_verification(data.require_email_verification)
|
.require_email_verification(data.require_email_verification)
|
||||||
.application_question(diesel_option_overwrite(&data.application_question))
|
.application_question(diesel_option_overwrite(application_question))
|
||||||
.private_instance(data.private_instance)
|
.private_instance(data.private_instance)
|
||||||
.default_theme(data.default_theme.clone())
|
.default_theme(default_theme)
|
||||||
.default_post_listing_type(data.default_post_listing_type)
|
.default_post_listing_type(data.default_post_listing_type)
|
||||||
.legal_information(diesel_option_overwrite(&data.legal_information))
|
.legal_information(diesel_option_overwrite(legal_information))
|
||||||
.application_email_admins(data.application_email_admins)
|
.application_email_admins(data.application_email_admins)
|
||||||
.hide_modlog_mod_names(data.hide_modlog_mod_names)
|
.hide_modlog_mod_names(data.hide_modlog_mod_names)
|
||||||
.updated(Some(Some(naive_now())))
|
.updated(Some(Some(naive_now())))
|
||||||
.slur_filter_regex(diesel_option_overwrite(&data.slur_filter_regex))
|
.slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone()))
|
||||||
.actor_name_max_length(data.actor_name_max_length)
|
.actor_name_max_length(data.actor_name_max_length)
|
||||||
.federation_enabled(data.federation_enabled)
|
.federation_enabled(data.federation_enabled)
|
||||||
.captcha_enabled(data.captcha_enabled)
|
.captcha_enabled(data.captcha_enabled)
|
||||||
|
|
|
@ -11,6 +11,7 @@ use lemmy_api_common::{
|
||||||
honeypot_check,
|
honeypot_check,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
password_length_check,
|
password_length_check,
|
||||||
|
sanitize_html,
|
||||||
send_new_applicant_email_to_admins,
|
send_new_applicant_email_to_admins,
|
||||||
send_verification_email,
|
send_verification_email,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
|
@ -92,6 +93,7 @@ impl PerformCrud for Register {
|
||||||
let slur_regex = local_site_to_slur_regex(&local_site);
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
check_slurs(&data.username, &slur_regex)?;
|
check_slurs(&data.username, &slur_regex)?;
|
||||||
check_slurs_opt(&data.answer, &slur_regex)?;
|
check_slurs_opt(&data.answer, &slur_regex)?;
|
||||||
|
let username = sanitize_html(&data.username);
|
||||||
|
|
||||||
let actor_keypair = generate_actor_keypair()?;
|
let actor_keypair = generate_actor_keypair()?;
|
||||||
is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
|
is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
|
||||||
|
@ -111,7 +113,7 @@ impl PerformCrud for Register {
|
||||||
|
|
||||||
// Register the new person
|
// Register the new person
|
||||||
let person_form = PersonInsertForm::builder()
|
let person_form = PersonInsertForm::builder()
|
||||||
.name(data.username.clone())
|
.name(username)
|
||||||
.actor_id(Some(actor_id.clone()))
|
.actor_id(Some(actor_id.clone()))
|
||||||
.private_key(Some(actor_keypair.private_key))
|
.private_key(Some(actor_keypair.private_key))
|
||||||
.public_key(actor_keypair.public_key)
|
.public_key(actor_keypair.public_key)
|
||||||
|
|
|
@ -23,7 +23,7 @@ use anyhow::anyhow;
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{remove_user_data, remove_user_data_in_community},
|
utils::{remove_user_data, remove_user_data_in_community, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -177,7 +177,7 @@ impl ActivityHandler for BlockUser {
|
||||||
let form = ModBanForm {
|
let form = ModBanForm {
|
||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
reason: self.summary,
|
reason: sanitize_html_opt(&self.summary),
|
||||||
banned: Some(true),
|
banned: Some(true),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
@ -211,7 +211,7 @@ impl ActivityHandler for BlockUser {
|
||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
reason: self.summary,
|
reason: sanitize_html_opt(&self.summary),
|
||||||
banned: Some(true),
|
banned: Some(true),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ use activitypub_federation::{
|
||||||
protocol::verification::verify_domains_match,
|
protocol::verification::verify_domains_match,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{ActivityHandler, Actor},
|
||||||
};
|
};
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::{context::LemmyContext, utils::sanitize_html_opt};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::{CommunityPersonBan, CommunityPersonBanForm},
|
community::{CommunityPersonBan, CommunityPersonBanForm},
|
||||||
|
@ -116,7 +116,7 @@ impl ActivityHandler for UndoBlockUser {
|
||||||
let form = ModBanForm {
|
let form = ModBanForm {
|
||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
reason: self.object.summary,
|
reason: sanitize_html_opt(&self.object.summary),
|
||||||
banned: Some(false),
|
banned: Some(false),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
@ -135,7 +135,7 @@ impl ActivityHandler for UndoBlockUser {
|
||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
reason: self.object.summary,
|
reason: sanitize_html_opt(&self.object.summary),
|
||||||
banned: Some(false),
|
banned: Some(false),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ use lemmy_api_common::{
|
||||||
comment::{CommentReportResponse, CreateCommentReport},
|
comment::{CommentReportResponse, CreateCommentReport},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
post::{CreatePostReport, PostReportResponse},
|
post::{CreatePostReport, PostReportResponse},
|
||||||
utils::local_user_view_from_jwt,
|
utils::{local_user_view_from_jwt, sanitize_html},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -131,7 +131,7 @@ impl ActivityHandler for Report {
|
||||||
post_id: post.id,
|
post_id: post.id,
|
||||||
original_post_name: post.name.clone(),
|
original_post_name: post.name.clone(),
|
||||||
original_post_url: post.url.clone(),
|
original_post_url: post.url.clone(),
|
||||||
reason: self.summary,
|
reason: sanitize_html(&self.summary),
|
||||||
original_post_body: post.body.clone(),
|
original_post_body: post.body.clone(),
|
||||||
};
|
};
|
||||||
PostReport::report(&mut context.pool(), &report_form).await?;
|
PostReport::report(&mut context.pool(), &report_form).await?;
|
||||||
|
@ -141,7 +141,7 @@ impl ActivityHandler for Report {
|
||||||
creator_id: actor.id,
|
creator_id: actor.id,
|
||||||
comment_id: comment.id,
|
comment_id: comment.id,
|
||||||
original_comment_text: comment.content.clone(),
|
original_comment_text: comment.content.clone(),
|
||||||
reason: self.summary,
|
reason: sanitize_html(&self.summary),
|
||||||
};
|
};
|
||||||
CommentReport::report(&mut context.pool(), &report_form).await?;
|
CommentReport::report(&mut context.pool(), &report_form).await?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
|
protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::ActivityHandler};
|
use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::ActivityHandler};
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::{context::LemmyContext, utils::sanitize_html_opt};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentUpdateForm},
|
comment::{Comment, CommentUpdateForm},
|
||||||
|
@ -105,6 +105,8 @@ pub(in crate::activities) async fn receive_remove_action(
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
let reason = sanitize_html_opt(&reason);
|
||||||
|
|
||||||
match DeletableObjects::read_from_db(object, context).await? {
|
match DeletableObjects::read_from_db(object, context).await? {
|
||||||
DeletableObjects::Community(community) => {
|
DeletableObjects::Community(community) => {
|
||||||
if community.local {
|
if community.local {
|
||||||
|
|
|
@ -16,7 +16,10 @@ use activitypub_federation::{
|
||||||
traits::Object,
|
traits::Object,
|
||||||
};
|
};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::local_site_opt_to_slur_regex};
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
utils::{local_site_opt_to_slur_regex, sanitize_html},
|
||||||
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentInsertForm, CommentUpdateForm},
|
comment::{Comment, CommentInsertForm, CommentUpdateForm},
|
||||||
|
@ -154,14 +157,15 @@ impl Object for ApubComment {
|
||||||
|
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
||||||
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
||||||
let content_slurs_removed = remove_slurs(&content, slur_regex);
|
let content = remove_slurs(&content, slur_regex);
|
||||||
|
let content = sanitize_html(&content);
|
||||||
let language_id =
|
let language_id =
|
||||||
LanguageTag::to_language_id_single(note.language, &mut context.pool()).await?;
|
LanguageTag::to_language_id_single(note.language, &mut context.pool()).await?;
|
||||||
|
|
||||||
let form = CommentInsertForm {
|
let form = CommentInsertForm {
|
||||||
creator_id: creator.id,
|
creator_id: creator.id,
|
||||||
post_id: post.id,
|
post_id: post.id,
|
||||||
content: content_slurs_removed,
|
content,
|
||||||
removed: None,
|
removed: None,
|
||||||
published: note.published.map(|u| u.naive_local()),
|
published: note.published.map(|u| u.naive_local()),
|
||||||
updated: note.updated.map(|u| u.naive_local()),
|
updated: note.updated.map(|u| u.naive_local()),
|
||||||
|
|
|
@ -16,7 +16,10 @@ use activitypub_federation::{
|
||||||
traits::{Actor, Object},
|
traits::{Actor, Object},
|
||||||
};
|
};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::local_site_opt_to_slur_regex};
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
utils::{local_site_opt_to_slur_regex, sanitize_html_opt},
|
||||||
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::InstanceId,
|
newtypes::InstanceId,
|
||||||
source::{
|
source::{
|
||||||
|
@ -129,13 +132,17 @@ impl Object for ApubSite {
|
||||||
let domain = apub.id.inner().domain().expect("group id has domain");
|
let domain = apub.id.inner().domain().expect("group id has domain");
|
||||||
let instance = DbInstance::read_or_create(&mut data.pool(), domain.to_string()).await?;
|
let instance = DbInstance::read_or_create(&mut data.pool(), domain.to_string()).await?;
|
||||||
|
|
||||||
|
let sidebar = read_from_string_or_source_opt(&apub.content, &None, &apub.source);
|
||||||
|
let sidebar = sanitize_html_opt(&sidebar);
|
||||||
|
let description = sanitize_html_opt(&apub.summary);
|
||||||
|
|
||||||
let site_form = SiteInsertForm {
|
let site_form = SiteInsertForm {
|
||||||
name: apub.name.clone(),
|
name: apub.name.clone(),
|
||||||
sidebar: read_from_string_or_source_opt(&apub.content, &None, &apub.source),
|
sidebar,
|
||||||
updated: apub.updated.map(|u| u.clone().naive_local()),
|
updated: apub.updated.map(|u| u.clone().naive_local()),
|
||||||
icon: apub.icon.clone().map(|i| i.url.into()),
|
icon: apub.icon.clone().map(|i| i.url.into()),
|
||||||
banner: apub.image.clone().map(|i| i.url.into()),
|
banner: apub.image.clone().map(|i| i.url.into()),
|
||||||
description: apub.summary.clone(),
|
description,
|
||||||
actor_id: Some(apub.id.clone().into()),
|
actor_id: Some(apub.id.clone().into()),
|
||||||
last_refreshed_at: Some(naive_now()),
|
last_refreshed_at: Some(naive_now()),
|
||||||
inbox_url: Some(apub.inbox.clone().into()),
|
inbox_url: Some(apub.inbox.clone().into()),
|
||||||
|
|
|
@ -19,7 +19,7 @@ use activitypub_federation::{
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{generate_outbox_url, local_site_opt_to_slur_regex},
|
utils::{generate_outbox_url, local_site_opt_to_slur_regex, sanitize_html, sanitize_html_opt},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::person::{Person as DbPerson, PersonInsertForm, PersonUpdateForm},
|
source::person::{Person as DbPerson, PersonInsertForm, PersonUpdateForm},
|
||||||
|
@ -138,12 +138,17 @@ impl Object for ApubPerson {
|
||||||
) -> Result<ApubPerson, LemmyError> {
|
) -> Result<ApubPerson, LemmyError> {
|
||||||
let instance_id = fetch_instance_actor_for_object(&person.id, context).await?;
|
let instance_id = fetch_instance_actor_for_object(&person.id, context).await?;
|
||||||
|
|
||||||
|
let name = sanitize_html(&person.preferred_username);
|
||||||
|
let display_name = sanitize_html_opt(&person.name);
|
||||||
|
let bio = read_from_string_or_source_opt(&person.summary, &None, &person.source);
|
||||||
|
let bio = sanitize_html_opt(&bio);
|
||||||
|
|
||||||
// Some Mastodon users have `name: ""` (empty string), need to convert that to `None`
|
// Some Mastodon users have `name: ""` (empty string), need to convert that to `None`
|
||||||
// https://github.com/mastodon/mastodon/issues/25233
|
// https://github.com/mastodon/mastodon/issues/25233
|
||||||
let display_name = person.name.filter(|n| !n.is_empty());
|
let display_name = display_name.filter(|n| !n.is_empty());
|
||||||
|
|
||||||
let person_form = PersonInsertForm {
|
let person_form = PersonInsertForm {
|
||||||
name: person.preferred_username,
|
name,
|
||||||
display_name,
|
display_name,
|
||||||
banned: None,
|
banned: None,
|
||||||
ban_expires: None,
|
ban_expires: None,
|
||||||
|
@ -153,7 +158,7 @@ impl Object for ApubPerson {
|
||||||
published: person.published.map(|u| u.naive_local()),
|
published: person.published.map(|u| u.naive_local()),
|
||||||
updated: person.updated.map(|u| u.naive_local()),
|
updated: person.updated.map(|u| u.naive_local()),
|
||||||
actor_id: Some(person.id.into()),
|
actor_id: Some(person.id.into()),
|
||||||
bio: read_from_string_or_source_opt(&person.summary, &None, &person.source),
|
bio,
|
||||||
local: Some(false),
|
local: Some(false),
|
||||||
admin: Some(false),
|
admin: Some(false),
|
||||||
bot_account: Some(person.kind == UserTypes::Service),
|
bot_account: Some(person.kind == UserTypes::Service),
|
||||||
|
|
|
@ -25,7 +25,13 @@ use html2md::parse_html;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
utils::{is_mod_or_admin, local_site_opt_to_sensitive, local_site_opt_to_slur_regex},
|
utils::{
|
||||||
|
is_mod_or_admin,
|
||||||
|
local_site_opt_to_sensitive,
|
||||||
|
local_site_opt_to_slur_regex,
|
||||||
|
sanitize_html,
|
||||||
|
sanitize_html_opt,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
self,
|
self,
|
||||||
|
@ -228,6 +234,10 @@ impl Object for ApubPost {
|
||||||
let language_id =
|
let language_id =
|
||||||
LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?;
|
LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?;
|
||||||
|
|
||||||
|
let name = sanitize_html(&name);
|
||||||
|
let embed_title = sanitize_html_opt(&embed_title);
|
||||||
|
let embed_description = sanitize_html_opt(&embed_description);
|
||||||
|
|
||||||
PostInsertForm {
|
PostInsertForm {
|
||||||
name,
|
name,
|
||||||
url: url.map(Into::into),
|
url: url.map(Into::into),
|
||||||
|
|
|
@ -12,7 +12,10 @@ use activitypub_federation::{
|
||||||
traits::Object,
|
traits::Object,
|
||||||
};
|
};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::check_person_block};
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
utils::{check_person_block, sanitize_html},
|
||||||
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
person::Person,
|
person::Person,
|
||||||
|
@ -118,10 +121,13 @@ impl Object for ApubPrivateMessage {
|
||||||
let recipient = note.to[0].dereference(context).await?;
|
let recipient = note.to[0].dereference(context).await?;
|
||||||
check_person_block(creator.id, recipient.id, &mut context.pool()).await?;
|
check_person_block(creator.id, recipient.id, &mut context.pool()).await?;
|
||||||
|
|
||||||
|
let content = read_from_string_or_source(¬e.content, &None, ¬e.source);
|
||||||
|
let content = sanitize_html(&content);
|
||||||
|
|
||||||
let form = PrivateMessageInsertForm {
|
let form = PrivateMessageInsertForm {
|
||||||
creator_id: creator.id,
|
creator_id: creator.id,
|
||||||
recipient_id: recipient.id,
|
recipient_id: recipient.id,
|
||||||
content: read_from_string_or_source(¬e.content, &None, ¬e.source),
|
content,
|
||||||
published: note.published.map(|u| u.naive_local()),
|
published: note.published.map(|u| u.naive_local()),
|
||||||
updated: note.updated.map(|u| u.naive_local()),
|
updated: note.updated.map(|u| u.naive_local()),
|
||||||
deleted: Some(false),
|
deleted: Some(false),
|
||||||
|
|
|
@ -23,7 +23,10 @@ use activitypub_federation::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::local_site_opt_to_slur_regex};
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
utils::{local_site_opt_to_slur_regex, sanitize_html, sanitize_html_opt},
|
||||||
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::InstanceId,
|
newtypes::InstanceId,
|
||||||
source::community::{CommunityInsertForm, CommunityUpdateForm},
|
source::community::{CommunityInsertForm, CommunityUpdateForm},
|
||||||
|
@ -94,10 +97,15 @@ impl Group {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_insert_form(self, instance_id: InstanceId) -> CommunityInsertForm {
|
pub(crate) fn into_insert_form(self, instance_id: InstanceId) -> CommunityInsertForm {
|
||||||
|
let name = sanitize_html(&self.preferred_username);
|
||||||
|
let title = sanitize_html(&self.name.unwrap_or(self.preferred_username));
|
||||||
|
let description = read_from_string_or_source_opt(&self.summary, &None, &self.source);
|
||||||
|
let description = sanitize_html_opt(&description);
|
||||||
|
|
||||||
CommunityInsertForm {
|
CommunityInsertForm {
|
||||||
name: self.preferred_username.clone(),
|
name,
|
||||||
title: self.name.unwrap_or(self.preferred_username),
|
title,
|
||||||
description: read_from_string_or_source_opt(&self.summary, &None, &self.source),
|
description,
|
||||||
removed: None,
|
removed: None,
|
||||||
published: self.published.map(|u| u.naive_local()),
|
published: self.published.map(|u| u.naive_local()),
|
||||||
updated: self.updated.map(|u| u.naive_local()),
|
updated: self.updated.map(|u| u.naive_local()),
|
||||||
|
|
|
@ -197,12 +197,12 @@ pub fn is_email_regex(test: &str) -> bool {
|
||||||
EMAIL_REGEX.is_match(test)
|
EMAIL_REGEX.is_match(test)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diesel_option_overwrite(opt: &Option<String>) -> Option<Option<String>> {
|
pub fn diesel_option_overwrite(opt: Option<String>) -> Option<Option<String>> {
|
||||||
match opt {
|
match opt {
|
||||||
// An empty string is an erase
|
// An empty string is an erase
|
||||||
Some(unwrapped) => {
|
Some(unwrapped) => {
|
||||||
if !unwrapped.eq("") {
|
if !unwrapped.eq("") {
|
||||||
Some(Some(unwrapped.clone()))
|
Some(Some(unwrapped))
|
||||||
} else {
|
} else {
|
||||||
Some(None)
|
Some(None)
|
||||||
}
|
}
|
||||||
|
@ -445,10 +445,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_diesel_option_overwrite() {
|
fn test_diesel_option_overwrite() {
|
||||||
assert_eq!(diesel_option_overwrite(&None), None);
|
assert_eq!(diesel_option_overwrite(None), None);
|
||||||
assert_eq!(diesel_option_overwrite(&Some(String::new())), Some(None));
|
assert_eq!(diesel_option_overwrite(Some(String::new())), Some(None));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
diesel_option_overwrite(&Some("test".to_string())),
|
diesel_option_overwrite(Some("test".to_string())),
|
||||||
Some(Some("test".to_string()))
|
Some(Some("test".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue