From 9f9eb947094a2221af7640b61e9eb4171db3f5e1 Mon Sep 17 00:00:00 2001 From: Geoffroy Empain <geoffroy@charlie-bravo.be> Date: Mon, 28 Dec 2020 12:50:48 +0100 Subject: [PATCH] fix: search is broken --- src/entities/api/api-scope.ts | 43 +++++----- .../orgs/handlers/sites/list-sites.ts | 86 +++++++++++++++++++ src/entities/orgs/routes.ts | 12 +++ .../{list-sites.ts => list-team-sites.ts} | 2 +- src/entities/teams/routes.ts | 4 +- src/utils/getPagination.ts | 5 +- 6 files changed, 126 insertions(+), 26 deletions(-) create mode 100644 src/entities/orgs/handlers/sites/list-sites.ts rename src/entities/teams/handlers/sites/{list-sites.ts => list-team-sites.ts} (98%) diff --git a/src/entities/api/api-scope.ts b/src/entities/api/api-scope.ts index 53a35c5..1d76c2f 100644 --- a/src/entities/api/api-scope.ts +++ b/src/entities/api/api-scope.ts @@ -1,20 +1,20 @@ export enum ApiScope { user_read = 'user.read', user_disconnect = 'user.disconnect', - user_hook_list = 'user_hook_list', - user_hook_create = 'user_hook_create', - user_hook_read = 'user_hook_read', - user_hook_update = 'user_hook_update', - user_hook_delete = 'user_hook_delete', + user_hook_list = 'user.hook.list', + user_hook_create = 'user.hook.create', + user_hook_read = 'user.hook.read', + user_hook_update = 'user.hook.update', + user_hook_delete = 'user.hook.delete', org_create = 'org.create', org_read = 'org.read', org_list = 'org.list', org_update = 'org.update', - org_hook_list = 'org_hook_list', - org_hook_create = 'org_hook_create', - org_hook_read = 'org_hook_read', - org_hook_update = 'org_hook_update', - org_hook_delete = 'org_hook_delete', + org_hook_list = 'org.hook.list', + org_hook_create = 'org.hook.create', + org_hook_read = 'org.hook.read', + org_hook_update = 'org.hook.update', + org_hook_delete = 'org.hook.delete', member_get_current = 'member.get.current', members_list = 'members.list', member_delete = 'member.delete', @@ -35,14 +35,15 @@ export enum ApiScope { team_member_delete = 'team.member.delete', team_sites_list = 'team.sites.list', team_sites_add = 'team.sites.add', - team_hook_list = 'team_hook_list', - team_hook_create = 'team_hook_create', - team_hook_read = 'team_hook_read', - team_hook_update = 'team_hook_update', - team_hook_delete = 'team_hook_delete', - site_delete = 'site.delete', + team_hook_list = 'team.hook.list', + team_hook_create = 'team.hook.create', + team_hook_read = 'team.hook.read', + team_hook_update = 'team.hook.update', + team_hook_delete = 'team.hook.delete', + sites_list = 'sites.list', site_read = 'site.read', site_update = 'site.update', + site_delete = 'site.delete', site_password_set = 'site.password.set', site_password_remove = 'site.password.remove', site_name_validate = 'site.name.validate', @@ -57,11 +58,11 @@ export enum ApiScope { site_branch_password_remove = 'site.branch.password.remove', site_branch_redirects_read = 'site.branch.redirects.read', site_branch_redirects_set = 'site.branch.redirects.set', - site_hook_list = 'site_hook_list', - site_hook_create = 'site_hook_create', - site_hook_read = 'site_hook_read', - site_hook_update = 'site_hook_update', - site_hook_delete = 'site_hook_delete', + site_hook_list = 'site.hook.list', + site_hook_create = 'site.hook.create', + site_hook_read = 'site.hook.read', + site_hook_update = 'site.hook.update', + site_hook_delete = 'site.hook.delete', site_releases_list = 'site.releases.list', release_upload = 'release.upload', release_read = 'release.read', diff --git a/src/entities/orgs/handlers/sites/list-sites.ts b/src/entities/orgs/handlers/sites/list-sites.ts new file mode 100644 index 0000000..0821c29 --- /dev/null +++ b/src/entities/orgs/handlers/sites/list-sites.ts @@ -0,0 +1,86 @@ +import { Request, Response } from 'express'; +import { Site, Sites } from '../../../sites/site'; +import { object, string } from 'joi'; +import { wrapAsyncMiddleware } from '../../../../commons/utils/wrap-async-middleware'; +import { getPagination, pageResponse, pageValidators } from '../../../../utils/getPagination'; +import { FilterQuery } from 'mongodb'; +import { query } from '../../../../commons/express-joi/query'; +import { Teams } from '../../../teams/team'; +import { getUser } from '../../../../auth/utils/get-user'; +import { params } from '../../../../commons/express-joi/params'; +import { $id } from '../../../../utils/id'; +import { Members } from '../../../members/member'; +import { isOrgMemberGuard } from '../../guards/is-org-member-guard'; +import { orgExistsGuard } from '../../guards/org-exists-guard'; +import { isAdminOrOwner } from '../../../../auth/guards/is-admin-or-owner'; + +const validators = [ + ...pageValidators, + params(object({ + orgId: $id, + })), + query({ + search: { + $schema: string().optional().empty('').min(3) + .max(255), + }, + }), +]; + +async function handler(req: Request, res: Response): Promise<void> { + const { orgId } = req.params; + const { search } = req.query; + const pagination = getPagination(req); + + // find user teams in this org + const user = getUser(req); + const adminOrOwner = await isAdminOrOwner(user._id, orgId); + const member = await Members().findOne({ + orgId, + userId: user._id, + }); + + const teams = await Teams() + .find(adminOrOwner ? {} : { + members: member._id, + }) + .project({ _id: 1 }) + .toArray(); + + const dbQuery: FilterQuery<Site> = { + teamId: { + $in: teams.map(({ _id }) => _id), + }, + ...( + search + ? { + $text: { + $search: search, + }, + } + : undefined as any + ), + }; + + const count = await Sites() + .find(dbQuery) + .count(); + + const sites = await Sites() + .find(dbQuery) + .sort({ + updatedAt: -1, + }) + .skip(pagination.offset) + .limit(pagination.size) + .toArray(); + + res.json(pageResponse(sites, count)); +} + +export const listSites = [ + ...orgExistsGuard, + ...isOrgMemberGuard, + ...validators, + wrapAsyncMiddleware(handler), +]; diff --git a/src/entities/orgs/routes.ts b/src/entities/orgs/routes.ts index ad4b63b..4012c6e 100644 --- a/src/entities/orgs/routes.ts +++ b/src/entities/orgs/routes.ts @@ -12,6 +12,7 @@ import { deleteInvite } from './handlers/invites/delete-invite'; import { createOrg } from './handlers/create-org'; import { apiEndpoint } from '../api/api-endpoint'; import { ApiScope } from '../api/api-scope'; +import { listSites } from './handlers/sites/list-sites'; const router = Router(); @@ -123,4 +124,15 @@ apiEndpoint({ router, }); +// sites +apiEndpoint({ + name: 'list sites', + method: 'get', + path: '/api/v1/orgs/:orgId/sites', + handler: listSites, + auth: true, + apiScope: ApiScope.sites_list, + router, +}); + export default router; diff --git a/src/entities/teams/handlers/sites/list-sites.ts b/src/entities/teams/handlers/sites/list-team-sites.ts similarity index 98% rename from src/entities/teams/handlers/sites/list-sites.ts rename to src/entities/teams/handlers/sites/list-team-sites.ts index 4441ebf..dbef7db 100644 --- a/src/entities/teams/handlers/sites/list-sites.ts +++ b/src/entities/teams/handlers/sites/list-team-sites.ts @@ -57,7 +57,7 @@ async function handler(req: Request, res: Response): Promise<void> { res.json(pageResponse(sites, count)); } -export const listSites = [ +export const listTeamSites = [ ...teamExistsGuard, ...canReadTeamGuard, ...validators, diff --git a/src/entities/teams/routes.ts b/src/entities/teams/routes.ts index dac1964..e58aed8 100644 --- a/src/entities/teams/routes.ts +++ b/src/entities/teams/routes.ts @@ -4,7 +4,7 @@ import { deleteTeam } from './handlers/delete-team'; import { getTeam } from './handlers/get-team'; import { addMember } from './handlers/members/add-member'; import { deleteMember } from './handlers/members/delete-member'; -import { listSites } from './handlers/sites/list-sites'; +import { listTeamSites } from './handlers/sites/list-team-sites'; import { listMembers } from './handlers/members/list-members'; import { addSite } from './handlers/sites/add-site'; import { apiEndpoint } from '../api/api-endpoint'; @@ -46,7 +46,7 @@ apiEndpoint({ name: 'list sites', method: 'get', path: '/api/v1/teams/:teamId/sites', - handler: listSites, + handler: listTeamSites, auth: true, apiScope: ApiScope.team_sites_list, router, diff --git a/src/utils/getPagination.ts b/src/utils/getPagination.ts index 5160d7b..49beb16 100644 --- a/src/utils/getPagination.ts +++ b/src/utils/getPagination.ts @@ -7,11 +7,12 @@ export const pageValidators = [ query({ size: { transform: stringToInt(), - $schema: number().default(10).min(0).max(100), + $schema: number().optional().default(10).min(0) + .max(100), }, page: { transform: stringToInt(), - $schema: number().default(0).min(0), + $schema: number().optional().default(0).min(0), }, }), ];