Learn everything about our new Bitergia Research branch!

Hands-On Identity Management: GraphQL + Python for GrimoireLab

Share this Post

Table of Contents

Have you ever struggled when managing contributor identities within software projects? GrimoireLab is developing a new SortingHat version, the tool used for identity management, to turn it into a GraphQL service! This article summarizes how we used Graphene, a library for building GraphQL APIs in Python, for boosting SortingHat’s integration with other apps.

People contributing to software projects interact with the them through many different channels,  such as ticket/issues systems, Q&A forums, chats, mailing lists, code review, social media or meetings and events

From a project management perspective, a person needs to know their community. In order  to get valuable insights, that person may end up asking two main questions:

  • How many contributors does the project has?
  • How many organizations are contributing to the project?

To answer these questions, we need to manage contributor identities within the project. Let’s clarify this scenario using two contributors:

This slideshow requires JavaScript.

But wait… it turns out they are the same person! For those people knowing this contributor in person, this may not be a surprise, but a project manager may not have this information all the time. If this happens, this person would have been identified as different contributors and the metrics analyzed for the project would be incorrect.

In real life, this can be “a little bit” more complex:

sortinghat-multiple-identities-exaple

At this point, some people may get crazy wondering who is who in the project. This is the reason why SortingHat is for, the GrimoireLab tool for managing contributor identities.

SortingHat allows to perform base operations for managing many entities related with identities management (identities, organizations, enrollments, profiles, etc.). For instance, going back to the example we set above, we could ask SortingHat to merge those identities, add a new affiliation and complete that person’s profile with some basic information.

sortinghat-example

Boosting SortingHat integration

Now that we have dived into SortingHat some of its capabilities, it is time to talk about integration. Until now, SortingHat could be accessed via command line, imported as a Python module and also via Hatstall, a web-UI.

How can we boost integration? We started with the main idea of building a robust API. This API would have to be flexible and easy to adapt and ensure consistency as we expect it to be heavily used (i.e., many users and applications at the same time). That’s when GraphQL comes into play!

Why following this approach to build the API?

Let’s imagine we want to get a view for our application showing the information for a given unique identity. We may want to show its individual identities, its profile, its enrollments and the main email domains for each organization where it is enrolled.

If we followed a traditional REST approach, we would need to access to different endpoints to get the information we need for this view:

/unique_identities/<uuid>/identities

/unique_identities/<uuid>/profile

/unique_identities/<uuid>/enrollments

/organizations/<org_name>/domains

However, REST approach have some pitfalls to highlight:

  • It needs multiple requests per view (see example above).
  • The structure is just a convention between the server and the client.
  • It is common to ask for more information than is needed (overfetching) and also the opposite (underfetching).
  • The API documentation is not tied to the development.

Let’s see how a GraphQL query would look like for getting the information for the same view:

query {
    unique_identities(uuid:“<uuid>”) {
        identities {
            uid
        }
        profile {
            email
            gender
        }
        enrollments {
            organization
            end_date
        }
        domains {
            domain_name
        }
    }
}

Pointing out some of the strongest pros of using a GraphQL approach for building the API:

  • It needs one single request per view.
  • The client defines what it receives and the server only sends what is needed.
  • It is a strongly-typed language, which enforces field validation.

Turning SortingHat into a GraphQL service

At Bitergia, main maintainers from GrimoireLab tool, we are working to turning SortingHat into a service (currently under development). It is based on Graphene, a Python module that provides tools to implement a GraphQL API in Python. We are also working with Graphene-Django, another Python module built on top of Graphene which provides additional abstractions from Django framework.

The first step to take when designing a GraphQL service is to define its schema, which describes what data can be queried. We need to define three basic parts:

  • Types: Which are the data types we are using in the service.
  • Queries: What data we can ask for and how it is returned.
  • Mutations: Operations modifying the data.

In Graphene-Django, these parts are correspondingly defined using Django abstractions:

  • The types are defined by models.
  • For the queries, we need to implement resolvers.
  • The mutations can be translated as CRUD operations.

About the data types, we need to define our data model. If we have a look at the example we saw before, its structure is already very similar to a graph. We have defined types for all the basic entities we have in SortingHat (unique identities, single identities, organizations, domains, enrollments, profiles, and more).

Screenshot from 2020-02-19 11-07-30

Next, is to define some queries. Let’s see a recipe for building a basic query asking for the existing organizations.

Step 1

Define a new model object, in this case for Organizations. Then, we define a new type in schema.py script and define a basic resolver for the new query which returns all the Organization objects.

graphql-sortinghat

Once the query is defined, we will see that the API documentation has been automatically updated!

Screenshot from 2020-02-17 20-48-51

Step 2

Now that we have defined a basic type, we can define a new mutation and the fields we are going to accept as input. In this example, we are creating a mutation for adding a new organization. This means we need one field, in this case is the name of the organization to be added. Then, in the mutation class we specify which internal method is performing this change into the database.

Screenshot from 2020-02-17 20-53-44

This mutation is calling an internal method called add_organization, which is inside the api.py module. This module controls basic exceptions and calls to the corresponding method modifying the database directly, named db.py.

Screenshot from 2020-02-17 20-56-23

And, once again, we can see the API documentation has been automatically updated.

Screenshot from 2020-02-17 20-57-39

Closing remarks and future work

We have covered the main requirements to implement GraphQL in SortingHat. We also worked on extra features, such as pagination or authentication, that we will explain as a second part of this module. Meanwhile, you can find more detailed information at my talk in FOSDEM 2020.

 

Among the several features we are adding to this new version of SortingHat, one of the most important thing is implementing a command line and web client for this new service, plus checking what happens with nested queries and how to set a limit.

I am a Software Engineer working at Bitergia, a software development analytics firm composed by the main maintainers of GrimoireLab software which is also part of CHAOSS, one of the projects hosted at The Linux Foundation.

If you would like to contribute to this Open Source project, feel free to join GrimoireLab community. Of course, feedback is more than welcome!

 

mafesan

mafesan

Data analyst and Consultant at Bitergia.

More To Explore

Do You Want To Start
Your Metrics Journey?

drop us a line and Start with a Free Demo!