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")
}






原文地址:http://www.cnblogs.com/cheyunhua/p/16929328.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性