feat: add user-level parameter autofill (#11731)

This PR solves #10478 by auto-filling previously used template values in create and update workspace flows.

I decided against explicit user values in settings for these reasons:

* Autofill is far easier to implement
* Users benefit from autofill _by default_ — we don't need to teach them new concepts
* If we decide that autofill creates more harm than good, we can remove it without breaking compatibility
This commit is contained in:
Ammar Bandukwala
2024-01-30 16:02:21 -06:00
committed by GitHub
parent aeb4112513
commit adbb025e74
44 changed files with 862 additions and 137 deletions

View File

@ -569,6 +569,57 @@ func (api *API) userByName(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.User(user, organizationIDs))
}
// Returns recent build parameters for the signed-in user.
//
// @Summary Get autofill build parameters for user
// @ID get-autofill-build-parameters-for-user
// @Security CoderSessionToken
// @Produce json
// @Tags Users
// @Param user path string true "User ID, username, or me"
// @Param template_id query string true "Template ID"
// @Success 200 {array} codersdk.UserParameter
// @Router /users/{user}/autofill-parameters [get]
func (api *API) userAutofillParameters(rw http.ResponseWriter, r *http.Request) {
user := httpmw.UserParam(r)
p := httpapi.NewQueryParamParser().Required("template_id")
templateID := p.UUID(r.URL.Query(), uuid.UUID{}, "template_id")
p.ErrorExcessParams(r.URL.Query())
if len(p.Errors) > 0 {
httpapi.Write(r.Context(), rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid query parameters.",
Validations: p.Errors,
})
return
}
params, err := api.Database.GetUserWorkspaceBuildParameters(
r.Context(),
database.GetUserWorkspaceBuildParametersParams{
OwnerID: user.ID,
TemplateID: templateID,
},
)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(r.Context(), rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's parameters.",
Detail: err.Error(),
})
return
}
sdkParams := []codersdk.UserParameter{}
for _, param := range params {
sdkParams = append(sdkParams, codersdk.UserParameter{
Name: param.Name,
Value: param.Value,
})
}
httpapi.Write(r.Context(), rw, http.StatusOK, sdkParams)
}
// Returns the user's login type. This only works if the api key for authorization
// and the requested user match. Eg: 'me'
//