123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- 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) {
- user.FillUserByGitHubId()
- } else {
- 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
- }
- }
- 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
- }
- id := c.GetInt("id")
- user.Id = id
- 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
- }
|