直接完成
此提交包含在:
11
pkg/app/handler_func.go
一般檔案
11
pkg/app/handler_func.go
一般檔案
@@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func HandlerFunc(handler func(aw *Wrapper) Result) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
aw := NewWrapper(c)
|
||||
res := handler(aw)
|
||||
c.JSON(200, res)
|
||||
}
|
||||
}
|
72
pkg/app/wrapper.go
一般檔案
72
pkg/app/wrapper.go
一般檔案
@@ -0,0 +1,72 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"integrity-checkin/pkg/util"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg,omitempty"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
wrapper *Wrapper
|
||||
}
|
||||
|
||||
func (r Result) SendJSON() {
|
||||
r.wrapper.Ctx.JSON(200, r)
|
||||
}
|
||||
|
||||
type Wrapper struct {
|
||||
Ctx *gin.Context
|
||||
}
|
||||
|
||||
func NewWrapper(c *gin.Context) *Wrapper {
|
||||
return &Wrapper{Ctx: c}
|
||||
}
|
||||
|
||||
func (w Wrapper) OK() Result {
|
||||
return Result{
|
||||
Code: 0,
|
||||
Msg: "",
|
||||
Data: nil,
|
||||
wrapper: &w,
|
||||
}
|
||||
}
|
||||
func (w Wrapper) Success(data interface{}) Result {
|
||||
return Result{
|
||||
Code: 0,
|
||||
Msg: "",
|
||||
Data: data,
|
||||
wrapper: &w,
|
||||
}
|
||||
}
|
||||
func (w Wrapper) Error(msg string) Result {
|
||||
return Result{
|
||||
Code: -1,
|
||||
Msg: msg,
|
||||
Data: nil,
|
||||
wrapper: &w,
|
||||
}
|
||||
}
|
||||
func (w Wrapper) ErrorWithCode(code int, msg string) Result {
|
||||
return Result{
|
||||
Code: code,
|
||||
Msg: msg,
|
||||
Data: nil,
|
||||
wrapper: &w,
|
||||
}
|
||||
}
|
||||
func (w Wrapper) GetIP() string {
|
||||
return w.Ctx.ClientIP()
|
||||
}
|
||||
func (w Wrapper) ExtractUserClaims() *util.UserClaims {
|
||||
raw, exist := w.Ctx.Get("userClaims")
|
||||
if !exist {
|
||||
panic("userClaims not exists")
|
||||
}
|
||||
uc, ok := raw.(*util.UserClaims)
|
||||
if !ok {
|
||||
panic("userClaims failed to convert")
|
||||
}
|
||||
return uc
|
||||
}
|
67
pkg/httpclient/resty.go
一般檔案
67
pkg/httpclient/resty.go
一般檔案
@@ -0,0 +1,67 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"integrity-checkin/data/dto"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Client *resty.Client
|
||||
|
||||
func Setup() {
|
||||
Client = resty.New().SetTimeout(10 * time.Second)
|
||||
}
|
||||
func SDULogin(username string, password string) (*dto.SDULoginData, error) {
|
||||
resp, err := Client.R().SetFormData(map[string]string{
|
||||
"username": username,
|
||||
"password": password,
|
||||
}).Post("https://pass.sdu.edu.cn/cas/restlet/tickets")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result1 := string(resp.Body())
|
||||
if resp.StatusCode()/100 != 2 {
|
||||
return nil, errors.New(result1)
|
||||
}
|
||||
resp, err = Client.R().SetBody("service=https://service.sdu.edu.cn/tp_up/view?m=up").
|
||||
Post("https://pass.sdu.edu.cn/cas/restlet/tickets/" + result1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result2 := string(resp.Body())
|
||||
if resp.StatusCode()/100 != 2 {
|
||||
return nil, errors.New(result2)
|
||||
}
|
||||
resp, err = Client.R().SetQueryParams(map[string]string{
|
||||
"ticket": result2,
|
||||
"service": "https://service.sdu.edu.cn/tp_up/view?m=up",
|
||||
}).Get("https://pass.sdu.edu.cn/cas/serviceValidate")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result3 := string(resp.Body())
|
||||
if resp.StatusCode()/100 != 2 {
|
||||
return nil, errors.New(result3)
|
||||
}
|
||||
realName := ""
|
||||
username = ""
|
||||
if arr := regexp.MustCompile("<cas:USER_NAME>(.*?)<").FindStringSubmatch(result3); len(arr) >= 2 {
|
||||
realName = arr[1]
|
||||
} else {
|
||||
return nil, errors.New(result3)
|
||||
}
|
||||
if arr := regexp.MustCompile("<cas:ID_NUMBER>(.*?)<").FindStringSubmatch(result3); len(arr) >= 2 {
|
||||
username = arr[1]
|
||||
} else {
|
||||
return nil, errors.New(result3)
|
||||
}
|
||||
if realName == "" || username == "" {
|
||||
return nil, errors.New(result3)
|
||||
}
|
||||
return &dto.SDULoginData{
|
||||
RealName: realName,
|
||||
Username: username,
|
||||
}, nil
|
||||
}
|
42
pkg/util/permission.go
一般檔案
42
pkg/util/permission.go
一般檔案
@@ -0,0 +1,42 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
type UserClaims struct {
|
||||
UserID int `json:"user_id"`
|
||||
RoleID int `json:"role_id"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
const (
|
||||
JWTSecret = "fee516aa-8f5b-4248-a80c-bf467d40fd62"
|
||||
)
|
||||
|
||||
func ParseJWT(token string) (*UserClaims, error) {
|
||||
tokenClaims, err := jwt.ParseWithClaims(token, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(JWTSecret), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tokenClaims != nil {
|
||||
if claims, ok := tokenClaims.Claims.(*UserClaims); ok && tokenClaims.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
func GenerateJWT(userID int, roleID int) string {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims{
|
||||
UserID: userID,
|
||||
RoleID: roleID,
|
||||
StandardClaims: jwt.StandardClaims{},
|
||||
})
|
||||
str, err := token.SignedString([]byte(JWTSecret))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return str
|
||||
}
|
新增問題並參考
封鎖使用者