Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions pkg/protect/protect.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ package protect
*/
import "C"
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"strings"
"unsafe"
)

Expand Down Expand Up @@ -191,6 +194,61 @@ type Encrypted struct {
SteVecIndex interface{} `json:"sv,omitempty"`
}

// Value implements driver.Valuer for Encrypted.
// It formats the encrypted data for PostgreSQL eql_v2_encrypted composite type.
func (e *Encrypted) Value() (driver.Value, error) {
if e == nil {
return nil, nil
}

m := map[string]Encrypted{
"data": *e,
}

jsonBytes, err := json.Marshal(m)
if err != nil {
return nil, fmt.Errorf("failed to marshal encrypted value: %w", err)
}

return string(jsonBytes), nil
}

// Scan implements sql.Scanner for Encrypted.
// It deserializes JSON data from PostgreSQL eql_v2_encrypted columns.
func (e *Encrypted) Scan(value interface{}) error {
var jsonStr string
switch v := value.(type) {
case string:
jsonStr = v
case []byte:
jsonStr = string(v)
default:
return fmt.Errorf("cannot scan %T into Encrypted", value)
}

if jsonStr == "" {
return nil
}

if jsonStr[0] == '(' {
jsonStr = strings.Replace(jsonStr[2:len(jsonStr)-2], "\"\"", "\"", -1)
}

m := map[string]Encrypted{}

err := json.Unmarshal([]byte(jsonStr), &m)
if err != nil {
return fmt.Errorf("failed to unmarshal encrypted value: %w", err)
}

data, ok := m["data"]
if ok {
e = &data
}

return nil
}

// DecryptResult represents the result of a fallible decryption operation
type DecryptResult struct {
Data *string `json:"data,omitempty"`
Expand Down