Skip to content

Commit

Permalink
Merge branch 'master' into feat/auth-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
bodinsamuel committed Sep 17, 2024
2 parents a8152e7 + e40a1d8 commit 68be40f
Show file tree
Hide file tree
Showing 81 changed files with 974 additions and 618 deletions.
2 changes: 1 addition & 1 deletion docs-v2/host/self-host/self-hosting-instructions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ You can disable telemetry by setting the env var `TELEMETRY=false` (in the
## Logs[](#logs 'Direct link to Logs')

We use Elasticsearch to store Nango's execution logs and power the logs UI.
To limit the requirements to self-host, this stack is optional and up to the developper to setup.
To limit the requirements to self-host, this stack is optional and up to the developer to setup.

If you want to enable logs, you will need to:
- Host an Elasticsearch cluster
Expand Down
32 changes: 32 additions & 0 deletions docs-v2/integrations/all/odoo.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: Odoo
sidebarTitle: Odoo
---

API configurations: [`odoo`](https://nango.dev/providers.yaml)

## Features

| Features | Status |
| - | - |
| [Auth (OAuth)](/integrate/guides/authorize-an-api) ||
| [Sync data](/integrate/guides/sync-data-from-an-api) ||
| [Perform workflows](/integrate/guides/perform-workflows-with-an-api) ||
| [Proxy requests](/integrate/guides/proxy-requests-to-an-api) ||
| [Receive webhooks](/integrate/guides/receive-webhooks-from-an-api) | 🚫 (time to contribute: <48h) |

<Tip>We can implement missing features in &lt;48h, just ask for it in the [community](https://nango.dev/slack).</Tip>

## Getting started

- [How to register an Application](https://odoo-restapi.readthedocs.io/en/latest/connection/configuration.html)
- [OAuth related docs](https://odoo-restapi.readthedocs.io/en/latest/connection/logging_in/oauth2_authentication.html)
- [Odoo REST API docs](https://odoo-restapi.readthedocs.io/en/latest/)

<Tip>Need help getting started? Get help in the [community](https://nango.dev/slack).</Tip>

## API gotchas

- Nango currently supports the integration of Odoo using the [Odoo REST API by Synconic module](https://apps.odoo.com/apps/modules/17.0/restapi)

<Note>Add Getting Started links and Gotchas by [editing this page](https://github.com/nangohq/nango/tree/master/docs-v2/integrations/all/odoo.mdx)</Note>
1 change: 1 addition & 0 deletions docs-v2/integrations/erp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ sidebarTitle: ERP
<CardGroup cols={4}>
<Card title="Microsoft Dynamics 365 Finance & Operations" href="/integrations/all/microsoft-tenant-specific" color="#68a063" />
<Card title="Netsuite" href="/integrations/all/netsuite" color="#68a063" />
<Card title="Odoo" href="/integrations/all/odoo" color="#68a063" />
<Card title="Sage" href="/integrations/all/sage" color="#68a063" />
<Card title="Unanet" href="/integrations/all/unanet" color="#68a063" />
</CardGroup>
21 changes: 21 additions & 0 deletions docs-v2/integrations/integration-templates/discourse.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: 'Discourse API Integration Template'
sidebarTitle: 'Discourse'
---

## Get started with the Discourse template

<Card title="How to use integration templates"
href="/understand/concepts/templates"
icon="book-open">
Learn how to use integration templates in Nango
</Card>

<Card title="Get the Discourse template"
href="https://github.com/NangoHQ/nango/tree/master/integration-templates/discourse"
icon="github">
Get the latest version of the Discourse integration template from GitHub
</Card>

## Need help with the template?
Please reach out in the [Slack community](https://nango.dev/slack), we are very active there and happy to help!
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ sidebarTitle: 'Netsuite'
</Card>

<Card title="Get the Netsuite template"
href="https://github.com/NangoHQ/nango/tree/master/integration-templates/netsuite"
href="https://github.com/NangoHQ/nango/tree/master/integration-templates/netsuite-tba"
icon="github">
Get the latest version of the Netsuite integration template from GitHub
</Card>

## Need help with the template?
Please reach out in the [Slack community](https://nango.dev/slack), we are very active there and happy to help!
Please reach out in the [Slack community](https://nango.dev/slack), we are very active there and happy to help!
4 changes: 3 additions & 1 deletion docs-v2/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"integrations/integration-templates/checkr-partner",
"integrations/integration-templates/checkr-partner-staging",
"integrations/integration-templates/clari-copilot",
"integrations/integration-templates/discourse",
"integrations/integration-templates/expensify",
"integrations/integration-templates/exact-online",
"integrations/integration-templates/evaluagent",
Expand All @@ -290,7 +291,7 @@
"integrations/integration-templates/microsoft-active-directory",
"integrations/integration-templates/microsoft-teams",
"integrations/integration-templates/next-cloud-ocs",
"integrations/integration-templates/netsuite",
"integrations/integration-templates/netsuite-tba",
"integrations/integration-templates/notion",
"integrations/integration-templates/pipedrive",
"integrations/integration-templates/salesforce",
Expand Down Expand Up @@ -456,6 +457,7 @@
"integrations/all/netsuite",
"integrations/all/next-cloud",
"integrations/all/notion",
"integrations/all/odoo",
"integrations/all/okta",
"integrations/all/one-drive",
"integrations/all/one-note",
Expand Down
44 changes: 44 additions & 0 deletions integration-templates/discourse/helpers/paginate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { NangoSync, ProxyConfiguration } from '../../models';

export interface PaginationParams {
endpoint: string;
initialPage?: number;
params?: Record<string, any>;
}

/**
* Asynchronous generator function for paginating through API results.
*
* This function handles pagination by making repeated requests to the specified API endpoint.
* It yields arrays of results for each page until no more data is available.
*
* @param nango The NangoSync instance used for making API calls.
* @param params Configuration parameters for pagination, including the endpoint, initial page, and additional params.
* @returns An async generator that yields arrays of results from each page.
*/
async function* paginate<T>(nango: NangoSync, { endpoint, initialPage = 1, params }: PaginationParams): AsyncGenerator<T[], void, undefined> {
let currentPage = initialPage;

while (true) {
const payload: ProxyConfiguration = {
endpoint,
params: {
page: currentPage,
...params
}
};

const response = await nango.get<T[]>(payload);
const responseData = response.data;

if (!responseData || responseData.length === 0) {
break;
}

yield responseData;

currentPage++;
}
}

export default paginate;
17 changes: 17 additions & 0 deletions integration-templates/discourse/mappers/toUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { User } from '../../models';
import type { DiscourseUser } from '../types';

/**
* Converts a DiscourseUser object to a slim User object.
* Only includes essential properties mapped from DiscourseUser.
* @param user The DiscourseUser object to convert.
* @returns User object representing DiscourseUser user information.
*/
export function toUser(user: DiscourseUser): User {
return {
id: user.id,
username: user.username,
name: user.name,
admin: user.admin
};
}
17 changes: 17 additions & 0 deletions integration-templates/discourse/nango.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
integrations:
discourse:
syncs:
active-users:
description: |
Fetches a list of active users from Discourse.
endpoint: /discourse/active-users
sync_type: full
runs: every 1 hour
output: User
track_deletes: true
models:
User:
id: number
username: string
name: string
admin: boolean
32 changes: 32 additions & 0 deletions integration-templates/discourse/syncs/active-users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { NangoSync, User } from '../../models';
import type { DiscourseUser } from '../types';
import paginate from '../helpers/paginate.js';
import type { PaginationParams } from '../helpers/paginate';
import { toUser } from '../mappers/toUser.js';

/**
* Fetches user data from an API and saves it in batch.
*
* This function uses the `paginate` helper to fetch active users from the specified API endpoint in a paginated manner.
* It maps the raw user data to a `User` format using the `toUser` mapper function and then saves the mapped data
* using the `nango.batchSave` method.
* For detailed endpoint documentation, refer to:
* https://docs.discourse.org/#tag/Admin/operation/adminListUsers
*
* @param nango The NangoSync instance used for making API calls and saving data.
* @returns A promise that resolves when the data has been successfully fetched and saved.
*/
export default async function fetchData(nango: NangoSync): Promise<void> {
const config: PaginationParams = {
endpoint: '/admin/users/list/active',
params: {
order: 'created',
asc: 'true',
stats: true // Additional parameters for the API request can be added in here
}
};

for await (const users of paginate<DiscourseUser>(nango, config)) {
await nango.batchSave<User>(users.map(toUser), 'User');
}
}
26 changes: 26 additions & 0 deletions integration-templates/discourse/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export interface DiscourseUser {
id: number;
username: string;
name: string;
avatar_template: string;
email: string;
secondary_emails: (string | null)[];
active: boolean;
admin: boolean;
moderator: boolean;
last_seen_at: string;
last_emailed_at: string;
created_at: string;
last_seen_age: number;
last_emailed_age: number;
created_at_age: number;
trust_level: number;
manual_locked_trust_level: string;
title: string;
time_read: number;
staged: boolean;
days_visited: number;
posts_read_count: number;
topics_entered: number;
post_count: number;
}
70 changes: 70 additions & 0 deletions integration-templates/google-drive/actions/fetch-document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type { NangoAction, ProxyConfiguration } from '../../models';
import type { GoogleDriveFileResponse } from '../types.js';
import { mimeTypeMapping } from '../types.js';

/**
* Retrieves and returns the content of a Google Drive file as a base64-encoded string.
*
* For detailed endpoint documentation, refer to:
*
* https://developers.google.com/drive/api/reference/rest/v3/files/get
* https://developers.google.com/drive/api/reference/rest/v3/files/export
* @param nango - An instance of NangoAction used for making API requests.
* @param input - The ID of the file to be retrieved, provided as a string.
* @returns The base64-encoded content of the file.
* @throws Error if the input is invalid, or if the file metadata or content retrieval fails.
*/
export default async function runAction(nango: NangoAction, input: string): Promise<string> {
if (!input || typeof input !== 'string') {
throw new Error('Missing or invalid input: a file ID is required and should be a string');
}

// Fetch the file metadata first to get the MIME type
const Config: ProxyConfiguration = {
endpoint: `drive/v3/files/${input}`,
params: {
fields: 'id, name, mimeType'
}
};
const fileMetadataResponse = await nango.get<GoogleDriveFileResponse>(Config);

if (fileMetadataResponse.status !== 200 || !fileMetadataResponse.data) {
throw new Error(`Failed to retrieve file metadata: Status Code ${fileMetadataResponse.status}`);
}

const file = fileMetadataResponse.data;
const mimeTypeDetails = mimeTypeMapping[file.mimeType];

if (!mimeTypeDetails) {
throw new Error(`Unsupported MIME type: ${file.mimeType}`);
}

const { mimeType: exportMimeType, responseType } = mimeTypeDetails;

await nango.log('Fetching document of ', { exportMimeType });

const endpoint = responseType === 'text' ? `drive/v3/files/${file.id}/export` : `drive/v3/files/${file.id}`;
const params = responseType === 'text' ? { mimeType: exportMimeType } : { alt: 'media' };

const config: ProxyConfiguration = {
endpoint,
params,
responseType
};
const response = await nango.get(config);

if (response.status !== 200) {
throw new Error(`Failed to retrieve file content: Status Code ${response.status}`);
}

if (responseType === 'text') {
return response.data ?? '';
} else {
const chunks: Buffer[] = [];
for await (const chunk of response.data) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);
return buffer.toString('base64');
}
}
35 changes: 0 additions & 35 deletions integration-templates/google-drive/actions/fetch-pdf.ts

This file was deleted.

Loading

0 comments on commit 68be40f

Please sign in to comment.