Skip to content

Commit

Permalink
env-add-with-partner-portal-url
Browse files Browse the repository at this point in the history
  • Loading branch information
godot committed Jan 7, 2025
1 parent 45d1ed0 commit bed6fd2
Show file tree
Hide file tree
Showing 15 changed files with 162 additions and 120 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pipeline {
MPKIT_EMAIL = "[email protected]"
MPKIT_URL = "https://qa-17263.staging.oregon.platform-os.com"
POS_PORTAL_PASSWORD = credentials('POS_PORTAL_PASSWORD')
CI = 'true'
}

stages {
Expand Down
1 change: 1 addition & 0 deletions bin/pos-cli-deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ program
MARKETPLACE_EMAIL: authData.email,
MARKETPLACE_TOKEN: authData.token,
MARKETPLACE_URL: authData.url,
PARTNER_PORTAL_HOST: authData.partner_portal_url,
MARKETPLACE_ENV: environment,
CI: process.env.CI === 'true',
// TODO: Get rid off global system env, make it normal argument to function.
Expand Down
70 changes: 9 additions & 61 deletions bin/pos-cli-env-add.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,31 @@
#!/usr/bin/env node

const { program } = require('commander');
const ServerError = require('../lib//ServerError');
const logger = require('../lib/logger');
const validate = require('../lib/validators');
const Portal = require('../lib/portal');
const waitForStatus = require('../lib/data/waitForStatus');
const { readPassword } = require('../lib/utils/password');
const { storeEnvironment, deviceAuthorizationFlow } = require('../lib/environments');
const ServerError = require('../lib/ServerError');

const saveToken = (settings, token) => {
storeEnvironment(Object.assign(settings, { token: token }));
logger.Success(`Environment ${settings.url} as ${settings.environment} has been added successfuly.`);
};

const help = () => {
program.outputHelp();
process.exit(1);
}

const checkParams = params => {
// validate.existence({ argumentValue: params.email, argumentName: 'email', fail: help });
if (params.email) validate.email(params.email);

validate.existence({ argumentValue: program.args[0], argumentName: 'environment', fail: help });

validate.existence({ argumentValue: params.url, argumentName: 'URL', fail: help });
if (params.url.slice(-1) != '/') {
params.url = params.url + '/';
}
validate.url(params.url);
};


const login = async (email, password, url) => {
return Portal.login(email, password, url)
.then(response => {
if (response) return Promise.resolve(response[0].token);
})
}
const addEnv = require('../lib/env-add/main')

program.showHelpAfterError();
program
.name('pos-cli env add')
.arguments('[environment]', 'name of environment. Example: staging')
.arguments('<environment>', 'name of environment. Example: staging')
.option('--email <email>', 'Partner Portal account email. Example: [email protected]')
.option('--url <url>', 'marketplace url. Example: https://example.com')
.requiredOption('--url <url>', 'marketplace url. Example: https://example.com')
.option('--partner-portal-url <partnerPortalUrl>', 'Partner Partner URL', 'https://partners.platformos.com')
.option(
'--token <token>',
'if you have a token you can add it directly to pos-cli configuration without connecting to portal'
)
.action(async (environment, params) => {
try {
checkParams(params);
const settings = { url: params.url, environment: environment, email: params.email };

if (params.token) {
token = params.token;
} else if (!params.email){
token = await deviceAuthorizationFlow(params.url);
} else {
logger.Info(
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.HOST}/me/permissions`,
{ hideTimestamp: true }
);

const password = await readPassword();
logger.Info(`Asking ${Portal.HOST} for access token...`);

token = await login(params.email, password, params.url);
}

if (token) saveToken(settings, token);
await addEnv(environment, params);
} catch (e) {
if (ServerError.isNetworkError(e))
ServerError.handler(e)
else
logger.Error('Error');
process.exit(1);
logger.Error(e);
}
process.exit(1);
});

program.parse(process.argv);
4 changes: 2 additions & 2 deletions bin/pos-cli-env-refresh-token.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ program
token = await deviceAuthorizationFlow(authData.url);
} else {
logger.Info(
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.HOST}/me/permissions`,
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.url()}/me/permissions`,
{ hideTimestamp: true }
);

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

token = await login(authData.email, password, authData.url);
}
Expand Down
61 changes: 61 additions & 0 deletions lib/env-add/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const Portal = require('../portal');
const logger = require('../logger');
const validate = require('../validators');
const { storeEnvironment, deviceAuthorizationFlow } = require('../environments');
const waitForStatus = require('../data/waitForStatus');
const { readPassword } = require('../utils/password');

const checkParams = (env, params) => {
if (params.email) validate.email(params.email);

if (params.url.slice(-1) != '/') {
params.url = params.url + '/';
}
validate.url(params.url);
};

const saveToken = (settings, token) => {
storeEnvironment(Object.assign(settings, { token: token }));
logger.Success(`Environment ${settings.url} as ${settings.environment} has been added successfuly.`);
};

const login = async (email, password, url) => {
return Portal.login(email, password, url)
.then(response => {
if (response) return Promise.resolve(response[0].token);
})
}

const addEnv = async (environment, params) => {
checkParams(environment, params);
if (params.partnerPortalUrl) {
process.env['PARTNER_PORTAL_HOST'] ||= params.partnerPortalUrl
}

const settings = {
url: params.url,
environment: environment,
email: params.email,
partner_portal_url: process.env['PARTNER_PORTAL_HOST']
};

if (params.token) {
token = params.token;
} else if (!params.email){
token = await deviceAuthorizationFlow(params.url);
} else {
logger.Info(
`Please make sure that you have a permission to deploy. \n You can verify it here: ${Portal.url()}/me/permissions`,
{ hideTimestamp: true }
);

const password = await readPassword();
logger.Info(`Asking ${Portal.url()} for access token...`);

token = await login(params.email, password, params.url);
}

if (token) saveToken(settings, token);
}

module.exports = addEnv;
8 changes: 5 additions & 3 deletions lib/environments.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const initializeEsmModules = async () => {
if(!open) {
await import('open').then(imported => open = imported.default);
}

if (process.env['CI']) open = console.log
return true;
}

Expand All @@ -21,7 +21,8 @@ const storeEnvironment = settings => {
[settings.environment]: {
url: settings.url,
token: settings.token,
email: settings.email
email: settings.email,
partner_portal_url: settings.partner_portal_url
}
};

Expand Down Expand Up @@ -66,12 +67,13 @@ const deviceAuthorizationFlow = async (instanceUrl) => {
const deviceAuthorizationResponse = await Portal.requestDeviceAuthorization(instanceDomain);
logger.Debug('deviceAuthorizationResponse', deviceAuthorizationResponse);

const deviceAuthorization = JSON.parse(deviceAuthorizationResponse);
const deviceAuthorization = deviceAuthorizationResponse;
const verificationUrl = deviceAuthorization['verification_uri_complete'];
const deviceCode = deviceAuthorization['device_code']
const interval = (deviceAuthorization['interval'] || 5) * 1000;

await initializeEsmModules();
logger.Debug('verificationUrl', verificationUrl);
await open(verificationUrl);

const accessToken = await waitForAccessToken(deviceCode, interval);
Expand Down
12 changes: 6 additions & 6 deletions lib/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const glob = require('fast-glob');

const files = require('./files');
const logger = require('./logger');
const portal = require('./portal');
const Portal = require('./portal');
const prepareArchive = require('./prepareArchive');
const presignUrl = require('./presignUrl').presignUrlForPortal;
const uploadFile = require('./s3UploadFile').uploadFile;
Expand Down Expand Up @@ -68,21 +68,21 @@ const uploadArchive = async (token) => {
};

const createVersion = async (token, accessUrl, moduleVersionName) => {
const version = await portal.createVersion(token, accessUrl, moduleVersionName, moduleId)
const version = await Portal.createVersion(token, accessUrl, moduleVersionName, moduleId)
return version.id;
};

const waitForPublishing = async (token, moduleVersionId) => {
try {
await waitForStatus(() => portal.moduleVersionStatus(token, moduleId, moduleVersionId), 'pending', 'accepted');
await waitForStatus(() => Portal.moduleVersionStatus(token, moduleId, moduleVersionId), 'pending', 'accepted');
logger.Success('Module uploaded.');
} catch(e) {
throw new Error('Module not uploaded. Check email for errors.');
}
};

const getModule = async (token, name) => {
const modules = await portal.findModules(token, name);
const modules = await Portal.findModules(token, name);
const module = modules[0];
if (module){
return module;
Expand All @@ -98,14 +98,14 @@ const getToken = async (params) => {
} else {
password = await readPassword();
}
logger.Info(`Asking ${portal.HOST} for access token...`);
logger.Info(`Asking ${Portal.url()} for access token...`);
const token = await portalAuthToken(params.email, password);
return token;
}

const portalAuthToken = async (email, password) => {
try {
const token = await portal.jwtToken(email, password)
const token = await Portal.jwtToken(email, password)
return token.auth_token;
} catch (e) {
if (ServerError.isNetworkError(e))
Expand Down
30 changes: 14 additions & 16 deletions lib/portal.js
Original file line number Diff line number Diff line change
@@ -1,80 +1,78 @@
const { apiRequest } = require('./apiRequest');
const logger = require('./logger');

const HOST = process.env.PARTNER_PORTAL_HOST || 'https://partners.platformos.com';

const Portal = {
url: () => { return process.env.PARTNER_PORTAL_HOST || 'https://partners.platformos.com' },

login: (email, password, url) => {
logger.Debug('Portal.login ' + email + ' to ' + HOST);
logger.Debug('Portal.login ' + email + ' to ' + Portal.url());

return apiRequest({
uri: `${HOST}/api/user_tokens`,
uri: `${Portal.url()}/api/user_tokens`,
headers: { UserAuthorization: `${email}:${password}`, InstanceDomain: url },
});
},
jwtToken: (email, password) => {
return apiRequest({
method: 'POST',
uri: `${HOST}/api/authenticate`,
uri: `${Portal.url()}/api/authenticate`,
formData: { email: email, password: password },
});
},
findModules: (token, name) => {
return apiRequest({
method: 'GET',
uri: `${HOST}/api/pos_modules/?modules=${name}`,
uri: `${Portal.url()}/api/pos_modules/?modules=${name}`,
headers: { Authorization: `Bearer ${token}` },
});
},
moduleVersions(modules) {
return apiRequest({
uri: `${HOST}/api/pos_modules?modules=${modules.join(',')}`,
uri: `${Portal.url()}/api/pos_modules?modules=${modules.join(',')}`,
});
},
createVersion: (token, url, name, posModuleId) => {
return apiRequest({
method: 'POST',
uri: `${HOST}/api/pos_modules/${posModuleId}/pos_module_versions`,
uri: `${Portal.url()}/api/pos_modules/${posModuleId}/pos_module_versions`,
body: { pos_module_version: { archive: url, name: name } },
headers: { Authorization: `Bearer ${token}` },
});
},
moduleVersionStatus: (token, posModuleId, moduleVersionId) => {
return apiRequest({
method: 'GET',
uri: `${HOST}/api/pos_modules/${posModuleId}/pos_module_versions/${moduleVersionId}`,
uri: `${Portal.url()}/api/pos_modules/${posModuleId}/pos_module_versions/${moduleVersionId}`,
headers: { Authorization: `Bearer ${token}` },
});
},
moduleVersionsSearch: (moduleVersionName) => {
return apiRequest({
method: 'GET',
uri: `${HOST}/api/pos_module_version?name=${moduleVersionName}`
uri: `${Portal.url()}/api/pos_module_version?name=${moduleVersionName}`
});
},
requestDeviceAuthorization: (instanceDomain) => {
return apiRequest({
method: 'POST',
uri: `${HOST}/oauth/authorize_device`,
uri: `${Portal.url()}/oauth/authorize_device`,
formData: {
domain: instanceDomain
},
json: false
json: true
});
},
fetchDeviceAccessToken: (deviceCode) => {
return apiRequest({
method: 'POST',
uri: `${HOST}/oauth/device_token`,
uri: `${Portal.url()}/oauth/device_token`,
formData: {
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
device_code: deviceCode
},
json: true
});
},

HOST: HOST
}
};

module.exports = Portal;
13 changes: 6 additions & 7 deletions lib/presignUrl.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const fs = require('fs'),
url = require('url'),
request = require('request-promise'),
mime = require('mime');
const logger = require('./logger');
url = require('url'),
request = require('request-promise'),
mime = require('mime'),
logger = require('./logger'),
Portal = require('./portal');

const Portal = require('./portal');
const deployServiceUrl = () => process.env.DEPLOY_SERVICE_URL || url.resolve(process.env.MARKETPLACE_URL, '/api/private/urls');

const presignUrl = (s3FileName, fileName) => {
Expand Down Expand Up @@ -48,8 +48,7 @@ const presignDirectory = path => {
};

const presignUrlForPortal = (token, moduleName, filename) => {
const HOST = process.env.PARTNER_PORTAL_HOST || 'https://partners.platformos.com';
const serviceUrl = `${HOST}/api/pos_modules/${moduleName}/presign_url`;
const serviceUrl = `${Portal.url()}/api/pos_modules/${moduleName}/presign_url`;
logger.Debug(token);
return request
.get({
Expand Down
Loading

0 comments on commit bed6fd2

Please sign in to comment.