Fix front-end stuff

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2023-03-23 20:39:39 +01:00
parent 986ae45f52
commit c4e9f88e85
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
23 changed files with 229 additions and 83 deletions

View File

@ -44,5 +44,7 @@ import GroupSection from "@/components/Group/GroupSection.vue";
const { t } = useI18n({ useScope: "global" }); const { t } = useI18n({ useScope: "global" });
defineProps<{ group: IGroup }>(); defineProps<{
group: Pick<IGroup, "preferredUsername" | "domain" | "discussions">;
}>();
</script> </script>

View File

@ -56,5 +56,7 @@ import GroupSection from "@/components/Group/GroupSection.vue";
const { t } = useI18n({ useScope: "global" }); const { t } = useI18n({ useScope: "global" });
defineProps<{ group: IGroup }>(); defineProps<{
group: Pick<IGroup, "preferredUsername" | "domain" | "resources">;
}>();
</script> </script>

View File

@ -46,7 +46,7 @@ import { useRouter } from "vue-router";
import Draggable from "zhyswan-vuedraggable"; import Draggable from "zhyswan-vuedraggable";
import { IResource } from "@/types/resource"; import { IResource } from "@/types/resource";
import RouteName from "@/router/name"; import RouteName from "@/router/name";
import { IGroup, usernameWithDomain } from "@/types/actor"; import { IMinimalActor, usernameWithDomain } from "@/types/actor";
import ResourceDropdown from "./ResourceDropdown.vue"; import ResourceDropdown from "./ResourceDropdown.vue";
import { UPDATE_RESOURCE } from "@/graphql/resources"; import { UPDATE_RESOURCE } from "@/graphql/resources";
import { inject, ref } from "vue"; import { inject, ref } from "vue";
@ -59,7 +59,7 @@ import { Snackbar } from "@/plugins/snackbar";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
resource: IResource; resource: IResource;
group: IGroup; group: IMinimalActor;
inline?: boolean; inline?: boolean;
}>(), }>(),
{ inline: false } { inline: false }

View File

@ -215,12 +215,14 @@ export function useRegistrationConfig() {
}>(REGISTRATIONS, undefined, { fetchPolicy: "cache-only" }); }>(REGISTRATIONS, undefined, { fetchPolicy: "cache-only" });
const registrationsOpen = computed( const registrationsOpen = computed(
() => result.value?.config.registrationsOpen () => result.value?.config?.registrationsOpen
); );
const registrationsAllowlist = computed( 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 { return {
registrationsOpen, registrationsOpen,
registrationsAllowlist, registrationsAllowlist,

View File

@ -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<string | undefined>,
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 };
}

View File

@ -2,7 +2,7 @@ import { PERSON_MEMBERSHIPS } from "@/graphql/actor";
import { import {
CREATE_GROUP, CREATE_GROUP,
DELETE_GROUP, DELETE_GROUP,
FETCH_GROUP, FETCH_GROUP_PUBLIC,
LEAVE_GROUP, LEAVE_GROUP,
UPDATE_GROUP, UPDATE_GROUP,
} from "@/graphql/group"; } from "@/graphql/group";
@ -50,7 +50,7 @@ export function useGroup(
discussionsLimit?: number; discussionsLimit?: number;
} }
>( >(
FETCH_GROUP, FETCH_GROUP_PUBLIC,
() => ({ () => ({
name: unref(name), name: unref(name),
...options, ...options,

View File

@ -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<string | undefined>,
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 };
}

View File

@ -18,12 +18,13 @@ export function useCurrentUserClient() {
result: currentUserResult, result: currentUserResult,
error, error,
loading, loading,
onResult,
} = useQuery<{ } = useQuery<{
currentUser: ICurrentUser; currentUser: ICurrentUser;
}>(CURRENT_USER_CLIENT); }>(CURRENT_USER_CLIENT);
const currentUser = computed(() => currentUserResult.value?.currentUser); const currentUser = computed(() => currentUserResult.value?.currentUser);
return { currentUser, error, loading }; return { currentUser, error, loading, onResult };
} }
export function useLoggedUser() { export function useLoggedUser() {

View File

@ -148,3 +148,25 @@ export const DISCUSSION_COMMENT_CHANGED = gql`
} }
${ACTOR_FRAGMENT} ${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}
`;

View File

@ -54,8 +54,8 @@ export const LIST_GROUPS = gql`
${ACTOR_FRAGMENT} ${ACTOR_FRAGMENT}
`; `;
export const GROUP_FIELDS_FRAGMENTS = gql` export const GROUP_BASIC_FIELDS_FRAGMENTS = gql`
fragment GroupFullFields on Group { fragment GroupBasicFields on Group {
...ActorFragment ...ActorFragment
suspended suspended
visibility visibility
@ -137,18 +137,23 @@ export const GROUP_FIELDS_FRAGMENTS = gql`
} }
total total
} }
discussions(page: $discussionsPage, limit: $discussionsLimit) {
total
elements {
...DiscussionBasicFields
}
}
posts(page: $postsPage, limit: $postsLimit) { posts(page: $postsPage, limit: $postsLimit) {
total total
elements { elements {
...PostBasicFields ...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) { members(page: $membersPage, limit: $membersLimit) {
elements { elements {
id id
@ -196,14 +201,13 @@ export const GROUP_FIELDS_FRAGMENTS = gql`
total total
} }
} }
${ACTOR_FRAGMENT} ${GROUP_BASIC_FIELDS_FRAGMENTS}
${ADDRESS_FRAGMENT} ${DISCUSSION_BASIC_FIELDS_FRAGMENT}
${EVENT_OPTIONS_FRAGMENT} ${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT}
${TAG_FRAGMENT}
`; `;
export const FETCH_GROUP = gql` export const FETCH_GROUP_PUBLIC = gql`
query FetchGroup( query FetchGroupPublic(
$name: String! $name: String!
$afterDateTime: DateTime $afterDateTime: DateTime
$beforeDateTime: DateTime $beforeDateTime: DateTime
@ -211,19 +215,12 @@ export const FETCH_GROUP = gql`
$organisedEventsLimit: Int $organisedEventsLimit: Int
$postsPage: Int $postsPage: Int
$postsLimit: Int $postsLimit: Int
$membersPage: Int
$membersLimit: Int
$discussionsPage: Int
$discussionsLimit: Int
) { ) {
group(preferredUsername: $name) { group(preferredUsername: $name) {
...GroupFullFields ...GroupBasicFields
} }
} }
${GROUP_FIELDS_FRAGMENTS} ${GROUP_BASIC_FIELDS_FRAGMENTS}
${DISCUSSION_BASIC_FIELDS_FRAGMENT}
${POST_BASIC_FIELDS}
${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT}
`; `;
export const GET_GROUP = gql` export const GET_GROUP = gql`

View File

@ -161,3 +161,34 @@ export const PREVIEW_RESOURCE_LINK = gql`
} }
${RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT} ${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}
`;

View File

@ -44,7 +44,7 @@ export const userRoutes: RouteRecordRaw[] = [
}, },
}, },
{ {
path: "/resend-instructions", path: "/resend-instructions/:email?",
name: UserRouteName.RESEND_CONFIRMATION, name: UserRouteName.RESEND_CONFIRMATION,
component: (): Promise<any> => component: (): Promise<any> =>
import("@/views/User/ResendConfirmation.vue"), 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, name: UserRouteName.SEND_PASSWORD_RESET,
component: (): Promise<any> => import("@/views/User/SendPasswordReset.vue"), component: (): Promise<any> => import("@/views/User/SendPasswordReset.vue"),
props: true, props: true,

View File

@ -15,6 +15,8 @@ export interface IActor {
type: ActorType; type: ActorType;
} }
export type IMinimalActor = Pick<IActor, "preferredUsername" | "domain">;
export class Actor implements IActor { export class Actor implements IActor {
id?: string; id?: string;
@ -57,7 +59,7 @@ export class Actor implements IActor {
} }
export function usernameWithDomain( export function usernameWithDomain(
actor: IActor | undefined, actor: IMinimalActor | undefined,
force = false force = false
): string { ): string {
if (!actor) return ""; if (!actor) return "";

View File

@ -77,10 +77,9 @@ import { displayName, usernameWithDomain } from "@/types/actor";
import DiscussionListItem from "@/components/Discussion/DiscussionListItem.vue"; import DiscussionListItem from "@/components/Discussion/DiscussionListItem.vue";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import { MemberRole } from "@/types/enums"; import { MemberRole } from "@/types/enums";
import { useGroupDiscussionsList } from "@/composition/apollo/discussions";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import EmptyContent from "@/components/Utils/EmptyContent.vue"; import EmptyContent from "@/components/Utils/EmptyContent.vue";
import { useGroup } from "@/composition/apollo/group";
import { usePersonStatusGroup } from "@/composition/apollo/actor"; import { usePersonStatusGroup } from "@/composition/apollo/actor";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRouteQuery, integerTransformer } from "vue-use-route-query"; import { useRouteQuery, integerTransformer } from "vue-use-route-query";
@ -92,10 +91,13 @@ const DISCUSSIONS_PER_PAGE = 10;
const props = defineProps<{ preferredUsername: string }>(); const props = defineProps<{ preferredUsername: string }>();
const { group, loading: groupLoading } = useGroup(props.preferredUsername, { const { group, loading: groupLoading } = useGroupDiscussionsList(
props.preferredUsername,
{
discussionsPage: page.value, discussionsPage: page.value,
discussionsLimit: DISCUSSIONS_PER_PAGE, discussionsLimit: DISCUSSIONS_PER_PAGE,
}); }
);
const { person, loading: personLoading } = usePersonStatusGroup( const { person, loading: personLoading } = usePersonStatusGroup(
props.preferredUsername props.preferredUsername
@ -109,7 +111,7 @@ useHead({
const groupMemberships = computed((): (string | undefined)[] => { const groupMemberships = computed((): (string | undefined)[] => {
if (!person.value || !person.value.id) return []; if (!person.value || !person.value.id) return [];
return person.value.memberships.elements return (person.value.memberships?.elements ?? [])
.filter( .filter(
(membership: IMember) => (membership: IMember) =>
![ ![

View File

@ -649,7 +649,7 @@ const FullAddressAutoComplete = defineAsyncComponent(
// }, // },
// }, // },
// group: { // group: {
// query: FETCH_GROUP, // query: FETCH_GROUP_PUBLIC,
// fetchPolicy: "cache-and-network", // fetchPolicy: "cache-and-network",
// variables() { // variables() {
// return { // return {

View File

@ -73,9 +73,9 @@
t( t(
"{count} members", "{count} members",
{ {
count: group.members.total, count: group.members?.total,
}, },
group.members.total group.members?.total
) )
}} }}
<router-link <router-link
@ -388,9 +388,9 @@
<!-- Private things --> <!-- Private things -->
<div class="flex-1 m-0 flex flex-col flex-wrap gap-2"> <div class="flex-1 m-0 flex flex-col flex-wrap gap-2">
<!-- Group discussions --> <!-- Group discussions -->
<Discussions :group="group" class="flex-1" /> <Discussions :group="discussionGroup ?? group" class="flex-1" />
<!-- Resources --> <!-- Resources -->
<Resources :group="group" class="flex-1" /> <Resources :group="resourcesGroup ?? group" class="flex-1" />
</div> </div>
<!-- Public things --> <!-- Public things -->
<div class="flex-1 m-0 flex flex-col flex-wrap gap-2"> <div class="flex-1 m-0 flex flex-col flex-wrap gap-2">
@ -452,9 +452,9 @@
t( t(
"{count} members", "{count} members",
{ {
count: group.members.total, count: group.members?.total,
}, },
group.members.total group.members?.total
) )
}} }}
</event-metadata-block> </event-metadata-block>
@ -671,6 +671,7 @@ import { useAnonymousReportsConfig } from "../../composition/apollo/config";
import { computed, defineAsyncComponent, inject, ref, watch } from "vue"; import { computed, defineAsyncComponent, inject, ref, watch } from "vue";
import { useCurrentActorClient } from "@/composition/apollo/actor"; import { useCurrentActorClient } from "@/composition/apollo/actor";
import { useGroup, useLeaveGroup } from "@/composition/apollo/group"; import { useGroup, useLeaveGroup } from "@/composition/apollo/group";
import { useGroupDiscussionsList } from "@/composition/apollo/discussions";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useMutation, useQuery } from "@vue/apollo-composable"; import { useMutation, useQuery } from "@vue/apollo-composable";
import AccountGroup from "vue-material-design-icons/AccountGroup.vue"; 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 Events from "@/components/Group/Sections/EventsSection.vue";
import { Dialog } from "@/plugins/dialog"; import { Dialog } from "@/plugins/dialog";
import { Notifier } from "@/plugins/notifier"; import { Notifier } from "@/plugins/notifier";
import { useGroupResourcesList } from "@/composition/apollo/resources";
const props = defineProps<{ const props = defineProps<{
preferredUsername: string; preferredUsername: string;
@ -705,6 +707,14 @@ const {
} = useGroup(props.preferredUsername, { afterDateTime: new Date() }); } = useGroup(props.preferredUsername, { afterDateTime: new Date() });
const router = useRouter(); 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 { t } = useI18n({ useScope: "global" });
// const { person } = usePersonStatusGroup(group); // const { person } = usePersonStatusGroup(group);
@ -1037,7 +1047,7 @@ const isCurrentActorOnADifferentDomainThanGroup = computed((): boolean => {
const members = computed((): IMember[] => { const members = computed((): IMember[] => {
return ( return (
group.value?.members.elements.filter( (group.value?.members?.elements ?? []).filter(
(member: IMember) => (member: IMember) =>
![ ![
MemberRole.INVITED, MemberRole.INVITED,

View File

@ -290,7 +290,10 @@ const { result: membershipsResult, loading: membershipsLoading } = useQuery<{
}>( }>(
PERSON_MEMBERSHIPS, PERSON_MEMBERSHIPS,
() => ({ id: currentActor.value?.id }), () => ({ 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); const memberships = computed(() => membershipsResult.value?.person.memberships);

View File

@ -106,7 +106,7 @@
variant="text" variant="text"
:to="{ :to="{
name: RouteName.REGISTER, name: RouteName.REGISTER,
params: { query: {
default_email: credentials.email, default_email: credentials.email,
default_password: credentials.password, default_password: credentials.password,
}, },
@ -143,14 +143,6 @@ import { LoginError, LoginErrorCode } from "@/types/enums";
import { useCurrentUserClient } from "@/composition/apollo/user"; import { useCurrentUserClient } from "@/composition/apollo/user";
import { useHead } from "@vueuse/head"; import { useHead } from "@vueuse/head";
const props = withDefaults(
defineProps<{
email?: string;
password?: string;
}>(),
{ email: "", password: "" }
);
const { t } = useI18n({ useScope: "global" }); const { t } = useI18n({ useScope: "global" });
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
@ -177,8 +169,9 @@ const errors = ref<string[]>([]);
const submitted = ref(false); const submitted = ref(false);
const credentials = reactive({ const credentials = reactive({
email: "", email: typeof route.query.email === "string" ? route.query.email : "",
password: "", password:
typeof route.query.password === "string" ? route.query.password : "",
}); });
const redirect = ref<string | undefined>(""); const redirect = ref<string | undefined>("");
@ -298,9 +291,6 @@ const currentProvider = computed(() => {
}); });
onMounted(() => { onMounted(() => {
credentials.email = props.email;
credentials.password = props.password;
const query = route?.query; const query = route?.query;
errorCode.value = query?.code as LoginErrorCode; errorCode.value = query?.code as LoginErrorCode;
redirect.value = query?.redirect as string | undefined; redirect.value = query?.redirect as string | undefined;

View File

@ -181,7 +181,7 @@
variant="text" variant="text"
:to="{ :to="{
name: RouteName.LOGIN, name: RouteName.LOGIN,
params: { query: {
email: credentials.email, email: credentials.email,
password: credentials.password, password: credentials.password,
}, },
@ -212,7 +212,7 @@ import AuthProviders from "../../components/User/AuthProviders.vue";
import { computed, reactive, ref, watch } from "vue"; import { computed, reactive, ref, watch } from "vue";
import { useMutation, useQuery } from "@vue/apollo-composable"; import { useMutation, useQuery } from "@vue/apollo-composable";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { useHead } from "@vueuse/head"; import { useHead } from "@vueuse/head";
import { AbsintheGraphQLErrors } from "@/types/errors.model"; import { AbsintheGraphQLErrors } from "@/types/errors.model";
@ -221,6 +221,7 @@ type errorMessage = { type: errorType; message: string };
type credentialsType = { email: string; password: string; locale: string }; type credentialsType = { email: string; password: string; locale: string };
const { t, locale } = useI18n({ useScope: "global" }); const { t, locale } = useI18n({ useScope: "global" });
const route = useRoute();
const router = useRouter(); const router = useRouter();
const { result: configResult } = useQuery<{ config: IConfig }>(CONFIG); const { result: configResult } = useQuery<{ config: IConfig }>(CONFIG);
@ -229,17 +230,10 @@ const config = computed(() => configResult.value?.config);
const showGravatar = ref(false); const showGravatar = ref(false);
const props = withDefaults(
defineProps<{
email?: string;
password?: string;
}>(),
{ email: "", password: "" }
);
const credentials = reactive<credentialsType>({ const credentials = reactive<credentialsType>({
email: props.email, email: typeof route.query.email === "string" ? route.query.email : "",
password: props.password, password:
typeof route.query.password === "string" ? route.query.password : "",
locale: "en", locale: "en",
}); });

View File

@ -36,7 +36,7 @@ test("Login has everything we need", async ({ page }) => {
await page.goBack(); await page.goBack();
await registerLink.click(); await registerLink.click();
await page.waitForURL("/register/user"); await page.waitForURL("/register/user?default_email=&default_password=");
expect(page.url()).toContain("/register/user"); expect(page.url()).toContain("/register/user");
await page.goBack(); await page.goBack();
}); });

View File

@ -80,8 +80,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
) )
# This one should have a privacy setting # This one should have a privacy setting
field :organized_events, :paginated_event_list, field :organized_events, :paginated_event_list do
meta: [private: true, rule: :"read:group:events"] do
arg(:after_datetime, :datetime, arg(:after_datetime, :datetime,
default_value: nil, default_value: nil,
description: "Filter events that begin after this datetime" description: "Filter events that begin after this datetime"

View File

@ -85,7 +85,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
Language information Language information
""" """
object :language do object :language do
meta(:authorize, :administrator) meta(:authorize, :all)
field(:code, :string, description: "The iso-639-3 language code") field(:code, :string, description: "The iso-639-3 language code")
field(:name, :string, description: "The language name") field(:name, :string, description: "The language name")
end end

View File

@ -51,7 +51,8 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
middleware(Rajska.QueryAuthorization, middleware(Rajska.QueryAuthorization,
permit: :user, permit: :user,
scope: Mobilizon.Discussions.Discussion, scope: Mobilizon.Discussions.Discussion,
rule: :"read:group:discussions" rule: :"read:group:discussions",
args: %{slug: :slug}
) )
resolve(&Discussion.get_discussion/3) resolve(&Discussion.get_discussion/3)