graphql-platform icon indicating copy to clipboard operation
graphql-platform copied to clipboard

It's not possible to project an ignored property

Open eliottrobson opened this issue 3 years ago • 16 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

When using resolvers / extensions it is not possible to hide a field from the schema via .Ignore() and also simultaneously .Project() that field for use in an extension.

Steps to reproduce

Assume a model where we have a book type, this contains a "GoodreadsId" field that links to an ID on the good reads service and a resolver which uses their API to return extra data. Exposing this ID to the user isn't useful, but we need it to query the remote service.

Using .IsProjected() always adds to the query as expected. Using .Ignore() hides the field from the schema as expected. Using .Ignore() and .IsProjected() hides the field from the schema but does not add to the query.

public class BookType : ObjectType<Book>
{
    protected override void Configure(IObjectTypeDescriptor<Book> descriptor)
    {
        descriptor.Field(f => f.GoodreadsId)
            .Ignore()
            .IsProjected();
    } 
}

[ExtendObjectType(typeof(Book))]
public class BookExtensionsType
{
    public async Task<GoodreadsData> GetGoodreadsData([Parent] Book book)
    {
        // book.GoodreadsId is always null
    }
}

Relevant log output

No response

Additional Context?

No response

Product

Hot Chocolate

Version

11.3.7

eliottrobson avatar Sep 06 '21 15:09 eliottrobson

@michaelstaib i think it would make sense to way with this one until we have internal fields. Everything else would be a hack

PascalSenn avatar Sep 07 '21 13:09 PascalSenn

Shall we put that on the new projection engine stack.

michaelstaib avatar Sep 07 '21 22:09 michaelstaib

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar May 04 '22 13:05 stale[bot]

Hi, is there any news to this? In my current project I need this kind of "internal" field functionality too. Is there a good workaround for this issue?

kpko avatar May 06 '22 17:05 kpko

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Sep 03 '22 20:09 stale[bot]

@michaelstaib i guess for this @internal fields would be nice

PascalSenn avatar Sep 03 '22 21:09 PascalSenn

Is there any ongoing work on this? Another example is when you want to expose a field that depends on the ignored field that field won't be able to fetch. For example: Entity class

class ItemData
{
  public string StartTime { get; set; }
  public string EndTime { get; set; }
  // other fields here
}

Expected result

{
  "duration": {
    "start": "12:34",
    "end": "23:45"
  },
  // other fields here
}

anuith avatar Sep 30 '22 10:09 anuith

I would love some guidance on this as well @anuith In my case i am trying to hash Id's so a user can't index my database.

The best working solution i've come up with is this:

public class SecurityIndexExt {
        [IgnoreDataMember]
        [GraphQLIgnore]
        private int realId;

        [Key]
        [IgnoreDataMember]
        //[GraphQLIgnore]
        [IsProjected(true)]
        public int Id {
            get {
                return 0;
            }
            set {
                this.realId = value;
            }
        }

        public Guid Guid {
            get {
                string salt = "Z1@#!Q";
                using(MD5 md5 = MD5.Create()) {
                    byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(salt + this.realId.ToString()));
                    return new Guid(hash);
                }
            }
        }
    }

This makes it so Id is reported back as 0 in GraphQL but the value is still preserved. I haven't fully tested this with mutations yet but ill update my post if i find any issues.

RichardGrant-93 avatar Jan 16 '23 22:01 RichardGrant-93

So we just picked this up again and decided to move it to a later release as we are just closing v13 now.

The issue with this that as soon as you ignore the field, the field is gone and we cannot pick it up with any TypeInterceptor. We could change how [Ignore] is implemented, but this would need changes in a lot of different places.

We are working on some changes that might help fixing this issue aswell

PascalSenn avatar Feb 03 '23 16:02 PascalSenn

@PascalSenn

This could probably be solved by #2575.

public class BookType : ObjectType<Book>
{
    protected override void Configure(IObjectTypeDescriptor<Book> descriptor)
    {
        descriptor
            .Field("GoodreadsData")
            .Projects(f => f.GoodreadsId)
            .Resolve(/* ... */);
    } 
}

glen-84 avatar Mar 07 '23 15:03 glen-84

I just ran into this as well

onionhammer avatar Mar 21 '23 22:03 onionhammer

We just ran into this. Another upvote here.

dt200r avatar Mar 30 '23 22:03 dt200r

Same issue here, I have a hierarchyid property that I'd like to .ToString() before returning. In this case I have to hide the hierarchyid property because Hot Chocolate can't instantiate it since the type has no empty default constructor.

andagr avatar Sep 06 '23 12:09 andagr

Any news? Also running into it

phebing avatar Feb 28 '24 16:02 phebing

I just ran into this as well

tkideneB avatar Mar 03 '24 01:03 tkideneB