firefighter-incident 0.0.5__py3-none-any.whl → 0.0.6__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.
firefighter/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.0.5'
21
- __version_tuple__ = version_tuple = (0, 0, 5)
20
+ __version__ = version = '0.0.6'
21
+ __version_tuple__ = version_tuple = (0, 0, 6)
@@ -0,0 +1,42 @@
1
+ # Generated by Django 4.2.21 on 2025-06-02 16:29
2
+ import uuid
3
+
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("incidents", "0011_update_incidents"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="impactlevel",
16
+ name="id",
17
+ field=models.UUIDField(
18
+ default=uuid.uuid4, editable=False, primary_key=True, serialize=False
19
+ ),
20
+ ),
21
+ migrations.AlterField(
22
+ model_name="impactlevel",
23
+ name="value",
24
+ field=models.CharField(
25
+ choices=[
26
+ ("HT", "Highest"),
27
+ ("HI", "High"),
28
+ ("MD", "Medium"),
29
+ ("LO", "Low"),
30
+ ("LT", "Lowest"),
31
+ ("NO", "N/A"),
32
+ ],
33
+ default="LT",
34
+ max_length=2,
35
+ ),
36
+ ),
37
+ migrations.AlterField(
38
+ model_name="impacttype",
39
+ name="emoji",
40
+ field=models.CharField(default="▶", max_length=5),
41
+ ),
42
+ ]
@@ -0,0 +1,61 @@
1
+ import logging
2
+
3
+ from django.db import migrations
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ def get_new_components() -> dict:
9
+ """
10
+ Returns a dictionary of new components to be created.
11
+
12
+ Each entry in the dictionary maps a component name to a tuple containing:
13
+ - group_name: The name of the group the component belongs to.
14
+ - slack_channel: The associated Slack channel for the component.
15
+
16
+ Returns:
17
+ dict: A mapping of component names to (group name, slack channel) tuples.
18
+ """
19
+ return {
20
+ "Data Tools": ("Data", "impact-data-tools"),
21
+ "Catalog Access": ("Catalog", "impact-catalog-access"),
22
+ }
23
+
24
+
25
+ def add_new_components(apps, schema_editor):
26
+ Component = apps.get_model("incidents", "Component")
27
+ Group = apps.get_model("incidents", "Group")
28
+ new_components = get_new_components()
29
+
30
+ for name, (group_name, _slack) in new_components.items():
31
+ logger.info(f"Creating new component: '{name}' belonging to group '{group_name}'")
32
+ try:
33
+ group_instance = Group.objects.get(name=group_name)
34
+ new_component = Component(name=name, group=group_instance)
35
+ new_component.save()
36
+ except Exception:
37
+ logger.exception(f"Failed to create new group: '{group_name}'.")
38
+
39
+
40
+ def remove_new_components(apps, schema_editor):
41
+ Component = apps.get_model("incidents", "Component")
42
+ new_component_names = get_new_components().keys()
43
+
44
+ for name in new_component_names:
45
+ try:
46
+ component = Component.objects.get(name=name)
47
+ logger.info(f"Removing component: '{name}'")
48
+ component.delete()
49
+ except Exception:
50
+ logger.exception(f"Component '{name}' does not exist, skipping removal.")
51
+
52
+
53
+ class Migration(migrations.Migration):
54
+
55
+ dependencies = [
56
+ ("incidents", "0012_alter_impactlevel"),
57
+ ]
58
+
59
+ operations = [
60
+ migrations.RunPython(add_new_components, remove_new_components),
61
+ ]
@@ -0,0 +1,177 @@
1
+ import logging
2
+
3
+ from django.db import migrations, transaction
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ COMPONENT_SLACK_GROUPS = {
8
+ "Controlling": ("S08UYJGJ9HB", "finance-controlling"),
9
+ "Applications": ("S08V22ZJ6DQ", "corporate-it-applications"),
10
+ "Gitlab": ("S090A6LQ0U8", "platform-gitlab"),
11
+ "Seller Admin and Experience": ("S08UV261ZRU", "seller-seller-admin-and-experience"),
12
+ "Revenue": ("S08V22ZPBBL", "finance-revenue"),
13
+ "Catalog Exposition": ("S08VD2WE5ND", "catalog-catalog-exposition"),
14
+ "Company reputation": ("S090A63V7FS", "marketing-communication-company-reputation"),
15
+ "BO Catalog - Master Experience": ("S08VD2Y1DMF", "catalog-bo-catalog-master-experience"),
16
+ "Customer service": ("S08UV2GB7UN", "operations-customer-service"),
17
+ "Seller's invoices": ("S08VD38AFFB", "finance-sellers-invoices"),
18
+ "Cart & funnel": ("S08V2N7PRN0", "marketplace-cart-funnel"),
19
+ "Data Ingestion": ("S08UYJHEFEH", "data-data-ingestion"),
20
+ "Refunds": ("S08UM14D3LP", "payment-operations-refunds"),
21
+ "Data Analytics": ("S08V2NNDG9J", "data-data-analytics"),
22
+ "Mobile Apps": ("S08UV20CL6S", "marketplace-mobile-apps"),
23
+ "Navigation & Product discovery": ("S08UYHZFFD3", "marketplace-navigation-product-discovery"),
24
+ "Helpcenter after sales": ("S08UU3SHQTV", "operations-helpcenter-after-sales"),
25
+ "CDN": ("S08UM12RNTZ", "platform-cdn"),
26
+ "Customer's invoices": ("S08UYJGELJH", "finance-customers-invoices"),
27
+ "Returns": ("S08UYJHDNQM", "operations-returns"),
28
+ "Inventory": ("S08V2NNLW3W", "operations-inventory"),
29
+ "Loyalty and coupons": ("S08V230H1V0", "payment-operations-loyalty-and-coupons"),
30
+ "Seller Services": ("S08UM0SJ66T", "seller-seller-services"),
31
+ "Spinak": ("S08UYJGRTE1", "platform-spinak"),
32
+ "Data Tools": ("S08V2NPFDPE", "data-data-tools"),
33
+ "Product Management": ("S08UYJ5GU93", "catalog-product-management"),
34
+ "Compromised laptop / server": ("S08UU3T6H51", "security-compromised-laptop-server"),
35
+ "Catalog Performance": ("S08V22QDHJ6", "catalog-catalog-performance"),
36
+ "Spartacux Foundations": ("S08UYHZH97X", "marketplace-spartacux-foundations"),
37
+ "Stolen account(s) or IT materials": ("S08UU3TFJ3D", "security-stolen-accounts-or-it-materials"),
38
+ "MM Fulfillment": ("S08VD371F0R", "operations-mm-fulfillment"),
39
+ "HUB Integrators": ("S08UM0SSNNB", "seller-hub-integrators"),
40
+ "Exploited vulnerability": ("S08V2NPD084", "security-exploited-vulnerability"),
41
+ "Commercial Animation": ("S08V2N6UA3E", "marketplace-commercial-animation"),
42
+ "Cloud Infrastructure": ("S08UYJJ01HB", "platform-cloud-infrastructure"),
43
+ "Tracking": ("S08UYHZPSTX", "marketplace-tracking"),
44
+ "Data Warehouse": ("S08UYJHRWQ5", "data-data-warehouse"),
45
+ "Infra - System": ("S08UV2H5WDC", "corporate-it-infra-system"),
46
+ "VAT": ("S090A6LGGV6", "finance-vat"),
47
+ "Web performance": ("S090A63K124", "marketplace-web-performance"),
48
+ "Payouts to seller": ("S090A6M61A4", "payment-operations-payouts-to-seller"),
49
+ "Seller Catalog and Offer Management": ("S08UV261CHL", "seller-seller-catalog-and-offer-management"),
50
+ "Other": ("S08V22Z8S58", "other-other"),
51
+ "Network": ("S090A6M3B7S", "corporate-it-network"),
52
+ "Bot management & rate limiting & WAF": ("S090A6M8740", "security-bot-management-rate-limiting-waf"),
53
+ "Customer login & signup": ("S08V22H38AE", "marketplace-customer-login-signup"),
54
+ "Delivery experience": ("S08V2NP1E5A", "operations-delivery-experience"),
55
+ "Accounting": ("S08VD37CJBT", "finance-accounting"),
56
+ "Traffic acquisition": ("S08UU3BNPPV", "marketing-communication-traffic-acquisition"),
57
+ "Payment": ("S08UM13DTFH", "payment-operations-payment"),
58
+ "Data leak": ("S08UYJHBJPP", "security-data-leak"),
59
+ "Offer (Price & Stock)": ("S08V2NCSPJ8", "catalog-offer-price-stock"),
60
+ "Product Structure": ("S08V2NCNFV2", "catalog-product-structure"),
61
+ "Catalog Access": ("S090A69J064", "catalog-catalog-access"),
62
+ "Order management": ("S08UU3TRGJF", "operations-order-management"),
63
+ }
64
+
65
+
66
+ def update_components_slack_groups(apps, _):
67
+ try:
68
+ Component = apps.get_model("incidents", "Component")
69
+ UserGroup = apps.get_model("slack", "UserGroup")
70
+ except LookupError:
71
+ logger.exception("The 'slack' app is not installed. Skipping migration.")
72
+ return
73
+
74
+ with transaction.atomic():
75
+ for component_name, (user_group_id, user_group_name) in COMPONENT_SLACK_GROUPS.items():
76
+ try:
77
+ # Vérifier/créer le SlackUserGroup
78
+ user_group, _ = UserGroup.objects.get_or_create(
79
+ name=user_group_name
80
+ )
81
+ # Si le slack_group_id a changé, le mettre à jour
82
+ if user_group.usergroup_id != user_group_id:
83
+ user_group.usergroup_id = user_group_id
84
+ user_group.handle = user_group_name
85
+ user_group.save()
86
+
87
+ # Vérifier/créer le Component
88
+ component = Component.objects.get(name=component_name)
89
+ if not component:
90
+ logger.error(f"Component '{component_name}' n'existe pas.")
91
+ continue
92
+
93
+ # Lier le Component au SlackUserGroup via la relation du UserGroup
94
+ if not hasattr(user_group, "components"):
95
+ logger.error(f"UserGroup '{user_group_name}' n'a pas d'attribut 'components'.")
96
+ continue
97
+
98
+ if not user_group.components.filter(id=component.id).exists():
99
+ user_group.components.add(component)
100
+ logger.info(f"Component '{component_name}' ajouté au SlackUserGroup '{user_group_name}'")
101
+ except Exception:
102
+ logger.exception(f"Failed to update component: '{component_name}'.")
103
+
104
+
105
+ def ensure_firefighters_user_group(apps, _):
106
+ try:
107
+ Component = apps.get_model("incidents", "Component")
108
+ UserGroup = apps.get_model("slack", "UserGroup")
109
+ except LookupError:
110
+ logger.exception("The 'slack' app is not installed. Skipping Firefighters user group check.")
111
+ return
112
+
113
+ try:
114
+ firefighters_group = UserGroup.objects.get(name="firefighters")
115
+ except UserGroup.DoesNotExist:
116
+ logger.exception("UserGroup 'firefighters' does not exist.")
117
+ return
118
+
119
+ for component in Component.objects.all():
120
+ if not hasattr(firefighters_group, "components"):
121
+ logger.error("UserGroup 'firefighters' n'a pas d'attribut 'components'.")
122
+ break
123
+ if not firefighters_group.components.filter(id=component.id).exists():
124
+ firefighters_group.components.add(component)
125
+ logger.info(f"Component '{component.name}' ajouté au SlackUserGroup 'firefighters'.")
126
+
127
+
128
+ def cleanup_unused_slack_user_groups(apps, _):
129
+ try:
130
+ UserGroup = apps.get_model("slack", "UserGroup")
131
+ except LookupError:
132
+ logger.exception("The 'slack' app is not installed. Skipping user groups cleanup.")
133
+ return
134
+
135
+ valid_usergroup_ids = {v[0] for v in COMPONENT_SLACK_GROUPS.values()}
136
+
137
+ for user_group in UserGroup.objects.all():
138
+ if (
139
+ user_group.usergroup_id not in valid_usergroup_ids
140
+ and "firefighter" not in user_group.name.lower()
141
+ and hasattr(user_group, "components")
142
+ ):
143
+ components_to_remove = list(user_group.components.all())
144
+ if components_to_remove:
145
+ user_group.components.clear()
146
+ logger.info(
147
+ f"Removed components {[c.name for c in components_to_remove]} from SlackUserGroup '{user_group.name}'"
148
+ )
149
+
150
+
151
+ def delete_unused_slack_user_groups(apps, _):
152
+ try:
153
+ UserGroup = apps.get_model("slack", "UserGroup")
154
+ except LookupError:
155
+ logger.exception("The 'slack' app is not installed. Skipping user groups deletion.")
156
+ return
157
+
158
+ for user_group in UserGroup.objects.all():
159
+ if "firefighters" in user_group.name.lower():
160
+ continue
161
+ if hasattr(user_group, "components") and user_group.components.count() == 0:
162
+ logger.info(f"Deleting SlackUserGroup '{user_group.name}' (ID: {user_group.usergroup_id}) as it has no components.")
163
+ user_group.delete()
164
+
165
+
166
+ class Migration(migrations.Migration):
167
+
168
+ dependencies = [
169
+ ("incidents", "0013_add_missing_component"),
170
+ ]
171
+
172
+ operations = [
173
+ migrations.RunPython(update_components_slack_groups),
174
+ migrations.RunPython(ensure_firefighters_user_group),
175
+ migrations.RunPython(cleanup_unused_slack_user_groups),
176
+ migrations.RunPython(delete_unused_slack_user_groups),
177
+ ]
@@ -0,0 +1,24 @@
1
+ # Generated by Django 4.2.21 on 2025-06-03 15:03
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("incidents", "0014_update_components_slack_groups"),
10
+ ("slack", "0003_alter_usergroup_tag"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="usergroup",
16
+ name="components",
17
+ field=models.ManyToManyField(
18
+ blank=True,
19
+ help_text="Incident created with this usergroup automatically add the group members to these issue categories.",
20
+ related_name="usergroups",
21
+ to="incidents.component",
22
+ ),
23
+ ),
24
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firefighter-incident
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Incident Management tool made for Slack using Django
5
5
  Project-URL: Repository, https://github.com/ManoManoTech/firefighter-incident
6
6
  Project-URL: Documentation, https://manomanotech.github.io/firefighter-incident/latest/
@@ -6,7 +6,7 @@ gunicorn.conf.py,sha256=vHsTGjaKOr8FDMp6fTKYTX4AtokmPgYvvt5Mr0Q6APc,273
6
6
  main.py,sha256=CsbprHoOYhjCLpTJmq9Z_aRYFoFgWxoz2pDLuwm8Eqg,1558
7
7
  manage.py,sha256=5ivHGD13C6nJ8QvltKsJ9T9akA5he8da70HLWaEP3k8,689
8
8
  firefighter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- firefighter/_version.py,sha256=WcvKdm4etz9_Q5VW_LRgfCR0icS2PEtbz-C1JY6enCc,511
9
+ firefighter/_version.py,sha256=juzdq-mLyQD1MXj2IU1nbwqAl0oOYH7zZ9BDjNsqyB0,511
10
10
  firefighter/api/__init__.py,sha256=JQW0Bv6xwGqy7ioxx3h6UGMzkkJ4DntDpbvV1Ncgi8k,136
11
11
  firefighter/api/admin.py,sha256=x9Ysy-GiYjb0rynmFdS9g56e6n24fkN0ouGy5QD9Yrc,4629
12
12
  firefighter/api/apps.py,sha256=P5uU1_gMrDfzurdMbfqw1Bnb2uNKKcMq17WBPg2sLhc,204
@@ -156,6 +156,9 @@ firefighter/incidents/migrations/0008_impact_level.py,sha256=ZPDTYbt3q0gSEjMC7Nh
156
156
  firefighter/incidents/migrations/0009_update_sla.py,sha256=cLbDmOKrcQOa6lb1kMd-xPJC1w7iDJuEsDTKymEnUMw,849
157
157
  firefighter/incidents/migrations/0010_update_components.py,sha256=IwAj3axIXM95DrQcAZ8NBe-3GgL4NPrZqyBMdVqA8Lo,4301
158
158
  firefighter/incidents/migrations/0011_update_incidents.py,sha256=tV4MA5ZJcqiRPteOLxJNZuhj7q6ncWXjAklm_9IzLbo,3190
159
+ firefighter/incidents/migrations/0012_alter_impactlevel.py,sha256=fLMDjkYC8P2HffTRUJneMZlAiw1Z7trjXUZqSlEkAxM,1139
160
+ firefighter/incidents/migrations/0013_add_missing_component.py,sha256=qVLQEl-riFwYNCbhXM-9-GNCHE-bk9QhbVMKqqOL0Ag,1962
161
+ firefighter/incidents/migrations/0014_update_components_slack_groups.py,sha256=5tiQnrtOpYVUztFdvZ6xTUReuJfpDX0cOvqIvDZpBv0,8700
159
162
  firefighter/incidents/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
163
  firefighter/incidents/models/__init__.py,sha256=dCNP-zRYNNDOZB3JDDWp7vCl084Jh6RgDT_iP57RkOY,862
161
164
  firefighter/incidents/models/component.py,sha256=7GyXKNFk1MZns6RUGLpkNw5u6He7H9N1LexzXbG4sBM,7445
@@ -331,6 +334,7 @@ firefighter/slack/messages/slack_messages.py,sha256=8iYBfRDJw74wl_b5c5A-8_wJBNrT
331
334
  firefighter/slack/migrations/0001_initial_oss.py,sha256=XmTPgq7zCME2xDwzRFoVi4OegSIG9eSKoyTNoW05Qtg,12933
332
335
  firefighter/slack/migrations/0002_usergroup_tag.py,sha256=098tmGA81mT-R2uhb6uQfZ7gKiRG9bFhEwQ8rrp4SKM,583
333
336
  firefighter/slack/migrations/0003_alter_usergroup_tag.py,sha256=ncH3KUWEPZHlbdcAtOJ0KGt5H6EX-cKspTGU3osrAhE,591
337
+ firefighter/slack/migrations/0004_alter_usergroup_components.py,sha256=uCp1bhjcHRHbxlc_oewY__r4FY7eRHcoLSltJWgJ5x0,703
334
338
  firefighter/slack/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
335
339
  firefighter/slack/models/__init__.py,sha256=MGc4yuDnVhmAiHy1-5rjaLIfVv9JOup5arRutcUs8Ak,332
336
340
  firefighter/slack/models/conversation.py,sha256=euN3eS-9KUIxOErfxDhZ8nNdwkrp8JKefLJN6ypszXA,16190
@@ -440,8 +444,8 @@ firefighter_tests/test_slack/views/modals/test_open.py,sha256=Iatphd7vnrEMrv8ysK
440
444
  firefighter_tests/test_slack/views/modals/test_send_sos.py,sha256=_rE6jD-gOzcGyhlY0R9GzlGtPx65oOOguJYdENgxtLc,1289
441
445
  firefighter_tests/test_slack/views/modals/test_status.py,sha256=oQzPfwdg2tkbo9nfkO1GfS3WydxqSC6vy1AZjZDKT30,2226
442
446
  firefighter_tests/test_slack/views/modals/test_update_status.py,sha256=Y8Oa_fraj1vtaGig9Y28_6tOWvMrRPS-wyg3rY-DHBk,39380
443
- firefighter_incident-0.0.5.dist-info/METADATA,sha256=MrJmuQfWF1YiuJkIxwM4hJ5vmOnbW7YMg8ycN9fZZpM,5487
444
- firefighter_incident-0.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
445
- firefighter_incident-0.0.5.dist-info/entry_points.txt,sha256=c13meJbv7YNmYz7MipMOQwzQ5IeFOPXUBYAJ44XMQsM,61
446
- firefighter_incident-0.0.5.dist-info/licenses/LICENSE,sha256=krRiGp-a9-1nH1bWpBEdxyTKLhjLmn6DMVVoIb0zF90,1087
447
- firefighter_incident-0.0.5.dist-info/RECORD,,
447
+ firefighter_incident-0.0.6.dist-info/METADATA,sha256=nOfSjYKS60cgXoS8biKqN88DbhCpdAXuBfknqzCTEOA,5487
448
+ firefighter_incident-0.0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
449
+ firefighter_incident-0.0.6.dist-info/entry_points.txt,sha256=c13meJbv7YNmYz7MipMOQwzQ5IeFOPXUBYAJ44XMQsM,61
450
+ firefighter_incident-0.0.6.dist-info/licenses/LICENSE,sha256=krRiGp-a9-1nH1bWpBEdxyTKLhjLmn6DMVVoIb0zF90,1087
451
+ firefighter_incident-0.0.6.dist-info/RECORD,,