Skip to content
This repository was archived by the owner on Nov 15, 2024. It is now read-only.

Commit ba44920

Browse files
committed
wip
1 parent 524d7ee commit ba44920

File tree

19 files changed

+367
-82
lines changed

19 files changed

+367
-82
lines changed

api_server/bin/api_server.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ const SecretsConfig = require(ConfigDirectory + '/secrets.js');
1616
const PubNubConfig = require(ConfigDirectory + '/pubnub.js');
1717
const MixPanelConfig = require(ConfigDirectory + '/mixpanel.js');
1818
const SlackConfig = require(ConfigDirectory + '/slack.js');
19+
const GithubConfig = require(ConfigDirectory + '/github.js');
20+
const AsanaConfig = require(ConfigDirectory + '/asana.js');
1921
const LoggerConfig = require(ConfigDirectory + '/logger.js');
2022
const EmailConfig = require(ConfigDirectory + '/email.js');
2123
const AWSConfig = require(ConfigDirectory + '/aws.js');
@@ -71,6 +73,8 @@ const MyAPICluster = new ClusterWrapper(
7173
pubnub: PubNubConfig,
7274
mixpanel: MixPanelConfig,
7375
slack: SlackConfig,
76+
github: GithubConfig,
77+
asana: AsanaConfig,
7478
email: EmailConfig,
7579
aws: AWSConfig,
7680
webclient: WebClientConfig,

api_server/config/api.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,9 @@ module.exports = {
3535
assetEnvironment: process.env.CS_API_ASSET_ENV || 'prod',
3636

3737
// public url to access the API server from "beyond"
38-
publicApiUrl: process.env.CS_API_PUBLIC_URL || 'https://api.codestream.com'
38+
publicApiUrl: process.env.CS_API_PUBLIC_URL || 'https://api.codestream.com',
39+
40+
// environment, please use this configuration value sparingly, really anything that depends
41+
// on environment should have its own environment variable instead
42+
environment: process.env.CS_API_ENVIRONMENT || 'prod'
3943
};

api_server/config/asana.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// asana integration configuration
2+
3+
'use strict';
4+
5+
module.exports = {
6+
appClientId: process.env.CS_API_ASANA_CLIENT_ID,
7+
appClientSecret: process.env.CS_API_ASANA_CLIENT_SECRET
8+
};

api_server/config/github.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// github integration configuration
2+
3+
'use strict';
4+
5+
module.exports = {
6+
appClientId: process.env.CS_API_GITHUB_CLIENT_ID,
7+
appClientSecret: process.env.CS_API_GITHUB_CLIENT_SECRET
8+
};

api_server/lib/api_server/api_server_modules.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class APIServerModules {
6969
// we're looking for a module.js file, if we find it, we'll read in the module contents
7070
const moduleJS = Path.join(moduleDirectory, 'module.js');
7171
const name = Path.basename(moduleDirectory);
72-
let module = this.instantiateModule(moduleJS, name);
72+
let module = this.instantiateModule(moduleJS, name, moduleDirectory);
7373
if (typeof module === 'string') {
7474
// really an error
7575
throw module;
@@ -80,7 +80,7 @@ class APIServerModules {
8080
}
8181

8282
// instantiate a module, as given by the module.js file found in the module directory
83-
instantiateModule (moduleJS, name) {
83+
instantiateModule (moduleJS, name, path) {
8484
// we should get a class, derived from APIServerModule
8585
let moduleClass;
8686
try {
@@ -97,7 +97,8 @@ class APIServerModules {
9797
try {
9898
module = new moduleClass({
9999
modules: this,
100-
api: this.api
100+
api: this.api,
101+
path
101102
});
102103
module.name = module.name || name;
103104
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>All set with your Asana integration!</p>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// provide service to handle asana credential authorization
2+
3+
'use strict';
4+
5+
const APIServerModule = require(process.env.CS_API_TOP + '/lib/api_server/api_server_module.js');
6+
const fetch = require('node-fetch');
7+
const FS = require('fs');
8+
9+
class AsanaAuth extends APIServerModule {
10+
11+
services () {
12+
return async () => {
13+
return { asanaAuth: this };
14+
};
15+
}
16+
17+
async handleAuthRedirect (options) {
18+
const { request, provider, state } = options;
19+
const { config } = request.api;
20+
const { publicApiUrl, environment } = config.api;
21+
const { appClientId } = config.asana;
22+
const { response } = request;
23+
const parameters = {
24+
client_id: appClientId,
25+
redirect_uri: `${publicApiUrl}/no-auth/provider-token/${provider}/${environment}`,
26+
response_type: 'code',
27+
state
28+
};
29+
const query = Object.keys(parameters)
30+
.map(key => `${key}=${encodeURIComponent(parameters[key])}`)
31+
.join('&');
32+
response.redirect(`https://app.asana.com/-/oauth_authorize?${query}`);
33+
request.responseHandled = true;
34+
}
35+
36+
async preProcessTokenCallback (options) {
37+
// must exchange the provided authorization code for an access token
38+
const { request, state, provider } = options;
39+
const { config } = request.api;
40+
const { publicApiUrl, environment } = config.api;
41+
const { appClientId, appClientSecret } = config.asana;
42+
const code = request.request.query.code || '';
43+
const parameters = {
44+
grant_type: 'authorization_code',
45+
client_id: appClientId,
46+
client_secret: appClientSecret,
47+
code,
48+
redirect_uri: `${publicApiUrl}/no-auth/provider-token/${provider}/${environment}`,
49+
state
50+
};
51+
const FormData = require('form-data');
52+
const form = new FormData();
53+
Object.keys(parameters).forEach(key => {
54+
form.append(key, parameters[key]/*encodeURIComponent(parameters[key])*/);
55+
});
56+
const url = 'https://app.asana.com/-/oauth_token';
57+
const response = await fetch(
58+
url,
59+
{
60+
method: 'post',
61+
body: form
62+
}
63+
);
64+
const responseData = await response.json();
65+
return {
66+
accessToken: responseData.access_token,
67+
refreshToken: responseData.refresh_token,
68+
data: responseData.data
69+
};
70+
}
71+
72+
getAfterAuthHtml () {
73+
return this.afterAuthHtml;
74+
}
75+
76+
initialize () {
77+
this.afterAuthHtml = FS.readFileSync(this.path + '/afterAuth.html', { encoding: 'utf8' });
78+
}
79+
}
80+
81+
module.exports = AsanaAuth;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = require('./asana_auth.js');
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>All set with your Github integration!</p>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// provide service to handle github credential authorization
2+
3+
'use strict';
4+
5+
const APIServerModule = require(process.env.CS_API_TOP + '/lib/api_server/api_server_module.js');
6+
const fetch = require('node-fetch');
7+
const FS = require('fs');
8+
9+
class GithubAuth extends APIServerModule {
10+
11+
services () {
12+
return async () => {
13+
return { githubAuth: this };
14+
};
15+
}
16+
17+
async handleAuthRedirect (options) {
18+
const { request, provider, state } = options;
19+
const { config } = request.api;
20+
const { publicApiUrl, environment } = config.api;
21+
const { appClientId } = config.github;
22+
const { response } = request;
23+
const parameters = {
24+
client_id: appClientId,
25+
redirect_uri: `${publicApiUrl}/no-auth/provider-token/${provider}/${environment}`,
26+
scope: 'repo,user',
27+
state
28+
};
29+
const query = Object.keys(parameters)
30+
.map(key => `${key}=${encodeURIComponent(parameters[key])}`)
31+
.join('&');
32+
response.redirect(`https://github.com/login/oauth/authorize?${query}`);
33+
request.responseHandled = true;
34+
}
35+
36+
async preProcessTokenCallback (options) {
37+
// must exchange the provided authorization code for an access token
38+
const { request, state, provider } = options;
39+
const { config } = request.api;
40+
const { publicApiUrl, environment } = config.api;
41+
const { appClientId, appClientSecret } = config.github;
42+
const code = request.request.query.code || '';
43+
const parameters = {
44+
client_id: appClientId,
45+
client_secret: appClientSecret,
46+
code,
47+
redirect_uri: `${publicApiUrl}/no-auth/provider-token/${provider}/${environment}`,
48+
state
49+
};
50+
const query = Object.keys(parameters)
51+
.map(key => `${key}=${encodeURIComponent(parameters[key])}`)
52+
.join('&');
53+
const url = `https://github.com/login/oauth/access_token?${query}`;
54+
const response = await fetch(
55+
url,
56+
{
57+
method: 'post',
58+
headers: { 'Accept': 'application/json' }
59+
}
60+
);
61+
const responseData = await response.json();
62+
return { accessToken: responseData.access_token };
63+
}
64+
65+
getAfterAuthHtml () {
66+
return this.afterAuthHtml;
67+
}
68+
69+
initialize () {
70+
this.afterAuthHtml = FS.readFileSync(this.path + '/afterAuth.html', { encoding: 'utf8' });
71+
}
72+
}
73+
74+
module.exports = GithubAuth;

0 commit comments

Comments
 (0)