Repository: apigee/registry (go)

Issue:
Existence check for parent resource is missing while listing artifcts.
I was able to list artifacts for an `ApiDeployment` and `ApiSpec` that doesn't exist.

```
curl http://x.x.x.x/v1/projects/krpate-test/locations/global/apis/test/deployments
{
 "apiDeployments": [
  {
   "name": "projects/krpate-test/locations/global/apis/test/deployments/prod",
   "displayName": "",
   "description": "",
   "revisionId": "66f817f8",
   "apiSpecRevision": "",
   "endpointUri": "bleh.com",
   "externalChannelUri": "",
   "intendedAudience": "",
   "accessGuidance": "",
   "labels": {},
   "annotations": {},
   "createTime": "2023-01-19T22:15:05.690925Z",
   "revisionCreateTime": "2023-01-19T22:15:47.585520Z",
   "revisionUpdateTime": "2023-01-19T22:15:47.585520Z"
  }
 ],
 "nextPageToken": ""
}

curl http://x.x.x.x/v1/projects/krpate-test/locations/global/apis/test/deployments/invalid/artifacts
{
 "artifacts": [],
 "nextPageToken": ""
}
```

We used to have an existence check for the parent resource, but it looks like it was removed in https://github.com/apigee/registry/pull/818.

Pull request description:
return missing when list artifacts missing parent
Closes #959

Patch:
diff --git a/server/registry/internal/storage/list.go b/server/registry/internal/storage/list.go
index b525c5e..e82a5ae 100644
--- a/server/registry/internal/storage/list.go
+++ b/server/registry/internal/storage/list.go
@@ -1074,6 +1074,33 @@ func (c *Client) ListSpecRevisionArtifacts(ctx context.Context, parent names.Spe
 		token.Order = opts.Order
 	}
 
+	// if any explicit parent specified, ensure it exists
+	if parent.ProjectID != "-" && parent.ApiID != "-" && parent.VersionID != "-" && parent.SpecID != "-" {
+		specAndRev := strings.Split(parent.SpecID, "@")
+		if specAndRev[0] != "-" {
+			if _, err := c.GetSpec(ctx, parent.Spec()); err != nil {
+				return ArtifactList{}, err
+			}
+		}
+		if len(specAndRev) > 1 && specAndRev[1] != "-" {
+			if _, err := c.GetSpecRevision(ctx, parent); err != nil {
+				return ArtifactList{}, err
+			}
+		}
+	} else if parent.ProjectID != "-" && parent.ApiID != "-" && parent.VersionID != "-" && parent.SpecID == "-" {
+		if _, err := c.GetVersion(ctx, parent.Version()); err != nil {
+			return ArtifactList{}, err
+		}
+	} else if parent.ProjectID != "-" && parent.ApiID != "-" && parent.VersionID == "-" && parent.SpecID == "-" {
+		if _, err := c.GetApi(ctx, parent.Api()); err != nil {
+			return ArtifactList{}, err
+		}
+	} else if parent.ProjectID != "-" && parent.ApiID == "-" && parent.VersionID == "-" && parent.SpecID == "-" {
+		if _, err := c.GetProject(ctx, parent.Project()); err != nil {
+			return ArtifactList{}, err
+		}
+	}
+
 	op := c.db.WithContext(ctx)
 	if id := parent.ProjectID; id != "-" {
 		op = op.Where("artifacts.project_id = ?", id)
@@ -1209,6 +1236,29 @@ func (c *Client) ListDeploymentRevisionArtifacts(ctx context.Context, parent nam
 		token.Order = opts.Order
 	}
 
+	// if any explicit parent specified, ensure it exists
+	if parent.ProjectID != "-" && parent.ApiID != "-" && parent.DeploymentID != "-" {
+		deploymentAndRev := strings.Split(parent.DeploymentID, "@")
+		if deploymentAndRev[0] != "-" {
+			if _, err := c.GetDeployment(ctx, parent.Deployment()); err != nil {
+				return ArtifactList{}, err
+			}
+		}
+		if len(deploymentAndRev) > 1 && deploymentAndRev[1] != "-" {
+			if _, err := c.GetDeploymentRevision(ctx, parent); err != nil {
+				return ArtifactList{}, err
+			}
+		}
+	} else if parent.ProjectID != "-" && parent.ApiID != "-" && parent.DeploymentID == "-" {
+		if _, err := c.GetApi(ctx, parent.Api()); err != nil {
+			return ArtifactList{}, err
+		}
+	} else if parent.ProjectID != "-" && parent.ApiID == "-" && parent.DeploymentID == "-" {
+		if _, err := c.GetProject(ctx, parent.Project()); err != nil {
+			return ArtifactList{}, err
+		}
+	}
+
 	op := c.db.WithContext(ctx)
 	if id := parent.ProjectID; id != "-" {
 		op = op.Where("artifacts.project_id = ?", id)


Test patch:
diff --git a/server/registry/actions_artifacts_test.go b/server/registry/actions_artifacts_test.go
index 807d2b2..40ff569 100644
--- a/server/registry/actions_artifacts_test.go
+++ b/server/registry/actions_artifacts_test.go
@@ -949,7 +949,35 @@ func TestListArtifactsResponseCodes(t *testing.T) {
 		want  codes.Code
 	}{
 		{
-			desc: "parent parent not found",
+			desc: "parent spec not found",
+			req: &rpc.ListArtifactsRequest{
+				Parent: "projects/my-project/locations/global/apis/my-api/versions/v1/specs/s",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "parent spec rev not found",
+			req: &rpc.ListArtifactsRequest{
+				Parent: "projects/my-project/locations/global/apis/my-api/versions/v1/specs/s@123",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "parent deployment not found",
+			req: &rpc.ListArtifactsRequest{
+				Parent: "projects/my-project/locations/global/apis/my-api/deployments/d",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "parent deployment rev not found",
+			req: &rpc.ListArtifactsRequest{
+				Parent: "projects/my-project/locations/global/apis/my-api/deployments/d@123",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "parent version not found",
 			req: &rpc.ListArtifactsRequest{
 				Parent: "projects/my-project/locations/global/apis/my-api/versions/v1",
 			},