diff --git a/README.md b/README.md index 0559d77..98aae3a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ curl -v -s http://127.0.0.1:9090/api/v1/quarmails?rfc822_message=1 | jq ## update a QuarMail´s metadata (e.g. sandbox_results) by ID ``` - curl -v -s -X PATCH -d '{"sandbox_results":"12345abc"}' http://127.0.0.1:9090/api/v1/quarmails/311|jq + curl -v -s -X PATCH -d '{"cf_meta":"12345abc"}' http://127.0.0.1:9090/api/v1/quarmails/311|jq ``` ## delete a QuarMail by ID diff --git a/app/Gulag.py b/app/Gulag.py index 97a720c..7b04de0 100644 --- a/app/Gulag.py +++ b/app/Gulag.py @@ -61,6 +61,7 @@ class Gulag: self.fields['Mailrelays'] = self.db.get_fields('Mailrelays') self.fields['QuarMails'] = self.db.get_fields('QuarMails') self.fields['Attachments'] = self.db.get_fields('Attachments') + self.fields['URIs'] = self.db.get_fields('URIs') except GulagDBException as e: logging.warning(whoami(self) + e.message) raise GulagException(whoami(self) + e.message) from e @@ -178,9 +179,9 @@ class Gulag: "QuarMail(%s)@Mailbox(%s) imported" % (quarmail_id,mailbox['id']) ) quarmail_ids.append(quarmail_id) - # Ende for rcpts - # Alle MIME-Parts durchiterieren und Attachments - # (MIME-Parts mit name/filename Attribut) extrahieren + # End for rcpts + # Iterate through all MIME-parts and extract all + # attachments (parts with a name/filename attribute) for part in msg.walk(): if part.get_filename(): # ist ein Attachment @@ -533,6 +534,24 @@ class Gulag: if 'data' not in args: return at_db + def modify_attachment(self, attachment): + try: + if 'id' not in attachment: + raise GulagBadInputException(whoami(self) + "'id' is mandatory!") + for field in attachment: + if field not in self.fields['Attachments']: + raise GulagBadInputException(whoami(self) + + "Unknown Attachment field: " + field + ) + self.db.modify_attachment(attachment) + except GulagDBBadInputException as e: + raise GulagBadInputException(whoami(self) + e.message) from e + except GulagDBNotFoundException as e: + raise GulagNotFoundException(whoami(self) + e.message) from e + except GulagDBException as e: + logging.warning(whoami(self) + e.message) + raise GulagException(whoami(self) + e.message) from e + def get_quarmail_uris(self,args): if('from_rfc822_message' not in args): try: @@ -580,6 +599,24 @@ class Gulag: except GulagDBException as e: raise GulagException(whoami(self) + e.message) from e + def modify_uri(self, uri): + try: + if 'id' not in uri: + raise GulagBadInputException(whoami(self) + "'id' is mandatory!") + for field in uri: + if field not in self.fields['URIs']: + raise GulagBadInputException(whoami(self) + + "Unknown URI field: " + field + ) + self.db.modify_uri(uri) + except GulagDBBadInputException as e: + raise GulagBadInputException(whoami(self) + e.message) from e + except GulagDBNotFoundException as e: + raise GulagNotFoundException(whoami(self) + e.message) from e + except GulagDBException as e: + logging.warning(whoami(self) + e.message) + raise GulagException(whoami(self) + e.message) from e + def rspamd2mailbox(self,args): mailbox = None try: diff --git a/app/GulagDB.py b/app/GulagDB.py index a57b486..ad8cbfa 100644 --- a/app/GulagDB.py +++ b/app/GulagDB.py @@ -415,6 +415,31 @@ class GulagDB: except mariadb.Error as e: raise GulagDBException(whoami(self) + str(e.msg)) from e + def modify_attachment(self, attachment): + try: + cursor = self.conn.cursor() + mod_fields = "" + if 'id' not in attachment: + raise GulagDBBadInputException("Missing Attachment-ID!") + if len(attachment) < 2: + raise GulagDBBadInputException("No fields specified to modify!") + for field in attachment: + if field == 'id': + continue + mod_fields += " " + field + "='" + attachment[field] + "'," + mod_fields = str(mod_fields).rstrip(',') + cursor.execute( + "update Attachment set "+mod_fields+" where id="+str(attachment['id']) + ) + if(cursor.rowcount == 0): + raise GulagDBNotFoundException(whoami(self) + "No attachments modified!") + cursor.close() + return True + except GulagDBBadInputException as e: + raise GulagDBBadInputException(whoami(self) + e.message) from e + except mariadb.Error as e: + raise GulagDBException(whoami(self) + str(e.msg)) from e + def get_attachments(self): try: query = "select Attachments.*,QuarMails.mailbox_id,QuarMails.imap_uid" @@ -433,7 +458,9 @@ class GulagDB: dict = {} for (name, value) in zip(desc, tuple): dict[name[0]] = value - dict['href'] = self.uri_prefixes['attachments'] + str(dict['id']) + #dict['href'] = self.uri_prefixes['attachments'] + str(dict['id']) + dict['href'] = self.uri_prefixes['quarmails'] + str(quarmail_id) + dict['href'] += "/attachments/" + str(dict['id']) results.append(Attachment(dict).__dict__) return results except mariadb.Error as e: @@ -458,7 +485,9 @@ class GulagDB: dict = {} for (name, value) in zip(desc, tuple): dict[name[0]] = value - dict['href'] = self.uri_prefixes['attachments'] + str(dict['id']) + #dict['href'] = self.uri_prefixes['attachments'] + str(dict['id']) + dict['href'] = self.uri_prefixes['quarmails'] + str(quarmail_id) + dict['href'] += "/attachments/" + str(dict['id']) return Attachment(dict).__dict__ except mariadb.Error as e: raise GulagDBException(whoami(self) + str(e.msg)) from e @@ -554,6 +583,29 @@ class GulagDB: except mariadb.Error as e: raise GulagDBException(whoami(self) + str(e.msg)) from e + def modify_uri(self, uri): + try: + cursor = self.conn.cursor() + mod_fields = "" + if 'id' not in uri: + raise GulagDBBadInputException("Missing URI-ID!") + if len(uri) < 2: + raise GulagDBBadInputException("No fields specified to modify!") + for field in uri: + if field == 'id': + continue + mod_fields += " " + field + "='" + uri[field] + "'," + mod_fields = str(mod_fields).rstrip(',') + cursor.execute("update URI set "+mod_fields+" where id="+str(uri['id'])) + if(cursor.rowcount == 0): + raise GulagDBNotFoundException(whoami(self) + "No URIs modified!") + cursor.close() + return True + except GulagDBBadInputException as e: + raise GulagDBBadInputException(whoami(self) + e.message) from e + except mariadb.Error as e: + raise GulagDBException(whoami(self) + str(e.msg)) from e + def quarmail2uri(self,quarmail_id,uri_id): try: cursor = self.conn.cursor() @@ -582,6 +634,7 @@ class GulagDB: dict = {} for (name, value) in zip(desc, tuple): dict[name[0]] = value + #dict['href'] = self.uri_prefixes['uris'] + str(dict['id']) dict['href'] = self.uri_prefixes['quarmails'] + str(quarmail_id) dict['href'] += "/uris/" + str(dict['id']) results.append(URI(dict).__dict__) @@ -612,6 +665,7 @@ class GulagDB: dict = {} for (name, value) in zip(desc, tuple): dict[name[0]] = value + #dict['href'] = self.uri_prefixes['uris'] + str(dict['id']) dict['href'] = self.uri_prefixes['quarmails'] + str(quarmail_id) dict['href'] += "/uris/" + str(dict['id']) try: diff --git a/app/Resources.py b/app/Resources.py index 5e0efa6..7eb1d14 100644 --- a/app/Resources.py +++ b/app/Resources.py @@ -12,6 +12,7 @@ class GulagResource(Resource): self.gulag = gulag_object #XXX self.check_trusted_proxy() #XXX self.check_auth() + self.check_max_body_size() def check_trusted_proxy(self): remote_ip = request.remote_addr @@ -31,11 +32,12 @@ class GulagResource(Resource): if api_key not in self.gulag.config['api_keys']: abort(401, message="NOT AUTHORIZED!") - def check_dos(self): + def check_max_body_size(self): body_len = len(request.get_data(as_text=True)) if(body_len > self.gulag.config['dos_protection']['max_body_bytes']): raise GulagBadInputException(whoami(self) + - "Request body max size exceeded" + "Request exceedes maximum body size (" + + self.gulag.config['dos_protection']['max_body_bytes'] + " bytes)!" ) class ResRoot(GulagResource): @@ -191,6 +193,46 @@ class ResAttachment(GulagResource): abort(404, message=whoami(self)+e.message) except GulagException as e: abort(500, message=whoami(self)+e.message) + def patch(self,attachment_id): + try: + args = json.loads(request.get_data(as_text=True)) + args['id'] = attachment_id + except json.JSONDecodeError as e: + abort(400, message=whoami(self) + "Invalid JSON: " + e.msg) + try: + self.gulag.modify_attachment(args) + return Response(response=None,status=204,mimetype=None) + except GulagBadInputException as e: + abort(400, message=whoami(self)+e.message) + except GulagNotFoundException as e: + abort(404, message=whoami(self)+e.message) + except GulagException as e: + abort(500, message=whoami(self)+e.message) + +class ResURI(GulagResource): + def get(self,uri_id): + args = {"id": uri_id} + try: + return self.gulag.get_uri(args) + except GulagNotFoundException as e: + abort(404, message=whoami(self)+e.message) + except GulagException as e: + abort(500, message=whoami(self)+e.message) + def patch(self,uri_id): + try: + args = json.loads(request.get_data(as_text=True)) + args['id'] = uri_id + except json.JSONDecodeError as e: + abort(400, message=whoami(self) + "Invalid JSON: " + e.msg) + try: + self.gulag.modify_uri(args) + return Response(response=None,status=204,mimetype=None) + except GulagBadInputException as e: + abort(400, message=whoami(self)+e.message) + except GulagNotFoundException as e: + abort(404, message=whoami(self)+e.message) + except GulagException as e: + abort(500, message=whoami(self)+e.message) class ResRspamd2Mailbox(GulagResource): def post(self,mailbox_id): diff --git a/config/gulag-config.json b/config/gulag-config.json index 711843e..244f5ee 100644 --- a/config/gulag-config.json +++ b/config/gulag-config.json @@ -27,7 +27,8 @@ "mailrelays": "http://127.0.0.1:9090/api/v1/mailrelays/", "mailboxes": "http://127.0.0.1:9090/api/v1/mailboxes/", "quarmails": "http://127.0.0.1:9090/api/v1/quarmails/", - "attachments": "http://127.0.0.1:9090/api/v1/attachments/" + "attachments": "http://127.0.0.1:9090/api/v1/attachments/", + "uris": "http://127.0.0.1:9090/api/v1/uris/" }, "dos_protection": { "max_body_bytes": 8388608