indraq_cli 2.1.0 → 2.2.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.
Files changed (79) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +41 -15
  3. package/cloud-api/.dockerignore +18 -18
  4. package/cloud-api/.env.example +14 -14
  5. package/cloud-api/Dockerfile +19 -19
  6. package/cloud-api/README.md +93 -93
  7. package/cloud-api/dist/index.js +265 -27
  8. package/cloud-api/node_modules/.package-lock.json +1 -1
  9. package/cloud-api/package-lock.json +2 -2
  10. package/cloud-api/package.json +1 -1
  11. package/cloud-api/sql/001_init.sql +8 -8
  12. package/cloud-api/sql/002_user_providers_and_project_resources.sql +40 -40
  13. package/cloud-api/sql/003_environment_infrastructure.sql +19 -19
  14. package/cloud-api/sql/004_managed_aws_credentials.sql +20 -20
  15. package/cloud-api/sql/005_project_members_and_resource_grants.sql +22 -22
  16. package/cloud-api/sql/006_catalog_identity_password_security.sql +96 -96
  17. package/cloud-api/sql/007_aws_access_key_rotation.sql +16 -16
  18. package/cloud-api/sql/008_provider_scopes.sql +91 -91
  19. package/cloud-api/sql/009_scope_user_secrets_and_project_lifecycle.sql +13 -0
  20. package/cloud-api/src/index.ts +164 -27
  21. package/cloud-api/tsconfig.json +18 -18
  22. package/dist/cli/help-content.d.ts.map +1 -1
  23. package/dist/cli/help-content.js +29 -7
  24. package/dist/cli/help-content.js.map +1 -1
  25. package/dist/modules/access/commands/access.command.js +30 -30
  26. package/dist/modules/aws/services/route53-lookup.service.js.map +1 -1
  27. package/dist/modules/cloud/commands/cloud.command.d.ts +4 -0
  28. package/dist/modules/cloud/commands/cloud.command.d.ts.map +1 -1
  29. package/dist/modules/cloud/commands/cloud.command.js +52 -1
  30. package/dist/modules/cloud/commands/cloud.command.js.map +1 -1
  31. package/dist/modules/cloud/index.d.ts.map +1 -1
  32. package/dist/modules/cloud/index.js +6 -3
  33. package/dist/modules/cloud/index.js.map +1 -1
  34. package/dist/modules/cloud/services/cloud-jenkins.service.js +71 -71
  35. package/dist/modules/cloud/services/user-provider.service.d.ts +2 -8
  36. package/dist/modules/cloud/services/user-provider.service.d.ts.map +1 -1
  37. package/dist/modules/cloud/services/user-provider.service.js +7 -35
  38. package/dist/modules/cloud/services/user-provider.service.js.map +1 -1
  39. package/dist/modules/deploy/commands/build.command.d.ts +1 -0
  40. package/dist/modules/deploy/commands/build.command.d.ts.map +1 -1
  41. package/dist/modules/deploy/commands/build.command.js +12 -5
  42. package/dist/modules/deploy/commands/build.command.js.map +1 -1
  43. package/dist/modules/deploy/index.d.ts.map +1 -1
  44. package/dist/modules/deploy/index.js +11 -4
  45. package/dist/modules/deploy/index.js.map +1 -1
  46. package/dist/modules/prebuild/commands/prebuild.command.d.ts +0 -4
  47. package/dist/modules/prebuild/commands/prebuild.command.d.ts.map +1 -1
  48. package/dist/modules/prebuild/commands/prebuild.command.js +34 -38
  49. package/dist/modules/prebuild/commands/prebuild.command.js.map +1 -1
  50. package/dist/modules/prebuild/index.d.ts.map +1 -1
  51. package/dist/modules/prebuild/index.js +4 -8
  52. package/dist/modules/prebuild/index.js.map +1 -1
  53. package/dist/modules/scaffold/services/docker-template.service.js +95 -95
  54. package/dist/modules/scopes/commands/scope.command.d.ts.map +1 -1
  55. package/dist/modules/scopes/commands/scope.command.js +3 -47
  56. package/dist/modules/scopes/commands/scope.command.js.map +1 -1
  57. package/dist/modules/scopes/services/scope-native.service.js +2 -2
  58. package/dist/modules/scopes/services/scope-native.service.js.map +1 -1
  59. package/dist/modules/users/commands/user.command.d.ts +1 -0
  60. package/dist/modules/users/commands/user.command.d.ts.map +1 -1
  61. package/dist/modules/users/commands/user.command.js +15 -1
  62. package/dist/modules/users/commands/user.command.js.map +1 -1
  63. package/dist/modules/users/index.d.ts.map +1 -1
  64. package/dist/modules/users/index.js +3 -2
  65. package/dist/modules/users/index.js.map +1 -1
  66. package/dist/modules/users/providers/jenkins-user.provider.js +95 -95
  67. package/dist/shared/config/config-files.js +7 -7
  68. package/dist/shared/jenkins/jenkins.service.d.ts.map +1 -1
  69. package/dist/shared/jenkins/jenkins.service.js +13 -8
  70. package/dist/shared/jenkins/jenkins.service.js.map +1 -1
  71. package/dist/shared/jenkins/role-strategy-groovy.js +84 -84
  72. package/docs/ARCHITECTURE.md +29 -29
  73. package/docs/CREATE-DEPLOYMENT-reference.groovy +1105 -1105
  74. package/package.json +9 -5
  75. package/templates/jenkins/CREATE-DEPLOYMENT.groovy +1105 -1105
  76. package/templates/jenkins/Jenkinsfile-Mobile-App +759 -759
  77. package/CHANGELOG_v2.1.0.md +0 -27
  78. package/UPGRADE_v2.0_to_v2.1.md +0 -68
  79. package/cloud-api/dist/index.js.map +0 -1
@@ -121,10 +121,10 @@ const listQuery = (req: Request, defaultLimit = 10, maximum = 5000): { search: s
121
121
  };
122
122
 
123
123
  type ProjectAccess = 'view' | 'write';
124
- const projectAccessLevel = async (projectIdRaw: string, user: Auth): Promise<ProjectAccess | null> => {
124
+ const projectAccessLevel = async (projectIdRaw: string, user: Auth, includeArchived = false): Promise<ProjectAccess | null> => {
125
125
  const projectId = ensureUuid(projectIdRaw, 'Project ID');
126
126
  const result = await pool.query(
127
- `SELECT p.id,p.created_by,pm.role,pm.access_level
127
+ `SELECT p.id,p.created_by,p.archived_at,pm.role,pm.access_level
128
128
  FROM projects p
129
129
  LEFT JOIN project_members pm ON pm.project_id=p.id AND pm.user_id=$2
130
130
  WHERE p.id=$1
@@ -132,11 +132,12 @@ const projectAccessLevel = async (projectIdRaw: string, user: Auth): Promise<Pro
132
132
  [projectId, user.id]
133
133
  );
134
134
  if (!result.rowCount) return null;
135
- if (user.role === 'admin' || user.role === 'manager') return 'write';
136
135
  const row = result.rows[0];
136
+ if (row.archived_at && !includeArchived) return null;
137
+ if (user.role === 'admin') return 'write';
137
138
  if (row.created_by === user.id || row.role === 'owner' || row.access_level === 'write') return 'write';
138
- // Every authenticated organization user can discover/read every project.
139
- return 'view';
139
+ if (row.role || row.access_level === 'view') return 'view';
140
+ return null;
140
141
  };
141
142
 
142
143
  const hasProjectAccess = async (projectId: string, user: Auth): Promise<boolean> =>
@@ -147,7 +148,7 @@ const hasProjectWriteAccess = async (projectId: string, user: Auth): Promise<boo
147
148
 
148
149
  const hasProjectResourceAccess = async (resourceIdRaw: string, user: Auth, manage = false): Promise<boolean> => {
149
150
  const resourceId = ensureUuid(resourceIdRaw, 'Project resource ID');
150
- if (user.role === 'admin' || user.role === 'manager') return true;
151
+ if (user.role === 'admin') return true;
151
152
  const resource = await pool.query('SELECT project_id,created_by FROM project_resources WHERE id=$1', [resourceId]);
152
153
  if (!resource.rowCount) return false;
153
154
  const access = await projectAccessLevel(resource.rows[0].project_id, user);
@@ -300,7 +301,7 @@ const rotateManagedAwsAccessKey = async (
300
301
  const operatorUserId = await awsRotationOperatorUserId(actor, row);
301
302
  const iam = await awsIamClientForUser(operatorUserId);
302
303
  const keys = await iam.send(new ListAccessKeysCommand({ UserName: awsUsername }));
303
- const keyIds = (keys.AccessKeyMetadata || []).map((item) => item.AccessKeyId).filter((value): value is string => !!value);
304
+ const keyIds = (keys.AccessKeyMetadata || []).map((item: { AccessKeyId?: string }) => item.AccessKeyId).filter((value: string | undefined): value is string => !!value);
304
305
  if (keyIds.length >= 2) {
305
306
  throw Object.assign(
306
307
  new Error(`AWS IAM user ${awsUsername} already has two access keys. Remove the extra/unmanaged key before rotating through IndraQ.`),
@@ -834,11 +835,11 @@ app.post('/me/aws-credentials/:awsUsername/resolve', auth, async (req: AuthedReq
834
835
 
835
836
  app.get('/projects', auth, async (req: AuthedRequest, res) => {
836
837
  const { search, limit } = listQuery(req);
837
- const privileged = req.auth!.role === 'manager' || req.auth!.role === 'admin';
838
+ const archivedMode = req.query.archived === 'only' ? 'only' : req.query.archived === 'all' ? 'all' : 'active';
838
839
  const result = await pool.query(
839
840
  `SELECT p.*,u.email AS creator_email,
840
841
  CASE
841
- WHEN $3::boolean THEN 'write'
842
+ WHEN $3='admin' THEN 'write'
842
843
  WHEN p.created_by=$1 THEN 'write'
843
844
  WHEN pm.role='owner' OR pm.access_level='write' THEN 'write'
844
845
  ELSE 'view'
@@ -846,9 +847,11 @@ app.get('/projects', auth, async (req: AuthedRequest, res) => {
846
847
  FROM projects p
847
848
  JOIN users u ON u.id=p.created_by
848
849
  LEFT JOIN project_members pm ON pm.project_id=p.id AND pm.user_id=$1
849
- WHERE ($2='' OR p.name ILIKE '%'||$2||'%' OR p.kind ILIKE '%'||$2||'%' OR u.email ILIKE '%'||$2||'%')
850
+ WHERE ($3='admin' OR p.created_by=$1 OR pm.user_id=$1)
851
+ AND ($2='' OR p.name ILIKE '%'||$2||'%' OR p.kind ILIKE '%'||$2||'%' OR u.email ILIKE '%'||$2||'%')
852
+ AND ($4='all' OR ($4='only' AND p.archived_at IS NOT NULL) OR ($4='active' AND p.archived_at IS NULL))
850
853
  ORDER BY p.created_at DESC
851
- LIMIT $4`, [req.auth!.id, search, privileged, limit]
854
+ LIMIT $5`, [req.auth!.id, search, req.auth!.role, archivedMode, limit]
852
855
  );
853
856
  res.json(result.rows);
854
857
  });
@@ -887,6 +890,7 @@ app.get('/projects/:id', auth, async (req: AuthedRequest, res) => {
887
890
  app.patch('/projects/:id', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
888
891
  const reason = requireReason(req, res); if (!reason) return;
889
892
  const id = ensureUuid(routeParam(req.params.id), 'Project ID');
893
+ if (!(await hasProjectWriteAccess(id, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
890
894
  if (typeof req.body?.name === 'string' && req.body.name.trim()) {
891
895
  const duplicate = await pool.query('SELECT id FROM projects WHERE lower(name)=lower($1) AND id<>$2 LIMIT 1', [req.body.name.trim(), id]);
892
896
  if (duplicate.rowCount) { res.status(409).json({ error: `Project name "${req.body.name.trim()}" already exists organization-wide.` }); return; }
@@ -902,15 +906,37 @@ app.patch('/projects/:id', ...allow('manager', 'admin'), async (req: AuthedReque
902
906
 
903
907
  app.delete('/projects/:id', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
904
908
  const reason = requireReason(req, res); if (!reason) return;
905
- const id = routeParam(req.params.id);
909
+ const id = ensureUuid(routeParam(req.params.id), 'Project ID');
910
+ if ((await projectAccessLevel(id, req.auth!, true)) !== 'write') { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
906
911
  const result = await pool.query('DELETE FROM projects WHERE id=$1 RETURNING id,name', [id]);
907
912
  if (!result.rowCount) { res.status(404).json({ error: 'Project not found' }); return; }
908
913
  await audit(req.auth!.id, 'project.delete', 'project', id, reason, { name: result.rows[0].name });
909
914
  res.status(204).end();
910
915
  });
911
916
 
917
+ app.post('/projects/:id/archive', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
918
+ const reason = requireReason(req, res); if (!reason) return;
919
+ const id = ensureUuid(routeParam(req.params.id), 'Project ID');
920
+ if ((await projectAccessLevel(id, req.auth!, true)) !== 'write') { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
921
+ const result = await pool.query('UPDATE projects SET archived_at=COALESCE(archived_at,now()),archived_by=COALESCE(archived_by,$2),updated_at=now() WHERE id=$1 RETURNING id,name,archived_at,archived_by', [id, req.auth!.id]);
922
+ if (!result.rowCount) { res.status(404).json({ error: 'Project not found' }); return; }
923
+ await audit(req.auth!.id, 'project.archive', 'project', id, reason, { name: result.rows[0].name });
924
+ res.json(result.rows[0]);
925
+ });
926
+
927
+ app.post('/projects/:id/restore', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
928
+ const reason = requireReason(req, res); if (!reason) return;
929
+ const id = ensureUuid(routeParam(req.params.id), 'Project ID');
930
+ if ((await projectAccessLevel(id, req.auth!, true)) !== 'write') { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
931
+ const result = await pool.query('UPDATE projects SET archived_at=NULL,archived_by=NULL,updated_at=now() WHERE id=$1 RETURNING id,name,archived_at,archived_by', [id]);
932
+ if (!result.rowCount) { res.status(404).json({ error: 'Project not found' }); return; }
933
+ await audit(req.auth!.id, 'project.restore', 'project', id, reason, { name: result.rows[0].name });
934
+ res.json(result.rows[0]);
935
+ });
936
+
912
937
  app.get('/projects/:id/members', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
913
- const id = routeParam(req.params.id);
938
+ const id = ensureUuid(routeParam(req.params.id), 'Project ID');
939
+ if (!(await hasProjectWriteAccess(id, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
914
940
  const result = await pool.query(`SELECT pm.project_id,pm.user_id,pm.role,pm.access_level,pm.added_at,u.email,u.name,u.role AS user_role
915
941
  FROM project_members pm JOIN users u ON u.id=pm.user_id
916
942
  WHERE pm.project_id=$1 AND u.is_active=true ORDER BY u.email`, [id]);
@@ -919,7 +945,8 @@ app.get('/projects/:id/members', ...allow('manager', 'admin'), async (req: Authe
919
945
 
920
946
  app.post('/projects/:id/members', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
921
947
  const reason = requireReason(req, res); if (!reason) return;
922
- const id = routeParam(req.params.id);
948
+ const id = ensureUuid(routeParam(req.params.id), 'Project ID');
949
+ if (!(await hasProjectWriteAccess(id, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
923
950
  const userId = String(req.body?.userId || '');
924
951
  const project = await pool.query('SELECT id FROM projects WHERE id=$1', [id]);
925
952
  if (!project.rowCount) { res.status(404).json({ error: 'Project not found' }); return; }
@@ -946,7 +973,8 @@ app.post('/projects/:id/members', ...allow('manager', 'admin'), async (req: Auth
946
973
 
947
974
  app.delete('/projects/:id/members/:userId', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
948
975
  const reason = requireReason(req, res); if (!reason) return;
949
- const id = routeParam(req.params.id);
976
+ const id = ensureUuid(routeParam(req.params.id), 'Project ID');
977
+ if (!(await hasProjectWriteAccess(id, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
950
978
  const userId = routeParam(req.params.userId);
951
979
  const target = await pool.query('SELECT email,role FROM users WHERE id=$1', [userId]);
952
980
  if (req.auth!.role === 'manager' && target.rows[0]?.role && target.rows[0].role !== 'user') { res.status(403).json({ error: 'Managers may remove only normal users from projects.' }); return; }
@@ -1058,7 +1086,7 @@ app.get('/scopes', auth, async (req: AuthedRequest, res) => {
1058
1086
  LIMIT $${offset + 3}`,
1059
1087
  params
1060
1088
  );
1061
- res.json(result.rows.map((row) => ({
1089
+ res.json(result.rows.map((row: any) => ({
1062
1090
  id: row.id, provider: row.provider, name: row.name, description: row.description, company: row.company,
1063
1091
  config: row.config || {}, has_secret: !!row.encrypted_secret, access: row.access || 'manage',
1064
1092
  is_default: false, created_at: row.created_at, updated_at: row.updated_at
@@ -1144,6 +1172,7 @@ app.post('/scopes/:id/resolve', auth, async (req: AuthedRequest, res) => {
1144
1172
  const id = ensureUuid(routeParam(req.params.id), 'Scope ID');
1145
1173
  const access = await scopeAccessFor(id, req.auth!);
1146
1174
  if (!access) { res.status(404).json({ error: 'Scope not found or access denied' }); return; }
1175
+ if (access === 'use') { res.status(403).json({ error: 'MANAGE access is required to resolve the provider management credential.' }); return; }
1147
1176
  const result = await pool.query('SELECT id,provider,name,description,company,config,encrypted_secret FROM provider_scopes WHERE id=$1 AND is_active=true', [id]);
1148
1177
  if (!result.rowCount) { res.status(404).json({ error: 'Scope not found' }); return; }
1149
1178
  const row = result.rows[0];
@@ -1213,6 +1242,18 @@ app.get('/scopes/:id/audit', auth, async (req: AuthedRequest, res) => {
1213
1242
  res.json(result.rows);
1214
1243
  });
1215
1244
 
1245
+ app.get('/me/scopes', auth, async (req: AuthedRequest, res) => {
1246
+ const result = await pool.query(
1247
+ `SELECT ps.id,ps.provider,ps.name,ps.description,ps.company,ps.config,(ps.encrypted_secret IS NOT NULL) has_secret,
1248
+ CASE WHEN $2='admin' THEN 'manage' ELSE psm.access END AS access
1249
+ FROM provider_scopes ps
1250
+ LEFT JOIN provider_scope_members psm ON psm.scope_id=ps.id AND psm.user_id=$1
1251
+ WHERE ps.is_active=true AND ($2='admin' OR psm.user_id=$1)
1252
+ ORDER BY ps.provider,lower(ps.name)`, [req.auth!.id, req.auth!.role]
1253
+ );
1254
+ res.json(result.rows);
1255
+ });
1256
+
1216
1257
  app.get('/me/scope-defaults', auth, async (req: AuthedRequest, res) => {
1217
1258
  const result = await pool.query(
1218
1259
  `SELECT usd.provider,usd.scope_id,ps.name,ps.company,ps.config,ps.updated_at
@@ -1261,13 +1302,33 @@ app.post('/me/scopes/:provider/resolve', auth, async (req: AuthedRequest, res) =
1261
1302
  const visible = req.auth!.role === 'admin'
1262
1303
  ? await pool.query('SELECT id FROM provider_scopes WHERE provider=$1 AND is_active=true ORDER BY created_at', [provider])
1263
1304
  : await pool.query('SELECT ps.id FROM provider_scopes ps JOIN provider_scope_members psm ON psm.scope_id=ps.id WHERE psm.user_id=$1 AND ps.provider=$2 AND ps.is_active=true ORDER BY ps.created_at', [req.auth!.id, provider]);
1264
- if (visible.rowCount === 1) scopeId = visible.rows[0].id;
1265
- else if (visible.rowCount > 1) { res.status(409).json({ error: `Multiple ${provider} scopes are available. Link one to the project environment or set your default with \`indraq scope default\`.` }); return; }
1305
+ if (visible.rows.length === 1) scopeId = visible.rows[0].id;
1306
+ else if (visible.rows.length > 1) { res.status(409).json({ error: `Multiple ${provider} scopes are available. Link one to the project environment or set your default with \`indraq scope default\`.` }); return; }
1266
1307
  }
1267
- if (!scopeId || !(await scopeVisible(scopeId, req.auth!))) { res.status(404).json({ error: `No ${provider} scope is assigned to your account.` }); return; }
1308
+ const access = scopeId ? await scopeAccessFor(scopeId, req.auth!) : null;
1309
+ if (!scopeId || !access) { res.status(404).json({ error: `No ${provider} scope is assigned to your account.` }); return; }
1268
1310
  const row = (await pool.query('SELECT id,provider,name,description,company,config,encrypted_secret FROM provider_scopes WHERE id=$1 AND is_active=true', [scopeId])).rows[0];
1269
- await audit(req.auth!.id, 'scope.secret.resolve', 'provider-scope', scopeId, reason, { provider, projectId: projectId || null, environment: environment || null });
1270
- res.json({ id: row.id, provider: row.provider, name: row.name, description: row.description, company: row.company, config: row.config || {}, secret: row.encrypted_secret ? JSON.parse(decrypt(row.encrypted_secret)) : null });
1311
+ let secret: any = null;
1312
+ let credentialSource = 'scope-management';
1313
+ if (req.auth!.role !== 'admin' && provider === 'aws') {
1314
+ const own = await pool.query('SELECT access_key_id,encrypted_secret_access_key FROM scope_aws_credentials WHERE scope_id=$1 AND cloud_user_id=$2', [scopeId, req.auth!.id]);
1315
+ if (!own.rowCount) { res.status(404).json({ error: 'No AWS credential is provisioned for you in this scope.' }); return; }
1316
+ secret = { accessKeyId: own.rows[0].access_key_id, secretAccessKey: decrypt(own.rows[0].encrypted_secret_access_key) };
1317
+ credentialSource = 'user-native';
1318
+ } else if (req.auth!.role !== 'admin' && ['npm','jenkins-dev','jenkins-prod'].includes(provider)) {
1319
+ const own = await pool.query('SELECT external_username,encrypted_secret FROM scope_external_accounts WHERE scope_id=$1 AND cloud_user_id=$2', [scopeId, req.auth!.id]);
1320
+ if (!own.rowCount || !own.rows[0].encrypted_secret) { res.status(404).json({ error: `No ${provider} credential is provisioned for you in this scope. Rotate your provider password or ask a scope manager to reprovision you.` }); return; }
1321
+ secret = provider === 'npm'
1322
+ ? { identity: own.rows[0].external_username, secret: decrypt(own.rows[0].encrypted_secret) }
1323
+ : { username: own.rows[0].external_username, secret: decrypt(own.rows[0].encrypted_secret) };
1324
+ credentialSource = 'user-native';
1325
+ } else {
1326
+ secret = row.encrypted_secret ? JSON.parse(decrypt(row.encrypted_secret)) : null;
1327
+ }
1328
+ await audit(req.auth!.id, 'scope.credential.resolve', 'provider-scope', scopeId, reason, { provider, projectId: projectId || null, environment: environment || null, credentialSource });
1329
+ res.setHeader('Cache-Control', 'no-store');
1330
+ res.setHeader('Pragma', 'no-cache');
1331
+ res.json({ id: row.id, provider: row.provider, name: row.name, description: row.description, company: row.company, config: row.config || {}, secret, access: access === 'admin' ? 'manage' : access });
1271
1332
  });
1272
1333
 
1273
1334
  app.get('/projects/:projectId/environment-scopes', auth, async (req: AuthedRequest, res) => {
@@ -1378,12 +1439,13 @@ app.put('/scopes/:scopeId/users/:userId/external-account', ...allow('manager','a
1378
1439
  const externalUsername = String(req.body?.externalUsername || '').trim();
1379
1440
  if (!externalUsername) { res.status(400).json({ error: 'externalUsername is required.' }); return; }
1380
1441
  const externalEmail = req.body?.externalEmail ? String(req.body.externalEmail).trim() : null;
1442
+ const encryptedSecret = req.body?.secret ? encrypt(String(req.body.secret)) : null;
1381
1443
  const result = await pool.query(
1382
- `INSERT INTO scope_external_accounts(scope_id,cloud_user_id,provider,external_username,external_email,managed_by_user_id,config)
1383
- VALUES($1,$2,$3,$4,$5,$6,$7)
1384
- ON CONFLICT(scope_id,cloud_user_id) DO UPDATE SET external_username=excluded.external_username,external_email=excluded.external_email,managed_by_user_id=excluded.managed_by_user_id,config=excluded.config,updated_at=now()
1444
+ `INSERT INTO scope_external_accounts(scope_id,cloud_user_id,provider,external_username,external_email,managed_by_user_id,config,encrypted_secret)
1445
+ VALUES($1,$2,$3,$4,$5,$6,$7,$8)
1446
+ ON CONFLICT(scope_id,cloud_user_id) DO UPDATE SET external_username=excluded.external_username,external_email=excluded.external_email,managed_by_user_id=excluded.managed_by_user_id,config=excluded.config,encrypted_secret=COALESCE(excluded.encrypted_secret,scope_external_accounts.encrypted_secret),updated_at=now()
1385
1447
  RETURNING id,scope_id,cloud_user_id,provider,external_username,external_email,config,updated_at`,
1386
- [scopeId, userId, scope.rows[0].provider, externalUsername, externalEmail, req.auth!.id, req.body?.config || {}]
1448
+ [scopeId, userId, scope.rows[0].provider, externalUsername, externalEmail, req.auth!.id, req.body?.config || {}, encryptedSecret]
1387
1449
  );
1388
1450
  await audit(req.auth!.id, 'scope.native-account.upsert', 'provider-scope', scopeId, reason, { userId, provider: scope.rows[0].provider, externalUsername, externalEmail });
1389
1451
  res.json(result.rows[0]);
@@ -1490,6 +1552,74 @@ app.post('/me/scopes/:scopeId/aws-credential/resolve', auth, async (req: AuthedR
1490
1552
  res.json({ awsUsername: row.aws_username, accessKeyId: row.access_key_id, secretAccessKey: decrypt(row.encrypted_secret_access_key), indraqRole: row.indraq_role });
1491
1553
  });
1492
1554
 
1555
+ app.post('/me/scopes/:scopeId/aws-credential/rotate', auth, async (req: AuthedRequest, res) => {
1556
+ const reason = requireReason(req, res); if (!reason) return;
1557
+ const scopeId = ensureUuid(routeParam(req.params.scopeId), 'Scope ID');
1558
+ if (!(await scopeVisible(scopeId, req.auth!))) { res.status(403).json({ error: 'Scope access denied.' }); return; }
1559
+ const own = await pool.query('SELECT aws_username,access_key_id,encrypted_secret_access_key FROM scope_aws_credentials WHERE scope_id=$1 AND cloud_user_id=$2', [scopeId, req.auth!.id]);
1560
+ if (!own.rowCount) { res.status(404).json({ error: 'No AWS credential is stored for you in this scope.' }); return; }
1561
+ const scope = await pool.query('SELECT config,encrypted_secret FROM provider_scopes WHERE id=$1 AND provider=\'aws\' AND is_active=true', [scopeId]);
1562
+ if (!scope.rowCount || !scope.rows[0].encrypted_secret) { res.status(409).json({ error: 'AWS scope management credential is unavailable.' }); return; }
1563
+ const management = JSON.parse(decrypt(scope.rows[0].encrypted_secret));
1564
+ const region = String(scope.rows[0].config?.region || 'us-east-1');
1565
+ const iam = new IAMClient({ region, credentials: { accessKeyId: management.accessKeyId, secretAccessKey: management.secretAccessKey, ...(management.sessionToken ? { sessionToken: management.sessionToken } : {}) } });
1566
+ const created = await iam.send(new CreateAccessKeyCommand({ UserName: own.rows[0].aws_username }));
1567
+ const next = created.AccessKey;
1568
+ if (!next?.AccessKeyId || !next.SecretAccessKey) { res.status(502).json({ error: 'AWS did not return a replacement access key.' }); return; }
1569
+ try {
1570
+ await pool.query('UPDATE scope_aws_credentials SET access_key_id=$1,encrypted_secret_access_key=$2,updated_at=now() WHERE scope_id=$3 AND cloud_user_id=$4', [next.AccessKeyId, encrypt(next.SecretAccessKey), scopeId, req.auth!.id]);
1571
+ await iam.send(new DeleteAccessKeyCommand({ UserName: own.rows[0].aws_username, AccessKeyId: own.rows[0].access_key_id }));
1572
+ } catch (error) {
1573
+ try { await iam.send(new DeleteAccessKeyCommand({ UserName: own.rows[0].aws_username, AccessKeyId: next.AccessKeyId })); } catch { /* best effort */ }
1574
+ throw error;
1575
+ }
1576
+ await audit(req.auth!.id, 'scope.aws-credential.self-rotate', 'provider-scope', scopeId, reason, { awsUsername: own.rows[0].aws_username, previousAccessKeyId: own.rows[0].access_key_id, accessKeyId: next.AccessKeyId });
1577
+ res.setHeader('Cache-Control', 'no-store'); res.setHeader('Pragma', 'no-cache');
1578
+ res.json({ awsUsername: own.rows[0].aws_username, accessKeyId: next.AccessKeyId, secretAccessKey: next.SecretAccessKey });
1579
+ });
1580
+
1581
+ app.post('/me/scopes/:scopeId/external-account/rotate', auth, async (req: AuthedRequest, res) => {
1582
+ const reason = requireReason(req, res); if (!reason) return;
1583
+ const scopeId = ensureUuid(routeParam(req.params.scopeId), 'Scope ID');
1584
+ if (!(await scopeVisible(scopeId, req.auth!))) { res.status(403).json({ error: 'Scope access denied.' }); return; }
1585
+ const password = String(req.body?.password || '');
1586
+ if (password.length < 10) { res.status(400).json({ error: 'Password must be at least 10 characters.' }); return; }
1587
+ const account = await pool.query('SELECT provider,external_username FROM scope_external_accounts WHERE scope_id=$1 AND cloud_user_id=$2', [scopeId, req.auth!.id]);
1588
+ if (!account.rowCount) { res.status(404).json({ error: 'No NPM/Jenkins account is stored for you in this scope.' }); return; }
1589
+ const scope = await pool.query('SELECT provider,config,encrypted_secret FROM provider_scopes WHERE id=$1 AND is_active=true', [scopeId]);
1590
+ if (!scope.rowCount || !scope.rows[0].encrypted_secret) { res.status(409).json({ error: 'Provider management credential is unavailable.' }); return; }
1591
+ const provider = String(account.rows[0].provider);
1592
+ const management = JSON.parse(decrypt(scope.rows[0].encrypted_secret));
1593
+ const username = String(account.rows[0].external_username);
1594
+ if (provider === 'npm') {
1595
+ const base = String(scope.rows[0].config?.url || '').replace(/\/+$/, '');
1596
+ const tokenResponse = await fetch(`${base}/api/tokens`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ identity: management.identity, secret: management.secret }) });
1597
+ if (!tokenResponse.ok) { res.status(502).json({ error: `NPM management authentication failed (HTTP ${tokenResponse.status}).` }); return; }
1598
+ const token = (await tokenResponse.json() as { token?: string }).token;
1599
+ if (!token) { res.status(502).json({ error: 'NPM did not return a management token.' }); return; }
1600
+ const headers = { authorization: `Bearer ${token}`, 'content-type': 'application/json' };
1601
+ const usersResponse = await fetch(`${base}/api/users?expand=permissions`, { headers });
1602
+ if (!usersResponse.ok) { res.status(502).json({ error: `Unable to list NPM users (HTTP ${usersResponse.status}).` }); return; }
1603
+ const users = await usersResponse.json() as Array<{ id: number; email?: string; nickname?: string; name?: string }>;
1604
+ const wanted = username.toLowerCase();
1605
+ const target = users.find((u) => String(u.email || '').toLowerCase() === wanted || String(u.nickname || '').toLowerCase() === wanted || String(u.name || '').toLowerCase() === wanted);
1606
+ if (!target) { res.status(404).json({ error: `NPM user ${username} was not found.` }); return; }
1607
+ const update = await fetch(`${base}/api/users/${target.id}/auth`, { method: 'PUT', headers, body: JSON.stringify({ type: 'password', secret: password }) });
1608
+ if (!update.ok) { res.status(502).json({ error: `NPM password reset failed (HTTP ${update.status}).` }); return; }
1609
+ } else if (provider === 'jenkins-dev' || provider === 'jenkins-prod') {
1610
+ const url = String(scope.rows[0].config?.url || '').replace(/\/+$/, '');
1611
+ const adminUsername = String(management.username || '');
1612
+ const adminSecret = String(management.secret || '');
1613
+ const headers = await jenkinsRequestHeaders(url, adminUsername, adminSecret);
1614
+ const script = `import hudson.security.HudsonPrivateSecurityRealm\ndef user = hudson.model.User.getById(${JSON.stringify(username)}, false)\nif (user == null) throw new IllegalStateException('Jenkins user not found')\nuser.addProperty(HudsonPrivateSecurityRealm.Details.fromPlainPassword(${JSON.stringify(password)}))\nuser.save()\nprintln 'updated'`;
1615
+ const response = await fetch(`${url}/scriptText`, { method: 'POST', headers: { ...headers, 'content-type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ script }).toString() });
1616
+ if (!response.ok) { res.status(502).json({ error: `Jenkins password reset failed (HTTP ${response.status}).` }); return; }
1617
+ } else { res.status(400).json({ error: 'Scope must be NPM or Jenkins.' }); return; }
1618
+ await pool.query('UPDATE scope_external_accounts SET encrypted_secret=$1,updated_at=now() WHERE scope_id=$2 AND cloud_user_id=$3', [encrypt(password), scopeId, req.auth!.id]);
1619
+ await audit(req.auth!.id, 'scope.external-account.self-rotate', 'provider-scope', scopeId, reason, { provider, username });
1620
+ res.status(204).end();
1621
+ });
1622
+
1493
1623
  // Reusable provider credentials are scoped to the authenticated IndraQ user.
1494
1624
  // A user configures AWS/NPM/Jenkins/GHCR once and can reuse that profile across
1495
1625
  // every project they are allowed to access. Secrets are encrypted at rest and
@@ -1699,18 +1829,23 @@ app.get('/users/:id/resource-grants', ...allow('manager', 'admin'), async (req:
1699
1829
  const target = await pool.query('SELECT id,email,role,is_active FROM users WHERE id=$1', [userId]);
1700
1830
  if (!target.rowCount) { res.status(404).json({ error: 'User not found' }); return; }
1701
1831
  if (req.auth!.role === 'manager' && target.rows[0].role !== 'user') { res.status(403).json({ error: 'Managers may inspect grants only for normal users.' }); return; }
1832
+ const managerFilter = req.auth!.role === 'manager'
1833
+ ? ` AND (p.created_by=$2 OR EXISTS (SELECT 1 FROM project_members pm WHERE pm.project_id=p.id AND pm.user_id=$2 AND (pm.role='owner' OR pm.access_level='write')))`
1834
+ : '';
1835
+ const params: unknown[] = req.auth!.role === 'manager' ? [userId, req.auth!.id] : [userId];
1702
1836
  const result = await pool.query(`SELECT g.id,g.project_resource_id,g.user_id,g.permission,g.created_at,
1703
1837
  pr.project_id,p.name AS project_name,pr.resource_type,pr.provider,pr.environment,pr.external_id,pr.config
1704
1838
  FROM project_resource_grants g
1705
1839
  JOIN project_resources pr ON pr.id=g.project_resource_id
1706
1840
  JOIN projects p ON p.id=pr.project_id
1707
- WHERE g.user_id=$1
1708
- ORDER BY p.name,pr.provider,pr.resource_type`, [userId]);
1841
+ WHERE g.user_id=$1 AND p.archived_at IS NULL${managerFilter}
1842
+ ORDER BY p.name,pr.provider,pr.resource_type`, params);
1709
1843
  res.json(result.rows);
1710
1844
  });
1711
1845
 
1712
1846
  app.get('/projects/:projectId/resource-grants', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
1713
1847
  const projectId = routeParam(req.params.projectId);
1848
+ if (!(await hasProjectWriteAccess(projectId, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
1714
1849
  const userId = typeof req.query.userId === 'string' ? req.query.userId : undefined;
1715
1850
  const result = await pool.query(`SELECT g.id,g.project_resource_id,g.user_id,g.permission,g.created_at,
1716
1851
  u.email,u.name,pr.resource_type,pr.provider,pr.environment,pr.external_id,pr.config
@@ -1725,6 +1860,7 @@ app.get('/projects/:projectId/resource-grants', ...allow('manager', 'admin'), as
1725
1860
  app.post('/projects/:projectId/resources/:resourceId/grants', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
1726
1861
  const reason = requireReason(req, res); if (!reason) return;
1727
1862
  const projectId = routeParam(req.params.projectId);
1863
+ if (!(await hasProjectWriteAccess(projectId, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
1728
1864
  const resourceId = routeParam(req.params.resourceId);
1729
1865
  const userId = String(req.body?.userId || '');
1730
1866
  const permission = req.body?.permission === 'view' ? 'view' : 'manage';
@@ -1743,6 +1879,7 @@ app.post('/projects/:projectId/resources/:resourceId/grants', ...allow('manager'
1743
1879
  app.delete('/projects/:projectId/resources/:resourceId/grants/:userId', ...allow('manager', 'admin'), async (req: AuthedRequest, res) => {
1744
1880
  const reason = requireReason(req, res); if (!reason) return;
1745
1881
  const projectId = routeParam(req.params.projectId);
1882
+ if (!(await hasProjectWriteAccess(projectId, req.auth!))) { res.status(403).json({ error: 'WRITE access to the project is required.' }); return; }
1746
1883
  const resourceId = routeParam(req.params.resourceId);
1747
1884
  const userId = routeParam(req.params.userId);
1748
1885
  const target = await pool.query('SELECT email,role FROM users WHERE id=$1', [userId]);
@@ -1,18 +1,18 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "rootDir": "src",
7
- "outDir": "dist",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "types": [
12
- "node"
13
- ]
14
- },
15
- "include": [
16
- "src/**/*.ts"
17
- ]
18
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "rootDir": "src",
7
+ "outDir": "dist",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "types": [
12
+ "node"
13
+ ]
14
+ },
15
+ "include": [
16
+ "src/**/*.ts"
17
+ ]
18
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"help-content.d.ts","sourceRoot":"","sources":["../../src/cli/help-content.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;AAMpH,eAAO,MAAM,oBAAoB,QAAO,MA+FvC,CAAC;AA6HF,eAAO,MAAM,YAAY,GAAI,OAAO,SAAS,KAAG,MAS/C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,SAAS,GAAG,SAa3D,CAAC"}
1
+ {"version":3,"file":"help-content.d.ts","sourceRoot":"","sources":["../../src/cli/help-content.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;AAMpH,eAAO,MAAM,oBAAoB,QAAO,MAqGvC,CAAC;AA6IF,eAAO,MAAM,YAAY,GAAI,OAAO,SAAS,KAAG,MAS/C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,SAAS,GAAG,SAa3D,CAAC"}
@@ -9,7 +9,7 @@ const heading = (value) => chalk_1.default.bold(value);
9
9
  const command = (value) => chalk_1.default.cyan(value);
10
10
  const note = (value) => chalk_1.default.gray(value);
11
11
  const fullCommandReference = () => `
12
- ${heading('IndraQ CLI v2.1 — scope-based infrastructure and deployment')}
12
+ ${heading('IndraQ CLI v2.2 — scope-first infrastructure and deployment')}
13
13
 
14
14
  ${heading('Start here')}
15
15
  ${command('indraq login')} Sign in to https://cli.indraq.com
@@ -34,7 +34,8 @@ ${heading('Scopes — AWS / NPM / Jenkins / GHCR')}
34
34
  ${command('indraq scope rotate-password')} Rotate your own NPM/Jenkins password
35
35
 
36
36
  ${heading('Organization users')}
37
- ${command('indraq user list')} List organization users (MANAGER/ADMIN)
37
+ ${command('indraq user list')} List organization users (MANAGER/ADMIN)
38
+ ${command('indraq user scopes [email]')} Show your own or a manageable user's scope assignments
38
39
  ${command('indraq user create [username]')} Create Cloud user and select one or many manageable scopes
39
40
  ${command('indraq user update [username] --role <role>')} Admin changes organization role; assigned scopes synchronize
40
41
  ${command('indraq user delete [username]')} Permanently remove identity from scopes, then Cloud
@@ -49,6 +50,10 @@ ${heading('Projects and project access')}
49
50
  ${command('indraq project scopes --env <env>')} Link provider scopes to this project/environment
50
51
  ${command('indraq project add user')} Add a user and synchronize required scope/resource access
51
52
  ${command('indraq project delete user')} Remove project membership
53
+ ${command('indraq project rename [name]')} Rename a managed project
54
+ ${command('indraq project archive')} Archive a managed project
55
+ ${command('indraq project restore')} Restore an archived project
56
+ ${command('indraq project delete')} Permanently delete project metadata
52
57
  ${command('indraq access add user')} Grant selected project resources
53
58
  ${command('indraq access delete user')} Revoke selected project resources
54
59
 
@@ -56,7 +61,8 @@ ${heading('Prebuild and deploy')}
56
61
  ${command('indraq prebuild --env dev')} Jenkins + GHCR required; DNS + NPM optional
57
62
  ${command('indraq deploy:dev')} Deploy dev
58
63
  ${command('indraq deploy:prod')} Deploy prod
59
- ${command('indraq deploy build --env staging')} Deploy a named IndraQ project/resource environment
64
+ ${command('indraq deploy --env staging')} Deploy a named IndraQ project/resource environment
65
+ ${command('indraq deploy --env dev --select-scopes')} Explicitly review/change saved scope bindings before deploy
60
66
  ${command('indraq deployment create --env dev')} Reconcile deployment infrastructure
61
67
  ${command('indraq deployment run --env dev')} Run deployment
62
68
 
@@ -129,12 +135,21 @@ ${heading('Commands')}
129
135
  ${command('indraq scope remove-user')}
130
136
  ${command('indraq scope default aws')}
131
137
  ${command('indraq scope audit')}
138
+ ${command('indraq scope credentials')} Own AWS IAM credential for an assigned AWS scope
139
+ ${command('indraq scope rotate-key')} Rotate your own AWS access key
140
+ ${command('indraq scope rotate-password')} Rotate your own NPM/Jenkins password
132
141
 
133
- ${note('scope describe never prints passwords, API tokens, AWS secret keys, or GHCR tokens.')}
142
+ ${note("scope describe never prints passwords, API tokens, AWS secret keys, or GHCR tokens. Normal USE members never receive the organization provider-management secret; AWS/NPM/Jenkins resolve to the member's own native identity.")}
134
143
  `;
135
144
  const usersHelp = () => `
136
145
  ${heading('Users and scope membership')}
137
146
 
147
+ ${command('indraq user list')}
148
+ Lists organization users for MANAGER/ADMIN accounts.
149
+
150
+ ${command('indraq user scopes [email]')}
151
+ Shows your own scope assignments, or a user you are authorized to manage.
152
+
138
153
  ${command('indraq user create')}
139
154
  Creates the Cloud identity first, then asks the admin/manager which MANAGE scopes
140
155
  should receive the user. Multiple AWS/NPM/Jenkins/GHCR scopes can be selected.
@@ -154,6 +169,9 @@ ${command('indraq user update <user> --role manager')}
154
169
  ${command('indraq user delete')}
155
170
  Removes every manageable provider-scope identity first. Cloud deletion happens only
156
171
  after provider cleanup succeeds, so failed cleanup can be retried safely.
172
+
173
+ ${command('indraq password reset')}
174
+ Resets your own IndraQ Cloud password.
157
175
  `;
158
176
  const deployHelp = () => `
159
177
  ${heading('Project scopes, prebuild and deployment')}
@@ -167,14 +185,18 @@ ${command('indraq prebuild --env dev')}
167
185
  Optional Route53: Skip | Create/reconcile | Link existing
168
186
  Optional NPM: Skip | Create/reconcile | Link existing
169
187
 
170
- ${command('indraq deploy build --env dev')}
188
+ ${command('indraq deploy --env dev')}
171
189
  Builds the Docker image, pushes it to the GHCR scope linked/defaulted for dev, then
172
- runs the Jenkins deployment associated with the dev project environment.
190
+ runs the Jenkins deployment associated with the dev project environment. Normal
191
+ deployments reuse the saved project/environment scope bindings without prompting.
192
+
193
+ ${command('indraq deploy --env dev --select-scopes')}
194
+ Explicitly review or change the saved scope bindings before this deployment.
173
195
 
174
196
  ${note('--env is an IndraQ environment selector. Application environment files are part of your own Docker/build process and are not selected by this flag.')}
175
197
  `;
176
198
  const configureHelp = () => `
177
- ${heading('Configuration in v2.1')}
199
+ ${heading('Configuration in v2.2')}
178
200
 
179
201
  Organization provider credentials are configured once as named scopes by an ADMIN.
180
202
  Managers and users do not create organization AWS/NPM/Jenkins/GHCR credentials.
@@ -1 +1 @@
1
- {"version":3,"file":"help-content.js","sourceRoot":"","sources":["../../src/cli/help-content.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"help-content.js","sourceRoot":"","sources":["../../src/cli/help-content.ts"],"names":[],"mappings":"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"}
@@ -139,36 +139,36 @@ const syncAwsNativeAccess = async (user) => {
139
139
  const jenkinsRoleScript = (username, roleName, jobs) => {
140
140
  const pattern = jobs.length ? `^(?:${jobs.map(escapeRegex).join('|')})$` : 'a^';
141
141
  const enc = (v) => Buffer.from(v, 'utf8').toString('base64');
142
- return `
143
- import hudson.model.Item
144
- import hudson.model.Run
145
- import hudson.security.Permission
146
- import jenkins.model.Jenkins
147
-
148
- ${role_strategy_groovy_1.jenkinsRoleStrategyCompatGroovy}
149
- def decode = { String value -> new String(value.decodeBase64(), 'UTF-8') }
150
- def username = decode('${enc(username)}')
151
- def roleName = decode('${enc(roleName)}')
152
- def pattern = decode('${enc(pattern)}')
153
- def j = Jenkins.get()
154
- def strategy = j.authorizationStrategy
155
- indraqRequireRoleStrategy(strategy)
156
- def map = strategy.getRoleMap(indraqRoleType('Project'))
157
- def old = map.getRole(roleName)
158
- if (old != null) map.removeRole(old)
159
- if (pattern != 'a^') {
160
- Set<Permission> permissions = new HashSet<Permission>()
161
- permissions.add(Item.DISCOVER)
162
- permissions.add(Item.READ)
163
- permissions.add(Item.BUILD)
164
- permissions.add(Item.CANCEL)
165
- permissions.add(Item.WORKSPACE)
166
- def role = indraqNewRole(roleName, pattern, permissions)
167
- map.addRole(role)
168
- indraqAssignRole(map, role, username)
169
- }
170
- j.save()
171
- println 'OK|' + roleName + '|' + pattern
142
+ return `
143
+ import hudson.model.Item
144
+ import hudson.model.Run
145
+ import hudson.security.Permission
146
+ import jenkins.model.Jenkins
147
+
148
+ ${role_strategy_groovy_1.jenkinsRoleStrategyCompatGroovy}
149
+ def decode = { String value -> new String(value.decodeBase64(), 'UTF-8') }
150
+ def username = decode('${enc(username)}')
151
+ def roleName = decode('${enc(roleName)}')
152
+ def pattern = decode('${enc(pattern)}')
153
+ def j = Jenkins.get()
154
+ def strategy = j.authorizationStrategy
155
+ indraqRequireRoleStrategy(strategy)
156
+ def map = strategy.getRoleMap(indraqRoleType('Project'))
157
+ def old = map.getRole(roleName)
158
+ if (old != null) map.removeRole(old)
159
+ if (pattern != 'a^') {
160
+ Set<Permission> permissions = new HashSet<Permission>()
161
+ permissions.add(Item.DISCOVER)
162
+ permissions.add(Item.READ)
163
+ permissions.add(Item.BUILD)
164
+ permissions.add(Item.CANCEL)
165
+ permissions.add(Item.WORKSPACE)
166
+ def role = indraqNewRole(roleName, pattern, permissions)
167
+ map.addRole(role)
168
+ indraqAssignRole(map, role, username)
169
+ }
170
+ j.save()
171
+ println 'OK|' + roleName + '|' + pattern
172
172
  `;
173
173
  };
174
174
  const syncJenkinsNativeAccess = async (user) => {
@@ -1 +1 @@
1
- {"version":3,"file":"route53-lookup.service.js","sourceRoot":"","sources":["../../../../src/modules/aws/services/route53-lookup.service.ts"],"names":[],"mappings":";;;AAAA,8DAAyH;AACzH,8EAA+E;AAC/E,6EAA6E;AAC7E,sFAAkF;AAElF,MAAM,SAAS,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC3F,MAAM,MAAM,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAQxE,MAAM,sBAAsB,GAAG,KAAK,EAAE,MAAc,EAAsC,EAAE;IACjG,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACjC,2EAA2E;IAC3E,4EAA4E;IAC5E,yCAAyC;IACzC,IAAI,IAAA,sCAAmB,GAAE,EAAE,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,IAAA,4CAAoB,GAAE,CAAC;YAC/C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,KAAK,IAAI,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,MAAM,CAAE,QAAQ,CAAC,MAAc,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;YACtM,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,MAAM,GAAG,UAAU,CAAC,MAAmE,CAAC;gBAC9F,OAAO;oBACL,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;oBACnC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;oBAC9C,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,UAAU,IAAI,GAAG,CAA2C,EAAE;iBAC3I,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,kEAAkE,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAA,yCAAqB,EAAC,qDAAqD,CAAC,CAAC;IACvG,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,wCAAsB,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC,WAAW,IAAI,EAAE,CAAC;SAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAG,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,IAAK,CAAC,EAAE,CAAC,CAAC;SAC7D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;SACjE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,+CAA6B,CAAC;YAClE,YAAY,EAAE,IAAI,CAAC,EAAE;YACrB,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG;YAC7D,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC,CAAC;QACJ,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC;QACjG,IAAI,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AArCW,QAAA,sBAAsB,0BAqCjC;AAEK,MAAM,oBAAoB,GAAG,KAAK,EAAE,MAAc,EAA+B,EAAE;IACxF,MAAM,KAAK,GAAG,MAAM,IAAA,8BAAsB,EAAC,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,MAAM,8DAA8D,MAAM,qDAAqD,CAAC,CAAC;IACtM,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAJW,QAAA,oBAAoB,wBAI/B"}
1
+ {"version":3,"file":"route53-lookup.service.js","sourceRoot":"","sources":["../../../../src/modules/aws/services/route53-lookup.service.ts"],"names":[],"mappings":"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"}
@@ -34,5 +34,9 @@ export declare const listProjects: (options: ListCliOptions) => Promise<void>;
34
34
  export declare const linkProject: (options?: ListCliOptions) => Promise<void>;
35
35
  export declare const addProjectUser: () => Promise<void>;
36
36
  export declare const deleteProjectUser: () => Promise<void>;
37
+ export declare const renameProject: (newNameArg?: string) => Promise<void>;
38
+ export declare const archiveProject: (yes?: boolean) => Promise<void>;
39
+ export declare const restoreProject: () => Promise<void>;
40
+ export declare const deleteProject: (yes?: boolean) => Promise<void>;
37
41
  export {};
38
42
  //# sourceMappingURL=cloud.command.d.ts.map