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:
2026-06-21 10:22:01 -07:00
parent 4cf34f5221
commit 8a64bc48e6
5 changed files with 217 additions and 9 deletions

View File

@@ -700,6 +700,78 @@ class GravityZoneClient:
"accounts", "getNotificationsSettings", {}
) or {}
def get_account_details(self, account_id: Optional[str] = None) -> dict:
"""Account detail (accounts.getAccountDetails). With no id, returns the
API key owner's own account (verified live)."""
params: dict = {}
if account_id:
params["accountId"] = account_id
return self._jsonrpc_request("accounts", "getAccountDetails", params) or {}
def create_account(
self,
email: str,
password: Optional[str] = None,
username: Optional[str] = None,
role: Optional[int] = None,
profile: Optional[dict] = None,
rights: Optional[dict] = None,
phone_number: Optional[dict] = None,
extra: Optional[dict] = None,
) -> Any:
"""Create a console account (accounts.createAccount). STATE-CHANGING.
`email` is required (verified). Documented params: userName, password,
role (int), profile{fullName,language,timezone},
phoneNumber{countryCode,subscriberNumber}, rights{manageInventory,
managePoliciesRead/Write,...}. `extra` merges any additional documented
fields verbatim. Gate at the call site behind --confirm.
Docs: bitdefender.com/business/support/en/77212-125284-createaccount.html
"""
params: dict = {"email": email}
if username is not None:
params["userName"] = username
if password is not None:
params["password"] = password
if role is not None:
params["role"] = role
if profile is not None:
params["profile"] = profile
if rights is not None:
params["rights"] = rights
if phone_number is not None:
params["phoneNumber"] = phone_number
if extra:
params.update(extra)
return self._jsonrpc_request("accounts", "createAccount", params)
def update_account(self, account_id: str, fields: dict) -> Any:
"""Update a console account (accounts.updateAccount). STATE-CHANGING.
`accountId` is required (verified); `fields` are the documented
account attributes to change (same shape as create, minus email).
Gate at the call site behind --confirm.
"""
params: dict = {"accountId": account_id}
params.update(fields or {})
return self._jsonrpc_request("accounts", "updateAccount", params)
def delete_account(self, account_id: str) -> Any:
"""Delete a console account (accounts.deleteAccount). STATE-CHANGING.
`accountId` required (verified). Gate at the call site behind --confirm."""
return self._jsonrpc_request(
"accounts", "deleteAccount", {"accountId": account_id}
)
def configure_notifications_settings(self, settings: dict) -> Any:
"""Set notification settings (accounts.configureNotificationsSettings).
STATE-CHANGING — there are NO required params, so an empty payload is
accepted; the caller must pass the intended settings object. Gate at the
call site behind --confirm."""
return self._jsonrpc_request(
"accounts", "configureNotificationsSettings", settings or {}
)
# ======================================================================
# PUSH EVENT SERVICE (module `/push`)
# ----------------------------------------------------------------------