-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bd2b7dc
commit f6a19de
Showing
3 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package entities | ||
|
||
type Query struct { | ||
ID string `json:"id,omitempty"` | ||
Content string `json:"content,omitempty"` | ||
OwnerID string `json:"owner_id,omitempty"` | ||
Active bool `json:"active,omitempty"` | ||
Description string `json:"description,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package repos | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/google/uuid" | ||
"github.com/honeynet/ochi/backend/entities" | ||
|
||
"github.com/jmoiron/sqlx" | ||
"github.com/jmoiron/sqlx/reflectx" | ||
_ "github.com/mattn/go-sqlite3" | ||
) | ||
|
||
type QueryRepo struct { | ||
findByOwnerQuery *sqlx.Stmt | ||
deleteQuery *sqlx.Stmt | ||
createQuery *sqlx.NamedStmt | ||
updateQuery *sqlx.Stmt | ||
getByIdQuery *sqlx.Stmt | ||
db *sqlx.DB | ||
} | ||
|
||
func NewQueryRepo(db *sqlx.DB) (*QueryRepo, error) { | ||
r := &QueryRepo{} | ||
db.Mapper = reflectx.NewMapperFunc("json", strings.ToLower) | ||
_, err := db.Exec(`CREATE TABLE IF NOT EXISTS queries ( | ||
id TEXT PRIMARY KEY NOT NULL | ||
, content TEXT NOT NULL | ||
, owner_id TEXT NOT NULL | ||
, active INTEGER NOT NULL | ||
, description TEXT NOT NULL | ||
, CONSTRAINT id_unique UNIQUE (id) | ||
)`) | ||
if err != nil { | ||
return nil, err | ||
} | ||
r.findByOwnerQuery, err = db.Preparex("SELECT * FROM queries WHERE owner_id=?") | ||
if err != nil { | ||
return nil, err | ||
} | ||
r.createQuery, err = db.PrepareNamed("INSERT INTO queries (id, owner_id, content, active, description) VALUES (:id, :owner_id, :content, :active, :description)") | ||
if err != nil { | ||
return nil, err | ||
} | ||
r.updateQuery, err = db.Preparex("UPDATE queries SET content=?, active=?, description=? WHERE id=?") | ||
if err != nil { | ||
return nil, err | ||
} | ||
r.getByIdQuery, err = db.Preparex("SELECT * FROM queries WHERE id=?") | ||
if err != nil { | ||
return nil, err | ||
} | ||
r.deleteQuery, err = db.Preparex("DELETE FROM queries WHERE id=?") | ||
if err != nil { | ||
return nil, err | ||
} | ||
return r, nil | ||
} | ||
|
||
// Get a user | ||
func (r *QueryRepo) FindByOwnerId(ownerId string) ([]entities.Query, error) { | ||
qs := []entities.Query{} | ||
err := r.findByOwnerQuery.Select(&qs, ownerId) | ||
return qs, err | ||
} | ||
|
||
// Create a query | ||
func (r *QueryRepo) Create(owner_id, content, description string, active bool) (entities.Query, error) { | ||
id, err := uuid.NewRandom() | ||
if err != nil { | ||
return entities.Query{}, err | ||
} | ||
q := entities.Query{ID: id.String(), Content: content, OwnerID: owner_id, Active: active, Description: description} | ||
_, err = r.createQuery.Exec(&q) | ||
if err != nil { | ||
return entities.Query{}, err | ||
} | ||
return q, nil | ||
} | ||
|
||
// Update a query | ||
func (r *QueryRepo) Update(id, content, description string, active bool) error { | ||
res, err := r.updateQuery.Exec(content, active, description, id) | ||
if err != nil { | ||
return err | ||
} | ||
if cnt, err := res.RowsAffected(); err != nil { | ||
return err | ||
} else if cnt == 0 { | ||
return errors.New(fmt.Sprintf("%s not found", id)) | ||
} | ||
return nil | ||
} | ||
|
||
// GetByID | ||
func (r *QueryRepo) GetByID(id string) (entities.Query, error) { | ||
q := entities.Query{} | ||
err := r.getByIdQuery.Get(&q, id) | ||
return q, err | ||
} | ||
|
||
// Delete a query | ||
func (r *QueryRepo) Delete(id string) error { | ||
res, err := r.deleteQuery.Exec(id) | ||
if err != nil { | ||
return err | ||
} | ||
if cnt, err := res.RowsAffected(); err != nil { | ||
return err | ||
} else if cnt == 0 { | ||
return errors.New(fmt.Sprintf("%s not found", id)) | ||
} | ||
return nil | ||
} | ||
|
||
// // Find a user | ||
// func (r *QueryRepo) Find(email string) (entities.User, error) { | ||
// u := entities.User{Email: email} | ||
// err := r.readEmail.Get(&u, email) | ||
// if err == sql.ErrNoRows { | ||
// var id uuid.UUID | ||
// id, err = uuid.NewRandom() | ||
// if err != nil { | ||
// return u, err | ||
// } | ||
// u.ID = id.String() | ||
// _, err = r.create.Exec(&u) | ||
// if err != nil { | ||
// return u, err | ||
// } | ||
// } | ||
// return u, err | ||
// } | ||
|
||
// Close the db | ||
func (r *QueryRepo) Close() { | ||
if r.db != nil { | ||
r.db.Close() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package repos | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/jmoiron/sqlx" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestQuery(t *testing.T) { | ||
r := initRepo(t) | ||
u1, err := r.FindByOwnerId("test@test") | ||
require.NoError(t, err) | ||
require.Empty(t, u1) | ||
|
||
q, err := r.Create("123", "hello there", "this is desription", true) | ||
require.NoError(t, err) | ||
require.NotEmpty(t, q.ID) | ||
|
||
u1, err = r.FindByOwnerId("123") | ||
require.NoError(t, err) | ||
require.Equal(t, len(u1), 1) | ||
|
||
require.Equal(t, u1[0], q) | ||
|
||
err = r.Delete("Not found") | ||
require.Error(t, err) | ||
|
||
err = r.Delete(q.ID) | ||
require.NoError(t, err) | ||
|
||
u1, err = r.FindByOwnerId("123") | ||
require.NoError(t, err) | ||
require.Empty(t, u1) | ||
} | ||
|
||
func TestGetById_Missing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
_, err := r.GetByID("non-existing") | ||
require.ErrorContains(t, err, "sql: no rows in result set") | ||
} | ||
|
||
func TestGetById_Existing(t *testing.T) { | ||
r := initRepo(t) | ||
q, err := r.Create("001", "content", "description", true) | ||
require.NoError(t, err) | ||
require.Equal(t, "001", q.OwnerID) | ||
require.Equal(t, "content", q.Content) | ||
require.Equal(t, "description", q.Description) | ||
|
||
q1, err := r.GetByID(q.ID) | ||
require.NoError(t, err) | ||
require.Equal(t, q, q1) | ||
} | ||
|
||
func TestFindByOwnerId_Missing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
qs, err := r.FindByOwnerId("non-existing") | ||
require.NoError(t, err) | ||
require.Empty(t, qs) | ||
} | ||
|
||
func TestFindByOwnerId_Existing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
q, err := r.Create("001", "content", "description", true) | ||
require.NoError(t, err) | ||
require.Equal(t, "001", q.OwnerID) | ||
require.Equal(t, "content", q.Content) | ||
require.Equal(t, "description", q.Description) | ||
|
||
q1, err := r.Create("001", "content1", "description1", true) | ||
require.NoError(t, err) | ||
require.Equal(t, "001", q1.OwnerID) | ||
require.Equal(t, "content1", q1.Content) | ||
require.Equal(t, "description1", q1.Description) | ||
|
||
q2, err := r.Create("001", "content2", "description2", true) | ||
require.NoError(t, err) | ||
require.Equal(t, "001", q2.OwnerID) | ||
require.Equal(t, "content2", q2.Content) | ||
require.Equal(t, "description2", q2.Description) | ||
|
||
qs, err := r.FindByOwnerId("001") | ||
require.NoError(t, err) | ||
require.Contains(t, qs, q) | ||
require.Contains(t, qs, q1) | ||
require.Contains(t, qs, q2) | ||
} | ||
|
||
func TestDeleteQuery_Missing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
err := r.Delete("non-existing") | ||
require.ErrorContains(t, err, "non-existing not found") | ||
} | ||
|
||
func TestDeleteQuery_Existing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
q, err := r.Create("001", "content", "description", true) | ||
require.NoError(t, err) | ||
|
||
err = r.Delete(q.ID) | ||
require.NoError(t, err) | ||
|
||
err = r.Delete(q.ID) | ||
require.Error(t, err) | ||
|
||
_, err = r.GetByID(q.ID) | ||
require.Error(t, err) | ||
} | ||
|
||
func TestUpdateQuery_Missing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
err := r.Update("non-existing", "content", "description", true) | ||
require.ErrorContains(t, err, "non-existing not found") | ||
} | ||
|
||
func TestUpdateQuery_Existing(t *testing.T) { | ||
r := initRepo(t) | ||
|
||
q, err := r.Create("001", "content", "description", true) | ||
require.NoError(t, err) | ||
|
||
err = r.Update(q.ID, "content-new", "description-new", false) | ||
require.NoError(t, err) | ||
|
||
q1, err := r.GetByID(q.ID) | ||
require.Equal(t, "content-new", q1.Content) | ||
require.Equal(t, "description-new", q1.Description) | ||
require.Equal(t, false, q1.Active) | ||
} | ||
|
||
func initRepo(t *testing.T) *QueryRepo { | ||
tmp := t.TempDir() | ||
dbPath := fmt.Sprintf("%s/test.db", tmp) | ||
db, err := sqlx.Connect("sqlite3", dbPath) | ||
require.NoError(t, err) | ||
|
||
// defer os.Remove("./querytest.db") | ||
r, err := NewQueryRepo(db) | ||
require.NoError(t, err) | ||
require.NotNil(t, r) | ||
return r | ||
} |