From 00bc88267aba5fe546ee24f8101915f2aeaee046 Mon Sep 17 00:00:00 2001 From: acostapazo Date: Mon, 26 Jun 2023 17:13:52 +0200 Subject: [PATCH 1/9] chore(pydantic): make it compatible with future pydantic release --- alice/config.py | 5 ++--- alice/onboarding/models/bounding_box.py | 3 +-- alice/onboarding/models/report/checks/check.py | 3 +-- alice/onboarding/models/report/compliance/device_out.py | 7 +++---- .../models/report/compliance/domain_events_report.py | 2 +- .../onboarding/models/report/document/document_field.py | 4 ++-- .../onboarding/models/report/document/document_report.py | 9 ++++----- .../models/report/document/document_report_meta.py | 3 +-- .../models/report/document/document_side_report.py | 3 +-- .../models/report/document/document_side_report_meta.py | 3 +-- .../models/report/face_matching/face_matching.py | 3 +-- .../other_trusted_document_report.py | 2 +- .../other_trusted_document_report_meta.py | 3 +-- alice/onboarding/models/report/report.py | 4 ++-- alice/onboarding/models/report/selfie/selfie_report.py | 3 +-- alice/onboarding/models/report/shared/bounding_box.py | 3 +-- alice/onboarding/models/report/shared/href.py | 3 +-- .../models/report/summary/external_user_data.py | 2 +- alice/onboarding/models/user_info.py | 8 ++++---- requirements/requirements.txt | 2 +- 20 files changed, 31 insertions(+), 44 deletions(-) diff --git a/alice/config.py b/alice/config.py index e397abd..a3a02b7 100644 --- a/alice/config.py +++ b/alice/config.py @@ -1,7 +1,6 @@ from typing import Union -from pydantic.fields import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from requests import Session @@ -20,4 +19,4 @@ class Config: ) send_agent: bool = Field(default=True) verbose: bool = Field(default=False) - session: Union[Session, None] = None + session: Union[Session, None] = Field(default=None) diff --git a/alice/onboarding/models/bounding_box.py b/alice/onboarding/models/bounding_box.py index 17ea475..c378fae 100644 --- a/alice/onboarding/models/bounding_box.py +++ b/alice/onboarding/models/bounding_box.py @@ -1,5 +1,4 @@ -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field class BoundingBox(BaseModel): diff --git a/alice/onboarding/models/report/checks/check.py b/alice/onboarding/models/report/checks/check.py index 0355a36..37e129a 100644 --- a/alice/onboarding/models/report/checks/check.py +++ b/alice/onboarding/models/report/checks/check.py @@ -1,7 +1,6 @@ from typing import Optional -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field class Check(BaseModel): diff --git a/alice/onboarding/models/report/compliance/device_out.py b/alice/onboarding/models/report/compliance/device_out.py index f0000fd..3c5ddf0 100644 --- a/alice/onboarding/models/report/compliance/device_out.py +++ b/alice/onboarding/models/report/compliance/device_out.py @@ -1,7 +1,6 @@ -from typing import Optional +from typing import Union -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field class DeviceOut(BaseModel): @@ -14,7 +13,7 @@ class DeviceOut(BaseModel): platform: str platform_version: str model: str - ip: Optional[str] = None + ip: Union[str, None] = Field(default=None) def __hash__(self) -> int: return hash((type(self),) + tuple(self.__dict__.values())) diff --git a/alice/onboarding/models/report/compliance/domain_events_report.py b/alice/onboarding/models/report/compliance/domain_events_report.py index 6f40d50..d353982 100644 --- a/alice/onboarding/models/report/compliance/domain_events_report.py +++ b/alice/onboarding/models/report/compliance/domain_events_report.py @@ -1,6 +1,6 @@ from typing import List -from pydantic.main import BaseModel +from pydantic import BaseModel from alice.onboarding.models.report.compliance.device_out import DeviceOut from alice.onboarding.models.report.compliance.user_event_out import UserEventOut diff --git a/alice/onboarding/models/report/document/document_field.py b/alice/onboarding/models/report/document/document_field.py index e7f84b3..789a70f 100644 --- a/alice/onboarding/models/report/document/document_field.py +++ b/alice/onboarding/models/report/document/document_field.py @@ -1,7 +1,7 @@ from typing import List, Optional from meiga import Error, Result, Success, isFailure -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.checks.check import Check @@ -14,7 +14,7 @@ class ReportV1Field(BaseModel): name: str value: Optional[str] score: Optional[int] - checks: List[Check] = [] + checks: List[Check] = Field(default=[]) def get_check(self, check_key: str) -> Result[Check, Error]: for doc_check in self.checks: diff --git a/alice/onboarding/models/report/document/document_report.py b/alice/onboarding/models/report/document/document_report.py index 388ad88..d4fb25f 100644 --- a/alice/onboarding/models/report/document/document_report.py +++ b/alice/onboarding/models/report/document/document_report.py @@ -2,8 +2,7 @@ from typing import List, Union from meiga import Error, Result, Success, isFailure -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.checks.check import Check from alice.onboarding.models.report.document.document_field import ReportV1Field @@ -16,9 +15,9 @@ class DocumentSidesDetailReport(BaseModel): - front: Union[DocumentSideReport, None] = None - back: Union[DocumentSideReport, None] = None - internal: Union[DocumentSideReport, None] = None + front: Union[DocumentSideReport, None] = Field(default=None) + back: Union[DocumentSideReport, None] = Field(default=None) + internal: Union[DocumentSideReport, None] = Field(default=None) def get_completed_sides(self) -> int: completed_sides = 0 diff --git a/alice/onboarding/models/report/document/document_report_meta.py b/alice/onboarding/models/report/document/document_report_meta.py index 4873665..42781cd 100644 --- a/alice/onboarding/models/report/document/document_report_meta.py +++ b/alice/onboarding/models/report/document/document_report_meta.py @@ -1,5 +1,4 @@ -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.document.document_type import DocumentType diff --git a/alice/onboarding/models/report/document/document_side_report.py b/alice/onboarding/models/report/document/document_side_report.py index 982209d..6dc899a 100644 --- a/alice/onboarding/models/report/document/document_side_report.py +++ b/alice/onboarding/models/report/document/document_side_report.py @@ -2,8 +2,7 @@ from typing import Any, Dict, List, Optional from meiga import Error, Result, Success, isFailure -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.document.document_field import ReportV1Field from alice.onboarding.models.report.document.document_side import DocumentSide diff --git a/alice/onboarding/models/report/document/document_side_report_meta.py b/alice/onboarding/models/report/document/document_side_report_meta.py index 5539ac9..1c0016c 100644 --- a/alice/onboarding/models/report/document/document_side_report_meta.py +++ b/alice/onboarding/models/report/document/document_side_report_meta.py @@ -1,5 +1,4 @@ -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field class DocumentSideReportMeta(BaseModel): diff --git a/alice/onboarding/models/report/face_matching/face_matching.py b/alice/onboarding/models/report/face_matching/face_matching.py index 2454aa1..6a7606d 100644 --- a/alice/onboarding/models/report/face_matching/face_matching.py +++ b/alice/onboarding/models/report/face_matching/face_matching.py @@ -1,7 +1,6 @@ from datetime import datetime -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.document.document_side import DocumentSide diff --git a/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report.py b/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report.py index aaae30c..68857fb 100644 --- a/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report.py +++ b/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report.py @@ -11,7 +11,7 @@ class OtherTrustedDocumentReport(BaseModel): """ - A other trusted document report_v1 collects all the information extracted for a document during the onboarding process + The other trusted document report_v1 collects all the information extracted for a document during the onboarding process """ id: str = Field( diff --git a/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report_meta.py b/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report_meta.py index d50a61e..8391403 100644 --- a/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report_meta.py +++ b/alice/onboarding/models/report/other_trusted_document/other_trusted_document_report_meta.py @@ -1,7 +1,6 @@ from typing import Optional -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field class OtherTrustedDocumentReportMeta(BaseModel): diff --git a/alice/onboarding/models/report/report.py b/alice/onboarding/models/report/report.py index d210075..d9a8af6 100644 --- a/alice/onboarding/models/report/report.py +++ b/alice/onboarding/models/report/report.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List +from typing import List, Literal from pydantic import BaseModel, Field @@ -27,7 +27,7 @@ class Report(BaseModel): min_length=16, max_length=36, ) - version: int = Field(default=1, description="Report version", const=True) + version: int = Field(default=Literal[1], description="Report version") created_at: datetime = Field(description="Report creation time in ISO 8601 format") summary: ReportSummary = Field(description="User summary") selfies: List[SelfieReport] = Field(description="It collects all user selfies") diff --git a/alice/onboarding/models/report/selfie/selfie_report.py b/alice/onboarding/models/report/selfie/selfie_report.py index bf2f598..4f8a667 100644 --- a/alice/onboarding/models/report/selfie/selfie_report.py +++ b/alice/onboarding/models/report/selfie/selfie_report.py @@ -2,8 +2,7 @@ from typing import Dict, List, Optional from meiga import Error, Result, Success, isFailure -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.checks.check import Check from alice.onboarding.models.report.shared.href import Href diff --git a/alice/onboarding/models/report/shared/bounding_box.py b/alice/onboarding/models/report/shared/bounding_box.py index 17ea475..c378fae 100644 --- a/alice/onboarding/models/report/shared/bounding_box.py +++ b/alice/onboarding/models/report/shared/bounding_box.py @@ -1,5 +1,4 @@ -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field class BoundingBox(BaseModel): diff --git a/alice/onboarding/models/report/shared/href.py b/alice/onboarding/models/report/shared/href.py index da4e34e..ea02541 100644 --- a/alice/onboarding/models/report/shared/href.py +++ b/alice/onboarding/models/report/shared/href.py @@ -1,7 +1,6 @@ from typing import Dict, Optional -from pydantic import Field -from pydantic.main import BaseModel +from pydantic import BaseModel, Field from alice.onboarding.models.report.shared.bounding_box import BoundingBox diff --git a/alice/onboarding/models/report/summary/external_user_data.py b/alice/onboarding/models/report/summary/external_user_data.py index ea51494..3fb7376 100644 --- a/alice/onboarding/models/report/summary/external_user_data.py +++ b/alice/onboarding/models/report/summary/external_user_data.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic.main import BaseModel +from pydantic import BaseModel class ExternalUserData(BaseModel): diff --git a/alice/onboarding/models/user_info.py b/alice/onboarding/models/user_info.py index 690edaf..0e51f22 100644 --- a/alice/onboarding/models/user_info.py +++ b/alice/onboarding/models/user_info.py @@ -1,9 +1,9 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import BaseModel, Field class UserInfo(BaseModel): - first_name: Optional[str] = None - last_name: Optional[str] = None - email: Optional[str] = None + first_name: Optional[str] = Field(default=None) + last_name: Optional[str] = Field(default=None) + email: Optional[str] = Field(default=None) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index fa8d2ae..0478086 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,4 +1,4 @@ pyjwt>=2.3.0,<3.0.0 -pydantic>=1.8.2,<2.0.0 +pydantic>=1.8.2,<3 requests>=2.26.0,<3.0.0 meiga>=1.2.12,<1.9.0 \ No newline at end of file From db9636bd9dbc7045aaa621857711896de6d56d36 Mon Sep 17 00:00:00 2001 From: acostapazo Date: Mon, 26 Jun 2023 17:16:57 +0200 Subject: [PATCH 2/9] fix(static-analysis): solve mypy warnings --- alice/onboarding/models/report/report.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alice/onboarding/models/report/report.py b/alice/onboarding/models/report/report.py index d9a8af6..b593d2f 100644 --- a/alice/onboarding/models/report/report.py +++ b/alice/onboarding/models/report/report.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Literal +from typing import List from pydantic import BaseModel, Field @@ -27,7 +27,7 @@ class Report(BaseModel): min_length=16, max_length=36, ) - version: int = Field(default=Literal[1], description="Report version") + version: int = Field(default=1, description="Report version") created_at: datetime = Field(description="Report creation time in ISO 8601 format") summary: ReportSummary = Field(description="User summary") selfies: List[SelfieReport] = Field(description="It collects all user selfies") From 7f6bd542dc3f72f187245a1baacc976a1c1ec2e9 Mon Sep 17 00:00:00 2001 From: acostapazo Date: Mon, 26 Jun 2023 17:25:11 +0200 Subject: [PATCH 3/9] chore(requirements): be less restrictive on higher versions --- requirements/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 0478086..0cb9b03 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,4 +1,4 @@ -pyjwt>=2.3.0,<3.0.0 +pyjwt>=2.3.0,<3 pydantic>=1.8.2,<3 -requests>=2.26.0,<3.0.0 -meiga>=1.2.12,<1.9.0 \ No newline at end of file +requests>=2.26.0,<3 +meiga>=1.2.12,<2 \ No newline at end of file From 58704071c741430e82a1ed22ce389d38ee6a9bff Mon Sep 17 00:00:00 2001 From: acostapazo Date: Wed, 28 Jun 2023 15:20:33 +0200 Subject: [PATCH 4/9] chore: update examples add user examples and upgrad minimun meiga version --- .github/workflows/ci.yml | 2 ++ alice/__init__.py | 3 +- alice/auth/auth_errors.py | 7 +++-- .../report/document/document_side_report.py | 6 ++-- alice/onboarding/onboarding.py | 8 +++-- alice/onboarding/onboarding_client.py | 2 +- alice/onboarding/onboarding_errors.py | 2 +- alice/sandbox/sandbox_errors.py | 2 +- examples/dummy_cached_token_stack.py | 19 +++++++++++- examples/onboarding.py | 23 +++++++-------- examples/onboarding_get_users.py | 24 +++++++++++++++ examples/onboarding_report_v0.py | 29 +++++++++---------- examples/onboarding_with_certificate.py | 19 ++++++------ examples/onboarding_with_identification.py | 23 +++++++-------- examples/onboarding_with_screening.py | 14 +++------ examples/onboarding_with_user_matching.py | 15 ++++------ examples/onboarding_with_webhooks.py | 11 ++----- requirements/requirements.txt | 2 +- 18 files changed, 119 insertions(+), 92 deletions(-) create mode 100644 examples/onboarding_get_users.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a9ff48..729fad5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,6 +43,8 @@ jobs: run: lume -test - name: Example [Onboarding] run: python examples/onboarding.py + - name: Example [Onboarding Get Users] + run: python examples/onboarding_get_users.py - name: Example [Onboarding Report V0] run: python examples/onboarding_report_v0.py - name: Example [Onboarding with Identification] diff --git a/alice/__init__.py b/alice/__init__.py index 5fb51a3..5775cd4 100644 --- a/alice/__init__.py +++ b/alice/__init__.py @@ -5,6 +5,7 @@ ROOT_PATH = os.path.abspath(os.path.dirname(__file__)) -__version__ = open(f"{ROOT_PATH}/VERSION").read()[:-1] +with open(f"{ROOT_PATH}/VERSION") as f: + __version__ = f.read()[:-1] __all__ = public_api.__all__ diff --git a/alice/auth/auth_errors.py b/alice/auth/auth_errors.py index 00385a1..fe09136 100644 --- a/alice/auth/auth_errors.py +++ b/alice/auth/auth_errors.py @@ -1,5 +1,6 @@ +from __future__ import annotations + from dataclasses import dataclass -from typing import Dict from meiga import Error from requests import Response @@ -9,7 +10,7 @@ class AuthError(Error): operation: str code: int - message: Dict[str, str] + message: dict[str, str] | None # type: ignore def __str__(self) -> str: return self.__repr__() @@ -18,7 +19,7 @@ def __repr__(self) -> str: return f"[AuthError: [operation: {self.operation} | code: {self.code} | message: {self.message}]]" @staticmethod - def from_response(operation: str, response: Response) -> "AuthError": + def from_response(operation: str, response: Response) -> AuthError: code = response.status_code try: message = response.json() diff --git a/alice/onboarding/models/report/document/document_side_report.py b/alice/onboarding/models/report/document/document_side_report.py index 6dc899a..6e0f4d3 100644 --- a/alice/onboarding/models/report/document/document_side_report.py +++ b/alice/onboarding/models/report/document/document_side_report.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Union from meiga import Error, Result, Success, isFailure from pydantic import BaseModel, Field @@ -25,8 +25,8 @@ class DocumentSideReport(BaseModel): description="Document side media resources" ) meta: DocumentSideReportMeta - created_at: Optional[datetime] - forensics_scores: Optional[Dict[str, Any]] + created_at: Union[datetime, None] = Field(default=None) + forensics_scores: Union[Dict[str, Any], None] = Field(default=None) def get_field(self, field_name: str) -> Result[ReportV1Field, Error]: for side_field in self.fields: diff --git a/alice/onboarding/onboarding.py b/alice/onboarding/onboarding.py index 7759bcc..998270a 100644 --- a/alice/onboarding/onboarding.py +++ b/alice/onboarding/onboarding.py @@ -267,13 +267,15 @@ def get_users_status( self, verbose: Optional[bool] = False, page: int = 1, - page_size: int = 0, + page_size: int = 10, descending: bool = True, authorized: bool = False, sort_by: Union[str, None] = None, filter_field: Union[str, None] = None, filter_value: Union[str, None] = None, - ) -> Result[List[Dict[str, str]], Union[OnboardingError, AuthError]]: + ) -> Result[ + Dict[str, Union[List[Dict[str, str]], int]], Union[OnboardingError, AuthError] + ]: """ Returns every UserStatus available for all the Users in the onboarding platform ordered by creation date. @@ -300,7 +302,7 @@ def get_users_status( Returns ------- - A Result where if the operation is successful it returns list of dict which represent the status of each user. + A Result where if the operation is successful it returns a dict which represent the status of each user. Otherwise, it returns an OnboardingError or AuthError. """ verbose = self.verbose or verbose diff --git a/alice/onboarding/onboarding_client.py b/alice/onboarding/onboarding_client.py index d70cf53..bb24467 100644 --- a/alice/onboarding/onboarding_client.py +++ b/alice/onboarding/onboarding_client.py @@ -281,7 +281,7 @@ def get_users_status( self, verbose: Optional[bool] = False, page: int = 1, - page_size: int = 0, + page_size: int = 10, descending: bool = True, authorized: bool = False, sort_by: Union[str, None] = None, diff --git a/alice/onboarding/onboarding_errors.py b/alice/onboarding/onboarding_errors.py index deae9fb..c648fc3 100644 --- a/alice/onboarding/onboarding_errors.py +++ b/alice/onboarding/onboarding_errors.py @@ -9,7 +9,7 @@ class OnboardingError(Error): operation: str code: int - message: Optional[Dict[str, Any]] = None + message: Optional[Dict[str, Any]] = None # type: ignore def __init__( self, operation: str, code: int, message: Optional[Dict[str, Any]] = None diff --git a/alice/sandbox/sandbox_errors.py b/alice/sandbox/sandbox_errors.py index 9d759e7..ae9ee69 100644 --- a/alice/sandbox/sandbox_errors.py +++ b/alice/sandbox/sandbox_errors.py @@ -9,7 +9,7 @@ class SandboxError(Error): operation: str code: int - message: Optional[Dict[str, Any]] = None + message: Optional[Dict[str, Any]] = None # type: ignore def __init__( self, operation: str, code: int, message: Optional[Dict[str, Any]] = None diff --git a/examples/dummy_cached_token_stack.py b/examples/dummy_cached_token_stack.py index 6202dfa..059e40a 100644 --- a/examples/dummy_cached_token_stack.py +++ b/examples/dummy_cached_token_stack.py @@ -1,7 +1,24 @@ +from datetime import datetime, timedelta, timezone from uuid import uuid4 +import jwt + from alice.auth.cached_token_stack import CachedTokenStack -from tests.test_unit_cached_token_stack import generate_dummy_token + + +def generate_dummy_token( + expired: bool = False, payload_value: str = "payload_value" +) -> str: + if expired: + exp = (datetime.now(timezone.utc) - timedelta(minutes=60)).timestamp() + else: + exp = (datetime.now(timezone.utc) + timedelta(minutes=60)).timestamp() + + encoded_jwt = jwt.encode( + {"id": payload_value, "exp": exp}, "secret", algorithm="HS256" + ) + return encoded_jwt + stack = CachedTokenStack(max_size=100) diff --git a/examples/onboarding.py b/examples/onboarding.py index a97057c..0527ccd 100644 --- a/examples/onboarding.py +++ b/examples/onboarding.py @@ -1,9 +1,6 @@ import os from typing import Optional -from meiga import isSuccess -from meiga.decorators import meiga - from alice import Config, Onboarding from alice.onboarding.enums.document_side import DocumentSide from alice.onboarding.enums.document_type import DocumentType @@ -12,8 +9,7 @@ RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def onboarding_example(api_key: str, verbose: Optional[bool] = False): +def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) @@ -66,19 +62,20 @@ def onboarding_example(api_key: str, verbose: Optional[bool] = False): # Authenticate a user (only available if a user is already authorized) onboarding.authenticate_user(user_id=user_id, media_data=selfie_media_data) - return isSuccess - -def given_any_selfie_image_media_data(): - return open(f"{RESOURCES_PATH}/selfie.png", "rb").read() +def given_any_selfie_image_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/selfie.png", "rb") as f: + return f.read() -def given_any_document_front_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb").read() +def given_any_document_front_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb") as f: + return f.read() -def given_any_document_back_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb").read() +def given_any_document_back_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb") as f: + return f.read() if __name__ == "__main__": diff --git a/examples/onboarding_get_users.py b/examples/onboarding_get_users.py new file mode 100644 index 0000000..6d083ca --- /dev/null +++ b/examples/onboarding_get_users.py @@ -0,0 +1,24 @@ +import os +from typing import Optional + +from alice import Config, Onboarding + + +def onboarding_get_users_status_example( + api_key: str, verbose: Optional[bool] = False +) -> None: + config = Config(api_key=api_key, verbose=verbose) + onboarding = Onboarding.from_config(config) + + onboarding.get_users().unwrap_or_throw() + onboarding.get_users_status().unwrap_or_throw() + + +if __name__ == "__main__": + api_key = os.environ.get("ONBOARDING_API_KEY") + if api_key is None: + raise AssertionError( + "Please configure your ONBOARDING_API_KEY to run the example" + ) + print("Running onboarding example...") + onboarding_get_users_status_example(api_key=api_key, verbose=True) diff --git a/examples/onboarding_report_v0.py b/examples/onboarding_report_v0.py index 2e41837..353cbb5 100644 --- a/examples/onboarding_report_v0.py +++ b/examples/onboarding_report_v0.py @@ -1,9 +1,6 @@ import os from typing import Optional -from meiga import isSuccess -from meiga.decorators import meiga - from alice import Config, Onboarding from alice.onboarding.enums.document_side import DocumentSide from alice.onboarding.enums.document_type import DocumentType @@ -12,8 +9,7 @@ RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def onboarding_example(api_key: str, verbose: Optional[bool] = False): +def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) @@ -69,24 +65,27 @@ def onboarding_example(api_key: str, verbose: Optional[bool] = False): # Enable authentication for a user # Based on report results and your business logic, you can enable the authentication for a user - onboarding.enable_authentication(user_id=user_id) + onboarding.enable_authentication(user_id=user_id).unwrap_or_throw() # Authenticate a user - onboarding.authenticate_user(user_id=user_id, media_data=selfie_media_data) - - return isSuccess + onboarding.authenticate_user( + user_id=user_id, media_data=selfie_media_data + ).unwrap_or_throw() -def given_any_selfie_image_media_data(): - return open(f"{RESOURCES_PATH}/selfie.png", "rb").read() +def given_any_selfie_image_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/selfie.png", "rb") as f: + return f.read() -def given_any_document_front_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb").read() +def given_any_document_front_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb") as f: + return f.read() -def given_any_document_back_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb").read() +def given_any_document_back_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb") as f: + return f.read() if __name__ == "__main__": diff --git a/examples/onboarding_with_certificate.py b/examples/onboarding_with_certificate.py index 1d94f7a..b16aef7 100644 --- a/examples/onboarding_with_certificate.py +++ b/examples/onboarding_with_certificate.py @@ -2,7 +2,6 @@ from typing import Optional from meiga import isSuccess -from meiga.decorators import meiga from alice import Config, Onboarding from alice.onboarding.enums.document_side import DocumentSide @@ -12,8 +11,7 @@ RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def certified_onboarding(api_key: str, verbose: Optional[bool] = False): +def certified_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) @@ -69,16 +67,19 @@ def certified_onboarding(api_key: str, verbose: Optional[bool] = False): return isSuccess -def given_any_selfie_image_media_data(): - return open(f"{RESOURCES_PATH}/selfie.png", "rb").read() +def given_any_selfie_image_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/selfie.png", "rb") as f: + return f.read() -def given_any_document_front_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb").read() +def given_any_document_front_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb") as f: + return f.read() -def given_any_document_back_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb").read() +def given_any_document_back_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb") as f: + return f.read() if __name__ == "__main__": diff --git a/examples/onboarding_with_identification.py b/examples/onboarding_with_identification.py index 81ba093..b1f93c1 100644 --- a/examples/onboarding_with_identification.py +++ b/examples/onboarding_with_identification.py @@ -1,16 +1,12 @@ import os from typing import Optional -from meiga import isSuccess -from meiga.decorators import meiga - from alice import Config, Onboarding RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def identification_onboarding(api_key: str, verbose: Optional[bool] = False): +def identification_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) @@ -36,19 +32,20 @@ def identification_onboarding(api_key: str, verbose: Optional[bool] = False): ) assert isinstance(identifications.unwrap(), dict) - return isSuccess - -def given_any_selfie_image_media_data(): - return open(f"{RESOURCES_PATH}/selfie.png", "rb").read() +def given_any_selfie_image_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/selfie.png", "rb") as f: + return f.read() -def given_any_document_front_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb").read() +def given_any_document_front_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb") as f: + return f.read() -def given_any_document_back_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb").read() +def given_any_document_back_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb") as f: + return f.read() if __name__ == "__main__": diff --git a/examples/onboarding_with_screening.py b/examples/onboarding_with_screening.py index e597802..0758bdc 100644 --- a/examples/onboarding_with_screening.py +++ b/examples/onboarding_with_screening.py @@ -1,9 +1,6 @@ import os from typing import Optional -from meiga import isSuccess -from meiga.decorators import meiga - from alice import Config, Onboarding, UserInfo from alice.onboarding.enums.document_side import DocumentSide from alice.onboarding.enums.document_type import DocumentType @@ -11,9 +8,7 @@ RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def screening_onboarding(api_key: str, verbose: Optional[bool] = False): - +def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) @@ -56,11 +51,10 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False): user_id=user_id, verbose=verbose ).unwrap_or_throw() - return isSuccess - -def given_any_document_back_media_data(): - return open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb").read() +def given_any_document_back_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb") as f: + return f.read() if __name__ == "__main__": diff --git a/examples/onboarding_with_user_matching.py b/examples/onboarding_with_user_matching.py index ed2b09d..c654ce2 100644 --- a/examples/onboarding_with_user_matching.py +++ b/examples/onboarding_with_user_matching.py @@ -1,17 +1,15 @@ import os from typing import Optional -from meiga import isSuccess -from meiga.decorators import meiga - from alice import Config, Onboarding from alice.onboarding.enums.match_case import MatchCase RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def onboarding_with_user_matching(api_key: str, verbose: Optional[bool] = False): +def onboarding_with_user_matching( + api_key: str, verbose: Optional[bool] = False +) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) @@ -34,11 +32,10 @@ def onboarding_with_user_matching(api_key: str, verbose: Optional[bool] = False) matches = onboarding.user_matching(user_id=user_id, match_case=MatchCase.SELFIE) assert isinstance(matches.unwrap(), list) - return isSuccess - -def given_any_selfie_image_media_data(): - return open(f"{RESOURCES_PATH}/selfie.png", "rb").read() +def given_any_selfie_image_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/selfie.png", "rb") as f: + return f.read() if __name__ == "__main__": diff --git a/examples/onboarding_with_webhooks.py b/examples/onboarding_with_webhooks.py index 0e13be8..b080e08 100644 --- a/examples/onboarding_with_webhooks.py +++ b/examples/onboarding_with_webhooks.py @@ -2,17 +2,14 @@ import secrets from typing import Optional -from meiga import isSuccess from meiga.assertions import assert_success -from meiga.decorators import meiga from alice import Config, Webhook, Webhooks RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" -@meiga -def configure_webhooks(api_key: str, verbose: Optional[bool] = False): +def configure_webhooks(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) webhooks_client = Webhooks.from_config(config) @@ -64,14 +61,12 @@ def configure_webhooks(api_key: str, verbose: Optional[bool] = False): result = webhooks_client.delete_webhook(webhook_id) assert_success(result) - # Retrieve all webhook results of an specific webhook + # Retrieve all webhook results of a specific webhook webhook_results = webhooks_client.get_webhook_results(webhook_id).unwrap() - # Retrieve las webhook result of an specific webhook + # Retrieve las webhook result of a specific webhook last_webhook_result = webhooks_client.get_last_webhook_result(webhook_id).unwrap() - return isSuccess - if __name__ == "__main__": api_key = os.environ.get("ONBOARDING_API_KEY") diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 0cb9b03..fbd3a1d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,4 +1,4 @@ pyjwt>=2.3.0,<3 pydantic>=1.8.2,<3 requests>=2.26.0,<3 -meiga>=1.2.12,<2 \ No newline at end of file +meiga>=1.9.1,<2 \ No newline at end of file From 3bd09d1c64dc5b3e129b4e98604ae0d561a23c41 Mon Sep 17 00:00:00 2001 From: acostapazo Date: Wed, 28 Jun 2023 15:30:56 +0200 Subject: [PATCH 5/9] chore: update meiga usages of unwrap_or_throw() with unwrap_or_raise() --- examples/auth.py | 8 ++++---- examples/onboarding.py | 20 +++++++++++--------- examples/onboarding_get_users.py | 4 ++-- examples/onboarding_report_v0.py | 20 ++++++++++---------- examples/onboarding_with_certificate.py | 16 ++++++++-------- examples/onboarding_with_identification.py | 8 ++++---- examples/onboarding_with_screening.py | 16 ++++++++-------- examples/onboarding_with_user_matching.py | 8 ++++---- examples/sandbox.py | 8 ++++---- tests/test_integration_auth.py | 4 ++-- 10 files changed, 57 insertions(+), 55 deletions(-) diff --git a/examples/auth.py b/examples/auth.py index 60be9af..d5d73c5 100644 --- a/examples/auth.py +++ b/examples/auth.py @@ -22,11 +22,11 @@ def auth_example(api_key: str, user_id: str, verbose: Optional[bool] = False): config = Config(api_key=api_key, verbose=verbose) auth = Auth.from_config(config) - backend_token = auth.create_backend_token().unwrap_or_throw() + backend_token = auth.create_backend_token().unwrap_or_raise() backend_token_with_user = auth.create_backend_token( user_id=user_id - ).unwrap_or_throw() - user_token = auth.create_user_token(user_id=user_id).unwrap_or_throw() + ).unwrap_or_raise() + user_token = auth.create_user_token(user_id=user_id).unwrap_or_raise() return isSuccess @@ -40,6 +40,6 @@ def auth_example(api_key: str, user_id: str, verbose: Optional[bool] = False): verbose = False user_id = get_user_id_from_onboarding( api_key=api_key, verbose=verbose - ).unwrap_or_throw() + ).unwrap_or_raise() print("Running auth example...") auth_example(api_key=api_key, user_id=user_id, verbose=verbose) diff --git a/examples/onboarding.py b/examples/onboarding.py index 0527ccd..1ef6f6c 100644 --- a/examples/onboarding.py +++ b/examples/onboarding.py @@ -17,50 +17,52 @@ def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: document_front_media_data = given_any_document_front_media_data() document_back_media_data = given_any_document_back_media_data() - user_id = onboarding.create_user().unwrap_or_throw() + user_id = onboarding.create_user().unwrap_or_raise() # Upload a selfie (Recommended 1-second video) onboarding.add_selfie( user_id=user_id, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() # Create and upload front and back side from a document document_id = onboarding.create_document( user_id=user_id, type=DocumentType.ID_CARD, issuing_country="ESP" - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, media_data=document_front_media_data, side=DocumentSide.FRONT, manual=True, - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, media_data=document_back_media_data, side=DocumentSide.BACK, manual=True, - ).unwrap_or_throw() + ).unwrap_or_raise() # Generate the report report = onboarding.create_report( user_id=user_id, version=Version.V1 - ).unwrap_or_throw() + ).unwrap_or_raise() if verbose: print(f"report: {report}") href = report.selfies[0].media.get("cropped_face").href - media = onboarding.download(user_id=user_id, href=href).unwrap_or_throw() + media = onboarding.download(user_id=user_id, href=href).unwrap_or_raise() assert isinstance(media, bytes) # Enable authentication for a user # Based on report results and your business logic, you can enable the authentication for a user - onboarding.enable_authentication(user_id=user_id) + onboarding.enable_authentication(user_id=user_id).unwrap_or_raise() # Authenticate a user (only available if a user is already authorized) - onboarding.authenticate_user(user_id=user_id, media_data=selfie_media_data) + onboarding.authenticate_user( + user_id=user_id, media_data=selfie_media_data + ).unwrap_or_raise() def given_any_selfie_image_media_data() -> bytes: diff --git a/examples/onboarding_get_users.py b/examples/onboarding_get_users.py index 6d083ca..7bce9b8 100644 --- a/examples/onboarding_get_users.py +++ b/examples/onboarding_get_users.py @@ -10,8 +10,8 @@ def onboarding_get_users_status_example( config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) - onboarding.get_users().unwrap_or_throw() - onboarding.get_users_status().unwrap_or_throw() + onboarding.get_users().unwrap_or_raise() + onboarding.get_users_status().unwrap_or_raise() if __name__ == "__main__": diff --git a/examples/onboarding_report_v0.py b/examples/onboarding_report_v0.py index 353cbb5..91928bd 100644 --- a/examples/onboarding_report_v0.py +++ b/examples/onboarding_report_v0.py @@ -17,42 +17,42 @@ def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: document_front_media_data = given_any_document_front_media_data() document_back_media_data = given_any_document_back_media_data() - user_id = onboarding.create_user().unwrap_or_throw() + user_id = onboarding.create_user().unwrap_or_raise() # Upload a selfie (Recommended 1-second video) onboarding.add_selfie( user_id=user_id, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() # Create and upload front and back side from a document document_id = onboarding.create_document( user_id=user_id, type=DocumentType.ID_CARD, issuing_country="ESP" - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, media_data=document_front_media_data, side=DocumentSide.FRONT, manual=True, - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, media_data=document_back_media_data, side=DocumentSide.BACK, manual=True, - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_other_trusted_document( user_id=user_id, pdf=document_front_media_data, category="MyCategory", - ).unwrap_or_throw() + ).unwrap_or_raise() # Generate the report report = onboarding.create_report( user_id=user_id, version=Version.V0 - ).unwrap_or_throw() + ).unwrap_or_raise() if verbose: print(f"report: {report}") @@ -60,17 +60,17 @@ def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: media_id = list(report.get("selfie_reports").values())[0].get("media_avatar_id") media = onboarding.retrieve_media( user_id=user_id, media_id=media_id - ).unwrap_or_throw() + ).unwrap_or_raise() assert isinstance(media, bytes) # Enable authentication for a user # Based on report results and your business logic, you can enable the authentication for a user - onboarding.enable_authentication(user_id=user_id).unwrap_or_throw() + onboarding.enable_authentication(user_id=user_id).unwrap_or_raise() # Authenticate a user onboarding.authenticate_user( user_id=user_id, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() def given_any_selfie_image_media_data() -> bytes: diff --git a/examples/onboarding_with_certificate.py b/examples/onboarding_with_certificate.py index b16aef7..ca46d40 100644 --- a/examples/onboarding_with_certificate.py +++ b/examples/onboarding_with_certificate.py @@ -20,17 +20,17 @@ def certified_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: document_front_media_data = given_any_document_front_media_data() document_back_media_data = given_any_document_back_media_data() - user_id = onboarding.create_user().unwrap_or_throw() + user_id = onboarding.create_user().unwrap_or_raise() # Upload a selfie (Recommended 1-second video) onboarding.add_selfie( user_id=user_id, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() # Create and upload front and back side from a document document_id = onboarding.create_document( user_id=user_id, type=DocumentType.ID_CARD, issuing_country="ESP" - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, @@ -38,7 +38,7 @@ def certified_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: side=DocumentSide.FRONT, manual=True, source=DocumentSource.camera, - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, @@ -46,21 +46,21 @@ def certified_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: side=DocumentSide.BACK, manual=True, source=DocumentSource.camera, - ).unwrap_or_throw() + ).unwrap_or_raise() # Create Certificate - certificate_id = onboarding.create_certificate(user_id=user_id).unwrap_or_throw() + certificate_id = onboarding.create_certificate(user_id=user_id).unwrap_or_raise() # Retrieved Certificate from certificate_id certificate = onboarding.retrieve_certificate( user_id=user_id, certificate_id=certificate_id - ).unwrap_or_throw() + ).unwrap_or_raise() # Save PdfReport data to a file with open(f"certificate_{certificate_id}.pdf", "wb") as outfile: outfile.write(certificate) - certificates = onboarding.retrieve_certificates(user_id=user_id).unwrap_or_throw() + certificates = onboarding.retrieve_certificates(user_id=user_id).unwrap_or_raise() assert len(certificates) >= 1 diff --git a/examples/onboarding_with_identification.py b/examples/onboarding_with_identification.py index b1f93c1..5ce4535 100644 --- a/examples/onboarding_with_identification.py +++ b/examples/onboarding_with_identification.py @@ -14,18 +14,18 @@ def identification_onboarding(api_key: str, verbose: Optional[bool] = False) -> selfie_media_data = given_any_selfie_image_media_data() document_front_media_data = given_any_document_front_media_data() - user_id_target = onboarding.create_user().unwrap_or_throw() + user_id_target = onboarding.create_user().unwrap_or_raise() # Upload a selfie (Recommended 1-second video) onboarding.add_selfie( user_id=user_id_target, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() - user_id_probe = onboarding.create_user().unwrap_or_throw() + user_id_probe = onboarding.create_user().unwrap_or_raise() onboarding.add_selfie( user_id=user_id_probe, media_data=document_front_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() identifications = onboarding.identify_user( target_user_id=user_id_target, probe_user_ids=[user_id_probe, user_id_target] diff --git a/examples/onboarding_with_screening.py b/examples/onboarding_with_screening.py index 0758bdc..b836c81 100644 --- a/examples/onboarding_with_screening.py +++ b/examples/onboarding_with_screening.py @@ -16,40 +16,40 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: user_id = onboarding.create_user( user_info=UserInfo(first_name="Carmen", last_name="Espanola") - ).unwrap_or_throw() + ).unwrap_or_raise() # # Create and upload front and back side from a document document_id = onboarding.create_document( user_id=user_id, type=DocumentType.ID_CARD, issuing_country="ESP" - ).unwrap_or_throw() + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, media_data=document_back_media_data, side=DocumentSide.BACK, manual=True, - ).unwrap_or_throw() + ).unwrap_or_raise() # Screening - screening = onboarding.screening(user_id=user_id).unwrap_or_throw() + screening = onboarding.screening(user_id=user_id).unwrap_or_raise() assert isinstance(screening, dict) # Screening (with detail) detailed_screening = onboarding.screening( user_id=user_id, detail=True - ).unwrap_or_throw() + ).unwrap_or_raise() assert isinstance(detailed_screening, dict) # Add user to monitoring list - onboarding.screening_monitor_add(user_id=user_id).unwrap_or_throw() + onboarding.screening_monitor_add(user_id=user_id).unwrap_or_raise() - open_alerts = onboarding.screening_monitor_open_alerts().unwrap_or_throw() + open_alerts = onboarding.screening_monitor_open_alerts().unwrap_or_raise() assert isinstance(open_alerts, dict) onboarding.screening_monitor_delete( user_id=user_id, verbose=verbose - ).unwrap_or_throw() + ).unwrap_or_raise() def given_any_document_back_media_data() -> bytes: diff --git a/examples/onboarding_with_user_matching.py b/examples/onboarding_with_user_matching.py index c654ce2..a3c99c1 100644 --- a/examples/onboarding_with_user_matching.py +++ b/examples/onboarding_with_user_matching.py @@ -16,18 +16,18 @@ def onboarding_with_user_matching( selfie_media_data = given_any_selfie_image_media_data() - user_id = onboarding.create_user().unwrap_or_throw() + user_id = onboarding.create_user().unwrap_or_raise() # Upload a selfie (Recommended 1-second video) onboarding.add_selfie( user_id=user_id, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() - onboarding.void_selfie(user_id=user_id).unwrap_or_throw() + onboarding.void_selfie(user_id=user_id).unwrap_or_raise() onboarding.add_selfie( user_id=user_id, media_data=selfie_media_data - ).unwrap_or_throw() + ).unwrap_or_raise() matches = onboarding.user_matching(user_id=user_id, match_case=MatchCase.SELFIE) assert isinstance(matches.unwrap(), list) diff --git a/examples/sandbox.py b/examples/sandbox.py index b5072f4..70832f0 100644 --- a/examples/sandbox.py +++ b/examples/sandbox.py @@ -14,10 +14,10 @@ def sandbox_example(sandbox_token: str, email: str, verbose: Optional[bool] = Fa config = Config(sandbox_token=sandbox_token, verbose=verbose) sandbox = Sandbox.from_config(config) - user_id = sandbox.create_user(user_info=UserInfo(email=email)).unwrap_or_throw() - user_token = sandbox.get_user_token(email=email).unwrap_or_throw() - user = sandbox.get_user(email=email).unwrap_or_throw() - sandbox.delete_user(email=email).unwrap_or_throw() + user_id = sandbox.create_user(user_info=UserInfo(email=email)).unwrap_or_raise() + user_token = sandbox.get_user_token(email=email).unwrap_or_raise() + user = sandbox.get_user(email=email).unwrap_or_raise() + sandbox.delete_user(email=email).unwrap_or_raise() if verbose: print(f"user_id: {user_id}") diff --git a/tests/test_integration_auth.py b/tests/test_integration_auth.py index c7c793a..05075a5 100644 --- a/tests/test_integration_auth.py +++ b/tests/test_integration_auth.py @@ -14,7 +14,7 @@ def setup_method(self): def _get_user_id(self, config: Config) -> str: onboarding = Onboarding.from_config(config) - return onboarding.create_user().unwrap_or_throw() + return onboarding.create_user().unwrap_or_raise() def should_return_an_error_when_the_api_key_is_not_configured(self): config = Config() @@ -53,7 +53,7 @@ def should_create_a_valid_user_token(self, given_valid_api_key): auth = Auth.from_config(config) onboarding = Onboarding.from_config(config) - user_id = onboarding.create_user().unwrap_or_throw() + user_id = onboarding.create_user().unwrap_or_raise() result = auth.create_user_token(user_id=self._get_user_id(config)) result.assert_success(value_is_instance_of=str) From ae208fc0cbf369907f58cbc310e75b92fe150379 Mon Sep 17 00:00:00 2001 From: acostapazo Date: Thu, 29 Jun 2023 09:06:58 +0200 Subject: [PATCH 6/9] chore: add get_user_status() to examples/onboarding.py --- examples/onboarding.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/onboarding.py b/examples/onboarding.py index 1ef6f6c..838731f 100644 --- a/examples/onboarding.py +++ b/examples/onboarding.py @@ -19,6 +19,8 @@ def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: user_id = onboarding.create_user().unwrap_or_raise() + onboarding.get_user_status(user_id).unwrap_or_raise() + # Upload a selfie (Recommended 1-second video) onboarding.add_selfie( user_id=user_id, media_data=selfie_media_data From 255b6feaff3e11f23d42263a183977b47a2d802d Mon Sep 17 00:00:00 2001 From: Miguel Lorenzo Date: Thu, 29 Jun 2023 10:53:48 +0200 Subject: [PATCH 7/9] fix: add missing front doc side --- examples/onboarding_with_screening.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/examples/onboarding_with_screening.py b/examples/onboarding_with_screening.py index b836c81..813b39e 100644 --- a/examples/onboarding_with_screening.py +++ b/examples/onboarding_with_screening.py @@ -12,6 +12,7 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: config = Config(api_key=api_key, verbose=verbose) onboarding = Onboarding.from_config(config) + document_front_media_data = given_any_document_front_media_data() document_back_media_data = given_any_document_back_media_data() user_id = onboarding.create_user( @@ -22,6 +23,13 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: document_id = onboarding.create_document( user_id=user_id, type=DocumentType.ID_CARD, issuing_country="ESP" ).unwrap_or_raise() + onboarding.add_document( + user_id=user_id, + document_id=document_id, + media_data=document_front_media_data, + side=DocumentSide.FRONT, + manual=True, + ).unwrap_or_raise() onboarding.add_document( user_id=user_id, document_id=document_id, @@ -40,7 +48,7 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: user_id=user_id, detail=True ).unwrap_or_raise() assert isinstance(detailed_screening, dict) - + # # Add user to monitoring list onboarding.screening_monitor_add(user_id=user_id).unwrap_or_raise() @@ -52,6 +60,11 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: ).unwrap_or_raise() +def given_any_document_front_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb") as f: + return f.read() + + def given_any_document_back_media_data() -> bytes: with open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb") as f: return f.read() From 52e6a231accaa2b51fdfcbc5add020710fa80cd8 Mon Sep 17 00:00:00 2001 From: Miguel Lorenzo Date: Thu, 29 Jun 2023 10:55:12 +0200 Subject: [PATCH 8/9] feat: remove unexisting open alerts from python SDK --- alice/onboarding/onboarding.py | 35 ---------------------- alice/onboarding/onboarding_client.py | 42 --------------------------- examples/onboarding_with_screening.py | 5 +--- 3 files changed, 1 insertion(+), 81 deletions(-) diff --git a/alice/onboarding/onboarding.py b/alice/onboarding/onboarding.py index 0427cdd..e4f02d1 100644 --- a/alice/onboarding/onboarding.py +++ b/alice/onboarding/onboarding.py @@ -1155,41 +1155,6 @@ def screening_monitor_delete( ) ) - @early_return - def screening_monitor_open_alerts( - self, start_index: int = 0, size: int = 100, verbose: bool = False - ) -> Result[bool, Union[OnboardingError, AuthError]]: - """ - Retrieves from the monitoring list the users with open alerts - - Parameters - ---------- - start_index - DB index to start (0-2147483647) - size - Numbers of alerts to return (1-100). - verbose - Used for print service response as well as the time elapsed - - Returns - ------- - A Result where if the operation is successful it returns a dictionary. - Otherwise, it returns an OnboardingError or AuthError. - """ - verbose = self.verbose or verbose - response = self.onboarding_client.screening_monitor_open_alerts( - start_index=start_index, size=size, verbose=verbose - ).unwrap_or_return() - - if response.status_code == 200: - return Success(response.json()) - else: - return Failure( - OnboardingError.from_response( - operation="screening_monitor_open_alerts", response=response - ) - ) - @early_return def identify_user( self, diff --git a/alice/onboarding/onboarding_client.py b/alice/onboarding/onboarding_client.py index 0f2b2fd..e552855 100644 --- a/alice/onboarding/onboarding_client.py +++ b/alice/onboarding/onboarding_client.py @@ -1313,48 +1313,6 @@ def screening_monitor_delete( return Success(response) - @early_return - @timeit - def screening_monitor_open_alerts( - self, start_index: int = 0, size: int = 100, verbose: bool = False - ) -> Result[Response, Error]: - """ - Retrieves from the monitoring list the users with open alerts - - Parameters - ---------- - start_index - DB index to start (0-2147483647) - size - Numbers of alerts to return (1-100). - verbose - Used for print service response as well as the time elapsed - - - Returns - ------- - A Result object with Response object [requests library] if Success - """ - print_intro("screening_monitor_open_alerts", verbose=verbose) - - backend_token = self.auth.create_backend_token().unwrap_or_return() - print_token("backend_token", backend_token, verbose=verbose) - headers = self._auth_headers(backend_token) - - try: - response = self.session.get( - f"{self.url}/users/screening/monitor/alerts?start_index={start_index}&size={size}", - headers=headers, - timeout=self.timeout, - ) - except requests.exceptions.Timeout: - return Failure( - OnboardingError.timeout(operation="screening_monitor_open_alerts") - ) - print_response(response=response, verbose=verbose) - - return Success(response) - @early_return @timeit def identify_user( diff --git a/examples/onboarding_with_screening.py b/examples/onboarding_with_screening.py index 813b39e..4b6c458 100644 --- a/examples/onboarding_with_screening.py +++ b/examples/onboarding_with_screening.py @@ -48,13 +48,10 @@ def screening_onboarding(api_key: str, verbose: Optional[bool] = False) -> None: user_id=user_id, detail=True ).unwrap_or_raise() assert isinstance(detailed_screening, dict) - # + # Add user to monitoring list onboarding.screening_monitor_add(user_id=user_id).unwrap_or_raise() - open_alerts = onboarding.screening_monitor_open_alerts().unwrap_or_raise() - assert isinstance(open_alerts, dict) - onboarding.screening_monitor_delete( user_id=user_id, verbose=verbose ).unwrap_or_raise() From 394b856d714f28ddae44ea202995385e91a0b5d0 Mon Sep 17 00:00:00 2001 From: acostapazo Date: Thu, 29 Jun 2023 22:55:13 +0200 Subject: [PATCH 9/9] feat(selfie): add option wait_for_completion --- alice/onboarding/onboarding.py | 15 ++++- alice/onboarding/onboarding_client.py | 9 ++- .../onboarding_wait_for_completion_false.py | 58 +++++++++++++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 examples/onboarding_wait_for_completion_false.py diff --git a/alice/onboarding/onboarding.py b/alice/onboarding/onboarding.py index 4c17272..e874bf1 100644 --- a/alice/onboarding/onboarding.py +++ b/alice/onboarding/onboarding.py @@ -383,7 +383,11 @@ def add_user_feedback( @early_return def add_selfie( - self, user_id: str, media_data: bytes, verbose: Optional[bool] = False + self, + user_id: str, + media_data: bytes, + wait_for_completion: Optional[bool] = True, + verbose: Optional[bool] = False, ) -> Result[bool, Union[OnboardingError, AuthError]]: """ @@ -396,6 +400,8 @@ def add_selfie( User identifier media_data Binary media data. + wait_for_completion + This setting specifies whether or not the request should return immediately or wait for the operation to complete before returning. verbose Used for print service response as well as the time elapsed @@ -407,10 +413,13 @@ def add_selfie( """ verbose = self.verbose or verbose response = self.onboarding_client.add_selfie( - user_id=user_id, media_data=media_data, verbose=verbose + user_id=user_id, + media_data=media_data, + wait_for_completion=wait_for_completion, + verbose=verbose, ).unwrap_or_return() - if response.status_code == 200: + if response.status_code in [200, 201]: return isSuccess else: return Failure( diff --git a/alice/onboarding/onboarding_client.py b/alice/onboarding/onboarding_client.py index 2c125f4..1c9de6f 100644 --- a/alice/onboarding/onboarding_client.py +++ b/alice/onboarding/onboarding_client.py @@ -410,7 +410,11 @@ def add_user_feedback( @early_return @timeit def add_selfie( - self, user_id: str, media_data: bytes, verbose: Optional[bool] = False + self, + user_id: str, + media_data: bytes, + wait_for_completion: Optional[bool] = True, + verbose: Optional[bool] = False, ) -> Result[Response, Error]: """ @@ -423,6 +427,8 @@ def add_selfie( User identifier media_data Binary media data. + wait_for_completion + This setting specifies whether or not the request should return immediately or wait for the operation to complete before returning. verbose Used for print service response as well as the time elapsed @@ -444,6 +450,7 @@ def add_selfie( response = self.session.post( f"{self.url}/user/selfie", files=files, + data={"wait_for_completion": wait_for_completion}, headers=headers, timeout=self.timeout, ) diff --git a/examples/onboarding_wait_for_completion_false.py b/examples/onboarding_wait_for_completion_false.py new file mode 100644 index 0000000..93c957c --- /dev/null +++ b/examples/onboarding_wait_for_completion_false.py @@ -0,0 +1,58 @@ +import os +from time import sleep +from typing import Optional + +from alice import Config, Onboarding +from alice.onboarding.enums.version import Version + +RESOURCES_PATH = f"{os.path.dirname(os.path.abspath(__file__))}/../resources" + + +def onboarding_example(api_key: str, verbose: Optional[bool] = False) -> None: + config = Config( + api_key=api_key, + verbose=verbose, + onboarding_url="https://apis.staging.alicebiometrics.com/onboarding", + ) + onboarding = Onboarding.from_config(config) + + selfie_media_data = given_any_selfie_image_media_data() + + user_id = onboarding.create_user().unwrap_or_raise() + + onboarding.get_user_status(user_id).unwrap_or_raise() + + # Upload a selfie (Recommended 1-second video) + onboarding.add_selfie( + user_id=user_id, media_data=selfie_media_data, wait_for_completion=True + ).unwrap_or_raise() + + print("Waiting 4 seconds...") + sleep(4) + + # Generate the report + report = onboarding.create_report( + user_id=user_id, version=Version.V1 + ).unwrap_or_raise() + + if verbose: + print(f"report: {report}") + + href = report.selfies[0].media.get("cropped_face").href + media = onboarding.download(user_id=user_id, href=href).unwrap_or_raise() + assert isinstance(media, bytes) + + +def given_any_selfie_image_media_data() -> bytes: + with open(f"{RESOURCES_PATH}/selfie.png", "rb") as f: + return f.read() + + +if __name__ == "__main__": + api_key = os.environ.get("ONBOARDING_API_KEY") + if api_key is None: + raise AssertionError( + "Please configure your ONBOARDING_API_KEY to run the example" + ) + print("Running onboarding example...") + onboarding_example(api_key=api_key, verbose=True)