diff --git a/pkg/probo/coredata/control.go b/pkg/probo/coredata/control.go index d2c3f3e4b..aff119927 100644 --- a/pkg/probo/coredata/control.go +++ b/pkg/probo/coredata/control.go @@ -20,15 +20,17 @@ import ( "maps" "time" + "github.com/getprobo/probo/pkg/probo/coredata/gid" "github.com/getprobo/probo/pkg/probo/coredata/page" "github.com/jackc/pgx/v5" + "go.gearno.de/crypto/uuid" "go.gearno.de/kit/pg" ) type ( Control struct { - ID uuid.UUID + ID gid.GID FrameworkID string Name string Description string @@ -41,7 +43,7 @@ type ( ) func (c Control) CursorKey() page.CursorKey { - return page.NewCursorKey(c.ID, c.CreatedAt) + return page.NewCursorKey(uuid.UUID(c.ID), c.CreatedAt) } func (c *Control) scan(r pgx.Row) error { diff --git a/pkg/probo/coredata/entity_type_reg.go b/pkg/probo/coredata/entity_type_reg.go new file mode 100644 index 000000000..0b23a4c54 --- /dev/null +++ b/pkg/probo/coredata/entity_type_reg.go @@ -0,0 +1,23 @@ +// 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 + +const ( + OrganizationEntityType uint32 = iota + FrameworkEntityType + ControlEntityType + TaskEntityType + EvidenceEntityType +) diff --git a/pkg/probo/coredata/evidence.go b/pkg/probo/coredata/evidence.go index 524e2c0de..9f18a797e 100644 --- a/pkg/probo/coredata/evidence.go +++ b/pkg/probo/coredata/evidence.go @@ -14,11 +14,15 @@ package coredata -import "time" +import ( + "time" + + "github.com/getprobo/probo/pkg/probo/coredata/gid" +) type ( Evidence struct { - ID string + ID gid.GID TaskID string ContentID string CreatedAt time.Time diff --git a/pkg/probo/coredata/framework.go b/pkg/probo/coredata/framework.go index 418292c5c..12ed6a1f6 100644 --- a/pkg/probo/coredata/framework.go +++ b/pkg/probo/coredata/framework.go @@ -20,15 +20,16 @@ import ( "maps" "time" + "github.com/getprobo/probo/pkg/probo/coredata/gid" "github.com/getprobo/probo/pkg/probo/coredata/page" "github.com/jackc/pgx/v5" - "go.gearno.de/crypto/uuid" "go.gearno.de/kit/pg" + "go.gearno.de/crypto/uuid" ) type ( Framework struct { - ID uuid.UUID + ID gid.GID OrganizationID string Name string Description string @@ -41,7 +42,7 @@ type ( ) func (f Framework) CursorKey() page.CursorKey { - return page.NewCursorKey(f.ID, f.CreatedAt) + return page.NewCursorKey(uuid.UUID(f.ID), f.CreatedAt) } func (f *Framework) scan(r pgx.Row) error { diff --git a/pkg/probo/coredata/gid/gid.go b/pkg/probo/coredata/gid/gid.go new file mode 100644 index 000000000..b6b49283c --- /dev/null +++ b/pkg/probo/coredata/gid/gid.go @@ -0,0 +1,91 @@ +// 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 gid + +import ( + "database/sql/driver" + "encoding/base64" + "encoding/binary" + "fmt" + + "go.gearno.de/crypto/uuid" +) + +type ( + GID uuid.UUID +) + +func NewGID(et uint32) (GID, error) { + id, err := uuid.NewV7() + if err != nil { + return GID(uuid.Nil), err + } + + binary.BigEndian.PutUint32(id[10:14], et) + + return GID(id), nil +} + +func (gid GID) Value() (driver.Value, error) { + return gid[:], nil +} + +func (gid GID) EntityType() uint32 { + return binary.BigEndian.Uint32(gid[10:14]) +} + +func (gid *GID) Scan(value interface{}) error { + switch v := value.(type) { + case string: + id, err := uuid.Parse(v) + if err != nil { + return err + } + *gid = GID(id) + case []byte: + id, err := uuid.ParseBytes(v) + if err != nil { + return err + } + *gid = GID(id) + default: + return fmt.Errorf("invalid type for GID: expected string or []byte, got %T", value) + } + return nil +} + +func (gid GID) String() string { + return base64.RawURLEncoding.EncodeToString(gid[:]) +} + +func (gid GID) MarshalText() ([]byte, error) { + enc := base64.RawURLEncoding + + buf := make([]byte, enc.EncodedLen(len(gid))) + enc.Encode(buf, gid[:]) + + return buf, nil +} + +func (gid *GID) UnmarshalText(encoded []byte) error { + enc := base64.RawURLEncoding + + _, err := enc.Decode(gid[:], encoded) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/probo/coredata/organization.go b/pkg/probo/coredata/organization.go index 2dec54974..76422735e 100644 --- a/pkg/probo/coredata/organization.go +++ b/pkg/probo/coredata/organization.go @@ -20,13 +20,14 @@ import ( "maps" "time" + "github.com/getprobo/probo/pkg/probo/coredata/gid" "github.com/jackc/pgx/v5" "go.gearno.de/kit/pg" ) type ( Organization struct { - ID string + ID gid.GID Name string CreatedAt time.Time UpdatedAt time.Time diff --git a/pkg/probo/coredata/task.go b/pkg/probo/coredata/task.go index 4f9f95df2..cd79bd36d 100644 --- a/pkg/probo/coredata/task.go +++ b/pkg/probo/coredata/task.go @@ -20,15 +20,17 @@ import ( "maps" "time" + "github.com/getprobo/probo/pkg/probo/coredata/gid" "github.com/getprobo/probo/pkg/probo/coredata/page" "github.com/jackc/pgx/v5" + "go.gearno.de/crypto/uuid" "go.gearno.de/kit/pg" ) type ( Task struct { - ID uuid.UUID + ID gid.GID ControlID string ContentRef string CreatedAt time.Time @@ -39,7 +41,7 @@ type ( ) func (t Task) CursorKey() page.CursorKey { - return page.NewCursorKey(t.ID, t.CreatedAt) + return page.NewCursorKey(uuid.UUID(t.ID), t.CreatedAt) } func (t *Task) scan(r pgx.Row) error {