diff --git a/.coveralls.yml b/.coveralls.yml index 9138aa4..b82d4a9 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1,2 +1,2 @@ service_name: travis-pro -repo_token: 4il98EU1yJPayaqnEIoM9iK8K9wWsr8v7 +repo_token: plUwptjujYNJ6t2DUZBS49T4YvkEAIT5c diff --git a/README.md b/README.md index e02b184..48e0bb6 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ A chat application ![Jaguar](https://img00.deviantart.net/0a9d/i/2010/343/9/6/jaguar_by_alannahily-d34ju3t.jpg) +## Branches + +### master + +[![Build Status](https://travis-ci.com/Carrene/jaguar.svg?token=JgyQwxgapUeYpgeJwWxz&branch=master)](https://travis-ci.com/Carrene/jaguar) + Setting up development Environment on Linux ---------------------------------- diff --git a/jaguar/controllers/__init__.py b/jaguar/controllers/__init__.py index 4dd6f09..9077200 100644 --- a/jaguar/controllers/__init__.py +++ b/jaguar/controllers/__init__.py @@ -1,3 +1,2 @@ from .root import Root - diff --git a/jaguar/controllers/message.py b/jaguar/controllers/message.py new file mode 100644 index 0000000..d159d07 --- /dev/null +++ b/jaguar/controllers/message.py @@ -0,0 +1,39 @@ +from nanohttp import json, context, HTTPStatus, validate +from restfulpy.authorization import authorize +from restfulpy.orm import commit, DBSession +from restfulpy.controllers import ModelRestController + +from ..models import Envelop, Message + + +SUPPORTED_MIME_TYPES=['text/plain'] + + +class MessageController(ModelRestController): + __model__ = Envelop + + def __init__(self, target): + self.target = target + + @authorize + @validate( + body=dict( + max_length=(1024, '702 Must be less than 1024 charecters'), + required='400 Bad Request', + ) + ) + @json + @Message.expose + @commit + def send(self): + body = context.form.get('body') + mime_type = context.form.get('mimeType') + if not mime_type in SUPPORTED_MIME_TYPES: + raise HTTPStatus('415 Unsupported Media Type') + + message = Message(body=body, mime_type=mime_type) + message.target_id = self.target.id + message.sender_id = context.identity.id + DBSession.add(message) + return message + diff --git a/jaguar/controllers/target.py b/jaguar/controllers/target.py index 23ae1cf..a166c0a 100644 --- a/jaguar/controllers/target.py +++ b/jaguar/controllers/target.py @@ -1,15 +1,34 @@ -from nanohttp import json, context +from nanohttp import json, context, HTTPUnauthorized, HTTPStatus from restfulpy.authorization import authorize from restfulpy.controllers import ModelRestController from restfulpy.orm import DBSession from ..models import Target, target_member +from .message import MessageController class TargetController(ModelRestController): __model__ = Target + def __call__(self, *remaining_paths): + if len(remaining_paths) > 1 and remaining_paths[1] == 'messages': + target = self.get_target(remaining_paths[0]) + return MessageController(target)(*remaining_paths[2:]) + + return super().__call__(*remaining_paths) + + def get_target(self, id): + try: + int(id) + except: + raise HTTPStatus('706 Invalid Target Id') + target = DBSession.query(Target).filter(Target.id == id).one_or_none() + if target is None: + raise HTTPStatus('614 Target Not Exist') + + return target + @authorize @json @Target.expose diff --git a/jaguar/models/__init__.py b/jaguar/models/__init__.py index 6e27baf..c75fd4d 100644 --- a/jaguar/models/__init__.py +++ b/jaguar/models/__init__.py @@ -1,5 +1,5 @@ from .target import Target, Room, Direct, target_member -from .envelop import Envelop +from .envelop import Envelop, Message from .membership import Member, User, blocked, Contact from .messaging import ActivationEmail diff --git a/jaguar/models/envelop.py b/jaguar/models/envelop.py index 25d16c9..c124b7b 100644 --- a/jaguar/models/envelop.py +++ b/jaguar/models/envelop.py @@ -37,6 +37,7 @@ class Message(Envelop): ForeignKey('envelop.id'), primary_key=True, ) + mime_type=Field(Unicode(25)) # Since collections would be fairly small, # selecin loding is chosen for this relationship. diff --git a/jaguar/models/tests/test_message.py b/jaguar/models/tests/test_message.py index cd5efb0..fe0cb13 100644 --- a/jaguar/models/tests/test_message.py +++ b/jaguar/models/tests/test_message.py @@ -21,7 +21,7 @@ def test_message_model(db): # Test message model. As every message should have a sender # to be send, sender_id and target_id can not be nullable message = Message( - type='message', + mime_type='message', body='Hello world!', sender_id=member.id, target_id=room.id, diff --git a/jaguar/tests/test_send_message.py b/jaguar/tests/test_send_message.py new file mode 100644 index 0000000..ebc52dc --- /dev/null +++ b/jaguar/tests/test_send_message.py @@ -0,0 +1,63 @@ +from bddrest.authoring import given, when, Update, status, response, Remove + +from jaguar.tests.helpers import AutoDocumentationBDDTest +from jaguar.models import User, Room, Direct + + +class TestSendMessage(AutoDocumentationBDDTest): + + @classmethod + def mockup(cls): + session = cls.create_session() + user1 = User( + email='user1@example.com', + password='123456', + title='user1', + ) + room = Room(title='example', type='room') + direct = Direct(title='direct', type='direct') + session.add(user1) + session.add(room) + session.commit() + + def test_send_message_to_target(self): + self.login( + email='user1@example.com', + password='123456', + url='/apiv1/tokens', + verb='CREATE' + ) + + with self.given( + 'Send a message to a target', + '/apiv1/targets/id:1/messages', + 'SEND', + form=dict(body='hello world!', mimeType='text/plain') + ): + assert status == 200 + assert response.json['body'] == 'hello world!' + + when('Invalid target id', url_parameters=Update(id='Invalid')) + assert status == '706 Invalid Target Id' + + when('Target does not exist', url_parameters=Update(id=3)) + assert status == '614 Target Not Exist' + + when( + 'Try to send unsopported media type', + form=Update(mimeType='video/3gpp') + ) + assert status == 415 + + when( + 'Try to send long text', + form=Update(body=(1024 + 1) * 'a') + ) + assert status == '702 Must be less than 1024 charecters' + + when('Remove body from the form', form=Remove('body')) + assert status == 400 + + when('Try to pass an unauthorized request', authorization=None) + assert status == 401 +