diff --git a/README.md b/README.md index 3a12ce6..e545016 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ agents = siem_api_client.agents.get() ### Managed SAT ### # sends GET request to /company/companies/{id} endpoint -company = sat_api_client.company.companies.id(250).get() +accounts = sat_api_client.accounts.id("abc123").get() ### SIEM ### diff --git a/src/pyhuntress/clients/huntress_client.py b/src/pyhuntress/clients/huntress_client.py index 329f537..b3c9bba 100644 --- a/src/pyhuntress/clients/huntress_client.py +++ b/src/pyhuntress/clients/huntress_client.py @@ -37,15 +37,16 @@ class HuntressClient(ABC): def _get_url(self) -> str: pass - def _make_request( # noqa: C901 + def _make_request( self, method: RequestMethod, url: str, data: RequestData | None = None, + rawdata: RequestData | None = None, params: RequestParams | None = None, headers: dict[str, str] | None = None, retry_count: int = 0, - stream: bool = False, # noqa: FBT001, FBT002 + stream: bool = False, ) -> Response: """ Make an API request using the specified method, endpoint, data, and parameters. @@ -79,6 +80,15 @@ class HuntressClient(ABC): params=cast(dict[str, Any], params or {}), stream=stream, ) + elif rawdata: + response = requests.request( + method, + url, + headers=headers, + data=rawdata, + params=cast(dict[str, Any], params or {}), + stream=stream, + ) else: response = requests.request( method, diff --git a/src/pyhuntress/clients/managedsat_client.py b/src/pyhuntress/clients/managedsat_client.py index c6594c6..5dd2664 100644 --- a/src/pyhuntress/clients/managedsat_client.py +++ b/src/pyhuntress/clients/managedsat_client.py @@ -1,22 +1,21 @@ -import base64 import typing +from datetime import datetime, timedelta, timezone from pyhuntress.clients.huntress_client import HuntressClient from pyhuntress.config import Config if typing.TYPE_CHECKING: - from pyhuntress.endpoints.managedsat.CompanyEndpoint import CompanyEndpoint - from pyhuntress.endpoints.managedsat.ConfigurationsEndpoint import ConfigurationsEndpoint - from pyhuntress.endpoints.managedsat.ExpenseEndpoint import ExpenseEndpoint - from pyhuntress.endpoints.managedsat.FinanceEndpoint import FinanceEndpoint - from pyhuntress.endpoints.managedsat.MarketingEndpoint import MarketingEndpoint - from pyhuntress.endpoints.managedsat.ProcurementEndpoint import ProcurementEndpoint - from pyhuntress.endpoints.managedsat.ProjectEndpoint import ProjectEndpoint - from pyhuntress.endpoints.managedsat.SalesEndpoint import SalesEndpoint - from pyhuntress.endpoints.managedsat.ScheduleEndpoint import ScheduleEndpoint - from pyhuntress.endpoints.managedsat.ServiceEndpoint import ServiceEndpoint - from pyhuntress.endpoints.managedsat.SystemEndpoint import SystemEndpoint - from pyhuntress.endpoints.managedsat.TimeEndpoint import TimeEndpoint + from pyhuntress.endpoints.managedsat.AccountsEndpoint import AccountsEndpoint + from pyhuntress.endpoints.managedsat.UsersEndpoint import UsersEndpoint + from pyhuntress.endpoints.managedsat.AssignmentsEndpoint import AssignmentsEndpoint + from pyhuntress.endpoints.managedsat.EpisodesEndpoint import EpisodesEndpoint + from pyhuntress.endpoints.managedsat.DepartmentsEndpoint import DepartmentsEndpoint + from pyhuntress.endpoints.managedsat.GroupsEndpoint import GroupsEndpoint + from pyhuntress.endpoints.managedsat.LearnersEndpoint import LearnersEndpoint + from pyhuntress.endpoints.managedsat.PhishingCampaignsEndpoint import PhishingCampaignsEndpoint + from pyhuntress.endpoints.managedsat.PhishingCampaignScenariosEndpoint import PhishingCampaignScenariosEndpoint + from pyhuntress.endpoints.managedsat.PhishingAttemptsEndpoint import PhishingAttemptsActionsEndpoint + from pyhuntress.endpoints.managedsat.PhishingScenariosEndpoint import PhishingScenariosEndpoint class ManagedSATCodebaseError(Exception): @@ -32,134 +31,130 @@ class HuntressSATAPIClient(HuntressClient): def __init__( self, - managedsat_url: str, - public_key: str, - private_key: str, + client_id: str, + client_secret: str, + api_scopes: str, ) -> None: """ - Initializes the client with the given credentials and optionally a specific codebase. - If no codebase is given, it tries to get it from the API. + Initializes the client with the given credentials. Parameters: - managedsat_url (str): URL of the Huntress Managed SAT instance. - public_key (str): Your Huntress Managed SAT API Public key. - private_key (str): Your Huntress Managed SAT API Private key. + client_id (str): URL of the Huntress Managed SAT client id. + client_secret (str): Your Huntress Managed SAT API client secret. + api_scopes (str): Your Huntress Managed SAT API scope. """ - self.managedsat_url: str = managedsat_url - self.public_key: str = public_key - self.private_key: str = private_key + self.client_id: str = client_id + self.client_secret: str = client_secret + self.api_scopes: str = api_scopes + self.token_expiry_time: datetime = datetime.now(tz=timezone.utc) + + # Grab first access token + self.access_token: str = self._get_access_token() # Initializing endpoints @property - def company(self) -> "CompanyEndpoint": - from pyhuntress.endpoints.managedsat.CompanyEndpoint import CompanyEndpoint + def accounts(self) -> "AccountsEndpoint": + from pyhuntress.endpoints.managedsat.AccountsEndpoint import AccountsEndpoint - return CompanyEndpoint(self) + return AccountsEndpoint(self) @property - def configurations(self) -> "ConfigurationsEndpoint": - from pyhuntress.endpoints.managedsat.ConfigurationsEndpoint import ConfigurationsEndpoint + def users(self) -> "UsersEndpoint": + from pyhuntress.endpoints.managedsat.UsersEndpoint import UsersEndpoint - return ConfigurationsEndpoint(self) + return UsersEndpoint(self) @property - def expense(self) -> "ExpenseEndpoint": - from pyhuntress.endpoints.managedsat.ExpenseEndpoint import ExpenseEndpoint + def assignments(self) -> "AssignmentsEndpoint": + from pyhuntress.endpoints.managedsat.AssignmentsEndpoint import AssignmentsEndpoint - return ExpenseEndpoint(self) + return AssignmentsEndpoint(self) @property - def finance(self) -> "FinanceEndpoint": - from pyhuntress.endpoints.managedsat.FinanceEndpoint import FinanceEndpoint + def episodes(self) -> "EpisodesEndpoint": + from pyhuntress.endpoints.managedsat.EpisodesEndpoint import EpisodesEndpoint - return FinanceEndpoint(self) + return EpisodesEndpoint(self) @property - def marketing(self) -> "MarketingEndpoint": - from pyhuntress.endpoints.managedsat.MarketingEndpoint import MarketingEndpoint + def departments(self) -> "DepartmentsEndpoint": + from pyhuntress.endpoints.managedsat.DepartmentsEndpoint import DepartmentsEndpoint - return MarketingEndpoint(self) + return DepartmentsEndpoint(self) @property - def procurement(self) -> "ProcurementEndpoint": - from pyhuntress.endpoints.managedsat.ProcurementEndpoint import ProcurementEndpoint + def groups(self) -> "GroupsEndpoint": + from pyhuntress.endpoints.managedsat.GroupsEndpoint import GroupsEndpoint - return ProcurementEndpoint(self) + return GroupsEndpoint(self) @property - def project(self) -> "ProjectEndpoint": - from pyhuntress.endpoints.managedsat.ProjectEndpoint import ProjectEndpoint + def learners(self) -> "LearnersEndpoint": + from pyhuntress.endpoints.managedsat.LearnersEndpoint import LearnersEndpoint - return ProjectEndpoint(self) + return LearnersEndpoint(self) @property - def sales(self) -> "SalesEndpoint": - from pyhuntress.endpoints.managedsat.SalesEndpoint import SalesEndpoint + def phishing_campaigns(self) -> "PhishingCampaignsEndpoint": + from pyhuntress.endpoints.managedsat.PhishingCampaignsEndpoint import PhishingCampaignsEndpoint - return SalesEndpoint(self) + return PhishingCampaignsEndpoint(self) @property - def schedule(self) -> "ScheduleEndpoint": - from pyhuntress.endpoints.managedsat.ScheduleEndpoint import ScheduleEndpoint + def phishing_campaign_scenarios(self) -> "PhishingCampaignScenariosEndpoint": + from pyhuntress.endpoints.managedsat.PhishingCampaignScenariosEndpoint import PhishingCampaignScenariosEndpoint - return ScheduleEndpoint(self) + return PhishingCampaignScenariosEndpoint(self) @property - def service(self) -> "ServiceEndpoint": - from pyhuntress.endpoints.managedsat.ServiceEndpoint import ServiceEndpoint + def phishing_attempts(self) -> "PhishingAttemptsActionsEndpoint": + from pyhuntress.endpoints.managedsat.PhishingAttemptsActionsEndpoint import PhishingAttemptsActionsEndpoint - return ServiceEndpoint(self) + return PhishingAttemptsActionsEndpoint(self) @property - def system(self) -> "SystemEndpoint": - from pyhuntress.endpoints.managedsat.SystemEndpoint import SystemEndpoint + def phishing_scenarios(self) -> "PhishingScenariosEndpoint": + from pyhuntress.endpoints.managedsat.PhishingScenariosEndpoint import PhishingScenariosEndpoint - return SystemEndpoint(self) - - @property - def time(self) -> "TimeEndpoint": - from pyhuntress.endpoints.managedsat.TimeEndpoint import TimeEndpoint - - return TimeEndpoint(self) + return PhishingScenariosEndpoint(self) def _get_url(self) -> str: """ Generates and returns the URL for the Huntress Managed SAT API endpoints based on the company url and codebase. - + This only still exists incase Huntress eventually moves to some client specific URL format Returns: str: API URL. """ - return f"https://{self.managedsat_url}/{self.codebase.strip('/')}/apis/3.0" + return f"https://mycurricula.com/api/v1" - def _try_get_codebase_from_api(self, managedsat_url: str, company_name: str, headers: dict[str, str]) -> str: + def _get_access_token(self) -> str: """ - Tries to retrieve the codebase from the API using the provided company url, company name and headers. - - Parameters: - company_url (str): URL of the company. - company_name (str): Name of the company. - headers (dict[str, str]): Headers to be sent in the request. - - Returns: - str: Codebase string or None if an error occurs. + Performs a request to the ConnectWise Automate API to obtain an access token. """ - url = f"https://{managedsat_url}/login/companyinfo/{company_name}" - response = self._make_request("GET", url, headers=headers) - return response.json().get("Codebase") + token_url = self._get_url().replace("api/v1", "oauth/token") #strip the API endpoints to use the oauth token url + auth_response = self._make_request( + "POST", + token_url, + rawdata={ + "grant_type": "client_credentials", + "client_id": self.client_id, + "client_secret": self.client_secret, + "scope": self.api_scopes + }, + headers={ + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json" + }, + ) + auth_resp_json = auth_response.json() + token = auth_resp_json["access_token"] + expires_in_sec = auth_resp_json["expires_in"] + self.token_expiry_time = datetime.now(tz=timezone.utc) + timedelta(seconds=expires_in_sec) + return token - def _get_auth_string(self) -> str: - """ - Creates and returns the base64 encoded authorization string required for API requests. - - Returns: - str: Base64 encoded authorization string. - """ - return "Basic " + base64.b64encode( - bytes( - f"{self.company_name}+{self.public_key}:{self.private_key}", - encoding="utf8", - ) - ).decode("ascii") + def _refresh_access_token_if_necessary(self): + if datetime.now(tz=timezone.utc) > self.token_expiry_time: + self.access_token = self._get_access_token() def _get_headers(self) -> dict[str, str]: """ @@ -168,8 +163,9 @@ class HuntressSATAPIClient(HuntressClient): Returns: dict[str, str]: Dictionary of headers including Content-Type, Client ID, and Authorization. """ + self._refresh_access_token_if_necessary() return { - "Content-Type": "application/json", - "clientId": self.client_id, - "Authorization": self._get_auth_string(), + "Content-Type": "application/vnd.api+json", + "Accept": "application/vnd.api+json", + "Authorization": f"Bearer {self.access_token}", } diff --git a/src/pyhuntress/endpoints/managedsat/AccountsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsEndpoint.py new file mode 100644 index 0000000..adf247b --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdEndpoint import AccountsIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATAccounts +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsEndpoint( + HuntressEndpoint, + IGettable[SATAccounts, HuntressSATRequestParams], + IPaginateable[SATAccounts, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "accounts", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAccounts) + IPaginateable.__init__(self, SATAccounts) + + def id(self, id: int) -> AccountsIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized AccountsIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + AccountsIdEndpoint: The initialized AccountsIdEndpoint object. + """ + child = AccountsIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATAccounts]: + """ + Performs a GET request against the /accounts endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATData]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATAccounts, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAccounts: + """ + Performs a GET request against the /accounts endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAccountInformation: The parsed response data. + """ + return self._parse_many( + SATAccounts, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdAssignmentsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdAssignmentsEndpoint.py new file mode 100644 index 0000000..7bd3c87 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdAssignmentsEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATAssignments +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdAssignmentsEndpoint( + HuntressEndpoint, + IGettable[SATAssignments, HuntressSATRequestParams], + IPaginateable[SATAssignments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "assignments", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAssignments) + IPaginateable.__init__(self, SATAssignments) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATAssignments]: + """ + Performs a GET request against the /accounts/{id}/assignments endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATAssignments]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATAssignments, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAssignments: + """ + Performs a GET request against the /accounts/{id}/assignments endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAssignmentsInformation: The parsed response data. + """ + return self._parse_many( + SATAssignments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdDepartmentsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdDepartmentsEndpoint.py new file mode 100644 index 0000000..a440163 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdDepartmentsEndpoint.py @@ -0,0 +1,38 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATDepartments +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdDepartmentsEndpoint( + HuntressEndpoint, + IGettable[SATDepartments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "departments", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATDepartments) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATDepartments: + + """ + Performs a GET request against the /accounts/{id}/departments endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATDepartments: The parsed response data. + """ + return self._parse_many( + SATDepartments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdEndpoint.py new file mode 100644 index 0000000..bdcf118 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdEndpoint.py @@ -0,0 +1,56 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdUsersEndpoint import AccountsIdUsersEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdAssignmentsEndpoint import AccountsIdAssignmentsEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdDepartmentsEndpoint import AccountsIdDepartmentsEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdGroupsEndpoint import AccountsIdGroupsEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdLearnersEndpoint import AccountsIdLearnersEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdPhishingCampaignsEndpoint import AccountsIdPhishingCampaignsEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdPhishingScenariosEndpoint import AccountsIdPhishingScenariosEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATAccounts +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdEndpoint( + HuntressEndpoint, + IGettable[SATAccounts, HuntressSATRequestParams], + IPaginateable[SATAccounts, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAccounts) + IPaginateable.__init__(self, SATAccounts) + + self.users = self._register_child_endpoint(AccountsIdUsersEndpoint(client, parent_endpoint=self)) + self.assignments = self._register_child_endpoint(AccountsIdAssignmentsEndpoint(client, parent_endpoint=self)) + self.departments = self._register_child_endpoint(AccountsIdDepartmentsEndpoint(client, parent_endpoint=self)) + self.groups = self._register_child_endpoint(AccountsIdGroupsEndpoint(client, parent_endpoint=self)) + self.learners = self._register_child_endpoint(AccountsIdLearnersEndpoint(client, parent_endpoint=self)) + self.phishing_campaigns = self._register_child_endpoint(AccountsIdPhishingCampaignsEndpoint(client, parent_endpoint=self)) + self.phishing_scenarios = self._register_child_endpoint(AccountsIdPhishingScenariosEndpoint(client, parent_endpoint=self)) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAccounts: + """ + Performs a GET request against the /accounts/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAccountsInformation: The parsed response data. + """ + return self._parse_one( + SATAccounts, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdGroupsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdGroupsEndpoint.py new file mode 100644 index 0000000..2acc017 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdGroupsEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATGroups +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdGroupsEndpoint( + HuntressEndpoint, + IGettable[SATGroups, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "groups", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATGroups) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATGroups: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /accounts/{id}/groups endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATGroups: The parsed response data. + """ + return self._parse_many( + SATGroups, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdLearnersEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdLearnersEndpoint.py new file mode 100644 index 0000000..ce08bc3 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdLearnersEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATLearners +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdLearnersEndpoint( + HuntressEndpoint, + IGettable[SATLearners, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "learners", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATLearners) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATLearners: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /accounts/{id}/learners endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATGSATLearnersroups: The parsed response data. + """ + return self._parse_many( + SATLearners, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdPhishingCampaignsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdPhishingCampaignsEndpoint.py new file mode 100644 index 0000000..308d0fe --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdPhishingCampaignsEndpoint.py @@ -0,0 +1,38 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingCampaigns +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdPhishingCampaignsEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaigns, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "phishing_campaigns", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaigns) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaigns: + + """ + Performs a GET request against the /accounts/{id}/phishing-campaigns endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaigns: The parsed response data. + """ + return self._parse_many( + SATPhishingCampaigns, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdPhishingScenariosEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdPhishingScenariosEndpoint.py new file mode 100644 index 0000000..8cc49aa --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdPhishingScenariosEndpoint.py @@ -0,0 +1,38 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingScenarios +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdPhishingScenariosEndpoint( + HuntressEndpoint, + IGettable[SATPhishingScenarios, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "phishing_scenarios", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingScenarios) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingScenarios: + + """ + Performs a GET request against the /accounts/{id}/phishing-scenarios endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingScenarios: The parsed response data. + """ + return self._parse_many( + SATPhishingScenarios, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AccountsIdUsersEndpoint.py b/src/pyhuntress/endpoints/managedsat/AccountsIdUsersEndpoint.py new file mode 100644 index 0000000..1279bad --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AccountsIdUsersEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATUsers +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AccountsIdUsersEndpoint( + HuntressEndpoint, + IGettable[SATUsers, HuntressSATRequestParams], + IPaginateable[SATUsers, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "users", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATUsers) + IPaginateable.__init__(self, SATUsers) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATUsers]: + """ + Performs a GET request against the /accounts/{id}/users endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATUsers]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATUsers, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATUsers: + """ + Performs a GET request against the /accounts/{id}/users endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATUsersInformation: The parsed response data. + """ + return self._parse_many( + SATUsers, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsEndpoint.py new file mode 100644 index 0000000..3fb4aa5 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.AssignmentsIdEndpoint import AssignmentsIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATAssignments +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsEndpoint( + HuntressEndpoint, + IGettable[SATAssignments, HuntressSATRequestParams], + IPaginateable[SATAssignments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "assignments", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAssignments) + IPaginateable.__init__(self, SATAssignments) + + def id(self, id: int) -> AssignmentsIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized AssignmentsIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + AssignmentsIdEndpoint: The initialized AssignmentsIdEndpoint object. + """ + child = AssignmentsIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATAssignments]: + """ + Performs a GET request against the /assignments endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATData]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATAssignments, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAssignments: + """ + Performs a GET request against the /assignments endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAssignments: The parsed response data. + """ + return self._parse_many( + SATAssignments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsIdCompletionCertificateEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsIdCompletionCertificateEndpoint.py new file mode 100644 index 0000000..9bb8c70 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsIdCompletionCertificateEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATAssignmentsCompletionCertificates +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsIdCompletionCertificateEndpoint( + HuntressEndpoint, + IGettable[SATAssignmentsCompletionCertificates, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "completion-certificate", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAssignmentsCompletionCertificates) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAssignmentsCompletionCertificates: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /assignments/{id}/completion-certificate endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAssignmentsCompletionCertificatesInformation: The parsed response data. + """ + return self._parse_one( + SATAssignmentsCompletionCertificates, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsIdEndpoint.py new file mode 100644 index 0000000..f6b9c84 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsIdEndpoint.py @@ -0,0 +1,83 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.AssignmentsIdLearnersEndpoint import AssignmentsIdLearnersEndpoint +from pyhuntress.endpoints.managedsat.AssignmentsIdLearnerActivityEndpoint import AssignmentsIdLearnerActivityEndpoint +from pyhuntress.endpoints.managedsat.AssignmentsIdCompletionCertificateEndpoint import AssignmentsIdCompletionCertificateEndpoint +from pyhuntress.endpoints.managedsat.AssignmentsIdEnrollmentConditionsEndpoint import AssignmentsIdEnrollmentConditionsEndpoint +from pyhuntress.endpoints.managedsat.AssignmentsIdEnrollmentExtrasEndpoint import AssignmentsIdEnrollmentExtrasEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATAssignments +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsIdEndpoint( + HuntressEndpoint, + IGettable[SATAssignments, HuntressSATRequestParams], + IPaginateable[SATAssignments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAssignments) + IPaginateable.__init__(self, SATAssignments) + + self.learners = self._register_child_endpoint(AssignmentsIdLearnersEndpoint(client, parent_endpoint=self)) + self.learner_activity = self._register_child_endpoint(AssignmentsIdLearnerActivityEndpoint(client, parent_endpoint=self)) + self.completion_certificate = self._register_child_endpoint(AssignmentsIdCompletionCertificateEndpoint(client, parent_endpoint=self)) + self.enrollment_conditions = self._register_child_endpoint(AssignmentsIdEnrollmentConditionsEndpoint(client, parent_endpoint=self)) + self.enrollment_extras = self._register_child_endpoint(AssignmentsIdEnrollmentExtrasEndpoint(client, parent_endpoint=self)) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATAssignments]: + """ + Performs a GET request against the /assignments/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATAssignments]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATAssignments, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAssignments: + """ + Performs a GET request against the /assignments/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAssignmentsInformation: The parsed response data. + """ + return self._parse_one( + SATAssignments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsIdEnrollmentConditionsEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsIdEnrollmentConditionsEndpoint.py new file mode 100644 index 0000000..eafdfcd --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsIdEnrollmentConditionsEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATAssignments +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsIdEnrollmentConditionsEndpoint( + HuntressEndpoint, + IGettable[SATAssignments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "enrollment-conditions", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAssignments) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAssignments: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /assignments/{id}/enrollment-conditions endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAssignmentsInformation: The parsed response data. + """ + return self._parse_many( + SATAssignments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsIdEnrollmentExtrasEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsIdEnrollmentExtrasEndpoint.py new file mode 100644 index 0000000..e115948 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsIdEnrollmentExtrasEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATAssignments +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsIdEnrollmentExtrasEndpoint( + HuntressEndpoint, + IGettable[SATAssignments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "enrollment-extras", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATAssignments) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATAssignments: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /assignments/{id}/enrollment-extras endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAssignmentsInformation: The parsed response data. + """ + return self._parse_many( + SATAssignments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsIdLearnerActivityEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsIdLearnerActivityEndpoint.py new file mode 100644 index 0000000..0b17709 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsIdLearnerActivityEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATLearnerActivities +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsIdLearnerActivityEndpoint( + HuntressEndpoint, + IGettable[SATLearnerActivities, HuntressSATRequestParams], + IPaginateable[SATLearnerActivities, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "learner-activity", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATLearnerActivities) + IPaginateable.__init__(self, SATLearnerActivities) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATLearnerActivities]: + """ + Performs a GET request against the /assignments/{id}/learner-activity endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATLearnerActivities]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATLearnerActivities, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATLearnerActivities: + """ + Performs a GET request against the /assignments/{id}/learner-activity endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATLearnerActivitiesInformation: The parsed response data. + """ + return self._parse_many( + SATLearnerActivities, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/AssignmentsIdLearnersEndpoint.py b/src/pyhuntress/endpoints/managedsat/AssignmentsIdLearnersEndpoint.py new file mode 100644 index 0000000..ccec1ae --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/AssignmentsIdLearnersEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATLearners +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class AssignmentsIdLearnersEndpoint( + HuntressEndpoint, + IGettable[SATLearners, HuntressSATRequestParams], + IPaginateable[SATLearners, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "learners", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATLearners) + IPaginateable.__init__(self, SATLearners) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATLearners]: + """ + Performs a GET request against the /assignments/{id}/learners endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATLearners]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATLearners, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATLearners: + """ + Performs a GET request against the /assignments/{id}/learners endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATLearnersInformation: The parsed response data. + """ + return self._parse_many( + SATLearners, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/DepartmentsEndpoint.py b/src/pyhuntress/endpoints/managedsat/DepartmentsEndpoint.py new file mode 100644 index 0000000..0a73260 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/DepartmentsEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.DepartmentsIdEndpoint import DepartmentsIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATDepartments +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class DepartmentsEndpoint( + HuntressEndpoint, + IGettable[SATDepartments, HuntressSATRequestParams], + IPaginateable[SATDepartments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "departments", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATDepartments) + IPaginateable.__init__(self, SATDepartments) + + def id(self, id: int) -> DepartmentsIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized DepartmentsIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + DepartmentsIdEndpoint: The initialized DepartmentsIdEndpoint object. + """ + child = DepartmentsIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATDepartments]: + """ + Performs a GET request against the /departments endpoitments endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATDepartments]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATDepartments, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATDepartments: + """ + Performs a GET request against the /departments endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATDepartments: The parsed response data. + """ + return self._parse_many( + SATDepartments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/DepartmentsIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/DepartmentsIdEndpoint.py new file mode 100644 index 0000000..605d992 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/DepartmentsIdEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATDepartments +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class DepartmentsIdEndpoint( + HuntressEndpoint, + IGettable[SATDepartments, HuntressSATRequestParams], + IPaginateable[SATDepartments, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATDepartments) + IPaginateable.__init__(self, SATDepartments) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATDepartments]: + """ + Performs a GET request against the /departments/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATDepartments]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATDepartments, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATDepartments: + """ + Performs a GET request against the /departments/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATDepartments: The parsed response data. + """ + return self._parse_one( + SATDepartments, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/EpisodesEndpoint.py b/src/pyhuntress/endpoints/managedsat/EpisodesEndpoint.py new file mode 100644 index 0000000..7e76cac --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/EpisodesEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.EpisodesIdEndpoint import EpisodesIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATEpisodes +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class EpisodesEndpoint( + HuntressEndpoint, + IGettable[SATEpisodes, HuntressSATRequestParams], + IPaginateable[SATEpisodes, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "episodes", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATEpisodes) + IPaginateable.__init__(self, SATEpisodes) + + def id(self, id: int) -> EpisodesIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized EpisodesIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + EpisodesIdEndpoint: The initialized EpisodesIdEndpoint object. + """ + child = EpisodesIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATEpisodes]: + """ + Performs a GET request against the /episodes endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATData]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATEpisodes, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATEpisodes: + """ + Performs a GET request against the /episodes endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATEpisodes: The parsed response data. + """ + return self._parse_many( + SATEpisodes, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/EpisodesIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/EpisodesIdEndpoint.py new file mode 100644 index 0000000..f35a6dd --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/EpisodesIdEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATEpisodes +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class EpisodesIdEndpoint( + HuntressEndpoint, + IGettable[SATEpisodes, HuntressSATRequestParams], + IPaginateable[SATEpisodes, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATEpisodes) + IPaginateable.__init__(self, SATEpisodes) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATEpisodes]: + """ + Performs a GET request against the /episodes/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATEpisodes]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATEpisodes, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATEpisodes: + """ + Performs a GET request against the /episodes/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATEpisodes: The parsed response data. + """ + return self._parse_one( + SATEpisodes, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/GroupsEndpoint.py b/src/pyhuntress/endpoints/managedsat/GroupsEndpoint.py new file mode 100644 index 0000000..5c59708 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/GroupsEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.GroupsIdEndpoint import GroupsIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATGroups +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class GroupsEndpoint( + HuntressEndpoint, + IGettable[SATGroups, HuntressSATRequestParams], + IPaginateable[SATGroups, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "groups", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATGroups) + IPaginateable.__init__(self, SATGroups) + + def id(self, id: int) -> GroupsIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized GroupsIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + GroupsIdEndpoint: The initialized GroupsIdEndpoint object. + """ + child = GroupsIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATGroups]: + """ + Performs a GET request against the /groups endpoitments endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATGroups]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATGroups, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATGroups: + """ + Performs a GET request against the /groups endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATGroups: The parsed response data. + """ + return self._parse_many( + SATGroups, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/GroupsIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/GroupsIdEndpoint.py new file mode 100644 index 0000000..4773819 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/GroupsIdEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATGroups +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class GroupsIdEndpoint( + HuntressEndpoint, + IGettable[SATGroups, HuntressSATRequestParams], + IPaginateable[SATGroups, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATGroups) + IPaginateable.__init__(self, SATGroups) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATGroups]: + """ + Performs a GET request against the /groups/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATGroups]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATGroups, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATGroups: + """ + Performs a GET request against the /groups/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATGroups: The parsed response data. + """ + return self._parse_one( + SATGroups, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/LearnersEndpoint.py b/src/pyhuntress/endpoints/managedsat/LearnersEndpoint.py new file mode 100644 index 0000000..78aa1bd --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/LearnersEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.LearnersIdEndpoint import LearnersIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATLearners +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class LearnersEndpoint( + HuntressEndpoint, + IGettable[SATLearners, HuntressSATRequestParams], + IPaginateable[SATLearners, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "learners", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATLearners) + IPaginateable.__init__(self, SATLearners) + + def id(self, id: int) -> LearnersIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized LearnersIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + LearnersIdEndpoint: The initialized LearnersIdEndpoint object. + """ + child = LearnersIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATLearners]: + """ + Performs a GET request against the /learners endpoitments endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATLearners]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATLearners, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATLearners: + """ + Performs a GET request against the /learners endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATLearners: The parsed response data. + """ + return self._parse_many( + SATLearners, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/LearnersIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/LearnersIdEndpoint.py new file mode 100644 index 0000000..bfe18b1 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/LearnersIdEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATLearners +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class LearnersIdEndpoint( + HuntressEndpoint, + IGettable[SATLearners, HuntressSATRequestParams], + IPaginateable[SATLearners, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATLearners) + IPaginateable.__init__(self, SATLearners) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATLearners]: + """ + Performs a GET request against the /learners/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATLearners]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATLearners, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATLearners: + """ + Performs a GET request against the /learners/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATLearners: The parsed response data. + """ + return self._parse_one( + SATLearners, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingAttemptsActionsEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingAttemptsActionsEndpoint.py new file mode 100644 index 0000000..cde4d3b --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingAttemptsActionsEndpoint.py @@ -0,0 +1,21 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingAttemptsActionsReportEndpoint import PhishingAttemptsActionsReportEndpoint +from pyhuntress.interfaces import ( + IPostable, +) +from pyhuntress.models.managedsat import SATPhishingAttemptsReport +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingAttemptsActionsEndpoint( + HuntressEndpoint, + IPostable[SATPhishingAttemptsReport, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "actions", parent_endpoint=parent_endpoint) + IPostable.__init__(self, SATPhishingAttemptsReport) + + self.report = self._register_child_endpoint(PhishingAttemptsActionsReportEndpoint(client, parent_endpoint=self)) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingAttemptsActionsReportEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingAttemptsActionsReportEndpoint.py new file mode 100644 index 0000000..ae17225 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingAttemptsActionsReportEndpoint.py @@ -0,0 +1,30 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IPostable, +) +from pyhuntress.models.managedsat import SATPhishingAttemptsReport +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingAttemptsActionsReportEndpoint( + HuntressEndpoint, + IPostable[SATPhishingAttemptsReport, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "report", parent_endpoint=parent_endpoint) + IPostable.__init__(self, SATPhishingAttemptsReport) + +# def post(self, data: JSON | None = None, params: HuntressSATRequestParams | None = None) -> SATUsers: +# """ +# Performs a POST request against the /company/companies endpoint. +# +# Parameters: +# data (dict[str, Any]): The data to send in the request body. +# params (dict[str, int | str]): The parameters to send in the request query string. +# Returns: +# SATUsers: The parsed response data. +# """ +# return self._parse_one(SATUsers, super()._make_request("POST", data=data, params=params).json()) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingAttemptsEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingAttemptsEndpoint.py new file mode 100644 index 0000000..050987b --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingAttemptsEndpoint.py @@ -0,0 +1,21 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingAttemptsActionsEndpoint import PhishingAttemptsActionsEndpoint +from pyhuntress.interfaces import ( + IPostable, +) +from pyhuntress.models.managedsat import SATPhishingAttemptsReport +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingAttemptsActionsEndpoint( + HuntressEndpoint, + IPostable[SATPhishingAttemptsReport, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "phishing-attempts", parent_endpoint=parent_endpoint) + IPostable.__init__(self, SATPhishingAttemptsReport) + + self.actions = self._register_child_endpoint(PhishingAttemptsActionsEndpoint(client, parent_endpoint=self)) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosEndpoint.py new file mode 100644 index 0000000..7fff65d --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignScenariosIdEndpoint import PhishingCampaignScenariosIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATPhishingScenarios +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignScenariosEndpoint( + HuntressEndpoint, + IGettable[SATPhishingScenarios, HuntressSATRequestParams], + IPaginateable[SATPhishingScenarios, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "phishing-campaign-scenarios", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingScenarios) + IPaginateable.__init__(self, SATPhishingScenarios) + + def id(self, id: int) -> PhishingCampaignScenariosIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized PhishingCampaignScenariosIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + PhishingCampaignScenariosIdEndpoint: The initialized PhishingCampaignScenariosIdEndpoint object. + """ + child = PhishingCampaignScenariosIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATPhishingScenarios]: + """ + Performs a GET request against the /phishing-campaign-scenarios endpoints endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATData]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATPhishingScenarios, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingScenarios: + """ + Performs a GET request against the /phishing-campaign-scenarios endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingScenarios: The parsed response data. + """ + return self._parse_many( + SATPhishingScenarios, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdAttemptsEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdAttemptsEndpoint.py new file mode 100644 index 0000000..9cd9627 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdAttemptsEndpoint.py @@ -0,0 +1,38 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingCampaignAttempts +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignScenariosIdAttemptsEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaignAttempts, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "attempts", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaignAttempts) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaignAttempts: + + """ + Performs a GET request against the /accounts/{id}/attempts endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaignAttempts: The parsed response data. + """ + return self._parse_many( + SATPhishingCampaignAttempts, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdCampaignEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdCampaignEndpoint.py new file mode 100644 index 0000000..a5216f2 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdCampaignEndpoint.py @@ -0,0 +1,38 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingCampaigns +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignScenariosIdCampaignEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaigns, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "campaign", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaigns) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaigns: + + """ + Performs a GET request against the /phishing-campaign-scenarios/{id}/campaign endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaigns: The parsed response data. + """ + return self._parse_one( + SATPhishingCampaigns, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdEndpoint.py new file mode 100644 index 0000000..bacf660 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdEndpoint.py @@ -0,0 +1,79 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignScenariosIdAttemptsEndpoint import PhishingCampaignScenariosIdAttemptsEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignScenariosIdCampaignEndpoint import PhishingCampaignScenariosIdCampaignEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignScenariosIdScenarioEndpoint import PhishingCampaignScenariosIdScenarioEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATPhishingScenarios +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignScenariosIdEndpoint( + HuntressEndpoint, + IGettable[SATPhishingScenarios, HuntressSATRequestParams], + IPaginateable[SATPhishingScenarios, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingScenarios) + IPaginateable.__init__(self, SATPhishingScenarios) + + self.attempts = self._register_child_endpoint(PhishingCampaignScenariosIdAttemptsEndpoint(client, parent_endpoint=self)) + self.campaign = self._register_child_endpoint(PhishingCampaignScenariosIdCampaignEndpoint(client, parent_endpoint=self)) + self.campaign = self._register_child_endpoint(PhishingCampaignScenariosIdScenarioEndpoint(client, parent_endpoint=self)) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATPhishingScenarios]: + """ + Performs a GET request against the /phishing-campaigns/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATPhishingScenarios]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATPhishingScenarios, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingScenarios: + """ + Performs a GET request against the /phishing-campaigns/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingScenarios: The parsed response data. + """ + return self._parse_one( + SATPhishingScenarios, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdScenarioEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdScenarioEndpoint.py new file mode 100644 index 0000000..0458079 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignScenariosIdScenarioEndpoint.py @@ -0,0 +1,38 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingScenarios +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignScenariosIdScenarioEndpoint( + HuntressEndpoint, + IGettable[SATPhishingScenarios, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "scenario", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingScenarios) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingScenarios: + + """ + Performs a GET request against the /phishing-campaign-scenarios/{id}/scenario endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingScenarios: The parsed response data. + """ + return self._parse_one( + SATPhishingScenarios, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignsEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsEndpoint.py new file mode 100644 index 0000000..8bee66b --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignsIdEndpoint import PhishingCampaignsIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATPhishingCampaigns +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignsEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaigns, HuntressSATRequestParams], + IPaginateable[SATPhishingCampaigns, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "phishing-campaigns", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaigns) + IPaginateable.__init__(self, SATPhishingCampaigns) + + def id(self, id: int) -> PhishingCampaignsIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized PhishingCampaignsIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + PhishingCampaignsIdEndpoint: The initialized PhishingCampaignsIdEndpoint object. + """ + child = PhishingCampaignsIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATPhishingCampaigns]: + """ + Performs a GET request against the /phishing-campaign endpoints endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATData]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATPhishingCampaigns, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaigns: + """ + Performs a GET request against the /phishing-campaigns endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaigns: The parsed response data. + """ + return self._parse_many( + SATPhishingCampaigns, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdAttemptsEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdAttemptsEndpoint.py new file mode 100644 index 0000000..18066ec --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdAttemptsEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingCampaignAttempts +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignsIdAttemptsEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaignAttempts, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "attempts", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaignAttempts) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaignAttempts: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /accounts/{id}/attempts endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaignAttempts: The parsed response data. + """ + return self._parse_many( + SATPhishingCampaignAttempts, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdCampaignScenariosEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdCampaignScenariosEndpoint.py new file mode 100644 index 0000000..7b8f1d4 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdCampaignScenariosEndpoint.py @@ -0,0 +1,40 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, +) +from pyhuntress.models.managedsat import SATPhishingCampaigns +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignsIdCampaignScenariosEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaigns, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "campaign-scenarios", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaigns) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaigns: + + # TODO: Make this require the learnerid as a parameter + + """ + Performs a GET request against the /phishing-campaigns/{id}/campaign-scenarios endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaigns: The parsed response data. + """ + return self._parse_many( + SATPhishingCampaigns, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdEndpoint.py new file mode 100644 index 0000000..bf3b7de --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingCampaignsIdEndpoint.py @@ -0,0 +1,77 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignsIdAttemptsEndpoint import PhishingCampaignsIdAttemptsEndpoint +from pyhuntress.endpoints.managedsat.PhishingCampaignsIdCampaignScenariosEndpoint import PhishingCampaignsIdCampaignScenariosEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATPhishingCampaigns +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingCampaignsIdEndpoint( + HuntressEndpoint, + IGettable[SATPhishingCampaigns, HuntressSATRequestParams], + IPaginateable[SATPhishingCampaigns, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingCampaigns) + IPaginateable.__init__(self, SATPhishingCampaigns) + + self.attempts = self._register_child_endpoint(PhishingCampaignsIdAttemptsEndpoint(client, parent_endpoint=self)) + self.campaign_scenarios = self._register_child_endpoint(PhishingCampaignsIdCampaignScenariosEndpoint(client, parent_endpoint=self)) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATPhishingCampaigns]: + """ + Performs a GET request against the /phishing-campaigns/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATPhishingCampaigns]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATPhishingCampaigns, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingCampaigns: + """ + Performs a GET request against the /phishing-campaigns/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingCampaigns: The parsed response data. + """ + return self._parse_one( + SATPhishingCampaigns, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingScenariosEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingScenariosEndpoint.py new file mode 100644 index 0000000..6e1e546 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingScenariosEndpoint.py @@ -0,0 +1,86 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.PhishingScenariosIdEndpoint import PhishingScenariosIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATPhishingScenarios +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingScenariosEndpoint( + HuntressEndpoint, + IGettable[SATPhishingScenarios, HuntressSATRequestParams], + IPaginateable[SATPhishingScenarios, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "phishing-scenarios", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingScenarios) + IPaginateable.__init__(self, SATPhishingScenarios) + + def id(self, id: int) -> PhishingScenariosIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized PhishingScenariosIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + PhishingScenariosIdEndpoint: The initialized PhishingScenariosIdEndpoint object. + """ + child = PhishingScenariosIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATPhishingScenarios]: + """ + Performs a GET request against the /phishing-scenarios endpoitments endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATPhishingScenarios]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATPhishingScenarios, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingScenarios: + """ + Performs a GET request against the /phishing-scenarios endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATGroups: The parsed response data. + """ + return self._parse_many( + SATPhishingScenarios, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/PhishingScenariosIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/PhishingScenariosIdEndpoint.py new file mode 100644 index 0000000..7fde1a1 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/PhishingScenariosIdEndpoint.py @@ -0,0 +1,72 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATPhishingScenarios +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class PhishingScenariosIdEndpoint( + HuntressEndpoint, + IGettable[SATPhishingScenarios, HuntressSATRequestParams], + IPaginateable[SATPhishingScenarios, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATPhishingScenarios) + IPaginateable.__init__(self, SATPhishingScenarios) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATPhishingScenarios]: + """ + Performs a GET request against the /phishing-scenarios/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATPhishingScenarios]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATPhishingScenarios, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATPhishingScenarios: + """ + Performs a GET request against the /phishing-scenarios/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATPhishingScenarios: The parsed response data. + """ + return self._parse_one( + SATPhishingScenarios, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/endpoints/managedsat/UsersEndpoint.py b/src/pyhuntress/endpoints/managedsat/UsersEndpoint.py new file mode 100644 index 0000000..1dbb750 --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/UsersEndpoint.py @@ -0,0 +1,100 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.UsersIdEndpoint import UsersIdEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, + IPostable, +) +from pyhuntress.models.managedsat import SATUsers +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class UsersEndpoint( + HuntressEndpoint, + IGettable[SATUsers, HuntressSATRequestParams], +# IPostable[SATUsers, HuntressSATRequestParams], + IPaginateable[SATUsers, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "users", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATUsers) + IPaginateable.__init__(self, SATUsers) + + def id(self, id: int) -> UsersIdEndpoint: + """ + Sets the ID for this endpoint and returns an initialized UsersIdEndpoint object to move down the chain. + + Parameters: + id (int): The ID to set. + Returns: + UsersIdEndpoint: The initialized UsersIdEndpoint object. + """ + child = UsersIdEndpoint(self.client, parent_endpoint=self) + child._id = id + return child + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATUsers]: + """ + Performs a GET request against the /users endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATData]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATUsers, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATUsers: + """ + Performs a GET request against the /users endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATAccountInformation: The parsed response data. + """ + return self._parse_many( + SATUsers, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) + +# def post(self, data: JSON | None = None, params: HuntressSATRequestParams | None = None) -> SATUsers: +# """ +# Performs a POST request against the /company/companies endpoint. +# +# Parameters: +# data (dict[str, Any]): The data to send in the request body. +# params (dict[str, int | str]): The parameters to send in the request query string. +# Returns: +# SATUsers: The parsed response data. +# """ +# return self._parse_one(SATUsers, super()._make_request("POST", data=data, params=params).json()) diff --git a/src/pyhuntress/endpoints/managedsat/UsersIdEndpoint.py b/src/pyhuntress/endpoints/managedsat/UsersIdEndpoint.py new file mode 100644 index 0000000..bb78efc --- /dev/null +++ b/src/pyhuntress/endpoints/managedsat/UsersIdEndpoint.py @@ -0,0 +1,73 @@ +from pyhuntress.endpoints.base.huntress_endpoint import HuntressEndpoint +from pyhuntress.endpoints.managedsat.AccountsIdUsersEndpoint import AccountsIdUsersEndpoint +from pyhuntress.interfaces import ( + IGettable, + IPaginateable, +) +from pyhuntress.models.managedsat import SATUsers +from pyhuntress.responses.paginated_response import PaginatedResponse +from pyhuntress.types import ( + JSON, + HuntressSATRequestParams, +) + + +class UsersIdEndpoint( + HuntressEndpoint, + IGettable[SATUsers, HuntressSATRequestParams], + IPaginateable[SATUsers, HuntressSATRequestParams], +): + def __init__(self, client, parent_endpoint=None) -> None: + HuntressEndpoint.__init__(self, client, "{id}", parent_endpoint=parent_endpoint) + IGettable.__init__(self, SATUsers) + IPaginateable.__init__(self, SATUsers) + + def paginated( + self, + page: int, + limit: int, + params: HuntressSATRequestParams | None = None, + ) -> PaginatedResponse[SATUsers]: + """ + Performs a GET request against the /users/{id} endpoint and returns an initialized PaginatedResponse object. + + Parameters: + page (int): The page number to request. + limit (int): The number of results to return per page. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + PaginatedResponse[SATUsers]: The initialized PaginatedResponse object. + """ + if params: + params["page"] = page + params["limit"] = limit + else: + params = {"page": page, "limit": limit} + return PaginatedResponse( + super()._make_request("GET", params=params), + SATUsers, + self, + "data", + page, + limit, + params, + ) + + def get( + self, + data: JSON | None = None, + params: HuntressSATRequestParams | None = None, + ) -> SATUsers: + """ + Performs a GET request against the /users/{id} endpoint. + + Parameters: + data (dict[str, Any]): The data to send in the request body. + params (dict[str, int | str]): The parameters to send in the request query string. + Returns: + SATUsersInformation: The parsed response data. + """ + return self._parse_one( + SATUsers, + super()._make_request("GET", data=data, params=params).json().get('data', {}), + ) diff --git a/src/pyhuntress/models/managedsat/__init__.py b/src/pyhuntress/models/managedsat/__init__.py index 3f27158..1f5318d 100644 --- a/src/pyhuntress/models/managedsat/__init__.py +++ b/src/pyhuntress/models/managedsat/__init__.py @@ -6,13 +6,144 @@ from uuid import UUID from pydantic import Field from pyhuntress.models.base.huntress_model import HuntressModel + +class SATData(HuntressModel): + type: Literal[ + "accounts", + "users", + "assignments", + "learners", + "learner-activities", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATAccounts(HuntressModel): + type: Literal[ + "accounts", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATUsers(HuntressModel): + type: Literal[ + "users", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATAssignments(HuntressModel): + type: Literal[ + "assignments", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATLearners(HuntressModel): + type: Literal[ + "learners", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATLearnerActivities(HuntressModel): + type: Literal[ + "learner-activities", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATAccountsAttributes(HuntressModel): + name: str | None = Field(default=None, alias="Name") + status: str | None = Field(default=None, alias="Status") + type: str | None = Field(default=None, alias="Type") + plan: str | None = Field(default=None, alias="Plan") + licenses: int | None = Field(default=None, alias="Licenses") + createdAt: datetime | None = Field(default=None, alias="CreatedAt") + updatedAt: datetime | None = Field(default=None, alias="UpdatedAt") +class SATAssignmentsCompletionCertificates(HuntressModel): + type: Any | None = Field(default=None, alias="Type") + attributes: dict[str, str] | None = Field(default=None, alias="Attributes") -#class AccountingBatch(HuntressModel): -# info: Annotated[dict[str, str] | None, Field(alias="_info")] = None -# batch_identifier: Annotated[str | None, Field(alias="batchIdentifier")] = None -# closed_flag: Annotated[bool | None, Field(alias="closedFlag")] = None -# export_expenses_flag: Annotated[bool | None, Field(alias="exportExpensesFlag")] = None -# export_invoices_flag: Annotated[bool | None, Field(alias="exportInvoicesFlag")] = None -# export_products_flag: Annotated[bool | None, Field(alias="exportProductsFlag")] = None -# id: int | None = None +class SATEpisodes(HuntressModel): + type: Literal[ + "episodes", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATDepartments(HuntressModel): + type: Literal[ + "departments", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATGroups(HuntressModel): + type: Literal[ + "groups", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATPhishingCampaigns(HuntressModel): + type: Literal[ + "phishing-campaigns", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATPhishingScenarios(HuntressModel): + type: Literal[ + "phishing-campaign-scenarios", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATPhishingCampaignAttempts(HuntressModel): + type: Literal[ + "phishing-attempts", + ] | None = Field(default=None, alias="Type") + id: str | None = Field(default=None, alias="Id") + attributes: dict[str, Any] | None = Field(default=None, alias="Attributes") + relationships: dict[str, dict[str, dict[str, str]]] | None = Field(default=None, alias="Relationships") + links: dict[str, str] | None = Field(default=None, alias="Links") + meta: dict[str, dict[str, int]] | None = Field(default=None, alias="Meta") + +class SATPhishingAttemptsReport(HuntressModel): + data: Any + #This class needs to be researched more \ No newline at end of file