@credibledata/cred-cli 0.0.100 → 0.0.103

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.
Files changed (225) hide show
  1. package/README-DEV.md +2 -2
  2. package/README.md +1 -1
  3. package/coverage/coverage-summary.json +40 -0
  4. package/coverage/tmp/coverage-2152-1789496974457-0.json +1 -0
  5. package/coverage/tmp/coverage-2153-1789496954404-0.json +1 -0
  6. package/dist/client/api.js +6151 -2254
  7. package/dist/client/api.js.map +1 -1
  8. package/dist/client/base.js +1 -1
  9. package/dist/client/common.js +1 -1
  10. package/dist/client/configuration.js +1 -1
  11. package/dist/client/index.js +1 -1
  12. package/dist/clientconfiguration.js +114 -26
  13. package/dist/clientconfiguration.js.map +1 -1
  14. package/dist/clientconfiguration.spec.js +159 -37
  15. package/dist/clientconfiguration.spec.js.map +1 -1
  16. package/dist/commands/add.js +36 -5
  17. package/dist/commands/add.js.map +1 -1
  18. package/dist/commands/connection/createconnections.js +4 -4
  19. package/dist/commands/connection/createconnections.js.map +1 -1
  20. package/dist/commands/connection/createconnections.spec.js +11 -1
  21. package/dist/commands/connection/createconnections.spec.js.map +1 -1
  22. package/dist/commands/connection/deleteconnection.js +4 -4
  23. package/dist/commands/connection/deleteconnection.js.map +1 -1
  24. package/dist/commands/connection/deleteconnection.spec.js +1 -1
  25. package/dist/commands/connection/deleteconnection.spec.js.map +1 -1
  26. package/dist/commands/connection/listconnections.js +4 -4
  27. package/dist/commands/connection/listconnections.js.map +1 -1
  28. package/dist/commands/connection/listconnections.spec.js +1 -1
  29. package/dist/commands/connection/listconnections.spec.js.map +1 -1
  30. package/dist/commands/{project/createproject.js → environment/createenvironment.js} +17 -14
  31. package/dist/commands/environment/createenvironment.js.map +1 -0
  32. package/dist/commands/{project/createproject.spec.js → environment/createenvironment.spec.js} +46 -46
  33. package/dist/commands/environment/createenvironment.spec.js.map +1 -0
  34. package/dist/commands/{project/deleteproject.js → environment/deleteenvironment.js} +9 -9
  35. package/dist/commands/environment/deleteenvironment.js.map +1 -0
  36. package/dist/commands/{project/deleteproject.spec.js → environment/deleteenvironment.spec.js} +29 -29
  37. package/dist/commands/environment/deleteenvironment.spec.js.map +1 -0
  38. package/dist/commands/{project/getproject.js → environment/getenvironment.js} +8 -8
  39. package/dist/commands/environment/getenvironment.js.map +1 -0
  40. package/dist/commands/{project/getproject.spec.js → environment/getenvironment.spec.js} +32 -33
  41. package/dist/commands/environment/getenvironment.spec.js.map +1 -0
  42. package/dist/commands/{project/listprojects.js → environment/listenvironments.js} +10 -10
  43. package/dist/commands/environment/listenvironments.js.map +1 -0
  44. package/dist/commands/{project/listprojects.spec.js → environment/listenvironments.spec.js} +35 -35
  45. package/dist/commands/environment/listenvironments.spec.js.map +1 -0
  46. package/dist/commands/{project/setproject.js → environment/setenvironment.js} +6 -5
  47. package/dist/commands/environment/setenvironment.js.map +1 -0
  48. package/dist/commands/{project/setproject.spec.js → environment/setenvironment.spec.js} +9 -9
  49. package/dist/commands/environment/setenvironment.spec.js.map +1 -0
  50. package/dist/commands/environment/updateenvironment.js +130 -0
  51. package/dist/commands/environment/updateenvironment.js.map +1 -0
  52. package/dist/commands/environment/updateenvironment.spec.js +213 -0
  53. package/dist/commands/environment/updateenvironment.spec.js.map +1 -0
  54. package/dist/commands/get.js +66 -5
  55. package/dist/commands/get.js.map +1 -1
  56. package/dist/commands/legacy.js +9 -0
  57. package/dist/commands/legacy.js.map +1 -0
  58. package/dist/commands/list.js +95 -4
  59. package/dist/commands/list.js.map +1 -1
  60. package/dist/commands/materialization/cancelrun.js +62 -0
  61. package/dist/commands/materialization/cancelrun.js.map +1 -0
  62. package/dist/commands/materialization/getindex.js +52 -0
  63. package/dist/commands/materialization/getindex.js.map +1 -0
  64. package/dist/commands/materialization/getmaterialization.js +54 -0
  65. package/dist/commands/materialization/getmaterialization.js.map +1 -0
  66. package/dist/commands/materialization/getpreaggregate.js +55 -0
  67. package/dist/commands/materialization/getpreaggregate.js.map +1 -0
  68. package/dist/commands/materialization/getrun.js +54 -0
  69. package/dist/commands/materialization/getrun.js.map +1 -0
  70. package/dist/commands/materialization/listindexes.js +58 -0
  71. package/dist/commands/materialization/listindexes.js.map +1 -0
  72. package/dist/commands/materialization/listmaterializations.js +52 -0
  73. package/dist/commands/materialization/listmaterializations.js.map +1 -0
  74. package/dist/commands/materialization/listpreaggregates.js +61 -0
  75. package/dist/commands/materialization/listpreaggregates.js.map +1 -0
  76. package/dist/commands/materialization/listruns.js +60 -0
  77. package/dist/commands/materialization/listruns.js.map +1 -0
  78. package/dist/commands/materialization/rerun.js +111 -0
  79. package/dist/commands/materialization/rerun.js.map +1 -0
  80. package/dist/commands/misc/login.js +16 -2
  81. package/dist/commands/misc/login.js.map +1 -1
  82. package/dist/commands/misc/login.spec.js +133 -5
  83. package/dist/commands/misc/login.spec.js.map +1 -1
  84. package/dist/commands/package/deletepackage.js +4 -4
  85. package/dist/commands/package/deletepackage.js.map +1 -1
  86. package/dist/commands/package/deletepackage.spec.js +1 -1
  87. package/dist/commands/package/deletepackage.spec.js.map +1 -1
  88. package/dist/commands/package/listpackages.js +11 -4
  89. package/dist/commands/package/listpackages.js.map +1 -1
  90. package/dist/commands/package/listpackages.spec.js +13 -1
  91. package/dist/commands/package/listpackages.spec.js.map +1 -1
  92. package/dist/commands/package/publish.js +36 -13
  93. package/dist/commands/package/publish.js.map +1 -1
  94. package/dist/commands/package/publish.spec.js +27 -1
  95. package/dist/commands/package/publish.spec.js.map +1 -1
  96. package/dist/commands/package/updatepackage.js +4 -4
  97. package/dist/commands/package/updatepackage.js.map +1 -1
  98. package/dist/commands/package/updatepackage.spec.js +1 -1
  99. package/dist/commands/package/updatepackage.spec.js.map +1 -1
  100. package/dist/commands/permission/createpermission.js +123 -0
  101. package/dist/commands/permission/createpermission.js.map +1 -0
  102. package/dist/commands/permission/createpermission.spec.js +360 -0
  103. package/dist/commands/permission/createpermission.spec.js.map +1 -0
  104. package/dist/commands/permission/deletepermission.js +86 -0
  105. package/dist/commands/permission/deletepermission.js.map +1 -0
  106. package/dist/commands/permission/getpermission.js +85 -0
  107. package/dist/commands/permission/getpermission.js.map +1 -0
  108. package/dist/commands/permission/listpermissions.js +75 -0
  109. package/dist/commands/permission/listpermissions.js.map +1 -0
  110. package/dist/commands/permission/scope.js +140 -0
  111. package/dist/commands/permission/scope.js.map +1 -0
  112. package/dist/commands/rm.js +26 -4
  113. package/dist/commands/rm.js.map +1 -1
  114. package/dist/commands/set.js +12 -4
  115. package/dist/commands/set.js.map +1 -1
  116. package/dist/commands/update.js +29 -10
  117. package/dist/commands/update.js.map +1 -1
  118. package/dist/commands/version/archive-unarchive-version.js +4 -5
  119. package/dist/commands/version/archive-unarchive-version.js.map +1 -1
  120. package/dist/commands/version/archive-unarchive-version.spec.js +4 -4
  121. package/dist/commands/version/archive-unarchive-version.spec.js.map +1 -1
  122. package/dist/commands/version/listversions.js +4 -4
  123. package/dist/commands/version/listversions.js.map +1 -1
  124. package/dist/commands/version/listversions.spec.js +1 -1
  125. package/dist/commands/version/listversions.spec.js.map +1 -1
  126. package/dist/common/UserGroupId.js +1 -1
  127. package/dist/common/UserGroupId.js.map +1 -1
  128. package/dist/common/UserGroupId.spec.js +2 -4
  129. package/dist/common/UserGroupId.spec.js.map +1 -1
  130. package/dist/constants.js +95 -19
  131. package/dist/constants.js.map +1 -1
  132. package/dist/constants.spec.js +90 -0
  133. package/dist/constants.spec.js.map +1 -0
  134. package/dist/index.js +128 -15
  135. package/dist/index.js.map +1 -1
  136. package/dist/logger.js +5 -1
  137. package/dist/logger.js.map +1 -1
  138. package/openapitools.json +4 -1
  139. package/package.json +10 -9
  140. package/src/client/api.ts +9363 -3093
  141. package/src/client/base.ts +1 -1
  142. package/src/client/common.ts +1 -1
  143. package/src/client/configuration.ts +1 -1
  144. package/src/client/index.ts +1 -1
  145. package/src/clientconfiguration.spec.ts +238 -113
  146. package/src/clientconfiguration.ts +131 -30
  147. package/src/commands/add.ts +78 -12
  148. package/src/commands/connection/createconnections.spec.ts +11 -1
  149. package/src/commands/connection/createconnections.ts +4 -4
  150. package/src/commands/connection/deleteconnection.spec.ts +1 -1
  151. package/src/commands/connection/deleteconnection.ts +4 -4
  152. package/src/commands/connection/listconnections.spec.ts +1 -1
  153. package/src/commands/connection/listconnections.ts +4 -4
  154. package/src/commands/{project/createproject.spec.ts → environment/createenvironment.spec.ts} +56 -54
  155. package/src/commands/{project/createproject.ts → environment/createenvironment.ts} +17 -14
  156. package/src/commands/{project/deleteproject.spec.ts → environment/deleteenvironment.spec.ts} +59 -30
  157. package/src/commands/{project/deleteproject.ts → environment/deleteenvironment.ts} +10 -10
  158. package/src/commands/environment/getenvironment.spec.ts +110 -0
  159. package/src/commands/{project/getproject.ts → environment/getenvironment.ts} +9 -9
  160. package/src/commands/{project/listprojects.spec.ts → environment/listenvironments.spec.ts} +37 -35
  161. package/src/commands/{project/listprojects.ts → environment/listenvironments.ts} +13 -8
  162. package/src/commands/{project/setproject.spec.ts → environment/setenvironment.spec.ts} +8 -8
  163. package/src/commands/{project/setproject.ts → environment/setenvironment.ts} +4 -4
  164. package/src/commands/environment/updateenvironment.spec.ts +386 -0
  165. package/src/commands/environment/updateenvironment.ts +168 -0
  166. package/src/commands/get.ts +131 -9
  167. package/src/commands/legacy.ts +5 -0
  168. package/src/commands/list.ts +204 -9
  169. package/src/commands/materialization/cancelrun.ts +70 -0
  170. package/src/commands/materialization/getindex.ts +55 -0
  171. package/src/commands/materialization/getmaterialization.ts +57 -0
  172. package/src/commands/materialization/getpreaggregate.ts +58 -0
  173. package/src/commands/materialization/getrun.ts +55 -0
  174. package/src/commands/materialization/listindexes.ts +69 -0
  175. package/src/commands/materialization/listmaterializations.ts +53 -0
  176. package/src/commands/materialization/listpreaggregates.ts +74 -0
  177. package/src/commands/materialization/listruns.ts +77 -0
  178. package/src/commands/materialization/rerun.ts +123 -0
  179. package/src/commands/misc/login.spec.ts +165 -7
  180. package/src/commands/misc/login.ts +20 -2
  181. package/src/commands/package/deletepackage.spec.ts +1 -1
  182. package/src/commands/package/deletepackage.ts +4 -4
  183. package/src/commands/package/listpackages.spec.ts +17 -1
  184. package/src/commands/package/listpackages.ts +11 -4
  185. package/src/commands/package/publish.spec.ts +46 -1
  186. package/src/commands/package/publish.ts +38 -13
  187. package/src/commands/package/updatepackage.spec.ts +1 -1
  188. package/src/commands/package/updatepackage.ts +4 -4
  189. package/src/commands/permission/createpermission.spec.ts +507 -0
  190. package/src/commands/permission/createpermission.ts +181 -0
  191. package/src/commands/permission/deletepermission.ts +117 -0
  192. package/src/commands/permission/getpermission.ts +115 -0
  193. package/src/commands/permission/listpermissions.ts +101 -0
  194. package/src/commands/permission/scope.ts +180 -0
  195. package/src/commands/rm.ts +54 -9
  196. package/src/commands/set.ts +13 -4
  197. package/src/commands/update.ts +66 -23
  198. package/src/commands/version/archive-unarchive-version.spec.ts +4 -4
  199. package/src/commands/version/archive-unarchive-version.ts +4 -7
  200. package/src/commands/version/listversions.spec.ts +1 -1
  201. package/src/commands/version/listversions.ts +4 -4
  202. package/src/common/UserGroupId.spec.ts +2 -4
  203. package/src/common/UserGroupId.ts +1 -1
  204. package/src/constants.spec.ts +111 -0
  205. package/src/constants.ts +131 -19
  206. package/src/index.ts +187 -18
  207. package/src/logger.ts +5 -1
  208. package/bun.lock +0 -1158
  209. package/dist/commands/project/createproject.js.map +0 -1
  210. package/dist/commands/project/createproject.spec.js.map +0 -1
  211. package/dist/commands/project/deleteproject.js.map +0 -1
  212. package/dist/commands/project/deleteproject.spec.js.map +0 -1
  213. package/dist/commands/project/getproject.js.map +0 -1
  214. package/dist/commands/project/getproject.spec.js.map +0 -1
  215. package/dist/commands/project/listprojects.js.map +0 -1
  216. package/dist/commands/project/listprojects.spec.js.map +0 -1
  217. package/dist/commands/project/setproject.js.map +0 -1
  218. package/dist/commands/project/setproject.spec.js.map +0 -1
  219. package/dist/commands/project/updateproject.js +0 -68
  220. package/dist/commands/project/updateproject.js.map +0 -1
  221. package/dist/commands/project/updateproject.spec.js +0 -129
  222. package/dist/commands/project/updateproject.spec.js.map +0 -1
  223. package/src/commands/project/getproject.spec.ts +0 -109
  224. package/src/commands/project/updateproject.spec.ts +0 -217
  225. package/src/commands/project/updateproject.ts +0 -82
@@ -0,0 +1,117 @@
1
+ import {
2
+ EnvironmentPermissionsApi,
3
+ OrganizationPermissionsApi,
4
+ PackagePermissionsApi,
5
+ } from "../../client/api";
6
+ import { Configuration } from "../../client/configuration";
7
+ import { ClientConfiguration } from "../../clientconfiguration";
8
+ import { UserGroupId } from "../../common/UserGroupId";
9
+ import { logger } from "../../logger";
10
+ import { getConfirmation, printOutError } from "../../utils";
11
+ import {
12
+ describeScope,
13
+ PermissionScope,
14
+ resolveScope,
15
+ ScopeOptions,
16
+ } from "./scope";
17
+
18
+ const organizationPermissionsApi = new OrganizationPermissionsApi(
19
+ new Configuration(),
20
+ );
21
+ const environmentPermissionsApi = new EnvironmentPermissionsApi(
22
+ new Configuration(),
23
+ );
24
+ const packagePermissionsApi = new PackagePermissionsApi(new Configuration());
25
+
26
+ export async function deletePermission(
27
+ controlPlane: string,
28
+ userGroupIdValue: string,
29
+ debug: boolean,
30
+ autoConfirm: boolean,
31
+ options: ScopeOptions,
32
+ ) {
33
+ const clientConfig = new ClientConfiguration();
34
+
35
+ if (!clientConfig.doesConfigExists()) {
36
+ logger.error("Please, make sure that you are logged in");
37
+ return;
38
+ }
39
+
40
+ const organizationName = clientConfig.getOrganization();
41
+ if (!organizationName) {
42
+ logger.error("No organization set. Please login or set an organization.");
43
+ return;
44
+ }
45
+
46
+ const resolved = resolveScope(options, clientConfig.getProject());
47
+ if ("error" in resolved) {
48
+ logger.error(resolved.error);
49
+ process.exit(1);
50
+ return;
51
+ }
52
+
53
+ let userGroupId: string;
54
+ try {
55
+ userGroupId = new UserGroupId(userGroupIdValue).getValue();
56
+ } catch (e) {
57
+ logger.error((e as Error).message);
58
+ process.exit(1);
59
+ return;
60
+ }
61
+
62
+ const target = describeScope(organizationName, resolved);
63
+
64
+ if (!autoConfirm) {
65
+ const confirmation = await getConfirmation(
66
+ `Are you sure that you want to revoke ${userGroupId}'s permission on ${target}?`,
67
+ );
68
+ if (!confirmation) {
69
+ logger.info("Operation cancelled.");
70
+ return;
71
+ }
72
+ }
73
+
74
+ logger.info(`Revoking permission for ${userGroupId} on ${target}`);
75
+
76
+ const requestOptions = {
77
+ baseURL: controlPlane,
78
+ headers: {
79
+ Authorization: clientConfig.getAuthenticationHeader(),
80
+ },
81
+ };
82
+
83
+ try {
84
+ switch (resolved.scope) {
85
+ case PermissionScope.PACKAGE:
86
+ await packagePermissionsApi.deletePackagePermission(
87
+ organizationName,
88
+ resolved.environmentName as string,
89
+ resolved.packageName as string,
90
+ userGroupId,
91
+ requestOptions,
92
+ );
93
+ break;
94
+ case PermissionScope.ENVIRONMENT:
95
+ await environmentPermissionsApi.deleteEnvironmentPermission(
96
+ organizationName,
97
+ resolved.environmentName as string,
98
+ userGroupId,
99
+ requestOptions,
100
+ );
101
+ break;
102
+ default:
103
+ await organizationPermissionsApi.deleteOrganizationPermission(
104
+ organizationName,
105
+ userGroupId,
106
+ requestOptions,
107
+ );
108
+ break;
109
+ }
110
+
111
+ logger.info("Permission revoked successfully");
112
+ } catch (error) {
113
+ logger.error("Failed to revoke permission");
114
+ printOutError(error, debug);
115
+ process.exit(1);
116
+ }
117
+ }
@@ -0,0 +1,115 @@
1
+ import {
2
+ EnvironmentPermissionsApi,
3
+ OrganizationPermissionsApi,
4
+ PackagePermissionsApi,
5
+ } from "../../client/api";
6
+ import { Configuration } from "../../client/configuration";
7
+ import { ClientConfiguration } from "../../clientconfiguration";
8
+ import { UserGroupId } from "../../common/UserGroupId";
9
+ import { logger } from "../../logger";
10
+ import { printOutError } from "../../utils";
11
+ import {
12
+ describeScope,
13
+ PermissionScope,
14
+ resolveScope,
15
+ ScopeOptions,
16
+ } from "./scope";
17
+
18
+ const organizationPermissionsApi = new OrganizationPermissionsApi(
19
+ new Configuration(),
20
+ );
21
+ const environmentPermissionsApi = new EnvironmentPermissionsApi(
22
+ new Configuration(),
23
+ );
24
+ const packagePermissionsApi = new PackagePermissionsApi(new Configuration());
25
+
26
+ export async function getPermission(
27
+ controlPlane: string,
28
+ userGroupIdValue: string,
29
+ debug: boolean,
30
+ options: ScopeOptions,
31
+ ) {
32
+ const clientConfig = new ClientConfiguration();
33
+
34
+ if (!clientConfig.doesConfigExists()) {
35
+ logger.error("Please, make sure that you are logged in");
36
+ return;
37
+ }
38
+
39
+ const organizationName = clientConfig.getOrganization();
40
+ if (!organizationName) {
41
+ logger.error("No organization set. Please login or set an organization.");
42
+ return;
43
+ }
44
+
45
+ const resolved = resolveScope(options, clientConfig.getProject());
46
+ if ("error" in resolved) {
47
+ logger.error(resolved.error);
48
+ process.exit(1);
49
+ return;
50
+ }
51
+
52
+ let userGroupId: string;
53
+ try {
54
+ userGroupId = new UserGroupId(userGroupIdValue).getValue();
55
+ } catch (e) {
56
+ logger.error((e as Error).message);
57
+ process.exit(1);
58
+ return;
59
+ }
60
+
61
+ logger.info(
62
+ `Getting permission for ${userGroupId} on ${describeScope(organizationName, resolved)}`,
63
+ );
64
+
65
+ const requestOptions = {
66
+ baseURL: controlPlane,
67
+ headers: {
68
+ Authorization: clientConfig.getAuthenticationHeader(),
69
+ },
70
+ };
71
+
72
+ try {
73
+ let data: unknown;
74
+ switch (resolved.scope) {
75
+ case PermissionScope.PACKAGE: {
76
+ const response = await packagePermissionsApi.getPackagePermission(
77
+ organizationName,
78
+ resolved.environmentName as string,
79
+ resolved.packageName as string,
80
+ userGroupId,
81
+ requestOptions,
82
+ );
83
+ data = response.data;
84
+ break;
85
+ }
86
+ case PermissionScope.ENVIRONMENT: {
87
+ const response =
88
+ await environmentPermissionsApi.getEnvironmentPermission(
89
+ organizationName,
90
+ resolved.environmentName as string,
91
+ userGroupId,
92
+ requestOptions,
93
+ );
94
+ data = response.data;
95
+ break;
96
+ }
97
+ default: {
98
+ const response =
99
+ await organizationPermissionsApi.getOrganizationPermission(
100
+ organizationName,
101
+ userGroupId,
102
+ requestOptions,
103
+ );
104
+ data = response.data;
105
+ break;
106
+ }
107
+ }
108
+
109
+ console.log(JSON.stringify(data, null, 2));
110
+ } catch (error) {
111
+ logger.error("Failed to get permission");
112
+ printOutError(error, debug);
113
+ process.exit(1);
114
+ }
115
+ }
@@ -0,0 +1,101 @@
1
+ import {
2
+ EnvironmentPermissionsApi,
3
+ OrganizationPermissionsApi,
4
+ PackagePermissionsApi,
5
+ } from "../../client/api";
6
+ import { Configuration } from "../../client/configuration";
7
+ import { ClientConfiguration } from "../../clientconfiguration";
8
+ import { logger } from "../../logger";
9
+ import { printOutError } from "../../utils";
10
+ import {
11
+ describeScope,
12
+ PermissionScope,
13
+ resolveScope,
14
+ ScopeOptions,
15
+ } from "./scope";
16
+
17
+ const organizationPermissionsApi = new OrganizationPermissionsApi(
18
+ new Configuration(),
19
+ );
20
+ const environmentPermissionsApi = new EnvironmentPermissionsApi(
21
+ new Configuration(),
22
+ );
23
+ const packagePermissionsApi = new PackagePermissionsApi(new Configuration());
24
+
25
+ export async function listPermissions(
26
+ controlPlane: string,
27
+ debug: boolean,
28
+ options: ScopeOptions,
29
+ ) {
30
+ const clientConfig = new ClientConfiguration();
31
+
32
+ if (!clientConfig.doesConfigExists()) {
33
+ logger.error("Please, make sure that you are logged in");
34
+ return;
35
+ }
36
+
37
+ const organizationName = clientConfig.getOrganization();
38
+ if (!organizationName) {
39
+ logger.error("No organization set. Please login or set an organization.");
40
+ return;
41
+ }
42
+
43
+ const resolved = resolveScope(options, clientConfig.getProject());
44
+ if ("error" in resolved) {
45
+ logger.error(resolved.error);
46
+ process.exit(1);
47
+ return;
48
+ }
49
+
50
+ logger.info(
51
+ `Listing permissions on ${describeScope(organizationName, resolved)}`,
52
+ );
53
+
54
+ const requestOptions = {
55
+ baseURL: controlPlane,
56
+ headers: {
57
+ Authorization: clientConfig.getAuthenticationHeader(),
58
+ },
59
+ };
60
+
61
+ try {
62
+ let data: unknown;
63
+ switch (resolved.scope) {
64
+ case PermissionScope.PACKAGE: {
65
+ const response = await packagePermissionsApi.listPackagePermissions(
66
+ organizationName,
67
+ resolved.environmentName as string,
68
+ resolved.packageName as string,
69
+ requestOptions,
70
+ );
71
+ data = response.data;
72
+ break;
73
+ }
74
+ case PermissionScope.ENVIRONMENT: {
75
+ const response =
76
+ await environmentPermissionsApi.listEnvironmentPermissions(
77
+ organizationName,
78
+ resolved.environmentName as string,
79
+ requestOptions,
80
+ );
81
+ data = response.data;
82
+ break;
83
+ }
84
+ default: {
85
+ const response =
86
+ await organizationPermissionsApi.listOrganizationPermissions(
87
+ organizationName,
88
+ requestOptions,
89
+ );
90
+ data = response.data;
91
+ break;
92
+ }
93
+ }
94
+
95
+ console.log(JSON.stringify(data, null, 2));
96
+ } catch (error) {
97
+ logger.error("Failed to list permissions");
98
+ printOutError(error, debug);
99
+ process.exit(1);
100
+ }
101
+ }
@@ -0,0 +1,180 @@
1
+ import {
2
+ EnvironmentPermissionPermissionEnum,
3
+ OrganizationPermissionPermissionEnum,
4
+ PackagePermissionPermissionEnum,
5
+ } from "../../client/api";
6
+ import { UserGroupId } from "../../common/UserGroupId";
7
+
8
+ /**
9
+ * Which resource a permission is granted on. The organization is the default
10
+ * because it is the only scope that names no resource of its own.
11
+ */
12
+ export enum PermissionScope {
13
+ ORGANIZATION = "organization",
14
+ ENVIRONMENT = "environment",
15
+ PACKAGE = "package",
16
+ }
17
+
18
+ /**
19
+ * The roles each scope accepts.
20
+ *
21
+ * The organization is the odd one out: it ends in `member` where the other two
22
+ * end in `viewer`. They are not interchangeable, so the sets are listed per
23
+ * scope rather than shared.
24
+ *
25
+ * A package takes `viewer` alone, which is narrower than its schema enum. The
26
+ * enum carries admin and modeler because a package reports them -- they are
27
+ * inherited from the environment -- but only viewer is directly assignable, and
28
+ * the server rejects the other two. Deriving this set from the enum would let
29
+ * the CLI accept a grant that cannot be written.
30
+ */
31
+ const ROLES_BY_SCOPE: Record<PermissionScope, readonly string[]> = {
32
+ [PermissionScope.ORGANIZATION]: Object.values(
33
+ OrganizationPermissionPermissionEnum,
34
+ ),
35
+ [PermissionScope.ENVIRONMENT]: Object.values(
36
+ EnvironmentPermissionPermissionEnum,
37
+ ),
38
+ [PermissionScope.PACKAGE]: [PackagePermissionPermissionEnum.Viewer],
39
+ };
40
+
41
+ export type ScopeOptions = {
42
+ environment?: string;
43
+ package?: string;
44
+ };
45
+
46
+ /**
47
+ * The resource a command addresses: the scope plus the names needed to reach
48
+ * it. `environmentName` is set for both the environment and package scopes,
49
+ * since a package is addressed through its environment.
50
+ */
51
+ export type ResolvedScope = {
52
+ scope: PermissionScope;
53
+ environmentName?: string;
54
+ packageName?: string;
55
+ };
56
+
57
+ export function rolesFor(scope: PermissionScope): readonly string[] {
58
+ return ROLES_BY_SCOPE[scope];
59
+ }
60
+
61
+ /**
62
+ * Works out which resource the options address, reading the environment from
63
+ * the config when a package is named without one.
64
+ *
65
+ * Returns an error rather than guessing when the environment cannot be
66
+ * resolved: silently falling back to the organization would grant a wider
67
+ * permission than the caller asked for.
68
+ */
69
+ export function resolveScope(
70
+ options: ScopeOptions,
71
+ configuredEnvironment: string | undefined,
72
+ ): ResolvedScope | { error: string } {
73
+ // An option that was passed but is empty -- `--environment "$UNSET_VAR"` --
74
+ // is a mistake, not an omission. Treating it as absent would widen the grant
75
+ // to the next scope out, which is the outcome this function exists to refuse,
76
+ // so it is reported rather than interpreted.
77
+ for (const name of ["environment", "package"] as const) {
78
+ const value = options[name];
79
+ if (value !== undefined && value.trim() === "") {
80
+ return { error: `--${name} was given an empty value.` };
81
+ }
82
+ }
83
+
84
+ if (options.package) {
85
+ const environmentName = options.environment || configuredEnvironment;
86
+ if (!environmentName) {
87
+ return {
88
+ error: "A package permission needs an environment. Pass --environment, or set one with 'cred set environment <name>'.",
89
+ };
90
+ }
91
+ return {
92
+ scope: PermissionScope.PACKAGE,
93
+ environmentName,
94
+ packageName: options.package,
95
+ };
96
+ }
97
+
98
+ if (options.environment) {
99
+ return {
100
+ scope: PermissionScope.ENVIRONMENT,
101
+ environmentName: options.environment,
102
+ };
103
+ }
104
+
105
+ return { scope: PermissionScope.ORGANIZATION };
106
+ }
107
+
108
+ /** Names the resource in log lines, so a message says what was addressed. */
109
+ export function describeScope(
110
+ organizationName: string,
111
+ resolved: ResolvedScope,
112
+ ): string {
113
+ switch (resolved.scope) {
114
+ case PermissionScope.PACKAGE:
115
+ return `package ${organizationName}/${resolved.environmentName}/${resolved.packageName}`;
116
+ case PermissionScope.ENVIRONMENT:
117
+ return `environment ${organizationName}/${resolved.environmentName}`;
118
+ default:
119
+ return `organization ${organizationName}`;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Checks a role against the scope it is granted on, so a role the API would
125
+ * reject fails before the request instead of as an opaque 400.
126
+ */
127
+ export function validateRole(
128
+ scope: PermissionScope,
129
+ role: string,
130
+ ): string | null {
131
+ const allowed = rolesFor(scope);
132
+ if (!allowed.includes(role)) {
133
+ return `Invalid role '${role}' for a ${scope} permission. Expected one of: ${allowed.join(", ")}`;
134
+ }
135
+ return null;
136
+ }
137
+
138
+ /**
139
+ * The roles the authorization model accepts for public access, per scope.
140
+ *
141
+ * Narrower than the roles a named subject can hold, and not derivable from
142
+ * them: the model lists `user:*` on exactly three relations. Anything else
143
+ * reaches OpenFGA and fails there as a model validation error, so it is listed
144
+ * rather than special-cased.
145
+ */
146
+ const PUBLIC_ACCESS_ROLES_BY_SCOPE: Record<PermissionScope, readonly string[]> =
147
+ {
148
+ [PermissionScope.ORGANIZATION]: ["modeler"],
149
+ [PermissionScope.ENVIRONMENT]: ["viewer"],
150
+ [PermissionScope.PACKAGE]: ["viewer"],
151
+ };
152
+
153
+ /**
154
+ * Parses the subject and checks the roles public access may hold. Everything
155
+ * else about the subject -- whether a user's email is well formed, whether a
156
+ * group exists -- is left to the server, which is the authority on it.
157
+ */
158
+ export function parseSubject(
159
+ scope: PermissionScope,
160
+ role: string,
161
+ value: string,
162
+ ): { userGroupId: UserGroupId } | { error: string } {
163
+ let userGroupId: UserGroupId;
164
+ try {
165
+ userGroupId = new UserGroupId(value);
166
+ } catch (e) {
167
+ return { error: (e as Error).message };
168
+ }
169
+
170
+ if (userGroupId.isPublicAccess()) {
171
+ const allowed = PUBLIC_ACCESS_ROLES_BY_SCOPE[scope];
172
+ if (!allowed.includes(role)) {
173
+ return {
174
+ error: `Public access cannot be granted '${role}' on a ${scope}. Expected one of: ${allowed.join(", ")}`,
175
+ };
176
+ }
177
+ }
178
+
179
+ return { userGroupId };
180
+ }
@@ -5,7 +5,9 @@ import { deleteGroup } from "./group/deletegroup";
5
5
  import { removeMember } from "./group/removemember";
6
6
  import { deleteGroupAccessToken } from "./groupaccesstoken/deleteToken";
7
7
  import { deletePackage } from "./package/deletepackage";
8
- import { deleteProject } from "./project/deleteproject";
8
+ import { deleteEnvironment } from "./environment/deleteenvironment";
9
+ import { warnProjectDeprecated } from "./legacy";
10
+ import { deletePermission } from "./permission/deletepermission";
9
11
 
10
12
  export const registerRmCommands = (cli: Command, environment: Environment) => {
11
13
  const rm = cli
@@ -13,6 +15,34 @@ export const registerRmCommands = (cli: Command, environment: Environment) => {
13
15
  .description("Remove a resource")
14
16
  .argument("<resource>", "The resource to remove");
15
17
 
18
+ rm.command("permission")
19
+ .description(
20
+ "Revoke a user or group's permission on the organization, an environment, or a package.",
21
+ )
22
+ .argument(
23
+ "<userGroupId>",
24
+ "Whose permission to revoke [user:{email}|group:{groupName}|user:*]",
25
+ )
26
+ .option(
27
+ "--environment <environmentName>",
28
+ "Revoke the permission on this environment instead of the organization.",
29
+ )
30
+ .option(
31
+ "--package <packageName>",
32
+ "Revoke the permission on this package. Uses --environment, or the current environment.",
33
+ )
34
+ .option("--debug")
35
+ .option("-y, --yes", "Skip confirmation.")
36
+ .action((userGroupId, options) => {
37
+ deletePermission(
38
+ controlPlanesByEnv[environment],
39
+ userGroupId,
40
+ options.debug || false,
41
+ options.yes === true,
42
+ { environment: options.environment, package: options.package },
43
+ );
44
+ });
45
+
16
46
  rm.command("package")
17
47
  .description("Delete a package.")
18
48
  .argument("<packageName>", "The name of the package to delete.")
@@ -27,18 +57,33 @@ export const registerRmCommands = (cli: Command, environment: Environment) => {
27
57
  );
28
58
  });
29
59
 
60
+ const rmEnvironmentAction = (
61
+ environmentName: string,
62
+ options: { debug?: boolean; yes?: boolean },
63
+ ) => {
64
+ deleteEnvironment(
65
+ controlPlanesByEnv[environment],
66
+ environmentName,
67
+ options.debug,
68
+ options.yes,
69
+ );
70
+ };
71
+
72
+ rm.command("environment")
73
+ .description("Delete an environment.")
74
+ .argument("<environmentName>", "The name of the environment to delete.")
75
+ .option("--debug")
76
+ .option("-y, --yes", "Skip confirmation.")
77
+ .action(rmEnvironmentAction);
78
+
30
79
  rm.command("project")
31
- .description("Delete a project.")
32
- .argument("<projectName>", "The name of the project to delete.")
80
+ .description("[deprecated] Alias for 'rm environment'.")
81
+ .argument("<projectName>", "The name of the environment to delete.")
33
82
  .option("--debug")
34
83
  .option("-y, --yes", "Skip confirmation.")
35
84
  .action((projectName, options) => {
36
- deleteProject(
37
- controlPlanesByEnv[environment],
38
- projectName,
39
- options.debug,
40
- options.yes,
41
- );
85
+ warnProjectDeprecated("rm environment");
86
+ rmEnvironmentAction(projectName, options);
42
87
  });
43
88
 
44
89
  rm.command("connection")
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
- import { setProject } from "./project/setproject";
2
+ import { setEnvironment } from "./environment/setenvironment";
3
+ import { warnProjectDeprecated } from "./legacy";
3
4
 
4
5
  export const registerSetCommands = (cli: Command) => {
5
6
  const set = cli
@@ -7,10 +8,18 @@ export const registerSetCommands = (cli: Command) => {
7
8
  .description("Set a resource")
8
9
  .argument("<resource>", "The resource to set");
9
10
 
11
+ set.command("environment")
12
+ .description("Set the default environment.")
13
+ .argument("<environmentName>", "The name of the environment to set.")
14
+ .action(setEnvironment);
15
+
10
16
  set.command("project")
11
- .description("Set the default project.")
12
- .argument("<projectName>", "The name of the project to set.")
13
- .action(setProject);
17
+ .description("[deprecated] Alias for 'set environment'.")
18
+ .argument("<projectName>", "The name of the environment to set.")
19
+ .action((projectName) => {
20
+ warnProjectDeprecated("set environment");
21
+ setEnvironment(projectName);
22
+ });
14
23
 
15
24
  // TODO: It would be nice to `cred set org` and avoid logging again when switching orgs.
16
25
  };