From c4e9f88e8540d237161c818b7635403b3b4b6ce9 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Thu, 23 Mar 2023 20:39:39 +0100 Subject: [PATCH] Fix front-end stuff Signed-off-by: Thomas Citharel --- .../Group/Sections/DiscussionsSection.vue | 4 +- .../Group/Sections/ResourcesSection.vue | 4 +- js/src/components/Resource/FolderItem.vue | 4 +- js/src/composition/apollo/config.ts | 8 ++-- js/src/composition/apollo/discussions.ts | 44 +++++++++++++++++++ js/src/composition/apollo/group.ts | 4 +- js/src/composition/apollo/resources.ts | 44 +++++++++++++++++++ js/src/composition/apollo/user.ts | 3 +- js/src/graphql/discussion.ts | 22 ++++++++++ js/src/graphql/group.ts | 43 +++++++++--------- js/src/graphql/resources.ts | 31 +++++++++++++ js/src/router/user.ts | 4 +- js/src/types/actor/actor.model.ts | 4 +- .../views/Discussions/DiscussionsListView.vue | 16 ++++--- js/src/views/Event/EditView.vue | 2 +- js/src/views/Group/GroupView.vue | 24 +++++++--- js/src/views/Posts/PostView.vue | 5 ++- js/src/views/User/LoginView.vue | 18 ++------ js/src/views/User/RegisterView.vue | 18 +++----- js/tests/e2e/login.spec.ts | 2 +- lib/graphql/schema/actors/group.ex | 3 +- lib/graphql/schema/admin.ex | 2 +- lib/graphql/schema/discussions/discussion.ex | 3 +- 23 files changed, 229 insertions(+), 83 deletions(-) create mode 100644 js/src/composition/apollo/discussions.ts create mode 100644 js/src/composition/apollo/resources.ts diff --git a/js/src/components/Group/Sections/DiscussionsSection.vue b/js/src/components/Group/Sections/DiscussionsSection.vue index e8e59867..022ef7b4 100644 --- a/js/src/components/Group/Sections/DiscussionsSection.vue +++ b/js/src/components/Group/Sections/DiscussionsSection.vue @@ -44,5 +44,7 @@ import GroupSection from "@/components/Group/GroupSection.vue"; const { t } = useI18n({ useScope: "global" }); -defineProps<{ group: IGroup }>(); +defineProps<{ + group: Pick; +}>(); diff --git a/js/src/components/Group/Sections/ResourcesSection.vue b/js/src/components/Group/Sections/ResourcesSection.vue index 938b4f51..ff07f5a6 100644 --- a/js/src/components/Group/Sections/ResourcesSection.vue +++ b/js/src/components/Group/Sections/ResourcesSection.vue @@ -56,5 +56,7 @@ import GroupSection from "@/components/Group/GroupSection.vue"; const { t } = useI18n({ useScope: "global" }); -defineProps<{ group: IGroup }>(); +defineProps<{ + group: Pick; +}>(); diff --git a/js/src/components/Resource/FolderItem.vue b/js/src/components/Resource/FolderItem.vue index af0129b8..003628e6 100644 --- a/js/src/components/Resource/FolderItem.vue +++ b/js/src/components/Resource/FolderItem.vue @@ -46,7 +46,7 @@ import { useRouter } from "vue-router"; import Draggable from "zhyswan-vuedraggable"; import { IResource } from "@/types/resource"; import RouteName from "@/router/name"; -import { IGroup, usernameWithDomain } from "@/types/actor"; +import { IMinimalActor, usernameWithDomain } from "@/types/actor"; import ResourceDropdown from "./ResourceDropdown.vue"; import { UPDATE_RESOURCE } from "@/graphql/resources"; import { inject, ref } from "vue"; @@ -59,7 +59,7 @@ import { Snackbar } from "@/plugins/snackbar"; const props = withDefaults( defineProps<{ resource: IResource; - group: IGroup; + group: IMinimalActor; inline?: boolean; }>(), { inline: false } diff --git a/js/src/composition/apollo/config.ts b/js/src/composition/apollo/config.ts index 06c28a29..ce38d596 100644 --- a/js/src/composition/apollo/config.ts +++ b/js/src/composition/apollo/config.ts @@ -215,12 +215,14 @@ export function useRegistrationConfig() { }>(REGISTRATIONS, undefined, { fetchPolicy: "cache-only" }); const registrationsOpen = computed( - () => result.value?.config.registrationsOpen + () => result.value?.config?.registrationsOpen ); const registrationsAllowlist = computed( - () => result.value?.config.registrationsAllowlist + () => result.value?.config?.registrationsAllowlist + ); + const databaseLogin = computed( + () => result.value?.config?.auth?.databaseLogin ); - const databaseLogin = computed(() => result.value?.config.auth.databaseLogin); return { registrationsOpen, registrationsAllowlist, diff --git a/js/src/composition/apollo/discussions.ts b/js/src/composition/apollo/discussions.ts new file mode 100644 index 00000000..c98a3597 --- /dev/null +++ b/js/src/composition/apollo/discussions.ts @@ -0,0 +1,44 @@ +import { useQuery } from "@vue/apollo-composable"; +import { computed, unref } from "vue"; +import { useCurrentUserClient } from "./user"; +import type { Ref } from "vue"; +import { IGroup } from "@/types/actor"; +import { GROUP_DISCUSSIONS_LIST } from "@/graphql/discussion"; + +export function useGroupDiscussionsList( + name: string | undefined | Ref, + options?: { + discussionsPage?: number; + discussionsLimit?: number; + } +) { + const { currentUser } = useCurrentUserClient(); + const { result, error, loading, onResult, onError, refetch } = useQuery< + { + group: Pick< + IGroup, + "id" | "preferredUsername" | "name" | "domain" | "discussions" + >; + }, + { + name: string; + discussionsPage?: number; + discussionsLimit?: number; + } + >( + GROUP_DISCUSSIONS_LIST, + () => ({ + name: unref(name), + ...options, + }), + () => ({ + enabled: + unref(name) !== undefined && + unref(name) !== "" && + currentUser.value?.isLoggedIn, + fetchPolicy: "cache-and-network", + }) + ); + const group = computed(() => result.value?.group); + return { group, error, loading, onResult, onError, refetch }; +} diff --git a/js/src/composition/apollo/group.ts b/js/src/composition/apollo/group.ts index 0483d587..a59cd7eb 100644 --- a/js/src/composition/apollo/group.ts +++ b/js/src/composition/apollo/group.ts @@ -2,7 +2,7 @@ import { PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { CREATE_GROUP, DELETE_GROUP, - FETCH_GROUP, + FETCH_GROUP_PUBLIC, LEAVE_GROUP, UPDATE_GROUP, } from "@/graphql/group"; @@ -50,7 +50,7 @@ export function useGroup( discussionsLimit?: number; } >( - FETCH_GROUP, + FETCH_GROUP_PUBLIC, () => ({ name: unref(name), ...options, diff --git a/js/src/composition/apollo/resources.ts b/js/src/composition/apollo/resources.ts new file mode 100644 index 00000000..1f60281a --- /dev/null +++ b/js/src/composition/apollo/resources.ts @@ -0,0 +1,44 @@ +import { useQuery } from "@vue/apollo-composable"; +import { computed, unref } from "vue"; +import { useCurrentUserClient } from "./user"; +import type { Ref } from "vue"; +import { IGroup } from "@/types/actor"; +import { GROUP_RESOURCES_LIST } from "@/graphql/resources"; + +export function useGroupResourcesList( + name: string | undefined | Ref, + options?: { + resourcesPage?: number; + resourcesLimit?: number; + } +) { + const { currentUser } = useCurrentUserClient(); + const { result, error, loading, onResult, onError, refetch } = useQuery< + { + group: Pick< + IGroup, + "id" | "preferredUsername" | "name" | "domain" | "resources" + >; + }, + { + name: string; + resourcesPage?: number; + resourcesLimit?: number; + } + >( + GROUP_RESOURCES_LIST, + () => ({ + name: unref(name), + ...options, + }), + () => ({ + enabled: + unref(name) !== undefined && + unref(name) !== "" && + currentUser.value?.isLoggedIn, + fetchPolicy: "cache-and-network", + }) + ); + const group = computed(() => result.value?.group); + return { group, error, loading, onResult, onError, refetch }; +} diff --git a/js/src/composition/apollo/user.ts b/js/src/composition/apollo/user.ts index 0492e9c4..4e8128eb 100644 --- a/js/src/composition/apollo/user.ts +++ b/js/src/composition/apollo/user.ts @@ -18,12 +18,13 @@ export function useCurrentUserClient() { result: currentUserResult, error, loading, + onResult, } = useQuery<{ currentUser: ICurrentUser; }>(CURRENT_USER_CLIENT); const currentUser = computed(() => currentUserResult.value?.currentUser); - return { currentUser, error, loading }; + return { currentUser, error, loading, onResult }; } export function useLoggedUser() { diff --git a/js/src/graphql/discussion.ts b/js/src/graphql/discussion.ts index 1d14933b..ce886b1d 100644 --- a/js/src/graphql/discussion.ts +++ b/js/src/graphql/discussion.ts @@ -148,3 +148,25 @@ export const DISCUSSION_COMMENT_CHANGED = gql` } ${ACTOR_FRAGMENT} `; + +export const GROUP_DISCUSSIONS_LIST = gql` + query GroupDiscussionsList( + $name: String! + $discussionsPage: Int + $discussionsLimit: Int + ) { + group(preferredUsername: $name) { + id + preferredUsername + name + domain + discussions(page: $discussionsPage, limit: $discussionsLimit) { + total + elements { + ...DiscussionBasicFields + } + } + } + } + ${DISCUSSION_BASIC_FIELDS_FRAGMENT} +`; diff --git a/js/src/graphql/group.ts b/js/src/graphql/group.ts index ae45ef5a..ea188955 100644 --- a/js/src/graphql/group.ts +++ b/js/src/graphql/group.ts @@ -54,8 +54,8 @@ export const LIST_GROUPS = gql` ${ACTOR_FRAGMENT} `; -export const GROUP_FIELDS_FRAGMENTS = gql` - fragment GroupFullFields on Group { +export const GROUP_BASIC_FIELDS_FRAGMENTS = gql` + fragment GroupBasicFields on Group { ...ActorFragment suspended visibility @@ -137,18 +137,23 @@ export const GROUP_FIELDS_FRAGMENTS = gql` } total } - discussions(page: $discussionsPage, limit: $discussionsLimit) { - total - elements { - ...DiscussionBasicFields - } - } posts(page: $postsPage, limit: $postsLimit) { total elements { ...PostBasicFields } } + } + ${ACTOR_FRAGMENT} + ${ADDRESS_FRAGMENT} + ${EVENT_OPTIONS_FRAGMENT} + ${TAG_FRAGMENT} + ${POST_BASIC_FIELDS} +`; + +export const GROUP_FIELDS_FRAGMENTS = gql` + fragment GroupFullFields on Group { + ...GroupBasicFields members(page: $membersPage, limit: $membersLimit) { elements { id @@ -196,14 +201,13 @@ export const GROUP_FIELDS_FRAGMENTS = gql` total } } - ${ACTOR_FRAGMENT} - ${ADDRESS_FRAGMENT} - ${EVENT_OPTIONS_FRAGMENT} - ${TAG_FRAGMENT} + ${GROUP_BASIC_FIELDS_FRAGMENTS} + ${DISCUSSION_BASIC_FIELDS_FRAGMENT} + ${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT} `; -export const FETCH_GROUP = gql` - query FetchGroup( +export const FETCH_GROUP_PUBLIC = gql` + query FetchGroupPublic( $name: String! $afterDateTime: DateTime $beforeDateTime: DateTime @@ -211,19 +215,12 @@ export const FETCH_GROUP = gql` $organisedEventsLimit: Int $postsPage: Int $postsLimit: Int - $membersPage: Int - $membersLimit: Int - $discussionsPage: Int - $discussionsLimit: Int ) { group(preferredUsername: $name) { - ...GroupFullFields + ...GroupBasicFields } } - ${GROUP_FIELDS_FRAGMENTS} - ${DISCUSSION_BASIC_FIELDS_FRAGMENT} - ${POST_BASIC_FIELDS} - ${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT} + ${GROUP_BASIC_FIELDS_FRAGMENTS} `; export const GET_GROUP = gql` diff --git a/js/src/graphql/resources.ts b/js/src/graphql/resources.ts index ecc5523e..0a90bb6e 100644 --- a/js/src/graphql/resources.ts +++ b/js/src/graphql/resources.ts @@ -161,3 +161,34 @@ export const PREVIEW_RESOURCE_LINK = gql` } ${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT} `; + +export const GROUP_RESOURCES_LIST = gql` + query GroupResourcesList( + $name: String! + $resourcesPage: Int + $resourcesLimit: Int + ) { + group(preferredUsername: $name) { + id + preferredUsername + name + domain + resources(page: $resourcesPage, limit: $resourcesLimit) { + elements { + id + title + resourceUrl + summary + updatedAt + type + path + metadata { + ...ResourceMetadataBasicFields + } + } + total + } + } + } + ${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT} +`; diff --git a/js/src/router/user.ts b/js/src/router/user.ts index cd80c297..e65590c6 100644 --- a/js/src/router/user.ts +++ b/js/src/router/user.ts @@ -44,7 +44,7 @@ export const userRoutes: RouteRecordRaw[] = [ }, }, { - path: "/resend-instructions", + path: "/resend-instructions/:email?", name: UserRouteName.RESEND_CONFIRMATION, component: (): Promise => import("@/views/User/ResendConfirmation.vue"), @@ -57,7 +57,7 @@ export const userRoutes: RouteRecordRaw[] = [ }, }, { - path: "/password-reset/send", + path: "/password-reset/send/:email?", name: UserRouteName.SEND_PASSWORD_RESET, component: (): Promise => import("@/views/User/SendPasswordReset.vue"), props: true, diff --git a/js/src/types/actor/actor.model.ts b/js/src/types/actor/actor.model.ts index 088fd0da..2eab8c58 100644 --- a/js/src/types/actor/actor.model.ts +++ b/js/src/types/actor/actor.model.ts @@ -15,6 +15,8 @@ export interface IActor { type: ActorType; } +export type IMinimalActor = Pick; + export class Actor implements IActor { id?: string; @@ -57,7 +59,7 @@ export class Actor implements IActor { } export function usernameWithDomain( - actor: IActor | undefined, + actor: IMinimalActor | undefined, force = false ): string { if (!actor) return ""; diff --git a/js/src/views/Discussions/DiscussionsListView.vue b/js/src/views/Discussions/DiscussionsListView.vue index 60c718ea..607efa37 100644 --- a/js/src/views/Discussions/DiscussionsListView.vue +++ b/js/src/views/Discussions/DiscussionsListView.vue @@ -77,10 +77,9 @@ import { displayName, usernameWithDomain } from "@/types/actor"; import DiscussionListItem from "@/components/Discussion/DiscussionListItem.vue"; import RouteName from "../../router/name"; import { MemberRole } from "@/types/enums"; - +import { useGroupDiscussionsList } from "@/composition/apollo/discussions"; import { IMember } from "@/types/actor/member.model"; import EmptyContent from "@/components/Utils/EmptyContent.vue"; -import { useGroup } from "@/composition/apollo/group"; import { usePersonStatusGroup } from "@/composition/apollo/actor"; import { useI18n } from "vue-i18n"; import { useRouteQuery, integerTransformer } from "vue-use-route-query"; @@ -92,10 +91,13 @@ const DISCUSSIONS_PER_PAGE = 10; const props = defineProps<{ preferredUsername: string }>(); -const { group, loading: groupLoading } = useGroup(props.preferredUsername, { - discussionsPage: page.value, - discussionsLimit: DISCUSSIONS_PER_PAGE, -}); +const { group, loading: groupLoading } = useGroupDiscussionsList( + props.preferredUsername, + { + discussionsPage: page.value, + discussionsLimit: DISCUSSIONS_PER_PAGE, + } +); const { person, loading: personLoading } = usePersonStatusGroup( props.preferredUsername @@ -109,7 +111,7 @@ useHead({ const groupMemberships = computed((): (string | undefined)[] => { if (!person.value || !person.value.id) return []; - return person.value.memberships.elements + return (person.value.memberships?.elements ?? []) .filter( (membership: IMember) => ![ diff --git a/js/src/views/Event/EditView.vue b/js/src/views/Event/EditView.vue index d917583f..cbe8791e 100644 --- a/js/src/views/Event/EditView.vue +++ b/js/src/views/Event/EditView.vue @@ -649,7 +649,7 @@ const FullAddressAutoComplete = defineAsyncComponent( // }, // }, // group: { -// query: FETCH_GROUP, +// query: FETCH_GROUP_PUBLIC, // fetchPolicy: "cache-and-network", // variables() { // return { diff --git a/js/src/views/Group/GroupView.vue b/js/src/views/Group/GroupView.vue index 4b2b06d2..77582062 100644 --- a/js/src/views/Group/GroupView.vue +++ b/js/src/views/Group/GroupView.vue @@ -73,9 +73,9 @@ t( "{count} members", { - count: group.members.total, + count: group.members?.total, }, - group.members.total + group.members?.total ) }}
- + - +
@@ -452,9 +452,9 @@ t( "{count} members", { - count: group.members.total, + count: group.members?.total, }, - group.members.total + group.members?.total ) }} @@ -671,6 +671,7 @@ import { useAnonymousReportsConfig } from "../../composition/apollo/config"; import { computed, defineAsyncComponent, inject, ref, watch } from "vue"; import { useCurrentActorClient } from "@/composition/apollo/actor"; import { useGroup, useLeaveGroup } from "@/composition/apollo/group"; +import { useGroupDiscussionsList } from "@/composition/apollo/discussions"; import { useRouter } from "vue-router"; import { useMutation, useQuery } from "@vue/apollo-composable"; import AccountGroup from "vue-material-design-icons/AccountGroup.vue"; @@ -691,6 +692,7 @@ import Posts from "@/components/Group/Sections/PostsSection.vue"; import Events from "@/components/Group/Sections/EventsSection.vue"; import { Dialog } from "@/plugins/dialog"; import { Notifier } from "@/plugins/notifier"; +import { useGroupResourcesList } from "@/composition/apollo/resources"; const props = defineProps<{ preferredUsername: string; @@ -705,6 +707,14 @@ const { } = useGroup(props.preferredUsername, { afterDateTime: new Date() }); const router = useRouter(); +const { group: discussionGroup } = useGroupDiscussionsList( + props.preferredUsername +); +const { group: resourcesGroup } = useGroupResourcesList( + props.preferredUsername, + { resourcesPage: 1, resourcesLimit: 3 } +); + const { t } = useI18n({ useScope: "global" }); // const { person } = usePersonStatusGroup(group); @@ -1037,7 +1047,7 @@ const isCurrentActorOnADifferentDomainThanGroup = computed((): boolean => { const members = computed((): IMember[] => { return ( - group.value?.members.elements.filter( + (group.value?.members?.elements ?? []).filter( (member: IMember) => ![ MemberRole.INVITED, diff --git a/js/src/views/Posts/PostView.vue b/js/src/views/Posts/PostView.vue index bcb2332e..8aacfecb 100644 --- a/js/src/views/Posts/PostView.vue +++ b/js/src/views/Posts/PostView.vue @@ -290,7 +290,10 @@ const { result: membershipsResult, loading: membershipsLoading } = useQuery<{ }>( PERSON_MEMBERSHIPS, () => ({ id: currentActor.value?.id }), - () => ({ enabled: currentActor.value?.id !== undefined }) + () => ({ + enabled: + currentActor.value?.id !== undefined && currentActor.value?.id !== null, + }) ); const memberships = computed(() => membershipsResult.value?.person.memberships); diff --git a/js/src/views/User/LoginView.vue b/js/src/views/User/LoginView.vue index 115c7355..c5645cc5 100644 --- a/js/src/views/User/LoginView.vue +++ b/js/src/views/User/LoginView.vue @@ -106,7 +106,7 @@ variant="text" :to="{ name: RouteName.REGISTER, - params: { + query: { default_email: credentials.email, default_password: credentials.password, }, @@ -143,14 +143,6 @@ import { LoginError, LoginErrorCode } from "@/types/enums"; import { useCurrentUserClient } from "@/composition/apollo/user"; import { useHead } from "@vueuse/head"; -const props = withDefaults( - defineProps<{ - email?: string; - password?: string; - }>(), - { email: "", password: "" } -); - const { t } = useI18n({ useScope: "global" }); const router = useRouter(); const route = useRoute(); @@ -177,8 +169,9 @@ const errors = ref([]); const submitted = ref(false); const credentials = reactive({ - email: "", - password: "", + email: typeof route.query.email === "string" ? route.query.email : "", + password: + typeof route.query.password === "string" ? route.query.password : "", }); const redirect = ref(""); @@ -298,9 +291,6 @@ const currentProvider = computed(() => { }); onMounted(() => { - credentials.email = props.email; - credentials.password = props.password; - const query = route?.query; errorCode.value = query?.code as LoginErrorCode; redirect.value = query?.redirect as string | undefined; diff --git a/js/src/views/User/RegisterView.vue b/js/src/views/User/RegisterView.vue index 1f138cda..2a7857b9 100644 --- a/js/src/views/User/RegisterView.vue +++ b/js/src/views/User/RegisterView.vue @@ -181,7 +181,7 @@ variant="text" :to="{ name: RouteName.LOGIN, - params: { + query: { email: credentials.email, password: credentials.password, }, @@ -212,7 +212,7 @@ import AuthProviders from "../../components/User/AuthProviders.vue"; import { computed, reactive, ref, watch } from "vue"; import { useMutation, useQuery } from "@vue/apollo-composable"; import { useI18n } from "vue-i18n"; -import { useRouter } from "vue-router"; +import { useRoute, useRouter } from "vue-router"; import { useHead } from "@vueuse/head"; import { AbsintheGraphQLErrors } from "@/types/errors.model"; @@ -221,6 +221,7 @@ type errorMessage = { type: errorType; message: string }; type credentialsType = { email: string; password: string; locale: string }; const { t, locale } = useI18n({ useScope: "global" }); +const route = useRoute(); const router = useRouter(); const { result: configResult } = useQuery<{ config: IConfig }>(CONFIG); @@ -229,17 +230,10 @@ const config = computed(() => configResult.value?.config); const showGravatar = ref(false); -const props = withDefaults( - defineProps<{ - email?: string; - password?: string; - }>(), - { email: "", password: "" } -); - const credentials = reactive({ - email: props.email, - password: props.password, + email: typeof route.query.email === "string" ? route.query.email : "", + password: + typeof route.query.password === "string" ? route.query.password : "", locale: "en", }); diff --git a/js/tests/e2e/login.spec.ts b/js/tests/e2e/login.spec.ts index 85ecc31e..8e74aa32 100644 --- a/js/tests/e2e/login.spec.ts +++ b/js/tests/e2e/login.spec.ts @@ -36,7 +36,7 @@ test("Login has everything we need", async ({ page }) => { await page.goBack(); await registerLink.click(); - await page.waitForURL("/register/user"); + await page.waitForURL("/register/user?default_email=&default_password="); expect(page.url()).toContain("/register/user"); await page.goBack(); }); diff --git a/lib/graphql/schema/actors/group.ex b/lib/graphql/schema/actors/group.ex index 804c3fda..adfe41af 100644 --- a/lib/graphql/schema/actors/group.ex +++ b/lib/graphql/schema/actors/group.ex @@ -80,8 +80,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do ) # This one should have a privacy setting - field :organized_events, :paginated_event_list, - meta: [private: true, rule: :"read:group:events"] do + field :organized_events, :paginated_event_list do arg(:after_datetime, :datetime, default_value: nil, description: "Filter events that begin after this datetime" diff --git a/lib/graphql/schema/admin.ex b/lib/graphql/schema/admin.ex index ec432a08..97e428ff 100644 --- a/lib/graphql/schema/admin.ex +++ b/lib/graphql/schema/admin.ex @@ -85,7 +85,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do Language information """ object :language do - meta(:authorize, :administrator) + meta(:authorize, :all) field(:code, :string, description: "The iso-639-3 language code") field(:name, :string, description: "The language name") end diff --git a/lib/graphql/schema/discussions/discussion.ex b/lib/graphql/schema/discussions/discussion.ex index b13ae6a9..bed070a9 100644 --- a/lib/graphql/schema/discussions/discussion.ex +++ b/lib/graphql/schema/discussions/discussion.ex @@ -51,7 +51,8 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do middleware(Rajska.QueryAuthorization, permit: :user, scope: Mobilizon.Discussions.Discussion, - rule: :"read:group:discussions" + rule: :"read:group:discussions", + args: %{slug: :slug} ) resolve(&Discussion.get_discussion/3)