Nenhuma Descrição

manage_customers_routes.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. # IRIS Source Code
  2. # Copyright (C) 2024 - DFIR-IRIS
  3. # contact@dfir-iris.org
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Lesser General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 3 of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # Lesser General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Lesser General Public License
  16. # along with this program; if not, write to the Free Software Foundation,
  17. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. import datetime
  19. import traceback
  20. from flask import Blueprint
  21. from flask import request
  22. from flask_login import current_user
  23. from marshmallow import ValidationError
  24. from app import ac_current_user_has_permission
  25. from app.blueprints.access_controls import ac_api_requires
  26. from app.datamgmt.client.client_db import create_client
  27. from app.datamgmt.client.client_db import create_contact
  28. from app.datamgmt.client.client_db import delete_client
  29. from app.datamgmt.client.client_db import delete_contact
  30. from app.datamgmt.client.client_db import get_client
  31. from app.datamgmt.client.client_db import get_client_api
  32. from app.datamgmt.client.client_db import get_client_cases
  33. from app.datamgmt.client.client_db import get_client_contacts
  34. from app.datamgmt.client.client_db import get_client_list
  35. from app.datamgmt.client.client_db import update_client
  36. from app.datamgmt.client.client_db import update_contact
  37. from app.datamgmt.exceptions.ElementExceptions import ElementInUseException
  38. from app.datamgmt.exceptions.ElementExceptions import ElementNotFoundException
  39. from app.datamgmt.manage.manage_users_db import add_user_to_customer
  40. from app.iris_engine.utils.tracker import track_activity
  41. from app.models.authorization import Permissions
  42. from app.schema.marshables import ContactSchema
  43. from app.schema.marshables import CustomerSchema
  44. from app.blueprints.access_controls import ac_api_requires_client_access
  45. from app.blueprints.responses import response_error
  46. from app.blueprints.responses import response_success
  47. manage_customers_rest_blueprint = Blueprint('manage_customers_rest', __name__)
  48. @manage_customers_rest_blueprint.route('/manage/customers/list', methods=['GET'])
  49. @ac_api_requires(Permissions.customers_read)
  50. def list_customers():
  51. user_is_server_administrator = ac_current_user_has_permission(Permissions.server_administrator)
  52. client_list = get_client_list(current_user_id=current_user.id,
  53. is_server_administrator=user_is_server_administrator)
  54. return response_success("", data=client_list)
  55. @manage_customers_rest_blueprint.route('/manage/customers/<int:client_id>', methods=['GET'])
  56. @ac_api_requires(Permissions.customers_read)
  57. @ac_api_requires_client_access()
  58. def view_customer(client_id):
  59. customer = get_client_api(client_id)
  60. customer['contacts'] = ContactSchema().dump(get_client_contacts(client_id), many=True)
  61. return response_success(data=customer)
  62. @manage_customers_rest_blueprint.route('/manage/customers/<int:client_id>/contacts/<int:contact_id>/update', methods=['POST'])
  63. @ac_api_requires(Permissions.customers_write)
  64. @ac_api_requires_client_access()
  65. def customer_update_contact(client_id, contact_id):
  66. if not request.is_json:
  67. return response_error("Invalid request")
  68. if not get_client(client_id):
  69. return response_error(f"Invalid Customer ID {client_id}")
  70. try:
  71. contact = update_contact(request.json, contact_id, client_id)
  72. except ValidationError as e:
  73. return response_error(msg='Error update contact', data=e.messages)
  74. except Exception as e:
  75. print(traceback.format_exc())
  76. return response_error(f'An error occurred during contact update. {e}')
  77. track_activity(f"Updated contact {contact.contact_name}", ctx_less=True)
  78. # Return the customer
  79. contact_schema = ContactSchema()
  80. return response_success("Added successfully", data=contact_schema.dump(contact))
  81. @manage_customers_rest_blueprint.route('/manage/customers/<int:client_id>/contacts/add', methods=['POST'])
  82. @ac_api_requires(Permissions.customers_write)
  83. @ac_api_requires_client_access()
  84. def customer_add_contact(client_id):
  85. if not request.is_json:
  86. return response_error("Invalid request")
  87. if not get_client(client_id):
  88. return response_error(f"Invalid Customer ID {client_id}")
  89. try:
  90. contact = create_contact(request.json, client_id)
  91. except ValidationError as e:
  92. return response_error(msg='Error adding contact', data=e.messages)
  93. except Exception as e:
  94. print(traceback.format_exc())
  95. return response_error(f'An error occurred during contact addition. {e}')
  96. track_activity(f"Added contact {contact.contact_name}", ctx_less=True)
  97. # Return the customer
  98. contact_schema = ContactSchema()
  99. return response_success("Added successfully", data=contact_schema.dump(contact))
  100. @manage_customers_rest_blueprint.route('/manage/customers/<int:client_id>/cases', methods=['GET'])
  101. @ac_api_requires(Permissions.customers_read)
  102. @ac_api_requires_client_access()
  103. def get_customer_case_stats(client_id):
  104. cases = get_client_cases(client_id)
  105. cases_list = []
  106. now = datetime.date.today()
  107. cases_stats = {
  108. 'cases_last_month': 0,
  109. 'cases_last_year': 0,
  110. 'open_cases': 0,
  111. 'last_year': now.year - 1,
  112. 'last_month': now.month - 1,
  113. 'cases_rolling_week': 0,
  114. 'cases_current_month': 0,
  115. 'cases_current_year': 0,
  116. 'ratio_year': 0,
  117. 'ratio_month': 0,
  118. 'average_case_duration': 0,
  119. 'cases_total': len(cases)
  120. }
  121. last_month_start = datetime.date.today() - datetime.timedelta(days=30)
  122. last_month_end = datetime.date(now.year, now.month, 1)
  123. last_year_start = datetime.date(now.year - 1, 1, 1)
  124. last_year_end = datetime.date(now.year - 1, 12, 31)
  125. this_year_start = datetime.date(now.year, 1, 1)
  126. this_month_start = datetime.date(now.year, now.month, 1)
  127. for case in cases:
  128. cases_list.append(case._asdict())
  129. if now - datetime.timedelta(days=7) <= case.open_date <= now:
  130. cases_stats['cases_rolling_week'] += 1
  131. if this_month_start <= case.open_date <= now:
  132. cases_stats['cases_current_month'] += 1
  133. if this_year_start <= case.open_date <= now:
  134. cases_stats['cases_current_year'] += 1
  135. if last_month_start < case.open_date < last_month_end:
  136. cases_stats['cases_last_month'] += 1
  137. if last_year_start <= case.open_date <= last_year_end:
  138. cases_stats['cases_last_year'] += 1
  139. if case.close_date is None:
  140. cases_stats['open_cases'] += 1
  141. if cases_stats['cases_last_year'] == 0:
  142. st = 1
  143. et = cases_stats['cases_current_year'] + 1
  144. else:
  145. st = cases_stats['cases_last_year']
  146. et = cases_stats['cases_current_year']
  147. cases_stats['ratio_year'] = ((et - st)/(st)) * 100
  148. if cases_stats['cases_last_month'] == 0:
  149. st = 1
  150. et = cases_stats['cases_current_month'] + 1
  151. else:
  152. st = cases_stats['cases_last_month']
  153. et = cases_stats['cases_current_month']
  154. cases_stats['ratio_month'] = ((et - st)/(st)) * 100
  155. if (case.close_date is not None) and (case.open_date is not None):
  156. cases_stats['average_case_duration'] += (case.close_date - case.open_date).days
  157. if cases_stats['cases_total'] > 0 and cases_stats['open_cases'] > 0 and cases_stats['average_case_duration'] > 0:
  158. cases_stats['average_case_duration'] = cases_stats['average_case_duration'] / (cases_stats['cases_total'] - cases_stats['open_cases'])
  159. cases = {
  160. 'cases': cases_list,
  161. 'stats': cases_stats
  162. }
  163. return response_success(data=cases)
  164. @manage_customers_rest_blueprint.route('/manage/customers/update/<int:client_id>', methods=['POST'])
  165. @ac_api_requires(Permissions.customers_write)
  166. @ac_api_requires_client_access()
  167. def view_customers(client_id):
  168. if not request.is_json:
  169. return response_error("Invalid request")
  170. try:
  171. client = update_client(client_id, request.json)
  172. except ElementNotFoundException:
  173. return response_error('Invalid Customer ID')
  174. except ValidationError as e:
  175. return response_error("", data=e.messages)
  176. except Exception as e:
  177. print(traceback.format_exc())
  178. return response_error(f'An error occurred during Customer update. {e}')
  179. client_schema = CustomerSchema()
  180. return response_success("Customer updated", client_schema.dump(client))
  181. @manage_customers_rest_blueprint.route('/manage/customers/add', methods=['POST'])
  182. @ac_api_requires(Permissions.customers_write)
  183. def add_customers():
  184. if not request.is_json:
  185. return response_error("Invalid request")
  186. try:
  187. client = create_client(request.json)
  188. except ValidationError as e:
  189. return response_error(msg='Error adding customer', data=e.messages)
  190. except Exception as e:
  191. print(traceback.format_exc())
  192. return response_error(f'An error occurred during customer addition. {e}')
  193. track_activity(f"Added customer {client.name}", ctx_less=True)
  194. # Associate the created customer with the current user
  195. add_user_to_customer(current_user.id, client.client_id)
  196. # Return the customer
  197. client_schema = CustomerSchema()
  198. return response_success("Added successfully", data=client_schema.dump(client))
  199. @manage_customers_rest_blueprint.route('/manage/customers/delete/<int:client_id>', methods=['POST'])
  200. @ac_api_requires(Permissions.customers_write)
  201. @ac_api_requires_client_access()
  202. def delete_customers(client_id):
  203. try:
  204. delete_client(client_id)
  205. except ElementNotFoundException:
  206. return response_error('Invalid Customer ID')
  207. except ElementInUseException:
  208. return response_error('Cannot delete a referenced customer')
  209. except Exception:
  210. return response_error('An error occurred during customer deletion')
  211. track_activity(f"Deleted Customer with ID {client_id}", ctx_less=True)
  212. return response_success("Deleted successfully")
  213. @manage_customers_rest_blueprint.route('/manage/customers/<int:client_id>/contacts/<int:contact_id>/delete', methods=['POST'])
  214. @ac_api_requires(Permissions.customers_write)
  215. @ac_api_requires_client_access()
  216. def delete_contact_route(client_id, contact_id):
  217. try:
  218. delete_contact(contact_id)
  219. except ElementNotFoundException:
  220. return response_error('Invalid contact ID')
  221. except ElementInUseException:
  222. return response_error('Cannot delete a referenced contact')
  223. except Exception:
  224. return response_error('An error occurred during contact deletion')
  225. track_activity(f"Deleted Customer with ID {contact_id}", ctx_less=True)
  226. return response_success("Deleted successfully")