package controllers import ( "fmt" "log" "net/http" "smt/models" "time" "github.com/gin-gonic/gin" ) type RetrieveInput struct { SecretId int `json:"secretId"` DeviceName string `json:"deviceName"` DeviceCategory string `json:"deviceCategory"` UserName string `json:"userName"` SafeId int `json:"safeId"` SafeName string `json:"safeName"` } type ListSecret struct { SecretId int `db:"SecretId" json:"secretId"` SafeId int `db:"SafeId" json:"safeId"` DeviceName string `db:"DeviceName" json:"deviceName"` DeviceCategory string `db:"DeviceCategory" json:"deviceCategory"` UserName string `db:"UserName" json:"userName"` Secret string `db:"Secret" json:"-"` LastUpdated time.Time `db:"LastUpdated" json:"lastUpdated"` } func RetrieveSecret(c *gin.Context) { var input RetrieveInput // Validate the input matches our struct if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } log.Printf("RetrieveSecret received JSON input '%v'\n", input) // Populate fields s := models.Secret{} s.DeviceName = input.DeviceName s.DeviceCategory = input.DeviceCategory s.UserName = input.UserName if input.SecretId > 0 { s.SecretId = input.SecretId } retrieveSpecifiedSecret(&s, c) } func RetrieveSecretByDevicename(c *gin.Context) { DeviceName := c.Param("devicename") if DeviceName == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "no devicename value specified"}) return } // Create object based on specified data s := models.Secret{DeviceName: DeviceName} //s.DeviceName = DeviceName retrieveSpecifiedSecret(&s, c) } func RetrieveSecretByDevicecategory(c *gin.Context) { DeviceCategory := c.Param("devicecategory") if DeviceCategory == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "no devicecategory value specified"}) return } // Create object based on specified data s := models.Secret{DeviceCategory: DeviceCategory} retrieveSpecifiedSecret(&s, c) } func RetrieveSecretByUsername(c *gin.Context) { userName := c.Param("username") if userName == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "no username value specified"}) return } // Create object based on specified data s := models.Secret{UserName: userName} retrieveSpecifiedSecret(&s, c) } func retrieveSpecifiedSecret(s *models.Secret, c *gin.Context) { var UserId int var results []models.Secret // Get userId that we stored in the context earlier if val, ok := c.Get("user-id"); !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"}) return } else { UserId = val.(int) } // Work out which safe to query for this user if the safe was not specified safeList, err := models.UserGetSafesAllowed(int(UserId)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user safes"}) return } // If there was only one result then just use that if len(safeList) == 0 { errString := "no matching secret or user has no access to specified secret" log.Printf("retrieveSpecifiedSecret %s\n", errString) c.JSON(http.StatusBadRequest, gin.H{"error": errString}) return } else if len(safeList) == 1 { s.SafeId = safeList[0].SafeId results, err = models.SecretsGetFromMultipleSafes(s, []int{s.SafeId}) } else { // Create a list of all the safes this user can access var safeIds []int for _, safe := range safeList { safeIds = append(safeIds, safe.SafeId) } results, err = models.SecretsGetFromMultipleSafes(s, safeIds) } if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if len(results) == 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "found no matching secrets"}) return } // Create audit record for results for i := range results { a := models.Audit{ UserId: UserId, SecretId: results[i].SecretId, IpAddress: c.ClientIP(), EventText: fmt.Sprintf("User '%s' retrieved SecretId %d", safeList[0].User.UserName, results[i].SecretId), } a.AuditLogAdd() } // output results as json c.JSON(http.StatusOK, gin.H{"message": "success", "data": results, "count": len(results)}) } func ListSecrets(c *gin.Context) { var UserId int var results []ListSecret //var results []models.Secret s := models.Secret{} // Get userId that we stored in the context earlier if val, ok := c.Get("user-id"); !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"}) return } else { UserId = val.(int) } secretList, err := models.SecretsGetAllowed(&s, UserId) if err != nil { errString := fmt.Sprintf("error getting allowed secrets : '%s'", err) log.Printf("ListSecrets %s\n", errString) c.JSON(http.StatusBadRequest, gin.H{"error": errString}) return } // Extract the normal secret fields from the allowed list for _, secret := range secretList { results = append(results, ListSecret(secret.Secret)) } // Create audit record a := models.Audit{ UserId: UserId, IpAddress: c.ClientIP(), EventText: fmt.Sprintf("Listed %d secrets accessible to user", len(results)), } a.AuditLogAdd() // output results as json c.JSON(http.StatusOK, gin.H{"message": "success", "data": results, "count": len(results)}) }