Skip to content

Commit f19e5fa

Browse files
committed
Replace sql.ErrNoRow checks
1 parent b33e7f6 commit f19e5fa

19 files changed

+47
-66
lines changed

coderd/apikey.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package coderd
33
import (
44
"context"
55
"crypto/sha256"
6-
"database/sql"
7-
"errors"
86
"fmt"
97
"net"
108
"net/http"
@@ -167,7 +165,7 @@ func (api *API) apiKeyByID(rw http.ResponseWriter, r *http.Request) {
167165

168166
keyID := chi.URLParam(r, "keyid")
169167
key, err := api.Database.GetAPIKeyByID(ctx, keyID)
170-
if errors.Is(err, sql.ErrNoRows) {
168+
if httpapi.Is404Error(err) {
171169
httpapi.ResourceNotFound(rw)
172170
return
173171
}
@@ -202,7 +200,7 @@ func (api *API) apiKeyByName(rw http.ResponseWriter, r *http.Request) {
202200
TokenName: tokenName,
203201
UserID: user.ID,
204202
})
205-
if errors.Is(err, sql.ErrNoRows) {
203+
if httpapi.Is404Error(err) {
206204
httpapi.ResourceNotFound(rw)
207205
return
208206
}
@@ -323,7 +321,7 @@ func (api *API) deleteAPIKey(rw http.ResponseWriter, r *http.Request) {
323321
defer commitAudit()
324322

325323
err = api.Database.DeleteAPIKeyByID(ctx, keyID)
326-
if errors.Is(err, sql.ErrNoRows) {
324+
if httpapi.Is404Error(err) {
327325
httpapi.ResourceNotFound(rw)
328326
return
329327
}

coderd/files.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (api *API) fileByID(rw http.ResponseWriter, r *http.Request) {
126126
}
127127

128128
file, err := api.Database.GetFileByID(ctx, id)
129-
if errors.Is(err, sql.ErrNoRows) {
129+
if httpapi.Is404Error(err) {
130130
httpapi.ResourceNotFound(rw)
131131
return
132132
}

coderd/httpapi/httpapi.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package httpapi
33
import (
44
"bytes"
55
"context"
6+
"database/sql"
67
"encoding/json"
78
"errors"
89
"flag"
@@ -12,6 +13,9 @@ import (
1213
"strings"
1314
"time"
1415

16+
"github.com/coder/coder/coderd/database/dbauthz"
17+
"github.com/coder/coder/coderd/rbac"
18+
1519
"github.com/go-playground/validator/v10"
1620
"golang.org/x/xerrors"
1721

@@ -80,6 +84,16 @@ func init() {
8084
}
8185
}
8286

87+
// Is404Error returns true if the given error should return a 404 status code.
88+
// Both actual 404s and unauthorized errors should return 404s to not leak
89+
// information about the existence of resources.
90+
func Is404Error(err error) bool {
91+
if err == nil {
92+
return false
93+
}
94+
return xerrors.Is(err, sql.ErrNoRows) || dbauthz.IsNotAuthorizedError(err) || rbac.IsUnauthorizedError(err)
95+
}
96+
8397
// Convenience error functions don't take contexts since their responses are
8498
// static, it doesn't make much sense to trace them.
8599

coderd/httpmw/groupparam.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ package httpmw
22

33
import (
44
"context"
5-
"database/sql"
6-
"errors"
75
"net/http"
86

97
"github.com/go-chi/chi/v5"
10-
"golang.org/x/xerrors"
118

129
"github.com/coder/coder/coderd/database"
1310
"github.com/coder/coder/coderd/httpapi"
@@ -45,7 +42,7 @@ func ExtractGroupByNameParam(db database.Store) func(http.Handler) http.Handler
4542
OrganizationID: org.ID,
4643
Name: name,
4744
})
48-
if xerrors.Is(err, sql.ErrNoRows) {
45+
if httpapi.Is404Error(err) {
4946
httpapi.ResourceNotFound(rw)
5047
return
5148
}
@@ -73,7 +70,7 @@ func ExtractGroupParam(db database.Store) func(http.Handler) http.Handler {
7370
}
7471

7572
group, err := db.GetGroupByID(r.Context(), groupID)
76-
if errors.Is(err, sql.ErrNoRows) {
73+
if httpapi.Is404Error(err) {
7774
httpapi.ResourceNotFound(rw)
7875
return
7976
}

coderd/httpmw/organizationparam.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package httpmw
22

33
import (
44
"context"
5-
"database/sql"
6-
"errors"
75
"net/http"
86

97
"github.com/coder/coder/coderd/database"
@@ -47,7 +45,7 @@ func ExtractOrganizationParam(db database.Store) func(http.Handler) http.Handler
4745
}
4846

4947
organization, err := db.GetOrganizationByID(ctx, orgID)
50-
if errors.Is(err, sql.ErrNoRows) {
48+
if httpapi.Is404Error(err) {
5149
httpapi.ResourceNotFound(rw)
5250
return
5351
}
@@ -77,7 +75,7 @@ func ExtractOrganizationMemberParam(db database.Store) func(http.Handler) http.H
7775
OrganizationID: organization.ID,
7876
UserID: user.ID,
7977
})
80-
if errors.Is(err, sql.ErrNoRows) {
78+
if httpapi.Is404Error(err) {
8179
httpapi.ResourceNotFound(rw)
8280
return
8381
}

coderd/httpmw/templateparam.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package httpmw
22

33
import (
44
"context"
5-
"database/sql"
6-
"errors"
75
"net/http"
86

97
"github.com/go-chi/chi/v5"
@@ -34,7 +32,7 @@ func ExtractTemplateParam(db database.Store) func(http.Handler) http.Handler {
3432
return
3533
}
3634
template, err := db.GetTemplateByID(r.Context(), templateID)
37-
if errors.Is(err, sql.ErrNoRows) || (err == nil && template.Deleted) {
35+
if httpapi.Is404Error(err) || (err == nil && template.Deleted) {
3836
httpapi.ResourceNotFound(rw)
3937
return
4038
}

coderd/httpmw/templateversionparam.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package httpmw
33
import (
44
"context"
55
"database/sql"
6-
"errors"
76
"net/http"
87

98
"github.com/go-chi/chi/v5"
@@ -35,7 +34,7 @@ func ExtractTemplateVersionParam(db database.Store) func(http.Handler) http.Hand
3534
return
3635
}
3736
templateVersion, err := db.GetTemplateVersionByID(ctx, templateVersionID)
38-
if errors.Is(err, sql.ErrNoRows) {
37+
if httpapi.Is404Error(err) {
3938
httpapi.ResourceNotFound(rw)
4039
return
4140
}

coderd/httpmw/userparam.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ package httpmw
22

33
import (
44
"context"
5-
"database/sql"
65
"net/http"
76

8-
"golang.org/x/xerrors"
9-
107
"github.com/go-chi/chi/v5"
118
"github.com/google/uuid"
129

@@ -71,7 +68,7 @@ func ExtractUserParam(db database.Store, redirectToLoginOnMe bool) func(http.Han
7168
}
7269
//nolint:gocritic // System needs to be able to get user from param.
7370
user, err = db.GetUserByID(dbauthz.AsSystemRestricted(ctx), apiKey.UserID)
74-
if xerrors.Is(err, sql.ErrNoRows) {
71+
if httpapi.Is404Error(err) {
7572
httpapi.ResourceNotFound(rw)
7673
return
7774
}

coderd/httpmw/workspacebuildparam.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package httpmw
22

33
import (
44
"context"
5-
"database/sql"
6-
"errors"
75
"net/http"
86

97
"github.com/go-chi/chi/v5"
@@ -34,7 +32,7 @@ func ExtractWorkspaceBuildParam(db database.Store) func(http.Handler) http.Handl
3432
return
3533
}
3634
workspaceBuild, err := db.GetWorkspaceBuildByID(ctx, workspaceBuildID)
37-
if errors.Is(err, sql.ErrNoRows) {
35+
if httpapi.Is404Error(err) {
3836
httpapi.ResourceNotFound(rw)
3937
return
4038
}

coderd/httpmw/workspaceparam.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package httpmw
22

33
import (
44
"context"
5-
"database/sql"
6-
"errors"
75
"fmt"
86
"net/http"
97
"strings"
@@ -37,7 +35,7 @@ func ExtractWorkspaceParam(db database.Store) func(http.Handler) http.Handler {
3735
return
3836
}
3937
workspace, err := db.GetWorkspaceByID(ctx, workspaceID)
40-
if errors.Is(err, sql.ErrNoRows) {
38+
if httpapi.Is404Error(err) {
4139
httpapi.ResourceNotFound(rw)
4240
return
4341
}
@@ -74,7 +72,7 @@ func ExtractWorkspaceAndAgentParam(db database.Store) func(http.Handler) http.Ha
7472
Name: workspaceParts[0],
7573
})
7674
if err != nil {
77-
if errors.Is(err, sql.ErrNoRows) {
75+
if httpapi.Is404Error(err) {
7876
httpapi.ResourceNotFound(rw)
7977
return
8078
}

coderd/parameters.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (api *API) deleteParameter(rw http.ResponseWriter, r *http.Request) {
141141
ScopeID: scopeID,
142142
Name: name,
143143
})
144-
if errors.Is(err, sql.ErrNoRows) {
144+
if httpapi.Is404Error(err) {
145145
httpapi.ResourceNotFound(rw)
146146
return
147147
}

coderd/templates.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
407407
Name: templateName,
408408
})
409409
if err != nil {
410-
if errors.Is(err, sql.ErrNoRows) {
410+
if httpapi.Is404Error(err) {
411411
httpapi.ResourceNotFound(rw)
412412
return
413413
}
@@ -419,11 +419,6 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
419419
return
420420
}
421421

422-
if !api.Authorize(r, rbac.ActionRead, template) {
423-
httpapi.ResourceNotFound(rw)
424-
return
425-
}
426-
427422
createdByNameMap, err := getCreatedByNamesByTemplateIDs(ctx, api.Database, []database.Template{template})
428423
if err != nil {
429424
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -583,10 +578,6 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
583578
func (api *API) templateDAUs(rw http.ResponseWriter, r *http.Request) {
584579
ctx := r.Context()
585580
template := httpmw.TemplateParam(r)
586-
if !api.Authorize(r, rbac.ActionRead, template) {
587-
httpapi.ResourceNotFound(rw)
588-
return
589-
}
590581

591582
resp, _ := api.metricsCache.TemplateDAUs(template.ID)
592583
if resp == nil || resp.Entries == nil {

coderd/templateversions.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re
737737
}
738738

739739
job, err := api.Database.GetProvisionerJobByID(ctx, jobUUID)
740-
if xerrors.Is(err, sql.ErrNoRows) {
740+
if httpapi.Is404Error(err) {
741741
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
742742
Message: fmt.Sprintf("Provisioner job %q not found.", jobUUID),
743743
})
@@ -905,7 +905,7 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
905905
},
906906
Name: templateVersionName,
907907
})
908-
if errors.Is(err, sql.ErrNoRows) {
908+
if httpapi.Is404Error(err) {
909909
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
910910
Message: fmt.Sprintf("No template version found by name %q.", templateVersionName),
911911
})
@@ -959,7 +959,7 @@ func (api *API) templateVersionByOrganizationTemplateAndName(rw http.ResponseWri
959959
Name: templateName,
960960
})
961961
if err != nil {
962-
if errors.Is(err, sql.ErrNoRows) {
962+
if httpapi.Is404Error(err) {
963963
httpapi.ResourceNotFound(rw)
964964
return
965965
}
@@ -979,7 +979,7 @@ func (api *API) templateVersionByOrganizationTemplateAndName(rw http.ResponseWri
979979
},
980980
Name: templateVersionName,
981981
})
982-
if errors.Is(err, sql.ErrNoRows) {
982+
if httpapi.Is404Error(err) {
983983
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
984984
Message: fmt.Sprintf("No template version found by name %q.", templateVersionName),
985985
})
@@ -1032,7 +1032,7 @@ func (api *API) previousTemplateVersionByOrganizationTemplateAndName(rw http.Res
10321032
Name: templateName,
10331033
})
10341034
if err != nil {
1035-
if errors.Is(err, sql.ErrNoRows) {
1035+
if httpapi.Is404Error(err) {
10361036
httpapi.ResourceNotFound(rw)
10371037
return
10381038
}
@@ -1053,7 +1053,7 @@ func (api *API) previousTemplateVersionByOrganizationTemplateAndName(rw http.Res
10531053
Name: templateVersionName,
10541054
})
10551055
if err != nil {
1056-
if xerrors.Is(err, sql.ErrNoRows) {
1056+
if httpapi.Is404Error(err) {
10571057
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
10581058
Message: fmt.Sprintf("No template version found by name %q.", templateVersionName),
10591059
})
@@ -1073,7 +1073,7 @@ func (api *API) previousTemplateVersionByOrganizationTemplateAndName(rw http.Res
10731073
TemplateID: templateVersion.TemplateID,
10741074
})
10751075
if err != nil {
1076-
if xerrors.Is(err, sql.ErrNoRows) {
1076+
if httpapi.Is404Error(err) {
10771077
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
10781078
Message: fmt.Sprintf("No previous template version found for %q.", templateVersionName),
10791079
})
@@ -1138,7 +1138,7 @@ func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Reque
11381138
return
11391139
}
11401140
version, err := api.Database.GetTemplateVersionByID(ctx, req.ID)
1141-
if errors.Is(err, sql.ErrNoRows) {
1141+
if httpapi.Is404Error(err) {
11421142
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
11431143
Message: "Template version not found.",
11441144
})
@@ -1222,7 +1222,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
12221222

12231223
if req.TemplateID != uuid.Nil {
12241224
_, err := api.Database.GetTemplateByID(ctx, req.TemplateID)
1225-
if errors.Is(err, sql.ErrNoRows) {
1225+
if httpapi.Is404Error(err) {
12261226
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
12271227
Message: "Template does not exist.",
12281228
})
@@ -1318,7 +1318,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
13181318

13191319
if req.FileID != uuid.Nil {
13201320
file, err = api.Database.GetFileByID(ctx, req.FileID)
1321-
if errors.Is(err, sql.ErrNoRows) {
1321+
if httpapi.Is404Error(err) {
13221322
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
13231323
Message: "File not found.",
13241324
})

coderd/users.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
314314
}
315315

316316
_, err = api.Database.GetOrganizationByID(ctx, req.OrganizationID)
317-
if errors.Is(err, sql.ErrNoRows) {
317+
if httpapi.Is404Error(err) {
318318
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
319319
Message: fmt.Sprintf("Organization does not exist with the provided id %q.", req.OrganizationID),
320320
})
@@ -938,7 +938,7 @@ func (api *API) organizationByUserAndName(rw http.ResponseWriter, r *http.Reques
938938
ctx := r.Context()
939939
organizationName := chi.URLParam(r, "organizationname")
940940
organization, err := api.Database.GetOrganizationByName(ctx, organizationName)
941-
if errors.Is(err, sql.ErrNoRows) || rbac.IsUnauthorizedError(err) {
941+
if httpapi.Is404Error(err) {
942942
httpapi.ResourceNotFound(rw)
943943
return
944944
}

0 commit comments

Comments
 (0)