Skip to content

Commit

Permalink
Merge bb5eac8 into 78e605b
Browse files Browse the repository at this point in the history
  • Loading branch information
Awalgawe authored Mar 27, 2021
2 parents 78e605b + bb5eac8 commit 18d079c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 16 deletions.
70 changes: 70 additions & 0 deletions src/App.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,64 @@ describe('App', () => {
assert.instanceOf(app, App);
});
});

describe('with unsuccessful single team authorization results', () => {
it('should test once and throws multiple times when tokenVerificationEnabled is true', async () => {
// Arrange
const error = new Error("An API error occurred: something's wrong");
const test = sinon.fake.rejects(error);
const fakeLogger = createFakeLogger();
const overrides = mergeOverrides(withNoopAppMetadata(), withUnsuccessfulBotUserFetchingWebClient(test));
const App = await importApp(overrides); // eslint-disable-line @typescript-eslint/naming-convention, no-underscore-dangle, id-blacklist, id-match
const event: ReceiverEvent = {
ack: async () => {},
body: {
type: 'shortcut',
team: { id: '' },
enterprise: { id: '' },
user: { id: '' },
},
};

// Act
const app = new App({ token: '', signingSecret: '', logger: fakeLogger });

// Assert
assert.equal(await app.processEvent(event).catch((e) => e as Error), error);
assert.equal(await app.processEvent(event).catch((e) => e as Error), error); // retry
assert.equal(fakeLogger.warn.callCount, 2);
assert.equal(fakeLogger.error.callCount, 2);
assert.equal(test.callCount, 1);
});

it('should test and throws multiple times when tokenVerificationEnabled is false', async () => {
// Arrange
const error = new Error("An API error occurred: something's wrong");
const test = sinon.fake.rejects(error);
const fakeLogger = createFakeLogger();
const overrides = mergeOverrides(withNoopAppMetadata(), withUnsuccessfulBotUserFetchingWebClient(test));
const App = await importApp(overrides); // eslint-disable-line @typescript-eslint/naming-convention, no-underscore-dangle, id-blacklist, id-match
const event: ReceiverEvent = {
ack: async () => {},
body: {
type: 'shortcut',
team: { id: '' },
enterprise: { id: '' },
user: { id: '' },
},
};

// Act
const app = new App({ token: '', signingSecret: '', logger: fakeLogger, tokenVerificationEnabled: false });

// Assert
assert.equal(await app.processEvent(event).catch((e) => e as Error), error);
assert.equal(await app.processEvent(event).catch((e) => e as Error), error); // retry
assert.equal(fakeLogger.warn.callCount, 2);
assert.equal(fakeLogger.error.callCount, 2);
assert.equal(test.callCount, 2);
});
});
it('should succeed with an authorize callback', async () => {
// Arrange
const authorizeCallback = sinon.fake();
Expand Down Expand Up @@ -1915,6 +1973,18 @@ function withSuccessfulBotUserFetchingWebClient(botId: string, botUserId: string
};
}

function withUnsuccessfulBotUserFetchingWebClient(test: SinonSpy): Override {
return {
'@slack/web-api': {
WebClient: class {
public auth = {
test,
};
},
},
};
}

function withPostMessage(spy: SinonSpy): Override {
return {
'@slack/web-api': {
Expand Down
67 changes: 51 additions & 16 deletions src/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export interface AppOptions {
clientOptions?: Pick<WebClientOptions, 'slackApiUrl'>;
socketMode?: boolean;
developerMode?: boolean;
tokenVerificationEnabled?: boolean;
}

export { LogLevel, Logger } from '@slack/logger';
Expand Down Expand Up @@ -210,6 +211,7 @@ export default class App {
installerOptions = undefined,
socketMode = undefined,
developerMode = false,
tokenVerificationEnabled = true,
}: AppOptions = {}) {
// this.logLevel = logLevel;
this.developerMode = developerMode;
Expand Down Expand Up @@ -354,7 +356,21 @@ export default class App {
`token as well as authorize or oauth installer options were provided. ${tokenUsage}`,
);
}
this.authorize = singleAuthorization(this.client, { botId, botUserId, botToken: token });

if (botUserId !== undefined && botId !== undefined) {
this.authorize = ({ isEnterpriseInstall }) =>
Promise.resolve({
isEnterpriseInstall,
botId,
botUserId,
});
} else {
this.authorize = singleAuthorizeFactory({
client: this.client,
botToken: token,
tokenVerificationEnabled,
});
}
} else if (authorize === undefined && !usingOauth) {
throw new AppInitializationError(
`No token, no authorize, and no oauth installer options provided. ${tokenUsage}`,
Expand Down Expand Up @@ -1052,23 +1068,42 @@ function defaultErrorHandler(logger: Logger): ErrorHandler {
};
}

function singleAuthorization(
client: WebClient,
authorization: Partial<AuthorizeResult> & { botToken: Required<AuthorizeResult>['botToken'] },
): Authorize<boolean> {
// TODO: warn when something needed isn't found
const identifiers: Promise<{ botUserId: string; botId: string }> =
authorization.botUserId !== undefined && authorization.botId !== undefined
? Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId })
: client.auth.test({ token: authorization.botToken }).then((result) => {
return {
botUserId: result.user_id as string,
botId: result.bot_id as string,
};
});
function authTest(client: WebClient, token: string) {
return client.auth.test({ token }).then(({ user_id, bot_id }) => ({
botUserId: user_id as string,
botId: bot_id as string,
}));
}

interface SingleAuthorizeFactoryArgs {
client: WebClient;
tokenVerificationEnabled: boolean;
botToken: string;
}

function singleAuthorizeFactory({
client,
botToken,
tokenVerificationEnabled,
}: SingleAuthorizeFactoryArgs): App['authorize'] {
let identifiers: { botUserId: string; botId: string };

const authPromise = tokenVerificationEnabled ? authTest(client, botToken) : undefined;

return async ({ isEnterpriseInstall }) => {
return { isEnterpriseInstall, botToken: authorization.botToken, ...(await identifiers) };
if (!identifiers) {
if (authPromise) {
identifiers = await authPromise;
} else {
identifiers = await authTest(client, botToken);
}
}

return {
isEnterpriseInstall,
botToken,
...identifiers,
};
};
}

Expand Down

0 comments on commit 18d079c

Please sign in to comment.