Some GetUserDetails cleanup.

This commit is contained in:
Dessalines 2020-07-20 15:32:15 -04:00
parent 613b462662
commit ca7d2feedb
11 changed files with 78 additions and 78 deletions

2
server/Cargo.lock generated vendored
View file

@ -1549,7 +1549,9 @@ dependencies = [
"bcrypt",
"chrono",
"diesel",
"lazy_static",
"log",
"regex",
"serde 1.0.114",
"serde_json",
"sha2",

View file

@ -13,4 +13,6 @@ strum_macros = "0.18.0"
log = "0.4.0"
sha2 = "0.9"
bcrypt = "0.8.0"
url = { version = "2.1.1", features = ["serde"] }
url = { version = "2.1.1", features = ["serde"] }
lazy_static = "1.3.0"
regex = "1.3.5"

View file

@ -2,9 +2,12 @@
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;
@ -12,6 +15,7 @@ pub extern crate strum;
use chrono::NaiveDateTime;
use diesel::{dsl::*, result::Error, *};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{env, env::VarError};
@ -172,10 +176,19 @@ pub fn naive_now() -> NaiveDateTime {
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 {
@ -194,4 +207,10 @@ mod tests {
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"));
}
}

View file

@ -1,4 +1,5 @@
use crate::{
is_email_regex,
naive_now,
schema::{user_, user_::dsl::*},
Crud,
@ -125,9 +126,18 @@ impl User_ {
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)
}

View file

@ -19,4 +19,4 @@ serde_json = { version = "1.0.52", features = ["preserve_order"]}
comrak = "0.7"
lazy_static = "1.3.0"
openssl = "0.10"
url = { version = "2.1.1", features = ["serde"] }
url = { version = "2.1.1", features = ["serde"] }

View file

@ -44,10 +44,6 @@ pub fn convert_datetime(datetime: NaiveDateTime) -> DateTime<FixedOffset> {
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()
}
@ -165,7 +161,6 @@ pub fn is_valid_post_title(title: &str) -> bool {
#[cfg(test)]
mod tests {
use crate::{
is_email_regex,
is_valid_community_name,
is_valid_post_title,
is_valid_username,
@ -185,12 +180,6 @@ mod tests {
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"));

View file

@ -1,7 +1,7 @@
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;
@ -54,18 +54,6 @@ impl Claims {
.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)

View file

@ -110,7 +110,6 @@ pub struct GetUserDetailsResponse {
moderates: Vec<CommunityModeratorView>,
comments: Vec<CommentView>,
posts: Vec<PostView>,
admins: Vec<UserView>, // TODO why is this necessary, just use GetSite
}
#[derive(Serialize, Deserialize)]
@ -276,7 +275,7 @@ impl Perform for Oper<Login> {
// 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?
{
@ -643,14 +642,6 @@ impl Perform for Oper<GetUserDetails> {
})
.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
@ -665,7 +656,6 @@ impl Perform for Oper<GetUserDetails> {
moderates,
comments,
posts,
admins,
})
}
}

View file

@ -1,5 +1,4 @@
use crate::{
api::claims::Claims,
apub::{
activities::send_activity,
create_apub_response,
@ -253,7 +252,7 @@ pub async fn get_apub_user_http(
) -> 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?;

View file

@ -1,7 +1,7 @@
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,
@ -16,7 +16,6 @@ import {
CommentResponse,
BanUserResponse,
PostResponse,
AddAdminResponse,
} from '../interfaces';
import {
wsJsonToRes,
@ -41,6 +40,7 @@ interface UserDetailsProps {
enableNsfw: boolean;
view: UserDetailsView;
onPageChange(page: number): number | any;
admins: Array<UserView>;
}
interface UserDetailsState {
@ -49,7 +49,6 @@ interface UserDetailsState {
comments: Array<Comment>;
posts: Array<Post>;
saved?: Array<Post>;
admins: Array<UserView>;
}
export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
@ -63,7 +62,6 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
comments: [],
posts: [],
saved: [],
admins: [],
};
this.subscription = WebSocketService.Instance.subject
@ -152,7 +150,7 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
{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}
@ -160,7 +158,7 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
) : (
<CommentNodes
nodes={[{ comment: i.data as Comment }]}
admins={this.state.admins}
admins={this.props.admins}
noIndent
showContext
enableDownvotes={this.props.enableDownvotes}
@ -177,7 +175,7 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
<div>
<CommentNodes
nodes={commentsToFlatNodes(this.state.comments)}
admins={this.state.admins}
admins={this.props.admins}
noIndent
showContext
enableDownvotes={this.props.enableDownvotes}
@ -192,7 +190,7 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
{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}
@ -252,7 +250,6 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
follows: data.follows,
moderates: data.moderates,
posts: data.posts,
admins: data.admins,
});
} else if (res.op == UserOperation.CreateCommentLike) {
const data = res.data as CommentResponse;
@ -298,11 +295,6 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
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,
});
}
}
}

View file

@ -13,9 +13,9 @@ import {
DeleteAccountForm,
WebSocketJsonResponse,
GetSiteResponse,
Site,
UserDetailsView,
UserDetailsResponse,
AddAdminResponse,
} from '../interfaces';
import { WebSocketService, UserService } from '../services';
import {
@ -54,7 +54,7 @@ interface UserState {
deleteAccountLoading: boolean;
deleteAccountShowConfirm: boolean;
deleteAccountForm: DeleteAccountForm;
site: Site;
siteRes: GetSiteResponse;
}
interface UserProps {
@ -114,19 +114,24 @@ export class User extends Component<any, UserState> {
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,
},
},
};
@ -201,7 +206,7 @@ export class User extends Component<any, UserState> {
// 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();
}
@ -236,8 +241,9 @@ export class User extends Component<any, UserState> {
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}
/>
@ -637,7 +643,7 @@ export class User extends Component<any, UserState> {
/>
</div>
</div>
{this.state.site.enable_nsfw && (
{this.state.siteRes.site.enable_nsfw && (
<div class="form-group">
<div class="form-check">
<input
@ -1063,9 +1069,12 @@ export class User extends Component<any, UserState> {
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);
}
}
}