EXPERIMENTAL: this endpoint is experimental and is subject to change.
(rw http.ResponseWriter, r *http.Request)
| 5676 | |
| 5677 | // EXPERIMENTAL: this endpoint is experimental and is subject to change. |
| 5678 | func (api *API) putChatTemplateAllowlist(rw http.ResponseWriter, r *http.Request) { |
| 5679 | ctx := r.Context() |
| 5680 | if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceDeploymentConfig) { |
| 5681 | httpapi.ResourceNotFound(rw) |
| 5682 | return |
| 5683 | } |
| 5684 | |
| 5685 | var req codersdk.ChatTemplateAllowlist |
| 5686 | if !httpapi.Read(ctx, rw, r, &req) { |
| 5687 | return |
| 5688 | } |
| 5689 | |
| 5690 | // Validate all entries are valid UUIDs and deduplicate. |
| 5691 | seen := make(map[string]struct{}, len(req.TemplateIDs)) |
| 5692 | deduped := make([]string, 0, len(req.TemplateIDs)) |
| 5693 | for _, id := range req.TemplateIDs { |
| 5694 | parsed, err := uuid.Parse(id) |
| 5695 | if err != nil { |
| 5696 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 5697 | Message: "Invalid template ID in allowlist.", |
| 5698 | Detail: fmt.Sprintf("%q is not a valid UUID.", id), |
| 5699 | }) |
| 5700 | return |
| 5701 | } |
| 5702 | // Canonicalize to lowercase so deduplication is |
| 5703 | // case-insensitive and stored values are consistent. |
| 5704 | canonical := parsed.String() |
| 5705 | if _, ok := seen[canonical]; !ok { |
| 5706 | seen[canonical] = struct{}{} |
| 5707 | deduped = append(deduped, canonical) |
| 5708 | } |
| 5709 | } |
| 5710 | |
| 5711 | // Convert to UUIDs for the database query. |
| 5712 | parsedUUIDs := make([]uuid.UUID, len(deduped)) |
| 5713 | for i, s := range deduped { |
| 5714 | // Already validated above, safe to ignore error. |
| 5715 | parsedUUIDs[i], _ = uuid.Parse(s) |
| 5716 | } |
| 5717 | |
| 5718 | raw, err := json.Marshal(deduped) |
| 5719 | if err != nil { |
| 5720 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 5721 | Message: "Internal error encoding template allowlist.", |
| 5722 | Detail: err.Error(), |
| 5723 | }) |
| 5724 | return |
| 5725 | } |
| 5726 | |
| 5727 | err = api.Database.InTx(func(tx database.Store) error { |
| 5728 | // Verify all IDs refer to existing, non-deprecated templates |
| 5729 | // in a single query. |
| 5730 | if len(parsedUUIDs) > 0 { |
| 5731 | found, err := tx.GetTemplatesWithFilter(ctx, database.GetTemplatesWithFilterParams{ |
| 5732 | IDs: parsedUUIDs, |
| 5733 | Deprecated: sql.NullBool{ |
| 5734 | Bool: false, |
| 5735 | Valid: true, |
nothing calls this directly
no test coverage detected