Skip to content

Conversation

@swalkerhppr
Copy link

entoas

Issue

Generated openapi.json generates properties and operations for skipped edges:

$ grep -i "password\|secret" ent/openapi.json
                  "secret_parent": {
                  "secret_children": {
                  "secret_parent": {
                  "secret_children": {
    "/users/{id}/secret-children": {
        "summary": "List attached SecretChildrens",
        "description": "List attached SecretChildrens.",
        "operationId": "listUserSecretChildren",
                    "$ref": "#/components/schemas/User_SecretChildrenList"
    "/users/{id}/secret-parent": {
        "operationId": "readUserSecretParent",
                  "$ref": "#/components/schemas/User_SecretParentRead"
          "secret_parent": {
          "secret_children": {
      "User_SecretChildrenList": {
      "User_SecretParentRead": {

Code that causes the issue

// ent/schema/user.go
package schema

import (
  "entgo.io/contrib/entoas"
  "entgo.io/ent"
  "entgo.io/ent/schema/edge"
  "entgo.io/ent/schema/field"
)

// User holds the schema definition for the User entity.
type User struct {
  ent.Schema
}

// Fields of the User.
func (User) Fields() []ent.Field {
  return []ent.Field{
    field.String("username"),
    field.String("password").
      Annotations(
        entoas.Skip(true), // Skip the "password" field (this works)
      ),
    }
}

// Edges of the User.
func (User) Edges() []ent.Edge {
  return []ent.Edge{
    edge.To("secret_children", User.Type).
      Annotations(
        entoas.Skip(true), // Skip the "secret_children" edge
      ).
      From("secret_parent").
      Unique().
      Annotations(
        entoas.Skip(true), // Skip the "secret_parent" edge
      ),
    edge.To("children", User.Type).
      From("parent").
      Unique(),
  }
}

Expected behavior

  1. go generate ./...
  2. grep -i "password\|secret" ent/openapi.json should show no references to secret_children nor secret_parent

… not generate operations for skipped edges with annotations.
@lrstanley
Copy link

I was going to submit a similar PR yesterday (make skip supports fields, edges, and entire schemas), but noticed this is actually already supported, just not through the Skip annotation. You can use the following annotations on edges to remove them from the schema, depending on specifically what you want to skip:

		entoas.CreateOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
		entoas.ReadOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
		entoas.ListOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
		entoas.UpdateOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
		entoas.DeleteOperation(entoas.OperationPolicy(entoas.PolicyExclude)),

I do still think the documentation is lacking, and the choice of using PolicyExclude, compared to other extensions, a bit misleading/confusing.

@swalkerhppr
Copy link
Author

Tried again using the operation policy exclude annotations and it seems that there are still references to the "skipped" edges:

$ go get -u entgo.io/contrib/entoas@master
$ go generate ./...
$ grep -i "password\|secret" ent/openapi.json
                  "secret_parent": {
                  "secret_children": {
                  "secret_parent": {
                  "secret_children": {
          "secret_parent": {
          "secret_children": {

The updated code from above

// ent/schema/user.go
package schema

import (
  "entgo.io/contrib/entoas"
  "entgo.io/ent"
  "entgo.io/ent/schema/edge"
  "entgo.io/ent/schema/field"
)

// User holds the schema definition for the User entity.
type User struct {
  ent.Schema
}

// Fields of the User.
func (User) Fields() []ent.Field {
  return []ent.Field{
    field.String("username"),
    field.String("password").
      Annotations(
        entoas.Skip(true), // Skip the "password" field (this works)
      ),
    }
}

// Edges of the User.
func (User) Edges() []ent.Edge {
  return []ent.Edge{
    edge.To("secret_children", User.Type).
      Annotations(
        //entoas.Skip(true), // Skip the "secret_parent" edge
                entoas.CreateOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.ReadOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.ListOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.UpdateOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.DeleteOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
      ).
      From("secret_parent").
      Unique().
      Annotations(
        //entoas.Skip(true), // Skip the "secret_parent" edge
                entoas.CreateOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.ReadOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.ListOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.UpdateOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
                entoas.DeleteOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
      ),
    edge.To("children", User.Type).
      From("parent").
      Unique(),
  }
}

Here is the full generated openapi.json

I'm not sure if this is intended, but from my perspective a "Skip"ped field or edge should not show up in the spec at all, and with the current version it doesn't seem to be possible.

I think it would make sense to allow both where:

  • Skipped edges/fields - do not appear in the specification at all
  • Excluded edge/field operations - are not included as operations (i.e. objects with edges as properties will still be included)

I definitely agree that there could be more documentation on using annotations. It may be more clear to be able to use the same annotations on fields and edges and have them behave in the same way. Skip only works with fields right now.

@giautm giautm requested a review from masseelch April 29, 2024 09:22
@swalkerhppr
Copy link
Author

It has been a while without any feedback/changes.
Are there any suggested improvements to get this through or should I just close it without merging?
I understand you all are busy. Just want to know where we stand on this.
I am using it in my fork, so I'm not blocked.

Thanks!

@dnjaramba
Copy link

dnjaramba commented Jul 30, 2025

@masseelch @a8m any thoughts on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants