Skip to content

Commit d988a10

Browse files
committed
Improve pg security perfomance
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
1 parent fe4982c commit d988a10

File tree

4 files changed

+35
-17
lines changed

4 files changed

+35
-17
lines changed

packages/postgres/CHANGELOG.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
{
22
"name": "@hcengineering/postgres",
33
"entries": [
4+
{
5+
"version": "0.7.17",
6+
"tag": "@hcengineering/postgres_v0.7.17",
7+
"date": "Thu, 30 Oct 2025 20:24:36 GMT",
8+
"comments": {
9+
"patch": [
10+
{
11+
"comment": "Improve security pg perfomance"
12+
}
13+
]
14+
}
15+
},
416
{
517
"version": "0.7.16",
618
"tag": "@hcengineering/postgres_v0.7.16",

packages/postgres/CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Change Log - @hcengineering/postgres
22

3-
This log was last generated on Wed, 29 Oct 2025 18:01:56 GMT and should not be manually modified.
3+
This log was last generated on Thu, 30 Oct 2025 20:24:36 GMT and should not be manually modified.
4+
5+
## 0.7.17
6+
Thu, 30 Oct 2025 20:24:36 GMT
7+
8+
### Patches
9+
10+
- Improve security pg perfomance
411

512
## 0.7.16
613
Wed, 29 Oct 2025 18:01:56 GMT

packages/postgres/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hcengineering/postgres",
3-
"version": "0.7.16",
3+
"version": "0.7.17",
44
"main": "lib/index.js",
55
"svelte": "src/index.ts",
66
"types": "types/index.d.ts",

packages/postgres/src/storage.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -470,16 +470,16 @@ abstract class PostgresAdapterBase implements DbAdapter {
470470

471471
const select = `SELECT ${this.getProjection(vars, domain, projection, joins, options?.associations)} FROM ${domain}`
472472

473-
const showArchived = shouldShowArchived(query, options)
474-
const secJoin = this.addSecurity(_class, vars, query, showArchived, domain, ctx.contextData)
475-
if (secJoin !== undefined) {
476-
sqlChunks.push(secJoin)
477-
}
478473
if (joins.length > 0) {
479474
sqlChunks.push(this.buildJoinString(vars, joins))
480475
}
481476
sqlChunks.push(`WHERE ${this.buildQuery(vars, _class, domain, query, joins, options)}`)
482477

478+
const showArchived = shouldShowArchived(query, options)
479+
const secJoin = this.addSecurity(_class, vars, query, showArchived, domain, ctx.contextData)
480+
if (secJoin !== undefined) {
481+
sqlChunks.push(secJoin)
482+
}
483483
if (options?.sort !== undefined) {
484484
sqlChunks.push(this.buildOrder(_class, domain, options.sort, joins))
485485
}
@@ -491,18 +491,17 @@ abstract class PostgresAdapterBase implements DbAdapter {
491491
let total = options?.total === true ? 0 : -1
492492
if (options?.total === true) {
493493
const pvars = new ValuesVariables()
494-
const showArchived = shouldShowArchived(query, options)
495-
const secJoin = this.addSecurity(_class, pvars, query, showArchived, domain, ctx.contextData)
496494
const totalChunks: string[] = []
497-
if (secJoin !== undefined) {
498-
totalChunks.push(secJoin)
499-
}
500495
const joins = this.buildJoin(_class, options?.lookup)
501496
if (joins.length > 0) {
502497
totalChunks.push(this.buildJoinString(pvars, joins))
503498
}
504499
totalChunks.push(`WHERE ${this.buildQuery(pvars, _class, domain, query, joins, options)}`)
505-
500+
const showArchived = shouldShowArchived(query, options)
501+
const secJoin = this.addSecurity(_class, pvars, query, showArchived, domain, ctx.contextData)
502+
if (secJoin !== undefined) {
503+
totalChunks.push(secJoin)
504+
}
506505
const totalReq = `SELECT COUNT(${domain}._id) as count FROM ${domain}`
507506
const totalSql = [totalReq, ...totalChunks].join(' ')
508507
const totalResult = await connection.execute(totalSql, pvars.getValues())
@@ -632,14 +631,14 @@ abstract class PostgresAdapterBase implements DbAdapter {
632631
const privateCheck = domain === DOMAIN_SPACE ? ' OR sec.private = false' : ''
633632
const archivedCheck = showArchived ? '' : ' AND sec.archived = false'
634633
const q = `(sec._id = '${core.space.Space}' OR sec."_class" = '${core.class.SystemSpace}' OR sec.members @> '{"${acc.uuid}"}'${privateCheck})${archivedCheck}`
635-
const res = `INNER JOIN ${translateDomain(DOMAIN_SPACE)} AS sec ON sec._id = ${domain}.${key} AND sec."workspaceId" = ${vars.add(this.workspaceId, '::uuid')}`
634+
const res = `EXISTS (SELECT 1 FROM ${translateDomain(DOMAIN_SPACE)} sec WHERE sec._id = ${domain}.${key} AND sec."workspaceId" = ${vars.add(this.workspaceId, '::uuid')} AND ${q})`
636635

637636
const collabSec = getClassCollaborators(this.modelDb, this.hierarchy, _class)
638637
if (collabSec?.provideSecurity === true && [AccountRole.Guest, AccountRole.ReadOnlyGuest].includes(acc.role)) {
639-
const collab = ` INNER JOIN ${translateDomain(DOMAIN_COLLABORATOR)} AS collab_sec ON collab_sec.collaborator = '${acc.uuid}' AND collab_sec."attachedTo" = ${domain}._id AND collab_sec."workspaceId" = ${vars.add(this.workspaceId, '::uuid')} OR ${q}`
640-
return res + collab
638+
const collab = `OR EXISTS (SELECT 1 FROM ${translateDomain(DOMAIN_COLLABORATOR)} collab_sec WHERE collab_sec."workspaceId" = ${vars.add(this.workspaceId, '::uuid')} AND collab_sec."attachedTo" = ${domain}._id AND collab_sec.collaborator = '${acc.uuid}')`
639+
return `AND (${res} + ${collab})`
641640
}
642-
return `${res} AND ${q}`
641+
return `AND (${res})`
643642
}
644643
}
645644
}

0 commit comments

Comments
 (0)