Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
aweiland committed Aug 1, 2024
2 parents 7758a45 + 8b7db60 commit 0c848ef
Show file tree
Hide file tree
Showing 3 changed files with 270 additions and 5 deletions.
56 changes: 51 additions & 5 deletions src/apps/answers/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,47 @@ async def _validate_applet_for_user_response(self, applet_id: uuid.UUID) -> None
if not roles:
raise UserDoesNotHavePermissionError()

async def _validate_temp_take_now_relation_between_subjects(
self, respondent_subject_id: uuid.UUID, source_subject_id: uuid.UUID, target_subject_id: uuid.UUID
) -> None:
relation_respondent_source = await SubjectsCrud(self.session).get_relation(
respondent_subject_id, source_subject_id
)

if is_take_now_relation(relation_respondent_source) and not is_valid_take_now_relation(
relation_respondent_source
):
raise ValidationError("Invalid temp take now relation between subjects")

relation_respondent_target = await SubjectsCrud(self.session).get_relation(
respondent_subject_id, target_subject_id
)

if is_take_now_relation(relation_respondent_target) and not is_valid_take_now_relation(
relation_respondent_target
):
raise ValidationError("Invalid temp take now relation between subjects")

async def _delete_temp_take_now_relation_if_exists(
self, respondent_subject: SubjectSchema, target_subject: SubjectSchema, source_subject: SubjectSchema
):
relation_respondent_target = await SubjectsCrud(self.session).get_relation(
source_subject_id=respondent_subject.id, target_subject_id=target_subject.id
)
relation_respondent_source = await SubjectsCrud(self.session).get_relation(
source_subject_id=respondent_subject.id, target_subject_id=source_subject.id
)

if relation_respondent_target and (
is_take_now_relation(relation_respondent_target) and is_valid_take_now_relation(relation_respondent_target)
):
await SubjectsCrud(self.session).delete_relation(target_subject.id, respondent_subject.id)

if relation_respondent_source and (
is_take_now_relation(relation_respondent_source) and is_valid_take_now_relation(relation_respondent_source)
):
await SubjectsCrud(self.session).delete_relation(source_subject.id, respondent_subject.id)

async def _get_answer_relation(
self,
respondent_subject: SubjectSchema,
Expand All @@ -234,16 +275,14 @@ async def _get_answer_relation(
Role.managers(),
)
if source_subject.id == target_subject.id:
if is_admin:
return Relation.self

raise ValidationError("Subject relation not found")
return Relation.self

relation = await SubjectsCrud(self.session).get_relation(source_subject.id, target_subject.id)
if not relation:
if is_admin:
return Relation.admin
raise ValidationError("Subject relation not found")

return Relation.other

return relation.relation

Expand Down Expand Up @@ -292,6 +331,10 @@ async def _create_answer(self, applet_answer: AppletAnswerCreate) -> AnswerSchem
else:
source_subject = respondent_subject

await self._validate_temp_take_now_relation_between_subjects(
respondent_subject.id, source_subject.id, target_subject.id
)

relation = await self._get_answer_relation(respondent_subject, source_subject, target_subject)
answer = await AnswersCRUD(self.answer_session).create(
AnswerSchema(
Expand Down Expand Up @@ -340,6 +383,9 @@ async def _create_answer(self, applet_answer: AppletAnswerCreate) -> AnswerSchem
answer.version,
applet_answer.alerts,
)

await self._delete_temp_take_now_relation_if_exists(respondent_subject, target_subject, source_subject)

return answer

async def validate_multiinformant_assessment(
Expand Down
218 changes: 218 additions & 0 deletions src/apps/answers/tests/test_answers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,224 @@ async def test_answer_get_export_data__answer_from_manager(
response.json()["result"]["answers"][0]["respondentSecretId"],
)

async def test_answer_activity_items_create_temporary_relation_success(
self,
tom: User,
answer_create_applet_one: AppletAnswerCreate,
client: TestClient,
session: AsyncSession,
sam: User,
applet_one: AppletFull,
applet_one_sam_respondent,
applet_one_sam_subject,
) -> None:
client.login(tom)
subject_service = SubjectsService(session, tom.id)

data = answer_create_applet_one.copy(deep=True)

client.login(sam)
subject_service = SubjectsService(session, sam.id)
source_subject = await subject_service.create(
SubjectCreate(
applet_id=applet_one.id,
creator_id=tom.id,
first_name="source",
last_name="subject",
secret_user_id=f"{uuid.uuid4()}",
)
)
target_subject = await subject_service.create(
SubjectCreate(
applet_id=applet_one.id,
creator_id=tom.id,
first_name="target",
last_name="subject",
secret_user_id=f"{uuid.uuid4()}",
)
)
# create a relation between respondent and source
await subject_service.create_relation(
relation="take-now",
source_subject_id=applet_one_sam_subject.id,
subject_id=source_subject.id,
meta={
"expiresAt": (datetime.datetime.now() + datetime.timedelta(days=1)).isoformat(),
},
)
# create a relation between respondent and target
await subject_service.create_relation(
relation="take-now",
source_subject_id=applet_one_sam_subject.id,
subject_id=target_subject.id,
meta={
"expiresAt": (datetime.datetime.now() + datetime.timedelta(days=1)).isoformat(),
},
)

await subject_service.create_relation(
relation="take-now",
source_subject_id=source_subject.id,
subject_id=target_subject.id,
meta={
"expiresAt": (datetime.datetime.now() + datetime.timedelta(days=1)).isoformat(),
},
)

data.source_subject_id = source_subject.id
data.target_subject_id = target_subject.id
data.input_subject_id = applet_one_sam_subject.id

# before posting the request, make sure that there is a temporary relation
existing_relation = await subject_service.get_relation(applet_one_sam_subject.id, target_subject.id)
assert existing_relation

response = await client.post(self.answer_url, data=data)

assert response.status_code == http.HTTPStatus.CREATED, response.json()
# after submitting make sure that the relation has been deleted
relation_exists = await subject_service.get_relation(applet_one_sam_subject.id, target_subject.id)
assert not relation_exists

async def test_answer_activity_items_create_permanent_relation_success(
self,
tom: User,
answer_create_applet_one: AppletAnswerCreate,
client: TestClient,
session: AsyncSession,
sam: User,
applet_one: AppletFull,
applet_one_sam_respondent,
applet_one_sam_subject,
) -> None:
client.login(tom)
subject_service = SubjectsService(session, tom.id)

data = answer_create_applet_one.copy(deep=True)

client.login(sam)
subject_service = SubjectsService(session, sam.id)
source_subject = await subject_service.create(
SubjectCreate(
applet_id=applet_one.id,
creator_id=tom.id,
first_name="source",
last_name="subject",
secret_user_id=f"{uuid.uuid4()}",
)
)
target_subject = await subject_service.create(
SubjectCreate(
applet_id=applet_one.id,
creator_id=tom.id,
first_name="target",
last_name="subject",
secret_user_id=f"{uuid.uuid4()}",
)
)
# create a relation between respondent and source
await subject_service.create_relation(
relation="parent", source_subject_id=applet_one_sam_subject.id, subject_id=source_subject.id
)
# create a relation between respondent and target
await subject_service.create_relation(
relation="parent", source_subject_id=applet_one_sam_subject.id, subject_id=target_subject.id
)

await subject_service.create_relation(
relation="parent", source_subject_id=source_subject.id, subject_id=target_subject.id
)

data.source_subject_id = source_subject.id
data.target_subject_id = target_subject.id
data.input_subject_id = applet_one_sam_subject.id

# before posting the request, make sure that there is a temporary relation
existing_relation = await subject_service.get_relation(applet_one_sam_subject.id, target_subject.id)
assert existing_relation

response = await client.post(self.answer_url, data=data)

assert response.status_code == http.HTTPStatus.CREATED, response.json()
# after submitting make sure that the relation has not been deleted
relation_exists = await subject_service.get_relation(applet_one_sam_subject.id, target_subject.id)
assert relation_exists

async def test_answer_activity_items_create_expired_temporary_relation_fail(
self,
tom: User,
answer_create_applet_one: AppletAnswerCreate,
client: TestClient,
session: AsyncSession,
sam: User,
applet_one: AppletFull,
applet_one_sam_respondent,
applet_one_sam_subject,
) -> None:
client.login(tom)
subject_service = SubjectsService(session, tom.id)

data = answer_create_applet_one.copy(deep=True)

client.login(sam)
subject_service = SubjectsService(session, sam.id)
source_subject = await subject_service.create(
SubjectCreate(
applet_id=applet_one.id,
creator_id=tom.id,
first_name="source",
last_name="subject",
secret_user_id=f"{uuid.uuid4()}",
)
)
target_subject = await subject_service.create(
SubjectCreate(
applet_id=applet_one.id,
creator_id=tom.id,
first_name="target",
last_name="subject",
secret_user_id=f"{uuid.uuid4()}",
)
)
# create a relation between respondent and source
await subject_service.create_relation(
relation="take-now",
source_subject_id=applet_one_sam_subject.id,
subject_id=source_subject.id,
meta={
"expiresAt": (datetime.datetime.now() - datetime.timedelta(days=1)).isoformat(),
},
)
# create a relation between respondent and target
await subject_service.create_relation(
relation="take-now",
source_subject_id=applet_one_sam_subject.id,
subject_id=target_subject.id,
meta={
"expiresAt": (datetime.datetime.now() - datetime.timedelta(days=1)).isoformat(),
},
)

await subject_service.create_relation(
relation="take-now",
source_subject_id=source_subject.id,
subject_id=target_subject.id,
meta={
"expiresAt": (datetime.datetime.now() - datetime.timedelta(days=1)).isoformat(),
},
)

data.source_subject_id = source_subject.id
data.target_subject_id = target_subject.id
data.input_subject_id = applet_one_sam_subject.id

# before posting the request, make sure that there is a temporary relation
existing_relation = await subject_service.get_relation(applet_one_sam_subject.id, target_subject.id)
assert existing_relation

response = await client.post(self.answer_url, data=data)
assert response.status_code == http.HTTPStatus.BAD_REQUEST, response.json()

async def test_answer_get_export_data__answer_from_respondent(
self,
client: TestClient,
Expand Down
1 change: 1 addition & 0 deletions src/apps/subjects/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SubjectStatus(str, Enum):
class Relation(str, Enum):
self = "self"
admin = "admin"
other = "other"


class SubjectTag(str, Enum):
Expand Down

0 comments on commit 0c848ef

Please sign in to comment.