diff --git a/cmd/laas/docs/docs.go b/cmd/laas/docs/docs.go index bb47ccd..2d0f22c 100644 --- a/cmd/laas/docs/docs.go +++ b/cmd/laas/docs/docs.go @@ -1594,6 +1594,9 @@ const docTemplate = `{ "models.Audit": { "type": "object", "properties": { + "entity": { + "type": "object" + }, "id": { "type": "integer", "example": 456 @@ -1604,12 +1607,19 @@ const docTemplate = `{ }, "type": { "type": "string", + "enum": [ + "obligation", + "license" + ], "example": "license" }, "type_id": { "type": "integer", "example": 34 }, + "user": { + "$ref": "#/definitions/models.User" + }, "user_id": { "type": "integer", "example": 123 @@ -2553,7 +2563,6 @@ const docTemplate = `{ "models.User": { "type": "object", "required": [ - "password", "userlevel", "username" ], @@ -2562,9 +2571,6 @@ const docTemplate = `{ "type": "integer", "example": 123 }, - "password": { - "type": "string" - }, "userlevel": { "type": "string", "example": "admin" @@ -2584,7 +2590,8 @@ const docTemplate = `{ ], "properties": { "password": { - "type": "string" + "type": "string", + "example": "fossy" }, "userlevel": { "type": "string", @@ -2604,7 +2611,8 @@ const docTemplate = `{ ], "properties": { "password": { - "type": "string" + "type": "string", + "example": "fossy" }, "username": { "type": "string", diff --git a/cmd/laas/docs/swagger.json b/cmd/laas/docs/swagger.json index 553e0b0..8ebc341 100644 --- a/cmd/laas/docs/swagger.json +++ b/cmd/laas/docs/swagger.json @@ -1587,6 +1587,9 @@ "models.Audit": { "type": "object", "properties": { + "entity": { + "type": "object" + }, "id": { "type": "integer", "example": 456 @@ -1597,12 +1600,19 @@ }, "type": { "type": "string", + "enum": [ + "obligation", + "license" + ], "example": "license" }, "type_id": { "type": "integer", "example": 34 }, + "user": { + "$ref": "#/definitions/models.User" + }, "user_id": { "type": "integer", "example": 123 @@ -2546,7 +2556,6 @@ "models.User": { "type": "object", "required": [ - "password", "userlevel", "username" ], @@ -2555,9 +2564,6 @@ "type": "integer", "example": 123 }, - "password": { - "type": "string" - }, "userlevel": { "type": "string", "example": "admin" @@ -2577,7 +2583,8 @@ ], "properties": { "password": { - "type": "string" + "type": "string", + "example": "fossy" }, "userlevel": { "type": "string", @@ -2597,7 +2604,8 @@ ], "properties": { "password": { - "type": "string" + "type": "string", + "example": "fossy" }, "username": { "type": "string", diff --git a/cmd/laas/docs/swagger.yaml b/cmd/laas/docs/swagger.yaml index eecbb95..5ec108e 100644 --- a/cmd/laas/docs/swagger.yaml +++ b/cmd/laas/docs/swagger.yaml @@ -4,6 +4,8 @@ definitions: type: object models.Audit: properties: + entity: + type: object id: example: 456 type: integer @@ -11,11 +13,16 @@ definitions: example: "2023-12-01T18:10:25.00+05:30" type: string type: + enum: + - obligation + - license example: license type: string type_id: example: 34 type: integer + user: + $ref: '#/definitions/models.User' user_id: example: 123 type: integer @@ -694,8 +701,6 @@ definitions: id: example: 123 type: integer - password: - type: string userlevel: example: admin type: string @@ -703,13 +708,13 @@ definitions: example: fossy type: string required: - - password - userlevel - username type: object models.UserInput: properties: password: + example: fossy type: string userlevel: example: admin @@ -725,6 +730,7 @@ definitions: models.UserLogin: properties: password: + example: fossy type: string username: example: fossy diff --git a/pkg/api/audit.go b/pkg/api/audit.go index fe2a471..b81419a 100644 --- a/pkg/api/audit.go +++ b/pkg/api/audit.go @@ -31,12 +31,13 @@ import ( // @Security ApiKeyAuth // @Router /audits [get] func GetAllAudit(c *gin.Context) { - var audit []models.Audit - query := db.DB.Model(&models.Audit{}) + var audits []models.Audit + + query := db.DB.Model(&models.Audit{}).Preload("User") _ = utils.PreparePaginateResponse(c, query, &models.AuditResponse{}) - if err := query.Order("timestamp desc").Find(&audit).Error; err != nil { + if err := query.Order("timestamp desc").Find(&audits).Error; err != nil { er := models.LicenseError{ Status: http.StatusInternalServerError, Message: "unable to fetch audits", @@ -47,11 +48,17 @@ func GetAllAudit(c *gin.Context) { c.JSON(http.StatusInternalServerError, er) return } + + for i := 0; i < len(audits); i++ { + if err := getAuditEntity(c, &audits[i]); err != nil { + return + } + } res := models.AuditResponse{ - Data: audit, + Data: audits, Status: http.StatusOK, Meta: &models.PaginationMeta{ - ResourceCount: len(audit), + ResourceCount: len(audits), }, } @@ -80,7 +87,7 @@ func GetAudit(c *gin.Context) { return } - if err := db.DB.Where(models.Audit{Id: parsedId}).First(&audit).Error; err != nil { + if err := db.DB.Preload("User").Where(&models.Audit{Id: parsedId}).First(&audit).Error; err != nil { er := models.LicenseError{ Status: http.StatusNotFound, Message: "no audit with such id exists", @@ -91,6 +98,11 @@ func GetAudit(c *gin.Context) { c.JSON(http.StatusNotFound, er) return } + + if err := getAuditEntity(c, &audit); err != nil { + return + } + res := models.AuditResponse{ Data: []models.Audit{audit}, Status: http.StatusOK, @@ -220,3 +232,35 @@ func GetChangeLogbyId(c *gin.Context) { } c.JSON(http.StatusOK, res) } + +// getAuditEntity is an utility function to fetch obligation or license associated with an audit +func getAuditEntity(c *gin.Context, audit *models.Audit) error { + if audit.Type == "license" || audit.Type == "License" { + audit.Entity = &models.LicenseDB{} + if err := db.DB.Where(&models.LicenseDB{Id: audit.TypeId}).First(&audit.Entity).Error; err != nil { + er := models.LicenseError{ + Status: http.StatusNotFound, + Message: "license corresponding with this audit does not exist", + Error: err.Error(), + Path: c.Request.URL.Path, + Timestamp: time.Now().Format(time.RFC3339), + } + c.JSON(http.StatusNotFound, er) + return err + } + } else if audit.Type == "obligation" || audit.Type == "Obligation" { + audit.Entity = &models.Obligation{} + if err := db.DB.Where(&models.Obligation{Id: audit.TypeId}).First(&audit.Entity).Error; err != nil { + er := models.LicenseError{ + Status: http.StatusNotFound, + Message: "obligation corresponding with this audit does not exist", + Error: err.Error(), + Path: c.Request.URL.Path, + Timestamp: time.Now().Format(time.RFC3339), + } + c.JSON(http.StatusNotFound, er) + return err + } + } + return nil +} diff --git a/pkg/api/licenses.go b/pkg/api/licenses.go index c272b00..db047f7 100644 --- a/pkg/api/licenses.go +++ b/pkg/api/licenses.go @@ -561,10 +561,6 @@ func UpdateLicense(c *gin.Context) { // addChangelogsForLicenseUpdate adds changelogs for the updated fields on license update func addChangelogsForLicenseUpdate(tx *gorm.DB, username string, newLicense, oldLicense *models.LicenseDB) error { - var user models.User - if err := tx.Where(models.User{Username: username}).First(&user).Error; err != nil { - return err - } var changes []models.ChangeLog if oldLicense.Fullname != newLicense.Fullname { diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 4f01eaa..0ca831d 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -311,14 +311,8 @@ func generateToken(user models.User) (string, error) { return "", err } - jwtUser := models.JWTUser{ - Id: user.Id, - Username: user.Username, - Userlevel: user.Userlevel, - } - claims := jwt.MapClaims{} - claims["user"] = jwtUser + claims["user"] = user claims["nbf"] = time.Now().Unix() claims["exp"] = time.Now().Add(time.Hour * time.Duration(tokenLifespan)).Unix() token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) diff --git a/pkg/models/types.go b/pkg/models/types.go index 5d58a40..f2cd5cc 100644 --- a/pkg/models/types.go +++ b/pkg/models/types.go @@ -256,25 +256,18 @@ type User struct { Id int64 `json:"id" gorm:"primary_key" example:"123"` Username string `json:"username" gorm:"unique;not null" binding:"required" example:"fossy"` Userlevel string `json:"userlevel" binding:"required" example:"admin"` - Userpassword *string `json:"password,omitempty" binding:"required"` -} - -// JWTUser struct is representation of user information in JWT. -type JWTUser struct { - Id int64 `json:"id"` - Username string `json:"username"` - Userlevel string `json:"userlevel"` + Userpassword *string `json:"-"` } type UserInput struct { Username string `json:"username" gorm:"unique;not null" binding:"required" example:"fossy"` Userlevel string `json:"userlevel" binding:"required" example:"admin"` - Userpassword *string `json:"password,omitempty" binding:"required"` + Userpassword *string `json:"password,omitempty" binding:"required" example:"fossy"` } type UserLogin struct { Username string `json:"username" binding:"required" example:"fossy"` - Userpassword string `json:"password" binding:"required"` + Userpassword string `json:"password" binding:"required" example:"fossy"` } // UserResponse struct is representation of design API response of user. @@ -296,10 +289,11 @@ type SearchLicense struct { type Audit struct { Id int64 `json:"id" gorm:"primary_key" example:"456"` UserId int64 `json:"user_id" example:"123"` - User User `gorm:"foreignKey:UserId;references:Id" json:"-"` - TypeId int64 `json:"type_id" example:"34"` + User User `gorm:"foreignKey:UserId;references:Id" json:"user"` Timestamp time.Time `json:"timestamp" example:"2023-12-01T18:10:25.00+05:30"` - Type string `json:"type" example:"license"` + Type string `json:"type" enums:"obligation,license" example:"license"` + TypeId int64 `json:"type_id" example:"34"` + Entity interface{} `json:"entity" gorm:"-" swaggertype:"object"` ChangeLogs []ChangeLog `json:"-"` }