本文同步發表於: Sponge Records
由於我們的專案有設計會員系統,本文將會建立創建帳號的功能,包含帳號格式檢查與是否有重複的信箱
這裡會將架構分為 controllers\accountsControllers.go 、 models\accounts.go,透過 main.go 寫的路由呼叫 accountsControllers.go 再透過 accounts.go 執行邏輯判斷與實作
我們將會實作 controllers\accountsControllers.go 中的 CreateAccount,透過這個函數先解讀 json 格式的請求,並且驗證正確性,驗證完成後 call models\accounts.go 做事
controllers\accountsControllers.go
package controllers
import (
	"net/http"
	"encoding/json"
	"golang-api/models"
	u "golang-api/utils"
)
//創建帳號的函數
var CreateAccount = func(w http.ResponseWriter, r *http.Request) {
	account := &models.Account{}//引用 accounts.go
	err := json.NewDecoder(r.Body).Decode(account)//解析傳入的 json 請求
	//如果輸入的請求錯誤
	if err != nil {
		u.Respond(w, u.Message(false, "Invalid request"))
		return
	}
	resp := account.Create() //呼叫 accounts.go 透過傳入的資料創建帳號
	u.Respond(w, resp)
}
我們將主要的邏輯放置在這裡,models\accounts.go 會包含驗證輸入的資料內容格式是否正確,如信箱是否有含有 @
與透過 orm 工具與資料庫溝通
models\accounts.go
package models
import (
	u "golang-api/utils" // 開頭的 u 代表用 u 來引用他
	"os"
	"strings"
	"github.com/dgrijalva/jwt-go"
	"github.com/jinzhu/gorm"
	"golang.org/x/crypto/bcrypt"
)
//JWT 結構
type Token struct {
	UserId uint
	jwt.StandardClaims
}
//帳號結構
type Account struct {
	gorm.Model
	Email    string `json:"email"`
	Password string `json:"password"`
	Token    string `json:"token";sql:"-"`
}
//驗證傳入訊息
func (account *Account) Validate() (map[string]interface{}, bool) {
	//如果傳入的 email 沒有含 @,回傳信箱格式錯誤
	if !strings.Contains(account.Email, "@") {
		return u.Message(false, "Email format error"), false
	}
    //如果密碼小於8位數,回傳帳號格式錯誤
	if len(account.Password) < 8 {
		return u.Message(false, "Password format error"), false
	}
	//認證 Email 是否存在	
	temp := &Account{}
	
	err := GetDB().Table("accounts").Where("email = ?", account.Email).First(temp).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return u.Message(false, "Connection error"), false
	}
    //如果 Email 已存在,回傳已被使用
	if temp.Email != "" {
		return u.Message(false, "Email has been used"), false
	}
	return u.Message(false, "Requirement passed"), true
}
//帳號創立
func (account *Account) Create() map[string]interface{} {
	if resp, ok := account.Validate(); !ok {
		return resp
	}
	hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(account.Password), bcrypt.DefaultCost)
	account.Password = string(hashedPassword)
	GetDB().Create(account)
	if account.ID <= 0 {
		return u.Message(false, "Failed to create account, connection error.")
	}
	//產生 jwt
	tk := &Token{UserId: account.ID}
	token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), tk)
	tokenString, _ := token.SignedString([]byte(os.Getenv("token_password")))
	account.Token = tokenString
	account.Password = "" 
    //創建完成
	response := u.Message(true, "Account has been created")
	response["account"] = account
	return response
}
下回將繼續進行會員系統設計,實作帳號登入功能,在 controllers\accountsControllers.go 、 models\accounts.go 添加新的程式碼以達到登入的目的