示例#1
0
    def __init__(
        self,
        *,
        host: str = BASE_URL,
        clientId: str = None,
        clientSecret: str = None,
        customerToken: str = None,
        flag: str = 'mgmt',
    ):
        self.host = host[:-1] if host.endswith('/') else host
        self.clientId = clientId
        self.clientSecret = clientSecret
        self.ssoCustomerToken = customerToken
        self.flag = flag
        self.session = requests.Session()

        if self.flag not in ('mgmt', 'sso'):
            raise e.KnowiException(
                f'invalid flag=`{flag}`. supported flag inputs are (`mgmt` or `sso`)'
            )

        if self.flag == 'mgmt':
            if not all([clientId, clientSecret]):
                raise e.KnowiException(
                    f'client id/secret needed to use management api with flag=`{flag}`'
                )
            else:
                self.auth()
        if self.flag == 'sso' and not customerToken:
            raise e.KnowiException(
                f'sso customer token needed to use single sign on api with flag=`{flag}`'
            )
示例#2
0
def _validateContentFilters(contentFilter: List[dict] = None):
    """ validate passed arguments in constructing a user or customer content filter

    :param contentFilter: parsing contentFilters as arrays of dict i.e.
    [{"fieldName": "Zip Code", "values": ["11787"], "operator": "="}]
    :return:
    """

    OPERATOR_NAME = [
        'equals', 'not equals', 'greater than', 'greater than or equals',
        'less than', 'less than or equals', 'contains', 'does not contain'
    ]
    OPERATOR_VALUE = ['=', '!=', '>', '>=', '<', '<=', 'like', 'not like']
    CONTENT_FILTER_FIELDS = ['fieldName', 'values', 'operator']

    if contentFilter and isinstance(contentFilter, list):
        for i in contentFilter:
            if all(elem in list(i) for elem in CONTENT_FILTER_FIELDS):
                filterValue = i['values']
                if not isinstance(i['values'], list):
                    i['values'] = [str(filterValue)]

                if i.get('operator') not in chain(OPERATOR_NAME,
                                                  OPERATOR_VALUE):
                    raise e.KnowiException(
                        f"invalid `operator` value in contentFilter= `{i['operator']}` "
                    )

            else:
                raise e.KnowiException(
                    f"missing/invalid contentFilter parameter. must have {CONTENT_FILTER_FIELDS}"
                )

    return contentFilter
示例#3
0
    def api_call(self,
                 apiMethod: str,
                 httpVerb: str,
                 *,
                 files: dict = None,
                 data: dict = None,
                 params: dict = None,
                 json: dict = None):
        """Create a request and execute the API call to Knowi.

        :param apiMethod: The target Knowi API method.
        :param httpVerb: HTTP Verb. e.g. 'GET'
        :param files:
        :param data: The body to attach to the request. If a dictionary is
                provided, form-encoding will take place.
                e.g. {'key1': 'value1', 'key2': 'value2'}
        :param params: The URL parameters to append to the URL.
                e.g. {'key1': 'value1', 'key2': 'value2'}
        :param json: JSON for the body to attach to the request
                (if files or data is not specified).
                e.g. {'key1': 'value1', 'key2': 'value2'}
        :return:
        """

        if apiMethod.startswith("/sso/") and self.flag != "sso":
            raise e.KnowiException(
                f'invalid method=`{apiMethod}` with flag=`{self.flag}`, use flag `sso`'
            )
        if not apiMethod.startswith('/sso') and self.flag == 'sso':
            raise e.KnowiException(
                f'invalid method=`{apiMethod}` with flag=`{self.flag}` use flag `mgmt`'
            )

        apiUrl = self._get_url(apiMethod)
        if data:
            data = cleanNullTerms(data)
        elif json:
            json = cleanNullTerms(json)
        requestArgs = {
            "data": data,
            "files": files,
            "params": params,
            "json": json
        }

        return self._request(httpVerb=httpVerb,
                             apiUrl=apiUrl,
                             requestArgs=requestArgs)
示例#4
0
    def wrapper(*args, **kwargs):

        props = kwargs['queryProperty']['properties']
        if props.get('categories'):
            if not isinstance(props['categories'], list):
                kwargs['queryProperty']['properties']['categories'] = [
                    props['categories']
                ]

        if props.get("direct"):
            if not isinstance("direct", bool):
                raise e.KnowiException(
                    f"invalid `direct` type, should be a bool: (`True`, `False`)"
                )

        if props.get("jsonPayload") and props.get("urlParams"):
            raise e.KnowiException(
                f"invalid attributes. Can't use both `jsonPayload` and `urlParams`"
            )
        return func(*args, **kwargs)
示例#5
0
    def wrapper(*args, **kwargs):
        if kwargs.get('shareProperty') or kwargs.get('userGroups'):
            shareProperties = kwargs.get('shareProperty') or kwargs.get(
                'userGroups')

            for i in shareProperties:
                if 'type' not in i:
                    raise e.KnowiException(
                        'missing attribute `type` in shareProperty')
                i['type'] = i['type'].capitalize()

                # sharing to users
                if i["type"] == 'Users':
                    if not all(key in i for key in ['access_level', 'name']):
                        raise e.KnowiException(
                            f"invalid/missing user property  key. must include: {SHARE_TO_USERS}"
                        )
                    if i['access_level'] not in ACCESS_LEVEL:
                        raise e.KnowiException(
                            f'invalid/missing property. access_level must be 1 or 2'
                        )

                # sharing to group
                elif i['type'] == 'Groups':
                    if not all(key in i for key in ['access_level', 'id']):
                        raise e.KnowiException(
                            f"invalid/missing group property. must include: {SHARE_TO_GROUPS}"
                        )
                    if i['access_level'] not in ACCESS_LEVEL:
                        raise ValueError(
                            f'missing/invalid property. access_level must be 1 or 2'
                        )
                else:
                    raise ValueError(
                        f"Invalid share `type`. allowed values: (`users`, `groups`)"
                    )

        return func(*args, **kwargs)
示例#6
0
    def wrapper(*args, **kwargs):

        if 'datasource' not in kwargs:
            raise e.KnowiException('missing parameter "datasource"')

        if kwargs.get('datasource') not in SUPPORTED_DATASOURCES:
            raise e.KnowiException(
                f" invalid/unsupported datasource={kwargs['datasource']}")

        if kwargs.get('datasource') == 'restapi':
            if 'url' not in kwargs:
                raise e.KnowiException(
                    f'Missing restapi host url={kwargs["url"]}')

        if kwargs['privateDatasource']:
            if not kwargs.get('privateConnector'):
                raise e.KnowiException(
                    'privateConnector is needed with a privateDatasource')
        if kwargs.get('tunnel'):
            if 'tunnelAddress' not in kwargs:
                raise e.KnowiException('tunnelAddress is needed with tunnel')

        return func(*args, **kwargs)
示例#7
0
    def wrapper(*args, **kwargs):

        if kwargs.get('timezone'):
            userTz = kwargs.get('timezone')
            if not isinstance(userTz, str):
                raise TypeError(
                    f"Got {type(userTz)}, expected type is string, {userTz}")
            if userTz not in pytz.all_timezones:
                raise ValueError(
                    f"Invalid timezone `{userTz}`! \n"
                    f"For reference, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
                )

        if kwargs.get('twoFA'):
            twoFA = kwargs.get('twoFA')
            phone = kwargs.get('phone')
            if not isinstance(kwargs.get('twoFA'), bool):
                raise TypeError(
                    f"`twoFA` type must be bool. Got {type(twoFA)}.")
            if not phone:
                raise ValueError(
                    f"`phone` is needed with twoFactorAuth= {twoFA}")

        if kwargs.get('phone'):
            kwargs['phone'] = str(kwargs.get('phone'))

        if kwargs.get('userInviteJson'):
            userProps = kwargs.get('userInviteJson')
            addGroups = userProps.get('userGroups', [])
            for i in addGroups:
                if not all(s in ['access_level', 'id'] for s in list(i)):
                    raise ValueError(
                        f'missing/invalid userGroups property: {i}')

        if kwargs.get('contentFilters') or kwargs.get('contentFilter'):
            userFilter = kwargs.get('contentFilter') or kwargs.get(
                'contentFilters')
            _validateContentFilters(userFilter)

        # editing existing user groups
        if kwargs.get('groups'):
            userGroups = kwargs.get("groups")
            if not isinstance(userGroups, List):
                raise TypeError(f"groups must be a array of dicts")

            for i in userGroups:
                if not all(key in i for key in ['access_level', 'id']):
                    raise e.KnowiException(
                        'missing/invalid properties. Required keys are `access_level` `id`'
                    )
                if i['access_level'] not in ACCESS_LEVEL:
                    raise e.KnowiException(
                        f'access_level must be `1` or `2`, got {i["access_level"]}'
                    )

        if kwargs.get('autoShareTo'):
            autoShare = kwargs.get('autoShareTo')
            if isinstance(autoShare, dict):
                autoShare = [autoShare]
            else:
                raise TypeError('`autoShareTo` must be dict of array of dict ')

            for i in autoShare:
                if not all(key in i for key in ['id']):
                    raise e.KnowiException('missing `id` field')

        return func(*args, **kwargs)