Skip to content

Commit

Permalink
Merge pull request #1072 from userlocalhost/feature/trigger/backward_…
Browse files Browse the repository at this point in the history
…compatibility

Added processing to invoke TriggerAction when an Entry is created or updated through APIv1 and ordinary view
  • Loading branch information
hinashi authored Feb 15, 2024
2 parents 10b7ea3 + 0b7d34f commit 2fa7374
Show file tree
Hide file tree
Showing 8 changed files with 383 additions and 20 deletions.
126 changes: 124 additions & 2 deletions api_v1/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from group.models import Group
from job.models import Job, JobOperation
from role.models import Role
from trigger import tasks as trigger_tasks
from trigger.models import TriggerCondition
from user.models import User


Expand Down Expand Up @@ -754,11 +756,25 @@ def test_get_entry(self):
self.assertEqual(len(results[0]["attrs"]), entry.attrs.count())
self.assertEqual(
[x for x in results[0]["attrs"] if x["name"] == "group"],
[{"name": "group", "value": "group1"}],
[
{
"id": entry.attrs.get(schema__name="group").id,
"schema_id": entry.attrs.get(schema__name="group").schema.id,
"name": "group",
"value": "group1",
}
],
)
self.assertEqual(
[x for x in results[0]["attrs"] if x["name"] == "groups"],
[{"name": "groups", "value": ["group1", "group2"]}],
[
{
"id": entry.attrs.get(schema__name="groups").id,
"schema_id": entry.attrs.get(schema__name="groups").schema.id,
"name": "groups",
"value": ["group1", "group2"],
}
],
)

# the case to specify only 'entry' parameter
Expand Down Expand Up @@ -1277,3 +1293,109 @@ def test_update_entry_that_has_deleted_attribute(self):
}
resp = self.client.post("/api/v1/entry", json.dumps(params), "application/json")
self.assertEqual(resp.status_code, 200)

@mock.patch(
"trigger.tasks.may_invoke_trigger.delay",
mock.Mock(side_effect=trigger_tasks.may_invoke_trigger),
)
def test_create_entry_when_trigger_is_set(self):
user = self.guest_login()

# Initialize Entity, Entries and TriggerConditoin
ref_entity = Entity.objects.create(name="Referred Entity", created_user=user)
ref_entry = Entry.objects.create(name="ref0", schema=ref_entity, created_user=user)
params = self.ALL_TYPED_ATTR_PARAMS_FOR_CREATING_ENTITY.copy()
for param in params:
if param["type"] & AttrTypeValue["object"]:
param["ref"] = ref_entity

entity = self.create_entity(**{"user": user, "name": "Entity", "attrs": params})
TriggerCondition.register(
entity,
[
{"attr_id": entity.attrs.get(name="val").id, "cond": "hoge"},
{"attr_id": entity.attrs.get(name="ref").id, "cond": ref_entry.id},
{"attr_id": entity.attrs.get(name="bool").id, "cond": True},
{"attr_id": entity.attrs.get(name="vals").id, "cond": "hoge"},
{"attr_id": entity.attrs.get(name="text").id, "cond": "hoge"},
{"attr_id": entity.attrs.get(name="refs").id, "cond": ref_entry.id},
],
[{"attr_id": entity.attrs.get(name="vals").id, "values": ["fuga", "piyo"]}],
)

# send a request to create an Entry with value that invoke TriggerAction
params = {
"name": "entry1",
"entity": entity.name,
"attrs": {
"val": "hoge",
"ref": "ref0",
"bool": True,
"vals": ["hoge", "fuga"],
"text": "hoge",
"refs": ["ref0"],
},
}
resp = self.client.post("/api/v1/entry", json.dumps(params), "application/json")
self.assertEqual(resp.status_code, 200)

# check trigger action was worked properly
job_query = Job.objects.filter(operation=JobOperation.MAY_INVOKE_TRIGGER.value)
self.assertEqual(job_query.count(), 1)
self.assertEqual(job_query.first().status, Job.STATUS["DONE"])

# check created Entry has expected value that is set by TriggerAction
entry = Entry.objects.get(id=resp.json()["result"])
self.assertEqual(entry.name, "entry1")
self.assertEqual(entry.get_attrv("val").value, "hoge")
self.assertEqual(
[x.referral.id for x in entry.get_attrv("refs").data_array.all()], [ref_entry.id]
)
self.assertEqual(
[x.value for x in entry.get_attrv("vals").data_array.all()], ["fuga", "piyo"]
)

@mock.patch(
"trigger.tasks.may_invoke_trigger.delay",
mock.Mock(side_effect=trigger_tasks.may_invoke_trigger),
)
def test_update_entry_when_trigger_is_set(self):
user = self.guest_login()

# Initialize Entity, Entry and TriggerConditoin
entity = self.create_entity(
**{
"user": user,
"name": "Entity",
"attrs": self.ALL_TYPED_ATTR_PARAMS_FOR_CREATING_ENTITY,
}
)
entry = self.add_entry(user, "entry", entity)
TriggerCondition.register(
entity,
[{"attr_id": entity.attrs.get(name="val").id, "cond": "hoge"}],
[{"attr_id": entity.attrs.get(name="vals").id, "values": ["fuga", "piyo"]}],
)

# send a request to edit created Entry with value toinvoke TriggerAction
params = {
"id": entry.id,
"name": "Changing Entry name",
"entity": entity.name,
"attrs": {
"val": "hoge",
},
}
resp = self.client.post("/api/v1/entry", json.dumps(params), "application/json")
self.assertEqual(resp.status_code, 200)

# check trigger action was worked properly
job_query = Job.objects.filter(operation=JobOperation.MAY_INVOKE_TRIGGER.value)
self.assertEqual(job_query.count(), 1)
self.assertEqual(job_query.first().status, Job.STATUS["DONE"])

# check created Entry has expected value that is set by TriggerAction
self.assertEqual(entry.get_attrv("val").value, "hoge")
self.assertEqual(
[x.value for x in entry.get_attrv("vals").data_array.all()], ["fuga", "piyo"]
)
42 changes: 42 additions & 0 deletions api_v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import custom_view
from airone.lib.acl import ACLType
from airone.lib.types import AttrTypeValue
from entity.models import Entity
from entry.models import Entry
from entry.settings import CONFIG as ENTRY_CONFIG
Expand All @@ -16,6 +17,41 @@


class EntryAPI(APIView):
def _be_compatible_with_trigger(self, entry, request_params):
entry_dict = entry.to_dict(self.request.user, with_metainfo=True)

def _get_value(attrname, attrtype, value):
if isinstance(value, list):
return [_get_value(attrname, attrtype, x) for x in value]

elif attrtype & AttrTypeValue["named"]:
[co_value] = list(value.values())

return co_value["id"] if co_value else None

elif attrtype & AttrTypeValue["object"]:
return value["id"] if value else None

else:
return value

trigger_params = []
for attrname in request_params["attrs"].keys():
try:
[(entity_attr_id, attrtype, attrvalue)] = [
(x["schema_id"], x["value"]["type"], x["value"]["value"])
for x in entry_dict["attrs"]
if x["name"] == attrname
]
except ValueError:
continue

trigger_params.append(
{"id": entity_attr_id, "value": _get_value(attrname, attrtype, attrvalue)}
)

return trigger_params

def post(self, request, format=None):
sel = PostEntrySerializer(data=request.data)

Expand Down Expand Up @@ -135,6 +171,12 @@ def _update_entry_name(entry):
# register target Entry to the Elasticsearch
entry.register_es()

# Create job for TriggerAction. Before calling, it's necessary to make parameters to pass
# to TriggerAction from raw_request_data by _be_compatible_with_trigger() method.
Job.new_invoke_trigger(
request.user, entry, self._be_compatible_with_trigger(entry, raw_request_data)
).run()

entry.del_status(Entry.STATUS_CREATING | Entry.STATUS_EDITING)

return Response(dict({"result": entry.id}, **resp_data))
Expand Down
4 changes: 4 additions & 0 deletions entry/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,8 @@ def to_dict(self, user, with_metainfo=False):
if attrv is None:
returning_attrs.append(
{
"id": attr.id,
"schema_id": attr.schema.id,
"name": attr.schema.name,
"value": AttributeValue.get_default_value(attr),
}
Expand All @@ -1636,6 +1638,8 @@ def to_dict(self, user, with_metainfo=False):
else:
returning_attrs.append(
{
"id": attr.id,
"schema_id": attr.schema.id,
"name": attr.schema.name,
"value": attrv.get_value(serialize=True, with_metainfo=with_metainfo),
}
Expand Down
16 changes: 11 additions & 5 deletions entry/tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3773,10 +3773,11 @@ def test_to_dict_entry_with_metainfo_param(self):
},
]
for info in expected_attrinfos:
self.assertEqual(
[x["value"] for x in ret_dict["attrs"] if x["name"] == info["name"]],
[info["value"]],
)
ret_attr_infos = [x for x in ret_dict["attrs"] if x["name"] == info["name"]]
self.assertEqual(len(ret_attr_infos), 1)
self.assertEqual(ret_attr_infos[0]["value"], info["value"])
self.assertIn("id", ret_attr_infos[0])
self.assertIn("schema_id", ret_attr_infos[0])

def test_to_dict_entry_for_checking_permission(self):
admin_user = User.objects.create(username="admin", is_superuser=True)
Expand Down Expand Up @@ -3829,7 +3830,12 @@ def test_to_dict_entry_for_checking_permission(self):
"name": entries[2].name,
"entity": {"id": public_entity.id, "name": public_entity.name},
"attrs": [
{"name": "attr1", "value": "hoge"},
{
"id": entries[2].attrs.get(schema__name="attr1").id,
"schema_id": entries[2].attrs.get(schema__name="attr1").schema.id,
"name": "attr1",
"value": "hoge",
},
],
},
)
Expand Down
Loading

0 comments on commit 2fa7374

Please sign in to comment.