@flowcore/cli-plugin-iam 1.5.0 → 1.6.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.6.1](https://github.com/flowcore-io/cli-plugin-iam/compare/v1.6.0...v1.6.1) (2025-03-20)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **role:** :art: improve formatting in GetRole command output, removed console logs ([ee41739](https://github.com/flowcore-io/cli-plugin-iam/commit/ee417394174d567abf48133d767ba70bedb2bdc2))
9
+
10
+ ## [1.6.0](https://github.com/flowcore-io/cli-plugin-iam/compare/v1.5.0...v1.6.0) (2025-02-16)
11
+
12
+
13
+ ### Features
14
+
15
+ * add edit role command to modify role details interactively ([d67eb3a](https://github.com/flowcore-io/cli-plugin-iam/commit/d67eb3a28d25ca7cac0683fb9aeb6f478386f8e8))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * :rotating_light: fixed linting errors ([7f481bd](https://github.com/flowcore-io/cli-plugin-iam/commit/7f481bd90bf67edfbd483dbd351b52ebba0d0bd2))
21
+
3
22
  ## [1.5.0](https://github.com/flowcore-io/cli-plugin-iam/compare/v1.4.0...v1.5.0) (2025-02-16)
4
23
 
5
24
 
package/README.md CHANGED
@@ -18,7 +18,7 @@ $ npm install -g @flowcore/cli-plugin-iam
18
18
  $ iam COMMAND
19
19
  running command...
20
20
  $ iam (--version)
21
- @flowcore/cli-plugin-iam/1.5.0 linux-x64 node-v20.16.0
21
+ @flowcore/cli-plugin-iam/1.6.1 linux-x64 node-v20.16.0
22
22
  $ iam --help [COMMAND]
23
23
  USAGE
24
24
  $ iam COMMAND
@@ -30,6 +30,7 @@ USAGE
30
30
  * [`iam delete policy NAME`](#iam-delete-policy-name)
31
31
  * [`iam delete role NAME`](#iam-delete-role-name)
32
32
  * [`iam edit policy NAME`](#iam-edit-policy-name)
33
+ * [`iam edit role NAME`](#iam-edit-role-name)
33
34
  * [`iam get policy [NAME]`](#iam-get-policy-name)
34
35
  * [`iam get role [NAME]`](#iam-get-role-name)
35
36
 
@@ -54,7 +55,7 @@ DESCRIPTION
54
55
  Delete a policy
55
56
  ```
56
57
 
57
- _See code: [src/commands/delete/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.5.0/src/commands/delete/policy.ts)_
58
+ _See code: [src/commands/delete/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.6.1/src/commands/delete/policy.ts)_
58
59
 
59
60
  ## `iam delete role NAME`
60
61
 
@@ -77,7 +78,7 @@ DESCRIPTION
77
78
  Delete a role
78
79
  ```
79
80
 
80
- _See code: [src/commands/delete/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.5.0/src/commands/delete/role.ts)_
81
+ _See code: [src/commands/delete/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.6.1/src/commands/delete/role.ts)_
81
82
 
82
83
  ## `iam edit policy NAME`
83
84
 
@@ -103,7 +104,33 @@ EXAMPLES
103
104
  $ FC_EDITOR=code flowcore iam edit policy my-policy -t my-tenant
104
105
  ```
105
106
 
106
- _See code: [src/commands/edit/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.5.0/src/commands/edit/policy.ts)_
107
+ _See code: [src/commands/edit/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.6.1/src/commands/edit/policy.ts)_
108
+
109
+ ## `iam edit role NAME`
110
+
111
+ Edit a role in your preferred editor
112
+
113
+ ```
114
+ USAGE
115
+ $ iam edit role NAME -t <value> [--profile <value>]
116
+
117
+ ARGUMENTS
118
+ NAME name
119
+
120
+ FLAGS
121
+ -t, --tenant=<value> (required) tenant
122
+ --profile=<value> Specify the configuration profile to use
123
+
124
+ DESCRIPTION
125
+ Edit a role in your preferred editor
126
+
127
+ EXAMPLES
128
+ $ flowcore iam edit role my-role -t my-tenant
129
+
130
+ $ FC_EDITOR=code flowcore iam edit role my-role -t my-tenant
131
+ ```
132
+
133
+ _See code: [src/commands/edit/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.6.1/src/commands/edit/role.ts)_
107
134
 
108
135
  ## `iam get policy [NAME]`
109
136
 
@@ -126,7 +153,7 @@ DESCRIPTION
126
153
  Get a policy
127
154
  ```
128
155
 
129
- _See code: [src/commands/get/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.5.0/src/commands/get/policy.ts)_
156
+ _See code: [src/commands/get/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.6.1/src/commands/get/policy.ts)_
130
157
 
131
158
  ## `iam get role [NAME]`
132
159
 
@@ -149,5 +176,5 @@ DESCRIPTION
149
176
  Get a role
150
177
  ```
151
178
 
152
- _See code: [src/commands/get/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.5.0/src/commands/get/role.ts)_
179
+ _See code: [src/commands/get/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.6.1/src/commands/get/role.ts)_
153
180
  <!-- commandsstop -->
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from "@flowcore/cli-plugin-config";
2
+ export declare const EDIT_ROLE_ARGS: {
3
+ NAME: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
4
+ };
5
+ export default class EditRole extends BaseCommand<typeof EditRole> {
6
+ static args: {
7
+ NAME: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static description: string;
10
+ static examples: string[];
11
+ static flags: {
12
+ tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ private spawnEditor;
16
+ }
@@ -0,0 +1,115 @@
1
+ import { BaseCommand, ValidateLogin } from "@flowcore/cli-plugin-config";
2
+ import { ClientFactory } from "@flowcore/cli-plugin-core";
3
+ import { Args, Flags } from "@oclif/core";
4
+ import { spawn } from "node:child_process";
5
+ import { unlink, writeFile } from "node:fs/promises";
6
+ import { tmpdir } from "node:os";
7
+ import { join } from "node:path";
8
+ import { tryit } from "radash";
9
+ import { v4 as uuidv4 } from "uuid";
10
+ import { OrganizationService } from "../../services/organization.service.js";
11
+ import { Api as IamApi } from "../../utils/clients/iam/Api.js";
12
+ export const EDIT_ROLE_ARGS = {
13
+ NAME: Args.string({ description: "name", required: true }),
14
+ };
15
+ export default class EditRole extends BaseCommand {
16
+ static args = EDIT_ROLE_ARGS;
17
+ static description = "Edit a role in your preferred editor";
18
+ static examples = [
19
+ "$ flowcore iam edit role my-role -t my-tenant",
20
+ "$ FC_EDITOR=code flowcore iam edit role my-role -t my-tenant",
21
+ ];
22
+ static flags = {
23
+ tenant: Flags.string({
24
+ char: "t",
25
+ description: "tenant",
26
+ required: true,
27
+ }),
28
+ };
29
+ async run() {
30
+ const { args, flags } = await this.parse(EditRole);
31
+ const graphqlClient = await ClientFactory.create(this.cliConfiguration, this.logger);
32
+ const organizationService = new OrganizationService(graphqlClient);
33
+ const organizations = await organizationService.getMyOrganizations();
34
+ const iamClient = new IamApi();
35
+ const config = this.cliConfiguration.getConfig();
36
+ const login = new ValidateLogin(config.login.url);
37
+ await login.validate(config, this.cliConfiguration, true);
38
+ const { auth } = config;
39
+ if (!auth?.accessToken) {
40
+ this.logger.fatal("Not logged in, run 'flowcore login'");
41
+ }
42
+ const organization = organizations.me.organizations.find((org) => org.organization.org === flags.tenant);
43
+ if (!organization) {
44
+ this.logger.fatal(`Organization ${flags.tenant} not found, or you are not a member`);
45
+ }
46
+ const [rolesErr, roles] = await tryit(iamClient.getApiV1RoleAssociationsOrganizationByOrganizationId)(organization.organization.id, {
47
+ headers: {
48
+ Authorization: `Bearer ${auth?.accessToken}`,
49
+ },
50
+ });
51
+ if (rolesErr) {
52
+ this.logger.fatal(`Failed to get roles: ${rolesErr.message}`);
53
+ }
54
+ const role = roles.data.find((role) => role.name === args.NAME);
55
+ if (!role) {
56
+ this.logger.fatal(`Role ${args.NAME} not found in tenant: ${flags.tenant}`);
57
+ }
58
+ // Create a temporary file with the role content
59
+ const tmpFile = join(tmpdir(), `role-${uuidv4()}.json`);
60
+ const roleContent = JSON.stringify({
61
+ description: role.description,
62
+ name: role.name,
63
+ }, null, 2);
64
+ try {
65
+ await writeFile(tmpFile, roleContent, "utf8");
66
+ await this.spawnEditor(tmpFile);
67
+ // Read and parse the edited content
68
+ const editedContent = await import(tmpFile, {
69
+ assert: { type: "json" },
70
+ });
71
+ // Update the role
72
+ const [updateErr] = await tryit(iamClient.patchApiV1RolesById)(role.id, {
73
+ description: editedContent.default.description,
74
+ id: role.id,
75
+ name: editedContent.default.name,
76
+ organizationId: organization.organization.id,
77
+ }, {
78
+ headers: {
79
+ Authorization: `Bearer ${auth?.accessToken}`,
80
+ },
81
+ });
82
+ if (updateErr) {
83
+ this.logger.fatal(`Failed to update role: ${updateErr.message}`);
84
+ }
85
+ this.logger.info(`Role ${role.name} updated successfully`);
86
+ }
87
+ catch (error) {
88
+ this.logger.fatal(`Error editing role: ${error}`);
89
+ }
90
+ finally {
91
+ await unlink(tmpFile).catch(() => {
92
+ // Ignore error if file doesn't exist
93
+ });
94
+ }
95
+ }
96
+ async spawnEditor(filePath) {
97
+ return new Promise((resolve, reject) => {
98
+ const editor = process.env.FC_EDITOR || process.env.EDITOR || "vim";
99
+ const child = spawn(editor, [filePath], {
100
+ stdio: "inherit",
101
+ });
102
+ child.on("exit", (code) => {
103
+ if (code === 0) {
104
+ resolve();
105
+ }
106
+ else {
107
+ reject(new Error(`Editor process exited with code ${code}`));
108
+ }
109
+ });
110
+ child.on("error", (err) => {
111
+ reject(err);
112
+ });
113
+ });
114
+ }
115
+ }
@@ -170,7 +170,6 @@ export default class GetRole extends BaseCommand {
170
170
  if (err) {
171
171
  this.logger.fatal(`Failed to get roles: ${err.message}`);
172
172
  }
173
- console.log(userRoles.data);
174
173
  const headers = [
175
174
  "Role ID",
176
175
  "Name",
@@ -129,7 +129,6 @@ export class RoleService {
129
129
  this.logger.debug(`Created binding for policy ${policyId} to role ${existingRole.id}`);
130
130
  }
131
131
  for (const policy of toRemove) {
132
- console.log(policy, alreadyLinkedPolicies.data);
133
132
  const policyId = alreadyLinkedPolicies.data.find((p) => p.name === policy)?.id;
134
133
  if (!policyId) {
135
134
  this.logger.fatal(`Policy ${policy} not found`);
@@ -122,17 +122,20 @@
122
122
  "role.js"
123
123
  ]
124
124
  },
125
- "get:policy": {
125
+ "edit:policy": {
126
126
  "aliases": [],
127
127
  "args": {
128
128
  "NAME": {
129
129
  "description": "name",
130
130
  "name": "NAME",
131
- "required": false
131
+ "required": true
132
132
  }
133
133
  },
134
- "description": "Get a policy",
135
- "examples": [],
134
+ "description": "Edit a policy in your preferred editor",
135
+ "examples": [
136
+ "$ flowcore iam edit policy my-policy -t my-tenant",
137
+ "$ FC_EDITOR=code flowcore iam edit policy my-policy -t my-tenant"
138
+ ],
136
139
  "flags": {
137
140
  "profile": {
138
141
  "description": "Specify the configuration profile to use",
@@ -141,35 +144,19 @@
141
144
  "multiple": false,
142
145
  "type": "option"
143
146
  },
144
- "json": {
145
- "char": "j",
146
- "description": "json output",
147
- "name": "json",
148
- "required": false,
149
- "allowNo": false,
150
- "type": "boolean"
151
- },
152
147
  "tenant": {
153
148
  "char": "t",
154
149
  "description": "tenant",
155
150
  "name": "tenant",
156
- "required": false,
151
+ "required": true,
157
152
  "hasDynamicHelp": false,
158
153
  "multiple": false,
159
154
  "type": "option"
160
- },
161
- "wide": {
162
- "char": "w",
163
- "description": "wide output",
164
- "name": "wide",
165
- "required": false,
166
- "allowNo": false,
167
- "type": "boolean"
168
155
  }
169
156
  },
170
157
  "hasDynamicHelp": false,
171
158
  "hiddenAliases": [],
172
- "id": "get:policy",
159
+ "id": "edit:policy",
173
160
  "pluginAlias": "@flowcore/cli-plugin-iam",
174
161
  "pluginName": "@flowcore/cli-plugin-iam",
175
162
  "pluginType": "core",
@@ -179,11 +166,59 @@
179
166
  "relativePath": [
180
167
  "dist",
181
168
  "commands",
182
- "get",
169
+ "edit",
183
170
  "policy.js"
184
171
  ]
185
172
  },
186
- "get:role": {
173
+ "edit:role": {
174
+ "aliases": [],
175
+ "args": {
176
+ "NAME": {
177
+ "description": "name",
178
+ "name": "NAME",
179
+ "required": true
180
+ }
181
+ },
182
+ "description": "Edit a role in your preferred editor",
183
+ "examples": [
184
+ "$ flowcore iam edit role my-role -t my-tenant",
185
+ "$ FC_EDITOR=code flowcore iam edit role my-role -t my-tenant"
186
+ ],
187
+ "flags": {
188
+ "profile": {
189
+ "description": "Specify the configuration profile to use",
190
+ "name": "profile",
191
+ "hasDynamicHelp": false,
192
+ "multiple": false,
193
+ "type": "option"
194
+ },
195
+ "tenant": {
196
+ "char": "t",
197
+ "description": "tenant",
198
+ "name": "tenant",
199
+ "required": true,
200
+ "hasDynamicHelp": false,
201
+ "multiple": false,
202
+ "type": "option"
203
+ }
204
+ },
205
+ "hasDynamicHelp": false,
206
+ "hiddenAliases": [],
207
+ "id": "edit:role",
208
+ "pluginAlias": "@flowcore/cli-plugin-iam",
209
+ "pluginName": "@flowcore/cli-plugin-iam",
210
+ "pluginType": "core",
211
+ "strict": true,
212
+ "enableJsonFlag": false,
213
+ "isESM": true,
214
+ "relativePath": [
215
+ "dist",
216
+ "commands",
217
+ "edit",
218
+ "role.js"
219
+ ]
220
+ },
221
+ "get:policy": {
187
222
  "aliases": [],
188
223
  "args": {
189
224
  "NAME": {
@@ -192,7 +227,7 @@
192
227
  "required": false
193
228
  }
194
229
  },
195
- "description": "Get a role",
230
+ "description": "Get a policy",
196
231
  "examples": [],
197
232
  "flags": {
198
233
  "profile": {
@@ -230,7 +265,7 @@
230
265
  },
231
266
  "hasDynamicHelp": false,
232
267
  "hiddenAliases": [],
233
- "id": "get:role",
268
+ "id": "get:policy",
234
269
  "pluginAlias": "@flowcore/cli-plugin-iam",
235
270
  "pluginName": "@flowcore/cli-plugin-iam",
236
271
  "pluginType": "core",
@@ -241,23 +276,20 @@
241
276
  "dist",
242
277
  "commands",
243
278
  "get",
244
- "role.js"
279
+ "policy.js"
245
280
  ]
246
281
  },
247
- "edit:policy": {
282
+ "get:role": {
248
283
  "aliases": [],
249
284
  "args": {
250
285
  "NAME": {
251
286
  "description": "name",
252
287
  "name": "NAME",
253
- "required": true
288
+ "required": false
254
289
  }
255
290
  },
256
- "description": "Edit a policy in your preferred editor",
257
- "examples": [
258
- "$ flowcore iam edit policy my-policy -t my-tenant",
259
- "$ FC_EDITOR=code flowcore iam edit policy my-policy -t my-tenant"
260
- ],
291
+ "description": "Get a role",
292
+ "examples": [],
261
293
  "flags": {
262
294
  "profile": {
263
295
  "description": "Specify the configuration profile to use",
@@ -266,19 +298,35 @@
266
298
  "multiple": false,
267
299
  "type": "option"
268
300
  },
301
+ "json": {
302
+ "char": "j",
303
+ "description": "json output",
304
+ "name": "json",
305
+ "required": false,
306
+ "allowNo": false,
307
+ "type": "boolean"
308
+ },
269
309
  "tenant": {
270
310
  "char": "t",
271
311
  "description": "tenant",
272
312
  "name": "tenant",
273
- "required": true,
313
+ "required": false,
274
314
  "hasDynamicHelp": false,
275
315
  "multiple": false,
276
316
  "type": "option"
317
+ },
318
+ "wide": {
319
+ "char": "w",
320
+ "description": "wide output",
321
+ "name": "wide",
322
+ "required": false,
323
+ "allowNo": false,
324
+ "type": "boolean"
277
325
  }
278
326
  },
279
327
  "hasDynamicHelp": false,
280
328
  "hiddenAliases": [],
281
- "id": "edit:policy",
329
+ "id": "get:role",
282
330
  "pluginAlias": "@flowcore/cli-plugin-iam",
283
331
  "pluginName": "@flowcore/cli-plugin-iam",
284
332
  "pluginType": "core",
@@ -288,10 +336,10 @@
288
336
  "relativePath": [
289
337
  "dist",
290
338
  "commands",
291
- "edit",
292
- "policy.js"
339
+ "get",
340
+ "role.js"
293
341
  ]
294
342
  }
295
343
  },
296
- "version": "1.5.0"
344
+ "version": "1.6.1"
297
345
  }
package/package.json CHANGED
@@ -91,7 +91,7 @@
91
91
  "version": "oclif readme && git add README.md",
92
92
  "update-schema": "rover graph introspect https://graph.api.flowcore.io/graphql -o schema.gql"
93
93
  },
94
- "version": "1.5.0",
94
+ "version": "1.6.1",
95
95
  "bugs": "https://github.com/flowcore-io/cli-plugin-iam/issues",
96
96
  "keywords": [
97
97
  "oclif"