mirror of https://github.com/Xhofe/alist
feat: support github login (#2639)
* Support Github Login * improve according to codefactor * fix due to last updates * optimization Co-authored-by: Noah Hsu <i@nn.ci>pull/2818/head
parent
c00dcc8f39
commit
83fe17c6ec
|
@ -145,6 +145,11 @@ func InitialSettings() []model.SettingItem {
|
|||
{Key: conf.SearchIndex, Value: "none", Type: conf.TypeSelect, Options: "database,bleve,none", Group: model.INDEX},
|
||||
{Key: conf.IgnorePaths, Value: "", Type: conf.TypeText, Group: model.INDEX, Flag: model.PRIVATE, Help: `one path per line`},
|
||||
{Key: conf.IndexProgress, Value: "{}", Type: conf.TypeText, Group: model.SINGLE, Flag: model.PRIVATE},
|
||||
|
||||
// GitHub settings
|
||||
{Key: conf.GithubClientId, Value: "", Type: conf.TypeString, Group: model.GITHUB, Flag: model.PRIVATE},
|
||||
{Key: conf.GithubClientSecrets, Value: "", Type: conf.TypeString, Group: model.GITHUB, Flag: model.PRIVATE},
|
||||
{Key: conf.GithubLoginEnabled, Value: "false", Type: conf.TypeBool, Group: model.GITHUB, Flag: model.PUBLIC},
|
||||
}
|
||||
if flags.Dev {
|
||||
initialSettingItems = append(initialSettingItems, []model.SettingItem{
|
||||
|
|
|
@ -53,6 +53,11 @@ const (
|
|||
// single
|
||||
Token = "token"
|
||||
IndexProgress = "index_progress"
|
||||
|
||||
//Github
|
||||
GithubClientId = "github_client_id"
|
||||
GithubClientSecrets = "github_client_secrets"
|
||||
GithubLoginEnabled = "github_login_enabled"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -21,6 +21,14 @@ func GetUserByName(username string) (*model.User, error) {
|
|||
return &user, nil
|
||||
}
|
||||
|
||||
func GetUserByGithubID(githubID int) (*model.User, error) {
|
||||
user := model.User{GithubID: githubID}
|
||||
if err := db.Where(user).First(&user).Error; err != nil {
|
||||
return nil, errors.Wrapf(err, "The Github ID is not associated with a user")
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func GetUserById(id uint) (*model.User, error) {
|
||||
var u model.User
|
||||
if err := db.First(&u, id).Error; err != nil {
|
||||
|
|
|
@ -8,6 +8,7 @@ const (
|
|||
GLOBAL
|
||||
ARIA2
|
||||
INDEX
|
||||
GITHUB
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -31,6 +31,7 @@ type User struct {
|
|||
// 9: webdav write
|
||||
Permission int32 `json:"permission"`
|
||||
OtpSecret string `json:"-"`
|
||||
GithubID int `json:"github_id"`
|
||||
}
|
||||
|
||||
func (u User) IsGuest() bool {
|
||||
|
|
|
@ -91,7 +91,7 @@ func CurrentUser(c *gin.Context) {
|
|||
}
|
||||
|
||||
func UpdateCurrent(c *gin.Context) {
|
||||
var req LoginReq
|
||||
var req model.User
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
common.ErrorResp(c, err, 400)
|
||||
return
|
||||
|
@ -101,6 +101,7 @@ func UpdateCurrent(c *gin.Context) {
|
|||
if req.Password != "" {
|
||||
user.Password = req.Password
|
||||
}
|
||||
user.GithubID = req.GithubID
|
||||
if err := op.UpdateUser(user); err != nil {
|
||||
common.ErrorResp(c, err, 500)
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package handles
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/db"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
func GithubLoginRedirect(c *gin.Context) {
|
||||
method := c.Query("method")
|
||||
callbackURL := c.Query("callback_url")
|
||||
withParams := c.Query("with_params")
|
||||
enabled, err := db.GetSettingItemByKey("github_login_enabled")
|
||||
clientId, err := db.GetSettingItemByKey("github_client_id")
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 400)
|
||||
return
|
||||
} else if enabled.Value == "true" {
|
||||
urlValues := url.Values{}
|
||||
urlValues.Add("client_id", clientId.Value)
|
||||
if method == "get_github_id" {
|
||||
urlValues.Add("allow_signup", "true")
|
||||
} else if method == "github_callback_login" {
|
||||
urlValues.Add("allow_signup", "false")
|
||||
}
|
||||
if method == "" {
|
||||
common.ErrorStrResp(c, "no method provided", 400)
|
||||
return
|
||||
}
|
||||
if withParams != "" {
|
||||
urlValues.Add("redirect_uri", common.GetApiUrl(c.Request)+"/api/auth/github_callback"+"?method="+method+"&callback_url="+callbackURL+"&with_params="+withParams)
|
||||
} else {
|
||||
urlValues.Add("redirect_uri", common.GetApiUrl(c.Request)+"/api/auth/github_callback"+"?method="+method+"&callback_url="+callbackURL)
|
||||
}
|
||||
c.Redirect(302, "https://github.com/login/oauth/authorize?"+urlValues.Encode())
|
||||
} else {
|
||||
common.ErrorStrResp(c, "github Login not enabled", 403)
|
||||
}
|
||||
}
|
||||
|
||||
var githubClient = resty.New().SetRetryCount(3)
|
||||
|
||||
func GithubLoginCallback(c *gin.Context) {
|
||||
argument := c.Query("method")
|
||||
callbackUrl := c.Query("callback_url")
|
||||
if argument == "get_github_id" || argument == "github_login" {
|
||||
enabled, err := db.GetSettingItemByKey("github_login_enabled")
|
||||
clientId, err := db.GetSettingItemByKey("github_client_id")
|
||||
clientSecret, err := db.GetSettingItemByKey("github_client_secrets")
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 400)
|
||||
return
|
||||
} else if enabled.Value == "true" {
|
||||
callbackCode := c.Query("code")
|
||||
if callbackCode == "" {
|
||||
common.ErrorStrResp(c, "No code provided", 400)
|
||||
return
|
||||
}
|
||||
resp, err := githubClient.R().SetHeader("content-type", "application/json").
|
||||
SetBody(map[string]string{
|
||||
"client_id": clientId.Value,
|
||||
"client_secret": clientSecret.Value,
|
||||
"code": callbackCode,
|
||||
"redirect_uri": common.GetApiUrl(c.Request) + "/api/auth/github_callback",
|
||||
}).Post("https://github.com/login/oauth/access_token")
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 400)
|
||||
return
|
||||
}
|
||||
accessToken := utils.Json.Get(resp.Body(), "access_token").ToString()
|
||||
resp, err = githubClient.R().SetHeader("Authorization", "Bearer "+accessToken).
|
||||
Get("https://api.github.com/user")
|
||||
ghUserID := utils.Json.Get(resp.Body(), "id").ToInt()
|
||||
if argument == "get_github_id" {
|
||||
c.Redirect(302, callbackUrl+"?githubID="+strconv.Itoa(ghUserID))
|
||||
}
|
||||
if argument == "github_login" {
|
||||
user, err := db.GetUserByGithubID(ghUserID)
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 400)
|
||||
}
|
||||
token, err := common.GenerateToken(user.Username)
|
||||
withParams := c.Query("with_params")
|
||||
if withParams == "true" {
|
||||
c.Redirect(302, callbackUrl+"&token="+token)
|
||||
} else if withParams == "false" {
|
||||
c.Redirect(302, callbackUrl+"?token="+token)
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
common.ErrorResp(c, errors.New("invalid request"), 500)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@ func Init(r *gin.Engine) {
|
|||
auth.POST("/me/update", handles.UpdateCurrent)
|
||||
auth.POST("/auth/2fa/generate", handles.Generate2FA)
|
||||
auth.POST("/auth/2fa/verify", handles.Verify2FA)
|
||||
auth.GET("/auth/github", handles.GithubLoginRedirect)
|
||||
auth.GET("/auth/github_callback", handles.GithubLoginCallback)
|
||||
|
||||
// no need auth
|
||||
public := api.Group("/public")
|
||||
|
|
Loading…
Reference in New Issue