fix: improve error message when deleting organization with resources (#17049)

Closes
[coder/internal#477](https://github.com/coder/internal/issues/477)

![Screenshot 2025-03-21 at 11 25
57 AM](https://github.com/user-attachments/assets/50cc03e9-395d-4fc7-8882-18cb66b1fac9)

I'm solving this issue in two parts:

1. Updated the postgres function so that it doesn't omit 0 values in the
error
2. Created a new query to fetch the number of resources associated with
an organization and using that information to provider a cleaner error
message to the frontend

> **_NOTE:_** SQL is not my strong suit, and the code was created with
the help of AI. So I'd take extra time looking over what I wrote there
This commit is contained in:
brettkolodny
2025-03-25 15:31:24 -04:00
committed by GitHub
parent 2c53f7ae7c
commit cf10d98aab
13 changed files with 416 additions and 22 deletions

View File

@ -4,6 +4,7 @@ import (
"database/sql"
"fmt"
"net/http"
"strings"
"github.com/google/uuid"
"golang.org/x/xerrors"
@ -161,10 +162,41 @@ func (api *API) deleteOrganization(rw http.ResponseWriter, r *http.Request) {
return nil
}, nil)
if err != nil {
orgResourcesRow, queryErr := api.Database.GetOrganizationResourceCountByID(ctx, organization.ID)
if queryErr != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error deleting organization.",
Detail: fmt.Sprintf("delete organization: %s", err.Error()),
})
return
}
detailParts := make([]string, 0)
addDetailPart := func(resource string, count int64) {
if count == 1 {
detailParts = append(detailParts, fmt.Sprintf("1 %s", resource))
} else if count > 1 {
detailParts = append(detailParts, fmt.Sprintf("%d %ss", count, resource))
}
}
addDetailPart("workspace", orgResourcesRow.WorkspaceCount)
addDetailPart("template", orgResourcesRow.TemplateCount)
// There will always be one member and group so instead we need to check that
// the count is greater than one.
addDetailPart("member", orgResourcesRow.MemberCount-1)
addDetailPart("group", orgResourcesRow.GroupCount-1)
addDetailPart("provisioner key", orgResourcesRow.ProvisionerKeyCount)
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error deleting organization.",
Detail: fmt.Sprintf("delete organization: %s", err.Error()),
Message: "Error deleting organization.",
Detail: fmt.Sprintf("This organization has %s that must be deleted first.", strings.Join(detailParts, ", ")),
})
return
}