iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 10
0
Modern Web

從coding到上線-打造自己的blog系統系列 第 10

Day10 Owner API串接

今天來寫go連上昨天寫的procedure

在database package創建main.go,寫入

// return owner page
func GetOwner(owner string) (*OwnerOut, error) {
	ownerData := &OwnerOut{}
	has, err := db.SQL("call get_owner(?)", owner).Get(ownerData)
	if err != nil {
		return nil, err
	} else if !has {
		return nil, nil
	}
	return ownerData, nil
}

// Update an owner
func CreateOwner(uid, uniquename, nickname, descript string) error {
	return checkAffect(db.Exec("call create_owner(?, ?, ?, ?)", uid, uniquename, nickname, descript))
}

// Update an owner if no need to update uniquename, newuniname should be ""
func UpdateOwner(uid, oid, uniquename, newuniname, nickname, descript string) error {
	return checkResult(db.Exec("call update_owner(?, ?, ?, ?, ?, ?)", uid, oid, uniquename, newuniname, nickname, descript))
}

// delete an owner
func DelOwner(uid, oid, owner string) error {
	return checkAffect(db.Exec("call del_owner(?, ?, ?)", uid, oid, owner))
}

// check affect row is > 0 or not
func checkAffect(res sql.Result, err error) error {
	if err == nil {
		count, err := res.RowsAffected()
		if err == nil {
			if count > 0 {
				// affect success
				return nil
			} else {
				// affect fail
				return ERR_TASK_FAIL
			}
		}
		return err
	}
	return err
}

// check database return error or not
func checkResult(res sql.Result, err error) error {
	if err == nil {
		return nil
	}
	return err
}

解釋:

  • 0 row affect的query在mysql中會return success不會返回錯誤,所以用checkAffect進行包裝,如果沒有改動到資料(where條件不穩吻合),就return錯誤

uid需要從cookie裡面拿出來建立common package,放這專案的通用函式,創建cookie.go寫入

package common

import (
	"app/apperr"
	"app/log"
	"github.com/gin-gonic/gin"
	"net/http"
	"net/url"
)

// get the cookie value
func GetCookieParam(c *gin.Context, name string) (url.Values, error) {
	var (
		accessCookie *http.Cookie
		err          error
	)

	// check cookie
	if accessCookie, err = c.Request.Cookie(name); err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, name + " not found in cookie")
		return nil, err
	}

	// check access
	param, err := url.ParseQuery(accessCookie.Value)
	if err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, name + " parse fail")
		return nil, err
	}

	return param, nil
}

現在把serve/main.go裡把空的owner function補上

func GetOwner(c *gin.Context) {
	// check project exist
	ownerData, err := database.GetOwner(c.Param("owner"))
	if err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error", "database error of getting owner")
		return
	}

	// drop uid
	ownerData.Uid = 0

	meta, err := json.Marshal(ownerData)
	if err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error", "parse json error")
		return
	}

	// return owner with blog
	c.HTML(http.StatusOK, "index", gin.H{
		"meta":        string(meta),
		"title":       ownerData.Nickname,
		"description": ownerData.Description,
		"list":        true,
	})
}

// create a new owner
func CreateOwner(c *gin.Context) {
	// get cookie param
	param, err := common.GetCookieParam(c, "AccessToken");
	if err != nil {
		return
	}

	if err := database.CreateOwner(param.Get("uid"), c.Param("owner"), c.PostForm("nickname"), c.PostForm("descript")); err != nil {
		if err == database.ERR_NAME_CONFLICT {
			log.Warn(c, apperr.ErrWrongArgument, err, "Name conflict of create owner")
		} else if err == database.ERR_TASK_FAIL {
			log.Warn(c, apperr.ErrWrongArgument, err, "put owner fail, please check oid and uid correct")
		} else {
			log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error. please try again", "database error of create owner")
		}
		return
	}

	c.Header("Location", "/.")
	c.Status(http.StatusCreated)
}

// update a new owner
func UpdateOwner(c *gin.Context) {
	// get cookie param
	param, err := common.GetCookieParam(c, "AccessToken");
	if err != nil {
		return
	}

	if err := database.UpdateOwner(param.Get("uid"), c.PostForm("oid"), c.Param("owner"), c.PostForm("newuniname"), c.PostForm("nickname"), c.PostForm("descript")); err != nil {
		if err == database.ERR_NAME_CONFLICT {
			log.Warn(c, apperr.ErrWrongArgument, err, "Name conflict of update owner")
		} else if err == database.ERR_TASK_FAIL {
			log.Warn(c, apperr.ErrWrongArgument, err, "put owner fail, please check oid and uid correct")
		} else {
			log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error. please try again", "database error of update owner")
		}
		return
	}

	c.Header("Location", "/.")
	c.Status(http.StatusCreated)
}

func DelOwner(c *gin.Context) {
	// get cookie param
	param, err := common.GetCookieParam(c, "AccessToken");
	if err != nil {
		return
	}

	err = database.DelOwner( param.Get("uid"), c.PostForm("oid"),c.Param("owner"))
	if err != nil {
		if err == database.ERR_TASK_FAIL {
			log.Warn(c, apperr.ErrWrongArgument, err, "delete owner fail, please check oid and owner name correct")
		} else {
			log.Warn(c, apperr.ErrPermissionDenied, err, "Sorry, something error. please try again", "database error of delete owner")
		}
		return
	}

	if err := os.RemoveAll(setting.Servers["main"].FilePath + "/" + c.PostForm("oid")); err != nil {
		log.Warn(c, apperr.ErrPermissionDenied, err, "something error in delete file")
		return
	}

	c.Status(http.StatusResetContent)
}

總結

owner的API已經完成了,之後要處理巢狀blog比較麻煩的情況

目前的工作環境

.
├── app
│   ├── app
│   ├── apperr
│   │   ├── code.go
│   │   ├── error.go
│   │   └── handle.go
│   ├── common
│   │   └── cookie.go
│   ├── config
│   │   └── app
│   │       ├── app.yaml
│   │       └── error.yaml
│   ├── database
│   │   ├── connect.go
│   │   ├── error.go
│   │   ├── main.go
│   │   └── scheme.go
│   ├── go.mod
│   ├── go.sum
│   ├── logger
│   │   ├── logger.go
│   │   └── logging.go
│   ├── main.go
│   ├── middleware
│   │   ├── error.go
│   │   └── log.go
│   ├── router
│   │   ├── host_switch.go
│   │   └── main.go
│   ├── serve
│   │   ├── main.go
│   │   └── main_test.go
│   ├── setting
│   │   └── setting.go
│   └── util
│       └── debug
│           ├── stack.go
│           └── stack_test.go
└── database
    └── maindata

上一篇
Day9 Owner CRUD Procedure
下一篇
Day11 模板
系列文
從coding到上線-打造自己的blog系統31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言