Ejemplo n.º 1
0
def get_data(request):
    """After authenticating with the server and getting back the URL of the
    collection, request::

        GET /collections/{user}/{collection}?since=timestamp

    `since` is optional; on first sync is should be empty or left off. The
    server will return an object::

        {until: timestamp,
         uuid: someuniquevalue,  # using a timestamp XXXX
         incomplete: bool, applications: {origin: {...},
                                                   ...} }

    The response may not be complete if there are too many applications.
    If this is the case then `incomplete` will be true (it may be left out
    if
    the response is complete).  Another request using `since={until}` will
    get further applications (this may need to be repeated many times).

    The client should save the value of `until` and use it for subsequent
    requests.

    In the case of no new items the response will be only::

        {until: timestamp}

    The client should always start with this GET request and only then send
    its own updates.  It should ensure that its local timestamp is
    sensible in comparison to the value of `until`.

    Applications returned may be older than the local applications, in that
    case then the client should ignore the server's application and use
    its local copy, causing an overwrite.  The same is true for deleted
    applications; if the local installed copy has a `last_modified` date
    newer than the deleted server instance then the server instance
    should be ignored (the user reinstalled an application).

    **NOTE:** there are some conflicts that may occur, specifically
    receipts should be merged.

    When an application is added from the server the client should
    *locally* set `app.sync` to true (this is in the [application
    representation]
    (https://developer.mozilla.org/en/OpenWebApps/The_JavaScript_API
    #Application_Representation), not the manifest).

    You must always retain `last_modified` as you received it from
    the server (unless you ignore the application in favor of a
    newer local version).
    """
    user, collection, dbtoken = check_auth(request)

    try:
        since = request.GET.get('since', '0')
        since = round_time(since)
    except TypeError:
        raise bad_request(INVALID_SINCE_VALUE)
    except ValueError:
        print 'Bad since', repr(since)
        raise bad_request(INVALID_SINCE_VALUE,
                          'Invalid value for since: %r' % since)

    if since.is_nan():
        raise bad_request(INVALID_SINCE_VALUE,
                          'Got NaN value for since')

    storage = get_storage(request)

    res = {'since': since,
           'until': round_time(),
           'uuid': storage.get_uuid(user, collection, dbtoken)}

    try:
        res['applications'] = storage.get_applications(user, collection,
                                                       since, token=dbtoken)
    except CollectionDeletedError, e:
        return {'collection_deleted': {'reason': e.reason,
                                       'client_id': e.client_id}}
def get_data(request):
    """After authenticating with the server and getting back the URL of the
    collection, request::

        GET /collections/{user}/{collection}?since=timestamp

    `since` is optional; on first sync is should be empty or left off. The
    server will return an object::

        {until: timestamp,
         uuid: someuniquevalue,  # using a timestamp XXXX
         incomplete: bool, applications: {origin: {...},
                                                   ...} }

    The response may not be complete if there are too many applications.
    If this is the case then `incomplete` will be true (it may be left out
    if
    the response is complete).  Another request using `since={until}` will
    get further applications (this may need to be repeated many times).

    The client should save the value of `until` and use it for subsequent
    requests.

    In the case of no new items the response will be only::

        {until: timestamp}

    The client should always start with this GET request and only then send
    its own updates.  It should ensure that its local timestamp is
    sensible in comparison to the value of `until`.

    Applications returned may be older than the local applications, in that
    case then the client should ignore the server's application and use
    its local copy, causing an overwrite.  The same is true for deleted
    applications; if the local installed copy has a `last_modified` date
    newer than the deleted server instance then the server instance
    should be ignored (the user reinstalled an application).

    **NOTE:** there are some conflicts that may occur, specifically
    receipts should be merged.

    When an application is added from the server the client should
    *locally* set `app.sync` to true (this is in the [application
    representation]
    (https://developer.mozilla.org/en/OpenWebApps/The_JavaScript_API
    #Application_Representation), not the manifest).

    You must always retain `last_modified` as you received it from
    the server (unless you ignore the application in favor of a
    newer local version).
    """
    user, collection, dbtoken = check_auth(request)

    try:
        since = request.GET.get('since', '0')
        since = round_time(since)
    except TypeError:
        raise bad_request(INVALID_SINCE_VALUE)
    except ValueError:
        logger.error('Bad since %r' % since)
        raise bad_request(INVALID_SINCE_VALUE,
                          'Invalid value for since: %r' % since)

    if since.is_nan():
        raise bad_request(INVALID_SINCE_VALUE, 'Got NaN value for since')

    storage = get_storage(request)

    res = {'since': since, 'uuid': storage.get_uuid(user, collection, dbtoken)}
    until = 0
    apps = []
    try:
        for index, (last_modified, app) in enumerate(
                storage.get_applications(user,
                                         collection,
                                         since,
                                         token=dbtoken)):
            if last_modified > until:
                until = last_modified

            apps.append(app)

        res['applications'] = apps
        if not until:
            until = since
        res['until'] = until

    except CollectionDeletedError, e:
        return {
            'collection_deleted': {
                'reason': e.reason,
                'client_id': e.client_id
            }
        }
Ejemplo n.º 3
0
def post_data(request):
    """The client should keep track of the last time it sent updates to the
    server, and send updates when there are newer applications.

    **NOTE:** there is a case when an update might be lost because of an
    update from another device; this would be okay except that the client
    doesn't know it needs to re-send that update.  How do we confirm that ?

    The updates are sent with::

        POST /collections/{user}/{collection}?lastget=somedate

        {origin: {...}, ...}

    Each object must have a `last_modified` key.

    The response is only::

        {received: timestamp}

    XXX
    if lastget (timestamp) was provided and the collection has been changed
    since that date, we send back a 412 Precondition Failed.

    """
    user, collection, dbtoken = check_auth(request)
    server_time = round_time()
    storage = get_storage(request)

    if 'delete' in request.params:
        # we were asked to delete the collection
        try:
            info = request.json_body
        except ValueError:
            raise bad_request(INVALID_JSON)

        if 'client_id' not in info:
            raise bad_request(MISSING_VALUE)

        client_id = info['client_id']
        reason = info.get('reason', '')
        storage.delete(user, collection, client_id, reason, token=dbtoken)
        return {'received': server_time}

    elif 'lastget' in request.params:
        last_get = round_time(float(request.params['lastget']))
        last_modified = storage.get_last_modified(user, collection,
                                                  token=dbtoken)
        if last_modified > last_get:
            raise exc.HTTPPreconditionFailed()

    try:
        apps = request.json_body
    except ValueError:
        raise bad_request(INVALID_JSON)

    # in case this fails, the error will get logged
    # and the user will get a 503 (empty body)

    storage.add_applications(user, collection, apps, token=dbtoken)

    return {'received': server_time}
def post_data(request):
    """The client should keep track of the last time it sent updates to the
    server, and send updates when there are newer applications.

    **NOTE:** there is a case when an update might be lost because of an
    update from another device; this would be okay except that the client
    doesn't know it needs to re-send that update.  How do we confirm that ?

    The updates are sent with::

        POST /collections/{user}/{collection}?lastget=somedate

        {origin: {...}, ...}

    Each object must have a `last_modified` key.

    The response is only::

        {received: timestamp}

    XXX
    if lastget (timestamp) was provided and the collection has been changed
    since that date, we send back a 412 Precondition Failed.

    """
    user, collection, dbtoken = check_auth(request)
    server_time = round_time()
    storage = get_storage(request)

    if 'delete' in request.params:
        # we were asked to delete the collection
        try:
            info = request.json_body
        except ValueError:
            raise bad_request(INVALID_JSON)

        if 'client_id' not in info:
            raise bad_request(MISSING_VALUE)

        client_id = info['client_id']
        reason = info.get('reason', '')
        storage.delete(user, collection, client_id, reason, token=dbtoken)
        return {'received': server_time}

    elif 'lastget' in request.params:
        last_get = round_time(float(request.params['lastget']))
        last_modified = storage.get_last_modified(user,
                                                  collection,
                                                  token=dbtoken)
        if last_modified > last_get:
            raise exc.HTTPPreconditionFailed()

    try:
        apps = request.json_body
    except ValueError:
        raise bad_request(INVALID_JSON)

    # in case this fails, the error will get logged
    # and the user will get a 503 (empty body)

    storage.add_applications(user, collection, apps, token=dbtoken)

    return {'received': server_time}