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

removed storeOrgInstallion and fetchOrgInstallation from Installation… #1148

Merged
merged 1 commit into from Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
60 changes: 24 additions & 36 deletions docs/_packages/oauth.md
Expand Up @@ -25,7 +25,7 @@ It may be helpful to read the tutorials on [getting started](https://slack.dev/n

### Initialize the installer

This package exposes an `InstallProvider` class, which sets up the required configuration and exposes methods such as `generateInstallUrl`, `handleCallback`, `authorize`, `orgAuthorize` for use within your apps. At a minimum, `InstallProvider` takes a `clientId` and `clientSecret` (both which can be obtained under the **Basic Information** of your app configuration). `InstallProvider` also requires a `stateSecret`, which is used to encode the generated state, and later used to decode that same state to verify it wasn't tampered with during the OAuth flow. **Note**: This example is not ready for production because it only stores installations (tokens) in memory. Please go to the [storing installations in a database](#storing-installations-in-a-database) section to learn how to plug in your own database.
This package exposes an `InstallProvider` class, which sets up the required configuration and exposes methods such as `generateInstallUrl`, `handleCallback`, `authorize` for use within your apps. At a minimum, `InstallProvider` takes a `clientId` and `clientSecret` (both which can be obtained under the **Basic Information** of your app configuration). `InstallProvider` also requires a `stateSecret`, which is used to encode the generated state, and later used to decode that same state to verify it wasn't tampered with during the OAuth flow. **Note**: This example is not ready for production because it only stores installations (tokens) in memory. Please go to the [storing installations in a database](#storing-installations-in-a-database) section to learn how to plug in your own database.

```javascript
const { InstallProvider } = require('@slack/oauth');
Expand Down Expand Up @@ -155,9 +155,7 @@ app.get('/slack/oauth_redirect', (req, res) => {

Although this package uses a default `MemoryInstallationStore`, it isn't recommended for production use since the access tokens it stores would be lost when the process terminates or restarts. Instead, `InstallProvider` has an option for supplying your own installation store, which is used to save and retrieve install information (like tokens) to your own database.

An installation store is an object that provides four methods: `storeInstallation`, `storeOrgInstallation`, `fetchInstallation` and `fetchOrgInstallation`. `storeInstallation` and `storeOrgInstallation` takes an `installation` as an argument, which is an object that contains all installation related data (like tokens, teamIds, enterpriseIds, etc). `fetchInstallation` and `fetchOrgInstallation` takes in a `installQuery`, which is used to query the database. The `installQuery` can contain `teamId`, `enterpriseId`, `userId`, and `conversationId`.

**Note**: `fetchOrgInstallation` and `storeOrgInstallation` were introduced to support Org wide app installations (currently in beta).
An installation store is an object that provides two methods: `storeInstallation`, and `fetchInstallation`. `storeInstallation` takes an `installation` as an argument, which is an object that contains all installation related data (like tokens, teamIds, enterpriseIds, etc). `fetchInstallation` takes in a `installQuery`, which is used to query the database. The `installQuery` can contain `teamId`, `enterpriseId`, `userId`, `conversationId` and `isEnterpriseInstall`.

In the following example, the `installationStore` option is used and the object is defined in line. The methods are implemented by calling an example database library with simple get and set operations.

Expand All @@ -171,39 +169,29 @@ const installer = new InstallProvider({
// returns nothing
storeInstallation: async (installation) => {
// replace myDB.set with your own database or OEM setter
if (installation.team.id !== undefined) {
// non enterprise org app installation
return myDB.set(installation.team.id, installation);
} else {
throw new Error('Failed saving installation data to installationStore');
}
},
// takes in an installQuery as an argument
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string'};
// returns installation object from database
fetchInstallation: async (installQuery) => {
// replace myDB.get with your own database or OEM getter
// non enterprise org app lookup
return await myDB.get(installQuery.teamId);
},
// takes in an installation object as an argument
// returns nothing
storeOrgInstallation: async (installation) => {
// replace myDB.set with your own database or OEM setter
if (installation.isEnterpriseInstall && installation.enterprise !== undefined) {
// enterprise app, org wide installation
if (installation.isEnterpriseInstall) {
// support for org wide app installation
return myDB.set(installation.enterprise.id, installation);
} else {
throw new Error('Failed saving installation data to installationStore');
// single team app installation
return myDB.set(installation.team.id, installation);
}
throw new Error('Failed saving installation data to installationStore');
},
// takes in an installQuery as an argument
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string'};
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: 'string', conversationId: 'string', isEnterpriseInstall: boolean};
// returns installation object from database
fetchInstallation: async (installQuery) => {
// replace myDB.get with your own database or OEM getter
// enterprise org app installation lookup
return await myDB.get(installQuery.enterpriseId);
if (query.isEnterpriseInstall && query.enterpriseId !== undefined) {
// org wide app installation lookup
return await myDB.get(installQuery.enterpriseId);
}
if (query.teamId !== undefined) {
// single team app installation lookup
return await myDB.get(installQuery.teamId);
}
throw new Error('Failed fetching installation');
},
},
});
Expand All @@ -212,19 +200,20 @@ const installer = new InstallProvider({

### Reading tokens and other installation data

You can use the the `installationProvider.authorize()` function to fetch data that has been saved in your installation store. For Org wide app installations, you can use `installationProvider.orgAuthorize()`
You can use the the `installationProvider.authorize()` function to fetch data that has been saved in your installation store.

```javascript
// installer.authorize takes in an installQuery as an argument
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string'};
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string', isEnterpriseInstall: boolean};
const result = installer.authorize({teamId: 'my-team-ID'});
const orgResult = installer.orgAuthorize({enterpriseId: 'my-enterprise-ID'});
/*
result = {
botToken: '',
userToken: '',
botId: '',
botUserId: '',
teamId: '';
enterpriseId: '';
}
*/
```
Expand All @@ -234,14 +223,13 @@ result = {
<strong><i>Reading extended installation data</i></strong>
</summary>

The `installer.authorize()`/`installer.orgAuthorize()` methods only returns a subset of the installation data returned by the installation store. To fetch the entire saved installation, use the `installer.installationStore.fetchInstallation()`/`installer.installationStore.fetchOrgInstallation()` methods.
The `installer.authorize()` method only returns a subset of the installation data returned by the installation store. To fetch the entire saved installation, use the `installer.installationStore.fetchInstallation()` method.

```javascript
// installer.installationStore.fetchInstallation takes in an installQuery as an argument
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string'};
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: 'string', conversationId: 'string', isEnterpriseInstall: boolean};
// returns an installation object
const result = await installer.installationStore.fetchInstallation({teamId: 'my-team-ID', enterpriseId: 'my-enterprise-ID'});
const orgResult = await installer.installationStore.fetchOrgInstallation({enterpriseId: 'my-enterprise-ID'});
const result = await installer.installationStore.fetchInstallation({teamId:'my-team-ID', enterpriseId:'my-enterprise-ID'});
```
</details>

Expand Down
39 changes: 19 additions & 20 deletions examples/oauth-v2/app.js
Expand Up @@ -31,28 +31,27 @@ const installer = new InstallProvider({
stateSecret: 'my-state-secret',
installationStore: {
storeInstallation: async (installation) => {
if (installation.team.id !== undefined) {
// non enterprise org app installation
return await keyv.set(installation.team.id, installation);
} else {
throw new Error('Failed saving installation data to installationStore');
}
},
storeOrgInstallation: async (installation) => {
if (installation.isEnterpriseInstall && installation.enterprise !== undefined) {
// enterprise app, org wide installation
if (installation.isEnterpriseInstall) {
// storing org installation
return await keyv.set(installation.enterprise.id, installation);
} else {
throw new Error('Failed saving installation data to installationStore');
} else if (installation.team !== null && installation.team.id !== undefined) {
// storing single team installation
return await keyv.set(installation.team.id, installation);;
}
throw new Error('Failed saving installation data to installationStore');
},
fetchInstallation: async (InstallQuery) => {
// non org app lookup
return await keyv.get(InstallQuery.teamId);
},
fetchOrgInstallation: async (InstallQuery) => {
// enterprise org app installation lookup
return await keyv.get(InstallQuery.enterpriseId);
if (query.isEnterpriseInstall) {
if (query.enterpriseId !== undefined) {
// fetching org installation
return await keyv.get(InstallQuery.enterpriseId)
}
}
if (query.teamId !== undefined) {
// fetching single team installation
return await keyv.get(InstallQuery.teamId);
}
throw new Error('Failed fetching installation');
},
},
});
Expand Down Expand Up @@ -101,10 +100,10 @@ slackEvents.on('app_home_opened', async (event, body) => {
let DBInstallData;
if (body.authorizations !== undefined && body.authorizations[0].is_enterprise_install) {
//org wide installation
DBInstallData = await installer.orgAuthorize({enterpriseId: body.enterprise_id});
DBInstallData = await installer.authorize({enterpriseId: body.enterprise_id, isEnterpriseInstall: true});
} else {
// non org wide installation
DBInstallData = await installer.authorize({teamId:body.team_id});
DBInstallData = await installer.authorize({teamId:body.team_id, isEnterpriseInstall: false});
}
const web = new WebClient(DBInstallData.botToken);
await web.views.publish({
Expand Down