@@ -10,6 +10,9 @@ import (
10
10
11
11
"github.com/dyaksa/encryption-pii/crypto/hmacx"
12
12
"github.com/dyaksa/encryption-pii/crypto/types"
13
+ "github.com/dyaksa/encryption-pii/validate/nik"
14
+ "github.com/dyaksa/encryption-pii/validate/npwp"
15
+ "github.com/dyaksa/encryption-pii/validate/phone"
13
16
"github.com/google/uuid"
14
17
)
15
18
@@ -128,6 +131,69 @@ func GenerateSQLConditions(data any) (strs []string) {
128
131
return
129
132
}
130
133
134
+ type ResultHeap struct {
135
+ Column string `json:"column"`
136
+ Value string `json:"value"`
137
+ }
138
+
139
+ func (c * Crypto ) BindHeap (entity any ) (err error ) {
140
+ entityPtrValue := reflect .ValueOf (entity )
141
+ if entityPtrValue .Kind () != reflect .Ptr {
142
+ return fmt .Errorf ("entity harus berupa pointer" )
143
+ }
144
+
145
+ entityValue := entityPtrValue .Elem ()
146
+ entityType := entityValue .Type ()
147
+
148
+ for i := 0 ; i < entityType .NumField (); i ++ {
149
+ field := entityType .Field (i )
150
+ if _ , ok := field .Tag .Lookup ("txt_heap_table" ); ok {
151
+ plainTextFieldName := field .Name [:len (field .Name )- 4 ]
152
+ bidxField := entityValue .FieldByName (field .Name )
153
+ txtHeapTable := field .Tag .Get ("txt_heap_table" )
154
+
155
+ switch originalValue := entityValue .FieldByName (plainTextFieldName ).Interface ().(type ) {
156
+ case types.AESChiper :
157
+ str , heaps := c .buildHeap (originalValue .To (), txtHeapTable )
158
+ err = c .saveToHeap (context .Background (), c .dbHeapPsql , heaps )
159
+ if err != nil {
160
+ return fmt .Errorf ("failed to save to heap: %w" , err )
161
+ }
162
+ bidxField .SetString (str )
163
+ }
164
+ }
165
+ }
166
+ return nil
167
+ }
168
+
169
+ func (c * Crypto ) saveToHeap (ctx context.Context , db * sql.DB , textHeaps []TextHeap ) (err error ) {
170
+ for _ , th := range textHeaps {
171
+ query := new (strings.Builder )
172
+ query .WriteString ("INSERT INTO " )
173
+ query .WriteString (th .Type )
174
+ query .WriteString (" (content, hash) VALUES ($1, $2)" )
175
+ if ok , _ := isHashExist (ctx , db , th .Type , FindTextHeapByHashParams {Hash : th .Hash }); ! ok {
176
+ _ , err = db .ExecContext (ctx , query .String (), th .Content , th .Hash )
177
+ }
178
+ }
179
+ return
180
+ }
181
+
182
+ func (c * Crypto ) buildHeap (value string , typeHeap string ) (s string , th []TextHeap ) {
183
+ var values = split (value )
184
+ builder := new (strings.Builder )
185
+ for _ , value := range values {
186
+ builder .WriteString (hmacx .HMACHash (c .HMACFunc (), value ).Hash ().ToLast8DigitValue ())
187
+ th = append (th , TextHeap {
188
+ Content : strings .ToLower (value ),
189
+ Type : typeHeap ,
190
+ Hash : hmacx .HMACHash (c .HMACFunc (), value ).Hash ().ToLast8DigitValue (),
191
+ })
192
+ }
193
+ return builder .String (), th
194
+ }
195
+
196
+ // Deprecated: any is deprecated. Use interface{} instead.
131
197
func InsertWithHeap [T Entity ](c * Crypto , ctx context.Context , tx * sql.Tx , tableName string , entity any , generic T ) (a T , err error ) {
132
198
entityValue := reflect .ValueOf (entity )
133
199
entityType := entityValue .Type ()
@@ -191,7 +257,7 @@ func InsertWithHeap[T Entity](c *Crypto, ctx context.Context, tx *sql.Tx, tableN
191
257
192
258
switch fieldValue := entityValue .Field (i ).Interface ().(type ) {
193
259
case types.AESChiper :
194
- str , heaps := BuildHeap (c , fieldValue .To (), field .Tag .Get ("txt_heap_table" ))
260
+ str , heaps := buildHeap (c , fieldValue .To (), field .Tag .Get ("txt_heap_table" ))
195
261
th = append (th , heaps ... )
196
262
args = append (args , str )
197
263
}
@@ -201,6 +267,11 @@ func InsertWithHeap[T Entity](c *Crypto, ctx context.Context, tx *sql.Tx, tableN
201
267
202
268
query := fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) RETURNING id" , tableName , strings .Join (fieldNames , ", " ), strings .Join (placeholders , ", " ))
203
269
270
+ err = saveToHeap (ctx , c .dbHeapPsql , th )
271
+ if err != nil {
272
+ return a , fmt .Errorf ("failed to save to heap please check heap db connection: %w" , err )
273
+ }
274
+
204
275
stmt , err := tx .PrepareContext (ctx , query )
205
276
if err != nil {
206
277
return a , fmt .Errorf ("failed to prepare statement: %w" , err )
@@ -212,13 +283,10 @@ func InsertWithHeap[T Entity](c *Crypto, ctx context.Context, tx *sql.Tx, tableN
212
283
return a , fmt .Errorf ("failed to execute statement: %w" , err )
213
284
}
214
285
215
- err = SaveToHeap (ctx , tx , th )
216
- if err != nil {
217
- return a , fmt .Errorf ("failed to save to heap: %w" , err )
218
- }
219
286
return a , nil
220
287
}
221
288
289
+ // Deprecated: any is deprecated. Use interface{} instead.
222
290
func UpdateWithHeap (c * Crypto , ctx context.Context , tx * sql.Tx , tableName string , entity any , id string ) error {
223
291
entityValue := reflect .ValueOf (entity )
224
292
entityType := entityValue .Type ()
@@ -283,7 +351,7 @@ func UpdateWithHeap(c *Crypto, ctx context.Context, tx *sql.Tx, tableName string
283
351
284
352
switch fieldValue := entityValue .Field (i ).Interface ().(type ) {
285
353
case types.AESChiper :
286
- str , heaps := BuildHeap (c , fieldValue .To (), field .Tag .Get ("txt_heap_table" ))
354
+ str , heaps := buildHeap (c , fieldValue .To (), field .Tag .Get ("txt_heap_table" ))
287
355
th = append (th , heaps ... )
288
356
args = append (args , str )
289
357
}
@@ -309,7 +377,7 @@ func UpdateWithHeap(c *Crypto, ctx context.Context, tx *sql.Tx, tableName string
309
377
return fmt .Errorf ("failed to execute statement: %w" , err )
310
378
}
311
379
312
- err = SaveToHeap (ctx , tx , th )
380
+ err = saveToHeap (ctx , c . dbHeapPsql , th )
313
381
if err != nil {
314
382
return fmt .Errorf ("failed to save to heap: %w" , err )
315
383
}
@@ -361,7 +429,7 @@ func QueryLike[T Entity](ctx context.Context, basQuery string, tx *sql.Tx, iOpti
361
429
return
362
430
}
363
431
364
- func BuildHeap (c * Crypto , value string , typeHeap string ) (s string , th []TextHeap ) {
432
+ func buildHeap (c * Crypto , value string , typeHeap string ) (s string , th []TextHeap ) {
365
433
var values = split (value )
366
434
builder := new (strings.Builder )
367
435
for _ , value := range values {
@@ -401,25 +469,25 @@ func SearchContents(ctx context.Context, tx *sql.Tx, table string, args FindText
401
469
return
402
470
}
403
471
404
- func SaveToHeap (ctx context.Context , tx * sql.Tx , textHeaps []TextHeap ) (err error ) {
472
+ func saveToHeap (ctx context.Context , db * sql.DB , textHeaps []TextHeap ) (err error ) {
405
473
for _ , th := range textHeaps {
406
474
query := new (strings.Builder )
407
475
query .WriteString ("INSERT INTO " )
408
476
query .WriteString (th .Type )
409
477
query .WriteString (" (content, hash) VALUES ($1, $2)" )
410
- if ok , _ := isHashExist (ctx , tx , th .Type , FindTextHeapByHashParams {Hash : th .Hash }); ! ok {
411
- _ , err = tx .ExecContext (ctx , query .String (), th .Content , th .Hash )
478
+ if ok , _ := isHashExist (ctx , db , th .Type , FindTextHeapByHashParams {Hash : th .Hash }); ! ok {
479
+ _ , err = db .ExecContext (ctx , query .String (), th .Content , th .Hash )
412
480
}
413
481
}
414
482
return
415
483
}
416
484
417
- func isHashExist (ctx context.Context , tx * sql.Tx , typeHeap string , args FindTextHeapByHashParams ) (bool , error ) {
485
+ func isHashExist (ctx context.Context , db * sql.DB , typeHeap string , args FindTextHeapByHashParams ) (bool , error ) {
418
486
var query = new (strings.Builder )
419
487
query .WriteString ("SELECT hash FROM " )
420
488
query .WriteString (typeHeap )
421
489
query .WriteString (" WHERE hash = $1" )
422
- row := tx .QueryRowContext (ctx , query .String (), args .Hash )
490
+ row := db .QueryRowContext (ctx , query .String (), args .Hash )
423
491
var i FindTextHeapRow
424
492
err := row .Scan (& i .Hash )
425
493
if err != nil {
@@ -435,8 +503,23 @@ func split(value string) (s []string) {
435
503
var sep = " "
436
504
reg := "[a-zA-Z0-9]+"
437
505
regex := regexp .MustCompile (reg )
438
- if validateEmail (value ) {
506
+ switch {
507
+ case validateEmail (value ):
439
508
sep = "@"
509
+ case phone .IsValid ((value )):
510
+ parse , err := phone .Parse (value )
511
+ if err != nil {
512
+ return
513
+ }
514
+ value = parse .ToString ()
515
+ sep = "-"
516
+ case nik .IsValid ((value )) || npwp .IsValid ((value )):
517
+ parse , err := nik .Parse (value )
518
+ if err != nil {
519
+ return
520
+ }
521
+ value = parse .ToString ()
522
+ sep = "."
440
523
}
441
524
parts := strings .Split (value , sep )
442
525
for _ , part := range parts {
0 commit comments