"bcrypt",
"chrono",
"diesel",
+ "lazy_static",
"log",
+ "regex",
"serde 1.0.114",
"serde_json",
"sha2",
log = "0.4.0"
sha2 = "0.9"
bcrypt = "0.8.0"
-url = { version = "2.1.1", features = ["serde"] }
\ No newline at end of file
+url = { version = "2.1.1", features = ["serde"] }
+lazy_static = "1.3.0"
+regex = "1.3.5"
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;
use chrono::NaiveDateTime;
use diesel::{dsl::*, result::Error, *};
+use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{env, env::VarError};
chrono::prelude::Utc::now().naive_utc()
}
+pub fn is_email_regex(test: &str) -> bool {
+ EMAIL_REGEX.is_match(test)
+}
+
+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;
+ use crate::{get_database_url_from_env, is_email_regex};
use diesel::{Connection, PgConnection};
pub fn establish_unpooled_connection() -> PgConnection {
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"));
+ }
}
use crate::{
+ is_email_regex,
naive_now,
schema::{user_, user_::dsl::*},
Crud,
use crate::schema::user_::dsl::*;
user_.filter(actor_id.eq(object_id)).first::<Self>(conn)
}
-}
-impl User_ {
+ pub fn find_by_email_or_username(
+ conn: &PgConnection,
+ username_or_email: &str,
+ ) -> Result<Self, Error> {
+ if is_email_regex(username_or_email) {
+ Self::find_by_email(conn, username_or_email)
+ } else {
+ Self::find_by_username(conn, username_or_email)
+ }
+ }
+
pub fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
user_.filter(name.eq(username)).first::<User_>(conn)
}
comrak = "0.7"
lazy_static = "1.3.0"
openssl = "0.10"
-url = { version = "2.1.1", features = ["serde"] }
\ No newline at end of file
+url = { version = "2.1.1", features = ["serde"] }
DateTime::<FixedOffset>::from_utc(datetime, *now.offset())
}
-pub fn is_email_regex(test: &str) -> bool {
- EMAIL_REGEX.is_match(test)
-}
-
pub fn remove_slurs(test: &str) -> String {
SLUR_REGEX.replace_all(test, "*removed*").to_string()
}
#[cfg(test)]
mod tests {
use crate::{
- is_email_regex,
is_valid_community_name,
is_valid_post_title,
is_valid_username,
assert_eq!(mentions[1].domain, "lemmy-alpha:8540".to_string());
}
- #[test]
- fn test_email() {
- assert!(is_email_regex("gush@gmail.com"));
- assert!(!is_email_regex("nada_neutho"));
- }
-
#[test]
fn test_valid_register_username() {
assert!(is_valid_username("Hello_98"));
use diesel::{result::Error, PgConnection};
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation};
use lemmy_db::{user::User_, Crud};
-use lemmy_utils::{is_email_regex, settings::Settings};
+use lemmy_utils::settings::Settings;
use serde::{Deserialize, Serialize};
type Jwt = String;
.unwrap()
}
- // TODO: move these into user?
- pub fn find_by_email_or_username(
- conn: &PgConnection,
- username_or_email: &str,
- ) -> Result<User_, Error> {
- if is_email_regex(username_or_email) {
- User_::find_by_email(conn, username_or_email)
- } else {
- User_::find_by_username(conn, username_or_email)
- }
- }
-
pub fn find_by_jwt(conn: &PgConnection, jwt: &str) -> Result<User_, Error> {
let claims: Claims = Claims::decode(&jwt).expect("Invalid token").claims;
User_::read(&conn, claims.id)
moderates: Vec<CommunityModeratorView>,
comments: Vec<CommentView>,
posts: Vec<PostView>,
- admins: Vec<UserView>, // TODO why is this necessary, just use GetSite
}
#[derive(Serialize, Deserialize)]
// Fetch that username / email
let username_or_email = data.username_or_email.clone();
let user = match blocking(pool, move |conn| {
- Claims::find_by_email_or_username(conn, &username_or_email)
+ User_::find_by_email_or_username(conn, &username_or_email)
})
.await?
{
})
.await??;
- let site_creator_id =
- blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??;
-
- let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
- let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
- let creator_user = admins.remove(creator_index);
- admins.insert(0, creator_user);
-
// If its not the same user, remove the email, and settings
// TODO an if let chain would be better here, but can't figure it out
// TODO separate out settings into its own thing
moderates,
comments,
posts,
- admins,
})
}
}
use crate::{
- api::claims::Claims,
apub::{
activities::send_activity,
create_apub_response,
) -> Result<HttpResponse<Body>, LemmyError> {
let user_name = info.into_inner().user_name;
let user = blocking(&db, move |conn| {
- Claims::find_by_email_or_username(conn, &user_name)
+ User_::find_by_email_or_username(conn, &user_name)
})
.await??;
let u = user.to_apub(&db).await?;
import { Component, linkEvent } from 'inferno';
import { WebSocketService, UserService } from '../services';
import { Subscription } from 'rxjs';
-import { retryWhen, delay, take, last } from 'rxjs/operators';
+import { retryWhen, delay, take } from 'rxjs/operators';
import { i18n } from '../i18next';
import {
UserOperation,
CommentResponse,
BanUserResponse,
PostResponse,
- AddAdminResponse,
} from '../interfaces';
import {
wsJsonToRes,
enableNsfw: boolean;
view: UserDetailsView;
onPageChange(page: number): number | any;
+ admins: Array<UserView>;
}
interface UserDetailsState {
comments: Array<Comment>;
posts: Array<Post>;
saved?: Array<Post>;
- admins: Array<UserView>;
}
export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
comments: [],
posts: [],
saved: [],
- admins: [],
};
this.subscription = WebSocketService.Instance.subject
{i.type === 'posts' ? (
<PostListing
post={i.data as Post}
- admins={this.state.admins}
+ admins={this.props.admins}
showCommunity
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
) : (
<CommentNodes
nodes={[{ comment: i.data as Comment }]}
- admins={this.state.admins}
+ admins={this.props.admins}
noIndent
showContext
enableDownvotes={this.props.enableDownvotes}
<div>
<CommentNodes
nodes={commentsToFlatNodes(this.state.comments)}
- admins={this.state.admins}
+ admins={this.props.admins}
noIndent
showContext
enableDownvotes={this.props.enableDownvotes}
{this.state.posts.map(post => (
<PostListing
post={post}
- admins={this.state.admins}
+ admins={this.props.admins}
showCommunity
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
follows: data.follows,
moderates: data.moderates,
posts: data.posts,
- admins: data.admins,
});
} else if (res.op == UserOperation.CreateCommentLike) {
const data = res.data as CommentResponse;
posts: this.state.posts,
comments: this.state.comments,
});
- } else if (res.op == UserOperation.AddAdmin) {
- const data = res.data as AddAdminResponse;
- this.setState({
- admins: data.admins,
- });
}
}
}
DeleteAccountForm,
WebSocketJsonResponse,
GetSiteResponse,
- Site,
UserDetailsView,
UserDetailsResponse,
+ AddAdminResponse,
} from '../interfaces';
import { WebSocketService, UserService } from '../services';
import {
deleteAccountLoading: boolean;
deleteAccountShowConfirm: boolean;
deleteAccountForm: DeleteAccountForm;
- site: Site;
+ siteRes: GetSiteResponse;
}
interface UserProps {
deleteAccountForm: {
password: null,
},
- site: {
- id: undefined,
- name: undefined,
- creator_id: undefined,
- published: undefined,
- creator_name: undefined,
- number_of_users: undefined,
- number_of_posts: undefined,
- number_of_comments: undefined,
- number_of_communities: undefined,
- enable_downvotes: undefined,
- open_registration: undefined,
- enable_nsfw: undefined,
+ siteRes: {
+ admins: [],
+ banned: [],
+ online: undefined,
+ site: {
+ id: undefined,
+ name: undefined,
+ creator_id: undefined,
+ published: undefined,
+ creator_name: undefined,
+ number_of_users: undefined,
+ number_of_posts: undefined,
+ number_of_comments: undefined,
+ number_of_communities: undefined,
+ enable_downvotes: undefined,
+ open_registration: undefined,
+ enable_nsfw: undefined,
+ },
},
};
// Couldnt get a refresh working. This does for now.
location.reload();
}
- document.title = `/u/${this.state.username} - ${this.state.site.name}`;
+ document.title = `/u/${this.state.username} - ${this.state.siteRes.site.name}`;
setupTippy();
}
sort={SortType[this.state.sort]}
page={this.state.page}
limit={fetchLimit}
- enableDownvotes={this.state.site.enable_downvotes}
- enableNsfw={this.state.site.enable_nsfw}
+ enableDownvotes={this.state.siteRes.site.enable_downvotes}
+ enableNsfw={this.state.siteRes.site.enable_nsfw}
+ admins={this.state.siteRes.admins}
view={this.state.view}
onPageChange={this.handlePageChange}
/>
/>
</div>
</div>
- {this.state.site.enable_nsfw && (
+ {this.state.siteRes.site.enable_nsfw && (
<div class="form-group">
<div class="form-check">
<input
this.context.router.history.push('/');
} else if (res.op == UserOperation.GetSite) {
const data = res.data as GetSiteResponse;
- this.setState({
- site: data.site,
- });
+ this.state.siteRes = data;
+ this.setState(this.state);
+ } else if (res.op == UserOperation.AddAdmin) {
+ const data = res.data as AddAdminResponse;
+ this.state.siteRes.admins = data.admins;
+ this.setState(this.state);
}
}
}