From 4e2bfd7485474f841de140091ca73d8c097efd7e Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Sun, 28 Apr 2024 22:45:58 -0700 Subject: [PATCH] Update admin/website search. Update param names. --- .../hooks/queries/useFilterQuery.ts | 6 +-- src/lib/prisma.ts | 4 +- src/lib/types.ts | 34 +++------------ src/pages/api/admin/users.ts | 4 +- src/pages/api/admin/websites.ts | 43 +++++++++++++++++-- src/pages/api/teams/[teamId]/users/index.ts | 4 +- .../api/teams/[teamId]/websites/index.ts | 4 +- src/pages/api/teams/index.ts | 4 +- src/pages/api/users/[userId]/teams.ts | 4 +- src/pages/api/users/index.ts | 4 +- src/pages/api/websites/[websiteId]/reports.ts | 4 +- src/pages/api/websites/index.ts | 4 +- src/queries/admin/report.ts | 14 +++--- src/queries/admin/team.ts | 8 ++-- src/queries/admin/teamUser.ts | 6 +-- src/queries/admin/user.ts | 6 +-- src/queries/admin/website.ts | 14 +++--- 17 files changed, 90 insertions(+), 77 deletions(-) diff --git a/src/components/hooks/queries/useFilterQuery.ts b/src/components/hooks/queries/useFilterQuery.ts index 1ac6564b..5963d099 100644 --- a/src/components/hooks/queries/useFilterQuery.ts +++ b/src/components/hooks/queries/useFilterQuery.ts @@ -1,14 +1,14 @@ import { UseQueryOptions } from '@tanstack/react-query'; import { useState } from 'react'; import { useApi } from './useApi'; -import { FilterResult, SearchFilter, FilterQueryResult } from 'lib/types'; +import { PageResult, PageParams, FilterQueryResult } from 'lib/types'; export function useFilterQuery({ queryKey, queryFn, ...options }: Omit & { queryFn: (params?: object) => any }): FilterQueryResult { - const [params, setParams] = useState({ + const [params, setParams] = useState({ query: '', page: 1, }); @@ -21,7 +21,7 @@ export function useFilterQuery({ }); return { - result: data as FilterResult, + result: data as PageResult, query, params, setParams, diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index eb866899..6250f2e5 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -5,7 +5,7 @@ import { MYSQL, POSTGRESQL, getDatabaseType } from 'lib/db'; import { SESSION_COLUMNS, OPERATORS, DEFAULT_PAGE_SIZE } from './constants'; import { fetchWebsite } from './load'; import { maxDate } from './date'; -import { QueryFilters, QueryOptions, SearchFilter } from './types'; +import { QueryFilters, QueryOptions, PageParams } from './types'; import { filtersToArray } from './params'; const MYSQL_DATE_FORMATS = { @@ -191,7 +191,7 @@ async function rawQuery(sql: string, data: object): Promise { return prisma.rawQuery(query, params); } -async function pagedQuery(model: string, criteria: T, filters: SearchFilter) { +async function pagedQuery(model: string, criteria: T, filters: PageParams) { const { page = 1, pageSize, orderBy, sortDescending = false } = filters || {}; const size = +pageSize || DEFAULT_PAGE_SIZE; diff --git a/src/lib/types.ts b/src/lib/types.ts index 712a6aac..95758b6f 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -24,31 +24,7 @@ export type DynamicDataType = ObjectValues; export type KafkaTopic = ObjectValues; export type ReportType = ObjectValues; -export interface WebsiteSearchFilter extends SearchFilter { - userId?: string; - teamId?: string; - includeTeams?: boolean; - onlyTeams?: boolean; -} - -export interface UserSearchFilter extends SearchFilter { - teamId?: string; -} - -export interface TeamSearchFilter extends SearchFilter { - userId?: string; -} - -export interface TeamUserSearchFilter extends SearchFilter { - teamId?: string; -} - -export interface ReportSearchFilter extends SearchFilter { - userId?: string; - websiteId?: string; -} - -export interface SearchFilter { +export interface PageParams { query?: string; page?: number; pageSize?: number; @@ -56,7 +32,7 @@ export interface SearchFilter { sortDescending?: boolean; } -export interface FilterResult { +export interface PageResult { data: T; count: number; page: number; @@ -66,10 +42,10 @@ export interface FilterResult { } export interface FilterQueryResult { - result: FilterResult; + result: PageResult; query: any; - params: SearchFilter; - setParams: Dispatch>; + params: PageParams; + setParams: Dispatch>; } export interface DynamicData { diff --git a/src/pages/api/admin/users.ts b/src/pages/api/admin/users.ts index 31b72ebf..4f03ec9f 100644 --- a/src/pages/api/admin/users.ts +++ b/src/pages/api/admin/users.ts @@ -1,13 +1,13 @@ import { canViewUsers } from 'lib/auth'; import { useAuth, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, Role, SearchFilter, User } from 'lib/types'; +import { NextApiRequestQueryBody, Role, PageParams, User } from 'lib/types'; import { pageInfo } from 'lib/schema'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getUsers } from 'queries'; import * as yup from 'yup'; -export interface UsersRequestQuery extends SearchFilter {} +export interface UsersRequestQuery extends PageParams {} export interface UsersRequestBody { userId: string; username: string; diff --git a/src/pages/api/admin/websites.ts b/src/pages/api/admin/websites.ts index 4fbcd5cc..86692144 100644 --- a/src/pages/api/admin/websites.ts +++ b/src/pages/api/admin/websites.ts @@ -1,13 +1,17 @@ import { canViewAllWebsites } from 'lib/auth'; +import { ROLES } from 'lib/constants'; import { useAuth, useCors, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { pageInfo } from 'lib/schema'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getWebsites } from 'queries'; import * as yup from 'yup'; -import { pageInfo } from 'lib/schema'; -export interface WebsitesRequestQuery extends SearchFilter {} +export interface WebsitesRequestQuery extends PageParams { + userId?: string; + includeTeams?: boolean; +} export interface WebsitesRequestBody { name: string; @@ -39,8 +43,29 @@ export default async ( return unauthorized(res); } + const { userId, includeOwnedTeams } = req.query; + const websites = await getWebsites( { + where: { + OR: [ + ...(userId && [{ userId }]), + ...(userId && + includeOwnedTeams && [ + { + team: { + deletedAt: null, + teamUser: { + some: { + role: ROLES.teamOwner, + userId, + }, + }, + }, + }, + ]), + ], + }, include: { user: { select: { @@ -48,6 +73,18 @@ export default async ( id: true, }, }, + team: { + where: { + deletedAt: null, + }, + include: { + teamUser: { + where: { + role: ROLES.teamOwner, + }, + }, + }, + }, }, }, req.query, diff --git a/src/pages/api/teams/[teamId]/users/index.ts b/src/pages/api/teams/[teamId]/users/index.ts index 3a03feaf..ccbf423a 100644 --- a/src/pages/api/teams/[teamId]/users/index.ts +++ b/src/pages/api/teams/[teamId]/users/index.ts @@ -1,13 +1,13 @@ import { canAddUserToTeam, canViewTeam } from 'lib/auth'; import { useAuth, useValidate } from 'lib/middleware'; import { pageInfo } from 'lib/schema'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { NextApiResponse } from 'next'; import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createTeamUser, getTeamUser, getTeamUsers } from 'queries'; import * as yup from 'yup'; -export interface TeamUserRequestQuery extends SearchFilter { +export interface TeamUserRequestQuery extends PageParams { teamId: string; } diff --git a/src/pages/api/teams/[teamId]/websites/index.ts b/src/pages/api/teams/[teamId]/websites/index.ts index fe244857..75020fa4 100644 --- a/src/pages/api/teams/[teamId]/websites/index.ts +++ b/src/pages/api/teams/[teamId]/websites/index.ts @@ -1,13 +1,13 @@ import * as yup from 'yup'; import { canViewTeam } from 'lib/auth'; import { useAuth, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { pageInfo } from 'lib/schema'; import { NextApiResponse } from 'next'; import { ok, unauthorized } from 'next-basics'; import { getTeamWebsites } from 'queries'; -export interface TeamWebsiteRequestQuery extends SearchFilter { +export interface TeamWebsiteRequestQuery extends PageParams { teamId: string; } diff --git a/src/pages/api/teams/index.ts b/src/pages/api/teams/index.ts index 08bf8f84..1e683469 100644 --- a/src/pages/api/teams/index.ts +++ b/src/pages/api/teams/index.ts @@ -3,13 +3,13 @@ import { Team } from '@prisma/client'; import { canCreateTeam } from 'lib/auth'; import { uuid } from 'lib/crypto'; import { useAuth, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { pageInfo } from 'lib/schema'; import { NextApiResponse } from 'next'; import { getRandomChars, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createTeam } from 'queries'; -export interface TeamsRequestQuery extends SearchFilter {} +export interface TeamsRequestQuery extends PageParams {} export interface TeamsRequestBody { name: string; } diff --git a/src/pages/api/users/[userId]/teams.ts b/src/pages/api/users/[userId]/teams.ts index ad4af648..3f2af9e2 100644 --- a/src/pages/api/users/[userId]/teams.ts +++ b/src/pages/api/users/[userId]/teams.ts @@ -1,12 +1,12 @@ import * as yup from 'yup'; import { useAuth, useCors, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { pageInfo } from 'lib/schema'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getUserTeams } from 'queries'; -export interface UserTeamsRequestQuery extends SearchFilter { +export interface UserTeamsRequestQuery extends PageParams { userId: string; } diff --git a/src/pages/api/users/index.ts b/src/pages/api/users/index.ts index 7f8c9174..333670a9 100644 --- a/src/pages/api/users/index.ts +++ b/src/pages/api/users/index.ts @@ -2,14 +2,14 @@ import { canCreateUser } from 'lib/auth'; import { ROLES } from 'lib/constants'; import { uuid } from 'lib/crypto'; import { useAuth, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, Role, SearchFilter, User } from 'lib/types'; +import { NextApiRequestQueryBody, Role, PageParams, User } from 'lib/types'; import { pageInfo } from 'lib/schema'; import { NextApiResponse } from 'next'; import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createUser, getUserByUsername } from 'queries'; import * as yup from 'yup'; -export interface UsersRequestQuery extends SearchFilter {} +export interface UsersRequestQuery extends PageParams {} export interface UsersRequestBody { username: string; password: string; diff --git a/src/pages/api/websites/[websiteId]/reports.ts b/src/pages/api/websites/[websiteId]/reports.ts index 5bb1652b..72e5b0f2 100644 --- a/src/pages/api/websites/[websiteId]/reports.ts +++ b/src/pages/api/websites/[websiteId]/reports.ts @@ -1,13 +1,13 @@ import * as yup from 'yup'; import { canViewWebsite } from 'lib/auth'; import { useAuth, useCors, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getWebsiteReports } from 'queries'; import { pageInfo } from 'lib/schema'; -export interface ReportsRequestQuery extends SearchFilter { +export interface ReportsRequestQuery extends PageParams { websiteId: string; } diff --git a/src/pages/api/websites/index.ts b/src/pages/api/websites/index.ts index 0b7826ac..c5eb7200 100644 --- a/src/pages/api/websites/index.ts +++ b/src/pages/api/websites/index.ts @@ -1,7 +1,7 @@ import { canCreateTeamWebsite, canCreateWebsite } from 'lib/auth'; import { uuid } from 'lib/crypto'; import { useAuth, useCors, useValidate } from 'lib/middleware'; -import { NextApiRequestQueryBody, SearchFilter } from 'lib/types'; +import { NextApiRequestQueryBody, PageParams } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createWebsite } from 'queries'; @@ -9,7 +9,7 @@ import userWebsitesRoute from 'pages/api/users/[userId]/websites'; import * as yup from 'yup'; import { pageInfo } from 'lib/schema'; -export interface WebsitesRequestQuery extends SearchFilter {} +export interface WebsitesRequestQuery extends PageParams {} export interface WebsitesRequestBody { name: string; diff --git a/src/queries/admin/report.ts b/src/queries/admin/report.ts index d6b28cc4..dc05a1d5 100644 --- a/src/queries/admin/report.ts +++ b/src/queries/admin/report.ts @@ -1,6 +1,6 @@ import { Prisma, Report } from '@prisma/client'; import prisma from 'lib/prisma'; -import { FilterResult, ReportSearchFilter } from 'lib/types'; +import { PageResult, PageParams } from 'lib/types'; import ReportFindManyArgs = Prisma.ReportFindManyArgs; async function findReport(criteria: Prisma.ReportFindUniqueArgs): Promise { @@ -17,8 +17,8 @@ export async function getReport(reportId: string): Promise { export async function getReports( criteria: ReportFindManyArgs, - filters: ReportSearchFilter = {}, -): Promise> { + filters: PageParams = {}, +): Promise> { const { query } = filters; const where: Prisma.ReportWhereInput = { @@ -50,8 +50,8 @@ export async function getReports( export async function getUserReports( userId: string, - filters?: ReportSearchFilter, -): Promise> { + filters?: PageParams, +): Promise> { return getReports( { where: { @@ -72,8 +72,8 @@ export async function getUserReports( export async function getWebsiteReports( websiteId: string, - filters: ReportSearchFilter = {}, -): Promise> { + filters: PageParams = {}, +): Promise> { return getReports( { where: { diff --git a/src/queries/admin/team.ts b/src/queries/admin/team.ts index 74b877de..e516c446 100644 --- a/src/queries/admin/team.ts +++ b/src/queries/admin/team.ts @@ -2,7 +2,7 @@ import { Prisma, Team } from '@prisma/client'; import { ROLES } from 'lib/constants'; import { uuid } from 'lib/crypto'; import prisma from 'lib/prisma'; -import { FilterResult, TeamSearchFilter } from 'lib/types'; +import { PageResult, PageParams } from 'lib/types'; import TeamFindManyArgs = Prisma.TeamFindManyArgs; export async function findTeam(criteria: Prisma.TeamFindUniqueArgs): Promise { @@ -22,8 +22,8 @@ export async function getTeam(teamId: string, options: { includeMembers?: boolea export async function getTeams( criteria: TeamFindManyArgs, - filters: TeamSearchFilter = {}, -): Promise> { + filters: PageParams = {}, +): Promise> { const { getSearchParameters } = prisma; const { query } = filters; @@ -42,7 +42,7 @@ export async function getTeams( ); } -export async function getUserTeams(userId: string, filters: TeamSearchFilter = {}) { +export async function getUserTeams(userId: string, filters: PageParams = {}) { return getTeams( { where: { diff --git a/src/queries/admin/teamUser.ts b/src/queries/admin/teamUser.ts index 43785b78..d172dd5a 100644 --- a/src/queries/admin/teamUser.ts +++ b/src/queries/admin/teamUser.ts @@ -1,7 +1,7 @@ import { Prisma, TeamUser } from '@prisma/client'; import { uuid } from 'lib/crypto'; import prisma from 'lib/prisma'; -import { FilterResult, TeamUserSearchFilter } from 'lib/types'; +import { PageResult, PageParams } from 'lib/types'; import TeamUserFindManyArgs = Prisma.TeamUserFindManyArgs; export async function findTeamUser(criteria: Prisma.TeamUserFindUniqueArgs): Promise { @@ -19,8 +19,8 @@ export async function getTeamUser(teamId: string, userId: string): Promise> { + filters?: PageParams, +): Promise> { const { query } = filters; const where: Prisma.TeamUserWhereInput = { diff --git a/src/queries/admin/user.ts b/src/queries/admin/user.ts index 819f492d..9e085112 100644 --- a/src/queries/admin/user.ts +++ b/src/queries/admin/user.ts @@ -1,7 +1,7 @@ import { Prisma } from '@prisma/client'; import { ROLES } from 'lib/constants'; import prisma from 'lib/prisma'; -import { FilterResult, Role, User, UserSearchFilter } from 'lib/types'; +import { PageResult, Role, User, PageParams } from 'lib/types'; import { getRandomChars } from 'next-basics'; import UserFindManyArgs = Prisma.UserFindManyArgs; @@ -49,8 +49,8 @@ export async function getUserByUsername(username: string, options: GetUserOption export async function getUsers( criteria: UserFindManyArgs, - filters?: UserSearchFilter, -): Promise> { + filters?: PageParams, +): Promise> { const { query } = filters; const where: Prisma.UserWhereInput = { diff --git a/src/queries/admin/website.ts b/src/queries/admin/website.ts index 949efb71..1f513bd4 100644 --- a/src/queries/admin/website.ts +++ b/src/queries/admin/website.ts @@ -1,6 +1,6 @@ import { Prisma, Website } from '@prisma/client'; import prisma from 'lib/prisma'; -import { FilterResult, WebsiteSearchFilter } from 'lib/types'; +import { PageResult, PageParams } from 'lib/types'; import WebsiteFindManyArgs = Prisma.WebsiteFindManyArgs; async function findWebsite(criteria: Prisma.WebsiteFindUniqueArgs): Promise { @@ -25,8 +25,8 @@ export async function getSharedWebsite(shareId: string) { export async function getWebsites( criteria: WebsiteFindManyArgs, - filters: WebsiteSearchFilter, -): Promise> { + filters: PageParams, +): Promise> { const { query } = filters; const where: Prisma.WebsiteWhereInput = { @@ -53,8 +53,8 @@ export async function getAllWebsites(userId: string) { export async function getUserWebsites( userId: string, - filters?: WebsiteSearchFilter, -): Promise> { + filters?: PageParams, +): Promise> { return getWebsites( { where: { @@ -78,8 +78,8 @@ export async function getUserWebsites( export async function getTeamWebsites( teamId: string, - filters?: WebsiteSearchFilter, -): Promise> { + filters?: PageParams, +): Promise> { return getWebsites( { where: {