2019-08-14 02:52:43 +00:00
#![ recursion_limit = " 512 " ]
2019-09-07 15:35:05 +00:00
#[ macro_use ]
pub extern crate strum_macros ;
#[ macro_use ]
pub extern crate lazy_static ;
#[ macro_use ]
pub extern crate failure ;
#[ macro_use ]
pub extern crate diesel ;
2019-03-21 01:22:31 +00:00
pub extern crate actix ;
pub extern crate actix_web ;
2019-03-23 01:42:57 +00:00
pub extern crate bcrypt ;
2019-09-07 15:35:05 +00:00
pub extern crate chrono ;
pub extern crate dotenv ;
pub extern crate jsonwebtoken ;
pub extern crate rand ;
2019-03-23 01:42:57 +00:00
pub extern crate regex ;
2019-09-07 15:35:05 +00:00
pub extern crate serde ;
pub extern crate serde_json ;
pub extern crate strum ;
2019-10-30 03:35:39 +00:00
pub extern crate lettre ;
pub extern crate lettre_email ;
2019-11-02 06:41:57 +00:00
pub extern crate crypto ;
2019-04-21 07:26:26 +00:00
2019-05-05 05:20:38 +00:00
pub mod api ;
2019-03-21 01:22:31 +00:00
pub mod apub ;
2019-05-03 01:34:21 +00:00
pub mod db ;
2019-09-07 15:35:05 +00:00
pub mod schema ;
2019-05-03 01:34:21 +00:00
pub mod websocket ;
2019-02-28 06:02:55 +00:00
2019-09-07 15:35:05 +00:00
use chrono ::{ DateTime , NaiveDateTime , Utc } ;
2019-02-28 06:02:55 +00:00
use dotenv ::dotenv ;
2019-03-23 01:42:57 +00:00
use regex ::Regex ;
2019-09-07 15:35:05 +00:00
use std ::env ;
2019-10-30 03:35:39 +00:00
use rand ::{ thread_rng , Rng } ;
use rand ::distributions ::Alphanumeric ;
use lettre ::{ SmtpClient , Transport } ;
use lettre_email ::{ Email } ;
use lettre ::smtp ::authentication ::{ Credentials , Mechanism } ;
use lettre ::smtp ::extension ::ClientId ;
use lettre ::smtp ::ConnectionReuseParameters ;
2019-02-28 06:02:55 +00:00
2019-03-05 03:52:09 +00:00
pub struct Settings {
db_url : String ,
2019-05-02 16:55:29 +00:00
hostname : String ,
jwt_secret : String ,
2019-10-13 19:06:18 +00:00
rate_limit_message : i32 ,
rate_limit_message_per_second : i32 ,
rate_limit_post : i32 ,
rate_limit_post_per_second : i32 ,
rate_limit_register : i32 ,
rate_limit_register_per_second : i32 ,
2019-10-30 03:35:39 +00:00
email_config : Option < EmailConfig > ,
}
pub struct EmailConfig {
smtp_server : String ,
smtp_login : String ,
smtp_password : String ,
smtp_from_address : String ,
2019-03-05 03:52:09 +00:00
}
impl Settings {
fn get ( ) -> Self {
dotenv ( ) . ok ( ) ;
2019-10-30 03:35:39 +00:00
2019-11-02 06:41:57 +00:00
let email_config = if env ::var ( " SMTP_SERVER " ) . is_ok ( ) & &
! env ::var ( " SMTP_SERVER " ) . unwrap ( ) . eq ( " " ) {
2019-10-30 03:35:39 +00:00
Some ( EmailConfig {
smtp_server : env ::var ( " SMTP_SERVER " ) . expect ( " SMTP_SERVER must be set " ) ,
smtp_login : env ::var ( " SMTP_LOGIN " ) . expect ( " SMTP_LOGIN must be set " ) ,
smtp_password : env ::var ( " SMTP_PASSWORD " ) . expect ( " SMTP_PASSWORD must be set " ) ,
smtp_from_address : env ::var ( " SMTP_FROM_ADDRESS " ) . expect ( " SMTP_FROM_ADDRESS must be set " )
} )
} else {
None
} ;
2019-03-05 03:52:09 +00:00
Settings {
2019-09-07 15:35:05 +00:00
db_url : env ::var ( " DATABASE_URL " ) . expect ( " DATABASE_URL must be set " ) ,
hostname : env ::var ( " HOSTNAME " ) . unwrap_or ( " rrr " . to_string ( ) ) ,
jwt_secret : env ::var ( " JWT_SECRET " ) . unwrap_or ( " changeme " . to_string ( ) ) ,
2019-10-13 19:06:18 +00:00
rate_limit_message : env ::var ( " RATE_LIMIT_MESSAGE " )
. unwrap_or ( " 30 " . to_string ( ) )
. parse ( )
. unwrap ( ) ,
rate_limit_message_per_second : env ::var ( " RATE_LIMIT_MESSAGE_PER_SECOND " )
. unwrap_or ( " 60 " . to_string ( ) )
. parse ( )
. unwrap ( ) ,
rate_limit_post : env ::var ( " RATE_LIMIT_POST " )
. unwrap_or ( " 3 " . to_string ( ) )
. parse ( )
. unwrap ( ) ,
rate_limit_post_per_second : env ::var ( " RATE_LIMIT_POST_PER_SECOND " )
. unwrap_or ( " 600 " . to_string ( ) )
. parse ( )
. unwrap ( ) ,
rate_limit_register : env ::var ( " RATE_LIMIT_REGISTER " )
. unwrap_or ( " 1 " . to_string ( ) )
. parse ( )
. unwrap ( ) ,
rate_limit_register_per_second : env ::var ( " RATE_LIMIT_REGISTER_PER_SECOND " )
. unwrap_or ( " 3600 " . to_string ( ) )
. parse ( )
. unwrap ( ) ,
2019-10-30 03:35:39 +00:00
email_config : email_config ,
2019-03-05 03:52:09 +00:00
}
}
fn api_endpoint ( & self ) -> String {
format! ( " {} /api/v1 " , self . hostname )
}
}
pub fn to_datetime_utc ( ndt : NaiveDateTime ) -> DateTime < Utc > {
DateTime ::< Utc > ::from_utc ( ndt , Utc )
}
2019-02-28 06:02:55 +00:00
2019-03-05 03:52:09 +00:00
pub fn naive_now ( ) -> NaiveDateTime {
chrono ::prelude ::Utc ::now ( ) . naive_utc ( )
2019-02-28 06:02:55 +00:00
}
2019-09-07 15:35:05 +00:00
pub fn naive_from_unix ( time : i64 ) -> NaiveDateTime {
2019-04-15 23:12:06 +00:00
NaiveDateTime ::from_timestamp ( time , 0 )
}
2019-03-23 01:42:57 +00:00
pub fn is_email_regex ( test : & str ) -> bool {
2019-04-09 18:35:16 +00:00
EMAIL_REGEX . is_match ( test )
}
pub fn remove_slurs ( test : & str ) -> String {
SLUR_REGEX . replace_all ( test , " *removed* " ) . to_string ( )
}
pub fn has_slurs ( test : & str ) -> bool {
SLUR_REGEX . is_match ( test )
2019-03-23 01:42:57 +00:00
}
2019-10-20 00:46:29 +00:00
pub fn extract_usernames ( test : & str ) -> Vec < & str > {
let mut matches : Vec < & str > = USERNAME_MATCHES_REGEX
. find_iter ( test )
. map ( | mat | mat . as_str ( ) )
. collect ( ) ;
// Unique
matches . sort_unstable ( ) ;
matches . dedup ( ) ;
// Remove /u/
matches . iter ( ) . map ( | t | & t [ 3 .. ] ) . collect ( )
}
2019-10-30 03:35:39 +00:00
pub fn generate_random_string ( ) -> String {
thread_rng ( )
. sample_iter ( & Alphanumeric )
. take ( 30 )
. collect ( )
}
pub fn send_email ( subject : & str , to_email : & str , to_username : & str , html : & str ) -> Result < ( ) , String > {
let email_config = Settings ::get ( ) . email_config . ok_or ( " no_email_setup " ) ? ;
let email = Email ::builder ( )
. to ( ( to_email , to_username ) )
. from ( ( email_config . smtp_login . to_owned ( ) , email_config . smtp_from_address ) )
. subject ( subject )
. html ( html )
. build ( )
. unwrap ( ) ;
2019-11-02 06:41:57 +00:00
let mut mailer = SmtpClient ::new_simple ( & email_config . smtp_server ) . unwrap ( )
. hello_name ( ClientId ::Domain ( " localhost " . to_string ( ) ) )
. credentials ( Credentials ::new (
email_config . smtp_login . to_owned ( ) ,
email_config . smtp_password . to_owned ( ) ) )
. smtp_utf8 ( true )
. authentication_mechanism ( Mechanism ::Plain )
. connection_reuse ( ConnectionReuseParameters ::ReuseUnlimited )
. transport ( ) ;
2019-10-30 03:35:39 +00:00
let result = mailer . send ( email . into ( ) ) ;
match result {
Ok ( _ ) = > Ok ( ( ) ) ,
Err ( _ ) = > Err ( " no_email_setup " . to_string ( ) ) ,
}
}
2019-03-05 03:52:09 +00:00
#[ cfg(test) ]
mod tests {
2019-10-20 00:46:29 +00:00
use crate ::{ extract_usernames , has_slurs , is_email_regex , remove_slurs , Settings } ;
2019-03-23 01:42:57 +00:00
#[ test ]
2019-03-05 03:52:09 +00:00
fn test_api ( ) {
2019-05-02 16:55:29 +00:00
assert_eq! ( Settings ::get ( ) . api_endpoint ( ) , " rrr/api/v1 " ) ;
2019-03-05 03:52:09 +00:00
}
2019-03-23 01:42:57 +00:00
2019-09-07 15:35:05 +00:00
#[ test ]
fn test_email ( ) {
2019-03-23 01:42:57 +00:00
assert! ( is_email_regex ( " gush@gmail.com " ) ) ;
assert! ( ! is_email_regex ( " nada_neutho " ) ) ;
2019-09-07 15:35:05 +00:00
}
2019-04-09 18:35:16 +00:00
2019-09-07 15:35:05 +00:00
#[ test ]
fn test_slur_filter ( ) {
2019-10-13 19:06:18 +00:00
let test =
" coons test dindu ladyboy tranny retardeds. This is a bunch of other safe text. " . to_string ( ) ;
2019-04-09 18:35:16 +00:00
let slur_free = " No slurs here " ;
2019-09-07 15:35:05 +00:00
assert_eq! (
remove_slurs ( & test ) ,
2019-09-18 19:00:41 +00:00
" *removed* test *removed* *removed* *removed* *removed*. This is a bunch of other safe text. "
2019-09-07 15:35:05 +00:00
. to_string ( )
) ;
2019-04-09 18:35:16 +00:00
assert! ( has_slurs ( & test ) ) ;
assert! ( ! has_slurs ( slur_free ) ) ;
2019-09-07 15:35:05 +00:00
}
2019-10-20 00:46:29 +00:00
#[ test ]
fn test_extract_usernames ( ) {
let usernames = extract_usernames ( " this is a user mention for [/u/testme](/u/testme) and thats all. Oh [/u/another](/u/another) user. And the first again [/u/testme](/u/testme) okay " ) ;
let expected = vec! [ " another " , " testme " ] ;
assert_eq! ( usernames , expected ) ;
}
2019-10-30 03:35:39 +00:00
// #[test]
// fn test_send_email() {
// let result = send_email("not a subject", "test_email@gmail.com", "ur user", "<h1>HI there</h1>");
// assert!(result.is_ok());
// }
2019-04-09 18:35:16 +00:00
}
lazy_static! {
static ref EMAIL_REGEX : Regex = Regex ::new ( r "^[a-zA-Z0-9.!#$%&’ *+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" ) . unwrap ( ) ;
2019-09-19 22:49:20 +00:00
static ref SLUR_REGEX : Regex = Regex ::new ( r "(fag(g|got|tard)?|maricos?|cock\s?sucker(s|ing)?|nig(\b|g?(a|er)?s?)\b|dindu(s?)|mudslime?s?|kikes?|mongoloids?|towel\s*heads?|\bspi(c|k)s?\b|\bchinks?|niglets?|beaners?|\bnips?\b|\bcoons?\b|jungle\s*bunn(y|ies?)|jigg?aboo?s?|\bpakis?\b|rag\s*heads?|gooks?|cunts?|bitch(es|ing|y)?|puss(y|ies?)|twats?|feminazis?|whor(es?|ing)|\bslut(s|t?y)?|\btrann?(y|ies?)|ladyboy(s?)|\b(b|re|r)tard(ed)?s?)" ) . unwrap ( ) ;
2019-10-20 00:46:29 +00:00
static ref USERNAME_MATCHES_REGEX : Regex = Regex ::new ( r "/u/[a-zA-Z][0-9a-zA-Z_]*" ) . unwrap ( ) ;
2019-03-23 01:42:57 +00:00
}