import json from json.decoder import JSONDecodeError from django.http import JsonResponse from oauth2_provider.decorators import protected_resource from lists.forms import ListItemForm, TagForm, EntityForm from lists.models import ListItem, Tag, Entity from users.models import User def list_view(request, user_id): """ Punto de entrada de las vistas de lista de un usuario """ # Tiene que existir un usuario con el id entregado. user = User.objects.filter(pk=user_id) if user.count() != 1: return JsonResponse({'status': 404, 'error': f'No existe un usuario con id {user_id}'}, status=404) user = user[0] if request.method == 'GET': return _get_list(request, user) elif request.method == 'POST': return _add_to_list(request, user) else: return JsonResponse({'status': 404, 'error': 'La ruta no existe'}, status=404) def _get_list(request, user): """Retorna la lista de un usuario""" encoded_list = [] for list_item in user.list.all(): encoded_list.append({ 'entity': { 'mbid': list_item.entity.mbid, 'type': list_item.entity.entity_type, }, 'tags': [{ 'id': tag.id, 'name': tag.name } for tag in list_item.tags.all()] }) return JsonResponse({'list': encoded_list}) @protected_resource() def _add_to_list(request, user): """Agrega un nuevo item a la lista del usuario""" # Solo el dueño o un administrador puede modificar la lista if request.user.id != user.id and not request.user.is_admin: return JsonResponse({'status': 403, 'error': 'El usuario no tiene permiso para hacer esta acción'}, status=403) try: request_data = json.loads(request.body.decode('utf8')) except JSONDecodeError: return JsonResponse({'status': 400, 'error': 'El body de la request no es json valido'}, status=400) list_item = ListItem(user=user) if request_data.get('entity') and Entity.objects.filter(mbid=request_data['entity']).count() == 0: # Entity no existe en la base de datos, se crea data = { 'mbid': request_data.get('entity', None), 'entity_type': request_data.get('entity_type', None) } entity_form = EntityForm(data) if not entity_form.is_valid(): return JsonResponse({'status': 400, 'error': entity_form.errors.as_json()}, status=400) entity_form.save() form = ListItemForm(request_data, instance=list_item) if not form.is_valid(): return JsonResponse({'status': 400, 'error': form.errors.as_json()}, status=400) if user.list.filter(entity__mbid=request_data['entity']).count() > 0: return JsonResponse({'status': 400, 'error': 'El usuario ya tiene esta entidad en su lista'}, status=400) form.save() return JsonResponse({'status': 200}) def list_item_view(request, user_id, list_item_id): """ Punto de entrada a las vistas de item de lista de un usuario """ # Tiene que existir un usuario con el id entregado. user = User.objects.filter(pk=user_id) if user.count() != 1: return JsonResponse({'status': 404, 'error': f'No existe un usuario con id {user_id}'}, status=404) user = user[0] # Tiene que existir un item de lista de usuario con el id entregado list_item = ListItem.objects.filter(id=list_item_id, user_id=user_id) if list_item.count() == 0: return JsonResponse({'status': 404, 'error': 'No existe el list_item'}, status=404) list_item = list_item[0] if request.method == 'GET': return _get_list_item(request, user, list_item) if request.method == 'PUT': return _update_list_item(request, user, list_item) elif request.method == 'DELETE': return _remove_list_item(request, user, list_item) else: return JsonResponse({'status': 404, 'error': 'La ruta no existe'}, status=404) def _get_list_item(request, user, list_item): """Obtiene un item de la lista del usuario""" encoded_list_item = { 'entity': { 'mbid': list_item.entity.mbid, 'type': list_item.entity.entity_type, }, 'tags': [{ 'id': tag.id, 'name': tag.name } for tag in list_item.tags.all()] } return JsonResponse(encoded_list_item) @protected_resource() def _update_list_item(request, user, list_item): # Solo el dueño o un administrador puede modificar la lista if request.user.id != user.id and not request.user.is_admin: return JsonResponse({'status': 403, 'error': 'El usuario no tiene permiso para hacer esta acción'}, status=403) try: request_data = json.loads(request.body.decode('utf8')) except JSONDecodeError: return JsonResponse({'status': 400, 'error': 'El body de la request no es json valido'}, status=400) form = ListItemForm(request_data, instance=list_item) if not form.is_valid(): return JsonResponse({'status': 400, 'error': form.errors.as_json()}, status=400) form.save() return JsonResponse({'status': 200}) @protected_resource() def _remove_list_item(request, user, list_item): """Elimina un item de la lista del usuario""" # Solo el dueño o un administrador puede modificar la lista if request.user.id != user.id and not request.user.is_admin: return JsonResponse({'status': 403, 'error': 'El usuario no tiene permiso para hacer esta acción'}, status=403) list_item.delete() return JsonResponse({'status': 200}) def tag_view(request, user_id, tag_id=None): """ Punto de entrada para las vistas de tags """ # Tiene que existir un usuario con el id entregado. user = User.objects.filter(pk=user_id) if user.count() != 1: return JsonResponse({'status': 404, 'error': f'No existe un usuario con id {user_id}'}, status=404) user = user[0] # Tag id puede ser none, pero si no lo es, tiene que existir tag = None if tag_id: tag = Tag.objects.filter(pk=tag_id) if tag.count() != 1: return JsonResponse({'status': 404, 'error': f'No existe una tag con id {tag}'}, status=404) tag = tag[0] if request.method == 'GET': return _get_tags(request, user) elif request.method == 'POST': return _post_tag(request, user) elif request.method == 'PUT' and tag: return _put_tag(request, user, tag) elif request.method == 'DELETE' and tag: return _delete_tag(request, user, tag) else: return JsonResponse({'status': 404, 'error': 'La ruta no existe'}, status=404) def _get_tags(request, user): """Obtiene todas las tags de un usuario""" encoded_tags = [] for tag in user.tags.all(): encoded_tags.append({ 'id': tag.id, 'name': tag.name }) return JsonResponse({'tags': encoded_tags}) @protected_resource() def _post_tag(request, user): """Crea una nueva tag en un usuario""" # Solo el dueño o un administrador puede modificar la lista if request.user.id != user.id and not request.user.is_admin: return JsonResponse({'status': 403, 'error': 'El usuario no tiene permiso para hacer esta acción'}, status=403) try: request_data = json.loads(request.body.decode('utf8')) except JSONDecodeError: return JsonResponse({'status': 400, 'error': 'El body de la request no es json valido'}, status=400) tag = Tag(user=user) form = TagForm(request_data, instance=tag) if not form.is_valid(): return JsonResponse({'status': 400, 'error': form.errors.as_json()}, status=400) if user.tags.filter(name=request_data['name']).count() > 0: return JsonResponse({'status': 400, 'error': 'El usuario ya tiene un tag con ese nombre'}, status=400) form.save() return JsonResponse({'status': 200}) @protected_resource() def _put_tag(request, user, tag): """Actualiza una tag""" # Solo el dueño o un administrador puede modificar la lista if request.user.id != user.id and not request.user.is_admin: return JsonResponse({'status': 403, 'error': 'El usuario no tiene permiso para hacer esta acción'}, status=403) try: request_data = json.loads(request.body.decode('utf8')) except JSONDecodeError: return JsonResponse({'status': 400, 'error': 'El body de la request no es json valido'}, status=400) form = TagForm(request_data, instance=tag) if not form.is_valid(): return JsonResponse({'status': 400, 'error': form.errors.as_json()}, status=400) if user.tags.filter(name=request_data['name']).count() > 0: return JsonResponse({'status': 400, 'error': 'El usuario ya tiene un tag con ese nombre'}, status=400) form.save() return JsonResponse({'status': 200}) @protected_resource() def _delete_tag(request, user, tag): """Elimina una tag de un usuario, al eliminarla se remueve de todas los listitem a las que estaba asociada""" # Solo el dueño o un administrador puede modificar la lista if request.user.id != user.id and not request.user.is_admin: return JsonResponse({'status': 403, 'error': 'El usuario no tiene permiso para hacer esta acción'}, status=403) # Eliminando la tag de los items que están asociados a ella for list_item in tag.list.all(): list_item.tags.remove(tag) tag.delete() return JsonResponse({'status': 200}, status=200)