forked from nutomic/lemmy
Returning specific slurs from slur filter on failure. Fixes #463
This commit is contained in:
parent
3f42af9885
commit
d4736be04f
6 changed files with 98 additions and 28 deletions
|
@ -176,11 +176,18 @@ impl Perform<CommunityResponse> for Oper<CreateCommunity> {
|
||||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_slurs(&data.name)
|
if let Err(slurs) = slur_check(&data.name) {
|
||||||
|| has_slurs(&data.title)
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|| (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap()))
|
}
|
||||||
{
|
|
||||||
return Err(APIError::err("no_slurs").into());
|
if let Err(slurs) = slur_check(&data.title) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(description) = &data.description {
|
||||||
|
if let Err(slurs) = slur_check(description) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
@ -242,8 +249,18 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
|
||||||
fn perform(&self, conn: &PgConnection) -> Result<CommunityResponse, Error> {
|
fn perform(&self, conn: &PgConnection) -> Result<CommunityResponse, Error> {
|
||||||
let data: &EditCommunity = &self.data;
|
let data: &EditCommunity = &self.data;
|
||||||
|
|
||||||
if has_slurs(&data.name) || has_slurs(&data.title) {
|
if let Err(slurs) = slur_check(&data.name) {
|
||||||
return Err(APIError::err("no_slurs").into());
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(slurs) = slur_check(&data.title) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(description) = &data.description {
|
||||||
|
if let Err(slurs) = slur_check(description) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let claims = match Claims::decode(&data.auth) {
|
let claims = match Claims::decode(&data.auth) {
|
||||||
|
|
|
@ -17,7 +17,9 @@ use crate::db::user_mention::*;
|
||||||
use crate::db::user_mention_view::*;
|
use crate::db::user_mention_view::*;
|
||||||
use crate::db::user_view::*;
|
use crate::db::user_view::*;
|
||||||
use crate::db::*;
|
use crate::db::*;
|
||||||
use crate::{extract_usernames, has_slurs, naive_from_unix, naive_now, remove_slurs};
|
use crate::{
|
||||||
|
extract_usernames, naive_from_unix, naive_now, remove_slurs, slur_check, slurs_vec_to_str,
|
||||||
|
};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
|
@ -88,8 +88,14 @@ impl Perform<PostResponse> for Oper<CreatePost> {
|
||||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_slurs(&data.name) || (data.body.is_some() && has_slurs(&data.body.to_owned().unwrap())) {
|
if let Err(slurs) = slur_check(&data.name) {
|
||||||
return Err(APIError::err("no_slurs").into());
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(body) = &data.body {
|
||||||
|
if let Err(slurs) = slur_check(body) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
@ -298,8 +304,15 @@ impl Perform<PostResponse> for Oper<CreatePostLike> {
|
||||||
impl Perform<PostResponse> for Oper<EditPost> {
|
impl Perform<PostResponse> for Oper<EditPost> {
|
||||||
fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
|
fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
|
||||||
let data: &EditPost = &self.data;
|
let data: &EditPost = &self.data;
|
||||||
if has_slurs(&data.name) || (data.body.is_some() && has_slurs(&data.body.to_owned().unwrap())) {
|
|
||||||
return Err(APIError::err("no_slurs").into());
|
if let Err(slurs) = slur_check(&data.name) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(body) = &data.body {
|
||||||
|
if let Err(slurs) = slur_check(body) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let claims = match Claims::decode(&data.auth) {
|
let claims = match Claims::decode(&data.auth) {
|
||||||
|
|
|
@ -186,10 +186,14 @@ impl Perform<SiteResponse> for Oper<CreateSite> {
|
||||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_slurs(&data.name)
|
if let Err(slurs) = slur_check(&data.name) {
|
||||||
|| (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap()))
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
{
|
}
|
||||||
return Err(APIError::err("no_slurs").into());
|
|
||||||
|
if let Some(description) = &data.description {
|
||||||
|
if let Err(slurs) = slur_check(description) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
@ -229,10 +233,14 @@ impl Perform<SiteResponse> for Oper<EditSite> {
|
||||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_slurs(&data.name)
|
if let Err(slurs) = slur_check(&data.name) {
|
||||||
|| (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap()))
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
{
|
}
|
||||||
return Err(APIError::err("no_slurs").into());
|
|
||||||
|
if let Some(description) = &data.description {
|
||||||
|
if let Err(slurs) = slur_check(description) {
|
||||||
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
|
@ -240,8 +240,8 @@ impl Perform<LoginResponse> for Oper<Register> {
|
||||||
return Err(APIError::err("passwords_dont_match").into());
|
return Err(APIError::err("passwords_dont_match").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_slurs(&data.username) {
|
if let Err(slurs) = slur_check(&data.username) {
|
||||||
return Err(APIError::err("no_slurs").into());
|
return Err(APIError::err(&slurs_vec_to_str(slurs)).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure there are no admins
|
// Make sure there are no admins
|
||||||
|
|
|
@ -62,8 +62,24 @@ pub fn remove_slurs(test: &str) -> String {
|
||||||
SLUR_REGEX.replace_all(test, "*removed*").to_string()
|
SLUR_REGEX.replace_all(test, "*removed*").to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_slurs(test: &str) -> bool {
|
pub fn slur_check(test: &str) -> Result<(), Vec<&str>> {
|
||||||
SLUR_REGEX.is_match(test)
|
let mut matches: Vec<&str> = SLUR_REGEX.find_iter(test).map(|mat| mat.as_str()).collect();
|
||||||
|
|
||||||
|
// Unique
|
||||||
|
matches.sort_unstable();
|
||||||
|
matches.dedup();
|
||||||
|
|
||||||
|
if matches.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slurs_vec_to_str(slurs: Vec<&str>) -> String {
|
||||||
|
let start = "No slurs - ";
|
||||||
|
let combined = &slurs.join(", ");
|
||||||
|
[start, combined].concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_usernames(test: &str) -> Vec<&str> {
|
pub fn extract_usernames(test: &str) -> Vec<&str> {
|
||||||
|
@ -127,7 +143,7 @@ pub fn send_email(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{extract_usernames, has_slurs, is_email_regex, remove_slurs};
|
use crate::{extract_usernames, is_email_regex, remove_slurs, slur_check, slurs_vec_to_str};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_email() {
|
fn test_email() {
|
||||||
|
@ -138,15 +154,29 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slur_filter() {
|
fn test_slur_filter() {
|
||||||
let test =
|
let test =
|
||||||
"coons test dindu ladyboy tranny retardeds. Capitalized Niggerz. This is a bunch of other safe text.".to_string();
|
"coons test dindu ladyboy tranny retardeds. Capitalized Niggerz. This is a bunch of other safe text.";
|
||||||
let slur_free = "No slurs here";
|
let slur_free = "No slurs here";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
remove_slurs(&test),
|
remove_slurs(&test),
|
||||||
"*removed* test *removed* *removed* *removed* *removed*. Capitalized *removed*. This is a bunch of other safe text."
|
"*removed* test *removed* *removed* *removed* *removed*. Capitalized *removed*. This is a bunch of other safe text."
|
||||||
.to_string()
|
.to_string()
|
||||||
);
|
);
|
||||||
assert!(has_slurs(&test));
|
|
||||||
assert!(!has_slurs(slur_free));
|
let has_slurs_vec = vec![
|
||||||
|
"Niggerz",
|
||||||
|
"coons",
|
||||||
|
"dindu",
|
||||||
|
"ladyboy",
|
||||||
|
"retardeds",
|
||||||
|
"tranny",
|
||||||
|
];
|
||||||
|
let has_slurs_err_str = "No slurs - Niggerz, coons, dindu, ladyboy, retardeds, tranny";
|
||||||
|
|
||||||
|
assert_eq!(slur_check(test), Err(has_slurs_vec));
|
||||||
|
assert_eq!(slur_check(slur_free), Ok(()));
|
||||||
|
if let Err(slur_vec) = slur_check(test) {
|
||||||
|
assert_eq!(&slurs_vec_to_str(slur_vec), has_slurs_err_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue