From e754e1172a93b9d067746740c8d636fec179bc5f Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Thu, 22 Oct 2020 09:37:30 +0200 Subject: [PATCH] Disable updating/deleting group posts and discussions for non-moderators Signed-off-by: Thomas Citharel --- js/src/components/Post/PostElementItem.vue | 2 +- js/src/graphql/discussion.ts | 1 + js/src/mixins/group.ts | 11 +++++++- js/src/variables.scss | 1 + js/src/views/Discussions/Discussion.vue | 31 ++++++++++++---------- js/src/views/Posts/List.vue | 4 +++ js/src/views/Posts/Post.vue | 7 +++-- 7 files changed, 39 insertions(+), 18 deletions(-) diff --git a/js/src/components/Post/PostElementItem.vue b/js/src/components/Post/PostElementItem.vue index 79c1a26f4..1e1f8b3e1 100644 --- a/js/src/components/Post/PostElementItem.vue +++ b/js/src/components/Post/PostElementItem.vue @@ -33,7 +33,7 @@ $options.filters.formatDateTimeString(new Date(post.insertedAt), false) }} {{ - $t("Created by {username}", { username: usernameWithDomain(post.author) }) + $t("Created by {username}", { username: `@${usernameWithDomain(post.author)}` }) }} diff --git a/js/src/graphql/discussion.ts b/js/src/graphql/discussion.ts index 460a136f6..9e29e2585 100644 --- a/js/src/graphql/discussion.ts +++ b/js/src/graphql/discussion.ts @@ -158,6 +158,7 @@ export const DISCUSSION_COMMENT_CHANGED = gql` actor { id preferredUsername + name domain avatar { url diff --git a/js/src/mixins/group.ts b/js/src/mixins/group.ts index 0781d06be..1cc4f6238 100644 --- a/js/src/mixins/group.ts +++ b/js/src/mixins/group.ts @@ -44,10 +44,19 @@ export default class GroupMixin extends Vue { person!: IPerson; get isCurrentActorAGroupAdmin(): boolean { + return this.hasCurrentActorThisRole(MemberRole.ADMINISTRATOR); + } + + get isCurrentActorAGroupModerator(): boolean { + return this.hasCurrentActorThisRole([MemberRole.MODERATOR, MemberRole.ADMINISTRATOR]); + } + + hasCurrentActorThisRole(givenRole: string | string[]): boolean { + const roles = Array.isArray(givenRole) ? givenRole : [givenRole]; return ( this.person && this.person.memberships.elements.some( - ({ parent: { id }, role }) => id === this.group.id && role === MemberRole.ADMINISTRATOR + ({ parent: { id }, role }) => id === this.group.id && roles.includes(role) ) ); } diff --git a/js/src/variables.scss b/js/src/variables.scss index d810f290e..6a4128112 100644 --- a/js/src/variables.scss +++ b/js/src/variables.scss @@ -104,6 +104,7 @@ $hero-body-padding-medium: 6rem 1.5rem; main > .container { background: $body-background-color; + min-height: 70vh; } $title-color: #3c376e; diff --git a/js/src/views/Discussions/Discussion.vue b/js/src/views/Discussions/Discussion.vue index fea1f7937..4faaba3f1 100644 --- a/js/src/views/Discussions/Discussion.vue +++ b/js/src/views/Discussions/Discussion.vue @@ -39,6 +39,7 @@

{{ discussion.title }} -import { Component, Prop, Vue } from "vue-property-decorator"; +import { Component, Prop } from "vue-property-decorator"; +import { mixins } from "vue-class-component"; import { GET_DISCUSSION, REPLY_TO_DISCUSSION, @@ -113,6 +115,7 @@ import { usernameWithDomain } from "@/types/actor"; import DiscussionComment from "@/components/Discussion/DiscussionComment.vue"; import { GraphQLError } from "graphql"; import { DELETE_COMMENT, UPDATE_COMMENT } from "@/graphql/comment"; +import GroupMixin from "@/mixins/group"; import RouteName from "../../router/name"; import { IComment } from "../../types/comment.model"; @@ -170,7 +173,7 @@ import { IComment } from "../../types/comment.model"; }, metaInfo() { return { - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore title: this.discussion.title, // all titles will be injected into this template @@ -178,7 +181,7 @@ import { IComment } from "../../types/comment.model"; }; }, }) -export default class discussion extends Vue { +export default class discussion extends mixins(GroupMixin) { @Prop({ type: String, required: true }) slug!: string; discussion: IDiscussion = new Discussion(); @@ -199,7 +202,7 @@ export default class discussion extends Vue { usernameWithDomain = usernameWithDomain; - async reply() { + async reply(): Promise { if (this.newComment === "") return; await this.$apollo.mutate({ @@ -234,7 +237,7 @@ export default class discussion extends Vue { this.newComment = ""; } - async updateComment(comment: IComment) { + async updateComment(comment: IComment): Promise { const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({ mutation: UPDATE_COMMENT, variables: { @@ -270,7 +273,7 @@ export default class discussion extends Vue { }); } - async deleteComment(comment: IComment) { + async deleteComment(comment: IComment): Promise { const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({ mutation: DELETE_COMMENT, variables: { @@ -308,7 +311,7 @@ export default class discussion extends Vue { }); } - async loadMoreComments() { + async loadMoreComments(): Promise { if (!this.hasMoreComments) return; this.page += 1; try { @@ -338,7 +341,7 @@ export default class discussion extends Vue { } } - async updateDiscussion() { + async updateDiscussion(): Promise { await this.$apollo.mutate({ mutation: UPDATE_DISCUSSION, variables: { @@ -368,7 +371,7 @@ export default class discussion extends Vue { this.editTitleMode = false; } - async deleteConversation() { + async deleteConversation(): Promise { await this.$apollo.mutate({ mutation: DELETE_DISCUSSION, variables: { @@ -376,28 +379,28 @@ export default class discussion extends Vue { }, }); if (this.discussion.actor) { - return this.$router.push({ + this.$router.push({ name: RouteName.DISCUSSION_LIST, params: { preferredUsername: usernameWithDomain(this.discussion.actor) }, }); } } - async handleErrors(errors: GraphQLError[]) { + async handleErrors(errors: GraphQLError[]): Promise { if (errors[0].message.includes("No such discussion")) { await this.$router.push({ name: RouteName.PAGE_NOT_FOUND }); } } - mounted() { + mounted(): void { window.addEventListener("scroll", this.handleScroll); } - destroyed() { + destroyed(): void { window.removeEventListener("scroll", this.handleScroll); } - handleScroll() { + handleScroll(): void { const scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop; const scrollHeight = diff --git a/js/src/views/Posts/List.vue b/js/src/views/Posts/List.vue index 214704117..34eec51f1 100644 --- a/js/src/views/Posts/List.vue +++ b/js/src/views/Posts/List.vue @@ -157,6 +157,10 @@ export default class PostList extends Vue { }