feat: add support for coder_git_auth data source (#6334)

* Add git auth providers schema

* Pipe git auth providers to the schema

* Add git auth providers to the API

* Add gitauth endpoint to query authenticated state

* Add endpoint to query git state

* Use BroadcastChannel to automatically authenticate with Git

* Add error validation for submitting the create workspace form

* Fix panic on template dry-run

* Add tests for the template version Git auth endpoint

* Show error if no gitauth is configured

* Add gitauth to cliui

* Fix unused method receiver

* Fix linting errors

* Fix dbauthz querier test

* Fix make gen

* Add JavaScript test for git auth

* Fix bad error message

* Fix provisionerd test race

See https://github.com/coder/coder/actions/runs/4277960646/jobs/7447232814

* Fix requested changes

* Add comment to CreateWorkspacePageView
This commit is contained in:
Kyle Carberry
2023-02-27 10:18:19 -06:00
committed by GitHub
parent 3d8b77d6f1
commit 7f226d4f90
64 changed files with 2788 additions and 861 deletions
+102
View File
@@ -19,6 +19,7 @@ import (
"github.com/coder/coder/coderd/audit"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/gitauth"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/parameter"
@@ -243,6 +244,107 @@ func (api *API) templateVersionRichParameters(rw http.ResponseWriter, r *http.Re
httpapi.Write(ctx, rw, http.StatusOK, templateVersionParameters)
}
// @Summary Get git auth by template version
// @ID get-git-auth-by-template-version
// @Security CoderSessionToken
// @Produce json
// @Tags Templates
// @Param templateversion path string true "Template version ID" format(uuid)
// @Success 200 {array} codersdk.TemplateVersionGitAuth
// @Router /templateversions/{templateversion}/gitauth [get]
func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var (
apiKey = httpmw.APIKey(r)
templateVersion = httpmw.TemplateVersionParam(r)
template = httpmw.TemplateParam(r)
)
if !api.Authorize(r, rbac.ActionRead, templateVersion.RBACObject(template)) {
httpapi.ResourceNotFound(rw)
return
}
rawProviders := templateVersion.GitAuthProviders
providers := make([]codersdk.TemplateVersionGitAuth, 0)
for _, rawProvider := range rawProviders {
var config *gitauth.Config
for _, provider := range api.GitAuthConfigs {
if provider.ID == rawProvider {
config = provider
break
}
}
if config == nil {
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("The template version references a Git auth provider %q that no longer exists.", rawProvider),
Detail: "You'll need to update the template version to use a different provider.",
})
return
}
// This is the URL that will redirect the user with a state token.
redirectURL, err := api.AccessURL.Parse(fmt.Sprintf("/gitauth/%s", config.ID))
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to parse access URL.",
Detail: err.Error(),
})
return
}
query := redirectURL.Query()
// The frontend uses a BroadcastChannel to notify listening pages for
// Git auth updates if the "notify" query parameter is set.
//
// It's important we do this in the backend, because the same endpoint
// is used for CLI authentication.
query.Add("redirect", "/gitauth?notify")
redirectURL.RawQuery = query.Encode()
provider := codersdk.TemplateVersionGitAuth{
ID: config.ID,
Type: config.Type,
AuthenticateURL: redirectURL.String(),
}
authLink, err := api.Database.GetGitAuthLink(ctx, database.GetGitAuthLinkParams{
ProviderID: config.ID,
UserID: apiKey.UserID,
})
// If there isn't an auth link, then the user just isn't authenticated.
if errors.Is(err, sql.ErrNoRows) {
providers = append(providers, provider)
continue
}
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching git auth link.",
Detail: err.Error(),
})
return
}
_, updated, err := refreshGitToken(ctx, api.Database, apiKey.UserID, config, authLink)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to refresh git auth token.",
Detail: err.Error(),
})
return
}
// If the token couldn't be validated, then we assume the user isn't
// authenticated and return early.
if !updated {
providers = append(providers, provider)
continue
}
provider.Authenticated = true
providers = append(providers, provider)
}
httpapi.Write(ctx, rw, http.StatusOK, providers)
}
// @Summary Get template variables by template version
// @ID get-template-variables-by-template-version
// @Security CoderSessionToken