Skip to content

Commit 8898949

Browse files
authored
[AAP-41483] feat: add edited_by to activation and allow is_enabled to be edited (#1232)
<!-- Mandatory: Provide a clear, concise description of the changes and their purpose --> The change allows user to directly start the activation after it is updated by one API call. It also shows who updates the activation by the edited_by field. It is to be used together with the already existing edited_at field. <!-- If applicable, provide a link to the issue that is being addressed --> [AAP-41483](https://issues.redhat.com/browse/AAP-41483) <!-- What is being changed? --> Added edited_by field to model Activation. Added is_enabled field to the editable list in the serializer <!-- Why is this change needed? --> <!-- How does this change address the issue? --> <!-- Does this change introduce any new dependencies, blockers or breaking changes? --> <!-- How it can be tested? --> To test the new feature, set is_enabled to true in the patch API body and verify the activation is restarted after it is updated. The patch API returns the updated activation includes the new field edited_by.
1 parent 33cb1a9 commit 8898949

File tree

5 files changed

+61
-4
lines changed

5 files changed

+61
-4
lines changed

src/aap_eda/api/serializers/activation.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ class ActivationListSerializer(serializers.ModelSerializer):
296296
)
297297
created_by = BasicUserFieldSerializer()
298298
modified_by = BasicUserFieldSerializer()
299+
edited_by = BasicUserFieldSerializer()
299300

300301
class Meta:
301302
model = models.Activation
@@ -321,6 +322,7 @@ class Meta:
321322
"edited_at",
322323
"created_by",
323324
"modified_by",
325+
"edited_by",
324326
"status_message",
325327
"awx_token_id",
326328
"log_level",
@@ -380,6 +382,7 @@ def to_representation(self, activation):
380382
"skip_audit_events": activation.skip_audit_events,
381383
"created_by": BasicUserSerializer(activation.created_by).data,
382384
"modified_by": BasicUserSerializer(activation.modified_by).data,
385+
"edited_by": BasicUserSerializer(activation.edited_by).data,
383386
}
384387

385388

@@ -565,6 +568,7 @@ class Meta:
565568
fields = [
566569
"name",
567570
"description",
571+
"is_enabled",
568572
"decision_environment_id",
569573
"rulebook_id",
570574
"extra_var",
@@ -629,6 +633,7 @@ def prepare_update(self, activation: models.Activation):
629633
rulebook_id = self.validated_data.get("rulebook_id")
630634
self.validated_data["user_id"] = self.context["request"].user.id
631635
self.validated_data["edited_at"] = timezone.now()
636+
self.validated_data["edited_by"] = self.context["request"].user
632637
if rulebook_id:
633638
rulebook = models.Rulebook.objects.get(id=rulebook_id)
634639
self.validated_data["rulebook_name"] = rulebook.name
@@ -822,6 +827,7 @@ class ActivationReadSerializer(serializers.ModelSerializer):
822827
)
823828
created_by = BasicUserFieldSerializer()
824829
modified_by = BasicUserFieldSerializer()
830+
edited_by = BasicUserFieldSerializer()
825831

826832
class Meta:
827833
model = models.Activation
@@ -850,6 +856,7 @@ class Meta:
850856
"edited_at",
851857
"created_by",
852858
"modified_by",
859+
"edited_by",
853860
"restarted_at",
854861
"status_message",
855862
"awx_token_id",
@@ -962,6 +969,7 @@ def to_representation(self, activation):
962969
"skip_audit_events": activation.skip_audit_events,
963970
"created_by": BasicUserSerializer(activation.created_by).data,
964971
"modified_by": BasicUserSerializer(activation.modified_by).data,
972+
"edited_by": BasicUserSerializer(activation.modified_by).data,
965973
}
966974

967975

src/aap_eda/api/views/activation.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ def partial_update(self, request, pk):
155155
ActivationStatus.WORKERS_OFFLINE,
156156
]:
157157
return Response(
158-
data="Activation is not in disabled mode or in stopped status",
158+
data=(
159+
"Activation is not in disabled mode and in stopped status"
160+
),
159161
status=status.HTTP_409_CONFLICT,
160162
)
161163
serializer = self.get_serializer(
@@ -165,6 +167,7 @@ def partial_update(self, request, pk):
165167
serializer.prepare_update(activation)
166168

167169
old_data = model_to_dict(activation)
170+
is_enabled = serializer.validated_data.pop("is_enabled", False)
168171
with transaction.atomic():
169172
serializer.update(activation, serializer.validated_data)
170173
check_related_permissions(
@@ -184,6 +187,11 @@ def partial_update(self, request, pk):
184187
)
185188
)
186189

190+
if is_enabled:
191+
response = self._start(activation)
192+
if response.status_code >= status.HTTP_400_BAD_REQUEST:
193+
return response
194+
187195
return Response(serializers.ActivationReadSerializer(activation).data)
188196

189197
@extend_schema(
@@ -346,7 +354,9 @@ def instances(self, request, id):
346354
@action(methods=["post"], detail=True, rbac_action=Action.ENABLE)
347355
def enable(self, request, pk):
348356
activation = self.get_object()
357+
return self._start(activation)
349358

359+
def _start(self, activation: models.Activation) -> Response:
350360
if activation.is_enabled:
351361
return Response(status=status.HTTP_204_NO_CONTENT)
352362

@@ -391,7 +401,7 @@ def enable(self, request, pk):
391401
)
392402
start_rulebook_process(
393403
process_parent_type=ProcessParentType.ACTIVATION,
394-
process_parent_id=pk,
404+
process_parent_id=activation.id,
395405
)
396406

397407
logger.info(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Generated by Django 4.2.16 on 2025-03-10 16:32
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
dependencies = [
10+
("core", "0059_alter_activation_user_alter_eventstream_owner"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="activation",
16+
name="edited_by",
17+
field=models.ForeignKey(
18+
default=None,
19+
editable=False,
20+
null=True,
21+
on_delete=django.db.models.deletion.SET_NULL,
22+
related_name="%s(class)s_edited+",
23+
to=settings.AUTH_USER_MODEL,
24+
),
25+
),
26+
]

src/aap_eda/core/models/activation.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ class Meta:
9999
edited_at = models.DateTimeField(null=True)
100100
status_updated_at = models.DateTimeField(null=True)
101101
status_message = models.TextField(null=True, default=None)
102+
edited_by = models.ForeignKey(
103+
User,
104+
related_name="%s(class)s_edited+",
105+
default=None,
106+
null=True,
107+
editable=False,
108+
on_delete=models.SET_NULL,
109+
)
102110
latest_instance = models.OneToOneField(
103111
"RulebookProcess",
104112
null=True,

tests/integration/api/test_activation.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,14 +1132,19 @@ def test_update_activation(
11321132

11331133
id = response.data["id"]
11341134
response = admin_client.patch(
1135-
f"{api_url_v1}/activations/{id}/", data={"name": "another_name"}
1135+
f"{api_url_v1}/activations/{id}/",
1136+
data={"name": "another_name", "is_enabled": True},
11361137
)
11371138
assert response.status_code == status.HTTP_200_OK
11381139
data = response.data
11391140
assert data["edited_at"] is not None
1141+
assert data["edited_by"]["username"] == "test.admin"
11401142
activation = models.Activation.objects.filter(id=data["id"]).first()
11411143
assert activation.name == "another_name"
11421144
assert activation.edited_at is not None
1145+
assert activation.edited_by.username == "test.admin"
1146+
assert activation.is_enabled is True
1147+
assert activation.status == enums.ActivationStatus.PENDING
11431148

11441149

11451150
@pytest.mark.django_db
@@ -1180,7 +1185,7 @@ def test_update_enabled_activation(
11801185
assert response.status_code == status.HTTP_409_CONFLICT
11811186
assert (
11821187
response.data
1183-
== "Activation is not in disabled mode or in stopped status"
1188+
== "Activation is not in disabled mode and in stopped status"
11841189
)
11851190

11861191

0 commit comments

Comments
 (0)