]> Untitled Git - lemmy.git/commitdiff
Adding admin abilities on user pages.
authorDessalines <tyhou13@gmx.com>
Mon, 14 Oct 2019 00:36:35 +0000 (17:36 -0700)
committerDessalines <tyhou13@gmx.com>
Mon, 14 Oct 2019 00:36:35 +0000 (17:36 -0700)
- Fixes #280

server/src/api/user.rs
ui/src/components/comment-node.tsx
ui/src/components/post-listing.tsx
ui/src/components/user.tsx
ui/src/interfaces.ts

index 222b6408381c1b8a99be471bf7fa8dd928a8caab..aded855723e91020a2b2cdbbc3db6a6c29f23ee8 100644 (file)
@@ -50,6 +50,7 @@ pub struct GetUserDetailsResponse {
   moderates: Vec<CommunityModeratorView>,
   comments: Vec<CommentView>,
   posts: Vec<PostView>,
+  admins: Vec<UserView>,
 }
 
 #[derive(Serialize, Deserialize)]
@@ -367,6 +368,11 @@ impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
 
     let follows = CommunityFollowerView::for_user(&conn, user_details_id)?;
     let moderates = CommunityModeratorView::for_user(&conn, user_details_id)?;
+    let site_creator_id = Site::read(&conn, 1)?.creator_id;
+    let mut admins = UserView::admins(&conn)?;
+    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);
 
     // Return the jwt
     Ok(GetUserDetailsResponse {
@@ -376,6 +382,7 @@ impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
       moderates: moderates,
       comments: comments,
       posts: posts,
+      admins: admins,
     })
   }
 }
index b45f13fcceca372be78b422044f5321624d92714..2cb556023ef815f25414ab40beea82ff900a9c0c 100644 (file)
@@ -137,7 +137,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                       </>
                     }
                     {/* Admins and mods can remove comments */}
-                    {this.canMod && 
+                    {(this.canMod || this.canAdmin) && 
                       <li className="list-inline-item">
                         {!node.comment.removed ? 
                         <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> :
index 2b7afc6b0e259f7a5d3d3c5266d9ff5609fe9e04..d0322d9849da7b9f8f69cdbaa6b1b93974d8130a 100644 (file)
@@ -24,7 +24,6 @@ interface PostListingState {
 
 interface PostListingProps {
   post: Post;
-  editable?: boolean;
   showCommunity?: boolean;
   showBody?: boolean;
   viewOnly?: boolean;
@@ -174,14 +173,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             </li>
           </ul>
           <ul class="list-inline mb-1 text-muted small font-weight-bold"> 
-            {UserService.Instance.user && this.props.editable &&
+            {UserService.Instance.user &&
               <>
-                <li className="list-inline-item mr-2">
-                  <span class="pointer" onClick={linkEvent(this, this.handleSavePostClick)}>{post.saved ? i18n.t('unsave') : i18n.t('save')}</span>
-                </li>
-                <li className="list-inline-item mr-2">
-                  <Link className="text-muted" to={`/create_post${this.crossPostParams}`}><T i18nKey="cross_post">#</T></Link>
-                </li>
+                {this.props.showBody &&
+                  <>
+                    <li className="list-inline-item mr-2">
+                      <span class="pointer" onClick={linkEvent(this, this.handleSavePostClick)}>{post.saved ? i18n.t('unsave') : i18n.t('save')}</span>
+                    </li>
+                    <li className="list-inline-item mr-2">
+                      <Link className="text-muted" to={`/create_post${this.crossPostParams}`}><T i18nKey="cross_post">#</T></Link>
+                    </li>
+                  </>
+                }
                 {this.myPost && 
                   <>
                     <li className="list-inline-item">
@@ -205,14 +208,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                   </>
                 }
                 {/* Mods can ban from community, and appoint as mods to community */}
-                {this.canMod &&
+                {(this.canMod || this.canAdmin) &&
+                  <li className="list-inline-item">
+                    {!post.removed ? 
+                    <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> :
+                    <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}><T i18nKey="restore">#</T></span>
+                    }
+                  </li>
+                }
+                {this.canMod && 
                   <>
-                    <li className="list-inline-item">
-                      {!post.removed ? 
-                      <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> :
-                      <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}><T i18nKey="restore">#</T></span>
-                      }
-                    </li>
                     {!this.isMod && 
                       <li className="list-inline-item">
                         {!post.banned_from_community ? 
@@ -326,23 +331,26 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     return this.props.admins && isMod(this.props.admins.map(a => a.id), this.props.post.creator_id);
   }
 
-  get adminsThenMods(): Array<number> {
-    return this.props.admins.map(a => a.id)
-    .concat(this.props.moderators.map(m => m.user_id));
-  }
-
   get canMod(): boolean {
+    if (this.props.admins && this.props.moderators) {
+      let adminsThenMods = this.props.admins.map(a => a.id)
+      .concat(this.props.moderators.map(m => m.user_id));
 
-    if (this.props.editable) {
-      return canMod(UserService.Instance.user, this.adminsThenMods, this.props.post.creator_id);
-    } else return false;
+      return canMod(UserService.Instance.user, adminsThenMods, this.props.post.creator_id);
+      } else { 
+      return false;
+    }
   }
 
   get canModOnSelf(): boolean {
+    if (this.props.admins && this.props.moderators) {
+      let adminsThenMods = this.props.admins.map(a => a.id)
+      .concat(this.props.moderators.map(m => m.user_id));
 
-    if (this.props.editable) {
-      return canMod(UserService.Instance.user, this.adminsThenMods, this.props.post.creator_id, true);
-    } else return false;
+      return canMod(UserService.Instance.user, adminsThenMods, this.props.post.creator_id, true);
+    } else { 
+      return false;
+    }
   }
 
   get canAdmin(): boolean {
index c5ba974f0be78dd52df032d98b535cfa936f66b0..016721ad198a84fb5630de0e5f5908371c5bfa7d 100644 (file)
@@ -2,7 +2,7 @@ import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
 import { Subscription } from "rxjs";
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse } from '../interfaces';
+import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse, BanUserResponse, AddAdminResponse } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter } from '../utils';
 import { PostListing } from './post-listing';
@@ -24,6 +24,7 @@ interface UserState {
   comments: Array<Comment>;
   posts: Array<Post>;
   saved?: Array<Post>;
+  admins: Array<UserView>;
   view: View;
   sort: SortType;
   page: number;
@@ -53,6 +54,7 @@ export class User extends Component<any, UserState> {
     moderates: [],
     comments: [],
     posts: [],
+    admins: [],
     loading: true,
     view: this.getViewFromProps(this.props),
     sort: this.getSortTypeFromProps(this.props),
@@ -199,8 +201,16 @@ export class User extends Component<any, UserState> {
         {combined.map(i =>
           <div>
             {i.type_ == "posts"
-              ? <PostListing post={i.data as Post} showCommunity viewOnly />
-              : <CommentNodes nodes={[{comment: i.data as Comment}]} noIndent />
+              ? <PostListing 
+              post={i.data as Post} 
+              admins={this.state.admins}
+              showCommunity 
+              viewOnly />
+              : 
+              <CommentNodes 
+                nodes={[{comment: i.data as Comment}]} 
+                admins={this.state.admins}
+                noIndent />
             }
           </div>
                      )
@@ -213,7 +223,9 @@ export class User extends Component<any, UserState> {
     return (
       <div>
         {this.state.comments.map(comment => 
-          <CommentNodes nodes={[{comment: comment}]} noIndent viewOnly />
+          <CommentNodes nodes={[{comment: comment}]} 
+            admins={this.state.admins}
+            noIndent />
         )}
       </div>
     );
@@ -223,7 +235,11 @@ export class User extends Component<any, UserState> {
     return (
       <div>
         {this.state.posts.map(post => 
-          <PostListing post={post} showCommunity viewOnly />
+          <PostListing 
+            post={post} 
+            admins={this.state.admins}
+            showCommunity 
+            viewOnly />
         )}
       </div>
     );
@@ -415,6 +431,7 @@ export class User extends Component<any, UserState> {
       this.state.follows = res.follows;
       this.state.moderates = res.moderates;
       this.state.posts = res.posts;
+      this.state.admins = res.admins;
       this.state.loading = false;
       if (this.isCurrentUser) {
         this.state.userSettingsForm.show_nsfw = UserService.Instance.user.show_nsfw;
@@ -454,6 +471,17 @@ export class User extends Component<any, UserState> {
       if (res.comment.my_vote !== null) 
         found.my_vote = res.comment.my_vote;
       this.setState(this.state);
+    } else if (op == UserOperation.BanUser) {
+      let res: BanUserResponse = msg;
+      this.state.comments.filter(c => c.creator_id == res.user.id)
+      .forEach(c => c.banned = res.banned);
+      this.state.posts.filter(c => c.creator_id == res.user.id)
+      .forEach(c => c.banned = res.banned);
+      this.setState(this.state);
+    } else if (op == UserOperation.AddAdmin) {
+      let res: AddAdminResponse = msg;
+      this.state.admins = res.admins;
+      this.setState(this.state);
     } else if (op == UserOperation.SaveUserSettings) {
         this.state = this.emptyState;
         this.state.userSettingsLoading = false;
index 3221415b3bf6729bb7e59929f28d5383282d17a6..b9ccf3032fe4ff84e163abc6fb424a7c8848817e 100644 (file)
@@ -172,6 +172,7 @@ export interface UserDetailsResponse {
   moderates: Array<CommunityUser>;
   comments: Array<Comment>;
   posts: Array<Post>;
+  admins: Array<UserView>;
 }
 
 export interface GetRepliesForm {