@jacebenson/jsn 4.3.7 → 4.3.8

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.
@@ -1,4 +1,9 @@
1
- import { formatRecordForDisplay, getStringField, resolveFieldsParam } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, resolveFieldsParam, assertSafeExactMatch, confirmDelete, quoteShellArg } from '../helpers.js';
2
+ import { declareCapabilities } from '../capabilities.js';
3
+
4
+ // add/remove write sys_user_grmember; the mutation guard (instance +
5
+ // read-only profile) and the delete confirmation both key off this.
6
+ declareCapabilities('groupmembers', { mutationSubcommands: ['add', 'remove'] });
2
7
 
3
8
  export function groupMembersCmd(wrap) {
4
9
  return {
@@ -42,6 +47,8 @@ export function groupMembersCmd(wrap) {
42
47
  handler: wrap(async (argv, app) => {
43
48
  const groupName = argv.group;
44
49
  const userName = argv.user;
50
+ assertSafeExactMatch(groupName);
51
+ assertSafeExactMatch(userName);
45
52
 
46
53
  // Resolve group sys_id
47
54
  const isGroupSysID = groupName.length === 32 && /^[0-9a-fA-F]+$/.test(groupName);
@@ -86,7 +93,7 @@ export function groupMembersCmd(wrap) {
86
93
  summary: `Added ${userName} to ${groupName}`,
87
94
  breadcrumbs: [
88
95
  { action: 'list', cmd: `jsn groupmembers list --query "group.name=${groupName}"`, description: 'List group members' },
89
- { action: 'remove', cmd: `jsn groupmembers remove --group "${groupName}" --user "${userName}"`, description: 'Remove this member' },
96
+ { action: 'remove', cmd: `jsn groupmembers remove --group ${quoteShellArg(groupName)} --user ${quoteShellArg(userName)}`, description: 'Remove this member' },
90
97
  ],
91
98
  });
92
99
  }),
@@ -96,10 +103,18 @@ export function groupMembersCmd(wrap) {
96
103
  describe: 'Remove a user from a group',
97
104
  builder: (y) => y
98
105
  .option('group', { alias: 'g', type: 'string', demandOption: true, describe: 'Group name or sys_id (required)' })
99
- .option('user', { alias: 'u', type: 'string', demandOption: true, describe: 'Username or sys_id (required)' }),
106
+ .option('user', { alias: 'u', type: 'string', demandOption: true, describe: 'Username or sys_id (required)' })
107
+ .option('force', { type: 'boolean', describe: 'Skip the confirmation prompt (removal)' }),
100
108
  handler: wrap(async (argv, app) => {
101
109
  const groupName = argv.group;
102
110
  const userName = argv.user;
111
+ assertSafeExactMatch(groupName);
112
+ assertSafeExactMatch(userName);
113
+ // Confirm before any lookup: a refused confirmation must not
114
+ // touch the instance at all.
115
+ await confirmDelete(app, argv, `Remove ${userName} from group ${groupName}`, {
116
+ rerun: ['groupmembers', 'remove', '--group', groupName, '--user', userName],
117
+ });
103
118
 
104
119
  // Resolve group sys_id
105
120
  const isGroupSysID = groupName.length === 32 && /^[0-9a-fA-F]+$/.test(groupName);
@@ -142,7 +157,7 @@ export function groupMembersCmd(wrap) {
142
157
  summary: `Removed ${userName} from ${groupName}`,
143
158
  breadcrumbs: [
144
159
  { action: 'list', cmd: `jsn groupmembers list --query "group.name=${groupName}"`, description: 'List group members' },
145
- { action: 'add', cmd: `jsn groupmembers add --group "${groupName}" --user "${userName}"`, description: 'Add user back to group' },
160
+ { action: 'add', cmd: `jsn groupmembers add --group ${quoteShellArg(groupName)} --user ${quoteShellArg(userName)}`, description: 'Add user back to group' },
146
161
  ],
147
162
  });
148
163
  }),
@@ -1,4 +1,9 @@
1
- import { formatRecordForDisplay, getStringField, resolveFieldsParam, assertSafeExactMatch } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, resolveFieldsParam, assertSafeExactMatch, confirmDelete, quoteShellArg } from '../helpers.js';
2
+ import { declareCapabilities } from '../capabilities.js';
3
+
4
+ // add/remove write sys_group_has_role; the mutation guard (instance +
5
+ // read-only profile) and the delete confirmation both key off this.
6
+ declareCapabilities('grouproles', { mutationSubcommands: ['add', 'remove'] });
2
7
 
3
8
  export function groupRolesCmd(wrap) {
4
9
  return {
@@ -88,7 +93,7 @@ export function groupRolesCmd(wrap) {
88
93
  summary: `Added role ${roleName} to ${groupName}`,
89
94
  breadcrumbs: [
90
95
  { action: 'list', cmd: `jsn grouproles list --query "group.name=${groupName}"`, description: 'List group roles' },
91
- { action: 'remove', cmd: `jsn grouproles remove --group "${groupName}" --role "${roleName}"`, description: 'Remove this role' },
96
+ { action: 'remove', cmd: `jsn grouproles remove --group ${quoteShellArg(groupName)} --role ${quoteShellArg(roleName)}`, description: 'Remove this role' },
92
97
  ],
93
98
  });
94
99
  }),
@@ -98,12 +103,18 @@ export function groupRolesCmd(wrap) {
98
103
  describe: 'Remove a role from a group',
99
104
  builder: (y) => y
100
105
  .option('group', { alias: 'g', type: 'string', demandOption: true, describe: 'Group name or sys_id (required)' })
101
- .option('role', { alias: 'r', type: 'string', demandOption: true, describe: 'Role name or sys_id (required)' }),
106
+ .option('role', { alias: 'r', type: 'string', demandOption: true, describe: 'Role name or sys_id (required)' })
107
+ .option('force', { type: 'boolean', describe: 'Skip the confirmation prompt (removal)' }),
102
108
  handler: wrap(async (argv, app) => {
103
109
  const groupName = argv.group;
104
110
  const roleName = argv.role;
105
111
  assertSafeExactMatch(groupName);
106
112
  assertSafeExactMatch(roleName);
113
+ // Confirm before any lookup: a refused confirmation must not
114
+ // touch the instance at all.
115
+ await confirmDelete(app, argv, `Remove role ${roleName} from group ${groupName}`, {
116
+ rerun: ['grouproles', 'remove', '--group', groupName, '--role', roleName],
117
+ });
107
118
 
108
119
  // Resolve group sys_id
109
120
  const isGroupSysID = groupName.length === 32 && /^[0-9a-fA-F]+$/.test(groupName);
@@ -146,7 +157,7 @@ export function groupRolesCmd(wrap) {
146
157
  summary: `Removed role ${roleName} from ${groupName}`,
147
158
  breadcrumbs: [
148
159
  { action: 'list', cmd: `jsn grouproles list --query "group.name=${groupName}"`, description: 'List group roles' },
149
- { action: 'add', cmd: `jsn grouproles add --group "${groupName}" --role "${roleName}"`, description: 'Add role back to group' },
160
+ { action: 'add', cmd: `jsn grouproles add --group ${quoteShellArg(groupName)} --role ${quoteShellArg(roleName)}`, description: 'Add role back to group' },
150
161
  ],
151
162
  });
152
163
  }),