Reduce handler request boilerplate
- Add session.Attach to reuse per-request sessions across middleware and ghome handlers - Make Session finalize/abort paths idempotent to avoid duplicate commit or rollback work - Move request_data parsing helper to internal/utils - Expand ParseRequestData usage across api, download, unit, live, multiunit, and subscenario handlers - Extract download package metadata into internal/handler/download/types.go - Return explicit errors from selected session lookup helpers and update callers - Make api action handlers return errors directly instead of calling ss.CheckErr in nested layers Signed-off-by: Sean Du <do4suki@gmail.com>
This commit is contained in:
@@ -4,25 +4,28 @@ import (
|
||||
usermodel "honoka-chan/internal/model/user"
|
||||
)
|
||||
|
||||
func (ss *Session) GetUserDeck(deckID int) (bool, *usermodel.UserDeck) {
|
||||
func (ss *Session) GetUserDeck(deckID int) (bool, *usermodel.UserDeck, error) {
|
||||
deckData := usermodel.UserDeck{}
|
||||
has, err := ss.UserEng.Table("user_deck").
|
||||
Where("user_id = ? AND deck_id = ?", ss.UserID, deckID).Get(&deckData)
|
||||
if ss.CheckErr(err) {
|
||||
return false, nil
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
return has, &deckData
|
||||
return has, &deckData, nil
|
||||
}
|
||||
|
||||
func (ss *Session) GetUserDeckUnit(deckID int) []usermodel.UserDeckUnit {
|
||||
has, deckData := ss.GetUserDeck(deckID)
|
||||
has, deckData, err := ss.GetUserDeck(deckID)
|
||||
if ss.CheckErr(err) {
|
||||
return []usermodel.UserDeckUnit{}
|
||||
}
|
||||
if !has {
|
||||
return []usermodel.UserDeckUnit{}
|
||||
}
|
||||
|
||||
unitData := []usermodel.UserDeckUnit{}
|
||||
err := ss.UserEng.Table("user_deck_unit").
|
||||
err = ss.UserEng.Table("user_deck_unit").
|
||||
Where("user_deck_id = ?", deckData.ID).Find(&unitData)
|
||||
if ss.CheckErr(err) {
|
||||
return []usermodel.UserDeckUnit{}
|
||||
|
||||
@@ -6,26 +6,30 @@ import (
|
||||
)
|
||||
|
||||
func (ss *Session) GetDeviceID() string {
|
||||
return ss.Ctx.Request.Header.Get("X-DEVICEID")
|
||||
return ss.deviceID
|
||||
}
|
||||
|
||||
func (ss *Session) GetRandKey() []byte {
|
||||
func (ss *Session) GetRandKey() ([]byte, error) {
|
||||
deviceKey := ghomemodel.DeviceKey{}
|
||||
has, err := ss.UserEng.Table(new(ghomemodel.DeviceKey)).
|
||||
Where("device_id = ?", ss.GetDeviceID()).Get(&deviceKey)
|
||||
if ss.CheckErr(err) {
|
||||
return nil
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !has {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return []byte(deviceKey.RandKey)
|
||||
return []byte(deviceKey.RandKey), nil
|
||||
}
|
||||
func (ss *Session) SetRandKey(key string) {
|
||||
var err error
|
||||
if ss.GetRandKey() == nil {
|
||||
randKey, err := ss.GetRandKey()
|
||||
if ss.CheckErr(err) {
|
||||
return
|
||||
}
|
||||
if randKey == nil {
|
||||
_, err = ss.UserEng.Insert(&ghomemodel.DeviceKey{
|
||||
DeviceID: ss.GetDeviceID(),
|
||||
RandKey: key,
|
||||
@@ -40,7 +44,10 @@ func (ss *Session) SetRandKey(key string) {
|
||||
}
|
||||
|
||||
func (ss *Session) Get3DESRandKey() ([]byte, error) {
|
||||
randKey := ss.GetRandKey()
|
||||
randKey, err := ss.GetRandKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(randKey) < 24 {
|
||||
return nil, errors.New("invalid rand key")
|
||||
}
|
||||
|
||||
@@ -2,15 +2,15 @@ package session
|
||||
|
||||
import loginmodel "honoka-chan/internal/model/login"
|
||||
|
||||
func (ss *Session) GetAuthKey(token string) (bool, *loginmodel.AuthKey) {
|
||||
func (ss *Session) GetAuthKey(token string) (bool, *loginmodel.AuthKey, error) {
|
||||
authKeyData := loginmodel.AuthKey{}
|
||||
has, err := ss.UserEng.Table(new(loginmodel.AuthKey)).
|
||||
Where("authorize_token = ?", token).Get(&authKeyData)
|
||||
if ss.CheckErr(err) {
|
||||
return false, nil
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
return has, &authKeyData
|
||||
return has, &authKeyData, nil
|
||||
}
|
||||
|
||||
func (ss *Session) SetAuthKey(authKey *loginmodel.AuthKey) {
|
||||
|
||||
+71
-13
@@ -13,19 +13,36 @@ import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Ctx *gin.Context
|
||||
type responseHooks struct {
|
||||
setHeader func(string, string)
|
||||
writeJSON func(int, any)
|
||||
writeBody func(int, string)
|
||||
abort func()
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
MainEng *xorm.Session
|
||||
UserEng *xorm.Session
|
||||
|
||||
UserID int
|
||||
UserPref usermodel.UserPref
|
||||
|
||||
deviceID string
|
||||
resp responseHooks
|
||||
done bool
|
||||
}
|
||||
|
||||
func New(ctx *gin.Context) *Session {
|
||||
ss := &Session{
|
||||
Ctx: ctx,
|
||||
deviceID: ctx.GetHeader("X-DEVICEID"),
|
||||
resp: responseHooks{
|
||||
setHeader: ctx.Header,
|
||||
writeJSON: ctx.JSON,
|
||||
writeBody: func(code int, body string) {
|
||||
ctx.String(code, body)
|
||||
},
|
||||
abort: ctx.Abort,
|
||||
},
|
||||
}
|
||||
|
||||
ss.MainEng = db.MainEng.NewSession()
|
||||
@@ -45,21 +62,62 @@ func Get(ctx *gin.Context) *Session {
|
||||
return ctx.MustGet("session").(*Session)
|
||||
}
|
||||
|
||||
func Attach(ctx *gin.Context) *Session {
|
||||
if ss, ok := ctx.Get("session"); ok {
|
||||
return ss.(*Session)
|
||||
}
|
||||
|
||||
ss := New(ctx)
|
||||
ctx.Set("session", ss)
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *Session) Finalize() {
|
||||
ss.MainEng.Close()
|
||||
if ss.CheckErr(ss.UserEng.Commit()) {
|
||||
if ss.done {
|
||||
return
|
||||
}
|
||||
ss.done = true
|
||||
|
||||
if ss.MainEng != nil {
|
||||
ss.MainEng.Close()
|
||||
ss.MainEng = nil
|
||||
}
|
||||
|
||||
if ss.UserEng == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := ss.UserEng.Commit(); err != nil {
|
||||
log.Println(err.Error())
|
||||
ss.UserEng.Close()
|
||||
ss.UserEng = nil
|
||||
ss.resp.writeJSON(500, gin.H{"error": err.Error()})
|
||||
ss.resp.abort()
|
||||
return
|
||||
}
|
||||
|
||||
ss.UserEng.Close()
|
||||
ss.UserEng = nil
|
||||
}
|
||||
|
||||
func (ss *Session) Abort(err error) {
|
||||
ss.MainEng.Close()
|
||||
ss.UserEng.Rollback()
|
||||
ss.UserEng.Close()
|
||||
if ss.done {
|
||||
return
|
||||
}
|
||||
ss.done = true
|
||||
|
||||
ss.Ctx.JSON(500, gin.H{"error": err.Error()})
|
||||
ss.Ctx.Abort()
|
||||
if ss.MainEng != nil {
|
||||
ss.MainEng.Close()
|
||||
ss.MainEng = nil
|
||||
}
|
||||
if ss.UserEng != nil {
|
||||
ss.UserEng.Rollback()
|
||||
ss.UserEng.Close()
|
||||
ss.UserEng = nil
|
||||
}
|
||||
|
||||
ss.resp.writeJSON(500, gin.H{"error": err.Error()})
|
||||
ss.resp.abort()
|
||||
}
|
||||
|
||||
func (ss *Session) CheckErr(err error) bool {
|
||||
@@ -77,7 +135,7 @@ func (ss *Session) Respond(resp any) {
|
||||
return
|
||||
}
|
||||
|
||||
ss.Ctx.Header("Content-Type", "application/json")
|
||||
ss.Ctx.Header("X-Message-Sign", base64.StdEncoding.EncodeToString(encrypt.RSASignSHA1(data)))
|
||||
ss.Ctx.String(http.StatusOK, string(data))
|
||||
ss.resp.setHeader("Content-Type", "application/json")
|
||||
ss.resp.setHeader("X-Message-Sign", base64.StdEncoding.EncodeToString(encrypt.RSASignSHA1(data)))
|
||||
ss.resp.writeBody(http.StatusOK, string(data))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user