mirror of
				https://github.com/songquanpeng/message-pusher.git
				synced 2025-11-01 03:52:43 +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"
 | |
| 	"message-pusher/common"
 | |
| 	"message-pusher/model"
 | |
| 	"net/http"
 | |
| 	"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("无效的参数")
 | |
| 	}
 | |
| 	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("无法连接至 GitHub 服务器,请稍后重试!")
 | |
| 	}
 | |
| 	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("无法连接至 GitHub 服务器,请稍后重试!")
 | |
| 	}
 | |
| 	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("返回值非法,用户字段为空,请稍后重试!")
 | |
| 	}
 | |
| 	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": "管理员未开启通过 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": "管理员关闭了新用户注册",
 | |
| 			})
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if user.Status != common.UserStatusEnabled {
 | |
| 		c.JSON(http.StatusOK, gin.H{
 | |
| 			"message": "用户已被封禁",
 | |
| 			"success": false,
 | |
| 		})
 | |
| 		return
 | |
| 	}
 | |
| 	setupLogin(&user, c)
 | |
| }
 | |
| 
 | |
| func GitHubBind(c *gin.Context) {
 | |
| 	if !common.GitHubOAuthEnabled {
 | |
| 		c.JSON(http.StatusOK, gin.H{
 | |
| 			"success": false,
 | |
| 			"message": "管理员未开启通过 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": "该 GitHub 账户已被绑定",
 | |
| 		})
 | |
| 		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
 | |
| }
 | 
