Skip to content

Commit

Permalink
feat: add a new endpoint for getting system events (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoubfaouzi authored Sep 4, 2023
1 parent 4707067 commit 12cbab7
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
23 changes: 23 additions & 0 deletions internal/behavior/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func RegisterHandlers(g *echo.Group, service Service,

g.GET("/behaviors/:id/", res.get, verifyID)
g.GET("/behaviors/:id/api-trace/", res.apis, verifyID)
g.GET("/behaviors/:id/sys-events/", res.events, verifyID)

}

Expand Down Expand Up @@ -81,6 +82,28 @@ func (r resource) apis(c echo.Context) error {
return c.JSON(http.StatusOK, pages)
}

func (r resource) events(c echo.Context) error {
ctx := c.Request().Context()

if len(c.QueryParams()) > 0 {
ctx = WithFilters(ctx, c.QueryParams())
}

count, err := r.service.CountEvents(ctx, c.Param("id"))
if err != nil {
return err
}

pages := pagination.NewFromRequest(c.Request(), count)
events, err := r.service.Events(
ctx, c.Param("id"), pages.Offset(), pages.Limit())
if err != nil {
return err
}
pages.Items = events
return c.JSON(http.StatusOK, pages)
}

// WithFilters returns a context that contains the API filters.
func WithFilters(ctx context.Context, value map[string][]string) context.Context {
return context.WithValue(ctx, filtersKey, value)
Expand Down
83 changes: 83 additions & 0 deletions internal/behavior/repostitory.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ type Repository interface {
Query(ctx context.Context, offset, limit int) ([]entity.Behavior, error)

CountAPIs(ctx context.Context, id string) (int, error)
CountEvents(ctx context.Context, id string) (int, error)
APIs(ctx context.Context, id string, offset, limit int) (
interface{}, error)
Events(ctx context.Context, id string, offset, limit int) (
interface{}, error)
}

// repository persists file scan behaviors in database.
Expand Down Expand Up @@ -152,6 +155,39 @@ func (r repository) CountAPIs(ctx context.Context, id string) (int, error) {
return count, err
}

// CountEvents returns the number of strings in a file doc in the database.
func (r repository) CountEvents(ctx context.Context, id string) (int, error) {
var count int
var statement string
params := make(map[string]interface{}, 1)
params["id"] = id + "::events"

filters, ok := ctx.Value(filtersKey).(map[string][]string)
if ok {
statement =
"SELECT RAW COUNT(event) AS count FROM `" + r.db.Bucket.Name() + "` d" +
" USE KEYS $id UNNEST d.sys_events as event"
i := 0
for k, v := range filters {
if i == 0 {
statement += " WHERE"
} else {
statement += " AND"
}
i++
statement += fmt.Sprintf(" event.%s IN $%s", k, k)
params[k] = v
}
} else {
statement =
"SELECT RAW ARRAY_LENGTH(d.sys_events) AS count FROM `" + r.db.Bucket.Name() + "` d" +
" USE KEYS $id"
}

err := r.db.Count(ctx, statement, params, &count)
return count, err
}

func (r repository) APIs(ctx context.Context, id string, offset,
limit int) (interface{}, error) {

Expand Down Expand Up @@ -198,3 +234,50 @@ func (r repository) APIs(ctx context.Context, id string, offset,
}
return results.([]interface{}), nil
}

func (r repository) Events(ctx context.Context, id string, offset,
limit int) (interface{}, error) {

var results interface{}
var statement string

params := make(map[string]interface{}, 1)
params["offset"] = offset
params["limit"] = limit
params["id"] = id + "::events"

filters, ok := ctx.Value(filtersKey).(map[string][]string)
if ok {
statement =
"SELECT RAW event FROM `" + r.db.Bucket.Name() + "` d" +
" USE KEYS $id UNNEST d.sys_events as event"
i := 0
for k, v := range filters {
if i == 0 {
statement += " WHERE"
} else {
statement += " AND"
}
i++
statement += fmt.Sprintf(" event.%s IN $%s", k, k)
params[k] = v
}
statement += " OFFSET $offset LIMIT $limit"
} else {
statement =
"SELECT RAW sys_events[$offset:$limit] FROM `" + r.db.Bucket.Name() +
"` USE KEYS $id"

}

err := r.db.Query(ctx, statement, params, &results)
if err != nil {
return nil, err
}
if len(results.([]interface{})) == 0 {
return results, nil
} else if len(results.([]interface{})) == 1 {
return results.([]interface{})[0], nil
}
return results.([]interface{}), nil
}
20 changes: 20 additions & 0 deletions internal/behavior/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ type Service interface {
Exists(ctx context.Context, id string) (bool, error)
Count(ctx context.Context) (int, error)
CountAPIs(ctx context.Context, id string) (int, error)
CountEvents(ctx context.Context, id string) (int, error)
APIs(ctx context.Context, id string, offset, limit int) (interface{}, error)
Events(ctx context.Context, id string, offset, limit int) (interface{}, error)
}

// Behavior represents the data about a behavior scan.
Expand Down Expand Up @@ -62,6 +64,14 @@ func (s service) CountAPIs(ctx context.Context, id string) (int, error) {
return count, err
}

func (s service) CountEvents(ctx context.Context, id string) (int, error) {
count, err := s.repo.CountEvents(ctx, id)
if err != nil {
return 0, err
}
return count, err
}

func (s service) APIs(ctx context.Context, id string, offset, limit int) (
interface{}, error) {

Expand All @@ -71,3 +81,13 @@ func (s service) APIs(ctx context.Context, id string, offset, limit int) (
}
return result, nil
}

func (s service) Events(ctx context.Context, id string, offset, limit int) (
interface{}, error) {

result, err := s.repo.Events(ctx, id, offset, limit)
if err != nil {
return nil, err
}
return result, nil
}

0 comments on commit 12cbab7

Please sign in to comment.