feat(bitdefender): complete Accounts module (build-out 1/N)
- Completed Accounts module for bitdefender skill (GravityZone Public API) - Added 5 methods: getAccountDetails, createAccount, updateAccount, deleteAccount, configureNotificationsSettings - Write methods require --confirm; raw also gates createAccount/updateAccount/configureNotificationsSettings - Param shapes validated against official docs and safe validation probes - configureNotificationsSettings is a setter with no required param; warning documented against empty payload on live tenant - selftest 42 -> 49 passing Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -265,6 +265,88 @@ def cmd_notif_settings(client, args):
|
||||
_emit(client.get_notifications_settings(), args.json, _print_kv)
|
||||
|
||||
|
||||
def cmd_account(client, args):
|
||||
_emit(client.get_account_details(args.account_id), args.json, _print_kv)
|
||||
|
||||
|
||||
def _load_json_arg(raw, label):
|
||||
"""Parse a JSON-object CLI arg; returns (obj, error_rc). error_rc is None on ok."""
|
||||
if raw is None:
|
||||
return {}, None
|
||||
try:
|
||||
obj = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
print(f"[ERROR] --{label} is not valid JSON: {exc}", file=sys.stderr)
|
||||
return None, 2
|
||||
if not isinstance(obj, dict):
|
||||
print(f"[ERROR] --{label} must be a JSON object.", file=sys.stderr)
|
||||
return None, 2
|
||||
return obj, None
|
||||
|
||||
|
||||
def cmd_account_create(client, args):
|
||||
rights, rc = _load_json_arg(args.rights_json, "rights-json")
|
||||
if rc:
|
||||
return rc
|
||||
extra, rc = _load_json_arg(args.extra_json, "extra-json")
|
||||
if rc:
|
||||
return rc
|
||||
profile = {}
|
||||
if args.full_name:
|
||||
profile["fullName"] = args.full_name
|
||||
if args.language:
|
||||
profile["language"] = args.language
|
||||
if args.timezone:
|
||||
profile["timezone"] = args.timezone
|
||||
if not _gated(f"create account {args.email} (role={args.role})", args.confirm):
|
||||
return 3
|
||||
result = client.create_account(
|
||||
email=args.email, password=args.password, username=args.username,
|
||||
role=args.role, profile=profile or None, rights=rights or None,
|
||||
extra=extra or None,
|
||||
)
|
||||
_emit({"createdAccount": args.email, "result": result}, args.json, _print_kv)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_account_update(client, args):
|
||||
fields, rc = _load_json_arg(args.set_json, "set-json")
|
||||
if rc:
|
||||
return rc
|
||||
if not fields:
|
||||
print("[ERROR] --set-json (object of fields to change) is required.",
|
||||
file=sys.stderr)
|
||||
return 2
|
||||
if not _gated(f"update account {args.id} fields={list(fields)}", args.confirm):
|
||||
return 3
|
||||
result = client.update_account(args.id, fields)
|
||||
_emit({"updatedAccount": args.id, "result": result}, args.json, _print_kv)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_account_delete(client, args):
|
||||
if not _gated(f"delete account {args.id}", args.confirm):
|
||||
return 3
|
||||
result = client.delete_account(args.id)
|
||||
_emit({"deletedAccount": args.id, "result": result}, args.json, _print_kv)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_notif_configure(client, args):
|
||||
settings, rc = _load_json_arg(args.settings_json, "settings-json")
|
||||
if rc:
|
||||
return rc
|
||||
if not settings:
|
||||
print("[ERROR] --settings-json (the settings object) is required.",
|
||||
file=sys.stderr)
|
||||
return 2
|
||||
if not _gated(f"configure notification settings ({list(settings)})", args.confirm):
|
||||
return 3
|
||||
result = client.configure_notifications_settings(settings)
|
||||
_emit({"notificationsConfigured": True, "result": result}, args.json, _print_kv)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_scan_tasks(client, args):
|
||||
_emit(client.list_scan_tasks(page=args.page, per_page=args.per_page),
|
||||
args.json, _print_scan_tasks_table)
|
||||
@@ -395,7 +477,8 @@ def cmd_make_group(client, args):
|
||||
DESTRUCTIVE_RAW_PATTERNS = ("delete", "createuninstall", "createremove",
|
||||
"createreconfigure", "isolat", "addtoblocklist",
|
||||
"removefromblocklist", "assignpolicy",
|
||||
"setpushevent")
|
||||
"setpushevent", "createaccount", "updateaccount",
|
||||
"configurenotif")
|
||||
|
||||
|
||||
def _is_destructive_method(method: str) -> bool:
|
||||
@@ -545,6 +628,11 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
sub.add_parser("notif-settings", help="Show notification settings.",
|
||||
parents=[common])
|
||||
|
||||
sp = sub.add_parser("account",
|
||||
help="Account detail (no id = the API key's own account).",
|
||||
parents=[common])
|
||||
sp.add_argument("account_id", nargs="?", help="Account id (optional).")
|
||||
|
||||
sp = sub.add_parser("scan-tasks", help="List scan tasks.", parents=[common])
|
||||
sp.add_argument("--page", type=int, default=1)
|
||||
sp.add_argument("--per-page", type=int, default=100)
|
||||
@@ -674,6 +762,36 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
help="Inherit the policy from the parent group.")
|
||||
sp.add_argument("--confirm", action="store_true")
|
||||
|
||||
sp = sub.add_parser("account-create", help="Create a console account (gated).",
|
||||
parents=[common])
|
||||
sp.add_argument("--email", required=True)
|
||||
sp.add_argument("--password")
|
||||
sp.add_argument("--username")
|
||||
sp.add_argument("--role", type=int, help="Numeric role id (see docs/console).")
|
||||
sp.add_argument("--full-name")
|
||||
sp.add_argument("--language", help="e.g. en_US")
|
||||
sp.add_argument("--timezone", help="e.g. America/Phoenix")
|
||||
sp.add_argument("--rights-json", help="JSON object of rights flags.")
|
||||
sp.add_argument("--extra-json", help="JSON object of any extra documented fields.")
|
||||
sp.add_argument("--confirm", action="store_true")
|
||||
|
||||
sp = sub.add_parser("account-update", help="Update a console account (gated).",
|
||||
parents=[common])
|
||||
sp.add_argument("--id", required=True, help="accountId.")
|
||||
sp.add_argument("--set-json", required=True, help="JSON object of fields to change.")
|
||||
sp.add_argument("--confirm", action="store_true")
|
||||
|
||||
sp = sub.add_parser("account-delete", help="Delete a console account (gated).",
|
||||
parents=[common])
|
||||
sp.add_argument("--id", required=True, help="accountId.")
|
||||
sp.add_argument("--confirm", action="store_true")
|
||||
|
||||
sp = sub.add_parser("notif-configure",
|
||||
help="Set notification settings (gated).", parents=[common])
|
||||
sp.add_argument("--settings-json", required=True,
|
||||
help="JSON object of the notification settings to apply.")
|
||||
sp.add_argument("--confirm", action="store_true")
|
||||
|
||||
sp = sub.add_parser("push-set",
|
||||
help="Configure the push event service (gated).",
|
||||
parents=[common])
|
||||
@@ -705,6 +823,11 @@ HANDLERS = {
|
||||
"reports": cmd_reports,
|
||||
"accounts": cmd_accounts,
|
||||
"notif-settings": cmd_notif_settings,
|
||||
"account": cmd_account,
|
||||
"account-create": cmd_account_create,
|
||||
"account-update": cmd_account_update,
|
||||
"account-delete": cmd_account_delete,
|
||||
"notif-configure": cmd_notif_configure,
|
||||
"scan-tasks": cmd_scan_tasks,
|
||||
"push-settings": cmd_push_settings,
|
||||
"push-stats": cmd_push_stats,
|
||||
|
||||
Reference in New Issue
Block a user