Browse Source

added the group+places management, still missing tests

master
Julio Biason 11 years ago
parent
commit
d8c7c286b4
  1. 4
      doc/client/groups.rst
  2. 250
      luncho/blueprints/groups.py

4
doc/client/groups.rst

@ -6,3 +6,7 @@ Groups are used to select which people will go to which place.
.. autoflask:: luncho.server:app .. autoflask:: luncho.server:app
:blueprints: groups :blueprints: groups
:undoc-endpoints: static, show_api :undoc-endpoints: static, show_api
.. autoflask:: luncho.server:app
:blueprints: group_users
:undoc-endpoints: static, show_api

250
luncho/blueprints/groups.py

@ -12,9 +12,10 @@ from flask import jsonify
from luncho.helpers import ForceJSON from luncho.helpers import ForceJSON
from luncho.helpers import auth from luncho.helpers import auth
from luncho.server import db
from luncho.server import User from luncho.server import User
from luncho.server import Group from luncho.server import Group
from luncho.server import db from luncho.server import Place
from luncho.exceptions import LunchoException from luncho.exceptions import LunchoException
from luncho.exceptions import ElementNotFoundException from luncho.exceptions import ElementNotFoundException
@ -23,6 +24,10 @@ from luncho.exceptions import NewMaintainerDoesNotExistException
from luncho.exceptions import UserIsNotAdminException from luncho.exceptions import UserIsNotAdminException
# ----------------------------------------------------------------------
# Exceptions
# ----------------------------------------------------------------------
class UserIsNotMemberException(LunchoException): class UserIsNotMemberException(LunchoException):
"""The user is not the admin of the group. """The user is not the admin of the group.
@ -39,33 +44,9 @@ class UserIsNotMemberException(LunchoException):
self.message = 'User is not member of this group' self.message = 'User is not member of this group'
class SomeUsersNotFoundException(LunchoException): # ----------------------------------------------------------------------
"""Some users in the add list do not exist. # The base group management
# ----------------------------------------------------------------------
.. sourcecode:: http
HTTP/1.1 404 Not Found
Content-Type: text/json
{ "status": "ERROR",
"message", "Some users in the add list do not exist",
"users": ["<username>", "<username>", ...]}
"""
def __init__(self, users=None):
super(SomeUsersNotFoundException, self).__init__()
self.status = 404
self.message = 'Some users in the add list do not exist'
self.users = users
def response(self):
json = {'status': 'ERROR',
'message': self.message}
if self.users:
json['users'] = self.users
response = jsonify(json)
response.status_code = self.status
return response
groups = Blueprint('groups', __name__) groups = Blueprint('groups', __name__)
@ -163,10 +144,10 @@ def create_group():
id=new_group.id) id=new_group.id)
@groups.route('<groupId>/', methods=['PUT']) @groups.route('<group_id>/', methods=['PUT'])
@ForceJSON() @ForceJSON()
@auth @auth
def update_group(groupId): def update_group(group_id):
"""*Authenticated request* """*Authenticated request*
Update group information. The user must be the administrator of the group Update group information. The user must be the administrator of the group
@ -197,7 +178,7 @@ def update_group(groupId):
(:py:class:`AuthorizationRequiredException`) (:py:class:`AuthorizationRequiredException`)
""" """
user = request.user user = request.user
group = Group.query.get(groupId) group = Group.query.get(group_id)
if not group: if not group:
raise ElementNotFoundException('Group') raise ElementNotFoundException('Group')
@ -223,14 +204,14 @@ def update_group(groupId):
return jsonify(status='OK') return jsonify(status='OK')
@groups.route('<groupId>/', methods=['DELETE']) @groups.route('<group_id>/', methods=['DELETE'])
@auth @auth
def delete_group(groupId): def delete_group(group_id):
"""*Authenticated request* """*Authenticated request*
Delete a group. Only the administrator of the group can delete it. Delete a group. Only the administrator of the group can delete it.
:param groupId: The group Id :param group_id: The group Id
:header Authorization: Access token from `/token/`. :header Authorization: Access token from `/token/`.
@ -243,7 +224,7 @@ def delete_group(groupId):
(:py:class:`AuthorizationRequiredException`) (:py:class:`AuthorizationRequiredException`)
""" """
user = request.user user = request.user
group = Group.query.get(groupId) group = Group.query.get(group_id)
if not group: if not group:
raise ElementNotFoundException('Group') raise ElementNotFoundException('Group')
@ -255,19 +236,23 @@ def delete_group(groupId):
return jsonify(status='OK') return jsonify(status='OK')
# ----------------------------------------------------------------------
# Group users
# ----------------------------------------------------------------------
group_users = Blueprint('group_users', __name__) group_users = Blueprint('group_users', __name__)
@group_users.route('<groupId>/users/', methods=['PUT']) @group_users.route('<group_id>/users/', methods=['PUT'])
@ForceJSON(required=['usernames']) @ForceJSON(required=['usernames'])
@auth @auth
def add_users_to_group(groupId): def add_users_to_group(group_id):
"""*Authenticated request* """*Authenticated request*
Add users to the group. Only the group administrator can add users to Add users to the group. Only the group administrator can add users to
their groups. their groups.
:param groupId: The group Id :param group_id: The group Id
**Example request**: **Example request**:
@ -277,21 +262,27 @@ def add_users_to_group(groupId):
:header Authorization: Access token from `/token/`. :header Authorization: Access token from `/token/`.
:status 200: Success :status 200: Success. Users that couldn't be found will be returned in
the "not_found" field.
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/json
{ "status": "OK", "not_found": [<user>, <user>, ...] }
:status 400: Request not in JSON format :status 400: Request not in JSON format
(:py:class:`RequestMustBeJSONException`) (:py:class:`RequestMustBeJSONException`)
:status 403: User is not the group administrator :status 403: User is not the group administrator
(:py:class:`UserIsNotAdminException`) (:py:class:`UserIsNotAdminException`)
:status 404: User not found (via token) :status 404: User not found (via token)
(:py:class:`UserNotFoundException`) (:py:class:`UserNotFoundException`)
:status 404: Incomplete request, some users not found; users that couldn't
be found will return in the "missing" field.
(:py:class:`SomeUsersNotFoundException`)
:status 412: Authorization required :status 412: Authorization required
(:py:class:`AuthorizationRequiredException`) (:py:class:`AuthorizationRequiredException`)
""" """
user = request.user user = request.user
group = Group.query.get(groupId) group = Group.query.get(group_id)
if not group: if not group:
raise ElementNotFoundException('Group') raise ElementNotFoundException('Group')
@ -307,22 +298,21 @@ def add_users_to_group(groupId):
continue continue
user_obj.groups.append(group) user_obj.groups.append(group)
db.session.commit()
if unknown: return jsonify(status='OK',
raise SomeUsersNotFoundException(unknown) not_found=unknown)
return jsonify(status='OK')
@group_users.route('<groupId>/users/', methods=['GET']) @group_users.route('<group_id>/users/', methods=['GET'])
@auth @auth
def list_group_members(groupId): def list_group_members(group_id):
"""*Authenticated request* """*Authenticated request*
Return a list of the users in the group. The user must be part of the Return a list of the users in the group. The user must be part of the
group to request this list. group to request this list.
:parma groupId: The group Id :param group_id: The group Id
:header Authorization: Access token from `/token/`. :header Authorization: Access token from `/token/`.
@ -341,10 +331,12 @@ def list_group_members(groupId):
(:py:class:`UserIsNotMemberException`) (:py:class:`UserIsNotMemberException`)
:status 404: User not found (via token) :status 404: User not found (via token)
(:py:class:`UserNotFoundException`) (:py:class:`UserNotFoundException`)
:status 404: Group not found
(:py:class:`ElementNotFoundException`)
:status 412: Authorization required :status 412: Authorization required
(:py:class:`AuthorizationRequiredException`) (:py:class:`AuthorizationRequiredException`)
""" """
group = Group.query.filter_by(id=groupId).first() group = Group.query.filter_by(id=group_id).first()
if not group: if not group:
raise ElementNotFoundException('Group') raise ElementNotFoundException('Group')
@ -355,5 +347,161 @@ def list_group_members(groupId):
for user in group.users: for user in group.users:
users.append({'username': user.username, users.append({'username': user.username,
'full_name': user.fullname}) 'full_name': user.fullname})
db.session.commit()
return jsonify(status='OK', users=users) return jsonify(status='OK', users=users)
# ----------------------------------------------------------------------
# Group places
# ----------------------------------------------------------------------
group_places = Blueprint('group_places', __name__)
@group_places.route('<group_id>/places/', methods=['GET'])
@auth
def get_group_places(group_id):
"""*Authenticated request*
Return the list of places for the group. The user must be a member of
the group the get the list of places.
:param group_id: The group Id
:header Authorization: Access token from `/token/`.
:status 200: Success
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/json
{ "status": "OK", "places": [ { "id": "<place id>",
"name": "<place name>"},
...] }
:status 403: The user is not a member of the group
(:py:class:`UserIsNotMemberException`)
:status 404: User not found (via token)
(:py:class:`UserNotFoundException`)
:status 404: Group does not exist
(:py:class:`ElementNotFoundException`)
:status 412: Authorization required
(:py:class:`AuthorizationRequiredException`)
"""
group = Group.query.get(group_id)
if not group:
raise ElementNotFoundException('Group')
if request.user not in group.users:
raise UserIsNotMemberException()
places = []
for place in group.places:
places.append({'id': place.id,
'name': place.name})
return jsonify(status='OK',
places=places)
@group_places.route('<group_id>/places/', methods=['POST'])
@ForceJSON(required=['places'])
@auth
def group_add_places(group_id):
"""*Authenticated request*
Add a list of places to the group. The user must be the admin of the group
to add a place; the place must belong to one of the group members to be
able to be added to the group.
:param group_id: The group Id
:header Authorization: Access token from `/token/`.
:status 200: Success. If there are any places that do not belong to group
members, those will be returned in the "rejected" field; places that
don't exist will be returned in the "not_found" field.
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: text/json
{ "status": "OK",
"rejected": [<place>, <place>, ...],
"not_found": [<place>, <place>, ...] }
:status 400: Request not in JSON format
(:py:class:`RequestMustBeJSONException`)
:status 403: User is not the group administrator
(:py:class:`UserIsNotAdminException`)
:status 404: User not found (via token)
(:py:class:`UserNotFoundException`)
:status 412: Authorization required
(:py:class:`AuthorizationRequiredException`)
"""
group = Group.query.get(group_id)
if not group:
raise ElementNotFoundException('Group')
if not group.owner == request.user:
raise UserIsNotAdminException()
not_found = []
rejected = []
for place_id in request.as_json.get('places', []):
place = Place.query.get(place_id)
if not place:
not_found.append(place_id)
continue
if place.owner not in group.users:
rejected.append(place_id)
group.places.append(place)
db.session.commit()
return jsonify(status='OK',
not_found=not_found,
rejected=rejected)
@group_places.route('<group_id>/places/<place_id>/', methods=['DELETE'])
@auth
def group_remove_place(group_id, place_id):
"""*Authenticated request*
Remove a place from the group. The user must be the group owner.
:param group_id: The group Id
:param place_id: The place Id
:header Authorization: Access token from `/token/`.
:status 200: Success
:status 403: User is not the group administrator
(:py:class:`UserIsNotAdminException`)
:status 404: User not found (via token)
(:py:class:`UserNotFoundException`)
:status 404: Group not found (:py:class:`ElementNotFoundException`)
:status 404: Place is not part of the group
(:py:class:`ElementNotFoundException`)
:status 412: Authorization required
(:py:class:`AuthorizationRequiredException`)
"""
group = Group.query.get(group_id)
if not group:
raise ElementNotFoundException('Group')
index = None
try:
index = group.places.index(place_id)
except ValueError:
raise ElementNotFoundException('Place')
del group.places[index]
db.session.commit()
return jsonify(status='OK')

Loading…
Cancel
Save