zou 0.19.59__py3-none-any.whl → 0.19.61__py3-none-any.whl
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.
- zou/__init__.py +1 -1
- zou/app/blueprints/auth/resources.py +3 -1
- zou/app/blueprints/crud/person.py +4 -1
- zou/app/blueprints/index/resources.py +7 -3
- zou/app/blueprints/persons/resources.py +4 -1
- zou/app/blueprints/previews/resources.py +5 -0
- zou/app/blueprints/user/resources.py +37 -1
- zou/app/config.py +1 -0
- zou/app/models/search_filter.py +4 -0
- zou/app/models/search_filter_group.py +3 -0
- zou/app/services/persons_service.py +3 -1
- zou/app/services/user_service.py +110 -28
- zou/app/utils/commands.py +7 -2
- zou/app/utils/emails.py +2 -2
- zou/app/utils/string.py +2 -0
- zou/migrations/versions/9d3bb33c6fc6_add_department_keys_to_filter_models.py +73 -0
- {zou-0.19.59.dist-info → zou-0.19.61.dist-info}/METADATA +5 -5
- {zou-0.19.59.dist-info → zou-0.19.61.dist-info}/RECORD +22 -21
- {zou-0.19.59.dist-info → zou-0.19.61.dist-info}/LICENSE +0 -0
- {zou-0.19.59.dist-info → zou-0.19.61.dist-info}/WHEEL +0 -0
- {zou-0.19.59.dist-info → zou-0.19.61.dist-info}/entry_points.txt +0 -0
- {zou-0.19.59.dist-info → zou-0.19.61.dist-info}/top_level.txt +0 -0
zou/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.19.
|
|
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(
|
|
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
|
|
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
|
|
279
|
+
Get basic configuration for the current instance.
|
|
280
280
|
---
|
|
281
281
|
tags:
|
|
282
282
|
- Index
|
|
283
283
|
responses:
|
|
284
284
|
200:
|
|
285
|
-
description:
|
|
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
|
|
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
|
|
zou/app/config.py
CHANGED
|
@@ -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(
|
zou/app/models/search_filter.py
CHANGED
|
@@ -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(
|
|
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):
|
zou/app/services/user_service.py
CHANGED
|
@@ -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
|
-
|
|
894
|
-
|
|
895
|
-
|
|
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
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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
|
-
|
|
903
|
-
|
|
912
|
+
if project_id not in subresult:
|
|
913
|
+
subresult[project_id] = []
|
|
904
914
|
|
|
905
|
-
|
|
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
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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(
|
|
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
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
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
|
-
|
|
1069
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
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
|
|
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:
|
zou/app/utils/commands.py
CHANGED
|
@@ -394,7 +394,9 @@ def sync_with_ldap_server():
|
|
|
394
394
|
)
|
|
395
395
|
.all()
|
|
396
396
|
):
|
|
397
|
-
persons_service.update_person(
|
|
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(
|
|
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)
|
zou/app/utils/emails.py
CHANGED
|
@@ -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["
|
|
15
|
+
if app.config["MAIL_DEBUG_BODY"]:
|
|
16
16
|
print(body)
|
|
17
|
-
|
|
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"]
|
zou/app/utils/string.py
CHANGED
|
@@ -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 ###
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zou
|
|
3
|
-
Version: 0.19.
|
|
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.
|
|
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
|
|
@@ -52,9 +52,9 @@ Requires-Dist: meilisearch ==0.31.5
|
|
|
52
52
|
Requires-Dist: opencv-python ==4.10.0.84
|
|
53
53
|
Requires-Dist: OpenTimelineIO ==0.17.0
|
|
54
54
|
Requires-Dist: OpenTimelineIO-Plugins ==0.17.0
|
|
55
|
-
Requires-Dist: orjson ==3.10.
|
|
55
|
+
Requires-Dist: orjson ==3.10.9
|
|
56
56
|
Requires-Dist: pillow ==11.0.0
|
|
57
|
-
Requires-Dist: psutil ==6.
|
|
57
|
+
Requires-Dist: psutil ==6.1.0
|
|
58
58
|
Requires-Dist: psycopg[binary] ==3.2.3
|
|
59
59
|
Requires-Dist: pyotp ==2.9.0
|
|
60
60
|
Requires-Dist: pysaml2 ==7.5.0
|
|
@@ -81,7 +81,7 @@ Requires-Dist: pre-commit ==4.0.1 ; extra == 'lint'
|
|
|
81
81
|
Provides-Extra: monitoring
|
|
82
82
|
Requires-Dist: prometheus-flask-exporter ==0.23.1 ; extra == 'monitoring'
|
|
83
83
|
Requires-Dist: pygelf ==0.4.2 ; extra == 'monitoring'
|
|
84
|
-
Requires-Dist: sentry-sdk ==2.
|
|
84
|
+
Requires-Dist: sentry-sdk ==2.17.0 ; extra == 'monitoring'
|
|
85
85
|
Provides-Extra: prod
|
|
86
86
|
Requires-Dist: gunicorn ; extra == 'prod'
|
|
87
87
|
Requires-Dist: gevent ; extra == 'prod'
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
zou/__init__.py,sha256=
|
|
1
|
+
zou/__init__.py,sha256=0ipQS0LM1jmY4x1OqN5dNC2NcN78T34DBnoO5MxyUvw,24
|
|
2
2
|
zou/cli.py,sha256=DHHf4mz33Bi0gGFJ0GdRUpjrMrMSQYyVubJFppHPZlU,18914
|
|
3
3
|
zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
|
|
4
4
|
zou/event_stream.py,sha256=_tue9Ry3aqCniZpKGhWJaY1Eo_fd6zOAfnzPvh_mJzU,8489
|
|
5
5
|
zou/job_settings.py,sha256=_aqBhujt2Q8sXRWIbgbDf-LUdXRdBimdtTc-fZbiXoY,202
|
|
6
6
|
zou/app/__init__.py,sha256=AJEGrLTirr5zZmA8DVSjZedtTuDg6eg9rG4kXMimPnQ,6966
|
|
7
7
|
zou/app/api.py,sha256=JTB_IMVO8EOoyqx9KdRkiIix0chOLi0yGDY-verUJXA,5127
|
|
8
|
-
zou/app/config.py,sha256=
|
|
8
|
+
zou/app/config.py,sha256=CR0wvWVF_T0Sfh-AGTphyXnMr0dm_ZVdXUOH3WUTz2s,6646
|
|
9
9
|
zou/app/mixin.py,sha256=eYwfS_CUFvNmldaQXrjsN5mK_gX0wYrBFykfx60uUM8,4897
|
|
10
10
|
zou/app/swagger.py,sha256=Jr7zsMqJi0V4FledODOdu-aqqVE02jMFzhqVxHK0_2c,54158
|
|
11
11
|
zou/app/blueprints/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
zou/app/blueprints/assets/__init__.py,sha256=T2zhDagHjXF6jRwOQ8vqokZTkBHyY7XtTI0Rlooamjs,2931
|
|
13
13
|
zou/app/blueprints/assets/resources.py,sha256=ff7g8_FzZC6dLvMxcYYffsIOy0CqKqdkZibGm2-qgko,25599
|
|
14
14
|
zou/app/blueprints/auth/__init__.py,sha256=xP874bMWUnLIirOPSEbpe-Q2fBBQrxZGKd0tLZmNJXk,1128
|
|
15
|
-
zou/app/blueprints/auth/resources.py,sha256=
|
|
15
|
+
zou/app/blueprints/auth/resources.py,sha256=ujdYPdz-anqIjK2Iepk5Yg4dRXJcHmc8sGpo6omG73A,45214
|
|
16
16
|
zou/app/blueprints/breakdown/__init__.py,sha256=Dp6GWSGxxWIedpyzTTEKpCRUYEo8oVNVyQhwNvTMmQM,1888
|
|
17
17
|
zou/app/blueprints/breakdown/resources.py,sha256=JY3j17kv7xPKV9S-XoOxNYivpGHlfZkXI5WuGtx3_Yk,13591
|
|
18
18
|
zou/app/blueprints/chats/__init__.py,sha256=YGmwGvddg3MgSYVIh-hmkX8t2em9_LblxBeJzFqFJD4,558
|
|
@@ -43,7 +43,7 @@ zou/app/blueprints/crud/notification.py,sha256=A-KNH0IDNCXlE4AddNxvmsD_7a9HqHGo_
|
|
|
43
43
|
zou/app/blueprints/crud/organisation.py,sha256=bNGo3Dtir2o_cHk0vDPs4cJw7mRWlSwPf2oA4lDQUyU,859
|
|
44
44
|
zou/app/blueprints/crud/output_file.py,sha256=jWSagq4LxwtFQH0XL_LjXaiW9FRn8T4k0tv1EbmPfg0,3954
|
|
45
45
|
zou/app/blueprints/crud/output_type.py,sha256=eYJXLPkUCRj9-v5mc3rxqEHM3yycmf6rVAoaOfbnAcU,1998
|
|
46
|
-
zou/app/blueprints/crud/person.py,sha256=
|
|
46
|
+
zou/app/blueprints/crud/person.py,sha256=FPvMt4ChXnfH6DheQL_jagakO6ic123UkOmsIM0cG_s,9281
|
|
47
47
|
zou/app/blueprints/crud/playlist.py,sha256=ZXaz-hHPej6XYKo_RUfJ2QnGOh2W8-y9hTkPZCUp7Zk,1876
|
|
48
48
|
zou/app/blueprints/crud/preview_background_file.py,sha256=WzOfag5qhz5B3-XDObYRC8TO4X-kIo1sHOnMCV62IEo,2437
|
|
49
49
|
zou/app/blueprints/crud/preview_file.py,sha256=252EDEdF-wQaL9ZhqQv5j9z_JKK5WeYwidJfFafArjo,3831
|
|
@@ -83,15 +83,15 @@ zou/app/blueprints/export/csv/time_spents.py,sha256=yYPtilOxfQD5mBwyh9h-PbTQBpab
|
|
|
83
83
|
zou/app/blueprints/files/__init__.py,sha256=7Wty30JW2OXIn-tBFXOWWmPuHnsnxPpH3jNtHvvr9tY,3987
|
|
84
84
|
zou/app/blueprints/files/resources.py,sha256=8SIV8kaqv3dxyL8nyqG3QiZmk5ZYIvUxw6k1ic-jhBs,69786
|
|
85
85
|
zou/app/blueprints/index/__init__.py,sha256=Dh3oQiirpg8RCkfVOuk3irIjSvUvuRf0jPxE6oGubz0,828
|
|
86
|
-
zou/app/blueprints/index/resources.py,sha256=
|
|
86
|
+
zou/app/blueprints/index/resources.py,sha256=_JiNodmq3-XCIz4vF0MYkkkg1Wdzh7Fl19KU0TTia1M,8742
|
|
87
87
|
zou/app/blueprints/news/__init__.py,sha256=HxBXjC15dVbotNAZ0CLf02iwUjxJr20kgf8_kT_9nwM,505
|
|
88
88
|
zou/app/blueprints/news/resources.py,sha256=SL0RYo-fs23GjQU1IW4kuEBg2SHdaXaonrOoOnWafdw,7183
|
|
89
89
|
zou/app/blueprints/persons/__init__.py,sha256=0cnHHw3K_8OEMm0qOi3wKVomSAg9IJSnVjAXabMeHks,3893
|
|
90
|
-
zou/app/blueprints/persons/resources.py,sha256=
|
|
90
|
+
zou/app/blueprints/persons/resources.py,sha256=0EBI6w63WhjqDSj-COYGk4NO6V1oRyAzfH4f7dXNYoE,42793
|
|
91
91
|
zou/app/blueprints/playlists/__init__.py,sha256=vuEk1F3hFHsmuKWhdepMoLyOzmNKDn1YrjjfcaIz0lQ,1596
|
|
92
92
|
zou/app/blueprints/playlists/resources.py,sha256=alRlMHypUFErXLsEYxpFK84cdjFJ3YWwamZtW0KcwLY,17211
|
|
93
93
|
zou/app/blueprints/previews/__init__.py,sha256=qGohO6LRNZKXBAegINcUXuZlrtxobJKQg84-rQ1L3AU,4202
|
|
94
|
-
zou/app/blueprints/previews/resources.py,sha256=
|
|
94
|
+
zou/app/blueprints/previews/resources.py,sha256=yuSs7-VOYdeSrTDwktx_3uyugxMN1r73FG0kNH-qNXg,48241
|
|
95
95
|
zou/app/blueprints/projects/__init__.py,sha256=Pn3fA5bpNFEPBzxTKJ2foV6osZFflXXSM2l2uZh3ktM,3927
|
|
96
96
|
zou/app/blueprints/projects/resources.py,sha256=E91Vj9EzId2pxiL50JRfrThiyif1PmzWS1oPeMThzQI,31544
|
|
97
97
|
zou/app/blueprints/search/__init__.py,sha256=QCjQIY_85l_orhdEiqav_GifjReuwsjZggN3V0GeUVY,356
|
|
@@ -129,7 +129,7 @@ zou/app/blueprints/source/shotgun/versions.py,sha256=8Mb35e5p3FLbbiu6AZb9tJErDKz
|
|
|
129
129
|
zou/app/blueprints/tasks/__init__.py,sha256=pNUqVEVX1KVu1IzRRJNsziPkhWKXqgyvQsNp7LbmIxo,4342
|
|
130
130
|
zou/app/blueprints/tasks/resources.py,sha256=b5z4OolidyKdKTP5kuZLk7tDLhgDs5W3rkH4ZWlwB0Y,56020
|
|
131
131
|
zou/app/blueprints/user/__init__.py,sha256=H9zCHcVobC6jq6dTToXKAjnZmDA0a9gChHiIP3BcZsc,4586
|
|
132
|
-
zou/app/blueprints/user/resources.py,sha256=
|
|
132
|
+
zou/app/blueprints/user/resources.py,sha256=loCigQvPCoRw6nVu_9TIY7pjUByJgk6vutFPSo0MwzI,39891
|
|
133
133
|
zou/app/file_trees/default.json,sha256=ryUrEmQYE8B_WkzCoQLgmem3N9yNwMIWx9G8p3HfG9o,2310
|
|
134
134
|
zou/app/file_trees/simple.json,sha256=VBI43Z3rjQxtTpVCq3ktUgS0UB8x-aTowKL9LXuXCFI,3149
|
|
135
135
|
zou/app/indexer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -166,8 +166,8 @@ zou/app/models/preview_file.py,sha256=Ur45Wau2X3qyKULh04EUcMbnBmaQc8y4IMs5NgELiA
|
|
|
166
166
|
zou/app/models/project.py,sha256=T2gTImmbd5O-U5GySWSwzkR0r_cY2RDr1niwSfOPqeA,8900
|
|
167
167
|
zou/app/models/project_status.py,sha256=pExaHH7x4Eu8xOqD3_mRRbMzjT2jJZ8rm-9jo7yUGXA,390
|
|
168
168
|
zou/app/models/schedule_item.py,sha256=coY5uDDuBoctaMICnfCzx4zT5om2E1uu4iq5MDWAPlY,1444
|
|
169
|
-
zou/app/models/search_filter.py,sha256=
|
|
170
|
-
zou/app/models/search_filter_group.py,sha256=
|
|
169
|
+
zou/app/models/search_filter.py,sha256=Q699mJa3GGwFEva93Y_nHiIcx3BDht9VsAe2zeQL0FA,1242
|
|
170
|
+
zou/app/models/search_filter_group.py,sha256=LGT2zn1lk3dCC-Fu7NU7VFD6MWprmBz7saQhS2ST2gA,980
|
|
171
171
|
zou/app/models/serializer.py,sha256=VKN5hHJ6M_jsvrbKe5SonnTeg5dxXSYqb_4JDVWIQwA,1477
|
|
172
172
|
zou/app/models/software.py,sha256=3y9xEOS8BBxqgTaRrCaSYHaB6uOdJ88uU5i-cACoCSk,517
|
|
173
173
|
zou/app/models/status_automation.py,sha256=95c0lmOetujyGWViLd_qsR4GWPhrmlvi9ZfkC0x1NuM,1391
|
|
@@ -200,7 +200,7 @@ zou/app/services/index_service.py,sha256=1w8rGJ7ArYC13B43hD4JOPtVhaRsbseJVVY-GnU
|
|
|
200
200
|
zou/app/services/names_service.py,sha256=TOSrintROmxcAlcFQE0i2E3PBLnw81GAztNselpTn18,2947
|
|
201
201
|
zou/app/services/news_service.py,sha256=g-QlITBbEvhvm-pLv7GtGACKX4uBPa-IKxfNOgMgaHo,8768
|
|
202
202
|
zou/app/services/notifications_service.py,sha256=7GDRio_mGaRYV5BHOAdpxBZjA_LLYUfVpbwZqy1n9pI,15685
|
|
203
|
-
zou/app/services/persons_service.py,sha256=
|
|
203
|
+
zou/app/services/persons_service.py,sha256=0CKYrmHDUq34VNNgLSWDKN37EgmD68ZqyrUmm4ABj18,16356
|
|
204
204
|
zou/app/services/playlists_service.py,sha256=pAlPHET4jNdST5jsmJrFUkf1SVhfSoML9zdNpZ_88l4,32439
|
|
205
205
|
zou/app/services/preview_files_service.py,sha256=M1kXryARUKwCDXsr0hOfUUyGn75y-qXIVIwlMOKWWHs,35609
|
|
206
206
|
zou/app/services/projects_service.py,sha256=_J8hIHy3MX5MsdEMRIKNfbyewwhxtMEcc_ymeHBsF38,21434
|
|
@@ -213,7 +213,7 @@ zou/app/services/sync_service.py,sha256=EunfXlma_IIb7011A_xLQLVQGAi-MteKgm2Y2NAx
|
|
|
213
213
|
zou/app/services/tasks_service.py,sha256=IoogHBoZhbJegnl5SYGgOaBp2YVqrL22Gccjfp8dPn8,69335
|
|
214
214
|
zou/app/services/telemetry_services.py,sha256=xQm1h1t_JxSFW59zQGf4NuNdUi1UfMa_6pQ-ytRbmGA,1029
|
|
215
215
|
zou/app/services/time_spents_service.py,sha256=H9X-60s6oqtY9rtU-K2jKwUSljfkdGlf_9wMr3iVfIA,15158
|
|
216
|
-
zou/app/services/user_service.py,sha256=
|
|
216
|
+
zou/app/services/user_service.py,sha256=Ih7-I0t_hzoRx_1Ya6zlvlWSLK0AabVtcXNPm7eYZNo,50514
|
|
217
217
|
zou/app/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
218
218
|
zou/app/stores/auth_tokens_store.py,sha256=-qOJPybLHvnMOq3PWk073OW9HJwOHGhFLZeOIlX1UVw,1290
|
|
219
219
|
zou/app/stores/file_store.py,sha256=yLQDM6mNbj9oe0vsWdBqun7D8Dw-eSjD1yHCCftX0OI,4045
|
|
@@ -225,11 +225,11 @@ zou/app/utils/auth.py,sha256=DZfZSr1Ulge0UK3hfvOWsMo3_d7RVP_llV118u9BtUI,870
|
|
|
225
225
|
zou/app/utils/cache.py,sha256=MRluTvGG67ybOkyzgD70B6PGKMdRyFdTc0AYy3dEQe8,1210
|
|
226
226
|
zou/app/utils/chats.py,sha256=ORngxQ3IQQF0QcVFJLxJ-RaU4ksQ9-0M8cmPa0pc0Ho,4302
|
|
227
227
|
zou/app/utils/colors.py,sha256=LaGV17NL_8xY0XSp8snGWz5UMwGnm0KPWXyE5BTMG6w,200
|
|
228
|
-
zou/app/utils/commands.py,sha256=
|
|
228
|
+
zou/app/utils/commands.py,sha256=z1tpCRY6wOH_uSrjPTS5kRkhYwW8SEA-pKhreaXLu0I,27472
|
|
229
229
|
zou/app/utils/csv_utils.py,sha256=difqBp9xp3nHvaOjW6B64A4X3Uyfe_vKGw10i6SJ5_E,1291
|
|
230
230
|
zou/app/utils/date_helpers.py,sha256=jFxDPCbAasg0I1gsC72AKEbGcx5c4pLqXZkSfZ4wLdQ,4724
|
|
231
231
|
zou/app/utils/dbhelpers.py,sha256=RSJuoxLexGJyME16GQCs-euFLBR0u-XAFdJ1KMSv5M8,1143
|
|
232
|
-
zou/app/utils/emails.py,sha256=
|
|
232
|
+
zou/app/utils/emails.py,sha256=hc4HWvVYsG1xoP3sR0Zig0sB0k0y7bNxuNxxBreN5Yg,1436
|
|
233
233
|
zou/app/utils/env.py,sha256=haveriMt1rDeLOosAPMm0IblF_QpMViEsjg7BJqD-rw,711
|
|
234
234
|
zou/app/utils/events.py,sha256=a_W70v0Oi4QJwJzCLVUQ8RTwjlWo-VzAT_hQZCz2HQU,3024
|
|
235
235
|
zou/app/utils/fido.py,sha256=qhUWZdDCvgWqydYS4DN1SVkNwdAQkRSV9zs0Xw9O15E,536
|
|
@@ -244,7 +244,7 @@ zou/app/utils/query.py,sha256=q8ETGPAqnz0Pt9xWoQt5o7FFAVYUKVCJiWpwefIr-iU,4592
|
|
|
244
244
|
zou/app/utils/remote_job.py,sha256=QPxcCWEv-NM1Q4IQawAyJAiSORwkMeOlByQb9OCShEw,2522
|
|
245
245
|
zou/app/utils/saml.py,sha256=m8wt_2RnMEHSrFvqCRGF91U5mwkqC6W-iBcx8N0LAqs,1679
|
|
246
246
|
zou/app/utils/shell.py,sha256=D30NuOzr1D6jsa9OF69JYXyqYNhtIdnfKSVYW4irbz8,405
|
|
247
|
-
zou/app/utils/string.py,sha256=
|
|
247
|
+
zou/app/utils/string.py,sha256=MX-zsf55ecyhedu4mk55FhByx_hOc_dSe7B1aVjJzO0,458
|
|
248
248
|
zou/app/utils/thumbnail.py,sha256=eUb25So1fbjxZKYRpTOxLcZ0vww5zXNVkfVIa_tu5Dk,6625
|
|
249
249
|
zou/migrations/README,sha256=MVlc9TYmr57RbhXET6QxgyCcwWP7w-vLkEsirENqiIQ,38
|
|
250
250
|
zou/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -354,6 +354,7 @@ zou/migrations/versions/99825b9cc778_.py,sha256=vleoLh_fCLwNnCmgZkW5x1-lJ09CgjPd
|
|
|
354
354
|
zou/migrations/versions/9a09467f9b2c_.py,sha256=cjSO3cXzHHhlcaQhShF9WlxmBWIfwLYSyIb9C6B5Dwc,1246
|
|
355
355
|
zou/migrations/versions/9b85c14fa8a7_add_day_off_new_columns.py,sha256=u6n5X_hwoeH9XnkWHB4PvVvGVrkddgDamweMrlPFQ9I,2106
|
|
356
356
|
zou/migrations/versions/9bd17364fc18_.py,sha256=nruaGMczzkWkya_D11QEU3uiU1UVEUItM6svSBjOw2c,1890
|
|
357
|
+
zou/migrations/versions/9d3bb33c6fc6_add_department_keys_to_filter_models.py,sha256=xUd0OIqp0q9l-pC6wCn2tfgCi6maeud6jf1CYGCHnxA,2084
|
|
357
358
|
zou/migrations/versions/9e5b3a9b0cee_add_new_column_metadatadescriptor_data_type_.py,sha256=HT34AjM9yN1IvLrCzx4-YOiocFDnPQ-FJ05icPCBnNo,5517
|
|
358
359
|
zou/migrations/versions/9f8445f9b42c_add_man_days_fields.py,sha256=muFsM2g_m-L5Zss36roTsjCoSDdhu_e4hVQntiNHyiY,828
|
|
359
360
|
zou/migrations/versions/a23682ccc1f1_.py,sha256=dVOUWldUZyLuLc6_HrgKUI5XH5-6Vjwai6Ew9kygkHw,1663
|
|
@@ -412,9 +413,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
|
|
|
412
413
|
zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
|
|
413
414
|
zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
414
415
|
zou/utils/movie.py,sha256=u9LCEOvmkxwm-KiZ6jKNdB9LSC6XXUDwJpVx8LkDwJg,16416
|
|
415
|
-
zou-0.19.
|
|
416
|
-
zou-0.19.
|
|
417
|
-
zou-0.19.
|
|
418
|
-
zou-0.19.
|
|
419
|
-
zou-0.19.
|
|
420
|
-
zou-0.19.
|
|
416
|
+
zou-0.19.61.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
|
|
417
|
+
zou-0.19.61.dist-info/METADATA,sha256=hSLIfr761zcENVUpwc4JbG4SPICbF9J3gyAkbmIvgFc,6676
|
|
418
|
+
zou-0.19.61.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
419
|
+
zou-0.19.61.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
|
|
420
|
+
zou-0.19.61.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
|
|
421
|
+
zou-0.19.61.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|