154 lines
4.2 KiB
Go
154 lines
4.2 KiB
Go
package auth
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"net/http"
|
|
"os"
|
|
"ripper/internal/app/github_auth"
|
|
"ripper/internal/middleware"
|
|
"ripper/internal/response"
|
|
jwtpkg "ripper/pkg/jwt"
|
|
"time"
|
|
)
|
|
|
|
type postLoginDeviceCodeRequest struct {
|
|
ClientId string `json:"client_id" form:"client_id"`
|
|
}
|
|
|
|
type postLoginDeviceCodeResponse struct {
|
|
DeviceCode string `json:"device_code"` // 设备代码
|
|
UserCode string `json:"user_code"` // 用户代码
|
|
VerificationUrl string `json:"verification_uri"` // 验证地址
|
|
ExpiresIn int `json:"expires_in"` // 过期时间
|
|
Interval int `json:"interval"` // 间隔时间
|
|
}
|
|
|
|
type loginDeviceRequestInfo struct {
|
|
Code string `json:"code"`
|
|
Authorization string `json:"authorization"`
|
|
DisplayUserName string `json:"displayUserName,omitempty"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
func postLoginDeviceCode(ctx *gin.Context) {
|
|
cli := postLoginDeviceCodeRequest{}
|
|
if err := ctx.ShouldBind(&cli); err != nil {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: -1,
|
|
Msg: "Invalid client id.",
|
|
}, false)
|
|
return
|
|
}
|
|
|
|
if cli.ClientId == "" {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: -1,
|
|
Msg: "Client id is required.",
|
|
}, false)
|
|
return
|
|
}
|
|
|
|
uid, devid, err := github_auth.BindClientToCode(cli.ClientId, 1800)
|
|
if err != nil {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: -1,
|
|
Msg: err.Error(),
|
|
}, false)
|
|
return
|
|
}
|
|
ctx.JSON(http.StatusOK, postLoginDeviceCodeResponse{
|
|
DeviceCode: devid,
|
|
UserCode: uid,
|
|
VerificationUrl: fmt.Sprintf("%s/login/device?user_code=%s", os.Getenv("DEFAULT_BASE_URL"), uid),
|
|
ExpiresIn: 1800,
|
|
Interval: 5,
|
|
})
|
|
}
|
|
|
|
func postLoginOauthAccessToken(ctx *gin.Context) {
|
|
v, exists := ctx.Get("client_auth_info")
|
|
if !exists {
|
|
ctx.JSON(http.StatusOK, gin.H{
|
|
"error": "authorization_pending",
|
|
"error_description": "The authorization request is still pending.",
|
|
"error_uri": "https://docs.github.com/developers/apps/authorizing-oauth-apps#error-codes-for-the-device-flow",
|
|
})
|
|
return
|
|
}
|
|
cliAuthInfo := v.(*github_auth.ClientAuthInfo)
|
|
t := time.Now()
|
|
t.Add(24 * 3 * time.Hour)
|
|
u, err := github_auth.GetClientAuthInfo(cliAuthInfo.UserCode)
|
|
if err != nil {
|
|
ctx.JSON(http.StatusOK, gin.H{
|
|
"error": "access_denied",
|
|
"error_description": "You must make a new request for a device code.",
|
|
"error_uri": "https://docs.github.com/developers/apps/authorizing-oauth-apps#error-codes-for-the-device-flow",
|
|
})
|
|
return
|
|
}
|
|
tk, _ := jwtpkg.CreateToken(&middleware.UserLoad{
|
|
UserDisplayName: cliAuthInfo.DisplayUserName,
|
|
CardCode: u.CardCode,
|
|
Client: cliAuthInfo.ClientId,
|
|
RegisteredClaims: jwtpkg.CreateStandardClaims(t.Unix(), "user"),
|
|
})
|
|
_ = github_auth.RemoveClientAuthInfoByDeviceCode(cliAuthInfo.ClientId)
|
|
ctx.JSON(http.StatusOK, gin.H{
|
|
"access_token": tk,
|
|
"scope": "",
|
|
"token_type": "bearer",
|
|
})
|
|
}
|
|
|
|
func postLoginDevice(ctx *gin.Context) {
|
|
var info loginDeviceRequestInfo
|
|
if err := response.BindStruct(ctx, &info); err != nil {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: 422,
|
|
Msg: "请求参数错误",
|
|
}, false)
|
|
return
|
|
}
|
|
// 验证密码
|
|
loginPassword := os.Getenv("LOGIN_PASSWORD")
|
|
if loginPassword != "" && info.Password != loginPassword {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: 422,
|
|
Msg: "访问密码错误",
|
|
}, false)
|
|
return
|
|
}
|
|
// 检查code是否存在
|
|
authInfo, err := github_auth.GetClientAuthInfo(info.Code)
|
|
if err != nil {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: 422,
|
|
Msg: "授权码填写错误",
|
|
}, false)
|
|
return
|
|
}
|
|
|
|
err = github_auth.UpdateClientAuthStatusByDeviceCode(authInfo.DeviceCode, info.Authorization, info.DisplayUserName)
|
|
if err != nil {
|
|
response.FailJson(ctx, response.FailStruct{
|
|
Code: 500,
|
|
Msg: "系统异常, 请稍后再试",
|
|
}, false)
|
|
return
|
|
}
|
|
response.SuccessJson(ctx, "ok")
|
|
}
|
|
|
|
func getLoginDevice(ctx *gin.Context) {
|
|
ctx.Header("Content-Type", "text/html; charset=utf-8")
|
|
ctx.HTML(http.StatusOK, "code.html", gin.H{})
|
|
}
|
|
|
|
func getHelpPage(ctx *gin.Context) {
|
|
ctx.Header("Content-Type", "text/html; charset=utf-8")
|
|
ctx.HTML(http.StatusOK, "help.html", gin.H{})
|
|
}
|