Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a GraphQL endpoint #134

Merged
merged 26 commits into from
Feb 24, 2023
Merged

Add a GraphQL endpoint #134

merged 26 commits into from
Feb 24, 2023

Conversation

patch0
Copy link
Contributor

@patch0 patch0 commented Feb 17, 2023

This is the start of a new GraphQL API that can be used by the editor-ui to fetch projects, components, images. GraphQL provides a documented, explorable API that allows the client to pull just the data it requires to fulfill the user's request.

This PR implements the ability to query the whole schema (Project, Component, Image), and provides just one mutation CreateProject.

Authorization is performed in the same way as the existing REST API, i.e. using a HTTP header Authorization: to provide the Hydra (v1) token.

Example queries

Fetch all projects the user can read", showing fields useful for the "my projects" page

{
  projects(first: 2) {
    edges {
      node {
        id
        name
        identifier
        updatedAt
      }
    }
  }
}

returns something like:

{
  "data": {
    "projects": {
      "edges": [
        {
          "node": {
            "id": "Z2lkOi8vYXBwL1Byb2plY3QvMGMzYjM1ODItODhjYi00NDdmLTk1OTYtMGVhZWU3MTQ2NDkw",
            "name": "Codebreaker",
            "identifier": "codebreaker-project-starter",
            "updatedAt": "2023-02-16T20:57:59Z"
          }
        },
        {
          "node": {
            "id": "Z2lkOi8vYXBwL1Byb2plY3QvOTVlNTdmM2MtNzlhYy00NmNmLWFiNDQtNjUxMzhjYzAwNjJh",
            "name": "Rocket Launch Example",
            "identifier": "rocket-launch-example",
            "updatedAt": "2023-02-16T20:57:59Z"
          }
        }
      ]
    }
  }
}

Note the use of obfuscated IDs, which is usual for GraphQL.

Here is a query to fetch a project that I've not given the auth token for:

{
  project(identifier: "wok-boss-drift") {
    id
    name
    identifier
    updatedAt
  }
}

The HTTP response is a 200, but the project is null, and data contains an errors array.

{
  "data": {
    "project": null
  },
  "errors": [
    {
      "message": "An object of type Project was hidden due to permissions",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "project"
      ]
    }
  ]
}

If the project doesn't exist, no errors are returned, the project is simply null.

Example mutation

This is an example of a mutation. This requires the Authorization header to be correctly set.

mutation CreateProject($project: CreateProjectInput!) {
  createProject(input: $project) {
    project {
      id
      identifier
      name
      userId
    }
  }
}

Then here are the variables

{
  "project": {
    "components": [
      {
        "content": "# Hello world!",
        "default": true,
        "extension": "py",
        "name": "main"
      }
    ],
    "name": "Project created via GraphQL!",
    "projectType": "python"
  }
}

And you have to set a header (which you can pinch from an existing editor-ui session).

 {
  "Authorization": "0xdeadbeef-redacted-secret"
}

This will then return

{
  "data": {
    "createProject": {
      "project": {
        "id": "Z2lkOi8vYXBwL1Byb2plY3QvOWJhMGNlM2EtOTAyOS00NWQxLTljYzAtZTAxN2IwYzc5Y2Rm",
        "identifier": "wok-boss-drift",
        "name": "Project created via GraphQL!",
        "userId": "132c698c-9934-48e8-b8ac-b80dfddf6ae9"
      }
    }
  }
}

Tests

Tests have been added to cover the new code.

With the GraphQL queries and mutations, I've tried to split the tests at sensible boundaries. E.g. the project_query_spec tests the ProjectType and tries to draw a line between that and any sub types, e.g. the ComponentType, ImageType. I'd anticipate those being tested separately.

Similarly the projects_query_spec doesn't test the ProjectType , but tests that an array of items with the correct __typename is returned.

@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 09:04 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 09:10 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 09:14 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 09:19 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 09:34 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 16:43 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 17:18 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 17:20 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 17:22 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 17:25 Inactive
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-graphql-sp-0bly2n February 17, 2023 17:46 Inactive
@patch0 patch0 marked this pull request as ready for review February 20, 2023 09:08
app/graphql/mutations/create_project.rb Outdated Show resolved Hide resolved
app/graphql/mutations/create_project.rb Outdated Show resolved Hide resolved
app/graphql/mutations/create_project.rb Outdated Show resolved Hide resolved
app/graphql/types/component_input_type.rb Outdated Show resolved Hide resolved
app/graphql/types/image_type.rb Outdated Show resolved Hide resolved
app/graphql/types/project_input_type.rb Outdated Show resolved Hide resolved
app/graphql/types/project_type.rb Show resolved Hide resolved
app/graphql/types/project_type.rb Show resolved Hide resolved
Copy link
Contributor

@loiswells97 loiswells97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! 🚢

@patch0 patch0 merged commit f9e9ae5 into main Feb 24, 2023
@patch0 patch0 deleted the graphql-spike branch February 24, 2023 11:38
patch0 added a commit that referenced this pull request Mar 2, 2023
# What's changed

* Rewrite `oauth_user` helper into `identifiable` concern to use the
Hydra Admin API library introduced in #134
* Changed the super class of the GraphQL controller to match the other
API calls.
* Upped the number of memoized helpers allowed by rubocop... 😅 

# Points for consideration

* When testing, the auth token has to be given in the headers, so I've
added that in everywhere.
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.

4 participants