



  

Meerkat Core documentation

 [Meerkat Core](index.html#document-index) 

 latest

 

Contents:

* [Meerkat Core Application Design](index.html#document-design)

	+ [Underlying technology](index.html#underlying-technology)

	+ [Solution Architecture](index.html#solution-architecture)

	+ [System Design](index.html#system-design)

* [Profile as a Service](index.html#document-profile)

	+ [Application / Service Architecture](index.html#application-service-architecture)

	+ [Object Data Models](index.html#object-data-models)

	+ [Core Endpoints](index.html#core-endpoints)

	+ [Image Resource Server API](index.html#image-resource-server-api)

[Meerkat Core](index.html#document-index)

* [Docs](index.html#document-index) »

* Meerkat Core documentation

* [Edit on GitHub](https://github.com/gctools-outilsgc/graphQL-core/blob/master/docs/index.rst)

---

Welcome to Meerkat Core’s Docs[¶](#welcome-to-meerkat-core-s-docs "Permalink to this headline")

===============================================================================================

Meerkat Core Application Design[¶](#meerkat-core-application-design "Permalink to this headline")

-------------------------------------------------------------------------------------------------

### Underlying technology[¶](#underlying-technology "Permalink to this headline")

#### Why Django?[¶](#why-django "Permalink to this headline")

The django application framework was used given it’s robust web service development capabilities, ease of language comprehension, and ability to quickly prototype ideas into web apps/services.

* Develop Fast: It has been designed in a way to help the developers make an application as fast as possible. From idea, production to release, Django helps in making it both cost effective and efficient.

* Fully Loaded: It works in a way that includes dozens of extras to help with user authentication, site maps, content administration, RSS feeds and much more. These aspects help in carrying out the web development process completely.

* Scalable: To meet the heaviest traffic demand, the benefits of Django framework can be seen. Large organizations leveraging Django include Pinterest, Instagram, BitBucket, etc.

#### Why GraphQL?[¶](#why-graphql "Permalink to this headline")

GraphQL is an application layer query language. What this means is that GraphQL is designed to interpret a string from a server or client and return data in an understandable, stable, and predictable format. As the [official website for GraphQL puts it](https://graphql.org/), “Describe your data, ask for what you want, get predictable results.”

**Benefits of GraphQL:**

* More Elegant Data Retrieval

* More Backend Stability

* Better Query Efficiency

* GraphQL Is a Specification

**Who Uses It:**

* Facebook

* GitHub

* Twitter

* Yelp

* wayfair

* neo4j

* GRAPHCOOL

### Solution Architecture[¶](#solution-architecture "Permalink to this headline")

![_images/Solution-architecture.png](_images/Solution-architecture.png)

### System Design[¶](#system-design "Permalink to this headline")

![_images/System-design.png](_images/System-design.png)

Profile as a Service[¶](#profile-as-a-service "Permalink to this headline")

---------------------------------------------------------------------------

### Application / Service Architecture[¶](#application-service-architecture "Permalink to this headline")

![_images/PaS-architecture.png](_images/PaS-architecture.png)

### Object Data Models[¶](#object-data-models "Permalink to this headline")

#### User[¶](#user "Permalink to this headline")

* `gcId` *a unique user identifier* (string)

* `name` *user’s name* (string)

* `email` *user’s email* (string)

* `avatar` *url to user’s profile avatar* (url)

* `titleEn` *user’s english position title* (string)

* `titleFr` *user’s french position title* (string)

* `mobilePhone` *mobile phone number* (string)

* `officePhone` *office phone number* (string)

* `address` *user’s work address* (address object)

* `supervisor` *user object of identified supervisor* (user object)

* `org` *organizational tier group object* (org tier object)

* `Employees` *array of user objects that have this user as their supervisor* (user object array)

* `OwnerOfOrgTier` *array of organizational tier objects that have this user as their owner* (organizational tier array)

#### Address[¶](#address "Permalink to this headline")

* `id` *unique address object identifier* (int)

* `streetAddress` (string)

* `city` (string)

* `province` (string)

* `postalCode` (string)

* `country` (string)

#### Organization Tier[¶](#organization-tier "Permalink to this headline")

* `id` *unique organizaitonal tier object identifier* (int)

* `nameEn` *english name of organizational tier* (string)

* `nameFr` *french name of organizational tier* (string)

* `organization` *top level organization object* (organization object)

* `ownerID` *user object of the user who is listed as the owner of this org tier* (user object)

* `OrgMembers` *array of user objects who are associated with this org tier* (user object array)

#### Organization[¶](#organization "Permalink to this headline")

* `id` *unique organization object identifier* (int)

* `nameEn` *english name of organization* (string)

* `nameFr` *french name of organization* (string)

* `acronymEn` *english acronym of the organization* (string)

* `acronymFr` *french acronym of the organization* (string)

* `OrgTiers` *array of organizational tiers that are associated with this organization* (organizational tier array)

### Core Endpoints[¶](#core-endpoints "Permalink to this headline")

All available endpoints use GraphQL query language.

#### /graphiql[¶](#graphiql "Permalink to this headline")

This endpoint is used to access the graphiql interface which permits querying into the graphQL core through an easy to understand user interface. See [/graphqlcore](#graphiql-reference-label) for available queries and mutations.

#### /graphqlcore[¶](#graphqlcore "Permalink to this headline")

This endpoint is used by client applications that do not require a graphical interface. This endpoint is a pure API.

##### Queries[¶](#queries "Permalink to this headline")

Queries do not require authentication of the client through the means of an access token.

###### Base query for all available information of a user without search criteria[¶](#base-query-for-all-available-information-of-a-user-without-search-criteria "Permalink to this headline")

```

profiles{

    gcID,

    name,

    email,

    avatar,

    mobilePhone,

    officePhone,

    titleEn,

    titleFr,

    address{

        id,

        streetAddress,

        city,

        province,

        postalCode,

        country

    }

    supervisor{

        gcID,

        name,

        email,

        avatar,

        mobilePhone,

        officePhone,

        titleEn,

        titleFr,

        address{

            id,

            streetAddress,

            city,

            province,

            postalCode,

            country

        }

    }

    org{

        id,

        nameEn,

        nameFr,

        organization{

            id,

            nameEn,

            nameFr,

            acronymEn,

            acronymFr,

        },

        ownerID{

            gcID,

            name,

            email,

            avatar,

            mobilePhone,

            officePhone,

            titleEn,

            titleFr,

            address{

                id,

                streetAddress,

                city,

                province,

                postalCode,

                country

            }

        }

    }

    OwnerOfOrgTier{

        nameEn,

        nameFr,

        organization{

            id,

            nameEn,

            nameFr,

            acronymEn,

            acronymFr,

        },

        OrgMembers{

            gcID,

            name,

            email,

            avatar,

            mobilePhone,

            officePhone,

            titleEn,

            titleFr,

            address{

                id,

                streetAddress,

                city,

                province,

                postalCode,

                country

            }

        }

    }

}

```

###### Query search criteria[¶](#query-search-criteria "Permalink to this headline")

Search criteria fields can be used separately or chained together to easily filter through data.

**Profile**

Available Arguments:

* `gcId` *exact match* (string)

* `name` *name contains* (string)

* `email` *exact match* (string)

* `mobilePhone` *mobile number contains* (string)

* `officePhone` *office number contains* (string)

* `titleEn` *title contains* (string)

* `titleFr` *title contains* (string)

Example with all available arguments:

```

query{

    profiles(

        gcID:"string",

        name:"string",

        email:"string",

        mobilePhone:"string",

        officePhone:"string",

        titleEn:"string",

        titleFr:"string"

    )

}

```

**Addresses**

Available arguments:

* `id` *exact match* (int)

* `streetAddress` *street address contains* (string)

* `city` *city contains* (string)

* `province` *exact match* (string)

* `postalCode` *exact match* (string)

* `country` *exact match* (string)

Example with all available arguments

```

query{

    addresses(

        id:2,

        streetAddress:"string",

        city:"string",

        province:"string",

        postalCode:"string",

        country:"string"

    )

}

```

**Organizational Tiers**

Available arguments:

* `id` *exact match* (int)

* `nameEn` *english name contains* (string)

* `nameFr` *french name contains* (string)

Example with all available arguments:

```

query{

    orgtiers(

        id:2,

        nameEn:"string",

        nameFr:"string",

    )

}

```

**Organizations**

Available arguments:

* `id` *exact match* (int)

* `nameEn` *name of organization contains* (string)

* `nameFr` *name of organization contains* (string)

* `acronymEn` *exact match* (string)

* `acronymFr` *exact match* (string)

```

query{

    organizations(

        id:1,

        nameEn:"string",

        nameFr:"string",

        acronymEn:"string",

        acronymFr:"string"

    )

}

```

###### Paginiation[¶](#paginiation "Permalink to this headline")

Retrieving too much data on a single request is unpractical and may even break your app. Pagination exists to solve this problem, allowing the client to specify how many items it wants.

The simple way defined in the GraphQL pagination documentation is to slice the results using two parameters: `first`, which returns the first n items and `skip`, which skips the first n items.

These two pagination parameters have been implemented on all of the search query functions.

The example query below will search for all profiles that contain the name “Bryan” but instead of returning the complete array the query b

elow is requesting items 2 and 3 in the array. Skip the first item in the array and send the next 2 in the array.

```

query{

    profiles(name:"Bryan", first:2, skip:1){

        name,

        avatar,

        email

    }

}

```

##### Mutations[¶](#mutations "Permalink to this headline")

Mutations do require authentication in the form of the users valid OpenID Connect access token. The access token must be passed in the request header in the form `Authorization: Bearer {access token}`.

###### Profile Mutations[¶](#profile-mutations "Permalink to this headline")

Available arguments to send in a mutation:

* `gcId` *a users identifier* (string)

* `profileInfo` *an array object with values to modify* (dict)

> 

> 

> 	+ `name` *user’s name* (string)

> 	+ `email` *user’s email* (string)

> 	+ `titleEn` *user’s english position title* (string)

> 	+ `titleFr` *user’s french position title* (string)

> 	+ `mobilePhone` *mobile phone number* (string)

> 	+ `officePhone` *office phone number* (string)

> 	+ `address` *user’s work address* (address object)

> 	

> 	

> 	

> 	> 

> 	> 

> 	> 	- `streetAddress` (string)

> 	> 	- `city` (string)

> 	> 	- `province` (string)

> 	> 	- `postalCode` (string)

> 	> 	- `country` (string)

> 	>

> 	+ `supervisor` *user object of identified supervisor* (user object)

> 	

> 	

> 	

> 	> 

> 	> 

> 	> 	- `gcID` *a users identifier* (string)

> 	>

> 	+ `org` *organizational tier group object*

> 	

> 	

> 	

> 	> 

> 	> 

> 	> 	- `orgID` *an organizatinal tier’s unique id* (int)

> 	>

>

Example mutation using all available arguments:

```

mutation{

    modifyProfile(

        gcId:2,

        profileInfo:{

        name:"string",

        email:"string",

        titleEn:"string",

        titleFr:"string",

        mobilePhone:"string",

        officePhone:"string",

        address:{

            streetAddress:"string",

            city:"string",

            province:"string",

            postalCode:"string",

            country:"string",

        }

        supervisor:{

            gcId:3

        }

        org:{

            orgId:1

        }

    }

    )

}

```

###### Organization Tier Mutations[¶](#organization-tier-mutations "Permalink to this headline")

**Create an OrgTier**

Available arguments to send in a mutation:

* `nameEn` *english name of org tier* (string)

* `nameFr` *french name of org tier* (string)

* `organizationId` *organization unique id* (int)

* `ownerGcId` *unique user who owns the organization* (int)

Example mutation to create an OrgTier:

```

mutation{

    createOrgTier(

        nameEn:"string",

        nameFr:"string",

        organizationId:3

        ownerGcId:2

     )

}

```

**Modify an OrgTier**

Available arguments to send in a mutation:

* `orgId` *unique identifier of the org tier to modify* (int)

* `dataToModify` *array of information to modify* (dict)

> 

> 

> 	+ `nameEn` *english name of org tier* (string)

> 	+ `nameFr` *french name of org tier* (string)

> 	+ `organizationId` *organization unique id* (int)

> 	+ `ownerGcId` *unique user who owns the organization* (int)

>

Example mutation to modify an OrgTier:

```

mutation{

    modifyOrgTier(

        orgId:2,

        dataToModify:{

        nameEn:"string",

        nameFr:"string",

        organizationId:4,

        ownerGcId:23

        }

    )

}

```

**Delete an OrgTier**

Available arguments to send in a mutation:

* `orgTierId` *unique identifier of the org tier* (int)

Example mutation to delete an OrgTier:

```

mutation{

    deleteOrgTier(

        orgTierId:6

        )

}

```

#### /protected[¶](#protected "Permalink to this headline")

This endpoint is similar to the `graphqlcore` endpoint however is used for data management applications that have access to additional graphQL mutations. This endpoint is protected by token authentication and requires an account and active token on the graphql-core.

### Image Resource Server API[¶](#image-resource-server-api "Permalink to this headline")

The Profile as a Service leverages [PictShare](https://github.com/chrisiaut/pictshare) which is a multi lingual, open source image hosting application with a simple resizing and upload API for the hosting of profile avatar images. PictShare is licensed under the [Apache-2.0 License](https://img.shields.io/badge/license-Apache-blue.svg?style=flat)](https://github.com/chrisiaut/pictshare/blob/master/LICENSE)

#### Features[¶](#features "Permalink to this headline")

* Simple API to upload any image from remote servers to your instance [via URL](#upload-from-url) and [via Base64](#upload-from-base64-string)

* 100% file based - no database needed

* Simple album functions with embedding support

* Converts gif to (much smaller) MP4

* MP4 resizing

* PictShare removes all exif data so you can upload photos from your phone and all GPS tags and camera model info get wiped

* Smart [resize, filter and rotation](#smart-query-system) features

* Duplicates don’t take up space. If the exact same images is uploaded twice, the second upload will link to the first

* Detailed traffic and view statistics of your images via ‘Pictshare stats <<https://github.com/chrisiaut/pictshare_stats>>’\_

##### Smart query system[¶](#smart-query-system "Permalink to this headline")

PictShare images can be changed after upload just by modifying the URL. It works like this:

`https://base.domain/<options>/<image>`

For example: `https://avatar.gccollab.ca/100x100/negative/b260e36b60.jpg` will show you the uploaded Image ``b260e36b60.jpg`` but resize it to 100x100 pixels and apply the “negative” filter. The original image on the resource server will stay untouched.

##### Available options[¶](#available-options "Permalink to this headline")

Original URL: `https://www.pictshare.net/b260e36b60.jpg`

Note: If an option needs a value it works like this: `optionname\_value`. Eg: `pixelate\_10`

If there is an option requested that’s not recognized by PictShare it’s simply ignored, so this will work: <https://www.pictshare.net/pictshare-is-awesome/b260e36b60.jpg> and also even this will work: <https://www.pictshare.net/b260e36b60.jpg/how-can-this-still/work/>

###### Resizing[¶](#resizing "Permalink to this headline")

| Option | Parameter | Example URL |

| --- | --- | --- |

| <width>x<height> | -none- | <https://pictshare.net/20x20/b260e36b60.jpg> |

| forcecesize | -none- | <https://pictshare.net/100x400/forcesize/b260e36b60.jpg> |

###### Rotating[¶](#rotating "Permalink to this headline")

| Option | Parameter | Example URL |

| --- | --- | --- |

| left | -none- | <https://pictshare.net/left/b260e36b60.jpg> |

| right | -none- | <https://pictshare.net/right/b260e36b60.jpg> |

| upside | -none- | <https://pictshare.net/upside/b260e36b60.jpg> |

###### Filters[¶](#filters "Permalink to this headline")

| Option | Parameter | Example URL |

| --- | --- | --- |

| negative | -none- | <https://pictshare.net/negative/b260e36b60.jpg> |

| grayscale | -none- | <https://pictshare.net/grayscale/b260e36b60.jpg> |

| brightness | -255 to 255 | <https://pictshare.net/brightness_100/b260e36b60.jpg> |

| edgedetect | -none- | <https://pictshare.net/edgedetect/b260e36b60.jpg> |

| smooth | -10 to 2048 | <https://pictshare.net/smooth_3/b260e36b60.jpg> |

| contrast | -100 to 100 | <https://pictshare.net/contrast_40/b260e36b60.jpg> |

| pixelate | 0 to 100 | <https://pictshare.net/pixelate_10/b260e36b60.jpg> |

| blur | -none- or 0 to 5 | <https://pictshare.net/blur/b260e36b60.jpg> |

| sepia | -none- | <https://pictshare.net/sepia/b260e36b60.jpg> |

| sharpen | -none- | <https://pictshare.net/sharpen/b260e36b60.jpg> |

| emboss | -none- | <https://pictshare.net/emboss/b260e36b60.jpg> |

| cool | -none- | <https://pictshare.net/cool/b260e36b60.jpg> |

| light | -none- | <https://pictshare.net/light/b260e36b60.jpg> |

| aqua | -none- | <https://pictshare.net/aqua/b260e36b60.jpg> |

| fuzzy | -none- | <https://pictshare.net/fuzzy/b260e36b60.jpg> |

| boost | -none- | <https://pictshare.net/boost/b260e36b60.jpg> |

| gray | -none- | <https://pictshare.net/gray/b260e36b60.jpg> |

###### GIF to MP4[¶](#gif-to-mp4 "Permalink to this headline")

| Option | Parameter | Example URL |

| --- | --- | --- |

| mp4 | -none- | <https://www.pictshare.net/mp4/102687fe65.gif> |

| raw | -none- | <https://www.pictshare.net/mp4/raw/102687fe65.gif> |

| preview | -none- | <https://www.pictshare.net/mp4/preview/102687fe65.gif> |

###### MP4 options[¶](#mp4-options "Permalink to this headline")

| Option | Parameter | Example URL |

| --- | --- | --- |

| -none- | -none- | <https://www.pictshare.net/65714d22f0.mp4> |

| raw | -none- | <https://www.pictshare.net/raw/65714d22f0.mp4> |

| preview | -none- | <https://www.pictshare.net/preview/65714d22f0.mp4> |

You can also combine as many options as you want. Even multiple times! Want your image to be negative, resized, grayscale , with increased brightness and negate it again? No problem: <https://pictshare.net/500x500/grayscale/negative/brightness_100/negative/b260e36b60.jpg>

#### Security and privacy[¶](#security-and-privacy "Permalink to this headline")

* No exif data is stored on the server, all jpegs get cleaned on upload

