mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-26 06:11:26 +00:00
More moderation fixed
This commit is contained in:
parent
9afadfb9c4
commit
e14e6e53cd
11 changed files with 93 additions and 52 deletions
|
@ -184,7 +184,7 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
category_id: 1,
|
category_id: 1,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,8 +196,8 @@ mod tests {
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
locked: false,
|
locked: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
category_id: 1,
|
category_id: 1,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,8 +180,8 @@ mod tests {
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
locked: false,
|
locked: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub struct CommunityForm {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub category_id: i32,
|
pub category_id: i32,
|
||||||
pub creator_id: i32,
|
pub creator_id: i32,
|
||||||
pub removed: bool,
|
pub removed: Option<bool>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>
|
pub updated: Option<chrono::NaiveDateTime>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ mod tests {
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
category_id: 1,
|
category_id: 1,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,7 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
category_id: 1,
|
category_id: 1,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -453,8 +453,8 @@ mod tests {
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
locked: false,
|
locked: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ pub struct PostForm {
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub creator_id: i32,
|
pub creator_id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: i32,
|
||||||
pub removed: bool,
|
pub removed: Option<bool>,
|
||||||
pub locked: bool,
|
pub locked: Option<bool>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>
|
pub updated: Option<chrono::NaiveDateTime>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
category_id: 1,
|
category_id: 1,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,8 +210,8 @@ mod tests {
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
locked: false,
|
locked: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
category_id: 1,
|
category_id: 1,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -212,8 +212,8 @@ mod tests {
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_user.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: false,
|
removed: None,
|
||||||
locked: false,
|
locked: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -261,8 +261,8 @@ pub struct EditPost {
|
||||||
name: String,
|
name: String,
|
||||||
url: Option<String>,
|
url: Option<String>,
|
||||||
body: Option<String>,
|
body: Option<String>,
|
||||||
removed: bool,
|
removed: Option<bool>,
|
||||||
locked: bool,
|
locked: Option<bool>,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
auth: String
|
auth: String
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ pub struct EditCommunity {
|
||||||
title: String,
|
title: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
category_id: i32,
|
category_id: i32,
|
||||||
removed: bool,
|
removed: Option<bool>,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
expires: Option<i64>,
|
expires: Option<i64>,
|
||||||
auth: String
|
auth: String
|
||||||
|
@ -836,14 +836,13 @@ impl Perform for CreateCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// When you create a community, make sure the user becomes a moderator and a follower
|
// When you create a community, make sure the user becomes a moderator and a follower
|
||||||
|
|
||||||
let community_form = CommunityForm {
|
let community_form = CommunityForm {
|
||||||
name: self.name.to_owned(),
|
name: self.name.to_owned(),
|
||||||
title: self.title.to_owned(),
|
title: self.title.to_owned(),
|
||||||
description: self.description.to_owned(),
|
description: self.description.to_owned(),
|
||||||
category_id: self.category_id,
|
category_id: self.category_id,
|
||||||
creator_id: user_id,
|
creator_id: user_id,
|
||||||
removed: false,
|
removed: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -988,8 +987,8 @@ impl Perform for CreatePost {
|
||||||
body: self.body.to_owned(),
|
body: self.body.to_owned(),
|
||||||
community_id: self.community_id,
|
community_id: self.community_id,
|
||||||
creator_id: user_id,
|
creator_id: user_id,
|
||||||
removed: false,
|
removed: None,
|
||||||
locked: false,
|
locked: None,
|
||||||
updated: None
|
updated: None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1612,15 +1611,24 @@ impl Perform for EditPost {
|
||||||
|
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
// Verify its the creator or a mod
|
// Verify its the creator or a mod or admin
|
||||||
let mut editors: Vec<i32> = CommunityModeratorView::for_community(&conn, self.community_id)
|
let mut editors: Vec<i32> = vec![self.creator_id];
|
||||||
|
editors.append(
|
||||||
|
&mut CommunityModeratorView::for_community(&conn, self.community_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|m| m.user_id)
|
.map(|m| m.user_id)
|
||||||
.collect();
|
.collect()
|
||||||
editors.push(self.creator_id);
|
);
|
||||||
|
editors.append(
|
||||||
|
&mut UserView::admins(&conn)
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|a| a.id)
|
||||||
|
.collect()
|
||||||
|
);
|
||||||
if !editors.contains(&user_id) {
|
if !editors.contains(&user_id) {
|
||||||
return self.error("Not allowed to edit comment.");
|
return self.error("Not allowed to edit post.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
|
@ -1652,21 +1660,21 @@ impl Perform for EditPost {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
if self.removed {
|
if let Some(removed) = self.removed.to_owned() {
|
||||||
let form = ModRemovePostForm {
|
let form = ModRemovePostForm {
|
||||||
mod_user_id: user_id,
|
mod_user_id: user_id,
|
||||||
post_id: self.edit_id,
|
post_id: self.edit_id,
|
||||||
removed: Some(self.removed),
|
removed: Some(removed),
|
||||||
reason: self.reason.to_owned(),
|
reason: self.reason.to_owned(),
|
||||||
};
|
};
|
||||||
ModRemovePost::create(&conn, &form).unwrap();
|
ModRemovePost::create(&conn, &form).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.locked {
|
if let Some(locked) = self.locked.to_owned() {
|
||||||
let form = ModLockPostForm {
|
let form = ModLockPostForm {
|
||||||
mod_user_id: user_id,
|
mod_user_id: user_id,
|
||||||
post_id: self.edit_id,
|
post_id: self.edit_id,
|
||||||
locked: Some(self.locked),
|
locked: Some(locked),
|
||||||
};
|
};
|
||||||
ModLockPost::create(&conn, &form).unwrap();
|
ModLockPost::create(&conn, &form).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1803,7 +1811,7 @@ impl Perform for EditCommunity {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
if self.removed {
|
if let Some(removed) = self.removed.to_owned() {
|
||||||
let expires = match self.expires {
|
let expires = match self.expires {
|
||||||
Some(time) => Some(naive_from_unix(time)),
|
Some(time) => Some(naive_from_unix(time)),
|
||||||
None => None
|
None => None
|
||||||
|
@ -1811,7 +1819,7 @@ impl Perform for EditCommunity {
|
||||||
let form = ModRemoveCommunityForm {
|
let form = ModRemoveCommunityForm {
|
||||||
mod_user_id: user_id,
|
mod_user_id: user_id,
|
||||||
community_id: self.edit_id,
|
community_id: self.edit_id,
|
||||||
removed: Some(self.removed),
|
removed: Some(removed),
|
||||||
reason: self.reason.to_owned(),
|
reason: self.reason.to_owned(),
|
||||||
expires: expires
|
expires: expires
|
||||||
};
|
};
|
||||||
|
|
|
@ -212,15 +212,15 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get isMod(): boolean {
|
get isMod(): boolean {
|
||||||
return isMod(this.props.moderators.map(m => m.user_id), this.props.node.comment.creator_id);
|
return this.props.moderators && isMod(this.props.moderators.map(m => m.user_id), this.props.node.comment.creator_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isAdmin(): boolean {
|
get isAdmin(): boolean {
|
||||||
return isMod(this.props.admins.map(a => a.id), this.props.node.comment.creator_id);
|
return this.props.admins && isMod(this.props.admins.map(a => a.id), this.props.node.comment.creator_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
get canAdmin(): boolean {
|
get canAdmin(): boolean {
|
||||||
return canMod(UserService.Instance.user, this.props.admins.map(a => a.id), this.props.node.comment.creator_id);
|
return this.props.admins && canMod(UserService.Instance.user, this.props.admins.map(a => a.id), this.props.node.comment.creator_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReplyClick(i: CommentNode) {
|
handleReplyClick(i: CommentNode) {
|
||||||
|
@ -240,7 +240,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
creator_id: i.props.node.comment.creator_id,
|
creator_id: i.props.node.comment.creator_id,
|
||||||
post_id: i.props.node.comment.post_id,
|
post_id: i.props.node.comment.post_id,
|
||||||
parent_id: i.props.node.comment.parent_id,
|
parent_id: i.props.node.comment.parent_id,
|
||||||
removed: i.props.node.comment.removed,
|
|
||||||
auth: null
|
auth: null
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.editComment(deleteForm);
|
WebSocketService.Instance.editComment(deleteForm);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { Link } from 'inferno-router';
|
import { Link } from 'inferno-router';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import { Post, CreatePostLikeForm, PostForm as PostFormI, SavePostForm } from '../interfaces';
|
import { Post, CreatePostLikeForm, PostForm as PostFormI, SavePostForm, CommunityUser, UserView } from '../interfaces';
|
||||||
import { MomentTime } from './moment-time';
|
import { MomentTime } from './moment-time';
|
||||||
import { PostForm } from './post-form';
|
import { PostForm } from './post-form';
|
||||||
import { mdToHtml } from '../utils';
|
import { mdToHtml, canMod, isMod } from '../utils';
|
||||||
|
|
||||||
interface PostListingState {
|
interface PostListingState {
|
||||||
showEdit: boolean;
|
showEdit: boolean;
|
||||||
|
@ -19,6 +19,8 @@ interface PostListingProps {
|
||||||
showCommunity?: boolean;
|
showCommunity?: boolean;
|
||||||
showBody?: boolean;
|
showBody?: boolean;
|
||||||
viewOnly?: boolean;
|
viewOnly?: boolean;
|
||||||
|
moderators?: Array<CommunityUser>;
|
||||||
|
admins?: Array<UserView>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PostListing extends Component<PostListingProps, PostListingState> {
|
export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
@ -98,6 +100,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
<span>by </span>
|
<span>by </span>
|
||||||
<Link className="text-info" to={`/user/${post.creator_id}`}>{post.creator_name}</Link>
|
<Link className="text-info" to={`/user/${post.creator_id}`}>{post.creator_name}</Link>
|
||||||
|
{this.isMod &&
|
||||||
|
<span className="mx-1 badge badge-secondary">mod</span>
|
||||||
|
}
|
||||||
|
{this.isAdmin &&
|
||||||
|
<span className="mx-1 badge badge-secondary">admin</span>
|
||||||
|
}
|
||||||
{this.props.showCommunity &&
|
{this.props.showCommunity &&
|
||||||
<span>
|
<span>
|
||||||
<span> to </span>
|
<span> to </span>
|
||||||
|
@ -135,7 +143,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
{this.props.post.am_mod &&
|
{this.canMod &&
|
||||||
<span>
|
<span>
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
{!this.props.post.removed ?
|
{!this.props.post.removed ?
|
||||||
|
@ -166,6 +174,29 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
return UserService.Instance.user && this.props.post.creator_id == UserService.Instance.user.id;
|
return UserService.Instance.user && this.props.post.creator_id == UserService.Instance.user.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get canMod(): boolean {
|
||||||
|
|
||||||
|
if (this.props.editable) {
|
||||||
|
let adminsThenMods = this.props.admins.map(a => a.id)
|
||||||
|
.concat(this.props.moderators.map(m => m.user_id));
|
||||||
|
|
||||||
|
return canMod(UserService.Instance.user, adminsThenMods, this.props.post.creator_id);
|
||||||
|
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isMod(): boolean {
|
||||||
|
return this.props.moderators && isMod(this.props.moderators.map(m => m.user_id), this.props.post.creator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
get isAdmin(): boolean {
|
||||||
|
return this.props.admins && isMod(this.props.admins.map(a => a.id), this.props.post.creator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
get canAdmin(): boolean {
|
||||||
|
return this.props.admins && canMod(UserService.Instance.user, this.props.admins.map(a => a.id), this.props.post.creator_id);
|
||||||
|
}
|
||||||
|
|
||||||
handlePostLike(i: PostListing) {
|
handlePostLike(i: PostListing) {
|
||||||
|
|
||||||
let form: CreatePostLikeForm = {
|
let form: CreatePostLikeForm = {
|
||||||
|
@ -207,8 +238,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
url: '',
|
url: '',
|
||||||
edit_id: i.props.post.id,
|
edit_id: i.props.post.id,
|
||||||
creator_id: i.props.post.creator_id,
|
creator_id: i.props.post.creator_id,
|
||||||
removed: !i.props.post.removed,
|
|
||||||
locked: !i.props.post.locked,
|
|
||||||
auth: null
|
auth: null
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.editPost(deleteForm);
|
WebSocketService.Instance.editPost(deleteForm);
|
||||||
|
@ -242,7 +271,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
edit_id: i.props.post.id,
|
edit_id: i.props.post.id,
|
||||||
creator_id: i.props.post.creator_id,
|
creator_id: i.props.post.creator_id,
|
||||||
removed: !i.props.post.removed,
|
removed: !i.props.post.removed,
|
||||||
locked: !i.props.post.locked,
|
|
||||||
reason: i.state.removeReason,
|
reason: i.state.removeReason,
|
||||||
auth: null,
|
auth: null,
|
||||||
};
|
};
|
||||||
|
@ -258,7 +286,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
community_id: i.props.post.community_id,
|
community_id: i.props.post.community_id,
|
||||||
edit_id: i.props.post.id,
|
edit_id: i.props.post.id,
|
||||||
creator_id: i.props.post.creator_id,
|
creator_id: i.props.post.creator_id,
|
||||||
removed: !i.props.post.removed,
|
|
||||||
locked: !i.props.post.locked,
|
locked: !i.props.post.locked,
|
||||||
auth: null,
|
auth: null,
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,7 +82,14 @@ export class Post extends Component<any, PostState> {
|
||||||
<h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> :
|
<h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> :
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md-8 col-lg-7 mb-3">
|
<div class="col-12 col-md-8 col-lg-7 mb-3">
|
||||||
<PostListing post={this.state.post} showBody showCommunity editable />
|
<PostListing
|
||||||
|
post={this.state.post}
|
||||||
|
showBody
|
||||||
|
showCommunity
|
||||||
|
editable
|
||||||
|
moderators={this.state.moderators}
|
||||||
|
admins={this.state.admins}
|
||||||
|
/>
|
||||||
<div className="mb-2" />
|
<div className="mb-2" />
|
||||||
<CommentForm postId={this.state.post.id} disabled={this.state.post.locked} />
|
<CommentForm postId={this.state.post.id} disabled={this.state.post.locked} />
|
||||||
{this.sortRadios()}
|
{this.sortRadios()}
|
||||||
|
|
|
@ -370,8 +370,8 @@ export interface PostForm {
|
||||||
updated?: number;
|
updated?: number;
|
||||||
edit_id?: number;
|
edit_id?: number;
|
||||||
creator_id: number;
|
creator_id: number;
|
||||||
removed: boolean;
|
removed?: boolean;
|
||||||
locked: boolean;
|
locked?: boolean;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
auth: string;
|
auth: string;
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ export interface CommentForm {
|
||||||
parent_id?: number;
|
parent_id?: number;
|
||||||
edit_id?: number;
|
edit_id?: number;
|
||||||
creator_id: number;
|
creator_id: number;
|
||||||
removed: boolean;
|
removed?: boolean;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
auth: string;
|
auth: string;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue