Skip to content

Commit

Permalink
docs: updated the README file
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathas committed Oct 17, 2023
1 parent 3f6da82 commit c2e7ad8
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 24 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,6 @@ resources/db/data

# GraphQL Schema (Auto-generated when the project runs)
schema.gql

# Compodoc generated
documentation
10 changes: 4 additions & 6 deletions .sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ MICROSOFT_IDENTITY_TENANT_ID=
MICROSOFT_IDENTITY_CLIENT_ID=
MICROSOFT_IDENTITY_CLIENT_SECRET=

MICROSOFT_IDENTITY_REDIRECT_URI=http://localhost:3000/microsoft/auth/redirect
MICROSOFT_IDENTITY_POST_LOGOUT_REDIRECT_URI=http://localhost:3000/microsoft/auth
MICROSOFT_GRAPH_REDIRECT_URI=http://localhost:3000/microsoft/auth/redirect
MICROSOFT_GRAPH_POST_LOGOUT_REDIRECT_URI=http://localhost:3000/microsoft/auth

MICROSOFT_IDENTITY_GRAPH_API_ENDPOINT=https://graph.microsoft.com/ # graph api endpoint string should end with a trailing slash

MICROSOFT_IDENTITY_USE_WEBHOOK=true
MICROSOFT_IDENTITY_WEBHOOK_URL=https://close-wrongly-jaybird.ngrok-free.app/webhook
MICROSOFT_GRAPH_USE_WEBHOOK=true
MICROSOFT_GRAPH_WEBHOOK_URL=https://close-wrongly-jaybird.ngrok-free.app/webhook
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Jonathas Ribeiro

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
193 changes: 181 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

A GraphQL API for managing To Dos and synchronizing them with Microsoft To Do API

![Microsoft To Do](/docs/images/microsoft-todo.png)

## Table of Contents

- [Features](#features)
- [Tech](#tech)
- [Installation](#installation)
- [Running the project](#running-the-project)
- [Configuring the integration with the Microsoft To Do API](#configuring-the-integration-with-the-microsoft-to-do-api)
- [Way of working](#way-of-working)
- [Integration tests](#integration-tests)
- [Database](#database)
- [Synchronization](#synchronization)
- [Webhook](#webhook)
- [GraphQL Subscription](#graphql-subscription)
- [Manual synchronization](#manual-synchronization)
- [Cron job](#cron-job)
- [More documentation](#more-documentation)
- [Compodoc](#compodoc)
- [Postman collection](#postman-collection)
- [GraphQL Playground](#graphql-playground)
- [Known limitations](#known-limitations)

## Features

- Possibility to query tasks
Expand All @@ -17,6 +40,8 @@ A GraphQL API for managing To Dos and synchronizing them with Microsoft To Do AP
## Tech

- PostgreSQL
- Redis
- Docker
- TypeScript
- NestJS
- Express
Expand All @@ -28,52 +53,196 @@ A GraphQL API for managing To Dos and synchronizing them with Microsoft To Do AP
$ npm install
```

## Running the app
## Running the project

1) Copy the .sample.env file to .env and fill in the Microsoft To Do API integration values.

2) Add to MICROSOFT_GRAPH_WEBHOOK_URL the address where the Microsoft To Do API will be able to find the webhook it will need to call to deliver the updates. In my case I have a free domain on [ngrok](https://ngrok.com/), so after starting the API I run the following to make it available:

```bash
$ ngrok http --domain=close-wrongly-jaybird.ngrok-free.app 3000
```

Ps: Webhook is only one of the ways that our project synchronizes with the Microsoft To Do. The API should also work without it.

3) Run the containers for the DB and Redis

```bash
$ docker compose -f ./resources/docker-compose.yml up
```

This command will automatically create the DB and required tables.

4) Run the API with one of the following commands

```bash
# development
$ npm run start
$ npm start

# watch mode
$ npm run start:dev

# debug mode
$ npm run start:debug

# production mode
$ npm run start:prod
```

## Test
## Configuring the integration with the Microsoft To Do API

```bash
# unit tests
$ npm run test
Since there's no client-side part connecting to our yet, the OAuth flow has been simplified without any page interaction.

# integration tests
$ npm run test:integration
After running the API successfully with the correct .env values:

1) Open [http://localhost:3000/microsoft/auth/signin](http://localhost:3000/microsoft/auth/signin) on your browser. This will redirect you to the authorization page from Microsoft after signing in.

![Permissions](/docs/images/permissions.png)

2) The redirect url is configured to [http://localhost:3000/microsoft/auth/redirect](http://localhost:3000/microsoft/auth/redirect) in Azure (app config), so after you accept the permission, you'll be redirected to the redirect endpoint. The MSIdentity controller will then use the code it received, request tokens and save them to the microsoft_integrations table.

# test coverage
$ npm run test:cov
3) That's it! After the previous step, our API is able to sync with the Microsoft To Do API.

## Integration tests

First the Docker containers need to be running and then you can run the integration tests like so:

```bash
$ npm run test:integration
```

## Way of working

The [husky](https://www.npmjs.com/package/husky) lib is used for enforcing some rules for local development using Git hooks.

- On every commit:
- The commit message is validated against [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
- The staged files are linted with several [eslint](https://www.npmjs.com/package/eslint) rules
- Before every push to the repository, the integration tests will run and should pass for the push to proceed.

More about way of working and release management can be found on [this post I wrote a while ago](https://jonathas.com/efficient-software-release-management-with-automated-changelog-generation/).

## Database

The diagram below is parsed via [mermaid](https://mermaid.js.org/syntax/entityRelationshipDiagram.html).

- The "ext" prefix in some of the fields refers to values that come from the Microsoft To Do API.
- A basic users table was created in order to keep track of the tokens, but no user authentication or handling is done at the moment.
- The subscriptions table was created so that when a list is created, a subscription for that list is created in the Microsoft To Do API. We need to create a subscription in order to be able to receive requests to our webhook which are related to tasks in a list. We keep track of it so that when a list is deleted, its related subscription is also deleted from the Microsoft To Do API.

```mermaid
erDiagram
tasks ||--o| lists : relates
lists ||--|{ tasks : contains
users ||--|| microsoft_integrations : has
tasks ||--|| subscriptions : has
tasks {
id int
name varchar(255)
description varchar(255)
is_done boolean
ext_id varchar(255)
list_id int
last_synched_at timestamp
created_at timestamp
updated_at timestamp
list_id int
}
lists {
id int
name varchar(255)
description varchar(255)
ext_id varchar(255)
ext_subscription_id varchar(255)
last_synched_at timestamp
created_at timestamp
updated_at timestamp
}
users {
id int
email varchar(255)
password varchar(255)
created_at timestamp
updated_at timestamp
}
microsoft_integrations {
id int
user_id int
access_token text
id_token text
refresh_token text
expires_on timestamp
created_at timestamp
updated_at timestamp
}
subscriptions {
id int
subscription_id varchar(255)
resource varchar(255)
ext_list_id varchar(255)
expiration_date_time timestamp
created_at timestamp
updated_at timestamp
}
```

## Synchronization

Our API synchronizes with the Microsoft To Do API in 3 ways

### Webhook

The Microsoft Graph API allows subscribing to task changes inside of lists, so whenever a list is created in our API, a subscription is created in the Microsoft Graph API to track changes to it.
In order for the webhook sync to work, a publicly accessible url for our API needs to be configured on .env and the integration set to true

```bash
MICROSOFT_GRAPH_USE_WEBHOOK=true
MICROSOFT_GRAPH_WEBHOOK_URL=https://close-wrongly-jaybird.ngrok-free.app/webhook
```

### GraphQL subscription

There's a ```notifications``` subscription available, which can be useful for client-side apps to know when some event happens. Every time a webhook request changes something in our DB, this change is pushed to the subscription

![GraphQL Subscription](/docs/images/subscription.png)

### Manual synchronization

It might happen that you created a task in the Microsoft To Do app but our API wasn't running at the time, or perhaps when you started the API you already had tasks in the app, so the manual synchronization allows for these changes to be synchronized to the DB.

You can run it by calling the ```startManualSync``` mutation.

### Cron job

A cron job can also be enabled in .env

```bash
USE_CRON=true
```

If enabled, it should run every minute and call the same method as the manual synchronization

## More documentation

## Compodoc

You can have a good overview about the project by running Compodoc:

```bash
$ npm run compodoc
```

This will generate a directory called "documentation" with several files, so you can open the index.html file on your browser.

## Postman collection

A [Postman](https://www.postman.com/downloads/) collection can be found inside of the docs directory. You can just import it to Postman and start using it with the API.

## GraphQL Playground

Another way of interacting with the API is with GraphQL Playground. You can access it by opening [http://localhost:3000/graphql](http://localhost:3000/graphql) on your browser.

## Known limitations

- There's no user management yet
- There's no user authentication yet
- Microsoft Graph API subscriptions are currently set to their [maximum length of subscription](https://learn.microsoft.com/en-us/graph/api/resources/subscription?view=graph-rest-1.0#maximum-length-of-subscription-per-resource-type) (4230 minutes) and there's no renewal mechanism.
Binary file added docs/images/microsoft-todo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/permissions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/subscription.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions src/config/microsoft-graph.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export interface MicrosoftGraphConfig {
clientSecret: string;
redirectUri: string;
postLogoutRedirectUri: string;
graphApiEndpoint: string;
useWebhook: boolean;
webhookUrl: string;
}
Expand All @@ -19,10 +18,9 @@ export default registerAs(
tenantId: process.env.MICROSOFT_IDENTITY_TENANT_ID,
clientId: process.env.MICROSOFT_IDENTITY_CLIENT_ID,
clientSecret: process.env.MICROSOFT_IDENTITY_CLIENT_SECRET,
redirectUri: process.env.MICROSOFT_IDENTITY_REDIRECT_URI,
postLogoutRedirectUri: process.env.MICROSOFT_IDENTITY_POST_LOGOUT_REDIRECT_URI,
graphApiEndpoint: process.env.MICROSOFT_IDENTITY_GRAPH_API_ENDPOINT,
useWebhook: process.env.MICROSOFT_IDENTITY_USE_WEBHOOK === 'true',
webhookUrl: process.env.MICROSOFT_IDENTITY_WEBHOOK_URL
redirectUri: process.env.MICROSOFT_GRAPH_REDIRECT_URI,
postLogoutRedirectUri: process.env.MICROSOFT_GRAPH_POST_LOGOUT_REDIRECT_URI,
useWebhook: process.env.MICROSOFT_GRAPH_USE_WEBHOOK === 'true',
webhookUrl: process.env.MICROSOFT_GRAPH_WEBHOOK_URL
})
);
4 changes: 4 additions & 0 deletions tsconfig.doc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"include": ["src/**/*.ts"],
"exclude": ["src/test.ts", "src/**/*.spec.ts"]
}

0 comments on commit c2e7ad8

Please sign in to comment.