diff --git a/backend/api/blueprints/leads.py b/backend/api/blueprints/leads.py index 9516460..e83b101 100644 --- a/backend/api/blueprints/leads.py +++ b/backend/api/blueprints/leads.py @@ -1,4 +1,7 @@ +import re from flask import Blueprint, request +from pydantic.class_validators import validator +from pydantic.networks import EmailStr, HttpUrl import sqlalchemy.exc as sa_exc from sqlalchemy import text @@ -6,7 +9,8 @@ from ..auth import auth from ..db import db from ..pagination import parse_pagination_params - +from .users import get_user_by_username +from pydantic import BaseModel, ValidationError leads_bp = Blueprint("leads", __name__) @@ -361,6 +365,43 @@ def _create_new_lead(request, valid_data_sources=VALID_DATA_SOURCES): if not all(c.isalnum() or c.isspace() or c == "." or c == "&" or c == "'" for c in company_name): return {"message": "company_name can only contain a-z, 0-9, ., &, ', whitespace"}, 400 + # using pydantic model to check phone number, assigned, email and social media urls + class FieldTestModel(BaseModel): + phoneNum: str + assigned: str + email: EmailStr + socialLink: HttpUrl + + @validator("phoneNum", allow_reuse=True) + def check_phoneNumber_format(cls, v): + regExs = (r"\(\w{3}\) \w{3}\-\w{4}", r"^\w{3}\-\w{4}$") + if not re.search(regExs[0], v): + return ValueError("not match") + return v + + @validator("assigned", allow_reuse=True) + def check_assigned(cls, v): + user_response = get_user_by_username(v) + if not user_response: + raise ValueError(f"{v!r} is not a registered user") + return v + + try: + phoneNum = str(body.get("phone")).strip() + assigned = body.get("assigned") + email = EmailStr(body.get("email")) + link = body.get("twitter") + + testInstance = FieldTestModel(phoneNum=phoneNum, assigned=assigned, email=email, socialLink=link) + + testInstance.socialLink = link + link = body.get("facebook") + testInstance.socialLink = link + link = body.get("instagram") + testInstance.socialLink = link + except ValidationError as err: + return {"message": "{error}".format(error=err.errors()[0])} + # validate data source field data_source = body.get("data_source") if data_source: diff --git a/backend/requirements-prod.txt b/backend/requirements-prod.txt index 1183caa..ebe6b65 100644 --- a/backend/requirements-prod.txt +++ b/backend/requirements-prod.txt @@ -5,6 +5,7 @@ chardet==4.0.0 click==7.1.2 cryptography==3.4.7 ecdsa==0.17.0 +email-validator flasgger==0.9.5 Flask==1.1.2 Flask-Cors==3.0.10 @@ -14,12 +15,14 @@ gunicorn==20.1.0 idna==2.10 itsdangerous==2.0.1 Jinja2==3.0.1 +marshmallow==3.14.0 Mako==1.1.4 MarkupSafe==2.0.1 passlib==1.7.4 psycopg2-binary==2.8.6 pyasn1==0.4.8 pycparser==2.20 +pydantic==1.8.2 python-dateutil==2.8.1 python-editor==1.0.4 python-jose==3.3.0 diff --git a/backend/requirements.txt b/backend/requirements.txt index 8fc978e..e1d0291 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,12 +1,17 @@ alembic==1.6.0 appdirs==1.4.4 +attrs==21.2.0 +autopep8==1.5.7 black==21.6b0 certifi==2020.12.5 cffi==1.14.5 chardet==4.0.0 +charset-normalizer==2.0.7 click==7.1.2 +colorama==0.4.4 cryptography==3.4.7 ecdsa==0.17.0 +email-validator==1.1.3 flake8==3.9.2 flasgger==0.9.5 Flask==1.1.2 @@ -17,9 +22,11 @@ gunicorn==20.1.0 idna==2.10 itsdangerous==2.0.1 Jinja2==3.0.1 +jsonschema==4.1.0 Mako==1.1.4 MarkupSafe==2.0.1 mccabe==0.6.1 +mistune==0.8.4 mypy-extensions==0.4.3 passlib==1.7.4 pathspec==0.8.1 @@ -27,17 +34,21 @@ psycopg2-binary==2.8.6 pyasn1==0.4.8 pycodestyle==2.7.0 pycparser==2.20 +pydantic==1.8.2 pyflakes==2.3.1 +pyrsistent==0.18.0 python-dateutil==2.8.1 python-editor==1.0.4 python-jose==3.3.0 pytz==2021.1 PyYAML==5.4.1 regex==2021.7.6 -requests==2.25.1 +requests==2.26.0 rsa==4.7.2 six==1.16.0 SQLAlchemy==1.4.13 toml==0.10.2 +typing-extensions==3.10.0.2 urllib3==1.26.5 Werkzeug==2.0.1 +yattag==1.14.0