Skip to content

Commit d8ca013

Browse files
authored
env-add-with-partner-portal-url (#665)
* env-add-with-partner-portal-url * CF adjustments
1 parent 45d1ed0 commit d8ca013

File tree

16 files changed

+165
-122
lines changed

16 files changed

+165
-122
lines changed

Jenkinsfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pipeline {
88
MPKIT_EMAIL = "[email protected]"
99
MPKIT_URL = "https://qa-17263.staging.oregon.platform-os.com"
1010
POS_PORTAL_PASSWORD = credentials('POS_PORTAL_PASSWORD')
11+
CI = 'true'
1112
}
1213

1314
stages {

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ To authenticate, you'll need your [**Partner Portal**](https://partners.platform
2828

2929
To add an environment to your configuration file, use the `env add` command and authenticate with your **Partner Portal** credentials:
3030

31-
pos-cli env add [environment] --url [your application url]
31+
pos-cli env add [environment] --url [your application url] [optional: --partner-portal-url]
3232

33-
Example: `pos-cli env add staging --url https://example.com`
33+
Examples:
34+
35+
pos-cli env add staging --url https://example.com
36+
pos-cli env add staging --url https://example.com --partner-portal-url https://portal.private-stack.online
3437

3538
The configuration for your environments is stored in the `.pos` file.
3639

bin/pos-cli-deploy.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ program
3030
MARKETPLACE_EMAIL: authData.email,
3131
MARKETPLACE_TOKEN: authData.token,
3232
MARKETPLACE_URL: authData.url,
33+
PARTNER_PORTAL_HOST: authData.partner_portal_url,
3334
MARKETPLACE_ENV: environment,
3435
CI: process.env.CI === 'true',
3536
// TODO: Get rid off global system env, make it normal argument to function.

bin/pos-cli-env-add.js

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,29 @@
11
#!/usr/bin/env node
22

33
const { program } = require('commander');
4+
const ServerError = require('../lib//ServerError');
45
const logger = require('../lib/logger');
5-
const validate = require('../lib/validators');
6-
const Portal = require('../lib/portal');
7-
const waitForStatus = require('../lib/data/waitForStatus');
8-
const { readPassword } = require('../lib/utils/password');
9-
const { storeEnvironment, deviceAuthorizationFlow } = require('../lib/environments');
10-
const ServerError = require('../lib/ServerError');
11-
12-
const saveToken = (settings, token) => {
13-
storeEnvironment(Object.assign(settings, { token: token }));
14-
logger.Success(`Environment ${settings.url} as ${settings.environment} has been added successfuly.`);
15-
};
16-
17-
const help = () => {
18-
program.outputHelp();
19-
process.exit(1);
20-
}
21-
22-
const checkParams = params => {
23-
// validate.existence({ argumentValue: params.email, argumentName: 'email', fail: help });
24-
if (params.email) validate.email(params.email);
25-
26-
validate.existence({ argumentValue: program.args[0], argumentName: 'environment', fail: help });
27-
28-
validate.existence({ argumentValue: params.url, argumentName: 'URL', fail: help });
29-
if (params.url.slice(-1) != '/') {
30-
params.url = params.url + '/';
31-
}
32-
validate.url(params.url);
33-
};
34-
35-
36-
const login = async (email, password, url) => {
37-
return Portal.login(email, password, url)
38-
.then(response => {
39-
if (response) return Promise.resolve(response[0].token);
40-
})
41-
}
6+
const addEnv = require('../lib/envs/add')
427

8+
program.showHelpAfterError();
439
program
4410
.name('pos-cli env add')
45-
.arguments('[environment]', 'name of environment. Example: staging')
11+
.arguments('<environment>', 'name of environment. Example: staging')
4612
.option('--email <email>', 'Partner Portal account email. Example: [email protected]')
47-
.option('--url <url>', 'marketplace url. Example: https://example.com')
13+
.requiredOption('--url <url>', 'marketplace url. Example: https://example.com')
14+
.option('--partner-portal-url <partnerPortalUrl>', 'Partner Partner URL', 'https://partners.platformos.com')
4815
.option(
4916
'--token <token>',
5017
'if you have a token you can add it directly to pos-cli configuration without connecting to portal'
5118
)
5219
.action(async (environment, params) => {
5320
try {
54-
checkParams(params);
55-
const settings = { url: params.url, environment: environment, email: params.email };
56-
57-
if (params.token) {
58-
token = params.token;
59-
} else if (!params.email){
60-
token = await deviceAuthorizationFlow(params.url);
61-
} else {
62-
logger.Info(
63-
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.HOST}/me/permissions`,
64-
{ hideTimestamp: true }
65-
);
66-
67-
const password = await readPassword();
68-
logger.Info(`Asking ${Portal.HOST} for access token...`);
69-
70-
token = await login(params.email, password, params.url);
71-
}
72-
73-
if (token) saveToken(settings, token);
21+
await addEnv(environment, params);
7422
} catch (e) {
7523
if (ServerError.isNetworkError(e))
7624
ServerError.handler(e)
7725
else
78-
logger.Error('Error');
79-
process.exit(1);
26+
logger.Error(e);
8027
}
8128
});
8229

bin/pos-cli-env-refresh-token.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ program
3030
token = await deviceAuthorizationFlow(authData.url);
3131
} else {
3232
logger.Info(
33-
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.HOST}/me/permissions`,
33+
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.url()}/me/permissions`,
3434
{ hideTimestamp: true }
3535
);
3636

3737
const password = await readPassword();
38-
logger.Info(`Asking ${Portal.HOST} for access token...`);
38+
logger.Info(`Asking ${Portal.url()} for access token...`);
3939

4040
token = await login(authData.email, password, authData.url);
4141
}

lib/environments.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ const waitForStatus = require('../lib/data/waitForStatus');
77
// importing ESM modules in CommonJS project
88
let open;
99
const initializeEsmModules = async () => {
10+
if (process.env['CI']) open = console.log
11+
1012
if(!open) {
1113
await import('open').then(imported => open = imported.default);
1214
}
13-
1415
return true;
1516
}
1617

@@ -21,7 +22,8 @@ const storeEnvironment = settings => {
2122
[settings.environment]: {
2223
url: settings.url,
2324
token: settings.token,
24-
email: settings.email
25+
email: settings.email,
26+
partner_portal_url: settings.partner_portal_url
2527
}
2628
};
2729

@@ -66,12 +68,13 @@ const deviceAuthorizationFlow = async (instanceUrl) => {
6668
const deviceAuthorizationResponse = await Portal.requestDeviceAuthorization(instanceDomain);
6769
logger.Debug('deviceAuthorizationResponse', deviceAuthorizationResponse);
6870

69-
const deviceAuthorization = JSON.parse(deviceAuthorizationResponse);
71+
const deviceAuthorization = deviceAuthorizationResponse;
7072
const verificationUrl = deviceAuthorization['verification_uri_complete'];
7173
const deviceCode = deviceAuthorization['device_code']
7274
const interval = (deviceAuthorization['interval'] || 5) * 1000;
7375

7476
await initializeEsmModules();
77+
logger.Debug('verificationUrl', verificationUrl);
7578
await open(verificationUrl);
7679

7780
const accessToken = await waitForAccessToken(deviceCode, interval);

lib/envs/add.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const Portal = require('../portal');
2+
const logger = require('../logger');
3+
const validate = require('../validators');
4+
const { storeEnvironment, deviceAuthorizationFlow } = require('../environments');
5+
const waitForStatus = require('../data/waitForStatus');
6+
const { readPassword } = require('../utils/password');
7+
8+
const checkParams = (env, params) => {
9+
if (params.email) validate.email(params.email);
10+
11+
if (params.url.slice(-1) != '/') {
12+
params.url = params.url + '/';
13+
}
14+
validate.url(params.url);
15+
};
16+
17+
const saveToken = (settings, token) => {
18+
storeEnvironment(Object.assign(settings, { token: token }));
19+
logger.Success(`Environment ${settings.url} as ${settings.environment} has been added successfuly.`);
20+
};
21+
22+
const login = async (email, password, url) => {
23+
return Portal.login(email, password, url)
24+
.then(response => {
25+
if (response) return Promise.resolve(response[0].token);
26+
})
27+
}
28+
29+
const addEnv = async (environment, params) => {
30+
checkParams(environment, params);
31+
if (params.partnerPortalUrl) {
32+
process.env['PARTNER_PORTAL_HOST'] ||= params.partnerPortalUrl
33+
}
34+
35+
const settings = {
36+
url: params.url,
37+
environment: environment,
38+
email: params.email,
39+
partner_portal_url: process.env['PARTNER_PORTAL_HOST']
40+
};
41+
42+
if (params.token) {
43+
token = params.token;
44+
} else if (!params.email){
45+
token = await deviceAuthorizationFlow(params.url);
46+
} else {
47+
logger.Info(
48+
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.url()}/me/permissions`,
49+
{ hideTimestamp: true }
50+
);
51+
52+
const password = await readPassword();
53+
logger.Info(`Asking ${Portal.url()} for access token...`);
54+
55+
token = await login(params.email, password, params.url);
56+
}
57+
58+
if (token) saveToken(settings, token);
59+
}
60+
61+
module.exports = addEnv;

lib/modules.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const glob = require('fast-glob');
44

55
const files = require('./files');
66
const logger = require('./logger');
7-
const portal = require('./portal');
7+
const Portal = require('./portal');
88
const prepareArchive = require('./prepareArchive');
99
const presignUrl = require('./presignUrl').presignUrlForPortal;
1010
const uploadFile = require('./s3UploadFile').uploadFile;
@@ -68,21 +68,21 @@ const uploadArchive = async (token) => {
6868
};
6969

7070
const createVersion = async (token, accessUrl, moduleVersionName) => {
71-
const version = await portal.createVersion(token, accessUrl, moduleVersionName, moduleId)
71+
const version = await Portal.createVersion(token, accessUrl, moduleVersionName, moduleId)
7272
return version.id;
7373
};
7474

7575
const waitForPublishing = async (token, moduleVersionId) => {
7676
try {
77-
await waitForStatus(() => portal.moduleVersionStatus(token, moduleId, moduleVersionId), 'pending', 'accepted');
77+
await waitForStatus(() => Portal.moduleVersionStatus(token, moduleId, moduleVersionId), 'pending', 'accepted');
7878
logger.Success('Module uploaded.');
7979
} catch(e) {
8080
throw new Error('Module not uploaded. Check email for errors.');
8181
}
8282
};
8383

8484
const getModule = async (token, name) => {
85-
const modules = await portal.findModules(token, name);
85+
const modules = await Portal.findModules(token, name);
8686
const module = modules[0];
8787
if (module){
8888
return module;
@@ -98,14 +98,14 @@ const getToken = async (params) => {
9898
} else {
9999
password = await readPassword();
100100
}
101-
logger.Info(`Asking ${portal.HOST} for access token...`);
101+
logger.Info(`Asking ${Portal.url()} for access token...`);
102102
const token = await portalAuthToken(params.email, password);
103103
return token;
104104
}
105105

106106
const portalAuthToken = async (email, password) => {
107107
try {
108-
const token = await portal.jwtToken(email, password)
108+
const token = await Portal.jwtToken(email, password)
109109
return token.auth_token;
110110
} catch (e) {
111111
if (ServerError.isNetworkError(e))

lib/portal.js

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,78 @@
11
const { apiRequest } = require('./apiRequest');
22
const logger = require('./logger');
33

4-
const HOST = process.env.PARTNER_PORTAL_HOST || 'https://partners.platformos.com';
5-
64
const Portal = {
5+
url: () => { return process.env.PARTNER_PORTAL_HOST || 'https://partners.platformos.com' },
6+
77
login: (email, password, url) => {
8-
logger.Debug('Portal.login ' + email + ' to ' + HOST);
8+
logger.Debug('Portal.login ' + email + ' to ' + Portal.url());
99

1010
return apiRequest({
11-
uri: `${HOST}/api/user_tokens`,
11+
uri: `${Portal.url()}/api/user_tokens`,
1212
headers: { UserAuthorization: `${email}:${password}`, InstanceDomain: url },
1313
});
1414
},
1515
jwtToken: (email, password) => {
1616
return apiRequest({
1717
method: 'POST',
18-
uri: `${HOST}/api/authenticate`,
18+
uri: `${Portal.url()}/api/authenticate`,
1919
formData: { email: email, password: password },
2020
});
2121
},
2222
findModules: (token, name) => {
2323
return apiRequest({
2424
method: 'GET',
25-
uri: `${HOST}/api/pos_modules/?modules=${name}`,
25+
uri: `${Portal.url()}/api/pos_modules/?modules=${name}`,
2626
headers: { Authorization: `Bearer ${token}` },
2727
});
2828
},
2929
moduleVersions(modules) {
3030
return apiRequest({
31-
uri: `${HOST}/api/pos_modules?modules=${modules.join(',')}`,
31+
uri: `${Portal.url()}/api/pos_modules?modules=${modules.join(',')}`,
3232
});
3333
},
3434
createVersion: (token, url, name, posModuleId) => {
3535
return apiRequest({
3636
method: 'POST',
37-
uri: `${HOST}/api/pos_modules/${posModuleId}/pos_module_versions`,
37+
uri: `${Portal.url()}/api/pos_modules/${posModuleId}/pos_module_versions`,
3838
body: { pos_module_version: { archive: url, name: name } },
3939
headers: { Authorization: `Bearer ${token}` },
4040
});
4141
},
4242
moduleVersionStatus: (token, posModuleId, moduleVersionId) => {
4343
return apiRequest({
4444
method: 'GET',
45-
uri: `${HOST}/api/pos_modules/${posModuleId}/pos_module_versions/${moduleVersionId}`,
45+
uri: `${Portal.url()}/api/pos_modules/${posModuleId}/pos_module_versions/${moduleVersionId}`,
4646
headers: { Authorization: `Bearer ${token}` },
4747
});
4848
},
4949
moduleVersionsSearch: (moduleVersionName) => {
5050
return apiRequest({
5151
method: 'GET',
52-
uri: `${HOST}/api/pos_module_version?name=${moduleVersionName}`
52+
uri: `${Portal.url()}/api/pos_module_version?name=${moduleVersionName}`
5353
});
5454
},
5555
requestDeviceAuthorization: (instanceDomain) => {
5656
return apiRequest({
5757
method: 'POST',
58-
uri: `${HOST}/oauth/authorize_device`,
58+
uri: `${Portal.url()}/oauth/authorize_device`,
5959
formData: {
6060
domain: instanceDomain
6161
},
62-
json: false
62+
json: true
6363
});
6464
},
6565
fetchDeviceAccessToken: (deviceCode) => {
6666
return apiRequest({
6767
method: 'POST',
68-
uri: `${HOST}/oauth/device_token`,
68+
uri: `${Portal.url()}/oauth/device_token`,
6969
formData: {
7070
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
7171
device_code: deviceCode
7272
},
7373
json: true
7474
});
75-
},
76-
77-
HOST: HOST
75+
}
7876
};
7977

8078
module.exports = Portal;

0 commit comments

Comments
 (0)