package handler
import (
"github.com/gin-gonic/gin"
"sshfortress/model"
)
func MachineAll(c *gin.Context) {
q := model.MachineQ{}
err := c.ShouldBindQuery(&q)
if handleError(c, err) {
return
}
mdl := q.Machine
query := &(q.PaginationQ)
thisU, err := mwJwtUser(c)
list, total, err := mdl.All(query, thisU)
if handleError(c, err) {
return
}
jsonPagination(c, list, total, query)
}
func MachineOne(c *gin.Context) {
var mdl model.Machine
var err error
id, err := parseParamID(c)
if handleError(c, err) {
return
}
mdl.Id = id
err = mdl.One()
if handleError(c, err) {
return
}
jsonData(c, mdl)
}
func MachineCreate(c *gin.Context) {
var mdl model.Machine
err := c.ShouldBind(&mdl)
if handleError(c, err) {
return
}
err = mdl.Create()
if handleError(c, err) {
return
}
jsonData(c, mdl)
}
func MachineUpdate(c *gin.Context) {
var mdl model.Machine
err := c.ShouldBind(&mdl)
if handleError(c, err) {
return
}
err = mdl.Update()
if handleError(c, err) {
return
}
jsonSuccess(c)
}
func MachineDelete(c *gin.Context) {
u, err := mwJwtUser(c)
if handleError(c, err) {
return
}
var mdl model.Machine
id, err := parseParamID(c)
if handleError(c, err) {
return
}
mdl.Id = id
err = mdl.Delete(u)
if handleError(c, err) {
return
}
jsonSuccess(c)
}
//MachineHardware 获取机器的物理信息
func MachineHardware(c *gin.Context) {
id, err := parseParamID(c)
if handleError(c, err) {
return
}
hi, err := model.CreateHardwareInfo(id)
if handleError(c, err) {
return
}
jsonData(c, hi)
}
数据model
package model
import (
"errors"
)
type MachineQ struct {
Machine
PaginationQ
}
type Machine struct {
BaseModel
Name string `gorm:"type:varchar(50);unique_index" json:"name" form:"name"`
SshIp string `json:"ssh_ip" form:"ssh_ip"`
SshPort uint `json:"ssh_port"`
LanIp string `json:"lan_ip" form:"lan_ip"`
WanIp string `json:"wan_ip" form:"wan_ip"`
Cate uint `gorm:"default:'2'" json:"cate" comment:"机器性质:2:无外网ip 4:外网可以访问"`
ClusterSshId uint `gorm:"index" json:"cluster_ssh_id" comment:"关联集群管理ssh账号"`
ClusterJumperId *uint `gorm:"index,default:'0'" json:"cluster_jumper_id" form:"cluster_jumper_id" comment:"集群代理ID 关联clusterJumper表"`
UserId uint `gorm:"index" json:"user_id" comment:"机器的添加者"`
Status uint `gorm:"default:'0'" json:"status" form:"status" comment:"机器状态 0-未知 2-连接错误 4-ssh认证错误 8-正常 "`
User User `gorm:"association_autoupdate:false;association_autocreate:false" json:"user"`
ClusterSsh *ClusterSsh `gorm:"association_autoupdate:false;association_autocreate:false" json:"cluster_ssh,omitempty"`
ClusterJumper *ClusterJumper `gorm:"association_autoupdate:false;association_autocreate:false" json:"cluster_jumper,omitempty"`
//Hardware HardwareInfo `gorm:"type:json" json:"hardware"`
}
func (m *Machine) AfterFind() (err error) {
return
}
//One
func (m *Machine) One() error {
return crudOne(m)
}
//All
func (m Machine) All(q *PaginationQ, user *User) (list *[]Machine, total uint, err error) {
tx := db.Model(m).Preload("ClusterSsh").Preload("ClusterJumper") //.Where("ancestor_path like ?", m.qAncetorPath())
list = &[]Machine{}
//role ==2
//显示全部的机器
if m.Name != "" {
tx = tx.Where("`name` like ?", "%"+m.Name+"%")
}
if m.SshIp != "" {
tx = tx.Where("`ssh_ip` like ?", "%"+m.SshIp+"%")
}
if m.WanIp != "" {
tx = tx.Where("`wan_ip` like ?", "%"+m.WanIp+"%")
}
if m.LanIp != "" {
tx = tx.Where("`lan_ip` like ?", "%"+m.LanIp+"%")
}
if user.Role == 4 {
//普通用户显示自由机器和授权的机器
machineIds := []uint{}
err = db.Model(MachineUser{}).Where("user_id = ?", user.Id).Pluck("machine_id", &machineIds).Error
if err != nil {
return nil, 0, err
}
if len(machineIds) > 0 {
tx = tx.Where("`user_id` = ? OR `id` in (?)", user.Id, machineIds)
} else {
tx = tx.Where("`user_id` = ?", user.Id)
}
}
total, err = crudAll(q, tx, list)
return
}
//Update
func (m *Machine) Update() (err error) {
if m.Id < 1 {
return errors.New("id必须大于0")
}
return db.Model(m).Update(m).Error
}
//Create
func (m *Machine) Create() (err error) {
m.Id = 0
return db.Create(m).Error
}
//Delete
func (m *Machine) Delete(u *User) (err error) {
if m.Id < 2 {
return errors.New("id必须大于2")
}
//删除用户与机器的关联
err = db.Where("machine_id = ?", m.Id).Delete(MachineUser{}).Error
if err != nil {
return
}
if u.Role == UserRoleAdmin {
return crudDelete(m)
}
err = db.Unscoped().Where("`id` = ? AND `user_id` = ?", m.Id, u.Id).Delete(m).Error
return
}
// handler help
package handler
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
"net/http"
"sshfortress/model"
"sshfortress/stat"
"strconv"
"time"
)
func jsonError(c *gin.Context, msg interface{}) {
stat.GaugeVecApiError.WithLabelValues("API").Inc()
var ms string
switch v := msg.(type) {
case string:
ms = v
case error:
ms = v.Error()
default:
ms = ""
}
c.AbortWithStatusJSON(200, gin.H{"ok": false, "msg": ms})
}
func jsonAuthError(c *gin.Context, msg interface{}) {
c.AbortWithStatusJSON(http.StatusPreconditionFailed, gin.H{"ok": false, "msg": msg})
}
func jsonData(c *gin.Context, data interface{}) {
c.AbortWithStatusJSON(200, gin.H{"ok": true, "data": data})
}
//func jsonPagination(c *gin.Context, list interface{}, total uint, query *model.PaginationQ) {
// c.AbortWithStatusJSON(200, gin.H{"ok": true, "data": list, "total": total, "offset": query.Offset, "limit": query.Size})
//}
func jsonSuccess(c *gin.Context) {
c.AbortWithStatusJSON(200, gin.H{"ok": true, "msg": "success"})
}
func jsonPagination(c *gin.Context, list interface{}, total uint, query *model.PaginationQ) {
c.JSON(200, gin.H{"ok": true, "data": list, "total": total, "page": query.Page, "size": query.Size})
}
func handleError(c *gin.Context, err error) bool {
if err != nil {
//logrus.WithError(err).Error("gin context http handler error")
jsonError(c, err.Error())
return true
}
return false
}
func handlerAuthMiddlewareError(c *gin.Context, err error) bool {
if err != nil {
c.AbortWithStatusJSON(401, gin.H{"msg": err.Error()})
return true
}
return false
}
func wshandleError(err error) bool {
if err != nil {
stat.GaugeVecApiError.WithLabelValues("WS").Inc()
logrus.WithError(err).Error("handler ws ERROR:")
return true
}
return false
}
func wshandleErrorPro(wc *websocket.Conn, err error) bool {
if err != nil {
logrus.WithError(err).Error("ssh-websocket error")
wc.WriteControl(websocket.CloseMessage, []byte(err.Error()), time.Now())
return true
}
return false
}
func parseParamID(c *gin.Context) (uint, error) {
id := c.Param("id")
parseId, err := strconv.ParseUint(id, 10, 32)
if err != nil {
return 0, errors.New("id must be an unsigned int")
}
return uint(parseId), nil
}
func mwJwtUser(c *gin.Context) (*model.User, error) {
uid, err := mwJwtUid(c)
if err != nil {
return nil, err
}
sessionUserKey := fmt.Sprintf("thisUser:%d", uid)
vu, ok := c.Get(sessionUserKey)
if ok {
tu, okay := vu.(model.User)
if okay {
return &tu, nil
} else {
return nil, fmt.Errorf("gin.context %s 不是model.User", sessionUserKey)
}
}
//session context 没有值则mysql数据库中取,并设置context 值
user := model.User{}
user.Id = uid
err = user.One()
if err != nil {
return nil, fmt.Errorf("context can not get user of %d,error:%s", user.Id, err)
}
c.Set(sessionUserKey, user)
return &user, nil
}
func mwJwtUid(c *gin.Context) (uint, error) {
return getCtxUint(c, jwtCtxUidKey)
}
func getCtxUint(c *gin.Context, key string) (uint, error) {
v, exist := c.Get(key)
if !exist {
return 0, fmt.Errorf("context has no value for %s", key)
}
uintV, ok := v.(uint)
if ok {
return uintV, nil
}
return 0, fmt.Errorf("key for %s in gin.Context value is %v but not a uint type", key, v)
}
func queryUint(c *gin.Context, key string) (v uint, err error) {
sv, ok := c.GetQuery(key)
if !ok {
err = fmt.Errorf("query of %s is not exist", key)
return
}
parseId, err := strconv.ParseUint(sv, 10, 32)
if err != nil {
err = fmt.Errorf("query of %s is not a uint", key)
return
}
return uint(parseId), nil
}
func checkJwtUserAdmin(c *gin.Context) (u *model.User, err error) {
u, err = mwJwtUser(c)
if err != nil {
return
}
if u.Role != model.UserRoleAdmin {
return nil, errors.New("没有管理员权限")
}
return
}
//model help
package model
import (
"errors"
"github.com/jinzhu/gorm"
"time"
)
//PaginationQ gin handler query binding struct
type PaginationQ struct {
Size uint `form:"size" json:"size"`
Page uint `form:"page" json:"page"`
Total uint `json:"total" form:"-"`
Data interface{} `json:"data" form:"-" comment:"data 必须是[]interface{} 指针"`
Ok bool `json:"ok" form:"-"`
}
func (p *PaginationQ) Search(tx *gorm.DB) (err error) {
p.Ok = true
if p.Size == 9999 {
return tx.Find(p.Data).Error
}
if p.Size < 1 {
p.Size = 10
}
if p.Page < 1 {
p.Page = 1
}
var total uint
err = tx.Count(&total).Error
if err != nil {
return err
}
offset := p.Size * (p.Page - 1)
err = tx.Limit(p.Size).Offset(offset).Find(p.Data).Error
if err != nil {
return err
}
p.Total = total
return
}
func crudAll(p *PaginationQ, queryTx *gorm.DB, list interface{}) (uint, error) {
if p.Size == 9999 {
return 0, queryTx.Find(list).Error
}
if p.Size < 1 {
p.Size = 10
}
if p.Page < 1 {
p.Page = 1
}
var total uint
err := queryTx.Count(&total).Error
if err != nil {
return 0, err
}
offset := p.Size * (p.Page - 1)
err = queryTx.Limit(p.Size).Offset(offset).Find(list).Error
if err != nil {
return 0, err
}
return total, err
}
func crudOne(m interface{}) (err error) {
if db.First(m).RecordNotFound() {
return errors.New("resource is not found")
}
return nil
}
func crudDelete(m interface{}) (err error) {
//WARNING When delete a record, you need to ensure it’s primary field has value, and GORM will use the primary key to delete the record, if primary field’s blank, GORM will delete all records for the model
//primary key must be not zero value
db := db.Unscoped().Delete(m)
if err = db.Error; err != nil {
return
}
if db.RowsAffected != 1 {
return errors.New("resource is not found to destroy")
}
return nil
}
func mysqlTime(t time.Time) string {
return t.Format("2006-01-02 15:04:05")
}
标签:return,nil,err,改查,func,error,go,gin From: https://www.cnblogs.com/cheyunhua/p/16929328.html