From 22093c0c2982c31a237ac3547d5935c3bbacd02a Mon Sep 17 00:00:00 2001 From: Jordan Higuera Higuera Date: Thu, 3 Aug 2023 21:33:51 -0700 Subject: [PATCH 1/5] add sqlite compatibility + fix whitespace bug collections --- .gitignore | 2 + lib/api/controllers/links/getLinks.ts | 5 -- lib/api/controllers/links/postLink.ts | 7 +- lib/api/controllers/users/getUsers.ts | 13 ++- lib/api/controllers/users/updateUser.ts | 47 +++++++++- pages/api/avatar/[id].ts | 7 +- prisma/schema.prisma | 115 +++++++++++++----------- types/global.ts | 1 + 8 files changed, 130 insertions(+), 67 deletions(-) diff --git a/.gitignore b/.gitignore index e10e251..77956c8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,8 @@ next-env.d.ts # generated files and folders /data +.idea +prisma/dev.db # tests /tests diff --git a/lib/api/controllers/links/getLinks.ts b/lib/api/controllers/links/getLinks.ts index d5ed6df..22df9fb 100644 --- a/lib/api/controllers/links/getLinks.ts +++ b/lib/api/controllers/links/getLinks.ts @@ -66,7 +66,6 @@ export default async function getLink(userId: number, body: string) { query.searchQuery && query.searchFilter?.name ? query.searchQuery : undefined, - mode: "insensitive", }, }, { @@ -75,7 +74,6 @@ export default async function getLink(userId: number, body: string) { query.searchQuery && query.searchFilter?.url ? query.searchQuery : undefined, - mode: "insensitive", }, }, { @@ -84,7 +82,6 @@ export default async function getLink(userId: number, body: string) { query.searchQuery && query.searchFilter?.description ? query.searchQuery : undefined, - mode: "insensitive", }, }, { @@ -100,7 +97,6 @@ export default async function getLink(userId: number, body: string) { query.searchQuery && query.searchFilter?.tags ? { contains: query.searchQuery, - mode: "insensitive", } : undefined, OR: [ @@ -114,7 +110,6 @@ export default async function getLink(userId: number, body: string) { query.searchFilter?.tags ? query.searchQuery : undefined, - mode: "insensitive", }, collection: { members: { diff --git a/lib/api/controllers/links/postLink.ts b/lib/api/controllers/links/postLink.ts index 3a5bfbd..3653eb9 100644 --- a/lib/api/controllers/links/postLink.ts +++ b/lib/api/controllers/links/postLink.ts @@ -20,12 +20,15 @@ export default async function postLink( }; } - link.collection.name = link.collection.name.trim(); - + // This has to move above we assign link.collection.name + // Because if the link is null (write then delete text on collection) + // It will try to do trim on empty string and will throw and error, this prevents it. if (!link.collection.name) { link.collection.name = "Unnamed Collection"; } + link.collection.name = link.collection.name.trim(); + if (link.collection.id) { const collectionIsAccessible = (await getPermission( userId, diff --git a/lib/api/controllers/users/getUsers.ts b/lib/api/controllers/users/getUsers.ts index 381a713..9d752a6 100644 --- a/lib/api/controllers/users/getUsers.ts +++ b/lib/api/controllers/users/getUsers.ts @@ -17,14 +17,23 @@ export default async function getUser({ id: params.lookupId, username: params.lookupUsername?.toLowerCase(), }, + include: { + whitelistedUsers: { + select: { + username: true + } + } + } }); if (!user) return { response: "User not found.", status: 404 }; + const whitelistedUsernames = user.whitelistedUsers?.map(usernames => usernames.username); + if ( !isSelf && user?.isPrivate && - !user.whitelistedUsers.includes(username.toLowerCase()) + !whitelistedUsernames.includes(username.toLowerCase()) ) { return { response: "This profile is private.", status: 401 }; } @@ -33,7 +42,7 @@ export default async function getUser({ const data = isSelf ? // If user is requesting its own data - lessSensitiveInfo + {...lessSensitiveInfo, whitelistedUsers: whitelistedUsernames} : { // If user is requesting someone elses data id: lessSensitiveInfo.id, diff --git a/lib/api/controllers/users/updateUser.ts b/lib/api/controllers/users/updateUser.ts index 1f41fb5..91674ba 100644 --- a/lib/api/controllers/users/updateUser.ts +++ b/lib/api/controllers/users/updateUser.ts @@ -106,14 +106,56 @@ export default async function updateUser( username: user.username.toLowerCase(), email: user.email?.toLowerCase(), isPrivate: user.isPrivate, - whitelistedUsers: user.whitelistedUsers, password: user.newPassword && user.newPassword !== "" ? newHashedPassword : undefined, }, + include: { + whitelistedUsers: true + } }); + + const { whitelistedUsers, password, ...userInfo } = updatedUser; + + // If user.whitelistedUsers is not provided, we will assume the whitelistedUsers should be removed + const newWhitelistedUsernames: string[] = user.whitelistedUsers || []; + + // Get the current whitelisted usernames + const currentWhitelistedUsernames: string[] = whitelistedUsers.map((user) => user.username); + + // Find the usernames to be deleted (present in current but not in new) + const usernamesToDelete: string[] = currentWhitelistedUsernames.filter( + (username) => !newWhitelistedUsernames.includes(username) + ); + + // Find the usernames to be created (present in new but not in current) + const usernamesToCreate: string[] = newWhitelistedUsernames.filter( + (username) => !currentWhitelistedUsernames.includes(username) && username.trim() !== '' + ); + + // Delete whitelistedUsers that are not present in the new list + await prisma.whitelistedUser.deleteMany({ + where: { + userId: sessionUser.id, + username: { + in: usernamesToDelete, + }, + }, + }); + + // Create new whitelistedUsers that are not in the current list, no create many ;( + for (const username of usernamesToCreate) { + await prisma.whitelistedUser.create({ + data: { + username, + userId: sessionUser.id, + }, + }); + } + + const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY; const PRICE_ID = process.env.PRICE_ID; @@ -125,10 +167,9 @@ export default async function updateUser( user.email as string ); - const { password, ...userInfo } = updatedUser; - const response: Omit = { ...userInfo, + whitelistedUsers: newWhitelistedUsernames, profilePic: `/api/avatar/${userInfo.id}?${Date.now()}`, }; diff --git a/pages/api/avatar/[id].ts b/pages/api/avatar/[id].ts index 73b155b..ac4f1d3 100644 --- a/pages/api/avatar/[id].ts +++ b/pages/api/avatar/[id].ts @@ -33,11 +33,16 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) { where: { id: queryId, }, + include: { + whitelistedUsers: true + } }); + const whitelistedUsernames = targetUser?.whitelistedUsers.map(whitelistedUsername => whitelistedUsername.username); + if ( targetUser?.isPrivate && - !targetUser.whitelistedUsers.includes(username) + !whitelistedUsernames?.includes(username) ) { return res .setHeader("Content-Type", "text/plain") diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 43d8b90..da10e49 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -4,22 +4,22 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") + url = env("DATABASE_URL") } model Account { - id String @id @default(cuid()) - userId Int - type String - provider String - providerAccountId String - refresh_token String? @db.Text - access_token String? @db.Text - expires_at Int? - token_type String? - scope String? - id_token String? @db.Text - session_state String? + id String @id @default(cuid()) + userId Int + type String + provider String + providerAccountId String + refresh_token String? + access_token String? + expires_at Int? + token_type String? + scope String? + id_token String? + session_state String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@ -35,29 +35,37 @@ model Session { } model User { - id Int @id @default(autoincrement()) - name String + id Int @id @default(autoincrement()) + name String - username String? @unique + username String? @unique - email String? @unique - emailVerified DateTime? - image String? + email String? @unique + emailVerified DateTime? + image String? - accounts Account[] - sessions Session[] - - password String - collections Collection[] + accounts Account[] + sessions Session[] - tags Tag[] + password String + collections Collection[] - pinnedLinks Link[] - - collectionsJoined UsersAndCollections[] - isPrivate Boolean @default(false) - whitelistedUsers String[] @default([]) - createdAt DateTime @default(now()) + tags Tag[] + + pinnedLinks Link[] + + collectionsJoined UsersAndCollections[] + isPrivate Boolean @default(false) + whitelistedUsers whitelistedUser[] + createdAt DateTime @default(now()) +} + +model whitelistedUser { + id Int @id @default(autoincrement()) + + username String @default("") + User User? @relation(fields: [userId], references: [id]) + userId Int? } model VerificationToken { @@ -69,27 +77,26 @@ model VerificationToken { } model Collection { - id Int @id @default(autoincrement()) - name String - description String @default("") - color String @default("#0ea5e9") - isPublic Boolean @default(false) + id Int @id @default(autoincrement()) + name String + description String @default("") + color String @default("#0ea5e9") + isPublic Boolean @default(false) - - owner User @relation(fields: [ownerId], references: [id]) - ownerId Int - members UsersAndCollections[] - links Link[] - createdAt DateTime @default(now()) + owner User @relation(fields: [ownerId], references: [id]) + ownerId Int + members UsersAndCollections[] + links Link[] + createdAt DateTime @default(now()) @@unique([name, ownerId]) } model UsersAndCollections { - user User @relation(fields: [userId], references: [id]) + user User @relation(fields: [userId], references: [id]) userId Int - collection Collection @relation(fields: [collectionId], references: [id]) + collection Collection @relation(fields: [collectionId], references: [id]) collectionId Int canCreate Boolean @@ -100,24 +107,24 @@ model UsersAndCollections { } model Link { - id Int @id @default(autoincrement()) - name String - url String + id Int @id @default(autoincrement()) + name String + url String description String @default("") pinnedBy User[] - collection Collection @relation(fields: [collectionId], references: [id]) + collection Collection @relation(fields: [collectionId], references: [id]) collectionId Int - tags Tag[] - createdAt DateTime @default(now()) + tags Tag[] + createdAt DateTime @default(now()) } model Tag { - id Int @id @default(autoincrement()) - name String - links Link[] - owner User @relation(fields: [ownerId], references: [id]) + id Int @id @default(autoincrement()) + name String + links Link[] + owner User @relation(fields: [ownerId], references: [id]) ownerId Int @@unique([name, ownerId]) diff --git a/types/global.ts b/types/global.ts index 95b2640..04b68e0 100644 --- a/types/global.ts +++ b/types/global.ts @@ -36,6 +36,7 @@ export interface CollectionIncludingMembersAndLinkCount export interface AccountSettings extends User { profilePic: string; newPassword?: string; + whitelistedUsers: string[] } interface LinksIncludingTags extends Link { From 895ef8e60f7e66e2b7be470cb18d66908dba9dac Mon Sep 17 00:00:00 2001 From: Jordan Higuera Higuera Date: Fri, 4 Aug 2023 10:08:04 -0700 Subject: [PATCH 2/5] add mode insensitive in case we are using postgresql + rename table --- lib/api/controllers/links/getLinks.ts | 279 +++++++++++++------------- prisma/schema.prisma | 6 +- 2 files changed, 146 insertions(+), 139 deletions(-) diff --git a/lib/api/controllers/links/getLinks.ts b/lib/api/controllers/links/getLinks.ts index 22df9fb..4f9b1e6 100644 --- a/lib/api/controllers/links/getLinks.ts +++ b/lib/api/controllers/links/getLinks.ts @@ -1,145 +1,152 @@ -import { prisma } from "@/lib/api/db"; -import { LinkRequestQuery, Sort } from "@/types/global"; +import {prisma} from "@/lib/api/db"; +import {LinkRequestQuery, Sort} from "@/types/global"; +import * as process from "process"; export default async function getLink(userId: number, body: string) { - const query: LinkRequestQuery = JSON.parse(decodeURIComponent(body)); - console.log(query); + const query: LinkRequestQuery = JSON.parse(decodeURIComponent(body)); + console.log(query); - // Sorting logic - let order: any; - if (query.sort === Sort.DateNewestFirst) - order = { - createdAt: "desc", - }; - else if (query.sort === Sort.DateOldestFirst) - order = { - createdAt: "asc", - }; - else if (query.sort === Sort.NameAZ) - order = { - name: "asc", - }; - else if (query.sort === Sort.NameZA) - order = { - name: "desc", - }; - else if (query.sort === Sort.DescriptionAZ) - order = { - name: "asc", - }; - else if (query.sort === Sort.DescriptionZA) - order = { - name: "desc", - }; + const POSTGRES_IS_ENABLED = process.env.DATABASE_URL.startsWith("postgresql"); + // Sorting logic + let order: any; + if (query.sort === Sort.DateNewestFirst) + order = { + createdAt: "desc", + }; + else if (query.sort === Sort.DateOldestFirst) + order = { + createdAt: "asc", + }; + else if (query.sort === Sort.NameAZ) + order = { + name: "asc", + }; + else if (query.sort === Sort.NameZA) + order = { + name: "desc", + }; + else if (query.sort === Sort.DescriptionAZ) + order = { + name: "asc", + }; + else if (query.sort === Sort.DescriptionZA) + order = { + name: "desc", + }; - const links = await prisma.link.findMany({ - take: Number(process.env.PAGINATION_TAKE_COUNT) || 20, - skip: query.cursor ? 1 : undefined, - cursor: query.cursor - ? { - id: query.cursor, - } - : undefined, - where: { - collection: { - id: query.collectionId ? query.collectionId : undefined, // If collectionId was defined, filter by collection - OR: [ - { - ownerId: userId, - }, - { - members: { - some: { - userId, - }, - }, - }, - ], - }, - [query.searchQuery ? "OR" : "AND"]: [ - { - pinnedBy: query.pinnedOnly ? { some: { id: userId } } : undefined, - }, - { - name: { - contains: - query.searchQuery && query.searchFilter?.name - ? query.searchQuery - : undefined, - }, - }, - { - url: { - contains: - query.searchQuery && query.searchFilter?.url - ? query.searchQuery - : undefined, - }, - }, - { - description: { - contains: - query.searchQuery && query.searchFilter?.description - ? query.searchQuery - : undefined, - }, - }, - { - tags: - query.searchQuery && !query.searchFilter?.tags - ? undefined - : { - some: query.tagId - ? { - // If tagId was defined, filter by tag - id: query.tagId, - name: - query.searchQuery && query.searchFilter?.tags - ? { - contains: query.searchQuery, - } - : undefined, - OR: [ - { ownerId: userId }, // Tags owned by the user - { - links: { - some: { - name: { - contains: - query.searchQuery && - query.searchFilter?.tags - ? query.searchQuery - : undefined, - }, - collection: { - members: { - some: { - userId, // Tags from collections where the user is a member - }, - }, - }, - }, + const links = await prisma.link.findMany({ + take: Number(process.env.PAGINATION_TAKE_COUNT) || 20, + skip: query.cursor ? 1 : undefined, + cursor: query.cursor + ? { + id: query.cursor, + } + : undefined, + where: { + collection: { + id: query.collectionId ? query.collectionId : undefined, // If collectionId was defined, filter by collection + OR: [ + { + ownerId: userId, + }, + { + members: { + some: { + userId, }, - }, - ], - } - : undefined, + }, + }, + ], + }, + [query.searchQuery ? "OR" : "AND"]: [ + { + pinnedBy: query.pinnedOnly ? {some: {id: userId}} : undefined, }, + { + name: { + contains: + query.searchQuery && query.searchFilter?.name + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + }, + { + url: { + contains: + query.searchQuery && query.searchFilter?.url + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + }, + { + description: { + contains: + query.searchQuery && query.searchFilter?.description + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + }, + { + tags: + query.searchQuery && !query.searchFilter?.tags + ? undefined + : { + some: query.tagId + ? { + // If tagId was defined, filter by tag + id: query.tagId, + name: + query.searchQuery && query.searchFilter?.tags + ? { + contains: query.searchQuery, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + } + : undefined, + OR: [ + {ownerId: userId}, // Tags owned by the user + { + links: { + some: { + name: { + contains: + query.searchQuery && + query.searchFilter?.tags + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + collection: { + members: { + some: { + userId, // Tags from collections where the user is a member + }, + }, + }, + }, + }, + }, + ], + } + : undefined, + }, + }, + ], }, - ], - }, - include: { - tags: true, - collection: true, - pinnedBy: { - where: { id: userId }, - select: { id: true }, - }, - }, - orderBy: order || { - createdAt: "desc", - }, - }); + include: { + tags: true, + collection: true, + pinnedBy: { + where: {id: userId}, + select: {id: true}, + }, + }, + orderBy: order || { + createdAt: "desc", + }, + }); - return { response: links, status: 200 }; + return {response: links, status: 200}; } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index da10e49..dc9170b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -3,7 +3,7 @@ generator client { } datasource db { - provider = "postgresql" + provider = "sqlite" url = env("DATABASE_URL") } @@ -56,11 +56,11 @@ model User { collectionsJoined UsersAndCollections[] isPrivate Boolean @default(false) - whitelistedUsers whitelistedUser[] + whitelistedUsers WhitelistedUser[] createdAt DateTime @default(now()) } -model whitelistedUser { +model WhitelistedUser { id Int @id @default(autoincrement()) username String @default("") From 8747331c43677ac44dc43f1effbf01729fe50ff6 Mon Sep 17 00:00:00 2001 From: Jordan Higuera Higuera Date: Fri, 4 Aug 2023 10:13:23 -0700 Subject: [PATCH 3/5] remove unused import --- lib/api/controllers/links/getLinks.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api/controllers/links/getLinks.ts b/lib/api/controllers/links/getLinks.ts index 4f9b1e6..ee78512 100644 --- a/lib/api/controllers/links/getLinks.ts +++ b/lib/api/controllers/links/getLinks.ts @@ -1,6 +1,5 @@ import {prisma} from "@/lib/api/db"; import {LinkRequestQuery, Sort} from "@/types/global"; -import * as process from "process"; export default async function getLink(userId: number, body: string) { const query: LinkRequestQuery = JSON.parse(decodeURIComponent(body)); From 91f9fcb500e399aed74388df65f4fc90517e6a79 Mon Sep 17 00:00:00 2001 From: Jordan Higuera Higuera Date: Fri, 4 Aug 2023 14:41:53 -0700 Subject: [PATCH 4/5] changed default provider --- prisma/schema.prisma | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index dc9170b..c1c04d8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -3,7 +3,7 @@ generator client { } datasource db { - provider = "sqlite" + provider = "postgresql" url = env("DATABASE_URL") } From 9405445332b75bb641094a0c0eea7fd7c450ac7c Mon Sep 17 00:00:00 2001 From: Jordan Higuera Higuera Date: Fri, 4 Aug 2023 15:10:31 -0700 Subject: [PATCH 5/5] identation fix --- lib/api/controllers/links/getLinks.ts | 280 +++++++++++++------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/lib/api/controllers/links/getLinks.ts b/lib/api/controllers/links/getLinks.ts index ee78512..1601e20 100644 --- a/lib/api/controllers/links/getLinks.ts +++ b/lib/api/controllers/links/getLinks.ts @@ -2,150 +2,150 @@ import {prisma} from "@/lib/api/db"; import {LinkRequestQuery, Sort} from "@/types/global"; export default async function getLink(userId: number, body: string) { - const query: LinkRequestQuery = JSON.parse(decodeURIComponent(body)); - console.log(query); + const query: LinkRequestQuery = JSON.parse(decodeURIComponent(body)); + console.log(query); - const POSTGRES_IS_ENABLED = process.env.DATABASE_URL.startsWith("postgresql"); - // Sorting logic - let order: any; - if (query.sort === Sort.DateNewestFirst) - order = { - createdAt: "desc", - }; - else if (query.sort === Sort.DateOldestFirst) - order = { - createdAt: "asc", - }; - else if (query.sort === Sort.NameAZ) - order = { - name: "asc", - }; - else if (query.sort === Sort.NameZA) - order = { - name: "desc", - }; - else if (query.sort === Sort.DescriptionAZ) - order = { - name: "asc", - }; - else if (query.sort === Sort.DescriptionZA) - order = { - name: "desc", - }; + const POSTGRES_IS_ENABLED = process.env.DATABASE_URL.startsWith("postgresql"); + // Sorting logic + let order: any; + if (query.sort === Sort.DateNewestFirst) + order = { + createdAt: "desc", + }; + else if (query.sort === Sort.DateOldestFirst) + order = { + createdAt: "asc", + }; + else if (query.sort === Sort.NameAZ) + order = { + name: "asc", + }; + else if (query.sort === Sort.NameZA) + order = { + name: "desc", + }; + else if (query.sort === Sort.DescriptionAZ) + order = { + name: "asc", + }; + else if (query.sort === Sort.DescriptionZA) + order = { + name: "desc", + }; - const links = await prisma.link.findMany({ - take: Number(process.env.PAGINATION_TAKE_COUNT) || 20, - skip: query.cursor ? 1 : undefined, - cursor: query.cursor - ? { - id: query.cursor, - } - : undefined, - where: { - collection: { - id: query.collectionId ? query.collectionId : undefined, // If collectionId was defined, filter by collection - OR: [ - { - ownerId: userId, - }, - { - members: { - some: { - userId, + const links = await prisma.link.findMany({ + take: Number(process.env.PAGINATION_TAKE_COUNT) || 20, + skip: query.cursor ? 1 : undefined, + cursor: query.cursor + ? { + id: query.cursor, + } + : undefined, + where: { + collection: { + id: query.collectionId ? query.collectionId : undefined, // If collectionId was defined, filter by collection + OR: [ + { + ownerId: userId, + }, + { + members: { + some: { + userId, + }, + }, + }, + ], + }, + [query.searchQuery ? "OR" : "AND"]: [ + { + pinnedBy: query.pinnedOnly ? {some: {id: userId}} : undefined, + }, + { + name: { + contains: + query.searchQuery && query.searchFilter?.name + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + }, + { + url: { + contains: + query.searchQuery && query.searchFilter?.url + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + }, + { + description: { + contains: + query.searchQuery && query.searchFilter?.description + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + }, + }, + { + tags: + query.searchQuery && !query.searchFilter?.tags + ? undefined + : { + some: query.tagId + ? { + // If tagId was defined, filter by tag + id: query.tagId, + name: + query.searchQuery && query.searchFilter?.tags + ? { + contains: query.searchQuery, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined + } + : undefined, + OR: [ + {ownerId: userId}, // Tags owned by the user + { + links: { + some: { + name: { + contains: + query.searchQuery && + query.searchFilter?.tags + ? query.searchQuery + : undefined, + mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined }, + collection: { + members: { + some: { + userId, // Tags from collections where the user is a member + }, + }, + }, + }, }, - }, - ], - }, - [query.searchQuery ? "OR" : "AND"]: [ - { - pinnedBy: query.pinnedOnly ? {some: {id: userId}} : undefined, - }, - { - name: { - contains: - query.searchQuery && query.searchFilter?.name - ? query.searchQuery - : undefined, - mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined - }, - }, - { - url: { - contains: - query.searchQuery && query.searchFilter?.url - ? query.searchQuery - : undefined, - mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined - }, - }, - { - description: { - contains: - query.searchQuery && query.searchFilter?.description - ? query.searchQuery - : undefined, - mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined - }, - }, - { - tags: - query.searchQuery && !query.searchFilter?.tags - ? undefined - : { - some: query.tagId - ? { - // If tagId was defined, filter by tag - id: query.tagId, - name: - query.searchQuery && query.searchFilter?.tags - ? { - contains: query.searchQuery, - mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined - } - : undefined, - OR: [ - {ownerId: userId}, // Tags owned by the user - { - links: { - some: { - name: { - contains: - query.searchQuery && - query.searchFilter?.tags - ? query.searchQuery - : undefined, - mode: POSTGRES_IS_ENABLED ? "insensitive" : undefined - }, - collection: { - members: { - some: { - userId, // Tags from collections where the user is a member - }, - }, - }, - }, - }, - }, - ], - } - : undefined, - }, - }, - ], + }, + ], + } + : undefined, + }, }, - include: { - tags: true, - collection: true, - pinnedBy: { - where: {id: userId}, - select: {id: true}, - }, - }, - orderBy: order || { - createdAt: "desc", - }, - }); + ], + }, + include: { + tags: true, + collection: true, + pinnedBy: { + where: {id: userId}, + select: {id: true}, + }, + }, + orderBy: order || { + createdAt: "desc", + }, + }); - return {response: links, status: 200}; + return {response: links, status: 200}; }