diff --git a/backend/.eslintrc.cjs b/backend/.eslintrc.cjs index 684c26948..51adb6831 100644 --- a/backend/.eslintrc.cjs +++ b/backend/.eslintrc.cjs @@ -181,7 +181,7 @@ module.exports = { extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking', - // 'plugin:@typescript-eslint/strict', + 'plugin:@typescript-eslint/strict', 'prettier', ], rules: { diff --git a/backend/src/middleware/notifications/notificationsMiddleware.ts b/backend/src/middleware/notifications/notificationsMiddleware.ts index 5d2febffd..f7be031c8 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.ts +++ b/backend/src/middleware/notifications/notificationsMiddleware.ts @@ -19,7 +19,7 @@ import { pubsub, NOTIFICATION_ADDED, ROOM_COUNT_UPDATED, CHAT_MESSAGE_ADDED } fr import extractMentionedUsers from './mentions/extractMentionedUsers' const queryNotificationEmails = async (context, notificationUserIds) => { - if (!(notificationUserIds && notificationUserIds.length)) return [] + if (!notificationUserIds?.length) return [] const userEmailCypher = ` MATCH (user: User) // blocked users are filtered out from notifications already @@ -360,7 +360,7 @@ const notifyMemberOfGroup = async (groupId, userId, reason, context) => { } const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => { - if (!(idsOfUsers && idsOfUsers.length)) return [] + if (!idsOfUsers?.length) return [] await validateNotifyUsers(label, reason) let mentionedCypher switch (reason) { diff --git a/backend/src/middleware/permissionsMiddleware.ts b/backend/src/middleware/permissionsMiddleware.ts index a17072c4b..20063de11 100644 --- a/backend/src/middleware/permissionsMiddleware.ts +++ b/backend/src/middleware/permissionsMiddleware.ts @@ -18,7 +18,7 @@ const neode = getNeode() const isAuthenticated = rule({ cache: 'contextual', })(async (_parent, _args, ctx, _info) => { - return !!(ctx && ctx.user && ctx.user.id) + return !!ctx?.user?.id }) const isModerator = rule()(async (_parent, _args, { user }, _info) => { @@ -62,7 +62,7 @@ const isMySocialMedia = rule({ const isAllowedToChangeGroupSettings = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const ownerId = user.id const { id: groupId } = args const session = driver.session() @@ -92,7 +92,7 @@ const isAllowedToChangeGroupSettings = rule({ const isAllowedSeeingGroupMembers = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const { id: groupId } = args const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { @@ -128,7 +128,7 @@ const isAllowedSeeingGroupMembers = rule({ const isAllowedToChangeGroupMemberRole = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const currentUserId = user.id const { groupId, userId, roleInGroup } = args if (currentUserId === userId) return false @@ -175,7 +175,7 @@ const isAllowedToChangeGroupMemberRole = rule({ const isAllowedToJoinGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const { groupId, userId } = args const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { @@ -205,7 +205,7 @@ const isAllowedToJoinGroup = rule({ const isAllowedToLeaveGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const { groupId, userId } = args if (user.id !== userId) return false const session = driver.session() @@ -235,7 +235,7 @@ const isAllowedToLeaveGroup = rule({ const isMemberOfGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const { groupId } = args if (!groupId) return true const userId = user.id @@ -263,7 +263,7 @@ const isMemberOfGroup = rule({ const canRemoveUserFromGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const { groupId, userId } = args const currentUserId = user.id if (currentUserId === userId) return false @@ -299,7 +299,7 @@ const canRemoveUserFromGroup = rule({ const canCommentPost = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - if (!(user && user.id)) return false + if (!user?.id) return false const { postId } = args const userId = user.id const session = driver.session() diff --git a/backend/src/middleware/sentryMiddleware.ts b/backend/src/middleware/sentryMiddleware.ts index 6577be4ee..743ec32df 100644 --- a/backend/src/middleware/sentryMiddleware.ts +++ b/backend/src/middleware/sentryMiddleware.ts @@ -21,7 +21,7 @@ if (CONFIG.SENTRY_DSN_BACKEND) { // eslint-disable-next-line @typescript-eslint/no-explicit-any withScope: (scope, error, context: any) => { scope.setUser({ - id: context.user && context.user.id, + id: context.user?.id, }) scope.setExtra('body', context.req.body) scope.setExtra('origin', context.req.headers.origin) diff --git a/backend/src/middleware/validation/validationMiddleware.ts b/backend/src/middleware/validation/validationMiddleware.ts index 317595ee3..75f8f5d09 100644 --- a/backend/src/middleware/validation/validationMiddleware.ts +++ b/backend/src/middleware/validation/validationMiddleware.ts @@ -87,7 +87,7 @@ const validateReview = async (resolve, root, args, context, info) => { try { const txResult = await reportReadTxPromise existingReportedResource = txResult - if (!existingReportedResource || !existingReportedResource.length) + if (!existingReportedResource?.length) throw new Error(`Resource not found or is not a Post|Comment|User!`) existingReportedResource = existingReportedResource[0] if (!existingReportedResource.filed) diff --git a/backend/src/schema/resolvers/emails.ts b/backend/src/schema/resolvers/emails.ts index d4313558e..be721dda5 100644 --- a/backend/src/schema/resolvers/emails.ts +++ b/backend/src/schema/resolvers/emails.ts @@ -48,7 +48,7 @@ export default { // check email does not belong to anybody const existingEmail = await existingEmailAddress({ args, context }) - if (existingEmail && existingEmail.alreadyExistingEmail && existingEmail.user) + if (existingEmail?.alreadyExistingEmail && existingEmail.user) return existingEmail.alreadyExistingEmail const nonce = generateNonce() diff --git a/backend/src/schema/resolvers/groups.spec.ts b/backend/src/schema/resolvers/groups.spec.ts index a61d7e8b9..c8ce48c37 100644 --- a/backend/src/schema/resolvers/groups.spec.ts +++ b/backend/src/schema/resolvers/groups.spec.ts @@ -2429,7 +2429,7 @@ describe('in mode', () => { id: groupId, }, }) - return result.data && result.data.GroupMembers + return result.data?.GroupMembers ? !!result.data.GroupMembers.find((member) => member.id === userId) : null } diff --git a/backend/src/schema/resolvers/helpers/Resolver.ts b/backend/src/schema/resolvers/helpers/Resolver.ts index cad886ace..2d7faa7b7 100644 --- a/backend/src/schema/resolvers/helpers/Resolver.ts +++ b/backend/src/schema/resolvers/helpers/Resolver.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-dynamic-delete */ /* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ diff --git a/backend/src/schema/resolvers/helpers/events.ts b/backend/src/schema/resolvers/helpers/events.ts index ba68fb587..3e5f8d5a8 100644 --- a/backend/src/schema/resolvers/helpers/events.ts +++ b/backend/src/schema/resolvers/helpers/events.ts @@ -22,7 +22,7 @@ export const validateEventParams = (params) => { throw new UserInputError('Event venue must be present if event location is given!') } params.eventVenue = eventInput.eventVenue - params.eventLocationName = eventInput.eventLocationName && eventInput.eventLocationName.trim() + params.eventLocationName = eventInput.eventLocationName?.trim() if (params.eventLocationName) { locationName = params.eventLocationName } else { diff --git a/backend/src/schema/resolvers/helpers/filterInvisiblePosts.ts b/backend/src/schema/resolvers/helpers/filterInvisiblePosts.ts index 7769ac5f9..2a264ced4 100644 --- a/backend/src/schema/resolvers/helpers/filterInvisiblePosts.ts +++ b/backend/src/schema/resolvers/helpers/filterInvisiblePosts.ts @@ -9,7 +9,7 @@ const getInvisiblePosts = async (context) => { const readTxResultPromise = await session.readTransaction(async (transaction) => { let cypher = '' const { user } = context - if (user && user.id) { + if (user?.id) { cypher = ` MATCH (post:Post)<-[:CANNOT_SEE]-(user:User { id: $userId }) RETURN collect(post.id) AS invisiblePostIds` diff --git a/backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.ts b/backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.ts index 255d32c04..9d40b097e 100644 --- a/backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.ts +++ b/backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.ts @@ -6,7 +6,7 @@ import { mergeWith, isArray } from 'lodash' const getMyGroupIds = async (context) => { const { user } = context - if (!(user && user.id)) return [] + if (!user?.id) return [] const session = context.driver.session() const readTxResultPromise = await session.readTransaction(async (transaction) => { @@ -26,7 +26,7 @@ const getMyGroupIds = async (context) => { } export const filterPostsOfMyGroups = async (params, context) => { - if (!(params.filter && params.filter.postsInMyGroups)) return params + if (!params.filter?.postsInMyGroups) return params delete params.filter.postsInMyGroups const myGroupIds = await getMyGroupIds(context) params.filter = mergeWith( diff --git a/backend/src/schema/resolvers/passwordReset.ts b/backend/src/schema/resolvers/passwordReset.ts index 9995db969..ab53d65fa 100644 --- a/backend/src/schema/resolvers/passwordReset.ts +++ b/backend/src/schema/resolvers/passwordReset.ts @@ -47,7 +47,7 @@ export default { ) }) const [reset] = await passwordResetTxPromise - return !!(reset && reset.properties.usedAt) + return !!reset?.properties.usedAt } finally { session.close() } diff --git a/backend/src/schema/resolvers/user_management.ts b/backend/src/schema/resolvers/user_management.ts index 77f26ceb4..13437e815 100644 --- a/backend/src/schema/resolvers/user_management.ts +++ b/backend/src/schema/resolvers/user_management.ts @@ -49,7 +49,7 @@ export default { ) { delete currentUser.encryptedPassword return encode(currentUser) - } else if (currentUser && currentUser.disabled) { + } else if (currentUser?.disabled) { throw new AuthenticationError('Your account has been disabled.') } else { throw new AuthenticationError('Incorrect email address or password.') diff --git a/backend/src/schema/resolvers/users.ts b/backend/src/schema/resolvers/users.ts index 0abee49fd..4f1fb6d5b 100644 --- a/backend/src/schema/resolvers/users.ts +++ b/backend/src/schema/resolvers/users.ts @@ -228,7 +228,7 @@ export default { const session = context.driver.session() const deleteUserTxResultPromise = session.writeTransaction(async (transaction) => { - if (resource && resource.length) { + if (resource?.length) { await Promise.all( resource.map(async (node) => { const txResult = await transaction.run( diff --git a/backend/src/schema/resolvers/users/location.ts b/backend/src/schema/resolvers/users/location.ts index 2a4ce6427..d32c03cd2 100644 --- a/backend/src/schema/resolvers/users/location.ts +++ b/backend/src/schema/resolvers/users/location.ts @@ -47,8 +47,8 @@ const createLocation = async (session, mapboxData) => { nameRU: mapboxData.text_ru, type: mapboxData.id.split('.')[0].toLowerCase(), address: mapboxData.address, - lng: mapboxData.center && mapboxData.center.length ? mapboxData.center[0] : null, - lat: mapboxData.center && mapboxData.center.length ? mapboxData.center[1] : null, + lng: mapboxData.center?.length ? mapboxData.center[0] : null, + lat: mapboxData.center?.length ? mapboxData.center[1] : null, } let mutation = @@ -95,7 +95,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s debug(res) - if (!res || !res.features || !res.features[0]) { + if (!res?.features?.[0]) { throw new UserInputError('locationName is invalid') } @@ -110,7 +110,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s data = res.features[0] } - if (!data || !data.place_type || !data.place_type.length) { + if (!data?.place_type?.length) { throw new UserInputError('locationName is invalid') } @@ -172,7 +172,7 @@ export const queryLocations = async ({ place, lang }) => { `https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${CONFIG.MAPBOX_TOKEN}&types=region,place,country&language=${lang}`, ) // Return empty array if no location found or error occurred - if (!res || !res.features) { + if (!res?.features) { return [] } return res.features