all repos — caroster @ 339cbcd2ddf4c97ce812f3c42a312a346e709a2e

[Octree] Group carpool to your event https://caroster.io

🐛 Fix forbidden error on notifications fetch #491 #492
Tim Izzo tim@octree.ch
Fri, 16 Feb 2024 08:52:17 +0000
commit

339cbcd2ddf4c97ce812f3c42a312a346e709a2e

parent

d093130068a7eaa39a600bd411181a85f168dc74

A backend/src/api/notification/policies/check-find.ts

@@ -0,0 +1,11 @@

+import { errors } from "@strapi/utils"; + +export default async (policyContext) => { + const user = policyContext.state.user; + if (!user) throw new errors.ForbiddenError(); + + policyContext.args.filters = { + ...(policyContext.args || {}), + user: { id: { eq: user.id } }, + }; +};
M backend/src/api/travel/policies/check-update.tsbackend/src/api/travel/policies/check-update.ts

@@ -15,7 +15,7 @@

const event = travel.event; const eventId = policyContext.args?.data?.event; - if (eventId !== event.id) + if (!!eventId && eventId !== event.id) throw new errors.UnauthorizedError("Can't change travel linked event"); if (event.enabled_modules?.includes("caroster-plus")) {
M backend/src/graphql/notification/index.tsbackend/src/graphql/notification/index.ts

@@ -55,6 +55,10 @@ },

}, }, resolversConfig: { + "Query.notifications": { + auth: true, + policies: ["api::notification.check-find"], + }, "Mutation.readNotifications": { auth: true, },
M backend/src/graphql/user/index.tsbackend/src/graphql/user/index.ts

@@ -125,27 +125,35 @@ "UsersPermissionsUser.vehicles": {

auth: true, }, "UsersPermissionsUser.events": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.notifications": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.confirmed": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.provider": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.newsletterConsent": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.createdAt": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.onboardingCreator": { + auth: true, policies: [checkAuthUser], }, "UsersPermissionsUser.onboardingUser": { + auth: true, policies: [checkAuthUser], }, },
M frontend/containers/DrawerNotification/CardNotification.tsxfrontend/containers/DrawerNotification/CardNotification.tsx

@@ -29,10 +29,6 @@ router.push(`/e/${notification.attributes.event.data.attributes.uuid}`);

onClose(); }; - const showBadge = !notification.attributes.read; - const notificationContentKey = `notification.type.${notification.attributes.type}.content`; - const notificationContent = t(notificationContentKey); - return ( <Box padding={2}

@@ -51,7 +47,7 @@ justifyContent="space-between"

spacing={2} > <Box display="flex" alignItems="center" sx={{width: '168px'}}> - {showBadge && ( + {!notification.attributes.read && ( <Badge sx={{pr: 2}} color="error"

@@ -71,7 +67,9 @@ <Typography variant="overline" color="text.secondary">

{formatDate(notification.attributes.createdAt)} </Typography> </Stack> - <Typography>{notificationContent}</Typography> + <Typography> + {t(`notification.type.${notification.attributes.type}.content`)} + </Typography> </Box> </Box> );
M frontend/containers/DrawerNotification/DrawerContent.tsxfrontend/containers/DrawerNotification/DrawerContent.tsx

@@ -1,7 +1,6 @@

import {Drawer, Box, Icon, Typography} from '@mui/material/'; import useMediaQuery from '@mui/material/useMediaQuery'; import { - useUserNotificationsQuery, useReadNotificationsMutation, NotificationEntity, } from '../../generated/graphql';

@@ -12,22 +11,20 @@

interface Props { isOpen: boolean; onClose: () => void; - notification: NotificationEntity; + notifications: NotificationEntity[]; } -const DrawerContent = ({isOpen, onClose}: Props) => { - const {data} = useUserNotificationsQuery(); - const [readNotifications] = useReadNotificationsMutation(); +const DrawerContent = ({isOpen, onClose, notifications}: Props) => { + const isMobile = useMediaQuery('(max-width:400px)'); const {t} = useTranslation(); - const notifications = data?.me?.profile?.notifications?.data || []; const hasNotifications = notifications.length > 0; - const markAllRead = () => { - readNotifications({refetchQueries: ['UserNotifications']}); - }; + const [readNotifications] = useReadNotificationsMutation(); const isAllRead = notifications.every( notification => notification.attributes.read ); - const isMobile = useMediaQuery('(max-width:400px)'); + + const markAllRead = () => + readNotifications({refetchQueries: ['UserNotifications']}); return ( <Drawer

@@ -55,12 +52,11 @@ disabled={isAllRead}

/> <Box> {hasNotifications ? ( - notifications.map((notification, index) => ( + notifications.map(notification => ( <CardNotification key={notification.id} onClose={onClose} notification={notification} - isRead={readNotifications[index]} /> )) ) : (
M frontend/containers/DrawerNotification/index.tsxfrontend/containers/DrawerNotification/index.tsx

@@ -1,18 +1,21 @@

import Icon from '@mui/material/Icon'; import IconButton from '@mui/material/IconButton'; import React, {useState} from 'react'; -import {useUserNotificationsQuery} from '../../generated/graphql'; +import { + NotificationEntity, + useUserNotificationsQuery, +} from '../../generated/graphql'; import Badge from '@mui/material/Badge'; import DrawerContent from './DrawerContent'; + +const POLL_INTERVAL = 30000; const DrawerNotification = () => { - const POLL_INTERVAL = 30000; + const [isDrawerOpen, setIsDrawerOpen] = useState(false); const {data} = useUserNotificationsQuery({ pollInterval: POLL_INTERVAL, }); - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - - const notifications = data?.me?.profile?.notifications?.data || []; + const notifications = data?.notifications?.data || []; const hasUnreadNotifications = notifications.some( notification => !notification.attributes.read

@@ -40,6 +43,7 @@

<DrawerContent isOpen={isDrawerOpen} onClose={() => setIsDrawerOpen(false)} + notifications={notifications as NotificationEntity[]} /> </> );
M frontend/generated/graphql.tsxfrontend/generated/graphql.tsx

@@ -2121,7 +2121,7 @@ maxItems?: InputMaybe<Scalars['Int']['input']>;

}>; -export type UserNotificationsQuery = { __typename?: 'Query', me?: { __typename?: 'UsersPermissionsMe', profile?: { __typename?: 'UsersPermissionsUser', notifications?: { __typename?: 'NotificationRelationResponseCollection', data: Array<{ __typename?: 'NotificationEntity', id?: string | null, attributes?: { __typename?: 'Notification', type: Enum_Notification_Type, read?: boolean | null, createdAt?: any | null, event?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', name: string, uuid?: string | null } | null } | null } | null } | null }> } | null } | null } | null }; +export type UserNotificationsQuery = { __typename?: 'Query', notifications?: { __typename?: 'NotificationEntityResponseCollection', data: Array<{ __typename?: 'NotificationEntity', id?: string | null, attributes?: { __typename?: 'Notification', type: Enum_Notification_Type, read?: boolean | null, createdAt?: any | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', email: string } | null } | null } | null, event?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', name: string, uuid?: string | null } | null } | null } | null } | null }> } | null }; export type ReadNotificationsMutationVariables = Exact<{ id?: InputMaybe<Scalars['ID']['input']>;

@@ -2828,23 +2828,27 @@ export type ModuleLazyQueryHookResult = ReturnType<typeof useModuleLazyQuery>;

export type ModuleQueryResult = Apollo.QueryResult<ModuleQuery, ModuleQueryVariables>; export const UserNotificationsDocument = gql` query UserNotifications($maxItems: Int = 20) { - me { - profile { - notifications(pagination: {limit: $maxItems}, sort: "createdAt:DESC") { - data { - id - attributes { - type - read - createdAt - event { - data { - id - attributes { - name - uuid - } - } + notifications(pagination: {limit: $maxItems}, sort: "createdAt:DESC") { + data { + id + attributes { + type + read + createdAt + user { + data { + id + attributes { + email + } + } + } + event { + data { + id + attributes { + name + uuid } } }
M frontend/graphql/notifications.gqlfrontend/graphql/notifications.gql

@@ -1,21 +1,25 @@

query UserNotifications($maxItems: Int = 20) { - me { - profile { - notifications(pagination: {limit: $maxItems}, sort: "createdAt:DESC") { - data { - id - attributes { - type - read - createdAt - event { - data { - id - attributes { - name - uuid - } - } + notifications(pagination: {limit: $maxItems}, sort: "createdAt:DESC") { + data { + id + attributes { + type + read + createdAt + user { + data { + id + attributes { + email + } + } + } + event { + data { + id + attributes { + name + uuid } } }

@@ -35,4 +39,3 @@ }

} } } -