django-nativemojo 0.1.15__tar.gz → 0.1.16__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/PKG-INFO +3 -1
  2. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/__init__.py +1 -1
  3. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/management/commands/serializer_admin.py +121 -1
  4. django_nativemojo-0.1.16/mojo/apps/account/migrations/0006_add_device_tracking_models.py +72 -0
  5. django_nativemojo-0.1.16/mojo/apps/account/migrations/0007_delete_userdevicelocation.py +16 -0
  6. django_nativemojo-0.1.16/mojo/apps/account/migrations/0008_userdevicelocation.py +33 -0
  7. django_nativemojo-0.1.16/mojo/apps/account/migrations/0009_geolocatedip_subnet.py +18 -0
  8. django_nativemojo-0.1.16/mojo/apps/account/migrations/0010_group_avatar.py +20 -0
  9. django_nativemojo-0.1.16/mojo/apps/account/migrations/0011_user_org_registereddevice_pushconfig_and_more.py +118 -0
  10. django_nativemojo-0.1.16/mojo/apps/account/migrations/0012_remove_pushconfig_apns_key_file_and_more.py +21 -0
  11. django_nativemojo-0.1.16/mojo/apps/account/migrations/0013_pushconfig_test_mode_alter_pushconfig_apns_enabled_and_more.py +28 -0
  12. django_nativemojo-0.1.16/mojo/apps/account/migrations/0014_notificationdelivery_data_payload_and_more.py +48 -0
  13. django_nativemojo-0.1.16/mojo/apps/account/models/__init__.py +5 -0
  14. django_nativemojo-0.1.16/mojo/apps/account/models/device.py +281 -0
  15. django_nativemojo-0.1.16/mojo/apps/account/models/group.py +402 -0
  16. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/models/member.py +14 -1
  17. django_nativemojo-0.1.16/mojo/apps/account/models/push/__init__.py +4 -0
  18. django_nativemojo-0.1.16/mojo/apps/account/models/push/config.py +112 -0
  19. django_nativemojo-0.1.16/mojo/apps/account/models/push/delivery.py +93 -0
  20. django_nativemojo-0.1.16/mojo/apps/account/models/push/device.py +66 -0
  21. django_nativemojo-0.1.16/mojo/apps/account/models/push/template.py +99 -0
  22. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/models/user.py +190 -17
  23. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/rest/__init__.py +2 -0
  24. django_nativemojo-0.1.16/mojo/apps/account/rest/device.py +39 -0
  25. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/rest/group.py +8 -0
  26. django_nativemojo-0.1.16/mojo/apps/account/rest/push.py +187 -0
  27. django_nativemojo-0.1.16/mojo/apps/account/rest/user.py +141 -0
  28. django_nativemojo-0.1.16/mojo/apps/account/services/__init__.py +1 -0
  29. django_nativemojo-0.1.16/mojo/apps/account/services/push.py +363 -0
  30. django_nativemojo-0.1.16/mojo/apps/aws/migrations/0001_initial.py +206 -0
  31. django_nativemojo-0.1.16/mojo/apps/aws/migrations/0002_emaildomain_can_recv_emaildomain_can_send_and_more.py +28 -0
  32. django_nativemojo-0.1.16/mojo/apps/aws/migrations/0003_mailbox_is_domain_default_mailbox_is_system_default_and_more.py +31 -0
  33. django_nativemojo-0.1.16/mojo/apps/aws/migrations/0004_s3bucket.py +39 -0
  34. django_nativemojo-0.1.16/mojo/apps/aws/migrations/0005_alter_emaildomain_region_delete_s3bucket.py +21 -0
  35. django_nativemojo-0.1.16/mojo/apps/aws/models/__init__.py +19 -0
  36. django_nativemojo-0.1.16/mojo/apps/aws/models/email_attachment.py +99 -0
  37. django_nativemojo-0.1.16/mojo/apps/aws/models/email_domain.py +218 -0
  38. django_nativemojo-0.1.16/mojo/apps/aws/models/email_template.py +132 -0
  39. django_nativemojo-0.1.16/mojo/apps/aws/models/incoming_email.py +197 -0
  40. django_nativemojo-0.1.16/mojo/apps/aws/models/mailbox.py +288 -0
  41. django_nativemojo-0.1.16/mojo/apps/aws/models/sent_message.py +175 -0
  42. django_nativemojo-0.1.16/mojo/apps/aws/rest/__init__.py +7 -0
  43. django_nativemojo-0.1.16/mojo/apps/aws/rest/email.py +33 -0
  44. django_nativemojo-0.1.16/mojo/apps/aws/rest/email_ops.py +183 -0
  45. django_nativemojo-0.1.16/mojo/apps/aws/rest/messages.py +32 -0
  46. django_nativemojo-0.1.16/mojo/apps/aws/rest/send.py +101 -0
  47. django_nativemojo-0.1.16/mojo/apps/aws/rest/sns.py +403 -0
  48. django_nativemojo-0.1.16/mojo/apps/aws/rest/templates.py +19 -0
  49. django_nativemojo-0.1.16/mojo/apps/aws/services/__init__.py +32 -0
  50. django_nativemojo-0.1.16/mojo/apps/aws/services/email.py +390 -0
  51. django_nativemojo-0.1.16/mojo/apps/aws/services/email_ops.py +548 -0
  52. django_nativemojo-0.1.16/mojo/apps/docit/__init__.py +6 -0
  53. django_nativemojo-0.1.16/mojo/apps/docit/markdown_plugins/syntax_highlight.py +25 -0
  54. django_nativemojo-0.1.16/mojo/apps/docit/markdown_plugins/toc.py +12 -0
  55. django_nativemojo-0.1.16/mojo/apps/docit/migrations/0001_initial.py +113 -0
  56. django_nativemojo-0.1.16/mojo/apps/docit/migrations/0002_alter_book_modified_by_alter_page_modified_by.py +26 -0
  57. django_nativemojo-0.1.16/mojo/apps/docit/migrations/0003_alter_book_group.py +20 -0
  58. django_nativemojo-0.1.16/mojo/apps/docit/models/__init__.py +17 -0
  59. django_nativemojo-0.1.16/mojo/apps/docit/models/asset.py +231 -0
  60. django_nativemojo-0.1.16/mojo/apps/docit/models/book.py +227 -0
  61. django_nativemojo-0.1.16/mojo/apps/docit/models/page.py +319 -0
  62. django_nativemojo-0.1.16/mojo/apps/docit/models/page_revision.py +203 -0
  63. django_nativemojo-0.1.16/mojo/apps/docit/rest/__init__.py +10 -0
  64. django_nativemojo-0.1.16/mojo/apps/docit/rest/asset.py +17 -0
  65. django_nativemojo-0.1.16/mojo/apps/docit/rest/book.py +22 -0
  66. django_nativemojo-0.1.16/mojo/apps/docit/rest/page.py +22 -0
  67. django_nativemojo-0.1.16/mojo/apps/docit/rest/page_revision.py +17 -0
  68. django_nativemojo-0.1.16/mojo/apps/docit/services/__init__.py +11 -0
  69. django_nativemojo-0.1.16/mojo/apps/docit/services/docit.py +315 -0
  70. django_nativemojo-0.1.16/mojo/apps/docit/services/markdown.py +44 -0
  71. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/backends/s3.py +209 -0
  72. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/models/file.py +45 -9
  73. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/models/manager.py +269 -3
  74. django_nativemojo-0.1.16/mojo/apps/incident/migrations/0007_event_uid.py +18 -0
  75. django_nativemojo-0.1.16/mojo/apps/incident/migrations/0008_ticket_ticketnote.py +55 -0
  76. django_nativemojo-0.1.16/mojo/apps/incident/migrations/0009_incident_status.py +18 -0
  77. django_nativemojo-0.1.16/mojo/apps/incident/migrations/0010_event_country_code.py +18 -0
  78. django_nativemojo-0.1.16/mojo/apps/incident/migrations/0011_incident_country_code.py +18 -0
  79. django_nativemojo-0.1.16/mojo/apps/incident/migrations/0012_alter_incident_status.py +18 -0
  80. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/models/__init__.py +1 -0
  81. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/models/event.py +35 -0
  82. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/models/incident.py +2 -0
  83. django_nativemojo-0.1.16/mojo/apps/incident/models/ticket.py +62 -0
  84. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/reporter.py +21 -3
  85. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/rest/__init__.py +1 -0
  86. django_nativemojo-0.1.16/mojo/apps/incident/rest/ticket.py +43 -0
  87. django_nativemojo-0.1.16/mojo/apps/jobs/__init__.py +489 -0
  88. django_nativemojo-0.1.16/mojo/apps/jobs/adapters.py +24 -0
  89. django_nativemojo-0.1.16/mojo/apps/jobs/cli.py +616 -0
  90. django_nativemojo-0.1.16/mojo/apps/jobs/daemon.py +370 -0
  91. django_nativemojo-0.1.16/mojo/apps/jobs/examples/sample_jobs.py +376 -0
  92. django_nativemojo-0.1.16/mojo/apps/jobs/examples/webhook_examples.py +203 -0
  93. django_nativemojo-0.1.16/mojo/apps/jobs/handlers/__init__.py +5 -0
  94. django_nativemojo-0.1.16/mojo/apps/jobs/handlers/webhook.py +317 -0
  95. django_nativemojo-0.1.16/mojo/apps/jobs/job_engine.py +734 -0
  96. django_nativemojo-0.1.16/mojo/apps/jobs/keys.py +203 -0
  97. django_nativemojo-0.1.16/mojo/apps/jobs/local_queue.py +363 -0
  98. django_nativemojo-0.1.16/mojo/apps/jobs/management/__init__.py +3 -0
  99. django_nativemojo-0.1.16/mojo/apps/jobs/management/commands/__init__.py +3 -0
  100. django_nativemojo-0.1.16/mojo/apps/jobs/manager.py +1327 -0
  101. django_nativemojo-0.1.16/mojo/apps/jobs/migrations/0001_initial.py +97 -0
  102. django_nativemojo-0.1.16/mojo/apps/jobs/migrations/0002_alter_job_max_retries_joblog.py +39 -0
  103. django_nativemojo-0.1.16/mojo/apps/jobs/models/__init__.py +6 -0
  104. django_nativemojo-0.1.16/mojo/apps/jobs/models/job.py +441 -0
  105. django_nativemojo-0.1.16/mojo/apps/jobs/rest/__init__.py +2 -0
  106. django_nativemojo-0.1.16/mojo/apps/jobs/rest/control.py +466 -0
  107. django_nativemojo-0.1.16/mojo/apps/jobs/rest/jobs.py +421 -0
  108. django_nativemojo-0.1.16/mojo/apps/jobs/scheduler.py +571 -0
  109. django_nativemojo-0.1.16/mojo/apps/jobs/services/__init__.py +6 -0
  110. django_nativemojo-0.1.16/mojo/apps/jobs/services/job_actions.py +465 -0
  111. django_nativemojo-0.1.16/mojo/apps/jobs/settings.py +209 -0
  112. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/models/log.py +3 -0
  113. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/metrics/__init__.py +8 -1
  114. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/metrics/redis_metrics.py +198 -0
  115. django_nativemojo-0.1.16/mojo/apps/metrics/rest/__init__.py +4 -0
  116. django_nativemojo-0.1.16/mojo/apps/metrics/rest/categories.py +266 -0
  117. django_nativemojo-0.1.16/mojo/apps/metrics/rest/helpers.py +48 -0
  118. django_nativemojo-0.1.16/mojo/apps/metrics/rest/permissions.py +99 -0
  119. django_nativemojo-0.1.16/mojo/apps/metrics/rest/values.py +277 -0
  120. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/metrics/utils.py +17 -0
  121. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/decorators/http.py +40 -1
  122. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/__init__.py +11 -7
  123. django_nativemojo-0.1.16/mojo/helpers/aws/inbound_email.py +309 -0
  124. django_nativemojo-0.1.16/mojo/helpers/aws/kms.py +413 -0
  125. django_nativemojo-0.1.16/mojo/helpers/aws/ses_domain.py +959 -0
  126. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/__init__.py +1 -1
  127. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/utils.py +15 -0
  128. django_nativemojo-0.1.16/mojo/helpers/location/__init__.py +2 -0
  129. django_nativemojo-0.1.16/mojo/helpers/location/countries.py +262 -0
  130. django_nativemojo-0.1.16/mojo/helpers/location/geolocation.py +196 -0
  131. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/logit.py +37 -0
  132. django_nativemojo-0.1.16/mojo/helpers/redis/__init__.py +2 -0
  133. django_nativemojo-0.1.16/mojo/helpers/redis/adapter.py +606 -0
  134. django_nativemojo-0.1.16/mojo/helpers/redis/client.py +48 -0
  135. django_nativemojo-0.1.16/mojo/helpers/redis/pool.py +225 -0
  136. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/request.py +8 -0
  137. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/response.py +8 -0
  138. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/middleware/auth.py +1 -1
  139. django_nativemojo-0.1.16/mojo/middleware/cors.py +40 -0
  140. django_nativemojo-0.1.16/mojo/middleware/logging.py +174 -0
  141. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/middleware/mojo.py +5 -0
  142. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/models/rest.py +271 -57
  143. django_nativemojo-0.1.16/mojo/models/secrets.py +154 -0
  144. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/serializers/__init__.py +16 -10
  145. django_nativemojo-0.1.16/mojo/serializers/core/__init__.py +90 -0
  146. django_nativemojo-0.1.16/mojo/serializers/core/cache/__init__.py +121 -0
  147. django_nativemojo-0.1.16/mojo/serializers/core/cache/backends.py +518 -0
  148. django_nativemojo-0.1.16/mojo/serializers/core/cache/base.py +102 -0
  149. django_nativemojo-0.1.16/mojo/serializers/core/cache/disabled.py +181 -0
  150. django_nativemojo-0.1.16/mojo/serializers/core/cache/memory.py +287 -0
  151. django_nativemojo-0.1.16/mojo/serializers/core/cache/redis.py +533 -0
  152. django_nativemojo-0.1.16/mojo/serializers/core/cache/utils.py +454 -0
  153. {django_nativemojo-0.1.15/mojo/serializers → django_nativemojo-0.1.16/mojo/serializers/core}/manager.py +53 -4
  154. django_nativemojo-0.1.16/mojo/serializers/core/serializer.py +475 -0
  155. {django_nativemojo-0.1.15/mojo/serializers/advanced → django_nativemojo-0.1.16/mojo/serializers}/formats/csv.py +116 -139
  156. django_nativemojo-0.1.16/mojo/serializers/suggested_improvements.md +388 -0
  157. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/pyproject.toml +3 -1
  158. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/testit/client.py +1 -1
  159. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/testit/helpers.py +14 -0
  160. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/testit/runner.py +23 -6
  161. django_nativemojo-0.1.15/mojo/apps/account/models/__init__.py +0 -3
  162. django_nativemojo-0.1.15/mojo/apps/account/models/group.py +0 -116
  163. django_nativemojo-0.1.15/mojo/apps/account/rest/user.py +0 -51
  164. django_nativemojo-0.1.15/mojo/apps/aws/rest/__init__.py +0 -1
  165. django_nativemojo-0.1.15/mojo/apps/metrics/rest/__init__.py +0 -1
  166. django_nativemojo-0.1.15/mojo/apps/notify/README.md +0 -91
  167. django_nativemojo-0.1.15/mojo/apps/notify/README_NOTIFICATIONS.md +0 -566
  168. django_nativemojo-0.1.15/mojo/apps/notify/admin.py +0 -52
  169. django_nativemojo-0.1.15/mojo/apps/notify/handlers/example_handlers.py +0 -516
  170. django_nativemojo-0.1.15/mojo/apps/notify/handlers/ses/__init__.py +0 -25
  171. django_nativemojo-0.1.15/mojo/apps/notify/handlers/ses/bounce.py +0 -0
  172. django_nativemojo-0.1.15/mojo/apps/notify/handlers/ses/complaint.py +0 -25
  173. django_nativemojo-0.1.15/mojo/apps/notify/handlers/ses/message.py +0 -86
  174. django_nativemojo-0.1.15/mojo/apps/notify/management/commands/__init__.py +0 -1
  175. django_nativemojo-0.1.15/mojo/apps/notify/management/commands/process_notifications.py +0 -370
  176. django_nativemojo-0.1.15/mojo/apps/notify/mod +0 -0
  177. django_nativemojo-0.1.15/mojo/apps/notify/models/__init__.py +0 -12
  178. django_nativemojo-0.1.15/mojo/apps/notify/models/account.py +0 -128
  179. django_nativemojo-0.1.15/mojo/apps/notify/models/attachment.py +0 -24
  180. django_nativemojo-0.1.15/mojo/apps/notify/models/bounce.py +0 -68
  181. django_nativemojo-0.1.15/mojo/apps/notify/models/complaint.py +0 -40
  182. django_nativemojo-0.1.15/mojo/apps/notify/models/inbox.py +0 -113
  183. django_nativemojo-0.1.15/mojo/apps/notify/models/inbox_message.py +0 -173
  184. django_nativemojo-0.1.15/mojo/apps/notify/models/outbox.py +0 -129
  185. django_nativemojo-0.1.15/mojo/apps/notify/models/outbox_message.py +0 -288
  186. django_nativemojo-0.1.15/mojo/apps/notify/models/template.py +0 -30
  187. django_nativemojo-0.1.15/mojo/apps/notify/providers/aws.py +0 -73
  188. django_nativemojo-0.1.15/mojo/apps/notify/rest/ses.py +0 -0
  189. django_nativemojo-0.1.15/mojo/apps/notify/utils/__init__.py +0 -2
  190. django_nativemojo-0.1.15/mojo/apps/notify/utils/notifications.py +0 -404
  191. django_nativemojo-0.1.15/mojo/apps/notify/utils/parsing.py +0 -202
  192. django_nativemojo-0.1.15/mojo/apps/notify/utils/render.py +0 -144
  193. django_nativemojo-0.1.15/mojo/apps/tasks/README.md +0 -118
  194. django_nativemojo-0.1.15/mojo/apps/tasks/__init__.py +0 -44
  195. django_nativemojo-0.1.15/mojo/apps/tasks/manager.py +0 -644
  196. django_nativemojo-0.1.15/mojo/apps/tasks/rest/__init__.py +0 -2
  197. django_nativemojo-0.1.15/mojo/apps/tasks/rest/hooks.py +0 -0
  198. django_nativemojo-0.1.15/mojo/apps/tasks/rest/tasks.py +0 -76
  199. django_nativemojo-0.1.15/mojo/apps/tasks/runner.py +0 -439
  200. django_nativemojo-0.1.15/mojo/apps/tasks/task.py +0 -99
  201. django_nativemojo-0.1.15/mojo/apps/tasks/tq_handlers.py +0 -132
  202. django_nativemojo-0.1.15/mojo/helpers/redis.py +0 -10
  203. django_nativemojo-0.1.15/mojo/middleware/logging.py +0 -55
  204. django_nativemojo-0.1.15/mojo/models/meta.py +0 -262
  205. django_nativemojo-0.1.15/mojo/models/secrets.py +0 -68
  206. django_nativemojo-0.1.15/mojo/serializers/advanced/README.md +0 -363
  207. django_nativemojo-0.1.15/mojo/serializers/advanced/__init__.py +0 -247
  208. django_nativemojo-0.1.15/mojo/serializers/advanced/formats/__init__.py +0 -28
  209. django_nativemojo-0.1.15/mojo/serializers/advanced/formats/excel.py +0 -516
  210. django_nativemojo-0.1.15/mojo/serializers/advanced/formats/json.py +0 -239
  211. django_nativemojo-0.1.15/mojo/serializers/advanced/formats/response.py +0 -485
  212. django_nativemojo-0.1.15/mojo/serializers/advanced/serializer.py +0 -568
  213. django_nativemojo-0.1.15/mojo/serializers/optimized.py +0 -618
  214. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/LICENSE +0 -0
  215. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/NOTICE +0 -0
  216. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/README.md +0 -0
  217. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/__init__.py +0 -0
  218. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/admin.py +0 -0
  219. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/apps.py +0 -0
  220. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/management/__init__.py +0 -0
  221. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/management/commands/__init__.py +0 -0
  222. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/migrations/0001_initial.py +0 -0
  223. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/migrations/0002_user_is_email_verified_user_is_phone_verified.py +0 -0
  224. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/migrations/0003_group_mojo_secrets_user_mojo_secrets.py +0 -0
  225. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/migrations/0004_user_avatar.py +0 -0
  226. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/migrations/0005_group_last_activity.py +0 -0
  227. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/migrations/__init__.py +0 -0
  228. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/models/pkey.py +0 -0
  229. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/utils/__init__.py +0 -0
  230. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/utils/jwtoken.py +0 -0
  231. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/account/utils/passkeys.py +0 -0
  232. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/aws/__init__.py +0 -0
  233. {django_nativemojo-0.1.15/mojo/apps/aws/models → django_nativemojo-0.1.16/mojo/apps/aws/migrations}/__init__.py +0 -0
  234. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/aws/rest/s3.py +0 -0
  235. {django_nativemojo-0.1.15/mojo/apps/fileman → django_nativemojo-0.1.16/mojo/apps/docit/markdown_plugins}/__init__.py +0 -0
  236. {django_nativemojo-0.1.15/mojo/apps/fileman → django_nativemojo-0.1.16/mojo/apps/docit}/migrations/__init__.py +0 -0
  237. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/README.md +0 -0
  238. {django_nativemojo-0.1.15/mojo/apps/incident/migrations → django_nativemojo-0.1.16/mojo/apps/fileman}/__init__.py +0 -0
  239. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/apps.py +0 -0
  240. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/backends/__init__.py +0 -0
  241. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/backends/base.py +0 -0
  242. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/backends/filesystem.py +0 -0
  243. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/examples/configurations.py +0 -0
  244. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/examples/usage_example.py +0 -0
  245. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/management/__init__.py +0 -0
  246. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/management/commands/__init__.py +0 -0
  247. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/management/commands/cleanup_expired_uploads.py +0 -0
  248. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0001_initial.py +0 -0
  249. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0002_filemanager_parent_alter_filemanager_max_file_size.py +0 -0
  250. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0003_remove_file_fileman_fil_upload__c4bc35_idx_and_more.py +0 -0
  251. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0004_remove_file_original_filename_and_more.py +0 -0
  252. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0005_alter_file_upload_token.py +0 -0
  253. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0006_file_download_url_filemanager_forever_urls.py +0 -0
  254. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0007_remove_filemanager_forever_urls_and_more.py +0 -0
  255. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0008_file_category.py +0 -0
  256. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0009_rename_file_path_file_storage_file_path.py +0 -0
  257. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0010_filerendition.py +0 -0
  258. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/migrations/0011_alter_filerendition_original_file.py +0 -0
  259. {django_nativemojo-0.1.15/mojo/apps/incident/parsers → django_nativemojo-0.1.16/mojo/apps/fileman/migrations}/__init__.py +0 -0
  260. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/models/__init__.py +0 -0
  261. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/models/rendition.py +0 -0
  262. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/__init__.py +0 -0
  263. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/audio.py +0 -0
  264. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/base.py +0 -0
  265. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/document.py +0 -0
  266. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/image.py +0 -0
  267. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/utils.py +0 -0
  268. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/renderer/video.py +0 -0
  269. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/rest/__init__.py +0 -0
  270. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/rest/fileman.py +0 -0
  271. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/rest/upload.py +0 -0
  272. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/signals.py +0 -0
  273. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/tasks.py +0 -0
  274. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/utils/__init__.py +0 -0
  275. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/fileman/utils/upload.py +0 -0
  276. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/__init__.py +0 -0
  277. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/handlers/__init__.py +0 -0
  278. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/handlers/event_handlers.py +0 -0
  279. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/migrations/0001_initial.py +0 -0
  280. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/migrations/0002_rename_bundle_ruleset_bundle_minutes_event_hostname_and_more.py +0 -0
  281. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/migrations/0003_alter_event_model_id.py +0 -0
  282. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/migrations/0004_alter_incident_model_id.py +0 -0
  283. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/migrations/0005_incidenthistory.py +0 -0
  284. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/migrations/0006_alter_incident_state.py +0 -0
  285. {django_nativemojo-0.1.15/mojo/apps/logit → django_nativemojo-0.1.16/mojo/apps/incident/migrations}/__init__.py +0 -0
  286. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/models/history.py +0 -0
  287. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/models/rule.py +0 -0
  288. {django_nativemojo-0.1.15/mojo/apps/logit/migrations → django_nativemojo-0.1.16/mojo/apps/incident/parsers}/__init__.py +0 -0
  289. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/parsers/ossec/__init__.py +0 -0
  290. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/parsers/ossec/core.py +0 -0
  291. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/parsers/ossec/parsed.py +0 -0
  292. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/parsers/ossec/rules.py +0 -0
  293. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/parsers/ossec/utils.py +0 -0
  294. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/rest/event.py +0 -0
  295. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/incident/rest/ossec.py +0 -0
  296. {django_nativemojo-0.1.15/mojo/apps/notify → django_nativemojo-0.1.16/mojo/apps/jobs/examples}/__init__.py +0 -0
  297. {django_nativemojo-0.1.15/mojo/apps/notify/handlers → django_nativemojo-0.1.16/mojo/apps/jobs/migrations}/__init__.py +0 -0
  298. {django_nativemojo-0.1.15/mojo/apps/notify/management → django_nativemojo-0.1.16/mojo/apps/logit}/__init__.py +0 -0
  299. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/admin.py +0 -0
  300. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/migrations/0001_initial.py +0 -0
  301. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/migrations/0002_log_duid_log_payload_log_username.py +0 -0
  302. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/migrations/0003_log_level.py +0 -0
  303. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/migrations/0004_alter_log_level.py +0 -0
  304. {django_nativemojo-0.1.15/mojo/apps/notify/providers → django_nativemojo-0.1.16/mojo/apps/logit/migrations}/__init__.py +0 -0
  305. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/models/__init__.py +0 -0
  306. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/logit/rest.py +0 -0
  307. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/metrics/README.md +0 -0
  308. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/apps/metrics/rest/base.py +0 -0
  309. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/decorators/__init__.py +0 -0
  310. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/decorators/auth.py +0 -0
  311. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/decorators/cron.py +0 -0
  312. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/decorators/validate.py +0 -0
  313. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/errors.py +0 -0
  314. {django_nativemojo-0.1.15/mojo/apps/notify/rest → django_nativemojo-0.1.16/mojo/helpers}/__init__.py +0 -0
  315. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/client.py +0 -0
  316. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/ec2.py +0 -0
  317. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/iam.py +0 -0
  318. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/s3.py +0 -0
  319. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/ses.py +0 -0
  320. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/aws/sns.py +0 -0
  321. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/cron.py +0 -0
  322. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/aes.py +0 -0
  323. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/hash.py +0 -0
  324. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/privpub/__init__.py +0 -0
  325. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/privpub/hybrid.py +0 -0
  326. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/privpub/rsa.py +0 -0
  327. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/sign.py +0 -0
  328. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/crypto/too.l.py +0 -0
  329. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/daemon.py +0 -0
  330. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/dates.py +0 -0
  331. {django_nativemojo-0.1.15/mojo/helpers → django_nativemojo-0.1.16/mojo/helpers/dns}/__init__.py +0 -0
  332. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/dns/godaddy.py +0 -0
  333. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/filetypes.py +0 -0
  334. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/modules.py +0 -0
  335. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/paths.py +0 -0
  336. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/request_parser.py +0 -0
  337. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/settings/__init__.py +0 -0
  338. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/settings/helper.py +0 -0
  339. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/settings/parser.py +0 -0
  340. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/sysinfo.py +0 -0
  341. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/helpers/ua.py +0 -0
  342. {django_nativemojo-0.1.15/mojo/helpers/dns → django_nativemojo-0.1.16/mojo/middleware}/__init__.py +0 -0
  343. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/migrations/0001_initial.py +0 -0
  344. {django_nativemojo-0.1.15/mojo/middleware → django_nativemojo-0.1.16/mojo/migrations}/__init__.py +0 -0
  345. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/models/__init__.py +0 -0
  346. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/rest/__init__.py +0 -0
  347. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/rest/info.py +0 -0
  348. {django_nativemojo-0.1.15/mojo/serializers → django_nativemojo-0.1.16/mojo/rest}/openapi.py +0 -0
  349. /django_nativemojo-0.1.15/mojo/serializers/settings_example.py → /django_nativemojo-0.1.16/mojo/serializers/examples/settings.py +0 -0
  350. {django_nativemojo-0.1.15/mojo/migrations → django_nativemojo-0.1.16/mojo/serializers/formats}/__init__.py +0 -0
  351. {django_nativemojo-0.1.15/mojo/serializers/advanced → django_nativemojo-0.1.16/mojo/serializers}/formats/localizers.py +0 -0
  352. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/serializers/simple.py +0 -0
  353. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/mojo/urls.py +0 -0
  354. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/testit/__init__.py +0 -0
  355. {django_nativemojo-0.1.15 → django_nativemojo-0.1.16}/testit/faker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-nativemojo
3
- Version: 0.1.15
3
+ Version: 0.1.16
4
4
  Summary: A REST framework for DJANGO with some extra apps that make it easy to provide a secure robust graph like RESIT API.
5
5
  License: MIT
6
6
  Author: MOJO Dev Team
@@ -17,7 +17,9 @@ Requires-Dist: django (>=4.2.18,<6.0.0)
17
17
  Requires-Dist: django-cors-headers (>=4.7.0,<5.0.0)
18
18
  Requires-Dist: faker (>=35.2.0,<36.0.0)
19
19
  Requires-Dist: gevent (>=25.5.1,<26.0.0)
20
+ Requires-Dist: mistune (>=3.0.2,<4.0.0)
20
21
  Requires-Dist: pycryptodome (>=3.21.0,<4.0.0)
22
+ Requires-Dist: pygments (>=2.18.0,<3.0.0)
21
23
  Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
22
24
  Requires-Dist: pyobjict (>=2.0.2,<4.0.0)
23
25
  Requires-Dist: pytz (>=2025.1,<2026.0)
@@ -1,3 +1,3 @@
1
- __version__ = "0.1.15"
1
+ __version__ = "0.1.16"
2
2
 
3
3
  from mojo.helpers.response import JsonResponse
@@ -37,9 +37,24 @@ from mojo.serializers import (
37
37
  clear_serializer_caches,
38
38
  benchmark_serializers,
39
39
  list_serializers,
40
- set_default_serializer
40
+ set_default_serializer,
41
+ HAS_UJSON,
42
+ UJSON_VERSION
41
43
  )
42
44
 
45
+ # Import cache system for enhanced functionality
46
+ try:
47
+ from mojo.serializers.core.cache import (
48
+ get_cache_backend,
49
+ get_cache_stats,
50
+ get_available_backends,
51
+ test_backend_connectivity,
52
+ get_cache_health
53
+ )
54
+ HAS_CACHE_SYSTEM = True
55
+ except ImportError:
56
+ HAS_CACHE_SYSTEM = False
57
+
43
58
 
44
59
  class Command(BaseCommand):
45
60
  help = 'Manage MOJO serializers: benchmark, configure, and monitor performance'
@@ -146,6 +161,14 @@ class Command(BaseCommand):
146
161
  help='Graph configuration to test'
147
162
  )
148
163
 
164
+ # Cache information
165
+ cache_parser = subparsers.add_parser('cache-info', help='Show detailed cache information')
166
+ cache_parser.add_argument(
167
+ '--test-connectivity',
168
+ action='store_true',
169
+ help='Test cache backend connectivity'
170
+ )
171
+
149
172
  def handle(self, *args, **options):
150
173
  """Handle command execution."""
151
174
  action = options.get('action')
@@ -163,6 +186,7 @@ class Command(BaseCommand):
163
186
  'clear-cache': self.handle_clear_cache,
164
187
  'health': self.handle_health,
165
188
  'test': self.handle_test,
189
+ 'cache-info': self.handle_cache_info,
166
190
  }
167
191
 
168
192
  handler = handler_map.get(action)
@@ -196,6 +220,24 @@ class Command(BaseCommand):
196
220
  self.stdout.write(f" Class: {info['class_name']}")
197
221
  self.stdout.write(f" Description: {info['description']}")
198
222
 
223
+ # Show ujson information
224
+ self.stdout.write(f"\nPerformance Information:")
225
+ if HAS_UJSON:
226
+ self.stdout.write(f" ✓ ujson {UJSON_VERSION} available - optimal JSON performance")
227
+ else:
228
+ self.stdout.write(f" ⚠ ujson not available - using standard json (slower)")
229
+ self.stdout.write(f" Install with: pip install ujson")
230
+
231
+ # Show cache backend information
232
+ if HAS_CACHE_SYSTEM:
233
+ try:
234
+ cache_backend = get_cache_backend()
235
+ cache_stats = cache_backend.stats()
236
+ backend_type = cache_stats.get('backend', 'unknown')
237
+ self.stdout.write(f" ✓ Cache backend: {backend_type}")
238
+ except Exception as e:
239
+ self.stdout.write(f" ⚠ Cache backend error: {e}")
240
+
199
241
  def handle_benchmark(self, options):
200
242
  """Benchmark serializer performance."""
201
243
  model_class = self.get_model_class(options['model'])
@@ -279,6 +321,68 @@ class Command(BaseCommand):
279
321
  self.style.SUCCESS("Performance statistics cleared")
280
322
  )
281
323
 
324
+ def handle_cache_info(self, options):
325
+ """Show detailed cache information."""
326
+ if not HAS_CACHE_SYSTEM:
327
+ self.stdout.write(
328
+ self.style.ERROR("Cache system not available")
329
+ )
330
+ return
331
+
332
+ self.stdout.write(self.style.SUCCESS("Cache System Information:"))
333
+
334
+ try:
335
+ # Show available backends
336
+ backends = get_available_backends()
337
+ self.stdout.write(f"\nAvailable Backends:")
338
+ for name, info in backends.items():
339
+ status = "✓" if info['available'] else "✗"
340
+ self.stdout.write(f" {status} {name}: {info['description']}")
341
+ if info.get('ujson_available'):
342
+ self.stdout.write(f" ujson: {info.get('ujson_version', 'available')}")
343
+ if info.get('error'):
344
+ self.stdout.write(f" Error: {info['error']}")
345
+
346
+ # Show current backend health
347
+ health = get_cache_health()
348
+ self.stdout.write(f"\nCache Health: {health['status'].upper()}")
349
+ if health.get('issues'):
350
+ for issue in health['issues']:
351
+ self.stdout.write(f" ⚠ {issue}")
352
+
353
+ # Show recommendations
354
+ if health.get('recommendations'):
355
+ self.stdout.write(f"\nRecommendations:")
356
+ for rec in health['recommendations']:
357
+ self.stdout.write(f" • {rec}")
358
+
359
+ # Test connectivity if requested
360
+ if options.get('test_connectivity'):
361
+ self.stdout.write(f"\nTesting Cache Connectivity:")
362
+ backend_type = health.get('backend_type', 'unknown')
363
+ test_result = test_backend_connectivity(backend_type)
364
+
365
+ if test_result['connectivity']:
366
+ self.stdout.write(f" ✓ {backend_type} backend connectivity OK")
367
+ if test_result['functionality']:
368
+ perf = test_result.get('performance', {})
369
+ self.stdout.write(f" ✓ Functionality test passed")
370
+ if perf:
371
+ self.stdout.write(f" Set time: {perf.get('set_time_ms', 0)}ms")
372
+ self.stdout.write(f" Get time: {perf.get('get_time_ms', 0)}ms")
373
+ else:
374
+ self.stdout.write(f" ✗ Functionality test failed")
375
+ else:
376
+ self.stdout.write(f" ✗ {backend_type} backend connectivity failed")
377
+
378
+ for error in test_result.get('errors', []):
379
+ self.stdout.write(f" Error: {error}")
380
+
381
+ except Exception as e:
382
+ self.stdout.write(
383
+ self.style.ERROR(f"Error getting cache information: {e}")
384
+ )
385
+
282
386
  def handle_clear_cache(self, options):
283
387
  """Clear serializer caches."""
284
388
  serializer_name = options.get('serializer')
@@ -434,6 +538,21 @@ class Command(BaseCommand):
434
538
  f"{data['total_objects']} objects serialized"
435
539
  )
436
540
 
541
+ # Cache statistics
542
+ if HAS_CACHE_SYSTEM:
543
+ try:
544
+ cache_stats = get_cache_stats()
545
+ self.stdout.write(f"\nCache Statistics:")
546
+ self.stdout.write(f" Backend: {cache_stats.get('backend', 'unknown')}")
547
+ self.stdout.write(f" Hit Rate: {cache_stats.get('hit_rate', 0):.1%}")
548
+ self.stdout.write(f" Total Requests: {cache_stats.get('total_requests', 0)}")
549
+ self.stdout.write(f" Cache Size: {cache_stats.get('current_size', 0)}")
550
+ if cache_stats.get('max_size'):
551
+ utilization = cache_stats.get('current_size', 0) / cache_stats.get('max_size', 1)
552
+ self.stdout.write(f" Utilization: {utilization:.1%}")
553
+ except Exception as e:
554
+ self.stdout.write(f"\nCache Stats Error: {e}")
555
+
437
556
  # Individual serializer stats
438
557
  for key, value in stats.items():
439
558
  if key.endswith('_stats') and isinstance(value, dict):
@@ -528,4 +647,5 @@ class Command(BaseCommand):
528
647
  self.stdout.write(" clear-cache - Clear serializer caches")
529
648
  self.stdout.write(" health - Run health checks")
530
649
  self.stdout.write(" test - Test serializer functionality")
650
+ self.stdout.write(" cache-info - Show detailed cache information")
531
651
  self.stdout.write("\nUse 'python manage.py serializer_admin <action> --help' for more details")
@@ -0,0 +1,72 @@
1
+ # Generated by Django 4.2.21 on 2025-08-28
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('account', '0005_group_last_activity'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='GeoLocatedIP',
17
+ fields=[
18
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('created', models.DateTimeField(auto_now_add=True)),
20
+ ('modified', models.DateTimeField(auto_now=True, db_index=True)),
21
+ ('ip_address', models.GenericIPAddressField(db_index=True, unique=True)),
22
+ ('country_code', models.CharField(blank=True, db_index=True, max_length=3, null=True)),
23
+ ('country_name', models.CharField(blank=True, max_length=100, null=True)),
24
+ ('region', models.CharField(blank=True, db_index=True, max_length=100, null=True)),
25
+ ('city', models.CharField(blank=True, max_length=100, null=True)),
26
+ ('postal_code', models.CharField(blank=True, max_length=20, null=True)),
27
+ ('latitude', models.FloatField(blank=True, null=True)),
28
+ ('longitude', models.FloatField(blank=True, null=True)),
29
+ ('timezone', models.CharField(blank=True, max_length=50, null=True)),
30
+ ('provider', models.CharField(blank=True, max_length=50, null=True)),
31
+ ('data', models.JSONField(blank=True, default=dict)),
32
+ ('expires_at', models.DateTimeField(blank=True, default=None, null=True)),
33
+ ],
34
+ options={
35
+ 'verbose_name': 'Geolocated IP',
36
+ 'verbose_name_plural': 'Geolocated IPs',
37
+ },
38
+ ),
39
+ migrations.CreateModel(
40
+ name='UserDevice',
41
+ fields=[
42
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
43
+ ('duid', models.CharField(db_index=True, max_length=255)),
44
+ ('device_info', models.JSONField(blank=True, default=dict)),
45
+ ('user_agent_hash', models.CharField(blank=True, db_index=True, max_length=64, null=True)),
46
+ ('last_ip', models.GenericIPAddressField(blank=True, null=True)),
47
+ ('first_seen', models.DateTimeField(auto_now_add=True)),
48
+ ('last_seen', models.DateTimeField(auto_now=True)),
49
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='devices', to=settings.AUTH_USER_MODEL)),
50
+ ],
51
+ options={
52
+ 'ordering': ['-last_seen'],
53
+ 'unique_together': {('user', 'duid')},
54
+ },
55
+ ),
56
+ migrations.CreateModel(
57
+ name='UserDeviceLocation',
58
+ fields=[
59
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
60
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_locations_direct', to=settings.AUTH_USER_MODEL)),
61
+ ('ip_address', models.GenericIPAddressField(db_index=True)),
62
+ ('first_seen', models.DateTimeField(auto_now_add=True)),
63
+ ('last_seen', models.DateTimeField(auto_now=True)),
64
+ ('geolocation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='device_locations', to='account.geolocatedip')),
65
+ ('user_device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='account.userdevice')),
66
+ ],
67
+ options={
68
+ 'ordering': ['-last_seen'],
69
+ 'unique_together': {('user', 'user_device', 'ip_address')},
70
+ },
71
+ ),
72
+ ]
@@ -0,0 +1,16 @@
1
+ # Generated by Django 4.2.21 on 2025-08-28 16:24
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('account', '0006_add_device_tracking_models'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.DeleteModel(
14
+ name='UserDeviceLocation',
15
+ ),
16
+ ]
@@ -0,0 +1,33 @@
1
+ # Generated by Django 4.2.21 on 2025-08-28 22:30
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import mojo.models.rest
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ dependencies = [
12
+ ('account', '0007_delete_userdevicelocation'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='UserDeviceLocation',
18
+ fields=[
19
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+ ('ip_address', models.GenericIPAddressField(db_index=True)),
21
+ ('first_seen', models.DateTimeField(auto_now_add=True)),
22
+ ('last_seen', models.DateTimeField(auto_now=True)),
23
+ ('geolocation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='device_locations', to='account.geolocatedip')),
24
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_locations_direct', to=settings.AUTH_USER_MODEL)),
25
+ ('user_device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='account.userdevice')),
26
+ ],
27
+ options={
28
+ 'ordering': ['-last_seen'],
29
+ 'unique_together': {('user', 'user_device', 'ip_address')},
30
+ },
31
+ bases=(models.Model, mojo.models.rest.MojoModel),
32
+ ),
33
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.21 on 2025-08-29 00:23
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('account', '0008_userdevicelocation'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='geolocatedip',
15
+ name='subnet',
16
+ field=models.CharField(db_index=True, default=None, max_length=16, null=True),
17
+ ),
18
+ ]
@@ -0,0 +1,20 @@
1
+ # Generated by Django 4.2.21 on 2025-08-29 03:04
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('fileman', '0011_alter_filerendition_original_file'),
11
+ ('account', '0009_geolocatedip_subnet'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AddField(
16
+ model_name='group',
17
+ name='avatar',
18
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='fileman.file'),
19
+ ),
20
+ ]
@@ -0,0 +1,118 @@
1
+ # Generated by Django 4.2.21 on 2025-08-30 02:36
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import mojo.models.rest
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ dependencies = [
12
+ ('account', '0010_group_avatar'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.AddField(
17
+ model_name='user',
18
+ name='org',
19
+ field=models.ForeignKey(blank=True, help_text='Default organization for this user', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='org_users', to='account.group'),
20
+ ),
21
+ migrations.CreateModel(
22
+ name='RegisteredDevice',
23
+ fields=[
24
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
25
+ ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
26
+ ('modified', models.DateTimeField(auto_now=True, db_index=True)),
27
+ ('device_token', models.TextField(db_index=True, help_text='Push token from platform')),
28
+ ('device_id', models.CharField(db_index=True, help_text='App-provided device ID', max_length=255)),
29
+ ('platform', models.CharField(choices=[('ios', 'iOS'), ('android', 'Android'), ('web', 'Web')], db_index=True, max_length=20)),
30
+ ('app_version', models.CharField(blank=True, max_length=50)),
31
+ ('os_version', models.CharField(blank=True, max_length=50)),
32
+ ('device_name', models.CharField(blank=True, max_length=100)),
33
+ ('push_enabled', models.BooleanField(db_index=True, default=True)),
34
+ ('push_preferences', models.JSONField(blank=True, default=dict, help_text='Category-based notification preferences')),
35
+ ('is_active', models.BooleanField(db_index=True, default=True)),
36
+ ('last_seen', models.DateTimeField(auto_now=True)),
37
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='registered_devices', to=settings.AUTH_USER_MODEL)),
38
+ ],
39
+ options={
40
+ 'ordering': ['-last_seen'],
41
+ 'unique_together': {('user', 'device_id'), ('device_token', 'platform')},
42
+ },
43
+ bases=(models.Model, mojo.models.rest.MojoModel),
44
+ ),
45
+ migrations.CreateModel(
46
+ name='PushConfig',
47
+ fields=[
48
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
49
+ ('mojo_secrets', models.TextField(blank=True, default=None, null=True)),
50
+ ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
51
+ ('modified', models.DateTimeField(auto_now=True, db_index=True)),
52
+ ('name', models.CharField(help_text='Configuration name', max_length=100)),
53
+ ('is_active', models.BooleanField(db_index=True, default=True)),
54
+ ('apns_enabled', models.BooleanField(default=False)),
55
+ ('apns_key_id', models.CharField(blank=True, max_length=100)),
56
+ ('apns_team_id', models.CharField(blank=True, max_length=100)),
57
+ ('apns_bundle_id', models.CharField(blank=True, max_length=255)),
58
+ ('apns_key_file', models.TextField(blank=True, help_text='Encrypted via MojoSecrets')),
59
+ ('apns_use_sandbox', models.BooleanField(default=False)),
60
+ ('fcm_enabled', models.BooleanField(default=False)),
61
+ ('fcm_server_key', models.TextField(blank=True, help_text='Encrypted via MojoSecrets')),
62
+ ('fcm_sender_id', models.CharField(blank=True, max_length=100)),
63
+ ('default_sound', models.CharField(default='default', max_length=50)),
64
+ ('default_badge_count', models.IntegerField(default=1)),
65
+ ('group', models.OneToOneField(blank=True, help_text='Organization for this config. Null = system default', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='push_config', to='account.group')),
66
+ ],
67
+ options={
68
+ 'ordering': ['group__name', 'name'],
69
+ },
70
+ bases=(models.Model, mojo.models.rest.MojoModel),
71
+ ),
72
+ migrations.CreateModel(
73
+ name='NotificationTemplate',
74
+ fields=[
75
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
76
+ ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
77
+ ('modified', models.DateTimeField(auto_now=True, db_index=True)),
78
+ ('name', models.CharField(db_index=True, max_length=100)),
79
+ ('title_template', models.CharField(max_length=200)),
80
+ ('body_template', models.TextField()),
81
+ ('action_url', models.URLField(blank=True, help_text='Template URL with variable support', null=True)),
82
+ ('category', models.CharField(db_index=True, default='general', max_length=50)),
83
+ ('priority', models.CharField(choices=[('low', 'Low'), ('normal', 'Normal'), ('high', 'High')], db_index=True, default='normal', max_length=20)),
84
+ ('variables', models.JSONField(blank=True, default=dict, help_text='Expected template variables and descriptions')),
85
+ ('is_active', models.BooleanField(db_index=True, default=True)),
86
+ ('group', models.ForeignKey(blank=True, help_text='Organization for this template. Null = system template', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_templates', to='account.group')),
87
+ ],
88
+ options={
89
+ 'ordering': ['group__name', 'name'],
90
+ 'unique_together': {('group', 'name')},
91
+ },
92
+ bases=(models.Model, mojo.models.rest.MojoModel),
93
+ ),
94
+ migrations.CreateModel(
95
+ name='NotificationDelivery',
96
+ fields=[
97
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
98
+ ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
99
+ ('modified', models.DateTimeField(auto_now=True, db_index=True)),
100
+ ('title', models.CharField(max_length=200)),
101
+ ('body', models.TextField()),
102
+ ('category', models.CharField(db_index=True, max_length=50)),
103
+ ('action_url', models.URLField(blank=True, null=True)),
104
+ ('status', models.CharField(choices=[('pending', 'Pending'), ('sent', 'Sent'), ('delivered', 'Delivered'), ('failed', 'Failed')], db_index=True, default='pending', max_length=20)),
105
+ ('sent_at', models.DateTimeField(blank=True, db_index=True, null=True)),
106
+ ('delivered_at', models.DateTimeField(blank=True, null=True)),
107
+ ('error_message', models.TextField(blank=True, null=True)),
108
+ ('platform_data', models.JSONField(blank=True, default=dict, help_text='Platform-specific response data')),
109
+ ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_deliveries', to='account.registereddevice')),
110
+ ('template', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='deliveries', to='account.notificationtemplate')),
111
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_deliveries', to=settings.AUTH_USER_MODEL)),
112
+ ],
113
+ options={
114
+ 'ordering': ['-created'],
115
+ },
116
+ bases=(models.Model, mojo.models.rest.MojoModel),
117
+ ),
118
+ ]
@@ -0,0 +1,21 @@
1
+ # Generated by Django 4.2.21 on 2025-08-30 03:28
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('account', '0011_user_org_registereddevice_pushconfig_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveField(
14
+ model_name='pushconfig',
15
+ name='apns_key_file',
16
+ ),
17
+ migrations.RemoveField(
18
+ model_name='pushconfig',
19
+ name='fcm_server_key',
20
+ ),
21
+ ]
@@ -0,0 +1,28 @@
1
+ # Generated by Django 4.2.21 on 2025-08-30 04:34
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('account', '0012_remove_pushconfig_apns_key_file_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='pushconfig',
15
+ name='test_mode',
16
+ field=models.BooleanField(db_index=True, default=False, help_text='Enable test mode - fake notifications for development'),
17
+ ),
18
+ migrations.AlterField(
19
+ model_name='pushconfig',
20
+ name='apns_enabled',
21
+ field=models.BooleanField(default=False, help_text='APNS for iOS-specific needs. FCM is preferred.'),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name='pushconfig',
25
+ name='fcm_enabled',
26
+ field=models.BooleanField(default=True, help_text='FCM handles both iOS and Android notifications'),
27
+ ),
28
+ ]
@@ -0,0 +1,48 @@
1
+ # Generated by Django 4.2.23 on 2025-09-02 22:50
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('account', '0013_pushconfig_test_mode_alter_pushconfig_apns_enabled_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='notificationdelivery',
15
+ name='data_payload',
16
+ field=models.JSONField(blank=True, default=dict, help_text='Custom data payload sent with notification'),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='notificationtemplate',
20
+ name='data_template',
21
+ field=models.JSONField(blank=True, default=dict, help_text='Template data payload with variable support'),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name='notificationdelivery',
25
+ name='body',
26
+ field=models.TextField(blank=True, null=True),
27
+ ),
28
+ migrations.AlterField(
29
+ model_name='notificationdelivery',
30
+ name='title',
31
+ field=models.CharField(blank=True, max_length=200, null=True),
32
+ ),
33
+ migrations.AlterField(
34
+ model_name='notificationtemplate',
35
+ name='body_template',
36
+ field=models.TextField(blank=True, null=True),
37
+ ),
38
+ migrations.AlterField(
39
+ model_name='notificationtemplate',
40
+ name='title_template',
41
+ field=models.CharField(blank=True, max_length=200, null=True),
42
+ ),
43
+ migrations.AlterField(
44
+ model_name='notificationtemplate',
45
+ name='variables',
46
+ field=models.JSONField(blank=True, default=dict, help_text='Expected template variables and descriptions for title, body, action_url, and data_template'),
47
+ ),
48
+ ]
@@ -0,0 +1,5 @@
1
+ from .group import Group
2
+ from .user import User
3
+ from .member import GroupMember
4
+ from .device import GeoLocatedIP, UserDevice, UserDeviceLocation
5
+ from .push import RegisteredDevice, PushConfig, NotificationTemplate, NotificationDelivery