Skip to content

Commit

Permalink
feat: add prolific integration (M2-8325)
Browse files Browse the repository at this point in the history
  • Loading branch information
hamzace committed Jan 16, 2025
1 parent 9f3afe1 commit 7a5803b
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/apps/integrations/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

class AvailableIntegrations(str, Enum):
LORIS = "LORIS"
PROLIFIC = "PROLIFIC"
FUTURE = "FUTURE"


Expand Down
Empty file.
17 changes: 17 additions & 0 deletions src/apps/integrations/prolific/domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import json

from pydantic import BaseModel

from apps.integrations.db.schemas import IntegrationsSchema


class ProlificIntegration(BaseModel):
api_key: str

@classmethod
def from_schema(cls, schema: IntegrationsSchema):
configuration = json.loads(schema.configuration.replace("'", '"'))
return cls(api_key=configuration["api_key"])

def __repr__(self):
return "ProlificIntegration()"
Empty file.
39 changes: 39 additions & 0 deletions src/apps/integrations/prolific/service/prolific.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import uuid

import requests
from fastapi import HTTPException

from apps.integrations.crud.integrations import IntegrationsCRUD
from apps.integrations.db.schemas import IntegrationsSchema
from apps.integrations.domain import AvailableIntegrations
from apps.integrations.prolific.domain import ProlificIntegration
from apps.users.domain import User


class ProlificIntegrationService:
def __init__(self, applet_id: uuid.UUID, session, user: User) -> None:
self.applet_id = applet_id
self.session = session
self.user = user
self.type = AvailableIntegrations.PROLIFIC

async def create_prolific_integration(self, api_key: str) -> ProlificIntegration:
prolific_response = requests.get(
"https://api.prolific.com/api/v1/users/me/",
headers={"Authorization": f"Token {api_key}", "Content-Type": "application/json"},
)

if prolific_response.status_code != 200:
raise HTTPException(status_code=prolific_response.status_code, detail="Prolific token is invalid")

integration_schema = await IntegrationsCRUD(self.session).create(
IntegrationsSchema(
applet_id=self.applet_id,
type=self.type,
configuration={
"api_key": api_key,
},
)
)

return ProlificIntegration.from_schema(integration_schema)
25 changes: 25 additions & 0 deletions src/apps/integrations/service/integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
)
from apps.integrations.loris.domain.loris_integrations import LorisIntegrationPublic
from apps.integrations.loris.service.loris import LorisIntegrationService
from apps.integrations.prolific.service.prolific import ProlificIntegrationService
from apps.integrations.service.future_integration import FutureIntegrationService
from apps.users.domain import User

Expand Down Expand Up @@ -43,6 +44,24 @@ async def create_integration(self, newIntegration: Integration) -> Integration:
applet_id=newIntegration.applet_id,
configuration=loris_integration,
)
case AvailableIntegrations.PROLIFIC:
expected_keys = ["api_key"]
if None in [newIntegration.configuration.get(k, None) for k in expected_keys]:
raise UnexpectedPropertiesForIntegration(
provided_keys=list(newIntegration.configuration.keys()),
expected_keys=expected_keys,
integration_type=AvailableIntegrations.PROLIFIC,
)
prolific_integration = await ProlificIntegrationService(
newIntegration.applet_id,
self.session,
self.user,
).create_prolific_integration(api_key=newIntegration.configuration["api_key"])
return Integration(
integration_type=AvailableIntegrations.PROLIFIC,
applet_id=newIntegration.applet_id,
configuration=prolific_integration,
)
case AvailableIntegrations.FUTURE:
expected_keys = ["endpoint", "api_key"]
if None in [newIntegration.configuration.get(k, None) for k in expected_keys]:
Expand Down Expand Up @@ -82,6 +101,12 @@ async def retrieve_integration(self, applet_id, integration_type) -> Integration
applet_id=applet_id,
configuration=loris_integration,
)
case AvailableIntegrations.PROLIFIC:
return Integration(
integration_type=AvailableIntegrations.PROLIFIC,
applet_id=applet_id,
configuration={}, # Configuration is empty as we don't want to share the api_key
)
case AvailableIntegrations.FUTURE:
future_integration = FutureIntegrationPublic.from_schema(integration_schema)
return Integration(
Expand Down

0 comments on commit 7a5803b

Please sign in to comment.