CouchDB
  1. CouchDB
  2. COUCHDB-1155

Etag send by list function does not depend on userCtx

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 1.0.2
    • Fix Version/s: 1.3
    • Component/s: HTTP Interface
    • Labels:
      None

      Description

      List functions should send a different Etag when requested by different users.
      The following curl session shows identical Etags for different users. CouchDB must not be in admin party mode.

      PROTOCOL=http
      DOMAIN="127.0.0.1:5984"
      DB=testdb

      1. admin credentials for db creation
        ADMIN=admin:secure
      2. this user must have an empty roles array
        USER=user:secure

      curl -XDELETE $PROTOCOL://$ADMIN@$DOMAIN/$DB
      curl -XPUT $PROTOCOL://$ADMIN@$DOMAIN/$DB
      curl -XPUT $PROTOCOL://$ADMIN@$DOMAIN/$DB/foo -d '

      {"count":1}

      '
      curl -XPUT $PROTOCOL://$ADMIN@$DOMAIN/$DB/_design/foo -d '{ "views": { "bar": { "map": "function(doc)

      { emit(doc._id, null); }

      " } }, "lists": { "bar": "function(head, req)

      { return req.userCtx.name || \"anonymous\" }

      " }}'

      curl -s $PROTOCOL://$DOMAIN/$DB/_design/foo/_list/bar/bar --head | grep Etag
      curl -s $PROTOCOL://$USER@$DOMAIN/$DB/_design/foo/_list/bar/bar --head | grep Etag

      #=> Etag: "A1NKHA0935KMCSHFSK94EHZNL"
      #=> Etag: "A1NKHA0935KMCSHFSK94EHZNL"

      This issue is important for standalone CouchDB applications which use list functions depending on the user context, eg. showing a login button or username.

      regards
      Johannes

      PS: I tried to write a javascript test case but this issue can only be reproduced if the server is not in admin party mode, which the test suite requires. I am not so familar with those tests to temporarily change the admin party.

        Activity

        Hide
        Randall Leeds added a comment -

        Looking at the wiki: http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#ETags
        It seems as though it's the roles that affect the etag. The documentation only mentions _show, but perhaps _list behaves the same way. Can you verify this?
        If the whole user context is available to the list function then I think it's a fair argument that more than just roles should affect the etag.

        Although, I wonder if it's actually more correct to let the function generate the etag itself (or leave it off if it wants).
        After all, there's no requirement that a _list or _show be deterministic, so how should CouchDB know what etag to send?

        I'd love some input from the community and devs on this one, but lets try not to bikeshed toooo much. :-P

        Show
        Randall Leeds added a comment - Looking at the wiki: http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#ETags It seems as though it's the roles that affect the etag. The documentation only mentions _show, but perhaps _list behaves the same way. Can you verify this? If the whole user context is available to the list function then I think it's a fair argument that more than just roles should affect the etag. Although, I wonder if it's actually more correct to let the function generate the etag itself (or leave it off if it wants). After all, there's no requirement that a _list or _show be deterministic, so how should CouchDB know what etag to send? I'd love some input from the community and devs on this one, but lets try not to bikeshed toooo much. :-P
        Hide
        Robert Newson added a comment -

        It's certainly the case that the ETag currently includes only the users roles.

        It should be an easy fix to allow any returned ETag in a "headers" entry to override what we send.

        Show
        Robert Newson added a comment - It's certainly the case that the ETag currently includes only the users roles. It should be an easy fix to allow any returned ETag in a "headers" entry to override what we send.
        Hide
        Johannes J. Schmidt added a comment -

        Yes, allowing to send a custom ETag from the show and list functions headers entry would be great.
        Assigning every user a role, as suggested in http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#ETags, solves the problem in the meantime.

        Thanks a lot!

        Show
        Johannes J. Schmidt added a comment - Yes, allowing to send a custom ETag from the show and list functions headers entry would be great. Assigning every user a role, as suggested in http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#ETags , solves the problem in the meantime. Thanks a lot!
        Hide
        Noah Slater added a comment -

        I was stung by this today. I'm trying to build a CouchApp, but instead of building the page with client-side JavaScript, I am doing it all using shows and list functions. The first hurdle I ran into while implementing an authentication system was that the parts of the template that indicate whether you are logged in or not would fail to update. Turns out that CouchDB is caching the results of these functions, across sessions. So, I am +1 on updating Etag calculation depending on authenticated user, as well as roles. Until this is implemented I will have to use the unique role per user bodge.

        Show
        Noah Slater added a comment - I was stung by this today. I'm trying to build a CouchApp, but instead of building the page with client-side JavaScript, I am doing it all using shows and list functions. The first hurdle I ran into while implementing an authentication system was that the parts of the template that indicate whether you are logged in or not would fail to update. Turns out that CouchDB is caching the results of these functions, across sessions. So, I am +1 on updating Etag calculation depending on authenticated user, as well as roles. Until this is implemented I will have to use the unique role per user bodge.
        Hide
        Daniel MacDonald added a comment -

        I just ran in to this too. The suggested workaround of assigning roles to each user is especially annoying because normally only admins can assign roles, and I need to let anonymous users signup. I hacked this by allowing _design/auth/validate_doc_update to permit a special per-user role, but I felt dirty about it.

        Show
        Daniel MacDonald added a comment - I just ran in to this too. The suggested workaround of assigning roles to each user is especially annoying because normally only admins can assign roles, and I need to let anonymous users signup. I hacked this by allowing _design/auth/validate_doc_update to permit a special per-user role, but I felt dirty about it.
        Hide
        Stephane Alnet added a comment -

        This issue could probably be renamed "why do list functions provide an Etag?". As much as map and reduce functions are required to be idempotent, there's no such requirement for list functions – they are the only way to do e.g. a query that is time-dependent (using "new Date()" inside the list function) server-side.

        Unless the CouchDB API is modified to require list functions to be idempotent (same inputs = same outputs), to be able to send a valid Etag back with the response CouchDB would have to compute some hash of the output of the function every time it is eval'ed, since the output might be different every time (even with identical inputs).

        Show
        Stephane Alnet added a comment - This issue could probably be renamed "why do list functions provide an Etag?". As much as map and reduce functions are required to be idempotent, there's no such requirement for list functions – they are the only way to do e.g. a query that is time-dependent (using "new Date()" inside the list function) server-side. Unless the CouchDB API is modified to require list functions to be idempotent (same inputs = same outputs), to be able to send a valid Etag back with the response CouchDB would have to compute some hash of the output of the function every time it is eval'ed, since the output might be different every time (even with identical inputs).
        Hide
        Stéphane Alnet added a comment -

        Although you can't currently override the Etag you can modify it:

        "lists": {
        "test": "(function(){start({headers:{Etag:'foo'}}); send('');})"
        }

        GET /bar/_design/foo/_list/test/test

        HTTP/1.1 200 OK
        Vary: Accept
        Transfer-Encoding: chunked
        Server: CouchDB/1.2.0 (Erlang OTP/R15B01)
        Etag: foo, "4SNNDV6U28X8Z7TXTQURJAMPT"
        Date: Wed, 03 Oct 2012 08:20:14 GMT
        Content-Type: application/json

        So the Etag provided by Javascript is pre-pended to the CouchDB-generated Etag, which should be sufficient?

        Show
        Stéphane Alnet added a comment - Although you can't currently override the Etag you can modify it: "lists": { "test": "(function(){start({headers:{Etag:'foo'}}); send('');})" } GET /bar/_design/foo/_list/test/test HTTP/1.1 200 OK Vary: Accept Transfer-Encoding: chunked Server: CouchDB/1.2.0 (Erlang OTP/R15B01) Etag: foo, "4SNNDV6U28X8Z7TXTQURJAMPT" Date: Wed, 03 Oct 2012 08:20:14 GMT Content-Type: application/json So the Etag provided by Javascript is pre-pended to the CouchDB-generated Etag, which should be sufficient?
        Hide
        Randall Leeds added a comment -

        Is this covered by COUCHDB-1537?

        Show
        Randall Leeds added a comment - Is this covered by COUCHDB-1537 ?
        Hide
        Stephane Alnet added a comment - - edited

        Yes, it looks like this issue and COUCHDB-1537 are duplicates.

        I've updated the wiki based on commit 426b431..3bfa035

        Also the workaround I suggested for the more generic case (sending back an additional Etag field) makes the Etag header non-compliant (with RFC2616 section 3.11) and shouldn't be used; I'll create a new issue. EDIT: Created COUCHDB-1555.

        Show
        Stephane Alnet added a comment - - edited Yes, it looks like this issue and COUCHDB-1537 are duplicates. I've updated the wiki based on commit 426b431..3bfa035 Also the workaround I suggested for the more generic case (sending back an additional Etag field) makes the Etag header non-compliant (with RFC2616 section 3.11) and shouldn't be used; I'll create a new issue. EDIT: Created COUCHDB-1555 .

          People

          • Assignee:
            Randall Leeds
            Reporter:
            Johannes J. Schmidt
          • Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development