[ADD]first commit

This commit is contained in:
virus 2020-09-15 12:25:30 +08:00
commit e98c0f3b34
13 changed files with 469 additions and 0 deletions

18
conf/app.ini Normal file
View File

@ -0,0 +1,18 @@
RUN_MODE = debug
[app]
PAGE_SIZE = 10
JWT_SECRET = 23347$040412
[server]
HTTP_PORT = 8001
READ_TIMEOUT = 60
WRITE_TIMEOUT = 60
[database]
TYPE = mysql
USER = root
PASSWORD = a19960425
HOST = localhost:3306
NAME = blog
TABLE_PREFIX = blog_

40
go.mod Normal file
View File

@ -0,0 +1,40 @@
module github.com/go-pripro/shop
go 1.15
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-gonic/gin v1.6.3
github.com/go-ini/ini v1.61.0
github.com/go-playground/validator/v10 v10.3.0 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/jinzhu/gorm v1.9.16
github.com/json-iterator/go v1.1.10 // indirect
github.com/lib/pq v1.2.0 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
github.com/ugorji/go v1.1.8 // indirect
github.com/unknwon/com v1.0.1
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/ini.v1 v1.61.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
replace (
github.com/go-pripro/shop/conf => ./shop/pkg/conf
github.com/go-pripro/shop/docs => ./shop/docs
github.com/go-pripro/shop/middleware => ./shop/middleware
github.com/go-pripro/shop/models => ./shop/models
github.com/go-pripro/shop/pkg/e => ./shop/pkg/e
github.com/go-pripro/shop/pkg/logging => ./shop/pkg/logging
github.com/go-pripro/shop/pkg/setting => ./shop/pkg/setting
github.com/go-pripro/shop/pkg/util => ./shop/pkg/util
github.com/go-pripro/shop/routers => ./shop/routers
)

22
main.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"fmt"
"github.com/go-pripro/shop/pkg/setting"
"github.com/go-pripro/shop/routers"
"net/http"
)
func main() {
router := routers.InitRouter()
s := &http.Server{
Addr: fmt.Sprintf(":%d", setting.HTTPPort),
Handler: router,
ReadTimeout: setting.ReadTimeout,
WriteTimeout: setting.WriteTimeout,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
}

38
middleware/jwt/jwt.go Normal file
View File

@ -0,0 +1,38 @@
package jwt
import (
"github.com/gin-gonic/gin"
"github.com/go-pripro/shop/pkg/e"
"github.com/go-pripro/shop/pkg/util"
"net/http"
"time"
)
func JWT() gin.HandlerFunc {
return func(c *gin.Context) {
var code int
var data interface{}
code = e.SUCCESS
token := c.Query("token")
if token == "" {
code = e.INVALID_PARAMS
} else {
claims, err := util.ParseToken(token)
if err != nil {
code = e.ERROR_AUTH_CHECK_TOKEN_FAIL
} else if time.Now().Unix() > claims.ExpiresAt {
code = e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT
}
}
if code != e.SUCCESS {
c.JSON(http.StatusUnauthorized, gin.H{
"code" : code,
"msg" : e.GetMsg(code),
"data" : data,
})
c.Abort()
return
}
c.Next()
}
}

60
models/models.go Normal file
View File

@ -0,0 +1,60 @@
package models
import (
"fmt"
"github.com/go-pripro/shop/pkg/setting"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"log"
)
var db *gorm.DB
type Model struct {
ID int `gorm:"primary_key" json:"id"`
CreatedOn int `json:"created_on"`
ModifiedOn int `json:"modified_on"`
}
func init() {
var (
err error
dbType, dbName, user, password, host, tablePrefix string
)
sec, err := setting.Cfg.GetSection("database")
if err != nil {
log.Fatal(2, "Fail to get section 'database': %v", err)
}
dbType = sec.Key("TYPE").String()
dbName = sec.Key("NAME").String()
user = sec.Key("USER").String()
password = sec.Key("PASSWORD").String()
host = sec.Key("HOST").String()
tablePrefix = sec.Key("TABLE_PREFIX").String()
db, err = gorm.Open(dbType, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
user,
password,
host,
dbName))
if err != nil {
log.Println(err)
}
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return tablePrefix + defaultTableName
}
//db.AutoMigrate(&Tag{}, &Article{}, &Auth{})
//db.SingularTable(true)
db.LogMode(true)
db.DB().SetMaxIdleConns(10)
db.DB().SetMaxOpenConns(100)
}
func CloseDB() {
defer db.Close()
}

16
pkg/e/code.go Normal file
View File

@ -0,0 +1,16 @@
package e
const (
SUCCESS = 200
ERROR = 500
INVALID_PARAMS = 400
ERROR_EXIST_TAG = 10001
ERROR_NOT_EXIST_TAG = 10002
ERROR_NOT_EXIST_ARTICLE = 10003
ERROR_AUTH_CHECK_TOKEN_FAIL = 20001
ERROR_AUTH_CHECK_TOKEN_TIMEOUT = 20002
ERROR_AUTH_TOKEN = 20003
ERROR_AUTH = 20004
)

23
pkg/e/msg.go Normal file
View File

@ -0,0 +1,23 @@
package e
var MsgFlags = map[int]string{
SUCCESS: "ok",
ERROR: "fail",
INVALID_PARAMS: "请求参数错误",
ERROR_EXIST_TAG: "已存在该标签名称",
ERROR_NOT_EXIST_TAG: "该标签不存在",
ERROR_NOT_EXIST_ARTICLE: "该文章不存在",
ERROR_AUTH_CHECK_TOKEN_FAIL: "TOKEN鉴权失败",
ERROR_AUTH_CHECK_TOKEN_TIMEOUT: "TOKEN已超时",
ERROR_AUTH_TOKEN: "TOKEN生成失败",
ERROR_AUTH: "TOKEN错误",
}
func GetMsg(code int) string {
msg, ok := MsgFlags[code]
if ok {
return msg
}
return MsgFlags[ERROR]
}

44
pkg/logging/file.go Normal file
View File

@ -0,0 +1,44 @@
package logging
import (
"fmt"
"log"
"os"
"time"
)
var (
LogSavePath = "runtime/logs/"
LogSaveName = "log"
LogFileExt = "log"
TimeFormat = "20060102"
)
func getLogFilePath() string {
return fmt.Sprintf("%s", LogSavePath)
}
func getLogFileFullPath() string {
prefixPath := getLogFilePath()
suffixPath := fmt.Sprintf("%s%s.%s", LogSaveName, time.Now().Format(TimeFormat), LogFileExt)
return fmt.Sprintf("%s%s", prefixPath, suffixPath)
}
func openLogFile(filePath string) *os.File {
_, err := os.Stat(filePath)
switch {
case os.IsNotExist(err):
mkDir()
case os.IsPermission(err):
log.Fatalf("Permission :%v", err)
}
handle, err := os.OpenFile(filePath, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644)
if err != nil {
log.Fatalf("Fail to OpenFile :%v", err)
}
return handle
}
func mkDir() {
dir, _ := os.Getwd()
err := os.MkdirAll(dir + "/" + getLogFilePath(), os.ModePerm)
if err != nil {
panic(err)
}
}

63
pkg/logging/log.go Normal file
View File

@ -0,0 +1,63 @@
package logging
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
)
type Level int
var (
F *os.File
DefaultPrefix = ""
DefaultCallerDepth = 2
logger *log.Logger
logPrefix = ""
levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
)
const (
DEBUG Level = iota
INFO
WARNING
ERROR
FATAL
)
func init() {
filePath := getLogFileFullPath()
F = openLogFile(filePath)
logger = log.New(F, DefaultPrefix, log.LstdFlags)
}
func Debug(v ...interface{}) {
setPrefix(DEBUG)
logger.Println(v)
}
func Info(v ...interface{}) {
setPrefix(INFO)
logger.Println(v)
}
func Warn(v ...interface{}) {
setPrefix(WARNING)
logger.Println(v)
}
func Error(v ...interface{}) {
setPrefix(ERROR)
logger.Println(v)
}
func Fatal(v ...interface{}) {
setPrefix(FATAL)
logger.Fatalln(v)
}
func setPrefix(level Level) {
_, file, line, ok := runtime.Caller(DefaultCallerDepth)
if ok {
logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
} else {
logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
}
logger.SetPrefix(logPrefix)
}

54
pkg/setting/setting.go Normal file
View File

@ -0,0 +1,54 @@
package setting
import (
"github.com/go-ini/ini"
"log"
"time"
)
var Cfg *ini.File
var (
RunMode string
HTTPPort int
ReadTimeout time.Duration
WriteTimeout time.Duration
PageSize int
JwtSecret string
)
func init() {
var err error
Cfg, err = ini.Load("conf/app.ini")
if err != nil {
log.Fatalf("Fail to parse 'conf/app.ini': %v", err)
}
LoadBase()
LoadServer()
LoadApp()
}
func LoadBase() {
RunMode = Cfg.Section("").Key("RUN_MODE").MustString("debug")
}
func LoadServer() {
sec, err := Cfg.GetSection("server")
if err != nil {
log.Fatalf("Fail to get section 'sever' : %v", err)
}
HTTPPort = sec.Key("HTTP_PORT").MustInt(8000)
ReadTimeout = time.Duration(sec.Key("READ_TIMEOUT").MustUint(60)) * time.Second
WriteTimeout = time.Duration(sec.Key("WRITE_TIMEOUT").MustInt(60)) * time.Second
}
func LoadApp() {
sec, err := Cfg.GetSection("app")
if err != nil {
log.Fatalf("Fail to get section 'app':%v", err)
}
JwtSecret = sec.Key("JWT_SECRET").MustString("!@#!@#!@#!@@#!@#")
PageSize = sec.Key("PAGE_SIZE").MustInt(10)
}

45
pkg/util/jwt.go Normal file
View File

@ -0,0 +1,45 @@
package util
import (
jwt "github.com/dgrijalva/jwt-go"
"github.com/go-pripro/shop/pkg/setting"
"time"
)
var jwtSecret = []byte(setting.JwtSecret)
type Claims struct {
Username string `json:"username"`
Password string `json:"password"`
jwt.StandardClaims
}
func GenerateToken(username, password string) (string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(3 * time.Hour)
claims := Claims{
username,
password,
jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: "gin-blog",
},
}
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tokenClaims.SignedString(jwtSecret)
return token, err
}
func ParseToken(token string) (*Claims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if tokenClaims != nil {
if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
return claims, nil
}
}
return nil, err
}

17
pkg/util/pagenation.go Normal file
View File

@ -0,0 +1,17 @@
package util
import (
"github.com/gin-gonic/gin"
"github.com/go-pripro/shop/pkg/setting"
"github.com/unknwon/com"
)
func GetPage(c *gin.Context) int {
result := 0
page, _ := com.StrTo(c.Query("page")).Int()
if page > 0 {
result = (page - 1) * setting.PageSize
}
return result
}

29
routers/router.go Normal file
View File

@ -0,0 +1,29 @@
package routers
import (
"github.com/gin-gonic/gin"
"github.com/go-pripro/shop/pkg/setting"
)
func InitRouter() *gin.Engine {
r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
gin.SetMode(setting.RunMode)
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "test",
})
})
return r
}