]> Untitled Git - lemmy.git/commitdiff
Some GetUserDetails cleanup.
authorDessalines <tyhou13@gmx.com>
Mon, 20 Jul 2020 19:32:15 +0000 (15:32 -0400)
committerDessalines <tyhou13@gmx.com>
Mon, 20 Jul 2020 19:32:15 +0000 (15:32 -0400)
server/Cargo.lock
server/lemmy_db/Cargo.toml
server/lemmy_db/src/lib.rs
server/lemmy_db/src/user.rs
server/lemmy_utils/Cargo.toml
server/lemmy_utils/src/lib.rs
server/src/api/claims.rs
server/src/api/user.rs
server/src/apub/user.rs
ui/src/components/user-details.tsx
ui/src/components/user.tsx

index 1e0e04f861bb28d1adeea805438e2996bac21318..44fb405ea0975cd8008005c501765fceed0c3e96 100644 (file)
@@ -1549,7 +1549,9 @@ dependencies = [
  "bcrypt",
  "chrono",
  "diesel",
+ "lazy_static",
  "log",
+ "regex",
  "serde 1.0.114",
  "serde_json",
  "sha2",
index f10f217efec9dab91c2e944ec787aaec65edc881..6d342c1e76f492b0bc6de5b81d56c4e76ce67c0b 100644 (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"] }
\ No newline at end of file
+url = { version = "2.1.1", features = ["serde"] }
+lazy_static = "1.3.0"
+regex = "1.3.5"
index 2eead841d7dc25f3e22170d1fdbf8416f5704731..cca2994b8cc62467340798494fa9e48712f3dcf4 100644 (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"));
+  }
 }
index 718067f998570eb9e7d467f48ea8a23706d33633..e53890770b2365c5002d80631e1ec11332aadc0c 100644 (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)
   }
index fed22f585f8602fb58f50f29a6ec1c2cbff2faa3..9685c0edaafef7b0017fab6ed4a196b706ad5618 100644 (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"] }
\ No newline at end of file
+url = { version = "2.1.1", features = ["serde"] }
index d88335e2da5cf260b27fcdf91b769067ebfb9749..6d851b0337bf39681501ed734713da061fc0be1b 100644 (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"));
index eec9d1a71b4ab5920f609b28c3f73992bc8ce234..9118714ba1986a4f6ef3281cfca5a9f20da6c913 100644 (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)
index 2e62182396eccc444e5eb0f901c9ba4f22037206..71fecea78a5bd9ce96c90e6219cf9becd38ee8c5 100644 (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,
     })
   }
 }
index 2a98670ce3aff5b04530061ffdc0c7a4ab0b3049..403c4d4a803559ae8ff140c573ff9d2e6dde0fae 100644 (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?;
index 49b9589e73d3d759ca4ef3de966178c3620b49f0..5f2346a240f3baf11fa4a12e34de8795e8062be1 100644 (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,
-      });
     }
   }
 }
index 468d29801da41b6f07df6845d092c80d2e93ecaf..8ff5c3929b581eedd7e4387746b18c0a5b6379f0 100644 (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);
     }
   }
 }