Browse Source

updated documentation and updated the authentication method

master
Julio Biason 11 years ago
parent
commit
bebac1f97f
  1. 175
      luncho/blueprints/groups.py
  2. 99
      tests/group_tests.py

175
luncho/blueprints/groups.py

@ -10,7 +10,7 @@ from flask import request
from flask import jsonify from flask import jsonify
from luncho.helpers import ForceJSON from luncho.helpers import ForceJSON
from luncho.helpers import user_from_token from luncho.helpers import auth
from luncho.server import User from luncho.server import User
from luncho.server import Group from luncho.server import Group
@ -21,7 +21,15 @@ from luncho.exceptions import ElementNotFoundException
class AccountNotVerifiedException(LunchoException): class AccountNotVerifiedException(LunchoException):
"""The account isn't verified.""" """The account isn't verified.
.. sourcecode:: http
HTTP/1.1 412 Precondition Failed
Content-Type: test/json
{ "status": "ERROR", "message": "Account not verified" }
"""
def __init__(self): def __init__(self):
super(AccountNotVerifiedException, self).__init__() super(AccountNotVerifiedException, self).__init__()
self.status = 412 self.status = 412
@ -29,18 +37,34 @@ class AccountNotVerifiedException(LunchoException):
class NewMaintainerDoesNotExistException(LunchoException): class NewMaintainerDoesNotExistException(LunchoException):
"""The account for the new maintainer does not exist.""" """The account for the new admin does not exist.
.. sourcecode:: http
HTTP/1.1 404 Not found
Content-Type: test/json
{ "status": "ERROR", "message": "New admin not found" }
"""
def __init__(self): def __init__(self):
super(NewMaintainerDoesNotExistException, self).__init__() super(NewMaintainerDoesNotExistException, self).__init__()
self.status = 412 self.status = 404
self.message = 'New maintainer not found' self.message = 'New admin not found'
class UserIsNotAdminException(LunchoException): class UserIsNotAdminException(LunchoException):
"""The user is not the admin of the group.""" """The user is not the admin of the group.
.. sourcecode:: http
HTTP/1.1 403 Forbidden
Content-Type: test/json
{ "status": "ERROR", "message": "User is not admin" }
"""
def __init__(self): def __init__(self):
super(UserIsNotAdminException, self).__init__() super(UserIsNotAdminException, self).__init__()
self.status = 401 self.status = 403
self.message = 'User is not admin' self.message = 'User is not admin'
@ -49,10 +73,32 @@ groups = Blueprint('groups', __name__)
LOG = logging.getLogger('luncho.blueprints.groups') LOG = logging.getLogger('luncho.blueprints.groups')
@groups.route('<token>/', methods=['GET']) @groups.route('', methods=['GET'])
def user_groups(token): @auth
"""Return a list of the groups the user belongs or it's the owner.""" def user_groups():
user = user_from_token(token) """*Authenticated request* Return a list of the groups the user belongs or
it's the owner.
**Success (200)**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/json
{ "status": "OK", "groups": [ { "id": "<group id>" ,
"name": "<group name>",
"admin": <true if the user is admin>},
...] }
**User not found (via token) (404)**:
:py:class:`UserNotFoundException`
**Authorization required (412)**:
:py:class:`AuthorizationRequiredException`
"""
user = request.user
groups = {} groups = {}
for group in user.groups: for group in user.groups:
groups[group.id] = {'id': group.id, groups[group.id] = {'id': group.id,
@ -63,11 +109,30 @@ def user_groups(token):
groups=groups.values()) groups=groups.values())
@groups.route('<token>/', methods=['PUT']) @groups.route('', methods=['PUT'])
@ForceJSON(required=['name']) @ForceJSON(required=['name'])
def create_group(token): @auth
"""Create a new group belonging to the user.""" def create_group():
user = user_from_token(token) """*Authenticated request* Create a new group. Once the group is created,
the user becomes the administrator of the group.
**Example request**:
.. sourcecode:: http
{ "name": "Name for the group" }
**User not found (via token) (404)**:
:py:class:`UserNotFoundException`
**Authorization required (412)**:
:py:class:`AuthorizationRequiredException`
**Account not verified (412)**:
:py:class:`AccountNotVerifiedException`
"""
user = request.user
LOG.debug('User status: {verified}'.format(verified=user.verified)) LOG.debug('User status: {verified}'.format(verified=user.verified))
if not user.verified: if not user.verified:
@ -87,11 +152,48 @@ def create_group(token):
id=new_group.id) id=new_group.id)
@groups.route('<token>/<groupId>/', methods=['POST']) @groups.route('<groupId>/', methods=['POST'])
@ForceJSON() @ForceJSON()
def update_group(token, groupId): @auth
"""Update group information.""" def update_group(groupId):
user = user_from_token(token) """*Authenticated request* Update group information. The user must be
the administrator of the group to change any information. Partial requests
are accepted and missing fields are not changed.
The administrator of the group can be changed by sending the
"admin" field with the username of the new administrator.
**Example request**:
.. sourcecode:: http
{ "name": "new group name": "admin": "newAdmin"}
**Success (200)**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/json
{ "status": "OK" }
**Request not in JSON format (400)**:
:py:class:`RequestMustBeJSONException`
**User is not administrator of the group (403)**:
:py:class:`UserIsNotAdminException`
**User not found (via token) (404)**:
:py:class:`UserNotFoundException`
**The new admin does not exist (404)**:
:py:class:`NewMaintainerDoesNotExistException`
**Authorization required (412)**:
:py:class:`AuthorizationRequiredException`
"""
user = request.user
group = Group.query.get(groupId) group = Group.query.get(groupId)
if not group: if not group:
raise ElementNotFoundException('Group') raise ElementNotFoundException('Group')
@ -105,21 +207,44 @@ def update_group(token, groupId):
if 'name' in json: if 'name' in json:
group.name = json['name'] group.name = json['name']
if 'maintainer' in json: if 'admin' in json:
new_maintainer = User.query.get(json['maintainer']) new_maintainer = User.query.get(json['admin'])
if not new_maintainer: if not new_maintainer:
raise NewMaintainerDoesNotExistException() raise NewMaintainerDoesNotExistException()
group.owner = new_maintainer.username group.owner = new_maintainer.username
LOG.debug("new owner of {group} = {new_maintainer}".format(
group=group, new_maintainer=new_maintainer))
db.session.commit() db.session.commit()
return jsonify(status='OK') return jsonify(status='OK')
@groups.route('<token>/<groupId>/', methods=['DELETE']) @groups.route('<groupId>/', methods=['DELETE'])
def delete_group(token, groupId): @auth
"""Delete a group.""" def delete_group(groupId):
user = user_from_token(token) """*Authenticated request* Delete a group. Only the administrator of the
group can delete it.
**Success (200)**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/json
{ "status": "OK" }
**User is not administrator of the group (403)**:
:py:class:`UserIsNotAdminException`
**User not found (via token) (404)**:
:py:class:`UserNotFoundException`
**Authorization required (412)**:
:py:class:`AuthorizationRequiredException`
"""
user = request.user
group = Group.query.get(groupId) group = Group.query.get(groupId)
if not group: if not group:
raise ElementNotFoundException('Group') raise ElementNotFoundException('Group')

99
tests/group_tests.py

@ -28,14 +28,15 @@ class TestGroups(LunchoTests):
def test_empty_list(self): def test_empty_list(self):
"""Get an empty list from a user without groups.""" """Get an empty list from a user without groups."""
rv = self.get('/group/{token}/'.format(token=self.user.token)) rv = self.get('/group/', token=self.user.token)
self.assertJsonOk(rv, groups=[]) self.assertJsonOk(rv, groups=[])
def test_create_group(self): def test_create_group(self):
"""Test creating a group.""" """Test creating a group."""
request = {'name': 'Test group'} request = {'name': 'Test group'}
rv = self.put('/group/{token}/'.format(token=self.user.token), rv = self.put('/group/',
request) request,
token=self.user.token)
self.assertJsonOk(rv, id=1) self.assertJsonOk(rv, id=1)
def test_create_group_unverified_account(self): def test_create_group_unverified_account(self):
@ -44,22 +45,23 @@ class TestGroups(LunchoTests):
server.db.session.commit() server.db.session.commit()
request = {'name': 'Test group'} request = {'name': 'Test group'}
rv = self.put('/group/{token}/'.format(token=self.user.token), rv = self.put('/group/',
request) request,
token=self.user.token)
self.assertJsonError(rv, 412, 'Account not verified') self.assertJsonError(rv, 412, 'Account not verified')
def test_user_in_own_group(self): def test_user_in_own_group(self):
"""The user must belong to a group it owns.""" """The user must belong to a group it owns."""
token = self.user.token token = self.user.token
self.test_create_group() self.test_create_group()
rv = self.get('/group/{token}/'.format(token=token)) rv = self.get('/group/', token=token)
self.assertJsonOk(rv, groups=[{'id': 1, self.assertJsonOk(rv, groups=[{'id': 1,
'name': 'Test group', 'name': 'Test group',
'admin': True}]) 'admin': True}])
def test_get_groups_unknown_token(self): def test_get_groups_unknown_token(self):
"""Request groups with an unknown token.""" """Request groups with an unknown token."""
rv = self.get('/group/{token}/'.format(token='invalid')) rv = self.get('/group/', token='invalid')
self.assertJsonError(rv, 404, 'User not found (via token)') self.assertJsonError(rv, 404, 'User not found (via token)')
def test_get_groups_expired_token(self): def test_get_groups_expired_token(self):
@ -67,14 +69,15 @@ class TestGroups(LunchoTests):
self.user.token = 'expired' self.user.token = 'expired'
server.db.session.commit() server.db.session.commit()
rv = self.get('/group/{token}/'.format(token=self.user.token)) rv = self.get('/group/', token=self.user.token)
self.assertJsonError(rv, 400, 'Invalid token') self.assertJsonError(rv, 400, 'Invalid token')
def test_create_group_unknown_token(self): def test_create_group_unknown_token(self):
"""Try to create a group with an invalid token.""" """Try to create a group with an invalid token."""
request = {'name': 'Test group'} request = {'name': 'Test group'}
rv = self.put('/group/{token}/'.format(token='invalid'), rv = self.put('/group/',
request) request,
token='invalid')
self.assertJsonError(rv, 404, 'User not found (via token)') self.assertJsonError(rv, 404, 'User not found (via token)')
def test_create_group_expired_token(self): def test_create_group_expired_token(self):
@ -82,8 +85,9 @@ class TestGroups(LunchoTests):
server.db.session.commit() server.db.session.commit()
request = {'name': 'Test group'} request = {'name': 'Test group'}
rv = self.put('/group/{token}/'.format(token=self.user.token), rv = self.put('/group/',
request) request,
token=self.user.token)
self.assertJsonError(rv, 400, 'Invalid token') self.assertJsonError(rv, 400, 'Invalid token')
@ -112,9 +116,9 @@ class TestExistingGroups(LunchoTests):
"""Change the group name.""" """Change the group name."""
groupId = self.group.id groupId = self.group.id
request = {'name': 'New test group'} request = {'name': 'New test group'}
rv = self.post('/group/{token}/{groupId}/'.format(token=self.user.token, rv = self.post('/group/{groupId}/'.format(groupId=self.group.id),
groupId=self.group.id), request,
request) token=self.user.token)
self.assertJsonOk(rv) self.assertJsonOk(rv)
# check the database # check the database
@ -123,11 +127,10 @@ class TestExistingGroups(LunchoTests):
def test_update_name_invalid_token(self): def test_update_name_invalid_token(self):
"""Try to change the name with an unknown token.""" """Try to change the name with an unknown token."""
groupId = self.group.id
request = {'name': 'New test group'} request = {'name': 'New test group'}
rv = self.post('/group/{token}/{groupId}/'.format(token='invalid', rv = self.post('/group/{groupId}/'.format(groupId=self.group.id),
groupId=self.group.id), request,
request) token='invalid')
self.assertJsonError(rv, 404, 'User not found (via token)') self.assertJsonError(rv, 404, 'User not found (via token)')
def test_update_name_expired_token(self): def test_update_name_expired_token(self):
@ -136,9 +139,9 @@ class TestExistingGroups(LunchoTests):
server.db.session.commit() server.db.session.commit()
request = {'name': 'New test group'} request = {'name': 'New test group'}
rv = self.post('/group/{token}/{groupId}/'.format(token=self.user.token, rv = self.post('/group/{groupId}/'.format(groupId=self.group.id),
groupId=self.group.id), request,
request) token=self.user.token)
self.assertJsonError(rv, 400, 'Invalid token') self.assertJsonError(rv, 400, 'Invalid token')
def test_update_owner(self): def test_update_owner(self):
@ -152,11 +155,10 @@ class TestExistingGroups(LunchoTests):
groupId = self.group.id groupId = self.group.id
new_username = new_user.username new_username = new_user.username
request = {'maintainer': new_user.username} request = {'admin': new_user.username}
rv = self.post('/group/{token}/{groupId}/'.format( rv = self.post('/group/{groupId}/'.format(groupId=groupId),
token=self.user.token, request,
groupId=self.group.id), token=self.user.token)
request)
self.assertJsonOk(rv) self.assertJsonOk(rv)
# check the database # check the database
@ -165,40 +167,33 @@ class TestExistingGroups(LunchoTests):
def test_update_owner_invalid(self): def test_update_owner_invalid(self):
"""Try to change the owner to a user that doesn't exist.""" """Try to change the owner to a user that doesn't exist."""
groupId = self.group.id request = {'admin': 'unknown'}
current_owner = self.group.owner rv = self.post('/group/{groupId}/'.format(groupId=self.group.id),
request,
request = {'maintainer': 'unknown'} token=self.user.token)
rv = self.post('/group/{token}/{groupId}/'.format( self.assertJsonError(rv, 404, 'New admin not found')
token=self.user.token,
groupId=self.group.id
), request)
self.assertJsonError(rv, 401, 'New maintainer not found')
def test_update_unknown_group(self): def test_update_unknown_group(self):
"""Try to update a group that doesn't exist.""" """Try to update a group that doesn't exist."""
groupId = self.group.id + 10 groupId = self.group.id + 10
request = {'name': 'New test group'} request = {'name': 'New test group'}
rv = self.post('/group/{token}/{groupId}/'.format( rv = self.post('/group/{groupId}/'.format(groupId=groupId),
token=self.user.token, request,
groupId=groupId), token=self.user.token)
request)
self.assertJsonError(rv, 404, 'Group not found') self.assertJsonError(rv, 404, 'Group not found')
def test_delete_group(self): def test_delete_group(self):
"""Delete a group.""" """Delete a group."""
groupId = self.group.id groupId = self.group.id
rv = self.delete('/group/{token}/{groupId}/'.format( rv = self.delete('/group/{groupId}/'.format(groupId=groupId),
token=self.user.token, token=self.user.token)
groupId=groupId))
self.assertJsonOk(rv) self.assertJsonOk(rv)
def test_delete_unknown_group(self): def test_delete_unknown_group(self):
"""Delete a group that doesn't exist.""" """Delete a group that doesn't exist."""
groupId = self.group.id + 10 groupId = self.group.id + 10
rv = self.delete('/group/{token}/{groupId}/'.format( rv = self.delete('/group/{groupId}/'.format(groupId=groupId),
token=self.user.token, token=self.user.token)
groupId=groupId))
self.assertJsonError(rv, 404, 'Group not found') self.assertJsonError(rv, 404, 'Group not found')
def test_delete_not_admin(self): def test_delete_not_admin(self):
@ -210,16 +205,14 @@ class TestExistingGroups(LunchoTests):
server.db.session.commit() server.db.session.commit()
new_user.get_token() new_user.get_token()
rv = self.delete('/group/{token}/{groupId}/'.format( rv = self.delete('/group/{groupId}/'.format(groupId=self.group.id),
token=new_user.token, token=new_user.token)
groupId=self.group.id)) self.assertJsonError(rv, 403, 'User is not admin')
self.assertJsonError(rv, 401, 'User is not admin')
def test_delete_invalid_token(self): def test_delete_invalid_token(self):
"""Try to delete a group with an unknown token.""" """Try to delete a group with an unknown token."""
rv = self.delete('/group/{token}/{groupId}/'.format( rv = self.delete('/group/{groupId}/'.format(groupId=self.group.id),
token='invalid', token='invalid')
groupId=self.group.id))
self.assertJsonError(rv, 404, 'User not found (via token)') self.assertJsonError(rv, 404, 'User not found (via token)')
if __name__ == '__main__': if __name__ == '__main__':

Loading…
Cancel
Save