Introduce user repositories
This commit is contained in:
parent
4baa665693
commit
22638dcc51
7 changed files with 403 additions and 2 deletions
163
gitlab.go
Normal file
163
gitlab.go
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
OAUTH_GITLAB_FILE = ".gitlab-oauth-token"
|
||||
)
|
||||
|
||||
var (
|
||||
gitlabBaseURL = "https://gitlab.cri.epita.fr"
|
||||
gitlabClientID = ""
|
||||
gitlabSecret = ""
|
||||
gitlaboauth2Config oauth2.Config
|
||||
gitlaboidcVerifier *oidc.IDTokenVerifier
|
||||
gitlabToken *oauth2.Token
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&gitlabClientID, "gitlab-clientid", gitlabClientID, "ClientID for GitLab's OIDC")
|
||||
flag.StringVar(&gitlabSecret, "gitlab-secret", gitlabSecret, "Secret for GitLab's OIDC")
|
||||
}
|
||||
|
||||
func initializeGitLabOIDC(router *gin.Engine, authrouter *gin.RouterGroup, adminrouter *gin.RouterGroup) {
|
||||
adminrouter.GET("/auth/gitlabcri", redirectOAuth_GitLab)
|
||||
router.GET("/callback/gitlabcri/complete", GitLab_OAuth_complete)
|
||||
|
||||
if _, err := os.Stat(OAUTH_GITLAB_FILE); err == nil {
|
||||
gitlabToken, err = loadOAuth2Token(OAUTH_GITLAB_FILE)
|
||||
if err != nil {
|
||||
log.Println("Unable to load OAuth2 Token:", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if gitlabClientID != "" && gitlabSecret != "" {
|
||||
provider, err := oidc.NewProvider(context.Background(), gitlabBaseURL)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to setup oidc:", err)
|
||||
}
|
||||
|
||||
gitlaboauth2Config = oauth2.Config{
|
||||
ClientID: gitlabClientID,
|
||||
ClientSecret: gitlabSecret,
|
||||
RedirectURL: oidcRedirectURL + baseURL + "/callback/gitlabcri/complete",
|
||||
|
||||
// Discovery returns the OAuth2 endpoints.
|
||||
Endpoint: provider.Endpoint(),
|
||||
|
||||
// "openid" is a required scope for OpenID Connect flows.
|
||||
Scopes: []string{"api", "read_repository", "email"},
|
||||
}
|
||||
|
||||
oidcConfig := oidc.Config{
|
||||
ClientID: gitlabClientID,
|
||||
}
|
||||
gitlaboidcVerifier = provider.Verifier(&oidcConfig)
|
||||
|
||||
authrouter.GET("/api/gitlabcri/repositories", GitLab_getRepositories)
|
||||
}
|
||||
}
|
||||
|
||||
func loadOAuth2Token(file string) (*oauth2.Token, error) {
|
||||
fd, err := os.Open(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
var tok oauth2.Token
|
||||
err = json.NewDecoder(fd).Decode(&tok)
|
||||
|
||||
return &tok, err
|
||||
}
|
||||
|
||||
func saveOAuth2Token(file string, tok *oauth2.Token) error {
|
||||
fd, err := os.Create(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
return json.NewEncoder(fd).Encode(tok)
|
||||
}
|
||||
|
||||
func redirectOAuth_GitLab(c *gin.Context) {
|
||||
session := c.MustGet("Session").(*Session)
|
||||
|
||||
// Save next parameter
|
||||
if len(c.Request.URL.Query().Get("next")) > 0 {
|
||||
session.SetKey("gitlab-oidc-source", c.Request.URL.Query().Get("next"))
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusFound, gitlaboauth2Config.AuthCodeURL(hex.EncodeToString(session.Id)))
|
||||
}
|
||||
|
||||
func GitLab_OAuth_complete(c *gin.Context) {
|
||||
idsession, err := hex.DecodeString(c.Request.URL.Query().Get("state"))
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
session, err := getSession(idsession)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := gitlaboauth2Config.Exchange(c.Request.Context(), c.Request.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Failed to exchange token: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
gitlabToken = oauth2Token
|
||||
err = saveOAuth2Token(OAUTH_GITLAB_FILE, oauth2Token)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to save OAuth2 token: " + err.Error()})
|
||||
return
|
||||
|
||||
}
|
||||
log.Println("New GitLab OAuth2 session opened")
|
||||
|
||||
if source, ok := session.GetKey("gitlab-oidc-source"); ok {
|
||||
session.DeleteKey("gitlab-oidc-source")
|
||||
c.Redirect(http.StatusFound, baseURL+source.(string))
|
||||
} else {
|
||||
c.Redirect(http.StatusFound, baseURL+"/works")
|
||||
}
|
||||
session.Update()
|
||||
}
|
||||
|
||||
func GitLab_getRepositories(c *gin.Context) {
|
||||
client := gitlaboauth2Config.Client(c.Request.Context(), gitlabToken)
|
||||
|
||||
req, err := http.NewRequest("GET", gitlabBaseURL+"/api/v4/projects", nil)
|
||||
if err != nil {
|
||||
log.Println("Unable to create NewRequest before GitLab call: ", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when performing the GitLab request."})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Println("Unable to perform the GitLab request: ", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when performing the GitLab request."})
|
||||
return
|
||||
}
|
||||
|
||||
c.DataFromReader(resp.StatusCode, resp.ContentLength, resp.Header.Get("content-type"), resp.Body, nil)
|
||||
}
|
||||
Reference in a new issue