diff --git a/config/config.exs b/config/config.exs index 177bcc9bf..632d7111c 100644 --- a/config/config.exs +++ b/config/config.exs @@ -67,6 +67,7 @@ config :mobilizon, Mobilizon.Web.Upload, filters: [ Mobilizon.Web.Upload.Filter.Dedupe, Mobilizon.Web.Upload.Filter.AnalyzeMetadata, + Mobilizon.Web.Upload.Filter.Resize, Mobilizon.Web.Upload.Filter.Optimize ], allow_list_mime_types: ["image/gif", "image/jpeg", "image/png", "image/webp"], diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 46447aaf8..5d09d0b9c 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -45,7 +45,7 @@ LABEL org.opencontainers.image.title="mobilizon" \ org.opencontainers.image.revision=$VCS_REF \ org.opencontainers.image.created=$BUILD_DATE -RUN apk add --no-cache openssl ncurses-libs file postgresql-client libgcc libstdc++ imagemagick +RUN apk add --no-cache openssl ca-certificates ncurses-libs file postgresql-client libgcc libstdc++ imagemagick RUN mkdir -p /app/uploads && chown nobody:nobody /app/uploads RUN mkdir -p /etc/mobilizon && chown nobody:nobody /etc/mobilizon diff --git a/js/src/graphql/actor.ts b/js/src/graphql/actor.ts index 431ba2b84..54f616d94 100644 --- a/js/src/graphql/actor.ts +++ b/js/src/graphql/actor.ts @@ -117,6 +117,19 @@ export const GET_PERSON = gql` } `; +export const PERSON_FRAGMENT = gql` + fragment PersonFragment on Person { + id + avatar { + id + url + } + type + preferredUsername + name + } +`; + export const LIST_PROFILES = gql` query ListProfiles( $preferredUsername: String diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json index 234ea1da5..55450901f 100644 --- a/js/src/i18n/en_US.json +++ b/js/src/i18n/en_US.json @@ -1067,5 +1067,10 @@ "View less": "View less", "View more": "View more", "Breadcrumbs": "Breadcrumbs", - "Other actions": "Other actions" + "Other actions": "Other actions", + "Only group moderators can create, edit and delete events.": "Only group moderators can create, edit and delete events.", + "+ Create a post": "+ Create a post", + "Edited {relative_time} ago": "Edited {relative_time} ago", + "Members-only post": "Members-only post", + "This post is accessible only for members. You have access to it for moderation purposes only because you are an instance moderator.": "This post is accessible only for members. You have access to it for moderation purposes only because you are an instance moderator." } diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json index 9410d7437..cc125b8f9 100644 --- a/js/src/i18n/fr_FR.json +++ b/js/src/i18n/fr_FR.json @@ -1158,5 +1158,10 @@ "View less": "Voir moins", "View more": "Voir plus", "Breadcrumbs": "Fil d'Ariane", - "Other actions": "Autres actions" + "Other actions": "Autres actions", + "Only group moderators can create, edit and delete events.": "Seule⋅s les modérateur⋅ices de groupe peuvent créer, éditer et supprimer des événements.", + "+ Create a post": "+ Créer un billet", + "Edited {relative_time} ago": "Édité il y a {relative_time}", + "Members-only post": "Billet reservé aux membres", + "This post is accessible only for members. You have access to it for moderation purposes only because you are an instance moderator.": "Ce billet est accessible uniquement aux membres. Vous y avez accès à des fins de modération car vous êtes modérateur⋅ice de l'instance." } diff --git a/js/src/mixins/group.ts b/js/src/mixins/group.ts index b287fbd84..9b320e6a6 100644 --- a/js/src/mixins/group.ts +++ b/js/src/mixins/group.ts @@ -84,6 +84,14 @@ export default class GroupMixin extends Vue { ]); } + get isCurrentActorAGroupMember(): boolean { + return this.hasCurrentActorThisRole([ + MemberRole.MODERATOR, + MemberRole.ADMINISTRATOR, + MemberRole.MEMBER, + ]); + } + hasCurrentActorThisRole(givenRole: string | string[]): boolean { const roles = Array.isArray(givenRole) ? givenRole : [givenRole]; return ( diff --git a/js/src/views/Account/children/EditIdentity.vue b/js/src/views/Account/children/EditIdentity.vue index 52cc77f5a..4d4b6bcea 100644 --- a/js/src/views/Account/children/EditIdentity.vue +++ b/js/src/views/Account/children/EditIdentity.vue @@ -218,6 +218,7 @@ import { DELETE_PERSON, FETCH_PERSON, IDENTITIES, + PERSON_FRAGMENT, UPDATE_PERSON, } from "../../../graphql/actor"; import { IPerson, Person } from "../../../types/actor"; @@ -236,6 +237,8 @@ import { IConfig } from "@/types/config.model"; import { CONFIG } from "@/graphql/config"; import { ServerParseError } from "@apollo/client/link/http"; import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; +import pick from "lodash/pick"; +import { ActorType } from "@/types/enums"; @Component({ components: { @@ -345,11 +348,14 @@ export default class EditIdentity extends mixins(identityEditionMixin) { }); if (data) { - data.identities = data.identities.filter( - (i) => i.id !== this.identity.id - ); - - store.writeQuery({ query: IDENTITIES, data }); + store.writeQuery({ + query: IDENTITIES, + data: { + identities: data.identities.filter( + (i) => i.id !== this.identity.id + ), + }, + }); } }, }); @@ -392,14 +398,16 @@ export default class EditIdentity extends mixins(identityEditionMixin) { }); if (data && updateData?.updatePerson) { - const index = data.identities.findIndex( - (i) => i.id === this.identity.id - ); - - this.$set(data.identities, index, updateData?.updatePerson); this.maybeUpdateCurrentActorCache(updateData?.updatePerson); - store.writeQuery({ query: IDENTITIES, data }); + store.writeFragment({ + fragment: PERSON_FRAGMENT, + id: `Person:${updateData?.updatePerson.id}`, + data: { + ...updateData?.updatePerson, + type: ActorType.PERSON, + }, + }); } }, }); @@ -430,9 +438,15 @@ export default class EditIdentity extends mixins(identityEditionMixin) { }); if (data && updateData?.createPerson) { - data.identities.push(updateData?.createPerson); - - store.writeQuery({ query: IDENTITIES, data }); + store.writeQuery({ + query: IDENTITIES, + data: { + identities: [ + ...data.identities, + { ...updateData?.createPerson, type: ActorType.PERSON }, + ], + }, + }); } }, }); @@ -582,7 +596,7 @@ export default class EditIdentity extends mixins(identityEditionMixin) { } } - private async buildVariables() { + private async buildVariables(): Promise> { /** * We set the avatar only if user has selected one */ @@ -594,8 +608,13 @@ export default class EditIdentity extends mixins(identityEditionMixin) { `${this.identity.preferredUsername}'s avatar` ); } - const res = { ...this.identity, ...avatarObj }; - return res; + return pick({ ...this.identity, ...avatarObj }, [ + "id", + "preferredUsername", + "name", + "summary", + "avatar", + ]); } private async redirectIfNoIdentitySelected(identityParam?: string) { diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue index 34d068248..f659406fa 100644 --- a/js/src/views/Group/Group.vue +++ b/js/src/views/Group/Group.vue @@ -404,7 +404,7 @@ params: { preferredUsername: usernameWithDomain(group) }, }" class="button is-primary" - >{{ $t("+ Post a public message") }}{{ $t("+ Create a post") }} @@ -800,31 +800,11 @@ export default class Group extends mixins(GroupMixin) { return undefined; } - get groupMemberships(): (string | undefined)[] { - return this.person?.memberships?.elements - .filter( - (membership: IMember) => - ![ - MemberRole.REJECTED, - MemberRole.NOT_APPROVED, - MemberRole.INVITED, - ].includes(membership.role) - ) - .map(({ parent: { id } }) => id); - } - @Watch("isCurrentActorAGroupMember") refetchGroupData(): void { this.$apollo.queries.group.refetch(); } - get isCurrentActorAGroupMember(): boolean { - return ( - this.groupMemberships !== undefined && - this.groupMemberships.includes(this.group.id) - ); - } - get isCurrentActorARejectedGroupMember(): boolean { return ( this.person && diff --git a/js/src/views/Posts/List.vue b/js/src/views/Posts/List.vue index 1fb176f33..85288374e 100644 --- a/js/src/views/Posts/List.vue +++ b/js/src/views/Posts/List.vue @@ -45,7 +45,7 @@ params: { preferredUsername: usernameWithDomain(group) }, }" class="button is-primary" - >{{ $t("+ Post a public message") }}{{ $t("+ Create a post") }}
diff --git a/js/src/views/Posts/Post.vue b/js/src/views/Posts/Post.vue index 221f87e15..671475fc7 100644 --- a/js/src/views/Posts/Post.vue +++ b/js/src/views/Posts/Post.vue @@ -1,5 +1,5 @@