| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 | package controllerimport (	"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) {		user.FillUserByGitHubId()	} else {		if common.RegisterEnabled {			user.Username = "github_" + strconv.Itoa(model.GetMaxUserId()+1)			user.DisplayName = githubUser.Name			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)	user.FillUserById()	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}
 |