@extrahorizon/exh-cli 1.8.2-dev-74-994b4dc → 1.8.2-feat-76-eba7a78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/tasks/sync.js +23 -4
- package/build/commands/tasks/taskConfig.d.ts +4 -0
- package/build/commands/tasks/taskConfig.js +4 -0
- package/build/commands/tasks/util.d.ts +9 -0
- package/build/commands/tasks/util.js +98 -1
- package/build/repositories/auth.d.ts +1 -0
- package/build/repositories/auth.js +6 -1
- package/build/repositories/functions.js +1 -1
- package/build/repositories/user.d.ts +9 -0
- package/build/repositories/user.js +38 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ const fs = require("fs/promises");
|
|
|
5
5
|
const chalk = require("chalk");
|
|
6
6
|
const constants_1 = require("../../constants");
|
|
7
7
|
const util_1 = require("../../helpers/util");
|
|
8
|
+
const authRepository = require("../../repositories/auth");
|
|
8
9
|
const functionRepository = require("../../repositories/functions");
|
|
9
10
|
const taskConfig_1 = require("./taskConfig");
|
|
10
11
|
const util_2 = require("./util");
|
|
@@ -96,13 +97,31 @@ async function syncSingleTask(sdk, config) {
|
|
|
96
97
|
if (config.memoryLimit) {
|
|
97
98
|
request.memoryLimit = config.memoryLimit;
|
|
98
99
|
}
|
|
99
|
-
if (config.environment) {
|
|
100
|
-
request.environmentVariables =
|
|
101
|
-
Object.entries(config.environment).reduce((prev, curr) => ({ ...prev, [curr[0]]: { value: curr[1] } }), {});
|
|
102
|
-
}
|
|
103
100
|
if (config.retryPolicy) {
|
|
104
101
|
request.retryPolicy = config.retryPolicy;
|
|
105
102
|
}
|
|
103
|
+
if (config.executionCredentials) {
|
|
104
|
+
const credentials = await (0, util_2.syncFunctionUser)(sdk, {
|
|
105
|
+
taskName: config.name,
|
|
106
|
+
targetEmail: config.executionCredentials.email,
|
|
107
|
+
targetPermissions: config.executionCredentials.permissions,
|
|
108
|
+
});
|
|
109
|
+
config.environment = {
|
|
110
|
+
...config.environment,
|
|
111
|
+
API_HOST: authRepository.getHost(sdk),
|
|
112
|
+
API_OAUTH_CONSUMER_KEY: process.env.API_OAUTH_CONSUMER_KEY,
|
|
113
|
+
API_OAUTH_CONSUMER_SECRET: process.env.API_OAUTH_CONSUMER_SECRET,
|
|
114
|
+
API_OAUTH_TOKEN: credentials.token,
|
|
115
|
+
API_OAUTH_TOKEN_SECRET: credentials.tokenSecret,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (config.environment) {
|
|
119
|
+
const environmentVariables = {};
|
|
120
|
+
for (const [key, value] of Object.entries(config.environment)) {
|
|
121
|
+
environmentVariables[key] = { value };
|
|
122
|
+
}
|
|
123
|
+
request.environmentVariables = environmentVariables;
|
|
124
|
+
}
|
|
106
125
|
if (myFunction === undefined) {
|
|
107
126
|
await functionRepository.create(sdk, request);
|
|
108
127
|
console.log(chalk.green('Successfully created task', config.name));
|
|
@@ -17,6 +17,10 @@ export interface TaskConfig {
|
|
|
17
17
|
enabled: boolean;
|
|
18
18
|
errorsToRetry: string[];
|
|
19
19
|
};
|
|
20
|
+
executionCredentials?: {
|
|
21
|
+
email?: string;
|
|
22
|
+
permissions: string[];
|
|
23
|
+
};
|
|
20
24
|
}
|
|
21
25
|
export declare function assertExecutionPermission(mode: string): asserts mode is permissionModes | undefined;
|
|
22
26
|
export declare function validateConfig(config: TaskConfig): Promise<boolean>;
|
|
@@ -26,6 +26,10 @@ const taskConfigSchema = Joi.object({
|
|
|
26
26
|
}),
|
|
27
27
|
environment: Joi.object().pattern(/.*/, Joi.string()),
|
|
28
28
|
executionPermission: Joi.string().valid(...Object.values(permissionModes)),
|
|
29
|
+
executionCredentials: Joi.object({
|
|
30
|
+
email: Joi.string(),
|
|
31
|
+
permissions: Joi.array().items(Joi.string()).required(),
|
|
32
|
+
}),
|
|
29
33
|
});
|
|
30
34
|
function assertExecutionPermission(mode) {
|
|
31
35
|
if (mode !== undefined && !Object.values(permissionModes).includes(mode)) {
|
|
@@ -1 +1,10 @@
|
|
|
1
|
+
import { OAuth1Client } from '@extrahorizon/javascript-sdk';
|
|
1
2
|
export declare function zipFileFromDirectory(path: string): Promise<string>;
|
|
3
|
+
export declare function syncFunctionUser(sdk: OAuth1Client, data: {
|
|
4
|
+
taskName: string;
|
|
5
|
+
targetEmail?: string;
|
|
6
|
+
targetPermissions: string[];
|
|
7
|
+
}): Promise<{
|
|
8
|
+
token: any;
|
|
9
|
+
tokenSecret: any;
|
|
10
|
+
}>;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.zipFileFromDirectory = void 0;
|
|
3
|
+
exports.syncFunctionUser = exports.zipFileFromDirectory = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
const archiver = require("archiver");
|
|
7
|
+
const chalk = require("chalk");
|
|
7
8
|
const uuid_1 = require("uuid");
|
|
9
|
+
const authRepository = require("../../repositories/auth");
|
|
10
|
+
const functionRepository = require("../../repositories/functions");
|
|
11
|
+
const userRepository = require("../../repositories/user");
|
|
8
12
|
async function zipFileFromDirectory(path) {
|
|
9
13
|
return new Promise((res, rej) => {
|
|
10
14
|
const tmpPath = `${(0, os_1.tmpdir)()}/${(0, uuid_1.v4)()}`;
|
|
@@ -25,3 +29,96 @@ async function zipFileFromDirectory(path) {
|
|
|
25
29
|
});
|
|
26
30
|
}
|
|
27
31
|
exports.zipFileFromDirectory = zipFileFromDirectory;
|
|
32
|
+
async function syncFunctionUser(sdk, data) {
|
|
33
|
+
const { taskName, targetEmail, targetPermissions } = data;
|
|
34
|
+
const email = targetEmail || `exh.tasks+${taskName}@extrahorizon.com`;
|
|
35
|
+
validateEmail(email);
|
|
36
|
+
const password = `0Oo-${(0, uuid_1.v4)()}`;
|
|
37
|
+
const roleName = `exh.tasks.${taskName}`;
|
|
38
|
+
const role = await syncRoleWithPermissions(sdk, taskName, roleName, targetPermissions);
|
|
39
|
+
let user = await userRepository.findUserByEmail(sdk, email);
|
|
40
|
+
if (!user) {
|
|
41
|
+
console.log(chalk.white('⚙️ Creating a user for the task'));
|
|
42
|
+
const isEmailAvailable = await userRepository.isEmailAvailable(sdk, email);
|
|
43
|
+
if (!isEmailAvailable) {
|
|
44
|
+
throw new Error('❌ The user could not be created as the email address is already in use');
|
|
45
|
+
}
|
|
46
|
+
const registerUserData = {
|
|
47
|
+
firstName: `${taskName}`,
|
|
48
|
+
lastName: 'exh.tasks',
|
|
49
|
+
email,
|
|
50
|
+
password,
|
|
51
|
+
phoneNumber: '0000000000',
|
|
52
|
+
language: 'EN',
|
|
53
|
+
};
|
|
54
|
+
user = await userRepository.createUser(sdk, registerUserData);
|
|
55
|
+
console.log(chalk.green('✅ Successfully created a user for task'));
|
|
56
|
+
await assignRoleToUser(sdk, user.id, role.id);
|
|
57
|
+
return await createOAuth1Tokens(sdk, email, password);
|
|
58
|
+
}
|
|
59
|
+
console.log(chalk.white('⚙️ Checking for the existing users credentials'));
|
|
60
|
+
const currentFunction = await functionRepository.findByName(sdk, taskName);
|
|
61
|
+
const hasExistingCredentials = (currentFunction?.environmentVariables?.API_HOST?.value &&
|
|
62
|
+
currentFunction?.environmentVariables?.API_OAUTH_TOKEN_SECRET?.value &&
|
|
63
|
+
currentFunction?.environmentVariables?.API_OAUTH_TOKEN?.value &&
|
|
64
|
+
currentFunction?.environmentVariables?.API_OAUTH_CONSUMER_KEY?.value &&
|
|
65
|
+
currentFunction?.environmentVariables?.API_OAUTH_CONSUMER_SECRET?.value);
|
|
66
|
+
if (!hasExistingCredentials) {
|
|
67
|
+
throw new Error('❌ No credentials were found for the existing user');
|
|
68
|
+
}
|
|
69
|
+
const userRole = user.roles.find(({ name }) => name === roleName);
|
|
70
|
+
if (!userRole) {
|
|
71
|
+
await assignRoleToUser(sdk, user.id, role.id);
|
|
72
|
+
}
|
|
73
|
+
console.log(chalk.green('✅ Using existing credentials for the user'));
|
|
74
|
+
return {
|
|
75
|
+
token: currentFunction.environmentVariables.API_OAUTH_TOKEN.value,
|
|
76
|
+
tokenSecret: currentFunction.environmentVariables.API_OAUTH_TOKEN_SECRET.value,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
exports.syncFunctionUser = syncFunctionUser;
|
|
80
|
+
async function syncRoleWithPermissions(sdk, taskName, roleName, targetPermissions) {
|
|
81
|
+
console.log(chalk.white('⚙️ Checking if the role exists'));
|
|
82
|
+
let role = await userRepository.findGlobalRoleByName(sdk, roleName);
|
|
83
|
+
if (!role) {
|
|
84
|
+
console.log(chalk.white('⚙️ Role does not exist, creating a new role'));
|
|
85
|
+
const roleDescription = `A role created by the CLI for the execution of the task ${taskName}`;
|
|
86
|
+
role = await userRepository.createGlobalRole(sdk, roleName, roleDescription);
|
|
87
|
+
console.log(chalk.white('⚙️ Assigning permissions to the role'));
|
|
88
|
+
await userRepository.addPermissionsToGlobalRole(sdk, roleName, targetPermissions);
|
|
89
|
+
console.log(chalk.green('✅ Successfully assigned permissions to the role'));
|
|
90
|
+
return role;
|
|
91
|
+
}
|
|
92
|
+
const currentPermissions = role.permissions?.flatMap(permission => permission.name) || [];
|
|
93
|
+
const permissionsToAdd = targetPermissions.filter(targetPermission => !currentPermissions.includes(targetPermission));
|
|
94
|
+
const permissionsToRemove = currentPermissions.filter(currentPermission => !targetPermissions.includes(currentPermission));
|
|
95
|
+
if (permissionsToAdd.length > 0) {
|
|
96
|
+
console.log(chalk.white('⚙️ Adding missing permissions to the role'));
|
|
97
|
+
await userRepository.addPermissionsToGlobalRole(sdk, roleName, permissionsToAdd);
|
|
98
|
+
console.log(chalk.green('✅ Successfully added missing permissions to the role'));
|
|
99
|
+
}
|
|
100
|
+
if (permissionsToRemove.length > 0) {
|
|
101
|
+
console.log(chalk.white('⚙️ Removing excess permissions from the role'));
|
|
102
|
+
await userRepository.removePermissionsFromGlobalRole(sdk, roleName, permissionsToRemove);
|
|
103
|
+
console.log(chalk.green('✅ Successfully removed excess permissions from the role'));
|
|
104
|
+
}
|
|
105
|
+
return role;
|
|
106
|
+
}
|
|
107
|
+
async function assignRoleToUser(sdk, userId, roleId) {
|
|
108
|
+
console.log(chalk.white('⚙️ Assigning the role to the user'));
|
|
109
|
+
await userRepository.addGlobalRoleToUser(sdk, userId, roleId);
|
|
110
|
+
console.log(chalk.green('✅ Successfully assigned the role to the user'));
|
|
111
|
+
}
|
|
112
|
+
async function createOAuth1Tokens(sdk, email, password) {
|
|
113
|
+
console.log(chalk.white('⚙️ Creating OAuth1 tokens for the user', email));
|
|
114
|
+
const response = await authRepository.createOAuth1Tokens(sdk, email, password);
|
|
115
|
+
const { token, tokenSecret } = response.data;
|
|
116
|
+
console.log(chalk.green('✅ Successfully created OAuth1 tokens for the user', email));
|
|
117
|
+
return { token, tokenSecret };
|
|
118
|
+
}
|
|
119
|
+
function validateEmail(email) {
|
|
120
|
+
const emailRegex = /.+@.+\..+/;
|
|
121
|
+
if (email.length < 3 || email.length > 256 || !emailRegex.test(email)) {
|
|
122
|
+
throw new Error('Invalid email address');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { OAuth1Client } from '@extrahorizon/javascript-sdk';
|
|
2
2
|
export declare function getHost(sdk: OAuth1Client): string;
|
|
3
|
+
export declare function createOAuth1Tokens(sdk: OAuth1Client, email: string, password: string): Promise<any>;
|
|
3
4
|
export declare function fetchMe(sdk: OAuth1Client): Promise<import("@extrahorizon/javascript-sdk").UserData>;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchMe = exports.getHost = void 0;
|
|
3
|
+
exports.fetchMe = exports.createOAuth1Tokens = exports.getHost = void 0;
|
|
4
4
|
function getHost(sdk) {
|
|
5
5
|
return sdk?.raw?.defaults?.baseURL;
|
|
6
6
|
}
|
|
7
7
|
exports.getHost = getHost;
|
|
8
|
+
async function createOAuth1Tokens(sdk, email, password) {
|
|
9
|
+
const response = await sdk.raw.post('/auth/v2/oauth1/tokens', { email, password });
|
|
10
|
+
return response.data;
|
|
11
|
+
}
|
|
12
|
+
exports.createOAuth1Tokens = createOAuth1Tokens;
|
|
8
13
|
async function fetchMe(sdk) {
|
|
9
14
|
return await sdk?.users.me();
|
|
10
15
|
}
|
|
@@ -7,7 +7,7 @@ async function find(sdk) {
|
|
|
7
7
|
}
|
|
8
8
|
exports.find = find;
|
|
9
9
|
async function findByName(sdk, name) {
|
|
10
|
-
const response = await sdk.raw.get(`/tasks/v1/functions/${name}
|
|
10
|
+
const response = await sdk.raw.get(`/tasks/v1/functions/${name}`, { customResponseKeys: ['*'] });
|
|
11
11
|
return response.data;
|
|
12
12
|
}
|
|
13
13
|
exports.findByName = findByName;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OAuth1Client, RegisterUserData } from '@extrahorizon/javascript-sdk';
|
|
2
|
+
export declare function findUserByEmail(sdk: OAuth1Client, email: string): Promise<import("@extrahorizon/javascript-sdk").UserData>;
|
|
3
|
+
export declare function isEmailAvailable(sdk: OAuth1Client, email: string): Promise<boolean>;
|
|
4
|
+
export declare function createUser(sdk: OAuth1Client, data: RegisterUserData): Promise<import("@extrahorizon/javascript-sdk").UserData>;
|
|
5
|
+
export declare function findGlobalRoleByName(sdk: OAuth1Client, name: string): Promise<import("@extrahorizon/javascript-sdk").Role>;
|
|
6
|
+
export declare function createGlobalRole(sdk: OAuth1Client, name: string, description: string): Promise<import("@extrahorizon/javascript-sdk").Role>;
|
|
7
|
+
export declare function addPermissionsToGlobalRole(sdk: OAuth1Client, name: string, permissions: string[]): Promise<import("@extrahorizon/javascript-sdk").AffectedRecords>;
|
|
8
|
+
export declare function removePermissionsFromGlobalRole(sdk: OAuth1Client, name: string, permissions: string[]): Promise<import("@extrahorizon/javascript-sdk").AffectedRecords>;
|
|
9
|
+
export declare function addGlobalRoleToUser(sdk: OAuth1Client, userId: string, roleId: string): Promise<import("@extrahorizon/javascript-sdk").AffectedRecords>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addGlobalRoleToUser = exports.removePermissionsFromGlobalRole = exports.addPermissionsToGlobalRole = exports.createGlobalRole = exports.findGlobalRoleByName = exports.createUser = exports.isEmailAvailable = exports.findUserByEmail = void 0;
|
|
4
|
+
const javascript_sdk_1 = require("@extrahorizon/javascript-sdk");
|
|
5
|
+
async function findUserByEmail(sdk, email) {
|
|
6
|
+
const rql = (0, javascript_sdk_1.rqlBuilder)().eq('email', email).build();
|
|
7
|
+
return await sdk.users.findFirst({ rql });
|
|
8
|
+
}
|
|
9
|
+
exports.findUserByEmail = findUserByEmail;
|
|
10
|
+
async function isEmailAvailable(sdk, email) {
|
|
11
|
+
const { emailAvailable } = await sdk.users.isEmailAvailable(email);
|
|
12
|
+
return emailAvailable;
|
|
13
|
+
}
|
|
14
|
+
exports.isEmailAvailable = isEmailAvailable;
|
|
15
|
+
async function createUser(sdk, data) {
|
|
16
|
+
return await sdk.users.createAccount(data);
|
|
17
|
+
}
|
|
18
|
+
exports.createUser = createUser;
|
|
19
|
+
async function findGlobalRoleByName(sdk, name) {
|
|
20
|
+
return await sdk.users.globalRoles.findByName(name);
|
|
21
|
+
}
|
|
22
|
+
exports.findGlobalRoleByName = findGlobalRoleByName;
|
|
23
|
+
async function createGlobalRole(sdk, name, description) {
|
|
24
|
+
return await sdk.users.globalRoles.create({ name, description });
|
|
25
|
+
}
|
|
26
|
+
exports.createGlobalRole = createGlobalRole;
|
|
27
|
+
async function addPermissionsToGlobalRole(sdk, name, permissions) {
|
|
28
|
+
return await sdk.users.globalRoles.addPermissions((0, javascript_sdk_1.rqlBuilder)().eq('name', name).build(), { permissions });
|
|
29
|
+
}
|
|
30
|
+
exports.addPermissionsToGlobalRole = addPermissionsToGlobalRole;
|
|
31
|
+
async function removePermissionsFromGlobalRole(sdk, name, permissions) {
|
|
32
|
+
return await sdk.users.globalRoles.removePermissions((0, javascript_sdk_1.rqlBuilder)().eq('name', name).build(), { permissions });
|
|
33
|
+
}
|
|
34
|
+
exports.removePermissionsFromGlobalRole = removePermissionsFromGlobalRole;
|
|
35
|
+
async function addGlobalRoleToUser(sdk, userId, roleId) {
|
|
36
|
+
return await sdk.users.globalRoles.addToUsers((0, javascript_sdk_1.rqlBuilder)().eq('id', userId).build(), { roles: [roleId] });
|
|
37
|
+
}
|
|
38
|
+
exports.addGlobalRoleToUser = addGlobalRoleToUser;
|