Skip to content

Commit

Permalink
chore: release v0.0.26 (#44)
Browse files Browse the repository at this point in the history
* fix: added the model to the user object of the response (#41)

* Feat/logs (#43)

* feat: Link or hook of the user register query to the system logs table and development of the route to provide access to them

* feat: Link or hook of the remaining queries to the system logs table and development of the filter by username and date

* docs: Logs routes added to api specification

* feat: log and ipaddr util tests

* docs: Fix typo on openapi specification

* fix: Fix description on log test file for controller

---------

Co-authored-by: Antonio Donis <[email protected]>
  • Loading branch information
crijumubu and shoriwe authored Oct 1, 2023
1 parent 87fbf07 commit 0698569
Show file tree
Hide file tree
Showing 23 changed files with 555 additions and 9 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### 0.0.27 (2023-10-01)


### Bug Fixes

* Merge main to dev ([f7fd272](https://github.com/hawks-atlanta/authentication-go/commit/f7fd2724cb2b48bd37531edf61996a11bc7b3cb1))

### 0.0.26 (2023-10-01)

### 0.0.25 (2023-09-19)


Expand Down
2 changes: 1 addition & 1 deletion controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type (
func WithDB(db *gorm.DB) Option {
return func(c *Controller) error {
c.DB = db
return c.DB.AutoMigrate(&models.User{})
return c.DB.AutoMigrate(&models.User{}, &models.Log{})
}
}

Expand Down
64 changes: 64 additions & 0 deletions controller/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package controller

import (
"fmt"
"time"

"github.com/hawks-atlanta/authentication-go/models"
"gorm.io/gorm"
)

type Filter[T any] struct {
Object T `json:"object"`
ItemsPerPage int `json:"itemsPerPage"`
Page int `json:"page"`
}

func (c *Controller) CreateLog(log *models.Log) (err error) {
log.Model = models.Model{}
return c.DB.Create(log).Error
}

func (c *Controller) GetLogs() (logs []models.Log, err error) {

err = c.DB.Find(&logs).Error
return logs, err
}

func (c *Controller) GetLogsByUser(filter *Filter[models.User]) (logs []models.Log, err error) {
err = c.DB.Transaction(func(tx *gorm.DB) error {
var user models.User
err = tx.
Where("username = ?", filter.Object.Username).
First(&user).
Error
if err != nil {
err = fmt.Errorf("failed to query user: %w", err)
return err
}

err = tx.
Limit(filter.ItemsPerPage).
Offset((filter.Page-1)*filter.ItemsPerPage).
Where("user_uuid = ?", user.UUID).
Find(&logs).
Error
if err != nil {
err = fmt.Errorf("failed to query user logs: %w", err)
}
return err
})
return logs, err
}

func (c *Controller) GetLogsByDate(filter *Filter[time.Time]) (logs []models.Log, err error) {

err = c.DB.
Limit(filter.ItemsPerPage).
Offset((filter.Page-1)*filter.ItemsPerPage).
Where("log_time > ?", filter.Object).
Find(&logs).
Error

return logs, err
}
63 changes: 63 additions & 0 deletions controller/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package controller

import (
"testing"
"time"

"github.com/hawks-atlanta/authentication-go/database"
"github.com/hawks-atlanta/authentication-go/models"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
)

func TestLog(t *testing.T) {
t.Run("Failed user logs query", database.Test(func(t *testing.T, db *gorm.DB) {
assertions := assert.New(t)
c, err := New(WithDB(db))
assertions.Nil(err)

u := "Test"
_, err = c.GetLogsByUser(&Filter[models.User]{Object: models.User{Username: &u}, ItemsPerPage: -10, Page: 1})
assertions.EqualError(err, "failed to query user: record not found")
}))

t.Run("No available logs", database.Test(func(t *testing.T, db *gorm.DB) {
assertions := assert.New(t)
c, err := New(WithDB(db))
assertions.Nil(err)

logs, err := c.GetLogs()
assertions.Nil(err)
assertions.Equal(len(logs), 0, "The logs length should be equal to zero")

u := "Test"
_, err = c.GetLogsByUser(&Filter[models.User]{Object: models.User{Username: &u}, ItemsPerPage: 10, Page: 1})
assertions.NotNil(err)

_, err = c.GetLogsByDate(&Filter[time.Time]{Object: time.Now(), ItemsPerPage: 10, Page: 1})
assertions.Nil(err)
}))

t.Run("Succeed", database.Test(func(t *testing.T, db *gorm.DB) {
assertions := assert.New(t)
c, err := New(WithDB(db))
assertions.Nil(err)

l, u := models.RandomLog()
err = c.CreateLog(l)
assertions.Nil(err)

logs, err := c.GetLogs()
assertions.Nil(err)

assertions.Equal(len(logs), 1, "The logs length should be equal to 1")

logs, err = c.GetLogsByUser(&Filter[models.User]{Object: models.User{Username: &u}, ItemsPerPage: 10, Page: 1})
assertions.Nil(err)
assertions.Equal(len(logs), 1, "The logs length filtered by user should be equal to 1")

logs, err = c.GetLogsByDate(&Filter[time.Time]{Object: time.Now().Add(-time.Hour * 1), ItemsPerPage: 10, Page: 1})
assertions.Nil(err)
assertions.Equal(len(logs), 1, "The logs length filtered by date should be equal to 1")
}))
}
90 changes: 90 additions & 0 deletions docs/spec.openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'

/user/uuid/{username}:
get:
security:
Expand Down Expand Up @@ -169,6 +170,95 @@ paths:
schema:
$ref: '#/components/schemas/statusResponse'

/logs:
get:
tags:
- Logs
description: Display all system transactions
responses:
'200':
description: Logs found
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'
'500':
description: Internal error
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'

/logs/user:
post:
tags:
- Logs
description: Display all system transactions filter by username
requestBody:
content:
application/json:
schema:
type: object
properties:
object:
type: object
properties:
username:
type: string
itemsPerPage:
type: integer
page:
type: integer
responses:
'200':
description: User logs found
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'
'500':
description: Internal error
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'

/logs/date:
post:
tags:
- Logs
description: Display all system transactions filter by date
requestBody:
content:
application/json:
schema:
type: object
properties:
object:
type: string
itemsPerPage:
type: integer
page:
type: integer
responses:
'200':
description: Logs found by date
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'
'500':
description: Internal error
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'
components:
securitySchemes:
bearerAuth:
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ require (
gorm.io/gorm v1.25.4
)

require github.com/jaswdr/faker v1.10.2 // indirect

require (
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/bytedance/sonic v1.10.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ddosify/go-faker v0.1.1
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ddosify/go-faker v0.1.1 h1:S18MhU7p237JLTwkOyjfMND1M/vdTLlEbTvv005kdRY=
github.com/ddosify/go-faker v0.1.1/go.mod h1:59U3tEeBJY+7zXwZyuGpmfblEVb9yJ3hTPRPE8PC8SE=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
Expand Down Expand Up @@ -89,6 +91,8 @@ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jaswdr/faker v1.10.2 h1:GK03wuDqa8V6BE+2VRr3DJ/G4T0iUDCzVoBCj5TM4b8=
github.com/jaswdr/faker v1.10.2/go.mod h1:x7ZlyB1AZqwqKZgyQlnqEG8FDptmHlncA5u2zY/yi6w=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
Expand Down
19 changes: 19 additions & 0 deletions internal/utils/ipaddr/ipaddr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ipaddr

import (
"github.com/gin-gonic/gin"
)

func GetIpAddr(ctx *gin.Context) string {

IPAddress := ctx.Request.Header.Get("X-Real-Ip") // Try to get the IP address of a client even if it's behind a proxy or a load balancer

if IPAddress == "" {
IPAddress = ctx.Request.Header.Get("X-Forwarded-For") // If first method get blank result, try to get the IP address through X-Forwarded-For header
}
if IPAddress == "" {
IPAddress = ctx.Request.RemoteAddr // If the lasts methods don't get success, then get the IP from remote address request
}

return IPAddress
}
35 changes: 35 additions & 0 deletions internal/utils/ipaddr/ipaddr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ipaddr

import (
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)

func TestGetIpAddr(t *testing.T) {

req := httptest.NewRequest("GET", "/echo", nil)
req.Header.Set("X-Real-Ip", "192.168.1.1")
w := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(w)
ctx.Request = req
ipAddress := GetIpAddr(ctx)
assert.Equal(t, "192.168.1.1", ipAddress, "La dirección IP debe ser la misma que X-Real-Ip")

req = httptest.NewRequest("GET", "/echo", nil)
req.Header.Set("X-Forwarded-For", "192.168.2.2")
w = httptest.NewRecorder()
ctx, _ = gin.CreateTestContext(w)
ctx.Request = req
ipAddress = GetIpAddr(ctx)
assert.Equal(t, "192.168.2.2", ipAddress, "La dirección IP debe ser la misma que X-Forwarded-For")

req = httptest.NewRequest("GET", "/echo", nil)
w = httptest.NewRecorder()
ctx, _ = gin.CreateTestContext(w)
ctx.Request = req
ipAddress = GetIpAddr(ctx)
assert.NotEmpty(t, ipAddress, "La dirección IP no debe estar vacía")
}
29 changes: 29 additions & 0 deletions models/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package models

import (
"math/rand"
"time"

"github.com/ddosify/go-faker/faker"
"github.com/google/uuid"
)

type Log struct {
Model
User *User `json:"user,omitempty" gorm:"foreignKey:UserUUID;constraint:OnUpdate:CASCADE"`
UserUUID uuid.UUID `json:"userUUID" gorm:"not null;"`
Action string `json:"action" gorm:"not null"`
IpAddress string `json:"ipaddr" gorm:"not null"`
LogTime time.Time `json:"logTime" gorm:"not null;default:CURRENT_TIMESTAMP"`
}

func RandomLog() (*Log, string) {
user := RandomUser()
actions := []string{"User login", "User registration", "User JWT renewal", "User password update", "Got user by username"}
return &Log{
User: user,
UserUUID: user.UUID,
Action: actions[rand.Intn(4)],
IpAddress: faker.NewFaker().RandomIP(),
}, *user.Username
}
13 changes: 13 additions & 0 deletions models/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package models

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestRandomLog(t *testing.T) {
firstLog, _ := RandomLog()
secondLog, _ := RandomLog()
assert.NotEqual(t, firstLog, secondLog)
}
Loading

0 comments on commit 0698569

Please sign in to comment.