lemmy/server/lemmy_db/src/lib.rs
Dessalines 464ea862b1
Preferred usernames, banners and icons. (#1055)
* Re-organizing federation tests. #746 #1040

* Adding federation support for user bios. Fixes #992

* Adding icons, banners, and preferred usernames.

- Added optional community icons, and community banners.
- Added user banners.
- Added Site icon and banner, with custom favicon.
- Set up preferred usernames. Fixes #1017
- Added an additional post sort: Active
  - Hot rank now uses the published time.
  - Active uses the most recent comment time, and is default.
- DB Migration was required to add all these fields to the views.
- Added transfercommunity helper function.
- Removed title column from communities page.
- Abstracted an image-upload-form.tsx, and a banner-icon-header.tsx
- Fixes #899

* Some navbar fixes.

* Fixing css

* Some fixes.

- Showing correct user icon and banner after save without page reload.
- Abstracting diesel update overwrite.
- Adding some docs.

* Adding @ when a user doesn't have a preferred username.
2020-08-05 12:03:46 -04:00

231 lines
5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#[macro_use]
pub extern crate diesel;
#[macro_use]
pub extern crate strum_macros;
#[macro_use]
pub extern crate lazy_static;
pub extern crate bcrypt;
pub extern crate chrono;
pub extern crate log;
pub extern crate regex;
pub extern crate serde;
pub extern crate serde_json;
pub extern crate sha2;
pub extern crate strum;
use chrono::NaiveDateTime;
use diesel::{dsl::*, result::Error, *};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{env, env::VarError};
pub mod activity;
pub mod category;
pub mod comment;
pub mod comment_view;
pub mod community;
pub mod community_view;
pub mod moderator;
pub mod moderator_views;
pub mod password_reset_request;
pub mod post;
pub mod post_view;
pub mod private_message;
pub mod private_message_view;
pub mod schema;
pub mod site;
pub mod site_view;
pub mod user;
pub mod user_mention;
pub mod user_mention_view;
pub mod user_view;
pub trait Crud<T> {
fn create(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn read(conn: &PgConnection, id: i32) -> Result<Self, Error>
where
Self: Sized;
fn update(conn: &PgConnection, id: i32, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn delete(conn: &PgConnection, id: i32) -> Result<usize, Error>
where
Self: Sized;
}
pub trait Followable<T> {
fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error>
where
Self: Sized;
}
pub trait Joinable<T> {
fn join(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn leave(conn: &PgConnection, form: &T) -> Result<usize, Error>
where
Self: Sized;
}
pub trait Likeable<T> {
fn read(conn: &PgConnection, id: i32) -> Result<Vec<Self>, Error>
where
Self: Sized;
fn like(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn remove(conn: &PgConnection, form: &T) -> Result<usize, Error>
where
Self: Sized;
}
pub trait Bannable<T> {
fn ban(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn unban(conn: &PgConnection, form: &T) -> Result<usize, Error>
where
Self: Sized;
}
pub trait Saveable<T> {
fn save(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn unsave(conn: &PgConnection, form: &T) -> Result<usize, Error>
where
Self: Sized;
}
pub trait Readable<T> {
fn mark_as_read(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn mark_as_unread(conn: &PgConnection, form: &T) -> Result<usize, Error>
where
Self: Sized;
}
pub trait MaybeOptional<T> {
fn get_optional(self) -> Option<T>;
}
impl<T> MaybeOptional<T> for T {
fn get_optional(self) -> Option<T> {
Some(self)
}
}
impl<T> MaybeOptional<T> for Option<T> {
fn get_optional(self) -> Option<T> {
self
}
}
pub fn get_database_url_from_env() -> Result<String, VarError> {
env::var("LEMMY_DATABASE_URL")
}
#[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
pub enum SortType {
Active,
Hot,
New,
TopDay,
TopWeek,
TopMonth,
TopYear,
TopAll,
}
#[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
pub enum ListingType {
All,
Subscribed,
Community,
}
#[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
pub enum SearchType {
All,
Comments,
Posts,
Communities,
Users,
Url,
}
pub fn fuzzy_search(q: &str) -> String {
let replaced = q.replace(" ", "%");
format!("%{}%", replaced)
}
pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) {
let page = page.unwrap_or(1);
let limit = limit.unwrap_or(10);
let offset = limit * (page - 1);
(limit, offset)
}
pub fn naive_now() -> NaiveDateTime {
chrono::prelude::Utc::now().naive_utc()
}
pub fn is_email_regex(test: &str) -> bool {
EMAIL_REGEX.is_match(test)
}
pub fn diesel_option_overwrite(opt: &Option<String>) -> Option<Option<String>> {
match opt {
// An empty string is an erase
Some(unwrapped) => {
if !unwrapped.eq("") {
Some(Some(unwrapped.to_owned()))
} else {
Some(None)
}
}
None => None,
}
}
lazy_static! {
static ref EMAIL_REGEX: Regex =
Regex::new(r"^[a-zA-Z0-9.!#$%&*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
}
#[cfg(test)]
mod tests {
use super::fuzzy_search;
use crate::{get_database_url_from_env, is_email_regex};
use diesel::{Connection, PgConnection};
pub fn establish_unpooled_connection() -> PgConnection {
let db_url = match get_database_url_from_env() {
Ok(url) => url,
Err(e) => panic!(
"Failed to read database URL from env var LEMMY_DATABASE_URL: {}",
e
),
};
PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url))
}
#[test]
fn test_fuzzy_search() {
let test = "This is a fuzzy search";
assert_eq!(fuzzy_search(test), "%This%is%a%fuzzy%search%".to_string());
}
#[test]
fn test_email() {
assert!(is_email_regex("gush@gmail.com"));
assert!(!is_email_regex("nada_neutho"));
}
}