code4me / 4me-sdk-graphql-dotnet

.NET SDK for 4me GraphQL, see https://developer.4me.com/graphql/
MIT License
3 stars 1 forks source link

More permissions needed when I query a time entry then actually needed #12

Closed HeinPauwelyn closed 1 week ago

HeinPauwelyn commented 2 weeks ago

I want to get time entries including the note and the person who spent it. For this I'm creating next query:

TimeEntryQuery _timeEntryQuery = Query.TimeEntry
    .SelectNote(new NoteQuery().Select(NoteField.Text, NoteField.Internal))
    .SelectPerson(new PersonQuery().Select(PersonField.PrimaryEmail))
    .Filter(TimeEntryField.ID, FilterOperator.Equals, "MyTimeEntryId");

When I'm trying to get the data I've got this exception:

Sdk4me.GraphQL.Sdk4meException: Missing required scope(s): account:Read, organization:Read, service:Read, team:Read

However using Postman and query below I don't have any issues.

{
    timeEntries(
        first: 1
        filter: { id: { values: ["MyTimeEntryId"] } }
    ) {
        nodes {
            note {
                internal
                text
            }
            person {
                primaryEmail
            }
        }
    }
}

Why are there more permissions needed when I do the same query using Sdk4me.GraphQL then when I'm do it inside Postman?

klaasvandeweerdt commented 2 weeks ago

@HeinPauwelyn, I will try to reproduce this. My first thought is default value selection. You should be able to see the GraphQL query in the debug window or capture it via a trace listener.

klaasvandeweerdt commented 2 weeks ago

@HeinPauwelyn, you did not specify any fields for the time entry object. In that case it uses a set of default defined values which includes: Account, Customer, Date, Deleted, Organization, Person, Service, TimeSpent, Deleted, Source, SourceID, CreatedAt, UpdatedAt. If any of those field is an object it also default select some fields.

The first line specified the fields, if no Select is used if defaults.

TimeEntryQuery _timeEntryQuery = Query.TimeEntry
    .Select(TimeEntryField.ID)
    .SelectNote(new NoteQuery().Select(NoteField.Text, NoteField.Internal))
    .SelectPerson(new PersonQuery().Select(PersonField.PrimaryEmail))
    .Filter(TimeEntryFilter.ID, FilterOperator.Equals, "MyTimeEntryId");

For GraphQL the ID is not required, for the SDK it is used to handle pagination.

Also keep in mind that using the TimeEntryField.ID enum in .Filter(TimeEntryField.ID, FilterOperator.Equals, "MyTimeEntryId") is obsolete, use TimeEntryFilter.ID instead. Filters have there own field enumerators, as not all fields can be used for filtering, and some fields were missing as they only exist in filters.

klaasvandeweerdt commented 1 week ago

@HeinPauwelyn, I'm adding client property to define the default behavior. Something like client.DefaultSelection = false;, when false true it will use the default coded fields, when false it will only select ID or all fields for entities without ID.

klaasvandeweerdt commented 1 week ago

@HeinPauwelyn, in the latest version (1.4.2) you can use Sdk4meClient.DefaultFieldSelection to overwrite the default behavior of the default field selection.