package auth import ( "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" "kumoly.io/kumoly/app/errors" "kumoly.io/kumoly/app/history" "kumoly.io/kumoly/app/server" ) func ApiGrps(c *gin.Context) { grps := []Group{} var result *gorm.DB if ACHas(c, SYSTEM) { result = DB.Find(&grps) } else { result = DB.Where("name not like ?", SYS_AUTH_PREFIX+"%").Find(&grps) } if result.Error != nil { panic(result.Error) } server.Res(c, &server.Response{Data: grps}) } type apiGrpNewReq struct { Name string `json:"name" example:"user" binding:"required"` DisplayName string `json:"display_name"` Description string `json:"description"` } func ApiGrpNew(c *gin.Context) { var data apiGrpNewReq if err := c.ShouldBindJSON(&data); err != nil { panic(err) } if (strings.HasPrefix(data.Name, SYS_AUTH_PREFIX) || data.Name == sys_user) && !ACHas(c, ADMIN) { panic(errors.ErrorForbidden) } grp := &Group{ Name: data.Name, Description: data.Description, DisplayName: data.DisplayName, } if err := DB.Create(grp).Error; err != nil { panic(err) } history.Send(history.Info().Nm("Create"). Bd(data).Grp(data.Name).Scp("grp"). Iss(c.GetString(GinUserKey)). Msgf("Create group %v", data.Name)) server.Res(c, &server.Response{Data: grp}) } type apiGrpUpdateReq struct { ID uint `json:"id" binding:"required"` Name string `json:"name" binding:"required"` DisplayName string `json:"display_name"` Description string `json:"description"` } func ApiGrpUpdate(c *gin.Context) { fetch := c.Query("fetch") var data apiGrpUpdateReq if err := c.ShouldBindJSON(&data); err != nil { panic(err) } grp := &Group{} err := DB.First(grp, data.ID).Error if err != nil { panic(errors.NewError(404, err)) } if strings.HasPrefix(grp.Name, SYS_AUTH_PREFIX) { panic(errors.ErrorForbidden) } if !ACHas(c, ADMIN, grp.Name, SYSTEM) { panic(errors.ErrorForbidden) } result := DB.Model(&grp).Updates(map[string]interface{}{ "name": data.Name, "display_name": data.DisplayName, "description": data.Description, }) if result.Error != nil { panic(result.Error) } if fetch != "" && ACHas(c, ADMIN, SYSTEM) { DB.Preload("Users").Preload("Users.Profile").First(grp, data.ID) } history.Send(history.Info().Nm("Update"). Bd(data).Grp(data.Name).Scp("grp"). Iss(c.GetString(GinUserKey)). Msgf("Update group %v", data.Name)) server.Res(c, &server.Response{Data: grp}) } func ApiGrpDel(c *gin.Context) { id := c.Param("id") if id == "" { panic(errors.ErrorBadRequest) } grp := &Group{} err := DB.First(grp, id).Error if err != nil { panic(errors.NewError(404, err)) } if strings.HasPrefix(grp.Name, SYS_AUTH_PREFIX) && !ACHas(c, ADMIN) { panic(errors.ErrorForbidden) } err = DB.Transaction(func(tx *gorm.DB) error { err = tx.Model(&grp).Association("Users").Clear() if err != nil { return err } err = tx.Delete(grp).Error if err != nil { return err } return nil }) if err != nil { panic(err) } history.Send(history.Info().Nm("Delete"). Bd(grp).Grp(grp.Name).Scp("grp"). Iss(c.GetString(GinUserKey)). Msgf("Delete group %v", grp.Name)) server.Res(c, &server.Response{Data: "ok"}) } func ApiGrpAssign(c *gin.Context) { uid := c.Param("uid") gid := c.Param("gid") if uid == "" || gid == "" { panic(errors.ErrorBadRequest) } usr := &User{} err := DB.Where("id = ?", uid).First(usr).Error if err != nil { panic(errors.NewError(404, err)) } grp := &Group{} err = DB.First(grp, gid).Error if err != nil { panic(errors.NewError(404, err)) } // deny access if !ACHas(c, grp.Name, ADMIN, SYSTEM) { panic(errors.ErrorForbidden) } // only sys can add sys if grp.Name == SYSTEM { if !ACHas(c, SYSTEM) { panic(errors.ErrorForbidden) } } err = DB.Transaction(func(tx *gorm.DB) error { return tx.Model(usr).Association("Groups").Append(grp) }) if err != nil { panic(err) } history.Send(history.Info().Nm("Assign"). Bd(map[string]string{"user": usr.Username, "group": grp.Name}). Grp(grp.Name).Iss(c.GetString(GinUserKey)).Scp("grp"). Msgf("Assigned %v to group %v", usr.Username, grp.Name)) server.Res(c, &server.Response{Data: "ok"}) } func ApiGrpRemove(c *gin.Context) { uid := c.Param("uid") gid := c.Param("gid") if uid == "" || gid == "" { panic(errors.ErrorBadRequest) } usr := &User{} err := DB.Where("id = ?", uid).First(usr).Error if err != nil { panic(errors.NewError(404, err)) } grp := &Group{} err = DB.First(grp, gid).Error if err != nil { panic(errors.NewError(404, err)) } if grp.Name == SYSTEM { if !ACHas(c, SYSTEM) { panic(errors.ErrorForbidden) } } if grp.Name == ADMIN && IsLastAdmin() { panic(ErrorDelLastAdmin) } err = DB.Transaction(func(tx *gorm.DB) error { return tx.Model(usr).Association("Groups").Delete(grp) }) if err != nil { panic(err) } history.Send(history.Info().Nm("Remove"). Bd(map[string]string{"user": usr.Username, "group": grp.Name}). Grp(grp.Name).Iss(c.GetString(GinUserKey)).Scp("grp"). Msgf("Remove %v from group %v", usr.Username, grp.Name)) server.Res(c, &server.Response{Data: "ok"}) }