From 069856957364c8bc9ae89b3cfd76e8c7c2f5232d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Julian=20Mu=C3=B1oz=20Buenahora?= <62572462+crijumubu@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:53:45 -0500 Subject: [PATCH] chore: release v0.0.26 (#44) * 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 --- CHANGELOG.md | 9 +++ controller/controller.go | 2 +- controller/log.go | 64 ++++++++++++++++ controller/log_test.go | 63 ++++++++++++++++ docs/spec.openapi.yaml | 90 ++++++++++++++++++++++ go.mod | 3 + go.sum | 4 + internal/utils/ipaddr/ipaddr.go | 19 +++++ internal/utils/ipaddr/ipaddr_test.go | 35 +++++++++ models/log.go | 29 +++++++ models/log_test.go | 13 ++++ models/user.go | 3 - package-lock.json | 4 +- package.json | 2 +- router/challenge.go | 11 ++- router/log.go | 66 ++++++++++++++++ router/log_test.go | 109 +++++++++++++++++++++++++++ router/login.go | 7 ++ router/query.go | 9 +++ router/register.go | 7 ++ router/router.go | 3 + router/update_password.go | 7 ++ router/utils.go | 5 ++ 23 files changed, 555 insertions(+), 9 deletions(-) create mode 100644 controller/log.go create mode 100644 controller/log_test.go create mode 100644 internal/utils/ipaddr/ipaddr.go create mode 100644 internal/utils/ipaddr/ipaddr_test.go create mode 100644 models/log.go create mode 100644 models/log_test.go create mode 100644 router/log.go create mode 100644 router/log_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index a1824e2..3b1b68f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/controller/controller.go b/controller/controller.go index c92e059..17c2977 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -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{}) } } diff --git a/controller/log.go b/controller/log.go new file mode 100644 index 0000000..adbb983 --- /dev/null +++ b/controller/log.go @@ -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 +} diff --git a/controller/log_test.go b/controller/log_test.go new file mode 100644 index 0000000..9d7186c --- /dev/null +++ b/controller/log_test.go @@ -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") + })) +} diff --git a/docs/spec.openapi.yaml b/docs/spec.openapi.yaml index 2a72533..44523f6 100644 --- a/docs/spec.openapi.yaml +++ b/docs/spec.openapi.yaml @@ -136,6 +136,7 @@ paths: application/json: schema: $ref: '#/components/schemas/statusResponse' + /user/uuid/{username}: get: security: @@ -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: diff --git a/go.mod b/go.mod index b3b2366..729054a 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,8 @@ 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 @@ -23,6 +25,7 @@ require ( 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 diff --git a/go.sum b/go.sum index 65df6e1..bded282 100644 --- a/go.sum +++ b/go.sum @@ -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= @@ -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= diff --git a/internal/utils/ipaddr/ipaddr.go b/internal/utils/ipaddr/ipaddr.go new file mode 100644 index 0000000..dd10760 --- /dev/null +++ b/internal/utils/ipaddr/ipaddr.go @@ -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 +} diff --git a/internal/utils/ipaddr/ipaddr_test.go b/internal/utils/ipaddr/ipaddr_test.go new file mode 100644 index 0000000..07fb225 --- /dev/null +++ b/internal/utils/ipaddr/ipaddr_test.go @@ -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") +} diff --git a/models/log.go b/models/log.go new file mode 100644 index 0000000..58090b9 --- /dev/null +++ b/models/log.go @@ -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 +} diff --git a/models/log_test.go b/models/log_test.go new file mode 100644 index 0000000..4e6b2b0 --- /dev/null +++ b/models/log_test.go @@ -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) +} diff --git a/models/user.go b/models/user.go index 4dd5d6a..a456725 100644 --- a/models/user.go +++ b/models/user.go @@ -2,7 +2,6 @@ package models import ( "fmt" - "regexp" "time" "github.com/brianvoe/gofakeit/v6" @@ -52,8 +51,6 @@ func (u *User) BeforeSave(tx *gorm.DB) (err error) { return err } -var phoneRegex = regexp.MustCompile(`(?m)^\d{2,18}$`) - var ( True = true False = false diff --git a/package-lock.json b/package-lock.json index 603ef99..588fcdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "authentication-go", - "version": "0.0.25", + "version": "0.0.27", "lockfileVersion": 3, "requires": true, "packages": { "": { - "version": "0.0.25", + "version": "0.0.27", "devDependencies": { "git-semver-tags": "^4.1.1", "standard-version": "^9.5.0" diff --git a/package.json b/package.json index c9c36e6..77bb3e9 100644 --- a/package.json +++ b/package.json @@ -3,5 +3,5 @@ "git-semver-tags": "^4.1.1", "standard-version": "^9.5.0" }, - "version": "0.0.25" + "version": "0.0.27" } diff --git a/router/challenge.go b/router/challenge.go index e2aa823..847ca8b 100644 --- a/router/challenge.go +++ b/router/challenge.go @@ -4,10 +4,17 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/hawks-atlanta/authentication-go/internal/utils/ipaddr" "github.com/hawks-atlanta/authentication-go/models" ) func (r *Router) Challenge(ctx *gin.Context) { - ctx.JSON(http.StatusOK, Token{JWT: r.C.JWT.New(ctx.MustGet(SessionVariale).(*models.User).Claims())}) - return + session := ctx.MustGet(SessionVariale).(*models.User) + log := models.Log{User: session, UserUUID: session.UUID, Action: "User JWT renewal", IpAddress: ipaddr.GetIpAddr(ctx)} + err := r.C.CreateLog(&log) + if err != nil { + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + return + } + ctx.JSON(http.StatusOK, Token{JWT: r.C.JWT.New(session.Claims())}) } diff --git a/router/log.go b/router/log.go new file mode 100644 index 0000000..4830543 --- /dev/null +++ b/router/log.go @@ -0,0 +1,66 @@ +package router + +import ( + "errors" + "net/http" + "time" + + "github.com/gin-gonic/gin" + "github.com/hawks-atlanta/authentication-go/controller" + "github.com/hawks-atlanta/authentication-go/models" + "gorm.io/gorm" +) + +// GET /logs +func (r *Router) GetLogs(ctx *gin.Context) { + + logs, err := r.C.GetLogs() + + if err != nil { + + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + return + } + + ctx.JSON(http.StatusOK, logs) + +} + +// GET /logs/username +func (r *Router) GetLogByUser(ctx *gin.Context) { + + var filter controller.Filter[models.User] + err := ctx.Bind(&filter) + if err != nil { + return + } + logs, err := r.C.GetLogsByUser(&filter) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { // User was not found + ctx.JSON(http.StatusNotFound, InternalServerError(err)) + } else { + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + } + return + } + + ctx.JSON(http.StatusOK, logs) +} + +// GET /logs/date +func (r *Router) GetLogByDate(ctx *gin.Context) { + + var filter controller.Filter[time.Time] + err := ctx.Bind(&filter) + if err != nil { + return + } + + logs, err := r.C.GetLogsByDate(&filter) + if err != nil { + + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + } + + ctx.JSON(http.StatusOK, logs) +} diff --git a/router/log_test.go b/router/log_test.go new file mode 100644 index 0000000..af03f40 --- /dev/null +++ b/router/log_test.go @@ -0,0 +1,109 @@ +package router + +import ( + "net/http" + "testing" + "time" + + "github.com/hawks-atlanta/authentication-go/controller" + "github.com/hawks-atlanta/authentication-go/database" + "github.com/hawks-atlanta/authentication-go/models" + "github.com/stretchr/testify/assert" + "gorm.io/gorm" +) + +func TestLogs(t *testing.T) { + t.Run("Succeed", database.Test(func(t *testing.T, db *gorm.DB) { + + expect, closeFunc := NewDefault(t, db) + defer closeFunc() + + expect. + GET(LogsRoute). + Expect(). + Status(http.StatusOK). + JSON(). + Array() + })) +} + +func TestUserLogs(t *testing.T) { + + t.Run("Succeed", database.Test(func(t *testing.T, db *gorm.DB) { + assertions := assert.New(t) + + expect, closeFunc := NewDefault(t, db) + defer closeFunc() + + l, u := models.RandomLog() + assertions.Nil(db.Create(l).Error) + + expect. + POST(LogsUserRoute). + WithJSON(controller.Filter[models.User]{Object: models.User{Username: &u}, ItemsPerPage: 10, Page: 1}). + Expect(). + Status(http.StatusOK). + JSON(). + Array() + })) + + t.Run("Logs not found", database.Test(func(t *testing.T, db *gorm.DB) { + + expect, closeFunc := NewDefault(t, db) + defer closeFunc() + + u := "Test" + expect. + POST(LogsUserRoute). + WithJSON(controller.Filter[models.User]{Object: models.User{Username: &u}, ItemsPerPage: 10, Page: 1}). + Expect(). + Status(http.StatusNotFound). + JSON(). + Object(). + Value("succeed"). + Boolean(). + IsFalse() + })) + t.Run("Invalid JSON", database.Test(func(t *testing.T, db *gorm.DB) { + expect, closeFunc := NewDefault(t, db) + defer closeFunc() + + expect. + POST(LogsUserRoute). + WithText("}"). + WithHeader("Content-Type", "application/json"). + Expect(). + Status(http.StatusBadRequest) + })) +} + +func TestDateLogs(t *testing.T) { + + t.Run("Succeed", database.Test(func(t *testing.T, db *gorm.DB) { + assertions := assert.New(t) + + expect, closeFunc := NewDefault(t, db) + defer closeFunc() + + l, _ := models.RandomLog() + assertions.Nil(db.Create(l).Error) + + expect. + POST(LogsDateRoute). + WithJSON(controller.Filter[time.Time]{Object: time.Now().Add(-time.Hour * 1), ItemsPerPage: 10, Page: 1}). + Expect(). + Status(http.StatusOK) + })) + + t.Run("Invalid JSON", database.Test(func(t *testing.T, db *gorm.DB) { + expect, closeFunc := NewDefault(t, db) + defer closeFunc() + + expect. + POST(LogsDateRoute). + WithText("}"). + WithHeader("Content-Type", "application/json"). + Expect(). + Status(http.StatusBadRequest) + })) +} diff --git a/router/login.go b/router/login.go index edf04c3..738a674 100644 --- a/router/login.go +++ b/router/login.go @@ -6,6 +6,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hawks-atlanta/authentication-go/controller" + "github.com/hawks-atlanta/authentication-go/internal/utils/ipaddr" "github.com/hawks-atlanta/authentication-go/models" ) @@ -29,5 +30,11 @@ func (r *Router) Login(ctx *gin.Context) { } return } + log := models.Log{User: &user, UserUUID: user.UUID, Action: "User login", IpAddress: ipaddr.GetIpAddr(ctx)} + err = r.C.CreateLog(&log) + if err != nil { + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + return + } ctx.JSON(http.StatusCreated, Token{JWT: r.C.JWT.New(user.Claims())}) } diff --git a/router/query.go b/router/query.go index a23df95..be0226f 100644 --- a/router/query.go +++ b/router/query.go @@ -5,6 +5,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hawks-atlanta/authentication-go/controller" + "github.com/hawks-atlanta/authentication-go/internal/utils/ipaddr" "github.com/hawks-atlanta/authentication-go/models" ) @@ -17,6 +18,14 @@ func (r *Router) UserByUsername(ctx *gin.Context) { ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) return } + + log := models.Log{User: &user, UserUUID: user.UUID, Action: "Got user by username", IpAddress: ipaddr.GetIpAddr(ctx)} + err = r.C.CreateLog(&log) + if err != nil { + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + return + } + res := models.User{Model: user.Model, Username: user.Username} ctx.JSON(http.StatusOK, res) } diff --git a/router/register.go b/router/register.go index 014502e..2936a6a 100644 --- a/router/register.go +++ b/router/register.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/hawks-atlanta/authentication-go/internal/utils/ipaddr" "github.com/hawks-atlanta/authentication-go/models" ) @@ -18,5 +19,11 @@ func (r *Router) Register(ctx *gin.Context) { ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) return } + log := models.Log{User: &user, UserUUID: user.UUID, Action: "User registration", IpAddress: ipaddr.GetIpAddr(ctx)} + err = r.C.CreateLog(&log) + if err != nil { + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + return + } ctx.JSON(http.StatusCreated, Token{JWT: r.C.JWT.New(user.Claims())}) } diff --git a/router/router.go b/router/router.go index e4e0fb2..4c35964 100644 --- a/router/router.go +++ b/router/router.go @@ -18,6 +18,9 @@ func New(opts ...Option) *gin.Engine { r.POST(LoginRoute, r.Login) r.POST(RegisterRoute, r.Register) + r.GET(LogsRoute, r.GetLogs) + r.POST(LogsUserRoute, r.GetLogByUser) + r.POST(LogsDateRoute, r.GetLogByDate) // Authentication required authReq := r.Group(RootRoute, r.Authorize) authReq.PATCH(AccountPasswordRoute, r.UpdatePassword) diff --git a/router/update_password.go b/router/update_password.go index 016bce4..cd95740 100644 --- a/router/update_password.go +++ b/router/update_password.go @@ -6,6 +6,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hawks-atlanta/authentication-go/controller" + "github.com/hawks-atlanta/authentication-go/internal/utils/ipaddr" "github.com/hawks-atlanta/authentication-go/models" ) @@ -25,5 +26,11 @@ func (r *Router) UpdatePassword(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, InternalServerError(err)) return } + log := models.Log{User: session, UserUUID: session.UUID, Action: "User password update", IpAddress: ipaddr.GetIpAddr(ctx)} //Add query time and change register msg + err = r.C.CreateLog(&log) + if err != nil { + ctx.JSON(http.StatusInternalServerError, InternalServerError(err)) + return + } ctx.AbortWithStatusJSON(http.StatusOK, SucceedResult("Password updated successfully")) } diff --git a/router/utils.go b/router/utils.go index 3badaaa..737e3fd 100644 --- a/router/utils.go +++ b/router/utils.go @@ -13,6 +13,11 @@ const ( RegisterRoute = "/register" ChallengeRoute = "/challenge" AccountPasswordRoute = "/account/password" + LogsRoute = "/logs" + UserRoute = "/user" + LogsUserRoute = LogsRoute + UserRoute + DateRoute = "/date" + LogsDateRoute = LogsRoute + DateRoute UserUUIDRoute = "/user/uuid" UserUUIDWithParamsRoute = UserUUIDRoute + "/:" + UsernameParam )