messages.py (5677B)
1 from flask import request, render_template, make_response, jsonify 2 from flask_restx import Namespace, Resource, fields 3 4 from MessageTagging.spam_detector import SpamDetector 5 from WebAPI.utils.mailer import Mailer 6 from database.models.messages import MessageModel 7 from database.models.spam import SpamModel 8 from database.repository import DbRepository 9 10 messages_ns = Namespace('messages', description='Message operations') 11 12 db_repository = DbRepository() 13 message_model = MessageModel() 14 spam_model = SpamModel() 15 mailer = Mailer() 16 sd = SpamDetector() 17 18 message_read_model = messages_ns.model('Message', { 19 'id': fields.Integer(readOnly=True, description='The message unique identifier'), 20 'name': fields.String(required=True, description='The senders name'), 21 'email': fields.String(required=True, description='The email address of the sender'), 22 'subject': fields.String(required=False, description='The subject of the message'), 23 'content': fields.String(required=True, description='The content of the message'), 24 'timestamp': fields.String(required=True, description='The time at which the message was sent'), 25 'relevance': fields.Float(readOnly=True, description='relevance, tries to set to low values for spam') 26 }) 27 28 29 @messages_ns.route('/') 30 class MessageList(Resource): 31 32 @messages_ns.doc('get_messages') 33 @messages_ns.response(400, "sort_order must be either 'ASC' or 'DESC'") 34 @messages_ns.response(400, "Invalid sort_by field. Must be one of {sort fields}") 35 @messages_ns.response(406, "Invalid accept header. Must be one of {valid_accept_headers}, received: {accept_header}") 36 @messages_ns.param('query', 'search query') 37 @messages_ns.param('sort_by', 'Field to sort the messages by') 38 @messages_ns.param('sort_order', 'Order to sort the messages (ASC or DESC)') 39 @messages_ns.param('page', 'The page to retrieve') 40 @messages_ns.param('page_size', 'The number of messages to retrieve per page') 41 @messages_ns.produces(['application/json', 'text/html']) 42 def get(self): 43 """Get (paginated) messages (HTML or JSON)""" 44 args = request.args 45 query = args.get('query', '', type=str) 46 page = args.get('page', 1, type=int) 47 page_size = args.get('page_size', 10, type=int) 48 sort_by = args.get('sort_by', 'id') # Default sort by 'id' 49 sort_order = args.get('sort_order', 'ASC').upper() # Default sort order 'ASC' 50 51 messages, total_pages = message_model.get_page(page, page_size, sort=sort_by, sort_order=sort_order, 52 search=query) 53 accept_header = request.headers.get('Accept', '') 54 55 if sort_order not in ['ASC', 'DESC']: 56 messages_ns.abort(400, "sort_order must be either 'ASC' or 'DESC'") 57 58 valid_sort_fields = ['id', 'name', 'email', 'subject', 'timestamp', 'relevance', 'content'] 59 if sort_by not in valid_sort_fields: 60 messages_ns.abort(400, f"Invalid sort_by field. Must be one of {valid_sort_fields}") 61 62 valid_accept_headers = ['', 'text/html', 'application/json'] 63 if accept_header not in valid_accept_headers: 64 messages_ns.abort(406, 65 f"Invalid accept header. Must be one of {valid_accept_headers}, received: {accept_header}") 66 67 if 'text/html' in accept_header: 68 response = make_response(render_template('component/messages_template.html', messages=messages)) 69 response.headers['X-Total-Pages'] = total_pages 70 response.headers['X-Current-Page'] = page 71 return response 72 else: 73 response = make_response(jsonify(messages)) 74 response.headers['X-Total-Pages'] = total_pages 75 response.headers['X-Current-Page'] = page 76 return response 77 78 79 @messages_ns.route('/<int:id>') 80 @messages_ns.response(404, 'Message not found') 81 class Message(Resource): 82 @messages_ns.marshal_with(message_read_model) 83 def get(self, id): 84 """Get a message""" 85 message = message_model.get(id) 86 if message: 87 return message, 200 88 else: 89 messages_ns.abort(404, "Message not found") 90 91 @messages_ns.response(204, 'Message deleted') 92 @messages_ns.response(404, 'Message not found') 93 def delete(self, id): 94 """Delete a message""" 95 message = message_model.get(id) 96 if not message: 97 messages_ns.abort(404, "Message not found") 98 99 try: 100 message_model.delete(id) 101 return make_response('', 204) 102 except Exception as e: 103 messages_ns.abort(500, "An internal error occurred") 104 """Delete a message by id""" 105 106 107 @messages_ns.response(404, 'Message not found') 108 @messages_ns.route('/flag/<int:id>') 109 class MessageList(Resource): 110 @messages_ns.response(204, 'Message flagged') 111 def post(self, id): 112 """Flag a message (moves it to spam)""" 113 message = message_model.get(id) 114 115 if not message: 116 messages_ns.abort(404, 'Message not found') 117 118 parameters = [ 119 message.get('name'), 120 message.get('email'), 121 message.get('subject'), 122 message.get('content'), 123 message.get('relevance') 124 ] 125 126 if message: 127 try: 128 spam_model.create(parameters) 129 except Exception as e: 130 messages_ns.abort(500, 'An error occurred') 131 132 try: 133 message_model.delete(message.get('id')) 134 except Exception as e: 135 spam_model.delete(message.get('id')) 136 messages_ns.abort(500, 'An error occurred') 137 138 return '', 204