mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-09-27 21:56:39 +08:00
208 lines
4.7 KiB
Go
208 lines
4.7 KiB
Go
package controller
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/gin-contrib/sessions"
|
||
"github.com/gin-gonic/gin"
|
||
"net/http"
|
||
"one-api/common"
|
||
"one-api/model"
|
||
"strconv"
|
||
"time"
|
||
)
|
||
|
||
type GitHubOAuthResponse struct {
|
||
AccessToken string `json:"access_token"`
|
||
Scope string `json:"scope"`
|
||
TokenType string `json:"token_type"`
|
||
}
|
||
|
||
type GitHubUser struct {
|
||
Login string `json:"login"`
|
||
Name string `json:"name"`
|
||
Email string `json:"email"`
|
||
}
|
||
|
||
func getGitHubUserInfoByCode(code string) (*GitHubUser, error) {
|
||
if code == "" {
|
||
return nil, errors.New("invalid parameter")
|
||
}
|
||
values := map[string]string{"client_id": common.GitHubClientId, "client_secret": common.GitHubClientSecret, "code": code}
|
||
jsonData, err := json.Marshal(values)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req, err := http.NewRequest("POST", "https://github.com/login/oauth/access_token", bytes.NewBuffer(jsonData))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
req.Header.Set("Accept", "application/json")
|
||
client := http.Client{
|
||
Timeout: 5 * time.Second,
|
||
}
|
||
res, err := client.Do(req)
|
||
if err != nil {
|
||
common.SysLog(err.Error())
|
||
return nil, errors.New("Unable to connect to GitHub servers, please try again later!")
|
||
}
|
||
defer res.Body.Close()
|
||
var oAuthResponse GitHubOAuthResponse
|
||
err = json.NewDecoder(res.Body).Decode(&oAuthResponse)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req, err = http.NewRequest("GET", "https://api.github.com/user", nil)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", oAuthResponse.AccessToken))
|
||
res2, err := client.Do(req)
|
||
if err != nil {
|
||
common.SysLog(err.Error())
|
||
return nil, errors.New("Unable to connect to GitHub server, please try again later!")
|
||
}
|
||
defer res2.Body.Close()
|
||
var githubUser GitHubUser
|
||
err = json.NewDecoder(res2.Body).Decode(&githubUser)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if githubUser.Login == "" {
|
||
return nil, errors.New("ilegal return value, user field is empty, please try again later!")
|
||
}
|
||
return &githubUser, nil
|
||
}
|
||
|
||
func GitHubOAuth(c *gin.Context) {
|
||
session := sessions.Default(c)
|
||
username := session.Get("username")
|
||
if username != nil {
|
||
GitHubBind(c)
|
||
return
|
||
}
|
||
|
||
if !common.GitHubOAuthEnabled {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": "The administrator has not enabled login and registration through GitHub",
|
||
})
|
||
return
|
||
}
|
||
code := c.Query("code")
|
||
githubUser, err := getGitHubUserInfoByCode(code)
|
||
if err != nil {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
user := model.User{
|
||
GitHubId: githubUser.Login,
|
||
}
|
||
if model.IsGitHubIdAlreadyTaken(user.GitHubId) {
|
||
err := user.FillUserByGitHubId()
|
||
if err != nil {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
} else {
|
||
if common.RegisterEnabled {
|
||
user.Username = "github_" + strconv.Itoa(model.GetMaxUserId()+1)
|
||
if githubUser.Name != "" {
|
||
user.DisplayName = githubUser.Name
|
||
} else {
|
||
user.DisplayName = "GitHub User"
|
||
}
|
||
user.Email = githubUser.Email
|
||
user.Role = common.RoleCommonUser
|
||
user.Status = common.UserStatusEnabled
|
||
|
||
if err := user.Insert(); err != nil {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
} else {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": "Admin turned off new user registration",
|
||
})
|
||
return
|
||
}
|
||
}
|
||
|
||
if user.Status != common.UserStatusEnabled {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"message": "User has been banned",
|
||
"success": false,
|
||
})
|
||
return
|
||
}
|
||
setupLogin(&user, c)
|
||
}
|
||
|
||
func GitHubBind(c *gin.Context) {
|
||
if !common.GitHubOAuthEnabled {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": "The administrator has not enabled login and registration through GitHub",
|
||
})
|
||
return
|
||
}
|
||
code := c.Query("code")
|
||
githubUser, err := getGitHubUserInfoByCode(code)
|
||
if err != nil {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
user := model.User{
|
||
GitHubId: githubUser.Login,
|
||
}
|
||
if model.IsGitHubIdAlreadyTaken(user.GitHubId) {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": "The GitHub account has been bound",
|
||
})
|
||
return
|
||
}
|
||
session := sessions.Default(c)
|
||
id := session.Get("id")
|
||
// id := c.GetInt("id") // critical bug!
|
||
user.Id = id.(int)
|
||
err = user.FillUserById()
|
||
if err != nil {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
user.GitHubId = githubUser.Login
|
||
err = user.Update(false)
|
||
if err != nil {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": false,
|
||
"message": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": true,
|
||
"message": "bind",
|
||
})
|
||
return
|
||
}
|