Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP 403 (Forbidden) not wrapped #14

Closed
adrienverge opened this issue Mar 23, 2020 · 0 comments · Fixed by #15
Closed

HTTP 403 (Forbidden) not wrapped #14

adrienverge opened this issue Mar 23, 2020 · 0 comments · Fixed by #15

Comments

@adrienverge
Copy link
Contributor

adrienverge commented Mar 23, 2020

In some cases, CouchDB can return HTTP 403 errors (for instance with usage of _security and/or validation functions). Here is a fully working example* to demonstrate 2 types of errors 403:

(* needs #13)

import asyncio

from aiocouch import CouchDB
from aiocouch.document import Document


URL = 'http://localhost:5984'


async def prepare():
    async with CouchDB(URL, user='root', password='password') as couch:
        users = await couch['_users']

        stranger = Document(users, 'org.couchdb.user:stranger')
        stranger.update({'name': 'stranger', 'password': 'pass', 'type': 'user', 'roles': []})
        await stranger.save()

        reader = Document(users, 'org.couchdb.user:reader')
        reader.update({'name': 'reader', 'password': 'pass', 'type': 'user', 'roles': []})
        await reader.save()

        writer = Document(users, 'org.couchdb.user:writer')
        writer.update({'name': 'writer', 'password': 'pass', 'type': 'user', 'roles': []})
        await writer.save()

        db = await couch.create('db')
        # Only 'reader' and 'writer' will be able to access this base:
        await db.set_security({'members': {'names': ['reader', 'writer']}})

        ddoc = await db.design_doc('_design/write_access')
        # Only 'writer' will be able to create or update documents:
        ddoc.update({
            'validate_doc_update': '''
                function(newDoc, oldDoc, userCtx, secObj) {
                  if (userCtx.name == 'writer')
                    return;
                  throw {forbidden: 'You are not allowed to write to this database'};
                }''',
        })
        await ddoc.save()


async def test():
    async with CouchDB(URL, user='stranger', password='pass') as couch:
        db = await couch['db']  # HTTP 403

    async with CouchDB(URL, user='writer', password='pass') as couch:
        db = await couch['db']                # OK
        await(await db.create('doc')).save()  # OK
        print(await db['doc'])                # OK

    async with CouchDB(URL, user='reader', password='pass') as couch:
        db = await couch['db']  # OK
        doc = await db['doc']   # OK
        doc["changed"] = True
        await doc.save()        # HTTP 403


asyncio.get_event_loop().run_until_complete(prepare())
asyncio.get_event_loop().run_until_complete(test())

I'll work on a commit to encapsulate aiohttp.client_exceptions.ClientResponseError(403) (currently raised) in the same manner as UnauthorizedError, BadRequestError, etc.

adrienverge added a commit to adrienverge/aiocouch that referenced this issue Mar 23, 2020
adrienverge added a commit to adrienverge/aiocouch that referenced this issue Mar 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant