Skip to content

Commit

Permalink
add oauth for v2
Browse files Browse the repository at this point in the history
  • Loading branch information
sharinetmc committed Dec 10, 2024
1 parent d1ff157 commit 8a45cbb
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 50 deletions.
189 changes: 140 additions & 49 deletions parsons/newmode/newmode.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from parsons.utilities.api_connector import APIConnector
from parsons.utilities.oauth_api_connector import OAuth2APIConnector
from parsons.utilities import check_env
from parsons import Table
import logging
import time

logger = logging.getLogger(__name__)

API_URL = "https://engage.newmode.net/api/"

API_URL_V1 = "https://engage.newmode.net/api/"
API_URL_V2 = "https://base.newmode.net/api/"
API_AUTH_URL = 'https://base.newmode.net/oauth/token'

class Newmode(object):
"""
Expand All @@ -25,29 +27,34 @@ class Newmode(object):
NewMode Class
"""

def __init__(self, api_user=None, api_password=None, api_version="v1.0"):
self.base_url = check_env.check("NEWMODE_API_URL", API_URL)
self.api_user = check_env.check("NEWMODE_API_USER", api_user)
self.api_password = check_env.check("NEWMODE_API_PASSWORD", api_password)
def __init__(self, api_user=None, api_password=None, client_id=None, client_secret=None, api_version="v1.0"):
self.api_version = check_env.check("NEWMODE_API_VERSION", api_version)
self.headers = {"Content-Type": "application/json"}
self.client = APIConnector(
self.base_url,
auth=(self.api_user, self.api_password),
headers=self.headers,
)

def check_api_version(self, documentation_url="TODO", v1_0=True, v2_1=True):
exception_text = f"Endpoint not supported by API version {self.api_version}"
if self.api_version == "v1.0":
if "v1" in self.api_version:
logger.warning(
"Newmode API v1.0 will no longer be supported starting February 2025."
f"Documentation for v2.1 here: {documentation_url}"
"Newmode API v1 will no longer be supported starting Feburary 2025."
)
if not v1_0:
raise Exception(exception_text)
elif self.api_version == "v2.1" and not v2_1:
raise Exception(exception_text)
self.base_url = API_URL_V1
self.api_user = check_env.check("NEWMODE_API_USER", api_user)
self.api_password = check_env.check("NEWMODE_API_PASSWORD", api_password)
self.headers = {"Content-Type": "application/json"}
self.client = APIConnector(
self.base_url,
auth=(self.api_user, self.api_password),
headers=self.headers,)
else:
self.base_url = API_URL_V2
self.client_id = check_env.check("NEWMODE_API_CLIENT_ID", client_id)
self.__client_secret = check_env.check("NEWMODE_API_CLIENT_SECRET", client_secret)
self.headers = {"content-type": "application/x-www-form-urlencoded"}
self.client = OAuth2APIConnector(
uri=self.base_url,
auto_refresh_url=API_AUTH_URL,
client_id=self.client_id,
client_secret=self.__client_secret,
headers=self.headers,
token_url=API_AUTH_URL,
grant_type="client_credentials",)

def convert_to_table(self, data):
"""Internal method to create a Parsons table from a data element."""
Expand All @@ -69,6 +76,8 @@ def base_request(self, method, url, requires_csrf=True, params={}):
response = None
if method == "GET":
response = self.client.get_request(url=url, params=params)
# if "targets" in url:
# response = self.client.get_request(url=url, params=params)['_embedded']['hal:tool']
elif method == "PATCH":
response = self.client.patch_request(url=url, params=params)
# response.get("_embedded", {}).get(f"osdi:{object_name}")
Expand All @@ -82,19 +91,18 @@ def converted_request(
supports_version=True,
params={},
convert_to_table=True,
v1_0=True,
v2_1=True,
):
self.check_api_version(v1_0=v1_0, v2_1=v2_1)
url = f"{self.api_version}/{endpoint}" if supports_version else endpoint
response = self.base_request(
method=method, url=url, requires_csrf=requires_csrf, params=params
)
if not response:
logging.warning(f"Empty result returned from endpoint: {endpoint}")
if convert_to_table:
return self.convert_to_table(response)
else:
return response

def get_csrf_token(self, max_retries=10):
"""
Retrieve a CSRF token for making API requests
Expand All @@ -104,11 +112,11 @@ def get_csrf_token(self, max_retries=10):
`Returns:`
The CSRF token.
"""

endpoint = "session/token"
for attempt in range(max_retries):
try:
response = self.converted_request(
endpoint="session/token",
endpoint=endpoint,
method="GET",
supports_version=False,
requires_csrf=False,
Expand All @@ -128,6 +136,7 @@ def get_csrf_token(self, max_retries=10):

def get_tools(self, params={}):
"""
V1 only
Retrieve all tools
`Args:`
params: dict
Expand All @@ -140,6 +149,7 @@ def get_tools(self, params={}):

def get_tool(self, tool_id, params={}):
"""
V1 only
Retrieve a specific tool by ID
`Args:`
tool_id: str
Expand All @@ -154,8 +164,9 @@ def get_tool(self, tool_id, params={}):
)
return response

def lookup_targets(self, tool_id, search=None, params={}):
def lookup_targets(self, target_id, search=None, location=None, params={}):
"""
V1 only
Lookup targets for a given tool
`Args:`
tool_id: str
Expand All @@ -167,16 +178,19 @@ def lookup_targets(self, tool_id, search=None, params={}):
`Returns:`
Parsons Table containing target data.
"""
endpoint = f"lookup/{tool_id}"
endpoint = f"lookup/{target_id}"
if search:
endpoint += f"/{search}"
if location:
endpoint += f"/{location}"
response = self.converted_request(
endpoint=endpoint, method="GET", params=params
)
return response

def get_action(self, tool_id, params={}):
"""
V1 only
Get action information for a specific tool
`Args:`
tool_id: str
Expand All @@ -193,6 +207,7 @@ def get_action(self, tool_id, params={}):

def run_action(self, tool_id, payload, params={}):
"""
V1 only
Run a specific action for a tool
`Args:`
tool_id: str
Expand All @@ -208,40 +223,34 @@ def run_action(self, tool_id, payload, params={}):
endpoint=f"action/{tool_id}", method="PATCH", payload=payload, params=params
)
return response

def get_target(self, target_id, params={}):
"""
Retrieve a specific target by ID
`Args:`
target_id: str
The ID of the target to retrieve.
params: dict
Query parameters to include in the request.
`Returns:`
Parsons Table containing target data.
"""
response = self.converted_request(
endpoint=f"target/{target_id}", method="GET", params=params
)
return response


def get_campaigns(self, params={}):
"""
V1 & V2
Retrieve all campaigns
In v2, a campaign is equivalent to Tools or Actions in V1.
`Args:`
params: dict
Query parameters to include in the request.
`Returns:`
Parsons Table containing campaigns data.
"""
if "v1" in self.api_version:
endpoint = "campaign"
else:
self.api_version = "jsonapi"
endpoint = "action/action"
response = self.converted_request(
endpoint="campaign", method="GET", params=params
endpoint=endpoint, method="GET", params=params
)
return response

def get_campaign(self, campaign_id, params={}):
"""
Retrieve a specific campaign by ID
V1 & V2
Retrieve a specific campaign by ID.
In v2, a campaign is equivalent to Tools or Actions in V1.
`Args:`
campaign_id: str
The ID of the campaign to retrieve.
Expand All @@ -250,13 +259,16 @@ def get_campaign(self, campaign_id, params={}):
`Returns:`
Parsons Table containing campaign data.
"""
endpoint = f"campaign/{campaign_id}" if "v1" in self.api_version else f"/campaign/{campaign_id}/form"

response = self.converted_request(
endpoint=f"campaign/{campaign_id}", method="GET", params=params
endpoint=endpoint, method="GET", params=params
)
return response

def get_organizations(self, params={}):
"""
V1 only
Retrieve all organizations
`Args:`
params: dict
Expand All @@ -271,6 +283,7 @@ def get_organizations(self, params={}):

def get_organization(self, organization_id, params={}):
"""
V1 only
Retrieve a specific organization by ID
`Args:`
organization_id: str
Expand All @@ -287,6 +300,7 @@ def get_organization(self, organization_id, params={}):

def get_services(self, params={}):
"""
V1 only
Retrieve all services
`Args:`
params: dict
Expand All @@ -301,6 +315,7 @@ def get_services(self, params={}):

def get_service(self, service_id, params={}):
"""
V1 only
Retrieve a specific service by ID
`Args:`
service_id: str
Expand All @@ -315,8 +330,24 @@ def get_service(self, service_id, params={}):
)
return response

def get_target(self, target_id, params={}):
"""
V1 only
Get specific target.
`Args:`
params: dict
Query parameters to include in the request.
`Returns:`
Parsons Table containing targets data.
"""
response = self.converted_request(
endpoint=f"target/{target_id}", method="GET", params=params
)
return response

def get_targets(self, params={}):
"""
V1 only
Retrieve all targets
`Args:`
params: dict
Expand All @@ -331,6 +362,7 @@ def get_targets(self, params={}):

def get_outreaches(self, tool_id, params={}):
"""
V1 only
Retrieve all outreaches for a specific tool
`Args:`
tool_id: str
Expand All @@ -348,6 +380,7 @@ def get_outreaches(self, tool_id, params={}):

def get_outreach(self, outreach_id, params={}):
"""
V1 only
Retrieve a specific outreach by ID
`Args:`
outreach_id: str
Expand All @@ -361,3 +394,61 @@ def get_outreach(self, outreach_id, params={}):
endpoint=f"outreach/{outreach_id}", method="GET", params=params
)
return response

def get_recipient(self, campaign_id, params={}):
"""
V2 only
Retrieve a specific recipient by ID
`Args:`
campaign_id: str
The ID of the campaign to retrieve.
params: dict
Query parameters to include in the request.
`Returns:`
Parsons Table containing recipient data.
"""
response = self.converted_request(
endpoint=f"campaign/{campaign_id}/target", method="GET", params=params
)
return response

def run_submit(self, campaign_id, params={}):
"""
V2 only
Pass a submission from a supporter to a campaign
that ultimately fills in a petition,
sends an email or triggers a phone call
depending on your campaign type
`Args:`
campaign_id: str
The ID of the campaign to retrieve.
params: dict
Query parameters to include in the request.
`Returns:`
Parsons Table containing submit data.
"""
response = self.converted_request(
endpoint=f"campaign/{campaign_id}/submit ", method="POST", params=params
)
return response

def get_submissions(self, params={}):
"""
V2 only
Retrieve and sort submission and contact data
for your organization using a range of filters
that include campaign id, data range and submission status
`Args:`
campaign_id: str
The ID of the campaign to retrieve.
params: dict
Query parameters to include in the request.
`Returns:`
Parsons Table containing submit data.
"""
response = self.converted_request(
endpoint="submission", method="POST", params=params
)
return response
2 changes: 1 addition & 1 deletion parsons/utilities/oauth_api_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(
client_id: str,
client_secret: str,
token_url: str,
auto_refresh_url: Optional[str],
auto_refresh_url: str,
headers: Optional[Dict[str, str]] = None,
pagination_key: Optional[str] = None,
data_key: Optional[str] = None,
Expand Down

0 comments on commit 8a45cbb

Please sign in to comment.