Пример #1
0
def check_auth_params(url, body):
    '''
    This function checks the validity of the authParams parameter as per the
    API. It takes the decoded json body of the request and raises an exception
    if a problem is found.

    The difference between check_auth_params and check_publisher_auth_params
    is that check_auth_params enforces validity to the API. In contrast,
    check_publisher_auth_params enforces validity as to this implementation.
    It checks specifically for the existence of the "username" and "password"
    fields.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthParams:

            Returned when the request does not specify the authParams parameter
            properly.

            Code: InvalidAuthParams
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthParams'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Note that not having an authParams key is valid.
    if 'authParams' not in body:
        return

    # When authParams is provided, the type must be a dictionary.
    if not isinstance(body['authParams'], dict):
        debug = 'The authParams is not a map.'
        raise_error(url, code, message, status, debug)

    # Make sure that all the values in the dictionary are strings.
    for key in body['authParams']:
        value = body['authParams'][key]
        if not isinstance(value, unicode) and not isinstance(value, str):
            debug = 'This authParams value is not a string: ' + unicode(key)
            raise_error(url, code, message, status, debug)
Пример #2
0
def check_auth_params(url, body):
    '''
    This function checks the validity of the authParams parameter as per the
    API. It takes the decoded json body of the request and raises an exception
    if a problem is found.

    The difference between check_auth_params and check_publisher_auth_params
    is that check_auth_params enforces validity to the API. In contrast,
    check_publisher_auth_params enforces validity as to this implementation.
    It checks specifically for the existence of the "username" and "password"
    fields.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthParams:

            Returned when the request does not specify the authParams parameter
            properly.

            Code: InvalidAuthParams
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthParams'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Note that not having an authParams key is valid.
    if 'authParams' not in body:
        return

    # When authParams is provided, the type must be a dictionary.
    if not isinstance(body['authParams'], dict):
        debug = 'The authParams is not a map.'
        raise_error(url, code, message, status, debug)

    # Make sure that all the values in the dictionary are strings.
    for key in body['authParams']:
        value = body['authParams'][key]
        if not isinstance(value, unicode) and not isinstance(value, str):
            debug = 'This authParams value is not a string: ' + unicode(key)
            raise_error(url, code, message, status, debug)
Пример #3
0
def decode_body(url, body):
    '''
    This function checks the validity of the body parameter. It takes the
    request body and returns python objects by decoding the body using
    json.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidFormat:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidFormat
            Message: The requested article could not be found.
            Debug: Varies with the error.
            HTTP Error Code: 400.
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidFormat'
    status = 400
    message = 'An error occurred. Please contact support.'

    # If the body cannot be decoded, a proper error response must be made.
    # This try except block intercepts the default exception and raises
    # a json encoded exception using the raise_error function.
    try:
        json_body = loads(body, encoding='utf-8')

    except ValueError:
        # If a ValueError occurred, the json decoder could not decode the
        # body of the request. We need to return an error to the client.
        # Note that we do not return the body of the request as it could
        # contain access credentials.
        debug = 'Could not decode post body. json is expected.'
        raise_error(url, code, message, status, debug)

    # Make sure a valid number of parameters have been provided.
    if len(json_body) < 1 or len(json_body) > 2:
        debug = 'Post body has an invalid number of parameters.'
        raise_error(url, code, message, status, debug)

    return json_body
Пример #4
0
def decode_body(url, body):
    '''
    This function checks the validity of the body parameter. It takes the
    request body and returns python objects by decoding the body using
    json.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidFormat:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidFormat
            Message: The requested article could not be found.
            Debug: Varies with the error.
            HTTP Error Code: 400.
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidFormat'
    status = 400
    message = 'An error occurred. Please contact support.'

    # If the body cannot be decoded, a proper error response must be made.
    # This try except block intercepts the default exception and raises
    # a json encoded exception using the raise_error function.
    try:
        json_body = loads(body, encoding='utf-8')

    except ValueError:
        # If a ValueError occurred, the json decoder could not decode the
        # body of the request. We need to return an error to the client.
        # Note that we do not return the body of the request as it could
        # contain access credentials.
        debug = 'Could not decode post body. json is expected.'
        raise_error(url, code, message, status, debug)

    # Make sure a valid number of parameters have been provided.
    if len(json_body) < 1 or len(json_body) > 2:
        debug = 'Post body has an invalid number of parameters.'
        raise_error(url, code, message, status, debug)

    return json_body
Пример #5
0
def check_authorization_header(url, environment):
    '''
    Checks for the existence of the auth-scheme token. Note that the validate
    API entry point has a different auth-scheme token.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthScheme:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidAuthScheme
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400.
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthScheme'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Make sure the token is provided.
    if 'HTTP_AUTHORIZATION' not in environment:
        debug = 'The authorization token has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure the token's value is correct. The auth-scheme token isn't
    # important for this part of the API, but it is for others.
    if environment['HTTP_AUTHORIZATION'] != AUTH_AUTHORIZATION_HEADER:
        debug = 'The authorization token is incorrect.'
        raise_error(url, code, message, status, debug)
Пример #6
0
def check_authorization_header(url, environment):
    '''
    Checks for the existence of the auth-scheme token. Note that the validate
    API entry point has a different auth-scheme token.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthScheme:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidAuthScheme
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400.
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthScheme'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Make sure the token is provided.
    if 'HTTP_AUTHORIZATION' not in environment:
        debug = 'The authorization token has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure the token's value is correct. The auth-scheme token isn't
    # important for this part of the API, but it is for others.
    if environment['HTTP_AUTHORIZATION'] != AUTH_AUTHORIZATION_HEADER:
        debug = 'The authorization token is incorrect.'
        raise_error(url, code, message, status, debug)
Пример #7
0
def get_session_id(url, environment):
    '''
    Checks for the existence of the auth-scheme token and then extracts the
    session id and returns it. Note that the auth API entry point has a
    different auth-scheme token.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthScheme:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidAuthScheme
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400.
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthScheme'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Make sure the token is provided.
    if 'HTTP_AUTHORIZATION' not in environment:
        debug = 'The authorization token has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure the token's value is correct. This token contains the session
    # id. It is not passed in the http body.
    token = environment['HTTP_AUTHORIZATION']
    scheme = SESSION_AUTHORIZATION_HEADER + ' session:'
    if not token.startswith(scheme):
        debug = 'The authorization token is incorrect.'
        raise_error(url, code, message, status, debug)

    # Try to extract the session key. The syntax below extracts the characters
    # from the length of the scheme string to the end. Note that whitespace
    # characters are stripped from the session_id.
    session_id = token[len(scheme):].strip()

    # Check to make sure a session id has actually been provided.
    if len(session_id) == 0:
        debug = 'The session id has not been provided.'
        raise_error(url, code, message, status, debug)

    # Return the session key.
    return session_id
Пример #8
0
def check_publisher_auth_params(url, body):
    '''
    This function checks for the existence of the authParams dictionary and
    the exiistence of the "username" and "password" keys in the authParams
    dictionary.

    The difference between check_auth_params and check_publisher_auth_params
    is that check_auth_params enforces validity to the API. In contrast,
    check_publisher_auth_params enforces validity as to this implementation.
    It checks specifically for the existence of the "username" and "password"
    fields.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthParams:

            Returned when the request does not specify the authParams parameter
            properly.

            Code: InvalidAuthParams
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthParams'
    status = 400
    message = 'An error occurred. Please contact support.'

    # In this implementation, authParams is required. The check for authParams
    # being a dictionary has already been carried out by check_auth_params.
    if 'authParams' not in body:
        debug = 'The authParams has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure username is provided. The check_auth_params has already
    # checked the type of the username.
    if 'username' not in body['authParams']:
        debug = 'The username has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure password is provided. The check_auth_params has already
    # checked the type of the password.
    if 'password' not in body['authParams']:
        debug = 'The password has not been provided.'
        raise_error(url, code, message, status, debug)
Пример #9
0
def check_publisher_auth_params(url, body):
    '''
    This function checks for the existence of the authParams dictionary and
    the exiistence of the "username" and "password" keys in the authParams
    dictionary.

    The difference between check_auth_params and check_publisher_auth_params
    is that check_auth_params enforces validity to the API. In contrast,
    check_publisher_auth_params enforces validity as to this implementation.
    It checks specifically for the existence of the "username" and "password"
    fields.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidAuthParams:

            Returned when the request does not specify the authParams parameter
            properly.

            Code: InvalidAuthParams
            Message: An error occurred. Please contact support.
            Debug: Varies with the error.
            HTTP Error Code: 400
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidAuthParams'
    status = 400
    message = 'An error occurred. Please contact support.'

    # In this implementation, authParams is required. The check for authParams
    # being a dictionary has already been carried out by check_auth_params.
    if 'authParams' not in body:
        debug = 'The authParams has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure username is provided. The check_auth_params has already
    # checked the type of the username.
    if 'username' not in body['authParams']:
        debug = 'The username has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure password is provided. The check_auth_params has already
    # checked the type of the password.
    if 'password' not in body['authParams']:
        debug = 'The password has not been provided.'
        raise_error(url, code, message, status, debug)
Пример #10
0
def validate(request, api, version, format, product_code):
    '''
    Overview:

        Attempt an authorization for a product using supplied session key
        (transmitted via the Authorization header). This API call is used
        periodically to validate that the session is still valid and the user
        should continue to be allowed to access protected resources. If the
        call returns a 401, a new authentication call must be made. The base
        URL scheme for this entry point is:

            /:api/:version/:format/validate/:productcode

        In this particular case, the api is "paywallproxy" and the version is
        v1.0.0. Currently, the only supported format is "json". The URL for
        this entry point therefore looks like:

            /paywallproxy/v1.0.0/json/validate/:productcode

        If the product cannot be found, an "InvalidProduct" error should be
        returned. This error will be returned to the client. A full list of
        errors that this entry point returns is available below. Client errors
        are proxied to the client. Server errors remain on Polar's server.

    Parameters:

        There are two sets of parameters that this API entry point requires.
        The first set consists of the product code, which is specified in the
        URL and the session id, which is specified in the authorization header.

        The product code is part of the URL. It is a publisher-assigned unique
        identifier for this product. The product code is required.

        An auth-scheme token is expected when a call is made to this API end
        point. It must conform to RFC 2617 specifications. The authorization
        header has the following form:

            Authorization: PolarPaywallProxySessionv1.0.0 session:<session id>

        Note that the session id is passed as a parameter through the
        authorization token.

        Details regarding the various parameters are described below.

        Product Code:

            A publisher-assigned unique identifier for this product.

            Availability: >= v1.0.0
            Required: Yes
            Location: URL
            Format: URL
            Type: String
            Max Length: 256

        Session Id:

            A session id generated by calling the auth entry point of this
            API.

            Availability: >= v1.0.0
            Required: Yes
            Location: Header
            Format: Header
            Type: String
            Max Length: 512

    Response:

        The following parameters are returned by this API end point. The
        resposne is json encoded. It has two keys; "sessionKey" and "products".
        "sessionKey" is a key that allows the client to re-authenticate without
        the supplied authentication parameters. "products" is a list of product
        identifiers that the user has access to.

        sessionKey:

            A key that allows the client to re-authenticate without the
            supplied authentication parameters.

            Availability: >= v1.0.0
            Required: Yes
            Location: POST Body
            Format: json
            Type: string
            Max Length: 512

        products:

            A list of product identifiers that the user has access to.

            Availability: >= v1.0.0
            Required: Yes
            Location: POST Body
            Format: json
            Type: list
            Max Length: N/A

        product:

            A publisher-assigned unique identifier for this product that the
            user has access to. Contained in the "products" list.

            Availability: >= v1.0.0
            Required: Yes
            Location: POST Body
            Format: json
            Type: string
            Max Length: 256

    Example:

        Example Request:

            POST /validate/gold-level HTTP/1.1
            Authorization: PolarPaywallProxySessionv1.0.0 session:9c4a51cc08d1

        Example Response:

            HTTP/1.1 200 OK
            Content-Type: application/json

            {
                "sessionKey": "9c4a51cc08d1",

                "products": [
                    "gold-level",
                    "silver-level"
                ]
            }

    Errors:

        Some of the following errors are marked optional. They are included in
        this example for completeness and testing purposes. Implementing them
        makes testing the connection between Polar's server and the publishers
        server easier.

        AccountProblem:

            There is a problem with the user's account. The user is
            prompted to contact technical support.

            Code: InvalidPaywallCredentials
            Message: Your account is not valid. Please contact support.
            HTTP Error Code: 403
            Required: Yes

        InvalidProduct:

            Thrown when the product code indicated is invalid.

            Code: InvalidProduct
            Message: The requested article could not be found.
            HTTP Error Code: 404
            Required: Yes

        SessionExpired:

            The session key provided has expired. Re-authenticate (to obtain
            a new session key) and retry the request.

            Code: SessionExpired
            Message: The session key provided has expired.
            HTTP Error Code: 401
            Required: Yes

        InvalidAPI:

            Returned when the publisher does not recognize the requested api.

            Code: InvalidAPI
            Message: An error occurred. Please contact support.
            Debug: The requested api is not implemented: <api>
            HTTP Error Code: 404
            Required: No

        InvalidVersion:

            Returned when the publisher does not recognize the requested
            version.

            Code: InvalidVersion
            Message: An error occurred. Please contact support.
            Debug: The requested version is not implemented: <version>
            HTTP Error Code: 404
            Required: No

        InvalidFormat:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidFormat
            Message: An error occurred. Please contact support.
            Debug: The requested format is not implemented: <format>
            HTTP Error Code: 404
            Required: No

        InvalidAuthScheme:

            Returned when the publisher does not recognize the requested
            format.

            Code: InvalidAuthScheme
            Message: An error occurred. Please contact support.
            Message: Varies with the error.
            HTTP Error Code: 400.
            Required: No
    '''
    # Store the full URL string so that it can be used to report errors.
    url = request.path

    # Validate the request.
    check_base_url(url, api, version, format)
    if len(request.body.strip()) > 0:
        # If there is a body for this API call, that implies that the caller
        # is not conforming to the API, so raise an error.
        code = 'InvalidFormat'
        message = 'Invalid post body.'
        status = 400
        raise_error(url, code, message, status)

    # Validate the session id using the data model.
    session_id = get_session_id(url, request._environ)
    products = model().validate_session(url, session_id, product_code)

    # Create the response body.
    result = {}
    result['sessionKey'] = session_id
    result['products'] = products
    content = dumps(result)

    status = 200
    headers = []
    content_type = 'application/json'
    return Response(content, headers, status, content_type)
Пример #11
0
def check_device(url, body):
    '''
    This function checks the validity of the device parameter. It takes the
    decoded json body of the request and raises an error if a problem is
    found.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidDevice:

            Returned when the request does not specify the device parameters
            properly.

            Code: InvalidDevice
            Message: The requested article could not be found.
            Debug: Varies with the error.
            HTTP Error Code: 400
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidDevice'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Validate that the device is provided as a parameter to the body. This
    # sample publisher does not store the device, but a production system
    # could store these values in order to perform analysis on the types of
    # devices that access products.
    if 'device' not in body:
        debug = 'The device has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure the device is a dictionary.
    if not isinstance(body['device'], dict):
        debug = 'The device is not a map.'
        raise_error(url, code, message, status, debug)

    # Check to make sure that the manufacturer of the device has been
    # provided.
    if 'manufacturer' not in body['device']:
        debug = 'The manufacturer has not been provided.'
        raise_error(url, code, message, status, debug)

    # Check to make sure the manufacturer is of the right type.
    manufacturer = body['device']['manufacturer']
    if not isinstance(manufacturer, unicode) and \
       not isinstance(manufacturer, str):
        debug = 'The manufacturer is not a string.'
        raise_error(url, code, message, status, debug)

    # Check to make sure that the model of the device has been provided.
    if 'model' not in body['device']:
        debug = 'The model has not been provided.'
        raise_error(url, code, message, status, debug)

    # Check to make sure the model is of the right type.
    model = body['device']['model']
    if not isinstance(model, unicode) and \
       not isinstance(model, str):
        debug = 'The model is not a string.'
        raise_error(url, code, message, status, debug)

    # Check to make sure that the os_version of the device has been provided.
    if 'os_version' not in body['device']:
        debug = 'The os_version has not been provided.'
        raise_error(url, code, message, status, debug)

    # Check to make sure the os_version is of the right type.
    os_version = body['device']['os_version']
    if not isinstance(os_version, unicode) and \
       not isinstance(os_version, str):
        debug = 'The os_version is not a string.'
        raise_error(url, code, message, status, debug)
Пример #12
0
    def validate_session(self, url, session_id, product):
        '''
        This function takes a session id, attempts to find the users that
        it is associated with. If it finds a user, it first updates the
        session tokens and then checks to make sure that the session key
        is still valid. It then returns the list of products that the user
        has access to. If it finds no user, it reports that the session key
        has been expired.

        Client Errors:

            This section documents errors that are returned to the client. Note
            that the publisher is free to modify the content of these messages
            as they please.

            SessionExpired:

                Thrown when the session id cannot be validated.

                Code: SessionExpired
                Message: Your session has expired. Please log back in.
                HTTP Error Code: 401
                Required: Yes

            AccountProblem:

                There is a problem with the user's account. The user is
                prompted to contact technical support.

                Code: AccountProblem
                Message: Your account is not valid. Please contact support.
                HTTP Error Code: 403
                Required: Yes
        '''
        self.lock.acquire()
        try:
            # Most of the errors in this function share a common code and
            # status.
            code = 'SessionExpired'
            status = 401
            message = 'Your session has expired. Please log back in.'

            # Loop over all of the users and check for the valid session id.
            for username in model.users:
                # If the session id does not belong to this user, keep
                # searching.
                if session_id not in model.users[username]['session ids']:
                    continue

                # Check to see if the user is valid. The check for a valid
                # account should come after the check for the session id as
                # the password validates the user's identity.
                if not model.users[username]['valid']:
                    code = 'AccountProblem'
                    message = ('Your account is not valid. Please contact '
                               'support.')
                    status = 403
                    raise_error(url, code, message, status)

                # Check to make sure the product is valid.
                if product not in model.users[username]['products']:
                    code = 'InvalidProduct'
                    message = 'The requested article could not be found.'
                    status = 404
                    raise_error(url, code, message, status)

                # Update the list of valid session ids; the session may have
                # expired since the last validation.
                self.update_session_ids(username)

                # Check to see if the session id is valid; it may have been
                # invalidated by the call to update_session_ids.
                if session_id not in model.users[username]['session ids']:
                    message = 'Your session has expired. Please log back in.'
                    raise_error(url, code, message, status)

                # Check to see if the session key is registered against the
                # right product. The only way this can happen during normal
                # operation is if a product that the user has authenticated
                # has been deleted.
                session = model.users[username]['session ids'][session_id]
                stored_product, timestamp = session
                if product != stored_product:
                    # Their session has expired.
                    raise_error(url, code, message, status)

                # Return the user's products, which indicate a successful
                # validation.
                products = model.users[username]['products']
                return products

            # If nothing has been returned at this point, raise an error.
            # We can only assume that their session key has expired.
            raise_error(url, code, message, status)

        finally:
            self.lock.release()
Пример #13
0
    def authenticate_user(self, url, username, password, product):
        '''
        This function first checks to see if a user is valid. If it is, it
        will then attempt to authenticate the user with the password. If
        the password attempt succeeds, this function generates and inserts
        a new session key and returns it.

        If any failures occur as a result of authenticating the user, an
        exception will be thrown. The exceptions are detailed below.

        Client Errors:

            This section documents errors that are returned to the client. Note
            that the publisher is free to modify the content of these messages
            as they please.

            InvalidPaywallCredentials:

                Thrown when the authentication parameters are invalid.

                Code: InvalidPaywallCredentials
                Message: Varies with the error.
                HTTP Error Code: 401
                Required: Yes

            AccountProblem:

                There is a problem with the user's account. The user is
                prompted to contact technical support.

                Code: AccountProblem
                Message: Your account is not valid. Please contact support.
                HTTP Error Code: 403
                Required: Yes

            InvalidProduct:

                Thrown when the product code indicated is invalid.

                Code: InvalidProduct
                Message: The requested article could not be found.
                HTTP Error Code: 404
                Required: Yes
        '''
        self.lock.acquire()
        try:
            # Most of the errors in this function share a common code and
            # status.
            code = 'InvalidPaywallCredentials'
            status = 401

            # Check to see if the username is known.
            if username not in model.users:
                message = 'The credentials you have provided are not valid.'
                raise_error(url, code, message, status)

            # Check to see if the password is valid.
            if model.users[username]['password'] != password:
                message = 'The credentials you have provided are not valid.'
                raise_error(url, code, message, status)

            # Check to see if the user is valid. The check for a valid account
            # should come after the check for the password as the password
            # validates the user's identity.
            if not model.users[username]['valid']:
                code = 'AccountProblem'
                message = 'Your account is not valid. Please contact support.'
                status = 403
                raise_error(url, code, message, status)

            # Check to see if the user has access to the requested product.
            if product not in model.users[username]['products']:
                code = 'InvalidProduct'
                message = 'The requested article could not be found.'
                status = 404
                raise_error(url, code, message, status)

            # Update all valid session keys. While this call is not required
            # at this time, issuing it helps keep the database of session ids
            # small; particularly since the user has likely not been accessing
            # content recently as they are logging in. Calling update now will
            # hopefully free up many keys, reducing the memory footprint of
            # the server.
            self.update_session_ids(username)

            # Return the session id and products.
            session_id = self.create_session_id(username, product)
            products = model.users[username]['products']
            return (session_id, products)

        finally:
            self.lock.release()
Пример #14
0
def check_device(url, body):
    '''
    This function checks the validity of the device parameter. It takes the
    decoded json body of the request and raises an error if a problem is
    found.

    Server Errors:

        This section documents errors that are persisted on the server and not
        sent to the client. Note that the publisher is free to modify the
        content of these messages as they please.

        InvalidDevice:

            Returned when the request does not specify the device parameters
            properly.

            Code: InvalidDevice
            Message: The requested article could not be found.
            Debug: Varies with the error.
            HTTP Error Code: 400
            Required: No
    '''
    # All of the errors in this function share a common code and status.
    code = 'InvalidDevice'
    status = 400
    message = 'An error occurred. Please contact support.'

    # Validate that the device is provided as a parameter to the body. This
    # sample publisher does not store the device, but a production system
    # could store these values in order to perform analysis on the types of
    # devices that access products.
    if 'device' not in body:
        debug = 'The device has not been provided.'
        raise_error(url, code, message, status, debug)

    # Make sure the device is a dictionary.
    if not isinstance(body['device'], dict):
        debug = 'The device is not a map.'
        raise_error(url, code, message, status, debug)

    # Check to make sure that the manufacturer of the device has been
    # provided.
    if 'manufacturer' not in body['device']:
        debug = 'The manufacturer has not been provided.'
        raise_error(url, code, message, status, debug)

    # Check to make sure the manufacturer is of the right type.
    manufacturer = body['device']['manufacturer']
    if not isinstance(manufacturer, unicode) and \
       not isinstance(manufacturer, str):
        debug = 'The manufacturer is not a string.'
        raise_error(url, code, message, status, debug)

    # Check to make sure that the model of the device has been provided.
    if 'model' not in body['device']:
        debug = 'The model has not been provided.'
        raise_error(url, code, message, status, debug)

    # Check to make sure the model is of the right type.
    model = body['device']['model']
    if not isinstance(model, unicode) and \
       not isinstance(model, str):
        debug = 'The model is not a string.'
        raise_error(url, code, message, status, debug)

    # Check to make sure that the os_version of the device has been provided.
    if 'os_version' not in body['device']:
        debug = 'The os_version has not been provided.'
        raise_error(url, code, message, status, debug)

    # Check to make sure the os_version is of the right type.
    os_version = body['device']['os_version']
    if not isinstance(os_version, unicode) and \
       not isinstance(os_version, str):
        debug = 'The os_version is not a string.'
        raise_error(url, code, message, status, debug)