141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
package http
|
|
|
|
import (
|
|
"net/url"
|
|
"time"
|
|
|
|
"quyun/app/models"
|
|
"quyun/database/fields"
|
|
"quyun/database/schemas/public/model"
|
|
"quyun/pkg/utils"
|
|
"quyun/providers/jwt"
|
|
"quyun/providers/wechat"
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
"github.com/pkg/errors"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
StatePrefix = "sns_basic_auth"
|
|
salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
)
|
|
|
|
// @provider
|
|
type auth struct {
|
|
wechat *wechat.Client
|
|
jwt *jwt.JWT
|
|
}
|
|
|
|
// @Router /auth/login [get]
|
|
// @Bind code query
|
|
// @Bind state query
|
|
// @Bind redirect query
|
|
func (ctl *auth) Login(ctx fiber.Ctx, code, state, redirect string) error {
|
|
log.Debugf("code: %s, state: %s", code, state)
|
|
|
|
// get the openid
|
|
token, err := ctl.wechat.AuthorizeCode2Token(code)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to get openid")
|
|
}
|
|
log.Debugf("tokenInfo %+v", token)
|
|
|
|
stableToken, err := ctl.wechat.GetStableAccessToken()
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to get stable access token")
|
|
}
|
|
log.Infof("stableToken %+v", stableToken)
|
|
|
|
authUserInfo, err := ctl.wechat.AuthorizeUserInfo(token.AccessToken, token.Openid)
|
|
if err != nil {
|
|
log.Error("failed to get user info: ", err)
|
|
authUserInfo = &wechat.AuthorizeUserInfo{
|
|
City: "",
|
|
Country: "",
|
|
Headimgurl: utils.RandomAvatar(),
|
|
Nickname: utils.RandomNickname(),
|
|
Openid: token.Openid,
|
|
Privilege: []string{},
|
|
Province: "",
|
|
Sex: 0,
|
|
Unionid: "",
|
|
}
|
|
}
|
|
|
|
log.Debugf("Auth User Info: %+v", authUserInfo)
|
|
|
|
userModel := &model.Users{
|
|
Status: fields.UserStatusOk,
|
|
OpenID: token.GetOpenID(),
|
|
// Username: fmt.Sprintf("u_%s", gonanoid.MustGenerate(salt, 8)),
|
|
Username: authUserInfo.Nickname,
|
|
Avatar: &authUserInfo.Headimgurl,
|
|
Metas: fields.ToJson(fields.UserMetas{
|
|
City: authUserInfo.City,
|
|
Country: authUserInfo.Country,
|
|
HeadImageUrl: authUserInfo.Headimgurl,
|
|
Nickname: authUserInfo.Nickname,
|
|
Privilege: authUserInfo.Privilege,
|
|
Province: authUserInfo.Province,
|
|
Sex: authUserInfo.Sex,
|
|
}),
|
|
AuthToken: fields.ToJson(fields.UserAuthToken{
|
|
StableAccessToken: stableToken.AccessToken,
|
|
StableExpiresAt: time.Now().Add(time.Second * time.Duration(stableToken.ExpiresIn)),
|
|
AccessToken: token.AccessToken,
|
|
ExpiresAt: time.Now().Add(time.Second * time.Duration(token.ExpiresIn)),
|
|
IsSnapshotuser: token.IsSnapshotuser,
|
|
RefreshToken: token.RefreshToken,
|
|
Scope: token.Scope,
|
|
}),
|
|
}
|
|
user, err := models.Users.GetUserByOpenIDOrCreate(ctx.Context(), token.GetOpenID(), userModel)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to get user by openid")
|
|
}
|
|
|
|
jwtToken, err := ctl.jwt.CreateToken(ctl.jwt.CreateClaims(jwt.BaseClaims{UserID: user.ID}))
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to create token")
|
|
}
|
|
|
|
ctx.Cookie(&fiber.Cookie{
|
|
Name: "token",
|
|
Value: jwtToken,
|
|
Expires: time.Now().Add(24 * time.Hour),
|
|
HTTPOnly: true,
|
|
})
|
|
|
|
return ctx.Redirect().To(redirect)
|
|
}
|
|
|
|
// @Router /auth/wechat [get]
|
|
// @Bind redirect query
|
|
func (ctl *auth) Wechat(ctx fiber.Ctx, redirect string) error {
|
|
log.Debugf("%s, query: %v", ctx.OriginalURL(), ctx.Queries())
|
|
|
|
// 添加 redirect 参数
|
|
fullUrl := utils.FullURI(ctx)
|
|
u, err := url.Parse(fullUrl)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
query := u.Query()
|
|
query.Set("redirect", redirect)
|
|
u.RawQuery = query.Encode()
|
|
u.Path = "/v1/auth/login"
|
|
fullUrl = u.String()
|
|
|
|
log.Debug("redirect_uri: ", fullUrl)
|
|
|
|
to, err := ctl.wechat.ScopeAuthorizeURL(
|
|
wechat.ScopeAuthorizeURLWithRedirectURI(fullUrl),
|
|
)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to get wechat auth url")
|
|
}
|
|
|
|
return ctx.Redirect().To(to.String())
|
|
}
|