Skip to content
This repository has been archived by the owner on Sep 13, 2023. It is now read-only.

Commit

Permalink
Merge pull request #19 from palavrapasse/18-feat-include-subscribe-da…
Browse files Browse the repository at this point in the history
…tabase-and-entities

feat: include subscribe database and entities
  • Loading branch information
rutesantos4 authored Jan 15, 2023
2 parents 0b9fe25 + 81f448b commit 562b8d9
Show file tree
Hide file tree
Showing 38 changed files with 551 additions and 211 deletions.
95 changes: 89 additions & 6 deletions pkg/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import (

_ "github.com/mattn/go-sqlite3"
. "github.com/palavrapasse/damn/pkg/entity"
. "github.com/palavrapasse/damn/pkg/entity/query"
. "github.com/palavrapasse/damn/pkg/entity/subscribe"
)

const (
_sqliteDriverName = "sqlite3"
)

const (
errorMessageCompleteTransaction = "could not complete transaction: %w"
errorMessageRollbackTransaction = "could not rollback transaction: %w"
)

type DatabaseContext[R Record] struct {
DB *sql.DB
FilePath string
Expand Down Expand Up @@ -58,13 +65,13 @@ func (ctx DatabaseContext[Record]) Insert(i Import) error {

defer func() {
if err != nil {
err = fmt.Errorf("could not complete transaction: %w", err)
err = fmt.Errorf(errorMessageCompleteTransaction, err)

err = tx.Rollback()
}

if err != nil {
err = fmt.Errorf("could not rollback transaction: %w", err)
err = fmt.Errorf(errorMessageRollbackTransaction, err)
}
}()

Expand Down Expand Up @@ -162,6 +169,82 @@ func (ctx DatabaseContext[Record]) Insert(i Import) error {
return err
}

func (ctx DatabaseContext[Record]) InsertSubscription(s Subscription) error {

var tx *sql.Tx

tctx, err := ctx.NewTransactionContext()

tx = tctx.Tx

defer func() {
if err != nil {
err = fmt.Errorf(errorMessageCompleteTransaction, err)

err = tx.Rollback()
}

if err != nil {
err = fmt.Errorf(errorMessageRollbackTransaction, err)
}
}()

func() {
sub := s.Subscriber
aff := s.Affected

// Primary first

var pts []any

cbs := []AnonymousErrorCallback{
func() (any, error) {
return typedInsertAndFindPrimary(TransactionContext[Subscriber](tctx), NewSubscriberTable(sub))
},
func() (any, error) {
return typedInsertAndFindPrimary(TransactionContext[Affected](tctx), NewAffectedTable(aff))
},
}

pts, err = returnOnCallbackError(cbs)

if err != nil {
return
}

// Foreign now

sub = pts[0].(PrimaryTable[Subscriber]).Records[0]
aff = pts[1].(PrimaryTable[Affected]).Records

if len(aff) > 0 {
subaff := map[Subscriber]Affected{}

for k := range aff {
subaff[sub] = aff[k]
}

cbs = []AnonymousErrorCallback{
func() (any, error) {
return typedInsertForeign(TransactionContext[SubscriberAffected](tctx), NewSubscriberAffectedTable(subaff))
},
}

_, err = returnOnCallbackError(cbs)

if err != nil {
return
}
}
}()

if err == nil {
err = tx.Commit()
}

return err
}

// Execute a query that can be customized using prepared statements. Consumers must provide a typed callback
// that shall return each row result mapped as a pointer to a struct.
//
Expand All @@ -185,13 +268,13 @@ func (ctx DatabaseContext[R]) CustomQuery(q string, mp TypedQueryResultMapper[R]

defer func() {
if err != nil {
err = fmt.Errorf("could not complete transaction: %w", err)
err = fmt.Errorf(errorMessageCompleteTransaction, err)

err = tx.Rollback()
}

if err != nil {
err = fmt.Errorf("could not rollback transaction: %w", err)
err = fmt.Errorf(errorMessageRollbackTransaction, err)
}
}()

Expand Down Expand Up @@ -346,7 +429,7 @@ func (ctx TransactionContext[R]) insertForeign(t ForeignTable[R]) (ForeignTable[
return t.Copy(updatedRecords), err
}

func typedInsertAndFindPrimary[R BadActor | Credentials | Leak | Platform | User](ctx TransactionContext[R], t PrimaryTable[R]) (PrimaryTable[R], error) {
func typedInsertAndFindPrimary[R BadActor | Credentials | Leak | Platform | User | Subscriber | Affected](ctx TransactionContext[R], t PrimaryTable[R]) (PrimaryTable[R], error) {
tctx := TransactionContext[R]{Tx: ctx.Tx}

tu, err := tctx.insertPrimary(t)
Expand All @@ -358,7 +441,7 @@ func typedInsertAndFindPrimary[R BadActor | Credentials | Leak | Platform | User
return tu, err
}

func typedInsertForeign[R HashCredentials | HashUser | LeakBadActor | LeakCredentials | LeakPlatform | LeakUser | UserCredentials](ctx TransactionContext[R], t ForeignTable[R]) (ForeignTable[R], error) {
func typedInsertForeign[R HashCredentials | HashUser | LeakBadActor | LeakCredentials | LeakPlatform | LeakUser | UserCredentials | SubscriberAffected](ctx TransactionContext[R], t ForeignTable[R]) (ForeignTable[R], error) {
return ctx.insertForeign(t)
}

Expand Down
98 changes: 80 additions & 18 deletions pkg/database/record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"testing"

"github.com/palavrapasse/damn/pkg/entity"
. "github.com/palavrapasse/damn/pkg/entity/query"
. "github.com/palavrapasse/damn/pkg/entity/subscribe"
)

func TestValuesReturnsSchemaValuesIfRecordIsBadActor(t *testing.T) {
r := entity.BadActor{BaId: 1, Identifier: "l33t"}
r := BadActor{BaId: 1, Identifier: "l33t"}

expectedValues := []any{r.BaId, r.Identifier}

Expand All @@ -20,7 +22,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsBadActor(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsCredentials(t *testing.T) {
r := entity.Credentials{CredId: 1, Password: "my.password"}
r := Credentials{CredId: 1, Password: "my.password"}

expectedValues := []any{r.CredId, r.Password}

Expand All @@ -32,7 +34,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsCredentials(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsHashCredentials(t *testing.T) {
r := entity.HashCredentials{CredId: 1, HSHA256: entity.NewHSHA256("my.password")}
r := HashCredentials{CredId: 1, HSHA256: entity.NewHSHA256("my.password")}

expectedValues := []any{r.CredId, r.HSHA256}

Expand All @@ -44,7 +46,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsHashCredentials(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsHashUser(t *testing.T) {
r := entity.HashUser{UserId: 1, HSHA256: entity.NewHSHA256("my.email@gmail.com")}
r := HashUser{UserId: 1, HSHA256: entity.NewHSHA256("my.email@gmail.com")}

expectedValues := []any{r.UserId, r.HSHA256}

Expand All @@ -56,7 +58,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsHashUser(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsLeakBadActor(t *testing.T) {
r := entity.LeakBadActor{BaId: 1, LeakId: 2}
r := LeakBadActor{BaId: 1, LeakId: 2}

expectedValues := []any{r.BaId, r.LeakId}

Expand All @@ -68,7 +70,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsLeakBadActor(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsLeakCredentials(t *testing.T) {
r := entity.LeakCredentials{CredId: 1, LeakId: 2}
r := LeakCredentials{CredId: 1, LeakId: 2}

expectedValues := []any{r.CredId, r.LeakId}

Expand All @@ -80,7 +82,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsLeakCredentials(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsLeakPlatform(t *testing.T) {
r := entity.LeakPlatform{PlatId: 1, LeakId: 2}
r := LeakPlatform{PlatId: 1, LeakId: 2}

expectedValues := []any{r.PlatId, r.LeakId}

Expand All @@ -92,7 +94,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsLeakPlatform(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsLeak(t *testing.T) {
r := entity.Leak{LeakId: 1, ShareDateSC: entity.DateInSeconds(2), Context: "twitter breach"}
r := Leak{LeakId: 1, ShareDateSC: DateInSeconds(2), Context: "twitter breach"}

expectedValues := []any{r.LeakId, r.ShareDateSC, r.Context}

Expand All @@ -104,7 +106,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsLeak(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsLeakUser(t *testing.T) {
r := entity.LeakUser{UserId: 1, LeakId: 2}
r := LeakUser{UserId: 1, LeakId: 2}

expectedValues := []any{r.UserId, r.LeakId}

Expand All @@ -116,7 +118,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsLeakUser(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsPlatform(t *testing.T) {
r := entity.Platform{PlatId: 1, Name: "twitter"}
r := Platform{PlatId: 1, Name: "twitter"}

expectedValues := []any{r.PlatId, r.Name}

Expand All @@ -128,7 +130,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsPlatform(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsUserCredentials(t *testing.T) {
r := entity.UserCredentials{CredId: 1, UserId: 2}
r := UserCredentials{CredId: 1, UserId: 2}

expectedValues := []any{r.CredId, r.UserId}

Expand All @@ -140,7 +142,7 @@ func TestValuesReturnsSchemaValuesIfRecordIsUserCredentials(t *testing.T) {
}

func TestValuesReturnsSchemaValuesIfRecordIsUser(t *testing.T) {
r := entity.User{UserId: 1, Email: "my.email@gmail.com"}
r := User{UserId: 1, Email: "my.email@gmail.com"}

expectedValues := []any{r.UserId, r.Email}

Expand All @@ -151,8 +153,44 @@ func TestValuesReturnsSchemaValuesIfRecordIsUser(t *testing.T) {
}
}

func TestValuesReturnsSchemaValuesIfRecordIsSubscriber(t *testing.T) {
r := Subscriber{SubscriberId: 1, B64Email: "base64Email"}

expectedValues := []any{r.SubscriberId, r.B64Email}

values := Values(r)

if !reflect.DeepEqual(values, expectedValues) {
t.Fatalf("Values should have return slice with values as defined in schema, but got: %v", values)
}
}

func TestValuesReturnsSchemaValuesIfRecordIsAffected(t *testing.T) {
r := Affected{AffectedId: 1, HSHA256Email: entity.NewHSHA256("Email")}

expectedValues := []any{r.AffectedId, r.HSHA256Email}

values := Values(r)

if !reflect.DeepEqual(values, expectedValues) {
t.Fatalf("Values should have return slice with values as defined in schema, but got: %v", values)
}
}

func TestValuesReturnsSchemaValuesIfRecordIsSubscriberAffected(t *testing.T) {
r := SubscriberAffected{AffId: 1, SubId: 2}

expectedValues := []any{r.AffId, r.SubId}

values := Values(r)

if !reflect.DeepEqual(values, expectedValues) {
t.Fatalf("Values should have return slice with values as defined in schema, but got: %v", values)
}
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsBadActor(t *testing.T) {
r := entity.BadActor{}
r := BadActor{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

Expand All @@ -164,7 +202,7 @@ func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsBadActor(t *testi
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsCredentials(t *testing.T) {
r := entity.Credentials{}
r := Credentials{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

Expand All @@ -176,7 +214,7 @@ func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsCredentials(t *te
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsLeak(t *testing.T) {
r := entity.Leak{}
r := Leak{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

Expand All @@ -188,7 +226,7 @@ func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsLeak(t *testing.T
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsPlatform(t *testing.T) {
r := entity.Platform{}
r := Platform{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

Expand All @@ -200,7 +238,31 @@ func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsPlatform(t *testi
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsUser(t *testing.T) {
r := entity.User{}
r := User{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

copyRecord := CopyWithNewKey(r, k)

if copyRecord != expectedRecord {
t.Fatalf("CopyWithNewKey should have set auto gen key via Copy method, but match failed: %v\n", copyRecord)
}
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsSubscriber(t *testing.T) {
r := Subscriber{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

copyRecord := CopyWithNewKey(r, k)

if copyRecord != expectedRecord {
t.Fatalf("CopyWithNewKey should have set auto gen key via Copy method, but match failed: %v\n", copyRecord)
}
}

func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsAffected(t *testing.T) {
r := Affected{}
k := entity.AutoGenKey(500)
expectedRecord := r.Copy(k)

Expand All @@ -212,7 +274,7 @@ func TestCopyWithNewKeyReturnsRecordWithAutoGenKeySetIfRecordIsUser(t *testing.T
}

func TestCopyWithNewKeyReturnsSameRecordIfRecordIsNotPrimary(t *testing.T) {
r := entity.LeakCredentials{}
r := LeakCredentials{}
k := entity.AutoGenKey(500)
expectedRecord := r

Expand Down
Loading

0 comments on commit 562b8d9

Please sign in to comment.