API: event-reference-requests #520

This commit is contained in:
Daniel Grams 2023-07-13 08:58:04 +02:00
parent 5a60801a78
commit ea17578890
18 changed files with 771 additions and 76 deletions

View File

@ -133,6 +133,8 @@ scope_list = [
"eventlist:write",
"customwidget:write",
"eventreference:write",
"eventreferencerequest:read",
"eventreferencerequest:write",
]
scopes = {k: get_localized_scope(k) for v, k in enumerate(scope_list)}
@ -220,6 +222,7 @@ import project.api.event_category.resources
import project.api.event_date.resources
import project.api.event_list.resources
import project.api.event_reference.resources
import project.api.event_reference_request.resources
import project.api.organization.resources
import project.api.organization_invitation.resources
import project.api.organization_relation.resources

View File

@ -0,0 +1,127 @@
from flask import abort, make_response
from flask_apispec import doc, marshal_with, use_kwargs
from marshmallow import ValidationError
from project import db
from project.access import access_or_401, has_access, login_api_user_or_401
from project.api import add_api_resource
from project.api.event_reference.schemas import EventReferenceIdSchema
from project.api.event_reference_request.schemas import (
EventReferenceRequestRejectRequestSchema,
EventReferenceRequestSchema,
EventReferenceRequestVerifyRequestSchema,
)
from project.api.resources import BaseResource, require_api_access
from project.models import EventReferenceRequest
from project.models.event_reference_request import EventReferenceRequestReviewStatus
from project.services.reference import create_event_reference_for_request
from project.views.reference_request_review import (
send_reference_request_review_status_mails,
)
class EventReferenceRequestResource(BaseResource):
@doc(summary="Get event reference request", tags=["Event Reference Requests"])
@marshal_with(EventReferenceRequestSchema)
@require_api_access("eventreferencerequest:read")
def get(self, id):
login_api_user_or_401()
reference_request = EventReferenceRequest.query.get_or_404(id)
if not has_access(
reference_request.event.admin_unit, "reference_request:read"
) and not has_access(reference_request.admin_unit, "reference_request:verify"):
abort(401)
return reference_request
@doc(
summary="Delete reference request",
tags=["Event Reference Requests"],
)
@marshal_with(None, 204)
@require_api_access("eventreferencerequest:write")
def delete(self, id):
login_api_user_or_401()
reference_request = EventReferenceRequest.query.get_or_404(id)
access_or_401(reference_request.event.admin_unit, "reference_request:delete")
db.session.delete(reference_request)
db.session.commit()
return make_response("", 204)
class EventReferenceRequestVerifyResource(BaseResource):
@doc(
summary="Verify event reference request. Returns reference id.",
tags=["Event Reference Requests"],
)
@use_kwargs(EventReferenceRequestVerifyRequestSchema, location="json", apply=True)
@marshal_with(EventReferenceIdSchema, 201)
@require_api_access("eventreferencerequest:write")
def post(self, id, **kwargs):
login_api_user_or_401()
reference_request = EventReferenceRequest.query.get_or_404(id)
access_or_401(reference_request.admin_unit, "reference_request:verify")
if (
reference_request.review_status
== EventReferenceRequestReviewStatus.verified
): # pragma: no cover
raise ValidationError("Request already verified")
reference_request.review_status = EventReferenceRequestReviewStatus.verified
reference = create_event_reference_for_request(reference_request)
reference.rating = kwargs.get("rating", reference.rating)
db.session.commit()
send_reference_request_review_status_mails(reference_request)
return reference, 201
class EventReferenceRequestRejectResource(BaseResource):
@doc(
summary="Reject event reference request",
tags=["Event Reference Requests"],
)
@use_kwargs(EventReferenceRequestRejectRequestSchema, location="json", apply=False)
@marshal_with(None, 204)
@require_api_access("eventreferencerequest:write")
def post(self, id):
login_api_user_or_401()
reference_request = EventReferenceRequest.query.get_or_404(id)
access_or_401(reference_request.admin_unit, "reference_request:verify")
if (
reference_request.review_status
== EventReferenceRequestReviewStatus.verified
): # pragma: no cover
raise ValidationError("Request already verified")
reference_request = self.update_instance(
EventReferenceRequestRejectRequestSchema, instance=reference_request
)
reference_request.review_status = EventReferenceRequestReviewStatus.rejected
db.session.commit()
return make_response("", 204)
add_api_resource(
EventReferenceRequestResource,
"/event-reference-requests/<int:id>",
"api_v1_event_reference_request",
)
add_api_resource(
EventReferenceRequestVerifyResource,
"/event-reference-requests/<int:id>/verify",
"api_v1_event_reference_request_verify",
)
add_api_resource(
EventReferenceRequestRejectResource,
"/event-reference-requests/<int:id>/reject",
"api_v1_event_reference_request_reject",
)

View File

@ -0,0 +1,126 @@
from marshmallow import fields, validate
from marshmallow_enum import EnumField
from project.api import marshmallow
from project.api.event.schemas import EventRefSchema, EventWriteIdSchema
from project.api.organization.schemas import (
OrganizationRefSchema,
OrganizationWriteIdSchema,
)
from project.api.schemas import (
IdSchemaMixin,
PaginationRequestSchema,
PaginationResponseSchema,
SQLAlchemyBaseSchema,
TrackableRequestSchemaMixin,
TrackableSchemaMixin,
)
from project.models import EventReferenceRequest
from project.models.event_reference_request import (
EventReferenceRequestRejectionReason,
EventReferenceRequestReviewStatus,
)
class EventReferenceRequestModelSchema(SQLAlchemyBaseSchema):
class Meta:
model = EventReferenceRequest
load_instance = True
class EventReferenceRequestIdSchema(EventReferenceRequestModelSchema, IdSchemaMixin):
pass
class EventReferenceRequestBaseSchemaMixin(TrackableSchemaMixin):
review_status = EnumField(
EventReferenceRequestReviewStatus,
load_default=EventReferenceRequestReviewStatus.inbox,
)
rejection_reason = EnumField(
EventReferenceRequestRejectionReason,
)
class EventReferenceRequestRefSchema(
EventReferenceRequestIdSchema, TrackableSchemaMixin
):
event = fields.Nested(EventRefSchema)
class EventReferenceRequestSchema(
EventReferenceRequestIdSchema, EventReferenceRequestBaseSchemaMixin
):
event = fields.Nested(EventRefSchema)
organization = fields.Nested(OrganizationRefSchema, attribute="admin_unit")
class EventReferenceRequestDumpSchema(EventReferenceRequestIdSchema):
event_id = marshmallow.auto_field()
organization_id = fields.Int(attribute="admin_unit_id")
class EventReferenceRequestListRequestSchema(
PaginationRequestSchema, TrackableRequestSchemaMixin
):
sort = fields.Str(
metadata={"description": "Sort result items."},
validate=validate.OneOf(["-created_at", "-updated_at", "-last_modified_at"]),
)
class EventReferenceRequestListResponseSchema(PaginationResponseSchema):
items = fields.List(
fields.Nested(EventReferenceRequestRefSchema),
metadata={"description": "Event reference requests"},
)
class EventReferenceRequestWriteSchemaMixin(object):
event = fields.Nested(
EventWriteIdSchema,
required=True,
metadata={"description": "Event to reference"},
)
target_organization = fields.Nested(
OrganizationWriteIdSchema,
attribute="admin_unit",
required=True,
metadata={"description": "Target organization."},
)
class EventReferenceRequestPostRequestSchema(
EventReferenceRequestModelSchema,
EventReferenceRequestWriteSchemaMixin,
):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.make_post_schema()
class EventReferenceRequestVerifyRequestSchema(SQLAlchemyBaseSchema):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.make_post_schema()
rating = fields.Int(
load_default=50,
dump_default=50,
validate=validate.OneOf([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]),
metadata={
"description": "How relevant the event is to your organization. 0 (Little relevant), 50 (Default), 100 (Highlight)."
},
)
class EventReferenceRequestRejectRequestSchema(
EventReferenceRequestModelSchema,
):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.make_post_schema()
rejection_reason = EnumField(
EventReferenceRequestRejectionReason,
)

View File

@ -6,6 +6,7 @@ from sqlalchemy import and_
from project import db
from project.access import (
access_or_401,
can_request_event_reference,
can_verify_admin_unit,
get_admin_unit_for_manage_or_404,
login_api_user,
@ -45,6 +46,12 @@ from project.api.event_reference.schemas import (
EventReferenceListRequestSchema,
EventReferenceListResponseSchema,
)
from project.api.event_reference_request.schemas import (
EventReferenceRequestIdSchema,
EventReferenceRequestListRequestSchema,
EventReferenceRequestListResponseSchema,
EventReferenceRequestPostRequestSchema,
)
from project.api.organization.schemas import (
OrganizationListRequestSchema,
OrganizationListResponseSchema,
@ -92,16 +99,23 @@ from project.services.importer.event_importer import EventImporter
from project.services.reference import (
get_reference_incoming_query,
get_reference_outgoing_query,
get_reference_requests_incoming_query,
get_reference_requests_outgoing_query,
get_relation_outgoing_query,
)
from project.services.search_params import (
AdminUnitSearchParams,
EventPlaceSearchParams,
EventReferenceRequestSearchParams,
EventReferenceSearchParams,
EventSearchParams,
OrganizerSearchParams,
TrackableSearchParams,
)
from project.views.reference_request import (
handle_request_according_to_relation,
send_reference_request_mails,
)
from project.views.utils import get_current_admin_unit_for_api, send_mail_async
@ -375,10 +389,78 @@ class OrganizationOutgoingEventReferenceListResource(BaseResource):
def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id)
pagination = get_reference_outgoing_query(admin_unit).paginate()
params = EventReferenceSearchParams()
params.load_from_request(**kwargs)
params.admin_unit_id = admin_unit.id
pagination = get_reference_outgoing_query(params).paginate()
return pagination
class OrganizationIncomingEventReferenceRequestListResource(BaseResource):
@doc(
summary="List incoming event reference requests of organization",
tags=["Organizations", "Event Reference Requests"],
)
@use_kwargs(EventReferenceRequestListRequestSchema, location=("query"))
@marshal_with(EventReferenceRequestListResponseSchema)
@require_api_access("eventreferencerequest:read")
def get(self, id, **kwargs):
login_api_user_or_401()
admin_unit = get_admin_unit_for_manage_or_404(id)
params = EventReferenceRequestSearchParams()
params.load_from_request(**kwargs)
params.admin_unit_id = admin_unit.id
pagination = get_reference_requests_incoming_query(params).paginate()
return pagination
class OrganizationOutgoingEventReferenceRequestListResource(BaseResource):
@doc(
summary="List outgoing event reference requests of organization",
tags=["Organizations", "Event Reference Requests"],
)
@use_kwargs(EventReferenceRequestListRequestSchema, location=("query"))
@marshal_with(EventReferenceRequestListResponseSchema)
@require_api_access("eventreferencerequest:read")
def get(self, id, **kwargs):
login_api_user_or_401()
admin_unit = get_admin_unit_for_manage_or_404(id)
params = EventReferenceRequestSearchParams()
params.load_from_request(**kwargs)
params.admin_unit_id = admin_unit.id
pagination = get_reference_requests_outgoing_query(params).paginate()
return pagination
@doc(
summary="Add reference request",
tags=["Organizations", "Event Reference Requests"],
)
@use_kwargs(EventReferenceRequestPostRequestSchema, location="json", apply=False)
@marshal_with(EventReferenceRequestIdSchema, 201)
@require_api_access("eventreferencerequest:write")
def post(self, id):
login_api_user_or_401()
admin_unit = get_admin_unit_for_manage_or_404(id)
reference_request = self.create_instance(EventReferenceRequestPostRequestSchema)
event = reference_request.event
if event.admin_unit_id != admin_unit.id:
abort(404)
if not can_request_event_reference(event):
abort(401)
db.session.add(reference_request)
reference, _ = handle_request_according_to_relation(reference_request, event)
db.session.commit()
send_reference_request_mails(reference_request, reference)
return reference_request, 201
class OrganizationOutgoingRelationListResource(BaseResource):
@doc(
summary="List outgoing relations of organization",
@ -626,6 +708,18 @@ add_api_resource(
"/organizations/<int:id>/event-references/outgoing",
"api_v1_organization_outgoing_event_reference_list",
)
add_api_resource(
OrganizationIncomingEventReferenceRequestListResource,
"/organizations/<int:id>/event-reference-requests/incoming",
"api_v1_organization_incoming_event_reference_request_list",
)
add_api_resource(
OrganizationOutgoingEventReferenceRequestListResource,
"/organizations/<int:id>/event-reference-requests/outgoing",
"api_v1_organization_outgoing_event_reference_request_list",
)
add_api_resource(
OrganizationOutgoingRelationListResource,
"/organizations/<int:id>/relations/outgoing",

View File

@ -66,4 +66,10 @@ class AdminUnitVerificationRequest(db.Model, TrackableMixin):
@listens_for(AdminUnitVerificationRequest, "before_insert")
@listens_for(AdminUnitVerificationRequest, "before_update")
def before_saving_admin_unit_verification_request(mapper, connect, self):
if self.review_status != AdminUnitVerificationRequestReviewStatus.rejected:
self.rejection_reason = None
if self.rejection_reason == 0:
self.rejection_reason = None
self.validate()

View File

@ -1,6 +1,7 @@
from enum import IntEnum
from sqlalchemy import Column, Integer, UniqueConstraint
from sqlalchemy.event import listens_for
from sqlalchemy.ext.hybrid import hybrid_property
from project import db
@ -38,3 +39,13 @@ class EventReferenceRequest(db.Model, TrackableMixin):
@hybrid_property
def verified(self):
return self.review_status == EventReferenceRequestReviewStatus.verified
@listens_for(EventReferenceRequest, "before_insert")
@listens_for(EventReferenceRequest, "before_update")
def before_saving_event_reference_request(mapper, connect, self):
if self.review_status != EventReferenceRequestReviewStatus.rejected:
self.rejection_reason = None
if self.rejection_reason == 0:
self.rejection_reason = None

View File

@ -10,7 +10,10 @@ from project.models import (
EventReferenceRequestReviewStatus,
)
from project.models.admin_unit import AdminUnit
from project.services.search_params import EventReferenceSearchParams
from project.services.search_params import (
EventReferenceRequestSearchParams,
EventReferenceSearchParams,
)
def create_event_reference_for_request(request):
@ -49,22 +52,42 @@ def get_reference_incoming_query(params: EventReferenceSearchParams):
return result
def get_reference_outgoing_query(admin_unit):
return (
EventReference.query.join(Event)
.filter(Event.admin_unit_id == admin_unit.id)
.order_by(EventReference.created_at.desc())
)
def get_reference_outgoing_query(params: EventReferenceSearchParams):
result = EventReference.query.join(Event)
if params.admin_unit_id:
result = result.filter(Event.admin_unit_id == params.admin_unit_id)
result = params.get_trackable_query(result, EventReference)
result = params.get_trackable_order_by(result, EventReference)
result = result.order_by(EventReference.created_at.desc())
return result
def get_reference_requests_incoming_query(admin_unit):
return EventReferenceRequest.query.filter(
and_(
EventReferenceRequest.review_status
!= EventReferenceRequestReviewStatus.verified,
EventReferenceRequest.admin_unit_id == admin_unit.id,
def get_reference_requests_incoming_query(params: EventReferenceRequestSearchParams):
result = EventReferenceRequest.query
if params.admin_unit_id:
result = result.filter(
EventReferenceRequest.admin_unit_id == params.admin_unit_id
)
)
result = params.get_trackable_query(result, EventReferenceRequest)
result = params.get_trackable_order_by(result, EventReferenceRequest)
result = result.order_by(EventReferenceRequest.created_at.desc())
return result
def get_reference_requests_outgoing_query(params: EventReferenceRequestSearchParams):
result = EventReferenceRequest.query.join(Event)
if params.admin_unit_id:
result = result.filter(Event.admin_unit_id == params.admin_unit_id)
result = params.get_trackable_query(result, EventReferenceRequest)
result = params.get_trackable_order_by(result, EventReferenceRequest)
result = result.order_by(EventReferenceRequest.created_at.desc())
return result
def get_reference_requests_incoming_badge_query(admin_unit):

View File

@ -63,6 +63,13 @@ class EventReferenceSearchParams(TrackableSearchParams):
self.admin_unit_id = None
class EventReferenceRequestSearchParams(TrackableSearchParams):
def __init__(self):
super().__init__()
self.admin_unit_id = None
self.review_status = None
class AdminUnitSearchParams(TrackableSearchParams):
def __init__(self):
super().__init__()

View File

@ -45,7 +45,10 @@ from project.services.event import (
)
from project.utils import get_event_category_name, get_place_str
from project.views.event_suggestion import send_event_suggestion_review_status_mail
from project.views.reference_request import handle_request_according_to_relation
from project.views.reference_request import (
handle_request_according_to_relation,
send_reference_request_mails,
)
from project.views.utils import (
flash_errors,
flash_message,
@ -222,8 +225,11 @@ def event_create_for_admin_unit_id(id):
reference_request.event_id = event.id
reference_request.admin_unit_id = target_admin_unit_id
db.session.add(reference_request)
msg = handle_request_according_to_relation(reference_request, event)
reference, msg = handle_request_according_to_relation(
reference_request, event
)
db.session.commit()
send_reference_request_mails(reference_request, reference)
flash(msg, "success")
return redirect(url_for("event_actions", event_id=event.id))

View File

@ -128,7 +128,10 @@ def manage_admin_unit_references_incoming(id):
@auth_required()
def manage_admin_unit_references_outgoing(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
references = get_reference_outgoing_query(admin_unit).paginate()
params = EventReferenceSearchParams()
params.admin_unit_id = admin_unit.id
references = get_reference_outgoing_query(params).paginate()
return render_template(
"manage/references_outgoing.html",

View File

@ -2,7 +2,6 @@ from flask import abort, flash, redirect, render_template, url_for
from flask_babel import gettext
from flask_security import auth_required
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.sql import desc
from project import app, db
from project.access import (
@ -16,6 +15,7 @@ from project.models import (
EventReferenceRequest,
EventReferenceRequestReviewStatus,
)
from project.models.event_reference import EventReference
from project.services.admin_unit import (
get_admin_unit_by_id,
get_admin_unit_relation,
@ -24,7 +24,9 @@ from project.services.admin_unit import (
from project.services.reference import (
create_event_reference_for_request,
get_reference_requests_incoming_query,
get_reference_requests_outgoing_query,
)
from project.services.search_params import EventReferenceRequestSearchParams
from project.views.utils import (
flash_errors,
get_pagination_urls,
@ -37,11 +39,10 @@ from project.views.utils import (
@auth_required()
def manage_admin_unit_reference_requests_incoming(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = (
get_reference_requests_incoming_query(admin_unit)
.order_by(desc(EventReferenceRequest.created_at))
.paginate()
)
params = EventReferenceRequestSearchParams()
params.admin_unit_id = admin_unit.id
requests = get_reference_requests_incoming_query(params).paginate()
return render_template(
"manage/reference_requests_incoming.html",
@ -55,12 +56,10 @@ def manage_admin_unit_reference_requests_incoming(id):
@auth_required()
def manage_admin_unit_reference_requests_outgoing(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = (
EventReferenceRequest.query.join(Event)
.filter(Event.admin_unit_id == admin_unit.id)
.order_by(desc(EventReferenceRequest.created_at))
.paginate()
)
params = EventReferenceRequestSearchParams()
params.admin_unit_id = admin_unit.id
requests = get_reference_requests_outgoing_query(params).paginate()
return render_template(
"manage/reference_requests_outgoing.html",
@ -99,15 +98,18 @@ def event_reference_request_create(event_id):
)
if form.validate_on_submit():
request = EventReferenceRequest()
form.populate_obj(request)
request.event = event
reference_request = EventReferenceRequest()
form.populate_obj(reference_request)
reference_request.event = event
try:
db.session.add(request)
db.session.add(reference_request)
msg = handle_request_according_to_relation(request, event)
reference, msg = handle_request_according_to_relation(
reference_request, event
)
db.session.commit()
send_reference_request_mails(reference_request, reference)
flash(msg, "success")
return redirect(
url_for(
@ -127,30 +129,62 @@ def event_reference_request_create(event_id):
def handle_request_according_to_relation(
request: EventReferenceRequest, event: Event
) -> str:
admin_unit = get_admin_unit_by_id(request.admin_unit_id)
relation = get_admin_unit_relation(request.admin_unit_id, event.admin_unit_id)
admin_unit = (
request.admin_unit
if request.admin_unit
else get_admin_unit_by_id(request.admin_unit_id)
)
relation = get_admin_unit_relation(admin_unit.id, event.admin_unit_id)
auto_verify = relation and relation.auto_verify_event_reference_requests
reference = None
if auto_verify:
request.review_status = EventReferenceRequestReviewStatus.verified
reference = create_event_reference_for_request(request)
send_auto_reference_inbox_mails(reference)
msg = gettext(
"%(organization)s accepted your reference request",
organization=admin_unit.name,
)
else:
request.review_status = EventReferenceRequestReviewStatus.inbox
send_reference_request_inbox_mails(request)
msg = gettext(
"Reference request to %(organization)s successfully created. You will be notified after the other organization reviews the event.",
organization=admin_unit.name,
)
return msg
return reference, msg
def send_member_reference_request_verify_mails(
def send_reference_request_mails(
request: EventReferenceRequest, reference: EventReference
):
if reference:
_send_auto_reference_mails(reference)
else:
_send_reference_request_inbox_mails(request)
def _send_reference_request_inbox_mails(request):
_send_member_reference_request_verify_mails(
request.admin_unit_id,
gettext("New reference request"),
"reference_request_notice",
request=request,
)
def _send_auto_reference_mails(reference):
_send_member_reference_request_verify_mails(
reference.admin_unit_id,
gettext("New reference automatically verified"),
"reference_auto_verified_notice",
reference=reference,
)
def _send_member_reference_request_verify_mails(
admin_unit_id, subject, template, **context
):
# Benachrichtige alle Mitglieder der AdminUnit, die Requests verifizieren können
@ -160,21 +194,3 @@ def send_member_reference_request_verify_mails(
emails = list(map(lambda member: member.user.email, members))
send_mails_async(emails, subject, template, **context)
def send_reference_request_inbox_mails(request):
send_member_reference_request_verify_mails(
request.admin_unit_id,
gettext("New reference request"),
"reference_request_notice",
request=request,
)
def send_auto_reference_inbox_mails(reference):
send_member_reference_request_verify_mails(
reference.admin_unit_id,
gettext("New reference automatically verified"),
"reference_auto_verified_notice",
reference=reference,
)

View File

@ -44,12 +44,6 @@ def event_reference_request_review(id):
if form.validate_on_submit():
form.populate_obj(request)
if request.review_status != EventReferenceRequestReviewStatus.rejected:
request.rejection_reason = None
if request.rejection_reason == 0:
request.rejection_reason = None
try:
if request.review_status == EventReferenceRequestReviewStatus.verified:
reference = create_event_reference_for_request(request)

View File

@ -38,12 +38,6 @@ def admin_unit_verification_request_review(id):
if form.validate_on_submit():
form.populate_obj(request)
if request.review_status != AdminUnitVerificationRequestReviewStatus.rejected:
request.rejection_reason = None
if request.rejection_reason == 0:
request.rejection_reason = None
try:
if (
request.review_status

View File

@ -0,0 +1,126 @@
from tests.seeder import Seeder
from tests.utils import UtilActions
def test_read(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
(
other_user_id,
other_admin_unit_id,
event_id,
reference_request_id,
) = seeder.create_outgoing_reference_request(admin_unit_id)
url = utils.get_url("api_v1_event_reference_request", id=reference_request_id)
utils.get_json_ok(url)
def test_read_noAccess(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
third_user_id = seeder.create_user("third@test.de")
third_admin_unit_id = seeder.create_admin_unit(third_user_id, "Third Crew")
(
other_user_id,
other_admin_unit_id,
event_id,
reference_request_id,
) = seeder.create_outgoing_reference_request(third_admin_unit_id)
url = utils.get_url("api_v1_event_reference_request", id=reference_request_id)
response = utils.get_json(url)
utils.assert_response_unauthorized(response)
def test_delete(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
(
other_user_id,
other_admin_unit_id,
event_id,
reference_request_id,
) = seeder.create_outgoing_reference_request(admin_unit_id)
url = utils.get_url("api_v1_event_reference_request", id=reference_request_id)
response = utils.delete(url)
utils.assert_response_no_content(response)
with app.app_context():
from project.models import EventReferenceRequest
reference = db.session.get(EventReferenceRequest, reference_request_id)
assert reference is None
def test_verify(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
(
other_user_id,
other_admin_unit_id,
event_id,
reference_request_id,
) = seeder.create_incoming_reference_request(admin_unit_id)
url = utils.get_url(
"api_v1_event_reference_request_verify", id=reference_request_id
)
data = {
"rating": 70,
}
response = utils.post_json(url, data)
utils.assert_response_created(response)
assert "id" in response.json
with app.app_context():
from project.models import (
EventReference,
EventReferenceRequest,
EventReferenceRequestReviewStatus,
)
reference_request = db.session.get(EventReferenceRequest, reference_request_id)
assert (
reference_request.review_status
== EventReferenceRequestReviewStatus.verified
)
reference = db.session.get(EventReference, int(response.json["id"]))
assert reference is not None
assert reference.admin_unit_id == admin_unit_id
assert reference.event_id == event_id
assert reference.rating == 70
def test_reject(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
(
other_user_id,
other_admin_unit_id,
event_id,
reference_request_id,
) = seeder.create_incoming_reference_request(admin_unit_id)
url = utils.get_url(
"api_v1_event_reference_request_reject", id=reference_request_id
)
data = {
"rejection_reason": "duplicate",
}
response = utils.post_json(url, data)
utils.assert_response_no_content(response)
with app.app_context():
from project.models import (
EventReferenceRequest,
EventReferenceRequestRejectionReason,
EventReferenceRequestReviewStatus,
)
reference_request = db.session.get(EventReferenceRequest, reference_request_id)
assert (
reference_request.review_status
== EventReferenceRequestReviewStatus.rejected
)
assert (
reference_request.rejection_reason
== EventReferenceRequestRejectionReason.duplicate
)

View File

@ -508,6 +508,160 @@ def test_references_outgoing(client, seeder: Seeder, utils: UtilActions):
utils.get_json_ok(url)
def test_reference_requests_incoming(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
seeder.create_incoming_reference_request(admin_unit_id)
url = utils.get_url(
"api_v1_organization_incoming_event_reference_request_list",
id=admin_unit_id,
)
utils.get_json_ok(url)
def test_reference_requests_outgoing(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
seeder.create_outgoing_reference_request(admin_unit_id)
url = utils.get_url(
"api_v1_organization_outgoing_event_reference_request_list",
id=admin_unit_id,
)
utils.get_json_ok(url)
def test_reference_requests_outgoing_post(
client, app, seeder: Seeder, utils: UtilActions, db, mocker
):
mail_mock = utils.mock_send_mails_async(mocker)
user_id, admin_unit_id = seeder.setup_api_access()
other_user_id = seeder.create_user("other@test.de")
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
event_id = seeder.create_event(admin_unit_id)
url = utils.get_url(
"api_v1_organization_outgoing_event_reference_request_list",
id=admin_unit_id,
)
data = {
"event": {"id": event_id},
"target_organization": {"id": other_admin_unit_id},
}
response = utils.post_json(url, data)
utils.assert_response_created(response)
assert "id" in response.json
utils.assert_send_mail_called(mail_mock, "other@test.de")
with app.app_context():
from project.models import (
EventReferenceRequest,
EventReferenceRequestReviewStatus,
)
reference_request = db.session.get(
EventReferenceRequest, int(response.json["id"])
)
assert reference_request is not None
assert reference_request.admin_unit_id == other_admin_unit_id
assert reference_request.event_id == event_id
assert (
reference_request.review_status == EventReferenceRequestReviewStatus.inbox
)
def test_reference_requests_outgoing_post_autoVerify(
client, app, seeder: Seeder, utils: UtilActions, db, mocker
):
mail_mock = utils.mock_send_mails_async(mocker)
user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id)
other_user_id = seeder.create_user("other@test.de")
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
seeder.create_admin_unit_relation(other_admin_unit_id, admin_unit_id, True)
url = utils.get_url(
"api_v1_organization_outgoing_event_reference_request_list",
id=admin_unit_id,
)
data = {
"event": {"id": event_id},
"target_organization": {"id": other_admin_unit_id},
}
response = utils.post_json(url, data)
utils.assert_response_created(response)
assert "id" in response.json
utils.assert_send_mail_called(mail_mock, "other@test.de")
with app.app_context():
from project.models import (
EventReference,
EventReferenceRequest,
EventReferenceRequestReviewStatus,
)
reference_request = db.session.get(
EventReferenceRequest, int(response.json["id"])
)
assert reference_request is not None
assert reference_request.admin_unit_id == other_admin_unit_id
assert reference_request.event_id == event_id
assert (
reference_request.review_status
== EventReferenceRequestReviewStatus.verified
)
reference = (
EventReference.query.filter(
EventReference.admin_unit_id == other_admin_unit_id
)
.filter(EventReference.event_id == event_id)
.first()
)
assert reference is not None
def test_reference_requests_outgoing_post_foreignEvent(
client, app, seeder: Seeder, utils: UtilActions, db
):
user_id, admin_unit_id = seeder.setup_api_access()
other_admin_unit_id = seeder.create_admin_unit(user_id, "Other Crew")
event_id = seeder.create_event(other_admin_unit_id)
url = utils.get_url(
"api_v1_organization_outgoing_event_reference_request_list",
id=admin_unit_id,
)
data = {
"event": {"id": event_id},
"target_organization": {"id": other_admin_unit_id},
}
response = utils.post_json(url, data)
utils.assert_response_notFound(response)
def test_reference_requests_outgoing_post_draft(
client, app, seeder: Seeder, utils: UtilActions, db
):
user_id, admin_unit_id = seeder.setup_api_access()
other_admin_unit_id = seeder.create_admin_unit(user_id, "Other Crew")
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url(
"api_v1_organization_outgoing_event_reference_request_list",
id=admin_unit_id,
)
data = {
"event": {"id": event_id},
"target_organization": {"id": other_admin_unit_id},
}
response = utils.post_json(url, data)
utils.assert_response_unauthorized(response)
def test_outgoing_relation_read(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
(

View File

@ -758,6 +758,15 @@ class Seeder(object):
reference_request_id = self.create_reference_request(event_id, admin_unit_id)
return (other_user_id, other_admin_unit_id, event_id, reference_request_id)
def create_outgoing_reference_request(self, admin_unit_id):
other_user_id = self.create_user("other@test.de")
other_admin_unit_id = self.create_admin_unit(other_user_id, "Other Crew")
event_id = self.create_event(admin_unit_id)
reference_request_id = self.create_reference_request(
event_id, other_admin_unit_id
)
return (other_user_id, other_admin_unit_id, event_id, reference_request_id)
def get_now_by_minute(self):
from datetime import datetime

View File

@ -157,11 +157,7 @@ def test_admin_unit_reference_requests_incoming(client, seeder, utils):
def test_admin_unit_reference_requests_outgoing(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
event_id = seeder.create_event(admin_unit_id)
other_user_id = seeder.create_user("other@test.de")
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
seeder.create_reference_request(event_id, other_admin_unit_id)
seeder.create_outgoing_reference_request(admin_unit_id)
utils.get_endpoint_ok(
"manage_admin_unit_reference_requests_outgoing", id=admin_unit_id