feat: user & article: dev complete
This commit is contained in:
26
utils/email.go
Normal file
26
utils/email.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jordan-wright/email"
|
||||
"nCovTrack-Backend/global"
|
||||
"net/smtp"
|
||||
)
|
||||
|
||||
func SendEmail(subject string, text string, to ...string) bool {
|
||||
//TODO: add logs
|
||||
e := email.Email{
|
||||
From: "nCovTrack Server<1853633282@qq.com>",
|
||||
To: to,
|
||||
Subject: subject,
|
||||
Text: []byte(text),
|
||||
}
|
||||
err := e.Send(
|
||||
fmt.Sprintf("%s:%d", global.ServerSettings.Email.Host, global.ServerSettings.Email.Port),
|
||||
smtp.PlainAuth("", global.ServerSettings.Email.Account, global.ServerSettings.Email.Password, global.ServerSettings.Email.Host),
|
||||
)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
23
utils/encrypt.go
Normal file
23
utils/encrypt.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func PasswordEncrypt(password string) string {
|
||||
salt := uuid.New().String()[24:]
|
||||
password = password + salt
|
||||
shaRes := hex.EncodeToString(sha256.New().Sum([]byte(password)))
|
||||
encryptPwd := fmt.Sprintf("ncov$%s$%s", shaRes[0:24], salt)
|
||||
return encryptPwd
|
||||
}
|
||||
|
||||
func PasswordCompare(plaintext string, ciphertext string) (ok bool) {
|
||||
salt := ciphertext[30:]
|
||||
password := plaintext + salt
|
||||
shaRes := hex.EncodeToString(sha256.New().Sum([]byte(password)))
|
||||
return shaRes[0:24] == ciphertext[5:29]
|
||||
}
|
||||
17
utils/jwt.go
17
utils/jwt.go
@@ -58,7 +58,7 @@ func RenewToken(tokenStr string) string {
|
||||
}
|
||||
fmt.Println(expireDuration)
|
||||
|
||||
claims["exp"] = time.Now().Add(15 * 24 * time.Hour).Unix()
|
||||
claims["exp"] = time.Now().Add(global.TOKEN_EXPIRE_DAYS * 24 * time.Hour).Unix()
|
||||
token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenStr, err = token.SignedString(JWT_KEY)
|
||||
if err != nil {
|
||||
@@ -66,3 +66,18 @@ func RenewToken(tokenStr string) string {
|
||||
}
|
||||
return tokenStr
|
||||
}
|
||||
|
||||
func ParseClaims(tokenStr string) jwt.MapClaims {
|
||||
token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) {
|
||||
return JWT_KEY, nil
|
||||
})
|
||||
if err != nil {
|
||||
switch err.(*jwt.ValidationError).Errors {
|
||||
case jwt.ValidationErrorSignatureInvalid:
|
||||
return nil
|
||||
case jwt.ValidationErrorIssuedAt:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return token.Claims.(jwt.MapClaims)
|
||||
}
|
||||
|
||||
14
utils/models.go
Normal file
14
utils/models.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package utils
|
||||
|
||||
type UtilRequestInfo struct {
|
||||
Url string
|
||||
Header string
|
||||
Body string
|
||||
Timeout int
|
||||
}
|
||||
|
||||
type GinResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg interface{} `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
67
utils/orm.go
67
utils/orm.go
@@ -1,67 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"gorm.io/gorm/clause"
|
||||
"nCovTrack-Backend/global"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
var colNameReg, _ = regexp.Compile(".*column:(.*);?")
|
||||
var uniqueKeyReg, _ = regexp.Compile(".*(primaryKey|unique).*")
|
||||
|
||||
func getNotZeroFields[T any](model T) []string {
|
||||
t := reflect.TypeOf(model)
|
||||
v := reflect.ValueOf(model)
|
||||
var notZeroFields []string
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
if !v.Field(i).IsZero() {
|
||||
colName := colNameReg.FindSubmatch([]byte(t.Field(i).Tag.Get("gorm")))
|
||||
if len(colName) != 2 {
|
||||
panic("Model Tag regex error")
|
||||
}
|
||||
notZeroFields = append(notZeroFields, string(colName[1]))
|
||||
}
|
||||
}
|
||||
return notZeroFields
|
||||
}
|
||||
|
||||
func Upsert[T any](model *T, forceUpdateFiled ...string) (ok bool) {
|
||||
t := reflect.TypeOf(model).Elem()
|
||||
v := reflect.ValueOf(model).Elem()
|
||||
var uniqueKeyField []clause.Column
|
||||
notZeroField := NewSet(forceUpdateFiled...).Add("modify_time")
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
gormTag := t.Field(i).Tag.Get("gorm")
|
||||
if uniqueKey(gormTag) {
|
||||
uniqueKeyField = append(uniqueKeyField, clause.Column{Name: columnName(gormTag)})
|
||||
continue
|
||||
}
|
||||
if !v.Field(i).IsZero() {
|
||||
notZeroField.Add(columnName(gormTag))
|
||||
} else if t.Field(i).Type.Name() == "Time" {
|
||||
v.Field(i).Set(reflect.ValueOf(time.Now()))
|
||||
}
|
||||
}
|
||||
tx := global.Db.Clauses(clause.OnConflict{
|
||||
Columns: uniqueKeyField,
|
||||
DoUpdates: clause.AssignmentColumns(notZeroField.ToSlice()),
|
||||
}, clause.Returning{}).Create(model)
|
||||
if tx.Error != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func columnName(gormTag string) string {
|
||||
colNames := colNameReg.FindSubmatch([]byte(gormTag))
|
||||
if len(colNames) != 2 {
|
||||
panic("Model tag regex error")
|
||||
}
|
||||
return string(colNames[1])
|
||||
}
|
||||
|
||||
func uniqueKey(gormTag string) bool {
|
||||
return uniqueKeyReg.Match([]byte(gormTag))
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package utils
|
||||
@@ -1,51 +1,26 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/models"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
SUCCESS = "Success"
|
||||
BAD_REQUEST = "Bad Request"
|
||||
DATA_NOT_FOUND = "Data not Found"
|
||||
STATUS_DATA_NOT_FOUND = 210
|
||||
SUCCESS = "Success"
|
||||
)
|
||||
|
||||
func Success(c *gin.Context, status int, code int, msg interface{}, data interface{}) {
|
||||
c.JSON(http.StatusOK, models.GinResponse{Code: code, Msg: msg, Data: data})
|
||||
c.JSON(http.StatusOK, GinResponse{Code: code, Msg: msg, Data: data})
|
||||
}
|
||||
|
||||
func Error(c *gin.Context, status int, code int, msg interface{}, data interface{}) {
|
||||
c.JSON(status, models.GinResponse{Code: code, Msg: msg, Data: data})
|
||||
c.JSON(status, GinResponse{Code: code, Msg: msg, Data: data})
|
||||
}
|
||||
|
||||
func Succ(c *gin.Context, data interface{}) {
|
||||
Success(c, http.StatusOK, http.StatusOK, SUCCESS, data)
|
||||
}
|
||||
|
||||
func DataNotFound(c *gin.Context, data interface{}) {
|
||||
Success(c, http.StatusOK, STATUS_DATA_NOT_FOUND, DATA_NOT_FOUND, data)
|
||||
}
|
||||
|
||||
func Err(c *gin.Context, status int, code int, msg interface{}) {
|
||||
Error(c, status, code, msg, nil)
|
||||
}
|
||||
|
||||
func ServerError(c *gin.Context, code int, msg interface{}) {
|
||||
Err(c, http.StatusInternalServerError, code, msg)
|
||||
}
|
||||
|
||||
func ServerErr(c *gin.Context, msg interface{}) {
|
||||
ServerError(c, http.StatusInternalServerError, msg)
|
||||
}
|
||||
|
||||
func RequestError(c *gin.Context, code int, data interface{}) {
|
||||
Error(c, http.StatusBadRequest, code, BAD_REQUEST, data)
|
||||
}
|
||||
|
||||
func RequestErr(c *gin.Context, data interface{}) {
|
||||
RequestError(c, http.StatusBadRequest, data)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package utils
|
||||
|
||||
type void struct{}
|
||||
|
||||
// This is set with generic
|
||||
|
||||
type Set[T comparable] struct {
|
||||
setMap map[T]void
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package utils
|
||||
@@ -4,6 +4,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func FormateDate(date time.Time) string {
|
||||
func FormatDate(date time.Time) string {
|
||||
return date.Format("06-01-02")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user