From b4acae1862bffdf7bd4a1dc25e744e340c790327 Mon Sep 17 00:00:00 2001 From: gearnode Date: Thu, 23 Jan 2025 10:06:54 +0100 Subject: [PATCH] Introduce multi tenant system Signed-off-by: gearnode --- pkg/probo/coredata/control.go | 7 ++++-- pkg/probo/coredata/framework.go | 15 ++++++++++--- pkg/probo/coredata/organization.go | 10 ++++++++- pkg/probo/coredata/scope.go | 35 ++++++++++++++++++++++++++++++ pkg/probo/coredata/task.go | 7 ++++-- pkg/probo/probo.go | 10 +++++---- 6 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 pkg/probo/coredata/scope.go diff --git a/pkg/probo/coredata/control.go b/pkg/probo/coredata/control.go index 0281e2a60..d2c3f3e4b 100644 --- a/pkg/probo/coredata/control.go +++ b/pkg/probo/coredata/control.go @@ -59,6 +59,7 @@ func (c *Control) scan(r pgx.Row) error { func (c *Controls) LoadByFrameworkID( ctx context.Context, conn pg.Conn, + scope *Scope, frameworkID string, cursor *page.Cursor, ) error { @@ -74,12 +75,14 @@ SELECT FROM controls WHERE - framework_id = @framework_id + %s + AND framework_id = @framework_id AND %s ` - q = fmt.Sprintf(q, cursor.SQLFragment()) + q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) args := pgx.NamedArgs{"framework_id": frameworkID} + maps.Copy(args, scope.SQLArguments()) maps.Copy(args, cursor.SQLArguments()) r, err := conn.Query(ctx, q, args) diff --git a/pkg/probo/coredata/framework.go b/pkg/probo/coredata/framework.go index ca74099fa..bbe00b423 100644 --- a/pkg/probo/coredata/framework.go +++ b/pkg/probo/coredata/framework.go @@ -58,6 +58,7 @@ func (f *Framework) scan(r pgx.Row) error { func (f *Frameworks) LoadByOrganizationID( ctx context.Context, conn pg.Conn, + scope *Scope, organizationID string, cursor *page.Cursor, ) error { @@ -73,14 +74,16 @@ SELECT FROM frameworks WHERE - organization_id = @organization_id + %s + AND organization_id = @organization_id AND %s ` - q = fmt.Sprintf(q, cursor.SQLFragment()) + q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) args := pgx.NamedArgs{"organization_id": organizationID} maps.Copy(args, cursor.SQLArguments()) + maps.Copy(args, cursor.SQLArguments()) r, err := conn.Query(ctx, q, args) if err != nil { @@ -110,6 +113,7 @@ WHERE func (f *Framework) LoadByID( ctx context.Context, conn pg.Conn, + scope *Scope, frameworkID string, ) error { q := ` @@ -124,10 +128,15 @@ SELECT FROM frameworks WHERE - framework_id = @framework_id + %s + AND framework_id = @framework_id LIMIT 1; ` + + q = fmt.Sprintf(q, scope.SQLFragment()) + args := pgx.NamedArgs{"framework_id": frameworkID} + maps.Copy(args, scope.SQLArguments()) r := conn.QueryRow(ctx, q, args) f2 := Framework{} diff --git a/pkg/probo/coredata/organization.go b/pkg/probo/coredata/organization.go index f74cefede..79e2c11f6 100644 --- a/pkg/probo/coredata/organization.go +++ b/pkg/probo/coredata/organization.go @@ -17,6 +17,8 @@ package coredata import ( "context" "time" + "maps" + "fmt" "github.com/jackc/pgx/v5" "go.gearno.de/kit/pg" @@ -43,6 +45,7 @@ func (o *Organization) scan(r pgx.Row) error { func (o *Organization) LoadByID( ctx context.Context, conn pg.Conn, + scope *Scope, organizationID string, ) error { q := ` @@ -54,11 +57,16 @@ SELECT FROM organizations WHERE - organization_id = @organization_id + %s + AND organization_id = @organization_id LIMIT 1; ` + q = fmt.Sprintf(q, scope.SQLFragment()) + args := pgx.NamedArgs{"organization_id": organizationID} + maps.Copy(args, scope.SQLArguments()) + r := conn.QueryRow(ctx, q, args) o2 := Organization{} diff --git a/pkg/probo/coredata/scope.go b/pkg/probo/coredata/scope.go new file mode 100644 index 000000000..755757a95 --- /dev/null +++ b/pkg/probo/coredata/scope.go @@ -0,0 +1,35 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package coredata + +import ( + "github.com/jackc/pgx/v5" +) + +type ( + Scope struct {} +) + +func NewScope() *Scope { + return &Scope{} +} + +func (*Scope) SQLArguments() pgx.NamedArgs { + return pgx.NamedArgs{} +} + +func (*Scope) SQLFragment() string { + return "TRUE" +} diff --git a/pkg/probo/coredata/task.go b/pkg/probo/coredata/task.go index 7926eb011..4f9f95df2 100644 --- a/pkg/probo/coredata/task.go +++ b/pkg/probo/coredata/task.go @@ -55,6 +55,7 @@ func (t *Task) scan(r pgx.Row) error { func (t *Tasks) LoadByControlID( ctx context.Context, conn pg.Conn, + scope *Scope, controlID string, cursor *page.Cursor, ) error { @@ -68,13 +69,15 @@ SELECT FROM tasks WHERE - control_id = @control_id + %s + AND control_id = @control_id AND %s ` - q = fmt.Sprintf(q, cursor.SQLFragment()) + q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) args := pgx.NamedArgs{"control_id": controlID} + maps.Copy(args, scope.SQLArguments()) maps.Copy(args, cursor.SQLArguments()) r, err := conn.Query(ctx, q, args) diff --git a/pkg/probo/probo.go b/pkg/probo/probo.go index 1f6003530..9878717ad 100644 --- a/pkg/probo/probo.go +++ b/pkg/probo/probo.go @@ -25,12 +25,14 @@ import ( type ( Service struct { pg *pg.Client + scope *coredata.Scope } ) func NewService(ctx context.Context, pgClient *pg.Client) *Service { return &Service{ pg: pgClient, + scope: coredata.NewScope(), // must be created from auth } } @@ -43,7 +45,7 @@ func (s *Service) GetOrganization( err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - return organization.LoadByID(ctx, conn, organizationID) + return organization.LoadByID(ctx, conn, s.scope, organizationID) }, ) @@ -64,7 +66,7 @@ func (s *Service) ListOrganizationFrameworks( err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - return frameworks.LoadByOrganizationID(ctx, conn, organizationID, cursor) + return frameworks.LoadByOrganizationID(ctx, conn, s.scope, organizationID, cursor) }, ) @@ -85,7 +87,7 @@ func (s *Service) ListFrameworkControls( err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - return controls.LoadByFrameworkID(ctx, conn, frameworkID, cursor) + return controls.LoadByFrameworkID(ctx, conn, s.scope, frameworkID, cursor) }, ) @@ -106,7 +108,7 @@ func (s *Service) ListControlTasks( err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - return tasks.LoadByControlID(ctx, conn, controlID, cursor) + return tasks.LoadByControlID(ctx, conn, s.scope, controlID, cursor) }, )