Some GetUserDetails cleanup.
This commit is contained in:
parent
613b462662
commit
ca7d2feedb
11 changed files with 78 additions and 78 deletions
2
server/Cargo.lock
generated
vendored
2
server/Cargo.lock
generated
vendored
|
@ -1549,7 +1549,9 @@ dependencies = [
|
|||
"bcrypt",
|
||||
"chrono",
|
||||
"diesel",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"regex",
|
||||
"serde 1.0.114",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
|
|
2
server/lemmy_db/Cargo.toml
vendored
2
server/lemmy_db/Cargo.toml
vendored
|
@ -14,3 +14,5 @@ log = "0.4.0"
|
|||
sha2 = "0.9"
|
||||
bcrypt = "0.8.0"
|
||||
url = { version = "2.1.1", features = ["serde"] }
|
||||
lazy_static = "1.3.0"
|
||||
regex = "1.3.5"
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl User_ {
|
||||
pub fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
|
||||
user_.filter(name.eq(username)).first::<User_>(conn)
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?;
|
||||
|
|
20
ui/src/components/user-details.tsx
vendored
20
ui/src/components/user-details.tsx
vendored
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
27
ui/src/components/user.tsx
vendored
27
ui/src/components/user.tsx
vendored
|
@ -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,6 +114,10 @@ export class User extends Component<any, UserState> {
|
|||
deleteAccountForm: {
|
||||
password: null,
|
||||
},
|
||||
siteRes: {
|
||||
admins: [],
|
||||
banned: [],
|
||||
online: undefined,
|
||||
site: {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
|
@ -128,6 +132,7 @@ export class User extends Component<any, UserState> {
|
|||
open_registration: undefined,
|
||||
enable_nsfw: undefined,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue