xanzy / go-gitlab

GitLab Go SDK
Apache License 2.0
2.36k stars 935 forks source link

Adding Cookie client for embed code into Gitlab site tree #1906

Open aborche opened 4 months ago

aborche commented 4 months ago

When you embed your code into gitlab tree, with this patch you can use all session cookies for API requests.

svanharmelen commented 4 months ago

Can you elaborate on the use case for this? Is gitlab tree a tool I don't know about? 😅

Additionally I wonder if you could solve your use case using https://github.com/xanzy/go-gitlab/blob/main/client_options.go#L137? It allows you to pass in a func the would update each request. So I guess you could add a func here that would set the header you need/want?

aborche commented 4 months ago

Can you elaborate on the use case for this? Is gitlab tree a tool I don't know about? 😅

This is a dirty hack.

nginx['custom_gitlab_server_config'] = "location /deployhelper {\n proxy_pass http://localhost:8099;\n}\n"

after this you can embed any external code in your gitlab site tree and use gitlab api with current logged user context. For example, you can automate some hard subroutines or embed own analytics portal which process many api requests in one page/step.

PS: also i know how to add a custom menu item in gitlab without contributing code in main gitlab tree. For example custom "Deploy Helper" application image

svanharmelen commented 4 months ago

Hmm... I see.. So isn't it possible to use https://github.com/xanzy/go-gitlab/blob/main/client_options.go#L137 instead to accomplish the same result?

I'm a bit worried that adding this (and people starting using it) might lead to issues that I cannot oversee. For example what happens when a cookie gets updated or changed after you created the client? There is no way the client would recover from that I guess.

So I think I would prefer to not add this as a client type, but that you instead enable this using the option func I mentioned.

aborche commented 4 months ago

i have no idea how i can use WithRequestOptions. Can you provide an example for my case?


func GetCtxBaseURL(c *gin.Context, config Config) string {
    scheme := "http"
    if c.Request.Header.Get("X-Forwarded-Proto") != "" {
        scheme = c.Request.Header.Get("X-Forwarded-Proto")
    }
    GitlabAPIHost := c.Request.Host
    if !config.GitlabUrlFromHost {
        GitlabAPIHost = config.CustomGitlabURL
    }
    ctxBaseURL := scheme + "://" + GitlabAPIHost + "/api/v4/"
    return ctxBaseURL
}

func GetCtxCookies(c *gin.Context) (GitlabCookies []*http.Cookie) {
    GitlabAuthCookies := []string{"known_sign_in", "_gitlab_session"}
    for _, value := range c.Request.Cookies() {
        if slices.Contains(GitlabAuthCookies, value.Name) {
            GitlabCookies = append(GitlabCookies, value)
        }
    }
    return GitlabCookies
}

func APIClient(c *gin.Context, cfg conf.Config) (*gitlab.Client, error) {
    ctxBaseUrl := conf.GetCtxBaseURL(c, cfg)
    ctxSessionCookies := conf.GetCtxCookies(c)
    git, err := gitlab.NewCookieClient(ctxSessionCookies, gitlab.WithBaseURL(ctxBaseUrl))
    if err != nil {
        return nil, fmt.Errorf("Failed to create client: %v", err)
    }
    if len(ctxSessionCookies) < 2 {
        return nil, errors.New("no requested cookies found")
    }
    return git, nil
}

func GetUserInfo(c *gin.Context, cfg conf.Config) (*gitlab.User, error) {
    git, err := APIClient(c, cfg)
    if err != nil {
        return nil, err
    }
    users, _, err := git.Users.CurrentUser()
    if err != nil {
        return nil, err
    }
    return users, err
}

func main() {
    cfg, err := conf.LoadConfig()
    r := gin.Default()
    rg := r.Group(cfg.UrlPrefix)
    r.LoadHTMLGlob("templates/*")

    rg.GET("/userInfo", func(c *gin.Context) {
        uinfo, err := GetUserInfo(c, cfg)
        c.JSON(200, any(uinfo))
    }
}
aborche commented 3 months ago

Hmm... I see.. So isn't it possible to use https://github.com/xanzy/go-gitlab/blob/main/client_options.go#L137 instead to accomplish the same result?

No, we can't use clientOptions. When we work with cookie methods, no other authentication methods can be used. The go-gitlab client does not have initial authentication information from the user. It uses existing authentication tokens from the upstream request.