Skip to content

Commit

Permalink
Create Direct API (#84)
Browse files Browse the repository at this point in the history
* Create direct API, first try, closes #2

* Review changes

* Some changes to be compatible with new restfulpy

* Coding style improvement

* Review changes

* Empty dict is changed to None
  • Loading branch information
mkhfring authored and pylover committed Aug 14, 2018
1 parent 283e511 commit 44ab47b
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 38 deletions.
8 changes: 3 additions & 5 deletions jaguar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

class Jaguar(Application):
__authenticator__ = Authenticator()

__configuration__ = '''
db:
Expand All @@ -31,18 +30,17 @@ class Jaguar(Application):
password: <smtp-password>
localhost: gmail.com
activation:
secret: activation-secret
max_age: 86400 # seconds
url: http://example.com/activate
'''

def __init__(self):
def __init__(self, application_name='jaguar', root=Root()):
super().__init__(
'jaguar',
root=Root(),
application_name,
root=root,
root_path=join(dirname(__file__), '..'),
version=__version__,
)
Expand Down
44 changes: 44 additions & 0 deletions jaguar/controllers/direct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from sqlalchemy import or_, and_
from nanohttp import json, context, HTTPStatus, validate
from restfulpy.controllers import ModelRestController
from restfulpy.authorization import authorize
from restfulpy.orm import DBSession, commit

from ..models import Direct, User, blocked


class DirectController(ModelRestController):
__model__ = Direct

@authorize
@validate(userId=dict(type_=(int, '705 Invalid User Id')))
@json(prevent_empty_form='710 Empty Form')
@Direct.expose
@commit
def create(self):
user_id = context.form.get('userId')
destination = DBSession.query(User) \
.filter(User.id == user_id).one_or_none()
if destination is None:
raise HTTPStatus('611 User Not Found')

is_blocked = DBSession.query(blocked) \
.filter(or_(
and_(
blocked.c.source == user_id,
blocked.c.destination == context.identity.id
),
and_(
blocked.c.source == context.identity.id,
blocked.c.destination == user_id
)
)) \
.count()
if is_blocked:
raise HTTPStatus('613 Not Allowed To Create Direct With This User')

source = User.current()
direct = Direct(title=destination.title, type='direct')
direct.members = [source, destination]
return direct

2 changes: 2 additions & 0 deletions jaguar/controllers/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .room import RoomController
from .target import TargetController
from .contact import ContactController
from .direct import DirectController


class ApiV1(Controller):
Expand All @@ -20,6 +21,7 @@ class ApiV1(Controller):
rooms = RoomController()
targets = TargetController()
contacts = ContactController()
directs = DirectController()

@json
def version(self):
Expand Down
32 changes: 3 additions & 29 deletions jaguar/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,18 @@
from restfulpy.testing import ApplicableTestCase
from restfulpy.orm import DBSession

from jaguar import Jaguar
from jaguar.authentication import Authenticator
from jaguar.controllers.root import Root
from jaguar.models.membership import User


HERE = path.abspath(path.dirname(__file__))


class AutoDocumentationBDDTest(ApplicableTestCase):

__application__ = Application(
'Mockup',
root=Root(),
authenticator=Authenticator()
)
__configuration__ = '''
db:
url: postgresql://postgres:postgres@localhost/jaguar_dev
test_url: postgresql://postgres:postgres@localhost/jaguar_test
administrative_url: postgresql://postgres:postgres@localhost/postgres
activation:
secret: activation-secret
max_age: 86400 # seconds
url: http://nc.carrene.com/activate
'''

@classmethod
def mockup(cls):
user = User(
email='[email protected]',
title='example',
password='123456',
)
user.is_active = True
DBSession.add(user)
DBSession.commit()
__application_factory__ = Jaguar

@classmethod
def get_spec_filename(cls, story):
Expand Down
81 changes: 81 additions & 0 deletions jaguar/tests/test_create_direct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from bddrest.authoring import status, given, when, Update, response

from jaguar.tests.helpers import AutoDocumentationBDDTest
from jaguar.models import User, blocked


class TestDirect(AutoDocumentationBDDTest):

@classmethod
def mockup(cls):
session = cls.create_session()
user1 = User(
email='[email protected]',
password='123456',
title='user1'
)
user2 = User(
email='[email protected]',
password='123456',
title='user2',
)
blocker = User(
email='[email protected]',
password='123456',
title='blocker',
)
blocker.blocked_users.append(user1)
session.add_all([blocker, user2])
session.commit()

def test_creat_token(self):
self.login(
email='[email protected]',
password='123456',
url='/apiv1/tokens',
verb='CREATE',
)

with self.given(
'Try to create a direct with a user',
'/apiv1/directs',
'CREATE',
form=dict(userId=3)
):
assert status == 200
assert response.json['title'] == 'user2'

when('The user not exists', form=Update(userId=5))
assert status == '611 User Not Found'

when(
'Try to pass invalid user id in the form',
form=Update(userId='Invalid')
)
assert status == '705 Invalid User Id'

when('Try to pass empty form', form=None)
assert status == '710 Empty Form'

when('Blocked user tries to create a direct', form=Update(userId=1))
assert status == '613 Not Allowed To Create Direct With This User'

self.logout()
self.login(
email='[email protected]',
password='123456',
url='/apiv1/tokens',
verb='CREATE',
)

with self.given(
'Try to create a direct with a blocked user',
'/apiv1/directs',
'CREATE',
form=dict(userId=2)
):
assert status == '613 Not Allowed To Create Direct With This User'

when('Try to pass an unauthorized request', authorization=None)
assert status == 401

11 changes: 11 additions & 0 deletions jaguar/tests/test_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@

class TestToken(AutoDocumentationBDDTest):

@classmethod
def mockup(cls):
session = cls.create_session()
user = User(
email='[email protected]',
title='user',
password='123456',
)
session.add(user)
session.commit()

def test_login(self):
with self.given(
'Login user',
Expand Down
4 changes: 1 addition & 3 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@ coverage
coveralls
pytest-pudb
pytest-cov
git+git://github.com/Carrene/[email protected]
git+git://github.com/Carrene/restfulpy.git@33d64275bd53b15745e7c6ff6d264989fdb9cb01
pymlconf==0.8.9

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


dependencies = [
'restfulpy >= 1.0.0a0',
'restfulpy >= 1.2.0b1',
]


Expand Down

0 comments on commit 44ab47b

Please sign in to comment.