Add Jwt Rewrite Router Add Models Add Auth

dev
aimerforreimu 6 years ago
parent fac23f97d6
commit e53be39e3a
  1. 6
      .gitignore
  2. 18
      README.md
  3. 42
      auxpiAll/all.go
  4. 227
      auxpiAll/all_easyjson.go
  5. 0
      auxpiAll/auxpiRun.log
  6. 6
      auxpiAll/e/code.go
  7. 3
      auxpiAll/e/msg.go
  8. 2
      auxpiAll/logging.go
  9. 31
      bootstrap/Config.go
  10. 15
      controllers/api/apiUpload.go
  11. 59
      controllers/api/auth/auth.go
  12. 26
      controllers/api/base/api.go
  13. 45
      controllers/index.go
  14. 6
      controllers/webUpload/webUpLoad.go
  15. 39
      middleware/jwt.go
  16. 16
      models/auth.go
  17. 24
      models/config.go
  18. 60
      models/models.go
  19. 16
      routers/api.go
  20. 10
      routers/api/auth/auth.go
  21. 30
      routers/api/v1/upload.go
  22. 45
      routers/router.go
  23. 2
      server/Smms.go
  24. 2
      server/SouGou.go
  25. 14
      utils/encryption.go
  26. 46
      utils/jwt.go
  27. 5
      utils/upload.go

6
.gitignore vendored

@ -1,6 +1,5 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
@ -19,4 +18,7 @@ auxpi.tar.gz
.idea
.idea/*
.vscode
.vscode/*
.vscode/*
siteConfig.json
.lock
.idea

@ -273,7 +273,7 @@ GOOS=darwin GOARCH=amd64 bee pack
```json
{
"code": 500,
"msg": "上传出错"
"msg": "上传失败"
}
```
@ -289,8 +289,8 @@ API 未开启返回值
```json
{
"code": 20001,
"msg": "Token鉴权失败"
"code": 403,
"msg": "Forbidden"
}
```
@ -299,8 +299,8 @@ API 未开启返回值
```json
{
"code": 10001,
"msg": "上传文件为空"
"code": 500,
"msg": "No files were uploaded."
}
```
@ -310,8 +310,8 @@ API 未开启返回值
```json
{
"code": 10002,
"msg": "上传文件太大"
"code": 500,
"msg": "File is too large."
}
```
@ -341,7 +341,7 @@ API 未开启返回值
## 致敬
[@wisp-x](https://github.com/wisp-x)
[wisp-x](https://github.com/wisp-x)
[@astaxie](https://github.com/astaxie)
[astaxie](https://github.com/astaxie)

@ -1,6 +1,5 @@
package auxpi
//Config 配置
type SiteConfig struct {
//站点名称
@ -13,6 +12,12 @@ type SiteConfig struct {
SiteUploadMaxNumber int `json:"site_upload_max_number"`
//最大图片规格 MB
SiteUpLoadMaxSize int64 `json:"site_up_load_max_size"`
//是否使用 Mysql,使用 Mysql 后就不会再使用 json 进行配置
DbOption DbOption `json:"db_option"`
//JWT Token
JwtSecret string `json:"jwt_secret"`
//加密所需 Salt
AuxpiSalt string `json:"auxpi_salt"`
//是否开启 API
OpenApiUpLoad bool `json:"open_api_up_load"`
//Api token 空为 不设置token
@ -23,7 +28,6 @@ type SiteConfig struct {
CacheConfig bool `json:"cache_config"`
//图床储存的一些配置
SiteUploadWay UploadConfig `json:"site_upload_way"`
}
type UploadConfig struct {
@ -35,7 +39,7 @@ type UploadConfig struct {
SinaAccount Account `json:"sina_account"`
//
}
type Account struct {
//用户名
UserName string `json:"user_name"`
@ -47,12 +51,12 @@ type Account struct {
DefultPicSize string `json:"defult_pic_size"`
}
//SM 图床 json
//SM 图床 json
type SmResponse struct {
Code string `json:"code"`
Data SmData `json:"data"`
}
type SmData struct {
Width int `json:"width"`
Height int `json:"height"`
@ -67,25 +71,22 @@ type SmData struct {
Delete string `json:"delete"`
}
//Sina 图床 json
//Sina 图床 json
type SinaMsg struct {
Code string `json:"code"`
Data SinaData `json:"data"`
}
type SinaData struct {
Count int `json:"count"`
Data string `json:"data"`
Pics SinaPics `json:"pics"`
}
type SinaPics struct {
Pic_1 picInfo `json:"pic_1"`
}
type picInfo struct {
Width int `json:"width"`
Size int `json:"size"`
@ -95,21 +96,32 @@ type picInfo struct {
Pid string `json:"pid"`
}
//Api & upload Json
//Api & upload Json
type ResultJson struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data fileData `json:"data"`
}
type fileData struct {
Name string `json:"name"`
Url string `json:"url"`
}
type ErrorJson struct {
Code int `json:"code"`
Msg string `json:"msg"`
type RespJson struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
//Db Option
type DbOption struct {
UseDb bool `json:"use_db"`
DbType string `json:"db_type"`
DbHost string `json:"db_host"`
DbName string `json:"db_name"`
DbUser string `json:"db_user"`
DblPass string `json:"dbl_pass"`
TablePrefix string `json:"table_prefix"`
}

@ -629,6 +629,12 @@ func easyjsonB926644bDecodeAuxpiAuxpiAll5(in *jlexer.Lexer, out *SiteConfig) {
out.SiteUploadMaxNumber = int(in.Int())
case "site_up_load_max_size":
out.SiteUpLoadMaxSize = int64(in.Int64())
case "db_option":
(out.DbOption).UnmarshalEasyJSON(in)
case "jwt_secret":
out.JwtSecret = string(in.String())
case "auxpi_salt":
out.AuxpiSalt = string(in.String())
case "open_api_up_load":
out.OpenApiUpLoad = bool(in.Bool())
case "api_token":
@ -703,6 +709,36 @@ func easyjsonB926644bEncodeAuxpiAuxpiAll5(out *jwriter.Writer, in SiteConfig) {
}
out.Int64(int64(in.SiteUpLoadMaxSize))
}
{
const prefix string = ",\"db_option\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
(in.DbOption).MarshalEasyJSON(out)
}
{
const prefix string = ",\"jwt_secret\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.JwtSecret))
}
{
const prefix string = ",\"auxpi_salt\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.AuxpiSalt))
}
{
const prefix string = ",\"open_api_up_load\":"
if first {
@ -1123,7 +1159,7 @@ func (v *ResultJson) UnmarshalJSON(data []byte) error {
func (v *ResultJson) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjsonB926644bDecodeAuxpiAuxpiAll9(l, v)
}
func easyjsonB926644bDecodeAuxpiAuxpiAll10(in *jlexer.Lexer, out *ErrorJson) {
func easyjsonB926644bDecodeAuxpiAuxpiAll10(in *jlexer.Lexer, out *RespJson) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
@ -1146,6 +1182,14 @@ func easyjsonB926644bDecodeAuxpiAuxpiAll10(in *jlexer.Lexer, out *ErrorJson) {
out.Code = int(in.Int())
case "msg":
out.Msg = string(in.String())
case "data":
if m, ok := out.Data.(easyjson.Unmarshaler); ok {
m.UnmarshalEasyJSON(in)
} else if m, ok := out.Data.(json.Unmarshaler); ok {
_ = m.UnmarshalJSON(in.Raw())
} else {
out.Data = in.Interface()
}
default:
in.SkipRecursive()
}
@ -1156,7 +1200,7 @@ func easyjsonB926644bDecodeAuxpiAuxpiAll10(in *jlexer.Lexer, out *ErrorJson) {
in.Consumed()
}
}
func easyjsonB926644bEncodeAuxpiAuxpiAll10(out *jwriter.Writer, in ErrorJson) {
func easyjsonB926644bEncodeAuxpiAuxpiAll10(out *jwriter.Writer, in RespJson) {
out.RawByte('{')
first := true
_ = first
@ -1180,33 +1224,192 @@ func easyjsonB926644bEncodeAuxpiAuxpiAll10(out *jwriter.Writer, in ErrorJson) {
}
out.String(string(in.Msg))
}
{
const prefix string = ",\"data\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if m, ok := in.Data.(easyjson.Marshaler); ok {
m.MarshalEasyJSON(out)
} else if m, ok := in.Data.(json.Marshaler); ok {
out.Raw(m.MarshalJSON())
} else {
out.Raw(json.Marshal(in.Data))
}
}
out.RawByte('}')
}
// MarshalJSON supports json.Marshaler interface
func (v ErrorJson) MarshalJSON() ([]byte, error) {
func (v RespJson) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
easyjsonB926644bEncodeAuxpiAuxpiAll10(&w, v)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v ErrorJson) MarshalEasyJSON(w *jwriter.Writer) {
func (v RespJson) MarshalEasyJSON(w *jwriter.Writer) {
easyjsonB926644bEncodeAuxpiAuxpiAll10(w, v)
}
// UnmarshalJSON supports json.Unmarshaler interface
func (v *ErrorJson) UnmarshalJSON(data []byte) error {
func (v *RespJson) UnmarshalJSON(data []byte) error {
r := jlexer.Lexer{Data: data}
easyjsonB926644bDecodeAuxpiAuxpiAll10(&r, v)
return r.Error()
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *ErrorJson) UnmarshalEasyJSON(l *jlexer.Lexer) {
func (v *RespJson) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjsonB926644bDecodeAuxpiAuxpiAll10(l, v)
}
func easyjsonB926644bDecodeAuxpiAuxpiAll11(in *jlexer.Lexer, out *Account) {
func easyjsonB926644bDecodeAuxpiAuxpiAll11(in *jlexer.Lexer, out *DbOption) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "use_db":
out.UseDb = bool(in.Bool())
case "db_type":
out.DbType = string(in.String())
case "db_host":
out.DbHost = string(in.String())
case "db_name":
out.DbName = string(in.String())
case "db_user":
out.DbUser = string(in.String())
case "dbl_pass":
out.DblPass = string(in.String())
case "table_prefix":
out.TablePrefix = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjsonB926644bEncodeAuxpiAuxpiAll11(out *jwriter.Writer, in DbOption) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"use_db\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Bool(bool(in.UseDb))
}
{
const prefix string = ",\"db_type\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.DbType))
}
{
const prefix string = ",\"db_host\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.DbHost))
}
{
const prefix string = ",\"db_name\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.DbName))
}
{
const prefix string = ",\"db_user\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.DbUser))
}
{
const prefix string = ",\"dbl_pass\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.DblPass))
}
{
const prefix string = ",\"table_prefix\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.TablePrefix))
}
out.RawByte('}')
}
// MarshalJSON supports json.Marshaler interface
func (v DbOption) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
easyjsonB926644bEncodeAuxpiAuxpiAll11(&w, v)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v DbOption) MarshalEasyJSON(w *jwriter.Writer) {
easyjsonB926644bEncodeAuxpiAuxpiAll11(w, v)
}
// UnmarshalJSON supports json.Unmarshaler interface
func (v *DbOption) UnmarshalJSON(data []byte) error {
r := jlexer.Lexer{Data: data}
easyjsonB926644bDecodeAuxpiAuxpiAll11(&r, v)
return r.Error()
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *DbOption) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjsonB926644bDecodeAuxpiAuxpiAll11(l, v)
}
func easyjsonB926644bDecodeAuxpiAuxpiAll12(in *jlexer.Lexer, out *Account) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
@ -1243,7 +1446,7 @@ func easyjsonB926644bDecodeAuxpiAuxpiAll11(in *jlexer.Lexer, out *Account) {
in.Consumed()
}
}
func easyjsonB926644bEncodeAuxpiAuxpiAll11(out *jwriter.Writer, in Account) {
func easyjsonB926644bEncodeAuxpiAuxpiAll12(out *jwriter.Writer, in Account) {
out.RawByte('{')
first := true
_ = first
@ -1293,23 +1496,23 @@ func easyjsonB926644bEncodeAuxpiAuxpiAll11(out *jwriter.Writer, in Account) {
// MarshalJSON supports json.Marshaler interface
func (v Account) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
easyjsonB926644bEncodeAuxpiAuxpiAll11(&w, v)
easyjsonB926644bEncodeAuxpiAuxpiAll12(&w, v)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v Account) MarshalEasyJSON(w *jwriter.Writer) {
easyjsonB926644bEncodeAuxpiAuxpiAll11(w, v)
easyjsonB926644bEncodeAuxpiAuxpiAll12(w, v)
}
// UnmarshalJSON supports json.Unmarshaler interface
func (v *Account) UnmarshalJSON(data []byte) error {
r := jlexer.Lexer{Data: data}
easyjsonB926644bDecodeAuxpiAuxpiAll11(&r, v)
easyjsonB926644bDecodeAuxpiAuxpiAll12(&r, v)
return r.Error()
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *Account) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjsonB926644bDecodeAuxpiAuxpiAll11(l, v)
easyjsonB926644bDecodeAuxpiAuxpiAll12(l, v)
}

@ -13,7 +13,11 @@ const (
ERROR_FILE_TYPE = 10005
ERROR_AUTH_CHECK_TOKEN_FAIL = 20001
ERROR_ACCESS_DENIED = 20002
ERROR_AUTH_CHECK_TOKEN_TIMEOUT = 20002
ERROR_AUTH_TOKEN = 20003
ERROR_AUTH = 20004
ERROR_ACCESS_DENIED = 20005
)

@ -10,6 +10,9 @@ var MsgFlags = map[int]string {
ERROR_CAN_NOT_GET_IMG_URL : "无法获取第三方图床 URL",
ERROR_TOO_MANY_IMAGES : "上传图片太多",
ERROR_AUTH_CHECK_TOKEN_FAIL : "Token鉴权失败",
ERROR_AUTH_CHECK_TOKEN_TIMEOUT:"Token 过期",
ERROR_AUTH_TOKEN:"Token 不正确",
ERROR_AUTH:"认证失败",
ERROR_ACCESS_DENIED : "禁止访问",
}

@ -5,6 +5,6 @@ import "github.com/astaxie/beego/logs"
func init() {
logs.SetLogger(logs.AdapterFile,`{"filename":"auxpiRun.log","level":6,"maxlines":0,"maxsize":0,"daily":true,"maxdays":10}`)
logs.Async(1e3)
logs.EnableFuncCallDepth(true)
//logs.EnableFuncCallDepth(true)
}

@ -6,6 +6,7 @@ import (
"encoding/json"
"github.com/astaxie/beego/cache"
"io/ioutil"
"math/rand"
"os"
"time"
)
@ -15,11 +16,9 @@ type AuxpiConfig struct {
var cCache, _ = cache.NewCache("memory", `{"interval":3600}`)
type JsonStruct struct {
}
var SiteConfig *auxpi.SiteConfig
func NewJsonStruct() *JsonStruct {
return &JsonStruct{}
type JsonStruct struct {
}
func (jst *JsonStruct) Load(filename string, v interface{}) {
@ -59,6 +58,7 @@ func init() {
lockDir := baseDir + "install.lock"
_, err := os.Stat(lockDir)
if err == nil {
SiteConfig = Config()
return
}
if os.IsNotExist(err) {
@ -70,6 +70,8 @@ func init() {
siteconfig.SiteUpLoadMaxSize = 5
siteconfig.SiteUploadMaxNumber = 10
siteconfig.OpenApiUpLoad = true
siteconfig.JwtSecret = GetRandomString(16)
siteconfig.AuxpiSalt = GetRandomString(16)
siteconfig.ApiToken = ""
siteconfig.ApiDefault = "SouGou"
siteconfig.CacheConfig = false
@ -79,7 +81,13 @@ func init() {
siteconfig.SiteUploadWay.SinaAccount.PassWord = ""
siteconfig.SiteUploadWay.SinaAccount.ResetSinaCookieTime = 3600
siteconfig.SiteUploadWay.SinaAccount.DefultPicSize = "large"
siteconfig.DbOption.UseDb = true
siteconfig.DbOption.DbType = "mysql"
siteconfig.DbOption.DbHost = "127.0.0.1:3306"
siteconfig.DbOption.DbName = "auxpi"
siteconfig.DbOption.DbUser = "root"
siteconfig.DbOption.DblPass = "root"
siteconfig.DbOption.TablePrefix = "auxpi_"
configJson, err := siteconfig.MarshalJSON()
if err != nil {
panic(err)
@ -93,6 +101,19 @@ func init() {
_, err = w.WriteString(string(configJson))
w.Flush()
f.Close()
SiteConfig = Config()
}
}
func GetRandomString(l int) string {
str := `0123456789abcdef!@#$%^&*()__+ghijklmnop?></qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return string(result)
}

@ -4,14 +4,14 @@ import (
"auxpi/auxpiAll"
"auxpi/auxpiAll/e"
"auxpi/bootstrap"
"auxpi/controllers/api/base"
"auxpi/utils"
"github.com/astaxie/beego"
"log"
"strings"
)
type ApiUpLoadController struct {
beego.Controller
base.ApiController
utils.UpLoadTools
}
@ -21,14 +21,15 @@ func (this *ApiUpLoadController) Prepare() {
}
var picType = []string{"png", "jpg", "jpeg", "gif", "bmp"}
var siteConfig = bootstrap.Config()
func (this *ApiUpLoadController) UpLoadHandle() {
//检测是否开启 token 认证
if siteConfig.ApiToken != "" {
if bootstrap.SiteConfig.ApiToken != "" {
//需要进行验证
apiToken := this.GetString("token")
if apiToken != siteConfig.ApiToken {
if apiToken != bootstrap.SiteConfig.ApiToken {
this.errorResp(e.ERROR_AUTH_CHECK_TOKEN_FAIL)
return
}
@ -39,7 +40,7 @@ func (this *ApiUpLoadController) UpLoadHandle() {
if f == nil {
this.errorResp(e.ERROR_FILE_IS_EMPTY)
}
if h.Size > siteConfig.SiteUpLoadMaxSize<<20 {
if h.Size > bootstrap.SiteConfig.SiteUpLoadMaxSize<<20 {
this.errorResp(e.ERROR_FILE_IS_TOO_LARGE)
}
defer f.Close()
@ -92,7 +93,7 @@ func (this *ApiUpLoadController) validate(contentType string, fileName string) b
//错误resp
func (this *ApiUpLoadController) errorResp(code int) {
result := &auxpi.ErrorJson{}
result := &auxpi.RespJson{}
result.Code = code
result.Msg = e.GetMsg(code)
this.Data["json"] = result

@ -0,0 +1,59 @@
package api
import (
"auxpi/auxpiAll"
"auxpi/auxpiAll/e"
"auxpi/controllers/api/base"
"auxpi/models"
"auxpi/utils"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/validation"
)
type Auth struct {
base.ApiController
}
type authInfo struct {
Username string `valid:"Required; MaxSize(32)"`
Password string `valid:"Required; MaxSize(32)"`
}
func (this *Auth) GetAuth() {
info := authInfo{}
code := e.INVALID_PARAMS
if err := this.ParseForm(&info); err != nil {
//TODO :写入后台日志
logs.Info("尝试鉴权失败")
}
valid := validation.Validation{}
ok, _ := valid.Valid(&info)
data := make(map[string]interface{})
if ok {
isExist := models.CheckAuth(info.Username, utils.GetSha256CodeWithSalt(info.Password))
if isExist {
token, err := utils.GenerateToken(info.Username, info.Password)
if err != nil {
code = e.ERROR_AUTH_TOKEN
} else {
data["token"] = token
code = e.SUCCESS
}
} else {
logs.Alert("hello")
code = e.ERROR_AUTH
}
} else {
for _, errs := range valid.Errors {
logs.Debug(errs.Value)
}
}
resp := &auxpi.RespJson{
code,
e.GetMsg(code),
data,
}
this.Data["json"] = resp
this.ServeJSON()
}

@ -0,0 +1,26 @@
package base
import (
"auxpi/auxpiAll"
"github.com/astaxie/beego"
)
type ApiController struct {
beego.Controller
}
//所有的 APi 不需要开启 CSRF
func (this *ApiController) Prepare() {
this.EnableXSRF = false
}
//调试 APi 只有 dev 模式下才能使用
func (this *ApiController) Test() {
resp := &auxpi.RespJson{
200,
"你好世界级",
make(map[string]interface{}),
}
this.Data["json"] = resp
this.ServeJSON()
}

@ -9,20 +9,15 @@ type PagesController struct {
beego.Controller
}
//获取 config 的配置
var siteConfig = bootstrap.Config()
func (this *PagesController) IndexShow() {
this.Data["siteName"] = siteConfig.SiteName
this.Data["siteUrl"] = siteConfig.SiteUrl
this.Data["siteFooterText"] = siteConfig.SiteFooter
this.Data["siteName"] = bootstrap.SiteConfig.SiteName
this.Data["siteUrl"] = bootstrap.SiteConfig.SiteUrl
this.Data["siteFooterText"] = bootstrap.SiteConfig.SiteFooter
this.Data["apiUrl"] = "/api/v1/auth/upload"
this.Data["maxNumber"] = siteConfig.SiteUploadMaxNumber
this.Data["maxNumber"] = bootstrap.SiteConfig.SiteUploadMaxNumber
//单位为Mb 5mb ==> 5*1024 kb
this.Data["maxPicSize"] = siteConfig.SiteUpLoadMaxSize << 10
this.Data["maxPicSize"] = bootstrap.SiteConfig.SiteUpLoadMaxSize << 10
this.Data["apiSelect"] = "SouGou"
this.Data["iconStyle"] = "sougou"
this.Data["iconColor"] = "orange"
@ -38,13 +33,13 @@ func (this *PagesController) IndexShow() {
func (this *PagesController) SinaShow() {
this.Data["siteName"] = siteConfig.SiteName
this.Data["siteUrl"] = siteConfig.SiteUrl
this.Data["siteFooterText"] = siteConfig.SiteFooter
this.Data["siteName"] = bootstrap.SiteConfig.SiteName
this.Data["siteUrl"] = bootstrap.SiteConfig.SiteUrl
this.Data["siteFooterText"] = bootstrap.SiteConfig.SiteFooter
this.Data["apiUrl"] = "/api/v1/auth/upload/"
this.Data["maxNumber"] = siteConfig.SiteUploadMaxNumber
this.Data["maxNumber"] = bootstrap.SiteConfig.SiteUploadMaxNumber
//单位为Mb 5mb ==> 5*1024 kb
this.Data[" maxPicSize"] = siteConfig.SiteUpLoadMaxSize << 10
this.Data[" maxPicSize"] = bootstrap.SiteConfig.SiteUpLoadMaxSize << 10
this.Data["xsrf_token"] = this.XSRFToken()
this.LayoutSections = make(map[string]string)
this.Data["apiSelect"] = "Sina"
@ -56,7 +51,7 @@ func (this *PagesController) SinaShow() {
this.LayoutSections["Left"] = "layouts/left.tpl"
this.Layout = "layouts/app.tpl"
//检测是否开启新浪图床
if siteConfig.SiteUploadWay.OpenSinaPicStore {
if bootstrap.SiteConfig.SiteUploadWay.OpenSinaPicStore {
this.TplName = "webUpload/box.tpl"
return
}
@ -65,13 +60,13 @@ func (this *PagesController) SinaShow() {
func (this *PagesController) SmmsShow() {
this.Data["siteName"] = siteConfig.SiteName
this.Data["siteUrl"] = siteConfig.SiteUrl
this.Data["siteFooterText"] = siteConfig.SiteFooter
this.Data["siteName"] = bootstrap.SiteConfig.SiteName
this.Data["siteUrl"] = bootstrap.SiteConfig.SiteUrl
this.Data["siteFooterText"] = bootstrap.SiteConfig.SiteFooter
this.Data["apiUrl"] = "/api/v1/auth/upload/"
this.Data["maxNumber"] = siteConfig.SiteUploadMaxNumber
this.Data["maxNumber"] = bootstrap.SiteConfig.SiteUploadMaxNumber
//单位为Mb 5mb ==> 5*1024 kb
this.Data["maxPicSize"] = siteConfig.SiteUpLoadMaxSize << 10
this.Data["maxPicSize"] = bootstrap.SiteConfig.SiteUpLoadMaxSize << 10
this.Data["xsrf_token"] = this.XSRFToken()
this.LayoutSections = make(map[string]string)
this.Data["apiSelect"] = "Smms"
@ -87,15 +82,15 @@ func (this *PagesController) SmmsShow() {
}
func (this *PagesController) AboutShow() {
this.Data["siteName"] = siteConfig.SiteName
this.Data["siteUrl"] = siteConfig.SiteUrl
this.Data["siteFooterText"] = siteConfig.SiteFooter
this.Data["siteName"] = bootstrap.SiteConfig.SiteName
this.Data["siteUrl"] = bootstrap.SiteConfig.SiteUrl
this.Data["siteFooterText"] = bootstrap.SiteConfig.SiteFooter
this.LayoutSections = make(map[string]string)
this.LayoutSections["Scripts"] = "webUpload/uploadScript.tpl"
this.LayoutSections["Header"] = "layouts/header.tpl"
this.LayoutSections["Footer"] = "layouts/footer.tpl"
this.LayoutSections["Left"] = "layouts/left.tpl"
this.Data["title"] = "关于 Buster API 图床"
this.Data["title"] = "关于"+bootstrap.SiteConfig.SiteName
this.Layout = "layouts/app.tpl"
this.TplName = "about/about-me.tpl"
}

@ -17,7 +17,7 @@ type WebUpLoadController struct {
}
var picType = []string{"png", "jpg", "jpeg", "gif", "bmp"}
var siteConfig = bootstrap.Config()
//代码冗余,但是使用 API 会造成不必要的消耗
func (this *WebUpLoadController) UpLoadHandle() {
@ -34,7 +34,7 @@ func (this *WebUpLoadController) UpLoadHandle() {
return
}
//检测是否超出大小限制
if h.Size > siteConfig.SiteUpLoadMaxSize<<20 {
if h.Size > bootstrap.SiteConfig.SiteUpLoadMaxSize<<20 {
this.errorResp(e.ERROR_FILE_IS_TOO_LARGE)
return
}
@ -58,7 +58,7 @@ func (this *WebUpLoadController) UpLoadHandle() {
//错误resp
func (this *WebUpLoadController) errorResp(code int) {
result := &auxpi.ErrorJson{}
result := &auxpi.RespJson{}
result.Code = code
result.Msg = e.GetMsg(code)
this.Data["json"] = result

@ -0,0 +1,39 @@
package middleware
import (
"auxpi/auxpiAll"
"auxpi/auxpiAll/e"
"auxpi/utils"
"github.com/astaxie/beego/context"
"time"
)
var JWT = func(ctx *context.Context) {
var code int
var data interface{}
var token string
code = e.SUCCESS
token = ctx.Request.Header.Get("X-Token")
if token == "" {
code = e.INVALID_PARAMS
} else {
claims, err := utils.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 {
errorInfo := auxpi.RespJson{
Code: code,
Msg: e.GetMsg(code),
Data: data,
}
info, _ := errorInfo.MarshalJSON()
ctx.Output.Header("Content-Type","application/json; charset=UTF-8")
ctx.ResponseWriter.Write(info)
return
}
}

@ -0,0 +1,16 @@
package models
type Auth struct {
ID int `gorm:"primary_key" json:"id"`
Username string `json:"username"`
Password string `json:"password"`
}
func CheckAuth(username, password string) bool {
var auth Auth
db.Select("id").Where(Auth{Username: username, Password: password}).First(&auth)
if auth.ID > 0 {
return true
}
return false
}

@ -1,24 +0,0 @@
package models
type SiteDefault struct {
Url string
Api string
}
type SiteConfig struct {
Name string
//最大上传的图片个数
UploadMaxNumber string
//最大图片规格 MB
UpLoadMaxSize int
//图床储存的一些配置
UploadWay UploadConfig
}
type UploadConfig struct {
//是否开启本地上传
LocalStore bool
//选择上传的图床 Sina | SouGou | All
StorePic string
//
}

@ -0,0 +1,60 @@
package models
import (
"auxpi/bootstrap"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"log"
)
var db *gorm.DB
//定义基础的 Model 实例
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
)
if err != nil {
log.Fatal(2, "Fail to get section 'database': %v", err)
}
dbType = bootstrap.SiteConfig.DbOption.DbType
dbName = bootstrap.SiteConfig.DbOption.DbName
user = bootstrap.SiteConfig.DbOption.DbUser
password = bootstrap.SiteConfig.DbOption.DblPass
host = bootstrap.SiteConfig.DbOption.DbHost
tablePrefix = bootstrap.SiteConfig.DbOption.TablePrefix
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(db)
log.Println(err)
}
//获取表名称
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return tablePrefix + defaultTableName;
}
db.SingularTable(true)
db.DB().SetMaxIdleConns(10)
db.DB().SetMaxOpenConns(100)
}
func CloseDB() {
defer db.Close()
}

@ -1,16 +0,0 @@
package routers
import (
"auxpi/controllers/api"
"github.com/astaxie/beego"
)
func RegisterOpenApi() {
//不需要控制的 api 放到这里
ns :=
beego.NewNamespace("/api/v1",
beego.NSRouter("/web_upload/", &api.ApiUpLoadController{}, "post:UpLoadHandle"),
)
beego.AddNamespace(ns)
}

@ -0,0 +1,10 @@
package auth
import (
"auxpi/controllers/api/auth"
"github.com/astaxie/beego"
)
func RegisterAuth() {
beego.Router("/auth",&api.Auth{},"post:GetAuth")
}

@ -0,0 +1,30 @@
package v1
import (
"auxpi/bootstrap"
"auxpi/controllers/api"
"github.com/astaxie/beego"
)
//不需要控制的 API
func RegisterOpenApiV1() {
//不需要控制的 api 放到这里
ns :=
beego.NewNamespace("/api/v1",
beego.NSRouter("/web_upload/", &api.ApiUpLoadController{}, "post:UpLoadHandle"),
)
beego.AddNamespace(ns)
}
//需要控制的 API
func RegisterControlApiV1() {
if bootstrap.SiteConfig.OpenApiUpLoad {
beego.Router("api/v1/upload", &api.ApiUpLoadController{}, "post:UpLoadHandle")
beego.Router("api/v1/upload", &api.ApiUpLoadController{}, "get,put,patch,delete,options,head:ErrorCapture")
} else {
beego.Router("api/v1/upload", &api.ApiUpLoadController{}, "*:ErrorCapture")
}
}

@ -1,27 +1,40 @@
// @APIVersion 1.0.0
// @Title File Upload API
// @Description AuXpI 图床提供的 API 上传的方法
// @Contact aimerforreimu#gmail.com (#->@)
package routers
import (
"auxpi/bootstrap"
"auxpi/controllers"
"auxpi/controllers/api"
"auxpi/controllers/api/base"
"auxpi/middleware"
"auxpi/routers/api/auth"
"auxpi/routers/api/v1"
"github.com/astaxie/beego"
)
var siteConfig = bootstrap.Config()
func init() {
//正式环境不使用控制器内环境,调试时使用控制器内反射路由
beego.Router("/",&page.PagesController{},"get:IndexShow")
beego.Router("/Sina",&page.PagesController{},"get:SinaShow")
beego.Router("/Smms",&page.PagesController{},"get:SmmsShow")
beego.Router("/about",&page.PagesController{},"get:AboutShow")
//注册无需控制的 API
RegisterOpenApi()
//部分 API 路由单独控制
if siteConfig.OpenApiUpLoad {
beego.Router("api/v1/upload", &api.ApiUpLoadController{}, "post:UpLoadHandle")
beego.Router("api/v1/upload", &api.ApiUpLoadController{}, "get,put,patch,delete,options,head:ErrorCapture")
} else {
beego.Router("api/v1/upload", &api.ApiUpLoadController{}, "*:ErrorCapture")
beego.Router("/", &page.PagesController{}, "get:IndexShow")
beego.Router("/Sina", &page.PagesController{}, "get:SinaShow")
beego.Router("/Smms", &page.PagesController{}, "get:SmmsShow")
beego.Router("/about", &page.PagesController{}, "get:AboutShow")
//auth
auth.RegisterAuth()
//dev 模式会打开测试路由方便调试
if beego.BConfig.RunMode == "dev" {
testRouter()
}
//v1 版本路由注册
v1.RegisterControlApiV1()
v1.RegisterOpenApiV1()
//v2 版本路由注册
}
//测试路由,不要随便开启
func testRouter() {
beego.InsertFilter("/test", beego.BeforeRouter, middleware.JWT)
beego.Router("/test", &base.ApiController{}, "post:Test")
}

@ -3,6 +3,7 @@ package server
import (
"auxpi/auxpiAll"
"bytes"
"github.com/astaxie/beego"
"io/ioutil"
"mime/multipart"
"net/http"
@ -29,6 +30,7 @@ func (this *Smms) UpLoatToSmms(img []byte, imgInfo string) string {
defer resp.Body.Close()
data, _ := ioutil.ReadAll(resp.Body)
sm := auxpi.SmResponse{}
beego.Alert(string(data))
sm.UnmarshalJSON([]byte(string(data)))
return string(sm.Data.Url)
}

@ -4,6 +4,7 @@ import (
"auxpi/bootstrap"
"bytes"
"encoding/base64"
"github.com/astaxie/beego"
"io/ioutil"
"net/http"
"strings"
@ -31,6 +32,7 @@ func (this *SouGou) UpLoadToSouGou(img []byte) string {
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
beego.Alert(string(body))
respUrl :=string(body)
respUrl = strings.Replace(respUrl,"http","https",-1)
return respUrl

@ -0,0 +1,14 @@
package utils
import (
"auxpi/bootstrap"
"crypto/sha256"
"fmt"
)
func GetSha256CodeWithSalt(s string) string {
h := sha256.New()
salt := bootstrap.SiteConfig.AuxpiSalt
h.Write([]byte(s+salt))
return fmt.Sprintf("%x", h.Sum(nil))
}

@ -0,0 +1,46 @@
package utils
import (
"auxpi/bootstrap"
"github.com/dgrijalva/jwt-go"
"time"
)
var jwtSecret = []byte(bootstrap.SiteConfig.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: "auxpi",
},
}
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
}

@ -14,7 +14,6 @@ type UpLoadTools struct {
}
var picType = []string{"png", "jpg", "jpeg", "gif", "bmp"}
var siteConfig = bootstrap.Config()
//返回不同图床的 URL
func (this *UpLoadTools) HandleUrl(apiSelect string, f multipart.File, h *multipart.FileHeader) string {
imgMime := h.Header.Get("Content-Type")
@ -28,14 +27,14 @@ func (this *UpLoadTools) HandleUrl(apiSelect string, f multipart.File, h *multip
case "SouGou":
url = this.UpLoadToSouGou(fileContent)
case "Sina":
if siteConfig.SiteUploadWay.OpenSinaPicStore == false {
if bootstrap.SiteConfig.SiteUploadWay.OpenSinaPicStore == false {
url = ""
}
url = this.UpLoadToSina(fileContent, imgMime)
case "Smms":
url = this.UpLoatToSmms(fileContent, imgInfo)
default:
switch siteConfig.ApiDefault {
switch bootstrap.SiteConfig.ApiDefault {
case "SouGou":
url = this.UpLoadToSouGou(fileContent)
case "Smms":

Loading…
Cancel
Save