nicolaiarocci/eve — pull request #77 by bcattle (2013-08-04 20:22:06+00:00)
Title: `auth_username_field` clobbering client-supplied filter

There is a conflict when `auth_username_field` is defined and the client provides a filter affecting that same field. The issue is that `auth_username_field` adds a new filter criteria, e.g. `{'username': 'bcattle'}`. This criteria replaces any filter criteria supplied by the client ([io/base.py line 188](https://github.com/nicolaiarocci/eve/blob/develop/eve/io/base.py#L188)):

```python
# if 'user-restricted resource access' is enabled and there's an Auth
# request active, add the username field to the query
username_field = config.DOMAIN[resource].get('auth_username_field')
if username_field and request.authorization and query is not None:
query.update({username_field: request.authorization.username})
```

Hence if I was trying to look up `/profiles/nicolaiarocci/` with `auth_username_field='username'` and my `username==bcattle`, internally Eve calls `findOne()` which returns `/profiles/bcattle/` rather than failing.

On an update the request will then fail with HTTP 412, because the ETag I supplied for `/profiles/nicolaiarocci/` fails to validate. This is the problem - the wrong error code is getting reported.

I added a special case to check for this conflict. Unfortunately the logic is convoluted. If `auth_username_field=='_id'` we also need to perform an `ObjectId()` comparison:

```python
# if 'user-restricted resource access' is enabled and there's an Auth
# request active, add the username field to the query
username_field = config.DOMAIN[resource].get('auth_username_field')
if username_field and request.authorization and query is not None:
# If the username_field *replaces* a field in the query,
# and the two values are different, deny the request
if username_field in query and \
query[username_field] != request.authorization.username:
# If the field is ID_FIELD, need additional check
# to make sure the ObjectId is not equal :(
if username_field != config.ID_FIELD or \
query[username_field] != ObjectId(request.authorization.username):
abort(401)
else:
query.update({username_field: request.authorization.username})
```

Does this logic seem reasonable?

This code may change with the fix proposed by @nicolaiarocci in #73 [here](https://github.com/nicolaiarocci/eve/issues/73#issuecomment-22069333). I'll write tests once that shakes out.

cc @rxl @asdine