MCPcopy Index your code
hub / github.com/coder/coder / upsertUserAIProviderKey

Method upsertUserAIProviderKey

coderd/exp_chats.go:6570–6644  ·  view source on GitHub ↗
(rw http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

6568}
6569
6570func (api *API) upsertUserAIProviderKey(rw http.ResponseWriter, r *http.Request) {
6571 ctx := r.Context()
6572 if !api.DeploymentValues.AI.BridgeConfig.AllowBYOK.Value() {
6573 httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{Message: "BYOK is disabled."})
6574 return
6575 }
6576 targetUser := httpmw.UserParam(r)
6577 providerID, err := parseUserAIProviderID(r)
6578 if err != nil {
6579 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "Invalid AI provider ID."})
6580 return
6581 }
6582 //nolint:gocritic // Users can attach their own key to an enabled provider without AI provider admin permissions.
6583 metadataCtx := dbauthz.AsAIProviderMetadataReader(ctx)
6584 provider, err := api.Database.GetAIProviderByID(metadataCtx, providerID)
6585 if err != nil {
6586 if errors.Is(err, sql.ErrNoRows) {
6587 httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{Message: "AI provider not found."})
6588 return
6589 }
6590 api.Logger.Error(ctx, "failed to get AI provider", slog.Error(err), slog.F("ai_provider_id", providerID))
6591 httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{Message: "Failed to get AI provider."})
6592 return
6593 }
6594 if !provider.Enabled {
6595 httpapi.Write(ctx, rw, http.StatusPreconditionFailed, codersdk.Response{Message: "AI provider is disabled."})
6596 return
6597 }
6598 var req codersdk.CreateUserAIProviderKeyRequest
6599 if !httpapi.Read(ctx, rw, r, &req) {
6600 return
6601 }
6602 if err := validateChatProviderAPIKeySize(req.APIKey); err != nil {
6603 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
6604 Message: "API key too large.",
6605 Detail: err.Error(),
6606 })
6607 return
6608 }
6609 if req.APIKey == "" {
6610 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "API key is required."})
6611 return
6612 }
6613 if strings.TrimSpace(req.APIKey) != req.APIKey {
6614 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "API key must not contain leading or trailing whitespace."})
6615 return
6616 }
6617 providerKeys, err := api.Database.GetAIProviderKeyPresence(metadataCtx, []uuid.UUID{providerID})
6618 if err != nil {
6619 api.Logger.Error(ctx, "failed to list AI provider key presence", slog.Error(err), slog.F("ai_provider_id", providerID))
6620 httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{Message: "Failed to list AI provider keys."})
6621 return
6622 }
6623 now := api.Clock.Now()
6624 _, err = api.Database.UpsertUserAIProviderKey(ctx, database.UpsertUserAIProviderKeyParams{
6625 ID: uuid.New(),
6626 UserID: targetUser.ID,
6627 AIProviderID: providerID,

Callers 1

Calls 15

WriteFunction · 0.92
UserParamFunction · 0.92
ReadFunction · 0.92
parseUserAIProviderIDFunction · 0.85
convertAIProviderSummaryFunction · 0.85
ContextMethod · 0.65
GetAIProviderByIDMethod · 0.65
NewMethod · 0.65

Tested by

no test coverage detected