zou 0.19.59__tar.gz → 0.19.61__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 (429) hide show
  1. {zou-0.19.59/zou.egg-info → zou-0.19.61}/PKG-INFO +5 -5
  2. {zou-0.19.59 → zou-0.19.61}/setup.cfg +4 -4
  3. zou-0.19.61/zou/__init__.py +1 -0
  4. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/auth/resources.py +3 -1
  5. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/person.py +4 -1
  6. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/index/resources.py +7 -3
  7. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/persons/resources.py +4 -1
  8. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/previews/resources.py +5 -0
  9. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/user/resources.py +37 -1
  10. {zou-0.19.59 → zou-0.19.61}/zou/app/config.py +1 -0
  11. {zou-0.19.59 → zou-0.19.61}/zou/app/models/search_filter.py +4 -0
  12. {zou-0.19.59 → zou-0.19.61}/zou/app/models/search_filter_group.py +3 -0
  13. {zou-0.19.59 → zou-0.19.61}/zou/app/services/persons_service.py +3 -1
  14. {zou-0.19.59 → zou-0.19.61}/zou/app/services/user_service.py +110 -28
  15. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/commands.py +7 -2
  16. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/emails.py +2 -2
  17. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/string.py +2 -0
  18. zou-0.19.61/zou/migrations/versions/9d3bb33c6fc6_add_department_keys_to_filter_models.py +73 -0
  19. {zou-0.19.59 → zou-0.19.61/zou.egg-info}/PKG-INFO +5 -5
  20. {zou-0.19.59 → zou-0.19.61}/zou.egg-info/SOURCES.txt +1 -0
  21. {zou-0.19.59 → zou-0.19.61}/zou.egg-info/requires.txt +4 -4
  22. zou-0.19.59/zou/__init__.py +0 -1
  23. {zou-0.19.59 → zou-0.19.61}/LICENSE +0 -0
  24. {zou-0.19.59 → zou-0.19.61}/README.rst +0 -0
  25. {zou-0.19.59 → zou-0.19.61}/pyproject.toml +0 -0
  26. {zou-0.19.59 → zou-0.19.61}/setup.py +0 -0
  27. {zou-0.19.59 → zou-0.19.61}/zou/app/__init__.py +0 -0
  28. {zou-0.19.59 → zou-0.19.61}/zou/app/api.py +0 -0
  29. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/__init__.py +0 -0
  30. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/assets/__init__.py +0 -0
  31. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/assets/resources.py +0 -0
  32. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/auth/__init__.py +0 -0
  33. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/breakdown/__init__.py +0 -0
  34. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/breakdown/resources.py +0 -0
  35. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/chats/__init__.py +0 -0
  36. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/chats/resources.py +0 -0
  37. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/comments/__init__.py +0 -0
  38. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/comments/resources.py +0 -0
  39. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/concepts/__init__.py +0 -0
  40. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/concepts/resources.py +0 -0
  41. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/__init__.py +0 -0
  42. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/asset_instance.py +0 -0
  43. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/attachment_file.py +0 -0
  44. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/base.py +0 -0
  45. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/chat.py +0 -0
  46. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/chat_message.py +0 -0
  47. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/comments.py +0 -0
  48. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/custom_action.py +0 -0
  49. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/day_off.py +0 -0
  50. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/department.py +0 -0
  51. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/entity.py +0 -0
  52. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/entity_link.py +0 -0
  53. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/entity_type.py +0 -0
  54. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/event.py +0 -0
  55. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/file_status.py +0 -0
  56. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/metadata_descriptor.py +0 -0
  57. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/milestone.py +0 -0
  58. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/news.py +0 -0
  59. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/notification.py +0 -0
  60. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/organisation.py +0 -0
  61. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/output_file.py +0 -0
  62. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/output_type.py +0 -0
  63. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/playlist.py +0 -0
  64. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/preview_background_file.py +0 -0
  65. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/preview_file.py +0 -0
  66. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/project.py +0 -0
  67. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/project_status.py +0 -0
  68. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/schedule_item.py +0 -0
  69. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/search_filter.py +0 -0
  70. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/search_filter_group.py +0 -0
  71. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/software.py +0 -0
  72. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/status_automation.py +0 -0
  73. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/studio.py +0 -0
  74. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/subscription.py +0 -0
  75. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/task.py +0 -0
  76. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/task_status.py +0 -0
  77. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/task_type.py +0 -0
  78. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/time_spent.py +0 -0
  79. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/crud/working_file.py +0 -0
  80. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/edits/__init__.py +0 -0
  81. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/edits/resources.py +0 -0
  82. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/entities/__init__.py +0 -0
  83. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/entities/resources.py +0 -0
  84. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/events/__init__.py +0 -0
  85. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/events/resources.py +0 -0
  86. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/__init__.py +0 -0
  87. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/__init__.py +0 -0
  88. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/assets.py +0 -0
  89. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/base.py +0 -0
  90. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/casting.py +0 -0
  91. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/edits.py +0 -0
  92. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/persons.py +0 -0
  93. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/playlists.py +0 -0
  94. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/projects.py +0 -0
  95. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/shots.py +0 -0
  96. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/task_types.py +0 -0
  97. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/tasks.py +0 -0
  98. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/export/csv/time_spents.py +0 -0
  99. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/files/__init__.py +0 -0
  100. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/files/resources.py +0 -0
  101. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/index/__init__.py +0 -0
  102. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/news/__init__.py +0 -0
  103. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/news/resources.py +0 -0
  104. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/persons/__init__.py +0 -0
  105. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/playlists/__init__.py +0 -0
  106. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/playlists/resources.py +0 -0
  107. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/previews/__init__.py +0 -0
  108. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/projects/__init__.py +0 -0
  109. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/projects/resources.py +0 -0
  110. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/search/__init__.py +0 -0
  111. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/search/resources.py +0 -0
  112. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/shots/__init__.py +0 -0
  113. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/shots/resources.py +0 -0
  114. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/__init__.py +0 -0
  115. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/__init__.py +0 -0
  116. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/assets.py +0 -0
  117. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/base.py +0 -0
  118. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/casting.py +0 -0
  119. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/edits.py +0 -0
  120. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/persons.py +0 -0
  121. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/shots.py +0 -0
  122. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/csv/task_type_estimations.py +0 -0
  123. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/kitsu.py +0 -0
  124. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/otio.py +0 -0
  125. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/__init__.py +0 -0
  126. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/assets.py +0 -0
  127. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/base.py +0 -0
  128. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/episode.py +0 -0
  129. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/exception.py +0 -0
  130. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/import_errors.py +0 -0
  131. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/notes.py +0 -0
  132. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/person.py +0 -0
  133. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/project.py +0 -0
  134. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/scene.py +0 -0
  135. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/sequence.py +0 -0
  136. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/shot.py +0 -0
  137. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/status.py +0 -0
  138. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/steps.py +0 -0
  139. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/tasks.py +0 -0
  140. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/team.py +0 -0
  141. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/source/shotgun/versions.py +0 -0
  142. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/tasks/__init__.py +0 -0
  143. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/tasks/resources.py +0 -0
  144. {zou-0.19.59 → zou-0.19.61}/zou/app/blueprints/user/__init__.py +0 -0
  145. {zou-0.19.59 → zou-0.19.61}/zou/app/file_trees/default.json +0 -0
  146. {zou-0.19.59 → zou-0.19.61}/zou/app/file_trees/simple.json +0 -0
  147. {zou-0.19.59 → zou-0.19.61}/zou/app/indexer/__init__.py +0 -0
  148. {zou-0.19.59 → zou-0.19.61}/zou/app/indexer/indexing.py +0 -0
  149. {zou-0.19.59 → zou-0.19.61}/zou/app/mixin.py +0 -0
  150. {zou-0.19.59 → zou-0.19.61}/zou/app/models/__init__.py +0 -0
  151. {zou-0.19.59 → zou-0.19.61}/zou/app/models/asset_instance.py +0 -0
  152. {zou-0.19.59 → zou-0.19.61}/zou/app/models/attachment_file.py +0 -0
  153. {zou-0.19.59 → zou-0.19.61}/zou/app/models/base.py +0 -0
  154. {zou-0.19.59 → zou-0.19.61}/zou/app/models/build_job.py +0 -0
  155. {zou-0.19.59 → zou-0.19.61}/zou/app/models/chat.py +0 -0
  156. {zou-0.19.59 → zou-0.19.61}/zou/app/models/chat_message.py +0 -0
  157. {zou-0.19.59 → zou-0.19.61}/zou/app/models/comment.py +0 -0
  158. {zou-0.19.59 → zou-0.19.61}/zou/app/models/custom_action.py +0 -0
  159. {zou-0.19.59 → zou-0.19.61}/zou/app/models/data_import_error.py +0 -0
  160. {zou-0.19.59 → zou-0.19.61}/zou/app/models/day_off.py +0 -0
  161. {zou-0.19.59 → zou-0.19.61}/zou/app/models/department.py +0 -0
  162. {zou-0.19.59 → zou-0.19.61}/zou/app/models/desktop_login_log.py +0 -0
  163. {zou-0.19.59 → zou-0.19.61}/zou/app/models/entity.py +0 -0
  164. {zou-0.19.59 → zou-0.19.61}/zou/app/models/entity_type.py +0 -0
  165. {zou-0.19.59 → zou-0.19.61}/zou/app/models/event.py +0 -0
  166. {zou-0.19.59 → zou-0.19.61}/zou/app/models/file_status.py +0 -0
  167. {zou-0.19.59 → zou-0.19.61}/zou/app/models/login_log.py +0 -0
  168. {zou-0.19.59 → zou-0.19.61}/zou/app/models/metadata_descriptor.py +0 -0
  169. {zou-0.19.59 → zou-0.19.61}/zou/app/models/milestone.py +0 -0
  170. {zou-0.19.59 → zou-0.19.61}/zou/app/models/news.py +0 -0
  171. {zou-0.19.59 → zou-0.19.61}/zou/app/models/notification.py +0 -0
  172. {zou-0.19.59 → zou-0.19.61}/zou/app/models/organisation.py +0 -0
  173. {zou-0.19.59 → zou-0.19.61}/zou/app/models/output_file.py +0 -0
  174. {zou-0.19.59 → zou-0.19.61}/zou/app/models/output_type.py +0 -0
  175. {zou-0.19.59 → zou-0.19.61}/zou/app/models/person.py +0 -0
  176. {zou-0.19.59 → zou-0.19.61}/zou/app/models/playlist.py +0 -0
  177. {zou-0.19.59 → zou-0.19.61}/zou/app/models/preview_background_file.py +0 -0
  178. {zou-0.19.59 → zou-0.19.61}/zou/app/models/preview_file.py +0 -0
  179. {zou-0.19.59 → zou-0.19.61}/zou/app/models/project.py +0 -0
  180. {zou-0.19.59 → zou-0.19.61}/zou/app/models/project_status.py +0 -0
  181. {zou-0.19.59 → zou-0.19.61}/zou/app/models/schedule_item.py +0 -0
  182. {zou-0.19.59 → zou-0.19.61}/zou/app/models/serializer.py +0 -0
  183. {zou-0.19.59 → zou-0.19.61}/zou/app/models/software.py +0 -0
  184. {zou-0.19.59 → zou-0.19.61}/zou/app/models/status_automation.py +0 -0
  185. {zou-0.19.59 → zou-0.19.61}/zou/app/models/studio.py +0 -0
  186. {zou-0.19.59 → zou-0.19.61}/zou/app/models/subscription.py +0 -0
  187. {zou-0.19.59 → zou-0.19.61}/zou/app/models/task.py +0 -0
  188. {zou-0.19.59 → zou-0.19.61}/zou/app/models/task_status.py +0 -0
  189. {zou-0.19.59 → zou-0.19.61}/zou/app/models/task_type.py +0 -0
  190. {zou-0.19.59 → zou-0.19.61}/zou/app/models/time_spent.py +0 -0
  191. {zou-0.19.59 → zou-0.19.61}/zou/app/models/working_file.py +0 -0
  192. {zou-0.19.59 → zou-0.19.61}/zou/app/services/__init__.py +0 -0
  193. {zou-0.19.59 → zou-0.19.61}/zou/app/services/assets_service.py +0 -0
  194. {zou-0.19.59 → zou-0.19.61}/zou/app/services/auth_service.py +0 -0
  195. {zou-0.19.59 → zou-0.19.61}/zou/app/services/backup_service.py +0 -0
  196. {zou-0.19.59 → zou-0.19.61}/zou/app/services/base_service.py +0 -0
  197. {zou-0.19.59 → zou-0.19.61}/zou/app/services/breakdown_service.py +0 -0
  198. {zou-0.19.59 → zou-0.19.61}/zou/app/services/chats_service.py +0 -0
  199. {zou-0.19.59 → zou-0.19.61}/zou/app/services/comments_service.py +0 -0
  200. {zou-0.19.59 → zou-0.19.61}/zou/app/services/concepts_service.py +0 -0
  201. {zou-0.19.59 → zou-0.19.61}/zou/app/services/custom_actions_service.py +0 -0
  202. {zou-0.19.59 → zou-0.19.61}/zou/app/services/deletion_service.py +0 -0
  203. {zou-0.19.59 → zou-0.19.61}/zou/app/services/edits_service.py +0 -0
  204. {zou-0.19.59 → zou-0.19.61}/zou/app/services/emails_service.py +0 -0
  205. {zou-0.19.59 → zou-0.19.61}/zou/app/services/entities_service.py +0 -0
  206. {zou-0.19.59 → zou-0.19.61}/zou/app/services/events_service.py +0 -0
  207. {zou-0.19.59 → zou-0.19.61}/zou/app/services/exception.py +0 -0
  208. {zou-0.19.59 → zou-0.19.61}/zou/app/services/file_tree_service.py +0 -0
  209. {zou-0.19.59 → zou-0.19.61}/zou/app/services/files_service.py +0 -0
  210. {zou-0.19.59 → zou-0.19.61}/zou/app/services/index_service.py +0 -0
  211. {zou-0.19.59 → zou-0.19.61}/zou/app/services/names_service.py +0 -0
  212. {zou-0.19.59 → zou-0.19.61}/zou/app/services/news_service.py +0 -0
  213. {zou-0.19.59 → zou-0.19.61}/zou/app/services/notifications_service.py +0 -0
  214. {zou-0.19.59 → zou-0.19.61}/zou/app/services/playlists_service.py +0 -0
  215. {zou-0.19.59 → zou-0.19.61}/zou/app/services/preview_files_service.py +0 -0
  216. {zou-0.19.59 → zou-0.19.61}/zou/app/services/projects_service.py +0 -0
  217. {zou-0.19.59 → zou-0.19.61}/zou/app/services/scenes_service.py +0 -0
  218. {zou-0.19.59 → zou-0.19.61}/zou/app/services/schedule_service.py +0 -0
  219. {zou-0.19.59 → zou-0.19.61}/zou/app/services/shots_service.py +0 -0
  220. {zou-0.19.59 → zou-0.19.61}/zou/app/services/stats_service.py +0 -0
  221. {zou-0.19.59 → zou-0.19.61}/zou/app/services/status_automations_service.py +0 -0
  222. {zou-0.19.59 → zou-0.19.61}/zou/app/services/sync_service.py +0 -0
  223. {zou-0.19.59 → zou-0.19.61}/zou/app/services/tasks_service.py +0 -0
  224. {zou-0.19.59 → zou-0.19.61}/zou/app/services/telemetry_services.py +0 -0
  225. {zou-0.19.59 → zou-0.19.61}/zou/app/services/time_spents_service.py +0 -0
  226. {zou-0.19.59 → zou-0.19.61}/zou/app/stores/__init__.py +0 -0
  227. {zou-0.19.59 → zou-0.19.61}/zou/app/stores/auth_tokens_store.py +0 -0
  228. {zou-0.19.59 → zou-0.19.61}/zou/app/stores/file_store.py +0 -0
  229. {zou-0.19.59 → zou-0.19.61}/zou/app/stores/publisher_store.py +0 -0
  230. {zou-0.19.59 → zou-0.19.61}/zou/app/stores/queue_store.py +0 -0
  231. {zou-0.19.59 → zou-0.19.61}/zou/app/swagger.py +0 -0
  232. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/__init__.py +0 -0
  233. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/api.py +0 -0
  234. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/auth.py +0 -0
  235. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/cache.py +0 -0
  236. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/chats.py +0 -0
  237. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/colors.py +0 -0
  238. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/csv_utils.py +0 -0
  239. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/date_helpers.py +0 -0
  240. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/dbhelpers.py +0 -0
  241. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/env.py +0 -0
  242. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/events.py +0 -0
  243. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/fido.py +0 -0
  244. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/fields.py +0 -0
  245. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/flask.py +0 -0
  246. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/fs.py +0 -0
  247. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/git.py +0 -0
  248. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/logs.py +0 -0
  249. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/monitoring.py +0 -0
  250. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/permissions.py +0 -0
  251. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/query.py +0 -0
  252. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/remote_job.py +0 -0
  253. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/saml.py +0 -0
  254. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/shell.py +0 -0
  255. {zou-0.19.59 → zou-0.19.61}/zou/app/utils/thumbnail.py +0 -0
  256. {zou-0.19.59 → zou-0.19.61}/zou/cli.py +0 -0
  257. {zou-0.19.59 → zou-0.19.61}/zou/debug.py +0 -0
  258. {zou-0.19.59 → zou-0.19.61}/zou/event_stream.py +0 -0
  259. {zou-0.19.59 → zou-0.19.61}/zou/job_settings.py +0 -0
  260. {zou-0.19.59 → zou-0.19.61}/zou/migrations/README +0 -0
  261. {zou-0.19.59 → zou-0.19.61}/zou/migrations/__init__.py +0 -0
  262. {zou-0.19.59 → zou-0.19.61}/zou/migrations/alembic.ini +0 -0
  263. {zou-0.19.59 → zou-0.19.61}/zou/migrations/env.py +0 -0
  264. {zou-0.19.59 → zou-0.19.61}/zou/migrations/script.py.mako +0 -0
  265. {zou-0.19.59 → zou-0.19.61}/zou/migrations/utils/__init__.py +0 -0
  266. {zou-0.19.59 → zou-0.19.61}/zou/migrations/utils/base.py +0 -0
  267. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/003be8a91001_add_start_and_end_dates_to_projects.py +0 -0
  268. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/0596674df51d_add_department_mentions_to_comments.py +0 -0
  269. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/05ac7e8caa21_remove_unique_constraint_for_taskstatus_.py +0 -0
  270. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/05b7dc79a416_add_archived_fields_to_main_tables.py +0 -0
  271. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/0cf5e0e035fa_drop_column_tasktype_for_shots.py +0 -0
  272. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/0ec3762a745d_add_attachment_table.py +0 -0
  273. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/0ef6416a507b_.py +0 -0
  274. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/10cf267d95c9_fix_schedule_item.py +0 -0
  275. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/16328eae4b5f_add_new_constraint_for_timespent.py +0 -0
  276. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/16df47d76c64_add_some_indexes.py +0 -0
  277. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/17ef8f7be758_disallow_null_choicetype.py +0 -0
  278. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/1bb55759146f_add_table_studio.py +0 -0
  279. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/1cb44194db49_add_file_size_field_to_preview_file.py +0 -0
  280. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/1e150c2cea4d_add_nb_entities_out.py +0 -0
  281. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/1e2d77a2f0c4_add_hd_by_default_column.py +0 -0
  282. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/1fab8c420678_add_attachments_to_message_chats.py +0 -0
  283. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/20dfeb36142b_add_projecttaskstatuslink_roles_for_.py +0 -0
  284. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/23122f290ca2_add_entity_chat_models.py +0 -0
  285. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/269d41bfb73f_add_entity_entity_links.py +0 -0
  286. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/29df910f04a4_create_unique_constraint_project_id_.py +0 -0
  287. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/29fe01a6c9eb_add_status_automation_field.py +0 -0
  288. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/2adc020885fa_.py +0 -0
  289. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/2baede80b111_add_entity_status_field.py +0 -0
  290. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/306266361f4f_.py +0 -0
  291. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/328fd44c6347_add_entity_created_by.py +0 -0
  292. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/32f134ff1201_add_is_shared_flag_to_filters.py +0 -0
  293. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/346250b5304c_add_position_to_preview_files.py +0 -0
  294. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/3476e147e632_add_acks_to_comments.py +0 -0
  295. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/389cfb9de776_.py +0 -0
  296. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/38baa9a23b3d_.py +0 -0
  297. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/398150912a3f_validation_status_preview.py +0 -0
  298. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/3b0d1321079e_.py +0 -0
  299. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/3d5c93bafb9d_.py +0 -0
  300. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/3e0538ddf80f_.py +0 -0
  301. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/3fee3bd10f9d_.py +0 -0
  302. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/4095103c7d01_add_is_clients_isolated_flag_to_projects.py +0 -0
  303. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/40dea9555940_.py +0 -0
  304. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/42ec83db6a01_change_person_preferred_two_factor_.py +0 -0
  305. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/43d0cf0ed5e7_.py +0 -0
  306. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/443d1e78a932_.py +0 -0
  307. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/45c2de366e66_.py +0 -0
  308. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/45dafbb3f4e1_for_person_contract_type_disallow_null.py +0 -0
  309. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/4715c2586036_add_last_preview_file_fields.py +0 -0
  310. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/4e3738cdc34c_.py +0 -0
  311. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/4f2398ebcd49_.py +0 -0
  312. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/523ee9647bee_.py +0 -0
  313. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/54ee0d1d60ba_add_build_job_model.py +0 -0
  314. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/556526e47daa_.py +0 -0
  315. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/57222395f2be_add_statusautomation_import_last_revision.py +0 -0
  316. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5798d2c9020b_change_person_role_to_choicetype.py +0 -0
  317. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/590aa1ffe731_add_notifications_enabled_flag.py +0 -0
  318. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/59a7445a966c_add_entity_is_shared.py +0 -0
  319. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5a291251823c_add_max_retake_parameter.py +0 -0
  320. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5ab9d7a75887_.py +0 -0
  321. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5b0fcbb94f24_.py +0 -0
  322. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5b7fa3e51701_add_is_client_allowed_flag_to_task_.py +0 -0
  323. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5b980f0dc365_add_comment_links.py +0 -0
  324. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5b9fd9ddfe43_add_homepage_and_contract_fields.py +0 -0
  325. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5c0498e264bc_add_slack_fields.py +0 -0
  326. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/5e2ce62632a6_add_workflow_to_project.py +0 -0
  327. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/680c64565f9d_for_searchfiltergroup_is_shared.py +0 -0
  328. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/693cc511d28d_add_taskstatus_priority.py +0 -0
  329. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6aa446ee4072_add_is_for_all_flage_to_playlists.py +0 -0
  330. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6bd3b102d61b_.py +0 -0
  331. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6c597e842afa_add_task_type_field_to_playlists.py +0 -0
  332. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6d1b2c60f58b_add_milestone_model.py +0 -0
  333. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6d7fa5a8e9a5_add_timesheets_locked_field_to_org.py +0 -0
  334. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6eeaff945706_add_data_field_on_entity_links.py +0 -0
  335. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/6f6049877105_.py +0 -0
  336. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/7417c8eb70d8_add_for_entity_field_to_playlists.py +0 -0
  337. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/772a5e43f05b_.py +0 -0
  338. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/7748d3d22925_add_columns_to_searchfilter_table_to_.py +0 -0
  339. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/77d6820f494f_add_reply_to_notif.py +0 -0
  340. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/7b1f765677d8_.py +0 -0
  341. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/7bc746997e8d_add_slack_token_field_to_organisation.py +0 -0
  342. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/7dc79d4ed7cd_.py +0 -0
  343. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/818f7bda2528_.py +0 -0
  344. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/82e7f7a95e84_add_project_id_to_events.py +0 -0
  345. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/82ee682204ab_add_is_generated_from_ldap_column_to_.py +0 -0
  346. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/8588f254d6b8_add_archived_fields.py +0 -0
  347. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/8739ae9fa28b_add_for_client_field.py +0 -0
  348. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/87efceb6745b_add_ready_for_to_entity.py +0 -0
  349. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/892b264937ec_.py +0 -0
  350. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/8a1b4a1b7f4a_add_totp_columns_for_person.py +0 -0
  351. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/8e4f39e321f4_add_day_off_table.py +0 -0
  352. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/8e67c183bed7_add_preference_fields.py +0 -0
  353. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/8fbd40afbe5f_allow_to_set_float_values_for_.py +0 -0
  354. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9010a64e5a2d_add_indices.py +0 -0
  355. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9060dd4f6116_notification_uc.py +0 -0
  356. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/925771029620_.py +0 -0
  357. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/92b40d79ad3f_allow_message_attachments.py +0 -0
  358. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/92bdfe07e5f5_discord_integration.py +0 -0
  359. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/956659992419_add_columns_for_person_to_store_fido_.py +0 -0
  360. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/96c79d31e648_add_mail_otp_columns_for_person.py +0 -0
  361. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/96f58a4a2a58_person_partial_index_for_email_only_.py +0 -0
  362. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/971dbf5a0faf_add_short_name_for_asset_type_entity_.py +0 -0
  363. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/98c90621cf58_add_for_client_flag_to_playlist.py +0 -0
  364. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/99825b9cc778_.py +0 -0
  365. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9a09467f9b2c_.py +0 -0
  366. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9b85c14fa8a7_add_day_off_new_columns.py +0 -0
  367. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9bd17364fc18_.py +0 -0
  368. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9e5b3a9b0cee_add_new_column_metadatadescriptor_data_type_.py +0 -0
  369. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/9f8445f9b42c_add_man_days_fields.py +0 -0
  370. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a23682ccc1f1_.py +0 -0
  371. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a252a094e977_add_descriptions_for_entities_tasks_and_.py +0 -0
  372. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a519c710877c_.py +0 -0
  373. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a65bdadbae2f_.py +0 -0
  374. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a66508788c53_add_nb_assets_ready.py +0 -0
  375. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a6c25eed3ea1_add_login_failed_attemps_and_last_login_.py +0 -0
  376. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/a7c43f3fbc76_add_duration_column_to_the_preview_file.py +0 -0
  377. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/aa0a60033106_feedback_request.py +0 -0
  378. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/addbbefa7028_add_departments_link_to_metadata_.py +0 -0
  379. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/ae0127f2fc56_add_previewfile_width_and_previewfile_.py +0 -0
  380. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/af1790868e2c_.py +0 -0
  381. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/b45cb782bb9c_.py +0 -0
  382. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/b4dd0add5f79_.py +0 -0
  383. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/b8c0a0f9d054_drop_task_status_is_reviewable.py +0 -0
  384. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/b8ed0fb263f8_add_person_jti_and_jti_expiration_date.py +0 -0
  385. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/b97a71306fc8_add_is_casting_standby_column_to_entity.py +0 -0
  386. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/be56dc0fb760_for_is_shared_disallow_nullable.py +0 -0
  387. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/bf1347acdee2_.py +0 -0
  388. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/c49e41f1298b_add_previewbackground.py +0 -0
  389. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/c68c2a62cfac_add_mimetype_column_to_attachment.py +0 -0
  390. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/c726b98be194_.py +0 -0
  391. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/c81f3e83bdb5_.py +0 -0
  392. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/ca28796a2a62_add_is_done_field_to_the_task_model.py +0 -0
  393. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/cf3d365de164_add_entity_version_model.py +0 -0
  394. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/cf6cec6d6bf5_add_status_field_to_preview_file.py +0 -0
  395. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/d80267806131_task_status_new_column_is_default.py +0 -0
  396. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/d8dcd5196d57_add_casting_label.py +0 -0
  397. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/de8a3de227ef_.py +0 -0
  398. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/deeacd38d373_for_projecttaskstatuslink_set_default_.py +0 -0
  399. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/df1834485f57_.py +0 -0
  400. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/df9f8a147e80_change_file_size_to_big_integer.py +0 -0
  401. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/e1ef93f40d3d_.py +0 -0
  402. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/e29638428dfd_add_schedule_item_table.py +0 -0
  403. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/e3f6db74cc1e_.py +0 -0
  404. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/e839d6603c09_add_person_id_to_shot_history.py +0 -0
  405. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/ee2373fbe3a4_.py +0 -0
  406. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f0567e8d0c62_.py +0 -0
  407. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f0c6cbb61869_add_production_style_field.py +0 -0
  408. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f344b867a911_for_description_of_entity_task_working_.py +0 -0
  409. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f4ff5a73d283_add_person_ldap_uid.py +0 -0
  410. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f5b113876a49_add_preferred_two_factor_authentication_.py +0 -0
  411. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f5bdca075cdc_add_preview_download_flag_to_projects.py +0 -0
  412. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f874ad5e898a_add_link_entity_type_task_type.py +0 -0
  413. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/f995b28fb749_.py +0 -0
  414. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/fb6b6f188497_.py +0 -0
  415. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/fb87feaaa094_add_missing_unique_constraints.py +0 -0
  416. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/fc322f908695_.py +0 -0
  417. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/fee7c696166e_.py +0 -0
  418. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/feffd3c5b806_introduce_concepts.py +0 -0
  419. {zou-0.19.59 → zou-0.19.61}/zou/migrations/versions/ffeed4956ab1_add_more_details_to_projects.py +0 -0
  420. {zou-0.19.59 → zou-0.19.61}/zou/remote/__init__.py +0 -0
  421. {zou-0.19.59 → zou-0.19.61}/zou/remote/config_payload.py +0 -0
  422. {zou-0.19.59 → zou-0.19.61}/zou/remote/normalize_movie.py +0 -0
  423. {zou-0.19.59 → zou-0.19.61}/zou/remote/playlist.py +0 -0
  424. {zou-0.19.59 → zou-0.19.61}/zou/utils/__init__.py +0 -0
  425. {zou-0.19.59 → zou-0.19.61}/zou/utils/movie.py +0 -0
  426. {zou-0.19.59 → zou-0.19.61}/zou.egg-info/dependency_links.txt +0 -0
  427. {zou-0.19.59 → zou-0.19.61}/zou.egg-info/entry_points.txt +0 -0
  428. {zou-0.19.59 → zou-0.19.61}/zou.egg-info/not-zip-safe +0 -0
  429. {zou-0.19.59 → zou-0.19.61}/zou.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zou
3
- Version: 0.19.59
3
+ Version: 0.19.61
4
4
  Summary: API to store and manage the data of your animation production
5
5
  Home-page: https://zou.cg-wire.com
6
6
  Author: CG Wire
@@ -41,7 +41,7 @@ Requires-Dist: flask-socketio==5.4.1
41
41
  Requires-Dist: flask==3.0.3
42
42
  Requires-Dist: gazu==0.10.16
43
43
  Requires-Dist: gevent-websocket==0.10.1
44
- Requires-Dist: gevent==24.10.2
44
+ Requires-Dist: gevent==24.10.3
45
45
  Requires-Dist: gunicorn==23.0.0
46
46
  Requires-Dist: isoweek==1.3.3
47
47
  Requires-Dist: itsdangerous==2.2.0
@@ -54,9 +54,9 @@ Requires-Dist: numpy==2.1.2; python_version >= "3.10"
54
54
  Requires-Dist: opencv-python==4.10.0.84
55
55
  Requires-Dist: OpenTimelineIO==0.17.0
56
56
  Requires-Dist: OpenTimelineIO-Plugins==0.17.0
57
- Requires-Dist: orjson==3.10.7
57
+ Requires-Dist: orjson==3.10.9
58
58
  Requires-Dist: pillow==11.0.0
59
- Requires-Dist: psutil==6.0.0
59
+ Requires-Dist: psutil==6.1.0
60
60
  Requires-Dist: psycopg[binary]==3.2.3
61
61
  Requires-Dist: pyotp==2.9.0
62
62
  Requires-Dist: pysaml2==7.5.0
@@ -85,7 +85,7 @@ Requires-Dist: pytest==8.3.3; extra == "test"
85
85
  Provides-Extra: monitoring
86
86
  Requires-Dist: prometheus-flask-exporter==0.23.1; extra == "monitoring"
87
87
  Requires-Dist: pygelf==0.4.2; extra == "monitoring"
88
- Requires-Dist: sentry-sdk==2.16.0; extra == "monitoring"
88
+ Requires-Dist: sentry-sdk==2.17.0; extra == "monitoring"
89
89
  Provides-Extra: lint
90
90
  Requires-Dist: autoflake==2.3.1; extra == "lint"
91
91
  Requires-Dist: black==24.10.0; extra == "lint"
@@ -47,7 +47,7 @@ install_requires =
47
47
  flask==3.0.3
48
48
  gazu==0.10.16
49
49
  gevent-websocket==0.10.1
50
- gevent==24.10.2
50
+ gevent==24.10.3
51
51
  gunicorn==23.0.0
52
52
  isoweek==1.3.3
53
53
  itsdangerous==2.2.0
@@ -60,9 +60,9 @@ install_requires =
60
60
  opencv-python==4.10.0.84
61
61
  OpenTimelineIO==0.17.0
62
62
  OpenTimelineIO-Plugins==0.17.0
63
- orjson==3.10.7
63
+ orjson==3.10.9
64
64
  pillow==11.0.0
65
- psutil==6.0.0
65
+ psutil==6.1.0
66
66
  psycopg[binary]==3.2.3
67
67
  pyotp==2.9.0
68
68
  pysaml2==7.5.0
@@ -99,7 +99,7 @@ test =
99
99
  monitoring =
100
100
  prometheus-flask-exporter==0.23.1
101
101
  pygelf==0.4.2
102
- sentry-sdk==2.16.0
102
+ sentry-sdk==2.17.0
103
103
  lint =
104
104
  autoflake==2.3.1
105
105
  black==24.10.0
@@ -0,0 +1 @@
1
+ __version__ = "0.19.61"
@@ -1369,7 +1369,9 @@ class SAMLSSOResource(Resource, ArgsMixin):
1369
1369
  user = persons_service.get_person_by_email(email)
1370
1370
  for k, v in person_info.items():
1371
1371
  if user.get(k) != v:
1372
- persons_service.update_person(user["id"], person_info)
1372
+ persons_service.update_person(
1373
+ user["id"], person_info, bypass_protected_accounts=True
1374
+ )
1373
1375
  break
1374
1376
  except PersonNotFoundException:
1375
1377
  user = persons_service.create_person(
@@ -203,7 +203,10 @@ class PersonResource(BaseModelResource, ArgsMixin):
203
203
  and persons_service.is_user_limit_reached()
204
204
  ):
205
205
  raise WrongParameterException("User limit reached.")
206
- if instance_dict["email"] in config.PROTECTED_ACCOUNTS:
206
+ if (
207
+ instance_dict["email"] in config.PROTECTED_ACCOUNTS
208
+ and instance_dict["id"] != persons_service.get_current_user()["id"]
209
+ ):
207
210
  message = None
208
211
  if data.get("active") is False:
209
212
  message = "Can't set this person as inactive it's a protected account."
@@ -9,7 +9,7 @@ from zou import __version__
9
9
 
10
10
  from zou.app import app, config
11
11
  from zou.app.utils import permissions, shell, date_helpers
12
- from zou.app.services import projects_service, stats_service
12
+ from zou.app.services import projects_service, stats_service, persons_service
13
13
 
14
14
  from flask_jwt_extended import jwt_required
15
15
 
@@ -276,17 +276,21 @@ class StatsResource(Resource):
276
276
  class ConfigResource(Resource):
277
277
  def get(self):
278
278
  """
279
- Get crisp token.
279
+ Get basic configuration for the current instance.
280
280
  ---
281
281
  tags:
282
282
  - Index
283
283
  responses:
284
284
  200:
285
- description: Crisp token
285
+ description: Configuration object including self-hosted status,
286
+ Crisp token, indexer configuration, SAML status, and dark
287
+ theme status.
286
288
  """
289
+ organisation = persons_service.get_organisation()
287
290
  conf = {
288
291
  "is_self_hosted": config.IS_SELF_HOSTED,
289
292
  "crisp_token": config.CRISP_TOKEN,
293
+ "dark_theme_by_default": organisation["dark_theme_by_default"],
290
294
  "indexer_configured": (
291
295
  len(config.INDEXER["key"]) > 0
292
296
  and config.INDEXER["key"] != "masterkey"
@@ -1255,7 +1255,10 @@ class ChangePasswordForPersonResource(Resource, ArgsMixin):
1255
1255
  permissions.check_admin_permissions()
1256
1256
  try:
1257
1257
  person = persons_service.get_person(person_id)
1258
- if person["email"] in config.PROTECTED_ACCOUNTS:
1258
+ if (
1259
+ person["email"] in config.PROTECTED_ACCOUNTS
1260
+ and person["id"] != persons_service.get_current_user()["id"]
1261
+ ):
1259
1262
  raise PersonInProtectedAccounts()
1260
1263
  current_user = persons_service.get_current_user()
1261
1264
  auth.validate_password(password, password_2)
@@ -1023,6 +1023,11 @@ class PersonThumbnailResource(BaseThumbnailResource):
1023
1023
  if not is_current_user and not permissions.has_admin_permissions():
1024
1024
  raise permissions.PermissionDenied
1025
1025
 
1026
+ def prepare_creation(self, instance_id):
1027
+ self.model = self.update_model_func(
1028
+ instance_id, {"has_avatar": True}, bypass_protected_accounts=True
1029
+ )
1030
+
1026
1031
 
1027
1032
  class CreatePersonThumbnailResource(PersonThumbnailResource):
1028
1033
  pass
@@ -544,6 +544,7 @@ class FiltersResource(Resource, ArgsMixin):
544
544
  arguments["entity_type"],
545
545
  arguments["is_shared"],
546
546
  arguments["search_filter_group_id"],
547
+ department_id=arguments["department_id"],
547
548
  ),
548
549
  201,
549
550
  )
@@ -558,6 +559,7 @@ class FiltersResource(Resource, ArgsMixin):
558
559
  ("entity_type", None, False),
559
560
  ("is_shared", False, False, inputs.boolean),
560
561
  ("search_filter_group_id", None, False),
562
+ ("department_id", None, False),
561
563
  ]
562
564
  )
563
565
 
@@ -591,6 +593,7 @@ class FilterResource(Resource, ArgsMixin):
591
593
  ("search_filter_group_id", None, False),
592
594
  ("is_shared", None, False, inputs.boolean),
593
595
  ("project_id", None, None),
596
+ ("department_id", None, None),
594
597
  ]
595
598
  )
596
599
  data = self.clear_empty_fields(
@@ -663,19 +666,27 @@ class FilterGroupsResource(Resource, ArgsMixin):
663
666
  name: entity_type
664
667
  required: False
665
668
  type: string
669
+ - in: formData
670
+ name: is_shared
671
+ required: False
672
+ type: boolean
666
673
  - in: formData
667
674
  name: project_id
668
675
  required: True
669
676
  type: string
670
677
  format: UUID
671
678
  example: a24a6ea4-ce75-4665-a070-57453082c25
679
+ - in: formData
680
+ name: department_id
681
+ required: False
682
+ format: UUID
683
+ example: a24a6ea4-ce75-4665-a070-57453082c25
672
684
  responses:
673
685
  201:
674
686
  description: Filter groups for the current user and only for
675
687
  open projects created.
676
688
  """
677
689
  arguments = self.get_arguments()
678
-
679
690
  return (
680
691
  user_service.create_filter_group(
681
692
  arguments["list_type"],
@@ -684,6 +695,7 @@ class FilterGroupsResource(Resource, ArgsMixin):
684
695
  arguments["project_id"],
685
696
  arguments["entity_type"],
686
697
  arguments["is_shared"],
698
+ arguments["department_id"],
687
699
  ),
688
700
  201,
689
701
  )
@@ -697,6 +709,7 @@ class FilterGroupsResource(Resource, ArgsMixin):
697
709
  ("project_id", None, False),
698
710
  ("is_shared", False, False, inputs.boolean),
699
711
  ("entity_type", None, False),
712
+ ("department_id", None, False),
700
713
  ]
701
714
  )
702
715
 
@@ -733,6 +746,28 @@ class FilterGroupResource(Resource, ArgsMixin):
733
746
  type: string
734
747
  format: UUID
735
748
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
749
+ - in: formData
750
+ name: name
751
+ type: string
752
+ x-example: Name of the filter group
753
+ - in: formData
754
+ name: color
755
+ type: string
756
+ x-example: Color of the filter group
757
+ - in: formData
758
+ name: is_shared
759
+ type: boolean
760
+ x-example: True
761
+ - in: formData
762
+ name: project_id
763
+ type: string
764
+ format: UUID
765
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
766
+ - in: formData
767
+ name: department_id
768
+ type: string
769
+ format: UUID
770
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
736
771
  responses:
737
772
  200:
738
773
  description: Given filter group with updated data
@@ -743,6 +778,7 @@ class FilterGroupResource(Resource, ArgsMixin):
743
778
  ("color", None, False),
744
779
  ("is_shared", None, False, inputs.boolean),
745
780
  ("project_id", None, None),
781
+ ("department_id", None, None),
746
782
  ]
747
783
  )
748
784
 
@@ -82,6 +82,7 @@ MAIL_PORT = os.getenv("MAIL_PORT", 25)
82
82
  MAIL_USERNAME = os.getenv("MAIL_USERNAME", "")
83
83
  MAIL_PASSWORD = os.getenv("MAIL_PASSWORD", "")
84
84
  MAIL_DEBUG = envtobool("MAIL_DEBUG", False)
85
+ MAIL_DEBUG_BODY = envtobool("MAIL_DEBUG_BODY", False)
85
86
  MAIL_USE_TLS = envtobool("MAIL_USE_TLS", False)
86
87
  MAIL_USE_SSL = envtobool("MAIL_USE_SSL", False)
87
88
  MAIL_DEFAULT_SENDER = os.getenv(
@@ -23,6 +23,10 @@ class SearchFilter(db.Model, BaseMixin, SerializerMixin):
23
23
  nullable=False,
24
24
  )
25
25
 
26
+ department_id = db.Column(
27
+ UUIDType(binary=False),
28
+ db.ForeignKey("department.id"),
29
+ )
26
30
  search_filter_group_id = db.Column(
27
31
  UUIDType(binary=False),
28
32
  db.ForeignKey("search_filter_group.id"),
@@ -24,3 +24,6 @@ class SearchFilterGroup(db.Model, BaseMixin, SerializerMixin):
24
24
 
25
25
  person_id = db.Column(UUIDType(binary=False), db.ForeignKey("person.id"))
26
26
  project_id = db.Column(UUIDType(binary=False), db.ForeignKey("project.id"))
27
+ department_id = db.Column(
28
+ UUIDType(binary=False), db.ForeignKey("department.id")
29
+ )
@@ -381,7 +381,9 @@ def update_person_last_presence(person_id):
381
381
  date = log.date
382
382
  elif time_spent is not None:
383
383
  date = time_spent.date
384
- return update_person(person_id, {"last_presence": date})
384
+ return update_person(
385
+ person_id, {"last_presence": date}, bypass_protected_accounts=True
386
+ )
385
387
 
386
388
 
387
389
  def get_presence_logs(year, month):
@@ -889,20 +889,30 @@ def get_user_filters(current_user_id):
889
889
  .all()
890
890
  )
891
891
 
892
+ current_user = persons_service.get_current_user(relations=True)
893
+ is_manager = permissions.has_manager_permissions()
894
+
892
895
  for search_filter in filters:
893
- if search_filter.list_type not in result:
894
- result[search_filter.list_type] = {}
895
- subresult = result[search_filter.list_type]
896
+ department_id = search_filter.department_id
897
+ is_in_departments = (
898
+ department_id is not None
899
+ and str(department_id) in current_user["departments"]
900
+ )
896
901
 
897
- if search_filter.project_id is None:
898
- project_id = "all"
899
- else:
900
- project_id = str(search_filter.project_id)
902
+ if department_id is None or is_manager or is_in_departments:
903
+ if search_filter.list_type not in result:
904
+ result[search_filter.list_type] = {}
905
+ subresult = result[search_filter.list_type]
906
+
907
+ if search_filter.project_id is None:
908
+ project_id = "all"
909
+ else:
910
+ project_id = str(search_filter.project_id)
901
911
 
902
- if project_id not in subresult:
903
- subresult[project_id] = []
912
+ if project_id not in subresult:
913
+ subresult[project_id] = []
904
914
 
905
- subresult[project_id].append(search_filter.serialize())
915
+ subresult[project_id].append(search_filter.serialize())
906
916
 
907
917
  return result
908
918
 
@@ -915,6 +925,7 @@ def create_filter(
915
925
  entity_type=None,
916
926
  is_shared=False,
917
927
  search_filter_group_id=None,
928
+ department_id=None,
918
929
  ):
919
930
  """
920
931
  Add a new search filter to the database.
@@ -937,6 +948,13 @@ def create_filter(
937
948
  "A search filter should have the same value for is_shared than its search filter group."
938
949
  )
939
950
 
951
+ if department_id is not None:
952
+ department = tasks_service.get_department(department_id)
953
+ if department is None:
954
+ raise WrongParameterException(
955
+ f"No department found with id: {department_id}"
956
+ )
957
+
940
958
  search_filter = SearchFilter.create(
941
959
  list_type=list_type,
942
960
  name=name,
@@ -946,6 +964,7 @@ def create_filter(
946
964
  entity_type=entity_type,
947
965
  is_shared=is_shared,
948
966
  search_filter_group_id=search_filter_group_id,
967
+ department_id=department_id,
949
968
  )
950
969
  search_filter.serialize()
951
970
  if search_filter.is_shared:
@@ -969,9 +988,24 @@ def update_filter(search_filter_id, data):
969
988
  if search_filter is None:
970
989
  raise SearchFilterNotFoundException
971
990
 
972
- if data.get("project_id", None) is None or (
973
- data["project_id"] is not None
974
- and not has_manager_project_access(data["project_id"])
991
+ department_id = data.get("department_id", None)
992
+ if department_id is not None:
993
+ department = tasks_service.get_department(department_id)
994
+ if department is None:
995
+ raise WrongParameterException(
996
+ f"No department found with id: {department_id}"
997
+ )
998
+
999
+ if (
1000
+ data.get("is_shared", None) is not None
1001
+ and search_filter.is_shared != data["is_shared"]
1002
+ and (
1003
+ data.get("project_id", None) is None
1004
+ or (
1005
+ data["project_id"] is not None
1006
+ and not has_manager_project_access(data["project_id"])
1007
+ )
1008
+ )
975
1009
  ):
976
1010
  data["is_shared"] = False
977
1011
 
@@ -992,6 +1026,15 @@ def update_filter(search_filter_id, data):
992
1026
  raise WrongParameterException(
993
1027
  "A search filter should have the same value for is_shared than its search filter group."
994
1028
  )
1029
+
1030
+ department_id = data.get("department_id", None)
1031
+ if department_id is not None:
1032
+ department = tasks_service.get_department(department_id)
1033
+ if department is None:
1034
+ raise WrongParameterException(
1035
+ f"No department found with id: {department_id}"
1036
+ )
1037
+
995
1038
  search_filter.update(data)
996
1039
  if search_filter.is_shared:
997
1040
  clear_filter_cache()
@@ -1028,7 +1071,7 @@ def get_filter_groups():
1028
1071
  return get_user_filter_groups(current_user["id"])
1029
1072
 
1030
1073
 
1031
- @cache.memoize_function(120)
1074
+ @cache.memoize_function(10)
1032
1075
  def get_user_filter_groups(current_user_id):
1033
1076
  """
1034
1077
  Retrieve search filter groups used for given user. It groups them by
@@ -1055,26 +1098,41 @@ def get_user_filter_groups(current_user_id):
1055
1098
  .all()
1056
1099
  )
1057
1100
 
1101
+ current_user = persons_service.get_current_user(relations=True)
1102
+ is_manager = permissions.has_manager_permissions()
1103
+
1058
1104
  for search_filter_group in filter_groups:
1059
1105
  if search_filter_group.list_type not in result:
1060
1106
  result[search_filter_group.list_type] = {}
1061
- subresult = result[search_filter_group.list_type]
1062
1107
 
1063
- if search_filter_group.project_id is None:
1064
- project_id = "all"
1065
- else:
1066
- project_id = str(search_filter_group.project_id)
1108
+ department_id = search_filter_group.department_id
1109
+ is_in_departments = (
1110
+ department_id is not None
1111
+ and str(department_id) in current_user["departments"]
1112
+ )
1113
+ if department_id is None or is_manager or is_in_departments:
1114
+ subresult = result[search_filter_group.list_type]
1067
1115
 
1068
- if project_id not in subresult:
1069
- subresult[project_id] = []
1116
+ if search_filter_group.project_id is None:
1117
+ project_id = "all"
1118
+ else:
1119
+ project_id = str(search_filter_group.project_id)
1070
1120
 
1071
- subresult[project_id].append(search_filter_group.serialize())
1121
+ if project_id not in subresult:
1122
+ subresult[project_id] = []
1123
+ subresult[project_id].append(search_filter_group.serialize())
1072
1124
 
1073
1125
  return result
1074
1126
 
1075
1127
 
1076
1128
  def create_filter_group(
1077
- list_type, name, color, project_id=None, entity_type=None, is_shared=False
1129
+ list_type,
1130
+ name,
1131
+ color,
1132
+ project_id=None,
1133
+ entity_type=None,
1134
+ is_shared=False,
1135
+ department_id=None,
1078
1136
  ):
1079
1137
  """
1080
1138
  Add a new search filter group to the database.
@@ -1084,6 +1142,14 @@ def create_filter_group(
1084
1142
  project_id is not None and not has_manager_project_access(project_id)
1085
1143
  ):
1086
1144
  is_shared = False
1145
+
1146
+ if department_id is not None:
1147
+ department = tasks_service.get_department(department_id)
1148
+ if department is None:
1149
+ raise WrongParameterException(
1150
+ f"No department found with id: {department_id}"
1151
+ )
1152
+
1087
1153
  search_filter_group = SearchFilterGroup.create(
1088
1154
  list_type=list_type,
1089
1155
  name=name,
@@ -1092,12 +1158,15 @@ def create_filter_group(
1092
1158
  person_id=current_user["id"],
1093
1159
  entity_type=entity_type,
1094
1160
  is_shared=is_shared,
1161
+ department_id=department_id,
1095
1162
  )
1096
1163
  search_filter_group.serialize()
1164
+
1097
1165
  if search_filter_group.is_shared:
1098
1166
  clear_filter_group_cache()
1099
1167
  else:
1100
1168
  clear_filter_group_cache(current_user["id"])
1169
+
1101
1170
  return search_filter_group.serialize()
1102
1171
 
1103
1172
 
@@ -1122,16 +1191,30 @@ def update_filter_group(search_filter_group_id, data):
1122
1191
  search_filter_group = SearchFilterGroup.get_by(
1123
1192
  id=search_filter_group_id, person_id=current_user["id"]
1124
1193
  )
1194
+
1125
1195
  if search_filter_group is None:
1126
1196
  raise SearchFilterGroupNotFoundException
1127
- if data.get("project_id", None) is None or (
1128
- data["project_id"] is not None
1129
- and not has_manager_project_access(data["project_id"])
1197
+
1198
+ if (
1199
+ data.get("is_shared", None) is not None
1200
+ and search_filter_group.is_shared != data["is_shared"]
1201
+ and (
1202
+ data.get("project_id", None) is None
1203
+ or (
1204
+ data["project_id"] is not None
1205
+ and not has_manager_project_access(data["project_id"])
1206
+ )
1207
+ )
1130
1208
  ):
1131
1209
  data["is_shared"] = False
1210
+
1132
1211
  search_filter_group.update(data)
1133
1212
 
1134
- if data.get("is_shared", None) is not None:
1213
+ if (
1214
+ data.get("is_shared", None) is not None
1215
+ and data.get("project_id", None) is not None
1216
+ and has_manager_project_access(data["project_id"])
1217
+ ):
1135
1218
  if (
1136
1219
  SearchFilter.query.filter_by(
1137
1220
  search_filter_group_id=search_filter_group_id
@@ -1284,7 +1367,6 @@ def get_last_notifications(
1284
1367
  query = query.filter(Notification.read == read)
1285
1368
 
1286
1369
  if watching is not None:
1287
- print(watching)
1288
1370
  if watching:
1289
1371
  query = query.filter(Subscription.id != None)
1290
1372
  else:
@@ -394,7 +394,9 @@ def sync_with_ldap_server():
394
394
  )
395
395
  .all()
396
396
  ):
397
- persons_service.update_person(person.id, {"active": False})
397
+ persons_service.update_person(
398
+ person.id, {"active": False}, bypass_protected_accounts=True
399
+ )
398
400
  print(
399
401
  "User %s disabled (not found in LDAP)." % person.desktop_login
400
402
  )
@@ -418,6 +420,7 @@ def sync_with_ldap_server():
418
420
  "desktop_login": user["desktop_login"],
419
421
  "ldap_uid": user["ldap_uid"],
420
422
  },
423
+ bypass_protected_accounts=True,
421
424
  )
422
425
  print(f"User {user['desktop_login']} updated.")
423
426
  except IsUserLimitReachedException:
@@ -470,7 +473,9 @@ def sync_with_ldap_server():
470
473
  )
471
474
  file_store.add_picture("thumbnails", person["id"], thumbnail_png_path)
472
475
  os.remove(thumbnail_png_path)
473
- persons_service.update_person(person["id"], {"has_avatar": True})
476
+ persons_service.update_person(
477
+ person["id"], {"has_avatar": True}, bypass_protected_accounts=True
478
+ )
474
479
 
475
480
  ldap_users = get_ldap_users()
476
481
  update_person_list_with_ldap_users(ldap_users)
@@ -12,9 +12,9 @@ def send_email(subject, html, recipient_email, body=None):
12
12
  """
13
13
  if body is None:
14
14
  body = strip_html_tags(html)
15
- if app.config["MAIL_DEBUG"]:
15
+ if app.config["MAIL_DEBUG_BODY"]:
16
16
  print(body)
17
- elif app.config["MAIL_ENABLED"]:
17
+ if app.config["MAIL_ENABLED"]:
18
18
  with app.app_context():
19
19
  try:
20
20
  mail_default_sender = app.config["MAIL_DEFAULT_SENDER"]
@@ -6,6 +6,8 @@ def strtobool(val):
6
6
  """
7
7
  if isinstance(val, bool):
8
8
  return val
9
+ if isinstance(val, int):
10
+ return bool(val)
9
11
  elif val.lower() in ("y", "yes", "t", "true", "on", "1"):
10
12
  return True
11
13
  elif val.lower() in ("n", "no", "f", "false", "off", "0"):
@@ -0,0 +1,73 @@
1
+ """add department keys to filter models
2
+
3
+ Revision ID: 9d3bb33c6fc6
4
+ Revises: 8e67c183bed7
5
+ Create Date: 2024-10-11 15:52:29.740222
6
+
7
+ """
8
+
9
+ from alembic import op
10
+ import sqlalchemy as sa
11
+ import sqlalchemy_utils
12
+ import sqlalchemy_utils
13
+ import uuid
14
+
15
+ # revision identifiers, used by Alembic.
16
+ revision = "9d3bb33c6fc6"
17
+ down_revision = "8e67c183bed7"
18
+ branch_labels = None
19
+ depends_on = None
20
+
21
+
22
+ def upgrade():
23
+ # ### commands auto generated by Alembic - please adjust! ###
24
+ with op.batch_alter_table("search_filter", schema=None) as batch_op:
25
+ batch_op.add_column(
26
+ sa.Column(
27
+ "department_id",
28
+ sqlalchemy_utils.types.uuid.UUIDType(binary=False),
29
+ default=uuid.uuid4,
30
+ nullable=True,
31
+ )
32
+ )
33
+ batch_op.create_foreign_key(
34
+ "search_filter_department_id_fkey",
35
+ "department",
36
+ ["department_id"],
37
+ ["id"],
38
+ )
39
+
40
+ with op.batch_alter_table("search_filter_group", schema=None) as batch_op:
41
+ batch_op.add_column(
42
+ sa.Column(
43
+ "department_id",
44
+ sqlalchemy_utils.types.uuid.UUIDType(binary=False),
45
+ default=uuid.uuid4,
46
+ nullable=True,
47
+ )
48
+ )
49
+ batch_op.create_foreign_key(
50
+ "search_filter_group_department_id_fkey",
51
+ "department",
52
+ ["department_id"],
53
+ ["id"],
54
+ )
55
+
56
+ # ### end Alembic commands ###
57
+
58
+
59
+ def downgrade():
60
+ # ### commands auto generated by Alembic - please adjust! ###
61
+ with op.batch_alter_table("search_filter_group", schema=None) as batch_op:
62
+ batch_op.drop_constraint(
63
+ "search_filter_group_department_id_fkey", type_="foreignkey"
64
+ )
65
+ batch_op.drop_column("department_id")
66
+
67
+ with op.batch_alter_table("search_filter", schema=None) as batch_op:
68
+ batch_op.drop_constraint(
69
+ "search_filter_department_id_fkey", type_="foreignkey"
70
+ )
71
+ batch_op.drop_column("department_id")
72
+
73
+ # ### end Alembic commands ###