API access with authorization #475

This commit is contained in:
Daniel Grams 2023-05-21 19:05:28 +02:00
parent b874550a64
commit fb34d4323c
58 changed files with 556 additions and 358 deletions

View File

@ -29,3 +29,4 @@ JWT_PRIVATE_KEY=""
JWT_PUBLIC_JWKS='' JWT_PUBLIC_JWKS=''
DOCS_URL='' DOCS_URL=''
ADMIN_UNIT_CREATE_REQUIRES_ADMIN=False ADMIN_UNIT_CREATE_REQUIRES_ADMIN=False
API_READ_ANONYM=False

View File

@ -26,6 +26,7 @@ x-web-env:
DOCS_URL: ${DOCS_URL} DOCS_URL: ${DOCS_URL}
SITE_NAME: ${SITE_NAME} SITE_NAME: ${SITE_NAME}
ADMIN_UNIT_CREATE_REQUIRES_ADMIN: ${ADMIN_UNIT_CREATE_REQUIRES_ADMIN:-False} ADMIN_UNIT_CREATE_REQUIRES_ADMIN: ${ADMIN_UNIT_CREATE_REQUIRES_ADMIN:-False}
API_READ_ANONYM: ${API_READ_ANONYM:-False}
x-web: x-web:
&default-web &default-web

View File

@ -52,6 +52,7 @@ app.config["SEO_SITEMAP_PING_GOOGLE"] = getenv_bool("SEO_SITEMAP_PING_GOOGLE", "
app.config["GOOGLE_MAPS_API_KEY"] = os.getenv("GOOGLE_MAPS_API_KEY") app.config["GOOGLE_MAPS_API_KEY"] = os.getenv("GOOGLE_MAPS_API_KEY")
set_env_to_app(app, "SITE_NAME", "EventCally") set_env_to_app(app, "SITE_NAME", "EventCally")
app.config["FLASK_DEBUG"] = getenv_bool("FLASK_DEBUG", "False") app.config["FLASK_DEBUG"] = getenv_bool("FLASK_DEBUG", "False")
app.config["API_READ_ANONYM"] = getenv_bool("API_READ_ANONYM", "False")
# if app.config["FLASK_DEBUG"]: # if app.config["FLASK_DEBUG"]:
# logging.basicConfig(level=logging.DEBUG) # logging.basicConfig(level=logging.DEBUG)
@ -268,6 +269,7 @@ from project.views import (
admin_unit, admin_unit,
admin_unit_member, admin_unit_member,
admin_unit_member_invitation, admin_unit_member_invitation,
custom_widget,
dump, dump,
event, event,
event_date, event_date,

View File

@ -34,6 +34,7 @@ def owner_access_or_401(user_id):
def login_api_user() -> bool: def login_api_user() -> bool:
return ( return (
current_token current_token
and current_token.user
and login_user(current_token.user) and login_user(current_token.user)
or current_user or current_user
and current_user.is_authenticated and current_user.is_authenticated

View File

@ -1,4 +1,4 @@
from apispec import APISpec from apispec import APISpec, BasePlugin
from apispec.exceptions import DuplicateComponentNameError from apispec.exceptions import DuplicateComponentNameError
from apispec.ext.marshmallow import MarshmallowPlugin from apispec.ext.marshmallow import MarshmallowPlugin
from flask import url_for from flask import url_for
@ -115,6 +115,11 @@ class RestApi(Api):
data["errors"] = errors data["errors"] = errors
class DocSecurityPlugin(BasePlugin):
def operation_helper(self, path=None, operations=None, **kwargs):
pass
scope_list = [ scope_list = [
"openid", "openid",
"profile", "profile",
@ -138,7 +143,7 @@ app.config.update(
"APISPEC_SPEC": APISpec( "APISPEC_SPEC": APISpec(
title="Event calendar API", title="Event calendar API",
version="0.1.0", version="0.1.0",
plugins=[marshmallow_plugin], plugins=[marshmallow_plugin, DocSecurityPlugin()],
openapi_version="2.0", openapi_version="2.0",
info=dict( info=dict(
description="This API provides endpoints to interact with the event calendar data." description="This API provides endpoints to interact with the event calendar data."
@ -174,16 +179,33 @@ def add_oauth2_scheme_with_transport(insecure: bool):
authorizationUrl = url_for("authorize", _external=True, _scheme="https") authorizationUrl = url_for("authorize", _external=True, _scheme="https")
tokenUrl = url_for("issue_token", _external=True, _scheme="https") tokenUrl = url_for("issue_token", _external=True, _scheme="https")
oauth2_scheme = { scopes = {k: k for _, k in enumerate(scope_list)}
oauth2_authorization_code_scheme = {
"type": "oauth2", "type": "oauth2",
"authorizationUrl": authorizationUrl, "authorizationUrl": authorizationUrl,
"tokenUrl": tokenUrl, "tokenUrl": tokenUrl,
"flow": "accessCode", "flow": "accessCode",
"scopes": {k: k for _, k in enumerate(scope_list)}, "scopes": scopes,
} }
try: try:
api_docs.spec.components.security_scheme("oauth2", oauth2_scheme) api_docs.spec.components.security_scheme(
"oauth2AuthCode", oauth2_authorization_code_scheme
)
except DuplicateComponentNameError: # pragma: no cover
pass
oauth2_client_credentials_scheme = {
"type": "oauth2",
"tokenUrl": tokenUrl,
"flow": "application",
"scopes": scopes,
}
try:
api_docs.spec.components.security_scheme(
"oauth2ClientCredentials", oauth2_client_credentials_scheme
)
except DuplicateComponentNameError: # pragma: no cover except DuplicateComponentNameError: # pragma: no cover
pass pass

View File

@ -16,13 +16,13 @@ from project.models import CustomWidget
class CustomWidgetResource(BaseResource): class CustomWidgetResource(BaseResource):
@doc(summary="Get custom widget", tags=["Custom Widgets"]) @doc(summary="Get custom widget", tags=["Custom Widgets"])
@marshal_with(CustomWidgetSchema) @marshal_with(CustomWidgetSchema)
@require_api_access()
def get(self, id): def get(self, id):
return CustomWidget.query.get_or_404(id) return CustomWidget.query.get_or_404(id)
@doc( @doc(
summary="Update custom widget", summary="Update custom widget",
tags=["Custom Widgets"], tags=["Custom Widgets"],
security=[{"oauth2": ["customwidget:write"]}],
) )
@use_kwargs(CustomWidgetPostRequestSchema, location="json", apply=False) @use_kwargs(CustomWidgetPostRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -42,7 +42,6 @@ class CustomWidgetResource(BaseResource):
@doc( @doc(
summary="Patch custom widget", summary="Patch custom widget",
tags=["Custom Widgets"], tags=["Custom Widgets"],
security=[{"oauth2": ["customwidget:write"]}],
) )
@use_kwargs(CustomWidgetPatchRequestSchema, location="json", apply=False) @use_kwargs(CustomWidgetPatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -62,7 +61,6 @@ class CustomWidgetResource(BaseResource):
@doc( @doc(
summary="Delete custom widget", summary="Delete custom widget",
tags=["Custom Widgets"], tags=["Custom Widgets"],
security=[{"oauth2": ["customwidget:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("customwidget:write") @require_api_access("customwidget:write")

View File

@ -2,7 +2,7 @@ from flask_apispec import doc, marshal_with
from project.api import add_api_resource from project.api import add_api_resource
from project.api.dump.schemas import DumpResponseSchema from project.api.dump.schemas import DumpResponseSchema
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.api.schemas import NoneSchema from project.api.schemas import NoneSchema
@ -14,6 +14,7 @@ class DumpResource(BaseResource):
) )
@marshal_with(NoneSchema, 404) @marshal_with(NoneSchema, 404)
@marshal_with(DumpResponseSchema, 200) @marshal_with(DumpResponseSchema, 200)
@require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
return None, 404 return None, 404

View File

@ -26,10 +26,9 @@ from project.api.event_date.schemas import (
EventDateListRequestSchema, EventDateListRequestSchema,
EventDateListResponseSchema, EventDateListResponseSchema,
) )
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.api.schemas import NoneSchema from project.api.schemas import NoneSchema
from project.models import AdminUnit, Event, EventDate, PublicStatus from project.models import AdminUnit, Event, EventDate, PublicStatus
from project.oauth2 import require_oauth
from project.services.event import ( from project.services.event import (
get_event_with_details_or_404, get_event_with_details_or_404,
get_events_query, get_events_query,
@ -61,6 +60,7 @@ class EventListResource(BaseResource):
@doc(summary="List events", tags=["Events"]) @doc(summary="List events", tags=["Events"])
@use_kwargs(EventListRequestSchema, location=("query")) @use_kwargs(EventListRequestSchema, location=("query"))
@marshal_with(EventListResponseSchema) @marshal_with(EventListResponseSchema)
@require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
pagination = ( pagination = (
Event.query.join(Event.admin_unit) Event.query.join(Event.admin_unit)
@ -78,7 +78,7 @@ class EventListResource(BaseResource):
class EventResource(BaseResource): class EventResource(BaseResource):
@doc(summary="Get event", tags=["Events"]) @doc(summary="Get event", tags=["Events"])
@marshal_with(EventSchema) @marshal_with(EventSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id): def get(self, id):
login_api_user() login_api_user()
event = get_event_with_details_or_404(id) event = get_event_with_details_or_404(id)
@ -86,11 +86,12 @@ class EventResource(BaseResource):
return event return event
@doc( @doc(
summary="Update event", tags=["Events"], security=[{"oauth2": ["event:write"]}] summary="Update event",
tags=["Events"],
) )
@use_kwargs(EventPostRequestSchema, location="json", apply=False) @use_kwargs(EventPostRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("event:write") @require_api_access("event:write")
def put(self, id): def put(self, id):
login_api_user_or_401() login_api_user_or_401()
event = Event.query.get_or_404(id) event = Event.query.get_or_404(id)
@ -106,10 +107,13 @@ class EventResource(BaseResource):
return make_response("", 204) return make_response("", 204)
@doc(summary="Patch event", tags=["Events"], security=[{"oauth2": ["event:write"]}]) @doc(
summary="Patch event",
tags=["Events"],
)
@use_kwargs(EventPatchRequestSchema, location="json", apply=False) @use_kwargs(EventPatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("event:write") @require_api_access("event:write")
def patch(self, id): def patch(self, id):
login_api_user_or_401() login_api_user_or_401()
event = Event.query.get_or_404(id) event = Event.query.get_or_404(id)
@ -126,10 +130,11 @@ class EventResource(BaseResource):
return make_response("", 204) return make_response("", 204)
@doc( @doc(
summary="Delete event", tags=["Events"], security=[{"oauth2": ["event:write"]}] summary="Delete event",
tags=["Events"],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("event:write") @require_api_access("event:write")
def delete(self, id): def delete(self, id):
login_api_user_or_401() login_api_user_or_401()
event = Event.query.get_or_404(id) event = Event.query.get_or_404(id)
@ -145,7 +150,7 @@ class EventDatesResource(BaseResource):
@doc(summary="List dates for event", tags=["Events", "Event Dates"]) @doc(summary="List dates for event", tags=["Events", "Event Dates"])
@use_kwargs(EventDateListRequestSchema, location=("query")) @use_kwargs(EventDateListRequestSchema, location=("query"))
@marshal_with(EventDateListResponseSchema) @marshal_with(EventDateListResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
event = Event.query.options( event = Event.query.options(
load_only(Event.id, Event.public_status) load_only(Event.id, Event.public_status)
@ -164,7 +169,7 @@ class EventSearchResource(BaseResource):
@doc(summary="Search for events", tags=["Events"]) @doc(summary="Search for events", tags=["Events"])
@use_kwargs(EventSearchRequestSchema, location=("query")) @use_kwargs(EventSearchRequestSchema, location=("query"))
@marshal_with(EventSearchResponseSchema) @marshal_with(EventSearchResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
login_api_user() login_api_user()
params = EventSearchParams() params = EventSearchParams()
@ -177,6 +182,7 @@ class EventReportsResource(BaseResource):
@doc(summary="Add event report", tags=["Events"]) @doc(summary="Add event report", tags=["Events"])
@use_kwargs(EventReportPostSchema, location="json", apply=False) @use_kwargs(EventReportPostSchema, location="json", apply=False)
@marshal_with(NoneSchema, 204) @marshal_with(NoneSchema, 204)
@require_api_access()
def post(self, id): def post(self, id):
event = Event.query.options( event = Event.query.options(
load_only(Event.id, Event.public_status) load_only(Event.id, Event.public_status)

View File

@ -5,7 +5,7 @@ from project.api.event_category.schemas import (
EventCategoryListRequestSchema, EventCategoryListRequestSchema,
EventCategoryListResponseSchema, EventCategoryListResponseSchema,
) )
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.models import EventCategory from project.models import EventCategory
@ -13,6 +13,7 @@ class EventCategoryListResource(BaseResource):
@doc(summary="List event categories", tags=["Event Categories"]) @doc(summary="List event categories", tags=["Event Categories"])
@use_kwargs(EventCategoryListRequestSchema, location=("query")) @use_kwargs(EventCategoryListRequestSchema, location=("query"))
@marshal_with(EventCategoryListResponseSchema) @marshal_with(EventCategoryListResponseSchema)
@require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
pagination = EventCategory.query.paginate() pagination = EventCategory.query.paginate()
return pagination return pagination

View File

@ -12,9 +12,8 @@ from project.api.event_date.schemas import (
EventDateSearchRequestSchema, EventDateSearchRequestSchema,
EventDateSearchResponseSchema, EventDateSearchResponseSchema,
) )
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.models import AdminUnit, Event, EventDate, PublicStatus from project.models import AdminUnit, Event, EventDate, PublicStatus
from project.oauth2 import require_oauth
from project.services.event import get_event_dates_query from project.services.event import get_event_dates_query
from project.services.event_search import EventSearchParams from project.services.event_search import EventSearchParams
@ -23,6 +22,7 @@ class EventDateListResource(BaseResource):
@doc(summary="List event dates", tags=["Event Dates"]) @doc(summary="List event dates", tags=["Event Dates"])
@use_kwargs(EventDateListRequestSchema, location=("query")) @use_kwargs(EventDateListRequestSchema, location=("query"))
@marshal_with(EventDateListResponseSchema) @marshal_with(EventDateListResponseSchema)
@require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
pagination = ( pagination = (
EventDate.query.join(EventDate.event) EventDate.query.join(EventDate.event)
@ -42,7 +42,7 @@ class EventDateListResource(BaseResource):
class EventDateResource(BaseResource): class EventDateResource(BaseResource):
@doc(summary="Get event date", tags=["Event Dates"]) @doc(summary="Get event date", tags=["Event Dates"])
@marshal_with(EventDateSchema) @marshal_with(EventDateSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id): def get(self, id):
event_date = EventDate.query.options( event_date = EventDate.query.options(
defaultload(EventDate.event).load_only( defaultload(EventDate.event).load_only(
@ -57,7 +57,7 @@ class EventDateSearchResource(BaseResource):
@doc(summary="Search for event dates", tags=["Event Dates"]) @doc(summary="Search for event dates", tags=["Event Dates"])
@use_kwargs(EventDateSearchRequestSchema, location=("query")) @use_kwargs(EventDateSearchRequestSchema, location=("query"))
@marshal_with(EventDateSearchResponseSchema) @marshal_with(EventDateSearchResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
login_api_user() login_api_user()
params = EventSearchParams() params = EventSearchParams()

View File

@ -19,13 +19,13 @@ from project.services.event_search import EventSearchParams
class EventListModelResource(BaseResource): class EventListModelResource(BaseResource):
@doc(summary="Get event list", tags=["Event Lists"]) @doc(summary="Get event list", tags=["Event Lists"])
@marshal_with(EventListSchema) @marshal_with(EventListSchema)
@require_api_access()
def get(self, id): def get(self, id):
return EventList.query.get_or_404(id) return EventList.query.get_or_404(id)
@doc( @doc(
summary="Update event list", summary="Update event list",
tags=["Event Lists"], tags=["Event Lists"],
security=[{"oauth2": ["eventlist:write"]}],
) )
@use_kwargs(EventListUpdateRequestSchema, location="json", apply=False) @use_kwargs(EventListUpdateRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -45,7 +45,6 @@ class EventListModelResource(BaseResource):
@doc( @doc(
summary="Patch event list", summary="Patch event list",
tags=["Event Lists"], tags=["Event Lists"],
security=[{"oauth2": ["eventlist:write"]}],
) )
@use_kwargs(EventListPatchRequestSchema, location="json", apply=False) @use_kwargs(EventListPatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -65,7 +64,6 @@ class EventListModelResource(BaseResource):
@doc( @doc(
summary="Delete event list", summary="Delete event list",
tags=["Event Lists"], tags=["Event Lists"],
security=[{"oauth2": ["eventlist:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("eventlist:write") @require_api_access("eventlist:write")
@ -87,6 +85,7 @@ class EventListEventListResource(BaseResource):
) )
@use_kwargs(EventListRequestSchema, location=("query")) @use_kwargs(EventListRequestSchema, location=("query"))
@marshal_with(EventListResponseSchema) @marshal_with(EventListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
params = EventSearchParams() params = EventSearchParams()
params.event_list_id = id params.event_list_id = id
@ -98,7 +97,6 @@ class EventListEventListWriteResource(BaseResource):
@doc( @doc(
summary="Add event", summary="Add event",
tags=["Event Lists", "Events"], tags=["Event Lists", "Events"],
security=[{"oauth2": ["eventlist:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("eventlist:write") @require_api_access("eventlist:write")
@ -120,7 +118,6 @@ class EventListEventListWriteResource(BaseResource):
@doc( @doc(
summary="Remove event", summary="Remove event",
tags=["Event Lists", "Events"], tags=["Event Lists", "Events"],
security=[{"oauth2": ["eventlist:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("eventlist:write") @require_api_access("eventlist:write")

View File

@ -2,13 +2,14 @@ from flask_apispec import doc, marshal_with
from project.api import add_api_resource from project.api import add_api_resource
from project.api.event_reference.schemas import EventReferenceSchema from project.api.event_reference.schemas import EventReferenceSchema
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.models import EventReference from project.models import EventReference
class EventReferenceResource(BaseResource): class EventReferenceResource(BaseResource):
@doc(summary="Get event reference", tags=["Event References"]) @doc(summary="Get event reference", tags=["Event References"])
@marshal_with(EventReferenceSchema) @marshal_with(EventReferenceSchema)
@require_api_access()
def get(self, id): def get(self, id):
return EventReference.query.get_or_404(id) return EventReference.query.get_or_404(id)

View File

@ -74,7 +74,6 @@ from project.api.place.schemas import (
) )
from project.api.resources import BaseResource, require_api_access from project.api.resources import BaseResource, require_api_access
from project.models import AdminUnit, Event, PublicStatus from project.models import AdminUnit, Event, PublicStatus
from project.oauth2 import require_oauth
from project.services.admin_unit import ( from project.services.admin_unit import (
get_admin_unit_invitation_query, get_admin_unit_invitation_query,
get_admin_unit_query, get_admin_unit_query,
@ -98,7 +97,7 @@ from project.views.utils import send_mail
class OrganizationResource(BaseResource): class OrganizationResource(BaseResource):
@doc(summary="Get organization", tags=["Organizations"]) @doc(summary="Get organization", tags=["Organizations"])
@marshal_with(OrganizationSchema) @marshal_with(OrganizationSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id): def get(self, id):
return AdminUnit.query.get_or_404(id) return AdminUnit.query.get_or_404(id)
@ -111,7 +110,7 @@ class OrganizationEventDateSearchResource(BaseResource):
) )
@use_kwargs(EventDateSearchRequestSchema, location=("query")) @use_kwargs(EventDateSearchRequestSchema, location=("query"))
@marshal_with(EventDateSearchResponseSchema) @marshal_with(EventDateSearchResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
@ -128,7 +127,7 @@ class OrganizationEventSearchResource(BaseResource):
@doc(summary="Search for events of organization", tags=["Organizations", "Events"]) @doc(summary="Search for events of organization", tags=["Organizations", "Events"])
@use_kwargs(EventSearchRequestSchema, location=("query")) @use_kwargs(EventSearchRequestSchema, location=("query"))
@marshal_with(EventSearchResponseSchema) @marshal_with(EventSearchResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
@ -145,7 +144,7 @@ class OrganizationEventListResource(BaseResource):
@doc(summary="List events of organization", tags=["Organizations", "Events"]) @doc(summary="List events of organization", tags=["Organizations", "Events"])
@use_kwargs(EventListRequestSchema, location=("query")) @use_kwargs(EventListRequestSchema, location=("query"))
@marshal_with(EventListResponseSchema) @marshal_with(EventListResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
@ -164,11 +163,10 @@ class OrganizationEventListResource(BaseResource):
@doc( @doc(
summary="Add new event", summary="Add new event",
tags=["Organizations", "Events"], tags=["Organizations", "Events"],
security=[{"oauth2": ["event:write"]}],
) )
@use_kwargs(EventPostRequestSchema, location="json", apply=False) @use_kwargs(EventPostRequestSchema, location="json", apply=False)
@marshal_with(EventIdSchema, 201) @marshal_with(EventIdSchema, 201)
@require_oauth("event:write") @require_api_access("event:write")
def post(self, id): def post(self, id):
login_api_user_or_401() login_api_user_or_401()
admin_unit = get_admin_unit_for_manage_or_404(id) admin_unit = get_admin_unit_for_manage_or_404(id)
@ -189,6 +187,7 @@ class OrganizationEventImportResource(BaseResource):
@marshal_with(EventIdSchema, 201) @marshal_with(EventIdSchema, 201)
@require_api_access("event:write") @require_api_access("event:write")
def post(self, id, **kwargs): def post(self, id, **kwargs):
login_api_user_or_401()
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
access_or_401(admin_unit, "event:create") access_or_401(admin_unit, "event:create")
@ -211,10 +210,13 @@ class OrganizationEventImportResource(BaseResource):
class OrganizationListResource(BaseResource): class OrganizationListResource(BaseResource):
@doc(summary="List organizations", tags=["Organizations"]) @doc(
summary="List organizations",
tags=["Organizations"],
)
@use_kwargs(OrganizationListRequestSchema, location=("query")) @use_kwargs(OrganizationListRequestSchema, location=("query"))
@marshal_with(OrganizationListResponseSchema) @marshal_with(OrganizationListResponseSchema)
@require_oauth(optional=True) @require_api_access()
def get(self, **kwargs): def get(self, **kwargs):
keyword = kwargs["keyword"] if "keyword" in kwargs else None keyword = kwargs["keyword"] if "keyword" in kwargs else None
@ -231,6 +233,7 @@ class OrganizationOrganizerListResource(BaseResource):
) )
@use_kwargs(OrganizerListRequestSchema, location=("query")) @use_kwargs(OrganizerListRequestSchema, location=("query"))
@marshal_with(OrganizerListResponseSchema) @marshal_with(OrganizerListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
name = kwargs["name"] if "name" in kwargs else None name = kwargs["name"] if "name" in kwargs else None
@ -241,11 +244,10 @@ class OrganizationOrganizerListResource(BaseResource):
@doc( @doc(
summary="Add new organizer", summary="Add new organizer",
tags=["Organizations", "Organizers"], tags=["Organizations", "Organizers"],
security=[{"oauth2": ["organizer:write"]}],
) )
@use_kwargs(OrganizerPostRequestSchema, location="json", apply=False) @use_kwargs(OrganizerPostRequestSchema, location="json", apply=False)
@marshal_with(OrganizerIdSchema, 201) @marshal_with(OrganizerIdSchema, 201)
@require_oauth("organizer:write") @require_api_access("organizer:write")
def post(self, id): def post(self, id):
login_api_user_or_401() login_api_user_or_401()
admin_unit = get_admin_unit_for_manage_or_404(id) admin_unit = get_admin_unit_for_manage_or_404(id)
@ -264,6 +266,7 @@ class OrganizationPlaceListResource(BaseResource):
@doc(summary="List places of organization", tags=["Organizations", "Places"]) @doc(summary="List places of organization", tags=["Organizations", "Places"])
@use_kwargs(PlaceListRequestSchema, location=("query")) @use_kwargs(PlaceListRequestSchema, location=("query"))
@marshal_with(PlaceListResponseSchema) @marshal_with(PlaceListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
name = kwargs["name"] if "name" in kwargs else None name = kwargs["name"] if "name" in kwargs else None
@ -274,11 +277,10 @@ class OrganizationPlaceListResource(BaseResource):
@doc( @doc(
summary="Add new place", summary="Add new place",
tags=["Organizations", "Places"], tags=["Organizations", "Places"],
security=[{"oauth2": ["place:write"]}],
) )
@use_kwargs(PlacePostRequestSchema, location="json", apply=False) @use_kwargs(PlacePostRequestSchema, location="json", apply=False)
@marshal_with(PlaceIdSchema, 201) @marshal_with(PlaceIdSchema, 201)
@require_oauth("place:write") @require_api_access("place:write")
def post(self, id): def post(self, id):
login_api_user_or_401() login_api_user_or_401()
admin_unit = get_admin_unit_for_manage_or_404(id) admin_unit = get_admin_unit_for_manage_or_404(id)
@ -300,6 +302,7 @@ class OrganizationIncomingEventReferenceListResource(BaseResource):
) )
@use_kwargs(EventReferenceListRequestSchema, location=("query")) @use_kwargs(EventReferenceListRequestSchema, location=("query"))
@marshal_with(EventReferenceListResponseSchema) @marshal_with(EventReferenceListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
@ -314,6 +317,7 @@ class OrganizationOutgoingEventReferenceListResource(BaseResource):
) )
@use_kwargs(EventReferenceListRequestSchema, location=("query")) @use_kwargs(EventReferenceListRequestSchema, location=("query"))
@marshal_with(EventReferenceListResponseSchema) @marshal_with(EventReferenceListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
@ -325,7 +329,6 @@ class OrganizationOutgoingRelationListResource(BaseResource):
@doc( @doc(
summary="List outgoing relations of organization", summary="List outgoing relations of organization",
tags=["Organizations", "Organization Relations"], tags=["Organizations", "Organization Relations"],
security=[{"oauth2": ["organization:read"]}],
) )
@use_kwargs(OrganizationRelationListRequestSchema, location=("query")) @use_kwargs(OrganizationRelationListRequestSchema, location=("query"))
@marshal_with(OrganizationRelationListResponseSchema) @marshal_with(OrganizationRelationListResponseSchema)
@ -341,7 +344,6 @@ class OrganizationOutgoingRelationListResource(BaseResource):
@doc( @doc(
summary="Add new outgoing relation", summary="Add new outgoing relation",
tags=["Organizations", "Organization Relations"], tags=["Organizations", "Organization Relations"],
security=[{"oauth2": ["organization:write"]}],
) )
@use_kwargs(OrganizationRelationCreateRequestSchema, location="json", apply=False) @use_kwargs(OrganizationRelationCreateRequestSchema, location="json", apply=False)
@marshal_with(OrganizationRelationIdSchema, 201) @marshal_with(OrganizationRelationIdSchema, 201)
@ -364,7 +366,6 @@ class OrganizationOrganizationInvitationListResource(BaseResource):
@doc( @doc(
summary="List organization invitations of organization", summary="List organization invitations of organization",
tags=["Organizations", "Organization Invitations"], tags=["Organizations", "Organization Invitations"],
security=[{"oauth2": ["organization:read"]}],
) )
@use_kwargs(OrganizationInvitationListRequestSchema, location=("query")) @use_kwargs(OrganizationInvitationListRequestSchema, location=("query"))
@marshal_with(OrganizationInvitationListResponseSchema) @marshal_with(OrganizationInvitationListResponseSchema)
@ -380,7 +381,6 @@ class OrganizationOrganizationInvitationListResource(BaseResource):
@doc( @doc(
summary="Add new organization invitation", summary="Add new organization invitation",
tags=["Organizations", "Organization Invitations"], tags=["Organizations", "Organization Invitations"],
security=[{"oauth2": ["organization:write"]}],
) )
@use_kwargs(OrganizationInvitationCreateRequestSchema, location="json", apply=False) @use_kwargs(OrganizationInvitationCreateRequestSchema, location="json", apply=False)
@marshal_with(OrganizationInvitationIdSchema, 201) @marshal_with(OrganizationInvitationIdSchema, 201)
@ -413,6 +413,7 @@ class OrganizationEventListListResource(BaseResource):
) )
@use_kwargs(EventListListRequestSchema, location=("query")) @use_kwargs(EventListListRequestSchema, location=("query"))
@marshal_with(EventListListResponseSchema) @marshal_with(EventListListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
name = kwargs["name"] if "name" in kwargs else None name = kwargs["name"] if "name" in kwargs else None
@ -423,7 +424,6 @@ class OrganizationEventListListResource(BaseResource):
@doc( @doc(
summary="Add new event list", summary="Add new event list",
tags=["Organizations", "Event Lists"], tags=["Organizations", "Event Lists"],
security=[{"oauth2": ["eventlist:write"]}],
) )
@use_kwargs(EventListCreateRequestSchema, location="json", apply=False) @use_kwargs(EventListCreateRequestSchema, location="json", apply=False)
@marshal_with(EventListIdSchema, 201) @marshal_with(EventListIdSchema, 201)
@ -449,6 +449,7 @@ class OrganizationEventListStatusListResource(BaseResource):
) )
@use_kwargs(EventListListRequestSchema, location=("query")) @use_kwargs(EventListListRequestSchema, location=("query"))
@marshal_with(EventListStatusListResponseSchema) @marshal_with(EventListStatusListResponseSchema)
@require_api_access()
def get(self, id, event_id, **kwargs): def get(self, id, event_id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
name = kwargs["name"] if "name" in kwargs else None name = kwargs["name"] if "name" in kwargs else None
@ -466,6 +467,7 @@ class OrganizationCustomWidgetListResource(BaseResource):
) )
@use_kwargs(CustomWidgetListRequestSchema, location=("query")) @use_kwargs(CustomWidgetListRequestSchema, location=("query"))
@marshal_with(CustomWidgetListResponseSchema) @marshal_with(CustomWidgetListResponseSchema)
@require_api_access()
def get(self, id, **kwargs): def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id) admin_unit = AdminUnit.query.get_or_404(id)
name = kwargs["name"] if "name" in kwargs else None name = kwargs["name"] if "name" in kwargs else None
@ -476,7 +478,6 @@ class OrganizationCustomWidgetListResource(BaseResource):
@doc( @doc(
summary="Add new custom widget", summary="Add new custom widget",
tags=["Organizations", "CustomWidgets"], tags=["Organizations", "CustomWidgets"],
security=[{"oauth2": ["customwidget:write"]}],
) )
@use_kwargs(CustomWidgetPostRequestSchema, location="json", apply=False) @use_kwargs(CustomWidgetPostRequestSchema, location="json", apply=False)
@marshal_with(CustomWidgetIdSchema, 201) @marshal_with(CustomWidgetIdSchema, 201)

View File

@ -18,7 +18,6 @@ class OrganizationInvitationResource(BaseResource):
@doc( @doc(
summary="Get organization invitation", summary="Get organization invitation",
tags=["Organization Invitations"], tags=["Organization Invitations"],
security=[{"oauth2": ["organization:read"]}],
) )
@marshal_with(OrganizationInvitationSchema) @marshal_with(OrganizationInvitationSchema)
@require_api_access("organization:read") @require_api_access("organization:read")
@ -32,7 +31,6 @@ class OrganizationInvitationResource(BaseResource):
@doc( @doc(
summary="Update organization invitation", summary="Update organization invitation",
tags=["Organization Invitations"], tags=["Organization Invitations"],
security=[{"oauth2": ["organization:write"]}],
) )
@use_kwargs(OrganizationInvitationUpdateRequestSchema, location="json", apply=False) @use_kwargs(OrganizationInvitationUpdateRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -52,7 +50,6 @@ class OrganizationInvitationResource(BaseResource):
@doc( @doc(
summary="Patch organization invitation", summary="Patch organization invitation",
tags=["Organization Invitations"], tags=["Organization Invitations"],
security=[{"oauth2": ["organization:write"]}],
) )
@use_kwargs(OrganizationInvitationPatchRequestSchema, location="json", apply=False) @use_kwargs(OrganizationInvitationPatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -72,7 +69,6 @@ class OrganizationInvitationResource(BaseResource):
@doc( @doc(
summary="Delete organization invitation", summary="Delete organization invitation",
tags=["Organization Invitations"], tags=["Organization Invitations"],
security=[{"oauth2": ["organization:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("organization:write") @require_api_access("organization:write")

View File

@ -19,7 +19,6 @@ class OrganizationRelationResource(BaseResource):
@doc( @doc(
summary="Get organization relation", summary="Get organization relation",
tags=["Organization Relations"], tags=["Organization Relations"],
security=[{"oauth2": ["organization:read"]}],
) )
@marshal_with(OrganizationRelationSchema) @marshal_with(OrganizationRelationSchema)
@require_api_access("organization:read") @require_api_access("organization:read")
@ -37,7 +36,6 @@ class OrganizationRelationResource(BaseResource):
@doc( @doc(
summary="Update organization relation", summary="Update organization relation",
tags=["Organization Relations"], tags=["Organization Relations"],
security=[{"oauth2": ["organization:write"]}],
) )
@use_kwargs(OrganizationRelationUpdateRequestSchema, location="json", apply=False) @use_kwargs(OrganizationRelationUpdateRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -57,7 +55,6 @@ class OrganizationRelationResource(BaseResource):
@doc( @doc(
summary="Patch organization relation", summary="Patch organization relation",
tags=["Organization Relations"], tags=["Organization Relations"],
security=[{"oauth2": ["organization:write"]}],
) )
@use_kwargs(OrganizationRelationPatchRequestSchema, location="json", apply=False) @use_kwargs(OrganizationRelationPatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@ -77,7 +74,6 @@ class OrganizationRelationResource(BaseResource):
@doc( @doc(
summary="Delete organization relation", summary="Delete organization relation",
tags=["Organization Relations"], tags=["Organization Relations"],
security=[{"oauth2": ["organization:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("organization:write") @require_api_access("organization:write")

View File

@ -9,25 +9,24 @@ from project.api.organizer.schemas import (
OrganizerPostRequestSchema, OrganizerPostRequestSchema,
OrganizerSchema, OrganizerSchema,
) )
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.models import EventOrganizer from project.models import EventOrganizer
from project.oauth2 import require_oauth
class OrganizerResource(BaseResource): class OrganizerResource(BaseResource):
@doc(summary="Get organizer", tags=["Organizers"]) @doc(summary="Get organizer", tags=["Organizers"])
@marshal_with(OrganizerSchema) @marshal_with(OrganizerSchema)
@require_api_access()
def get(self, id): def get(self, id):
return EventOrganizer.query.get_or_404(id) return EventOrganizer.query.get_or_404(id)
@doc( @doc(
summary="Update organizer", summary="Update organizer",
tags=["Organizers"], tags=["Organizers"],
security=[{"oauth2": ["organizer:write"]}],
) )
@use_kwargs(OrganizerPostRequestSchema, location="json", apply=False) @use_kwargs(OrganizerPostRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("organizer:write") @require_api_access("organizer:write")
def put(self, id): def put(self, id):
login_api_user_or_401() login_api_user_or_401()
organizer = EventOrganizer.query.get_or_404(id) organizer = EventOrganizer.query.get_or_404(id)
@ -41,11 +40,10 @@ class OrganizerResource(BaseResource):
@doc( @doc(
summary="Patch organizer", summary="Patch organizer",
tags=["Organizers"], tags=["Organizers"],
security=[{"oauth2": ["organizer:write"]}],
) )
@use_kwargs(OrganizerPatchRequestSchema, location="json", apply=False) @use_kwargs(OrganizerPatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("organizer:write") @require_api_access("organizer:write")
def patch(self, id): def patch(self, id):
login_api_user_or_401() login_api_user_or_401()
organizer = EventOrganizer.query.get_or_404(id) organizer = EventOrganizer.query.get_or_404(id)
@ -61,10 +59,9 @@ class OrganizerResource(BaseResource):
@doc( @doc(
summary="Delete organizer", summary="Delete organizer",
tags=["Organizers"], tags=["Organizers"],
security=[{"oauth2": ["organizer:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("organizer:write") @require_api_access("organizer:write")
def delete(self, id): def delete(self, id):
login_api_user_or_401() login_api_user_or_401()
organizer = EventOrganizer.query.get_or_404(id) organizer = EventOrganizer.query.get_or_404(id)

View File

@ -9,23 +9,24 @@ from project.api.place.schemas import (
PlacePostRequestSchema, PlacePostRequestSchema,
PlaceSchema, PlaceSchema,
) )
from project.api.resources import BaseResource from project.api.resources import BaseResource, require_api_access
from project.models import EventPlace from project.models import EventPlace
from project.oauth2 import require_oauth
class PlaceResource(BaseResource): class PlaceResource(BaseResource):
@doc(summary="Get place", tags=["Places"]) @doc(summary="Get place", tags=["Places"])
@marshal_with(PlaceSchema) @marshal_with(PlaceSchema)
@require_api_access()
def get(self, id): def get(self, id):
return EventPlace.query.get_or_404(id) return EventPlace.query.get_or_404(id)
@doc( @doc(
summary="Update place", tags=["Places"], security=[{"oauth2": ["place:write"]}] summary="Update place",
tags=["Places"],
) )
@use_kwargs(PlacePostRequestSchema, location="json", apply=False) @use_kwargs(PlacePostRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("place:write") @require_api_access("place:write")
def put(self, id): def put(self, id):
login_api_user_or_401() login_api_user_or_401()
place = EventPlace.query.get_or_404(id) place = EventPlace.query.get_or_404(id)
@ -36,10 +37,13 @@ class PlaceResource(BaseResource):
return make_response("", 204) return make_response("", 204)
@doc(summary="Patch place", tags=["Places"], security=[{"oauth2": ["place:write"]}]) @doc(
summary="Patch place",
tags=["Places"],
)
@use_kwargs(PlacePatchRequestSchema, location="json", apply=False) @use_kwargs(PlacePatchRequestSchema, location="json", apply=False)
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("place:write") @require_api_access("place:write")
def patch(self, id): def patch(self, id):
login_api_user_or_401() login_api_user_or_401()
place = EventPlace.query.get_or_404(id) place = EventPlace.query.get_or_404(id)
@ -51,10 +55,11 @@ class PlaceResource(BaseResource):
return make_response("", 204) return make_response("", 204)
@doc( @doc(
summary="Delete place", tags=["Places"], security=[{"oauth2": ["place:write"]}] summary="Delete place",
tags=["Places"],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_oauth("place:write") @require_api_access("place:write")
def delete(self, id): def delete(self, id):
login_api_user_or_401() login_api_user_or_401()
place = EventPlace.query.get_or_404(id) place = EventPlace.query.get_or_404(id)

View File

@ -1,13 +1,13 @@
from functools import wraps from functools import wraps
from authlib.oauth2 import OAuth2Error from authlib.oauth2 import OAuth2Error
from authlib.oauth2.rfc6749 import MissingAuthorizationError
from flask import request from flask import request
from flask_apispec import marshal_with from flask_apispec import marshal_with
from flask_apispec.annotations import annotate
from flask_apispec.views import MethodResource from flask_apispec.views import MethodResource
from flask_security import current_user from flask_wtf.csrf import validate_csrf
from project import db from project import app, csrf, db
from project.api.schemas import ErrorResponseSchema, UnprocessableEntityResponseSchema from project.api.schemas import ErrorResponseSchema, UnprocessableEntityResponseSchema
from project.oauth2 import require_oauth from project.oauth2 import require_oauth
@ -22,23 +22,44 @@ def etag_cache(func):
return wrapper return wrapper
def require_api_access(scopes=None, optional=False): def is_internal_request() -> bool:
try:
validate_csrf(csrf._get_csrf_token())
return True
except Exception:
return False
def require_api_access(scopes=None):
def inner_decorator(func): def inner_decorator(func):
def wrapped(*args, **kwargs): # see authlib ResourceProtector#__call__ def wrapped(*args, **kwargs): # see authlib ResourceProtector#__call__
try: # pragma: no cover try: # pragma: no cover
try: try:
require_oauth.acquire_token(scopes) require_oauth.acquire_token(scopes)
except MissingAuthorizationError as error:
if optional:
return func(*args, **kwargs)
require_oauth.raise_error_response(error)
except OAuth2Error as error: except OAuth2Error as error:
require_oauth.raise_error_response(error) require_oauth.raise_error_response(error)
except Exception as e: except Exception as e:
if not current_user or not current_user.is_authenticated: if app.config["API_READ_ANONYM"]:
return func(*args, **kwargs)
if not is_internal_request():
raise e raise e
return func(*args, **kwargs) return func(*args, **kwargs)
scope_list = scopes if type(scopes) is list else [scopes] if scopes else list()
security = [{"oauth2AuthCode": scope_list}]
if not scope_list:
security.append(
{
"oauth2ClientCredentials": scope_list,
}
)
annotate(
wrapped,
"docs",
[{"security": security}],
)
return wrapped return wrapped
return inner_decorator return inner_decorator

View File

@ -34,7 +34,6 @@ class UserOrganizationInvitationListResource(BaseResource):
@doc( @doc(
summary="List organization invitations of user", summary="List organization invitations of user",
tags=["Users", "Organization Invitations"], tags=["Users", "Organization Invitations"],
security=[{"oauth2": ["user:read"]}],
) )
@use_kwargs(OrganizationInvitationListRequestSchema, location=("query")) @use_kwargs(OrganizationInvitationListRequestSchema, location=("query"))
@marshal_with(OrganizationInvitationListResponseSchema) @marshal_with(OrganizationInvitationListResponseSchema)
@ -53,7 +52,6 @@ class UserOrganizationInvitationResource(BaseResource):
@doc( @doc(
summary="Get organization invitation of user", summary="Get organization invitation of user",
tags=["Users", "Organization Invitations"], tags=["Users", "Organization Invitations"],
security=[{"oauth2": ["user:read"]}],
) )
@marshal_with(OrganizationInvitationSchema) @marshal_with(OrganizationInvitationSchema)
@require_api_access("user:read") @require_api_access("user:read")
@ -67,7 +65,6 @@ class UserOrganizationInvitationResource(BaseResource):
@doc( @doc(
summary="Delete organization invitation of user", summary="Delete organization invitation of user",
tags=["Users", "Organization Invitations"], tags=["Users", "Organization Invitations"],
security=[{"oauth2": ["user:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("user:write") @require_api_access("user:write")
@ -86,7 +83,6 @@ class UserFavoriteEventListResource(BaseResource):
@doc( @doc(
summary="List favorite events of user", summary="List favorite events of user",
tags=["Users", "Events"], tags=["Users", "Events"],
security=[{"oauth2": ["user:read"]}],
) )
@use_kwargs(UserFavoriteEventListRequestSchema, location=("query")) @use_kwargs(UserFavoriteEventListRequestSchema, location=("query"))
@marshal_with(UserFavoriteEventListResponseSchema) @marshal_with(UserFavoriteEventListResponseSchema)
@ -104,7 +100,6 @@ class UserFavoriteEventSearchResource(BaseResource):
@doc( @doc(
summary="Search for favorite events of user", summary="Search for favorite events of user",
tags=["Users", "Events"], tags=["Users", "Events"],
security=[{"oauth2": ["user:read"]}],
) )
@use_kwargs(EventSearchRequestSchema, location=("query")) @use_kwargs(EventSearchRequestSchema, location=("query"))
@marshal_with(EventSearchResponseSchema) @marshal_with(EventSearchResponseSchema)
@ -124,7 +119,6 @@ class UserFavoriteEventListWriteResource(BaseResource):
@doc( @doc(
summary="Add event to users favorites", summary="Add event to users favorites",
tags=["Users", "Events"], tags=["Users", "Events"],
security=[{"oauth2": ["user:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("user:write") @require_api_access("user:write")
@ -142,7 +136,6 @@ class UserFavoriteEventListWriteResource(BaseResource):
@doc( @doc(
summary="Remove event from users favorites", summary="Remove event from users favorites",
tags=["Users", "Events"], tags=["Users", "Events"],
security=[{"oauth2": ["user:write"]}],
) )
@marshal_with(None, 204) @marshal_with(None, 204)
@require_api_access("user:write") @require_api_access("user:write")

View File

@ -258,9 +258,6 @@ def _insert_default_oauth2_client(user_id):
metadata = dict() metadata = dict()
metadata["client_name"] = "Mein Client" metadata["client_name"] = "Mein Client"
metadata["scope"] = " ".join(scope_list) metadata["scope"] = " ".join(scope_list)
metadata["grant_types"] = ["authorization_code", "refresh_token"]
metadata["response_types"] = ["code"]
metadata["token_endpoint_auth_method"] = "client_secret_post"
metadata["redirect_uris"] = ["/"] metadata["redirect_uris"] = ["/"]
client.set_client_metadata(metadata) client.set_client_metadata(metadata)

View File

@ -3,7 +3,7 @@ import os
from flask_babel import lazy_gettext from flask_babel import lazy_gettext
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField from wtforms import StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired from wtforms.validators import DataRequired, Optional
from project.api import scopes from project.api import scopes
from project.forms.widgets import MultiCheckboxField from project.forms.widgets import MultiCheckboxField
@ -13,11 +13,11 @@ from project.utils import split_by_crlf
class BaseOAuth2ClientForm(FlaskForm): class BaseOAuth2ClientForm(FlaskForm):
client_name = StringField(lazy_gettext("Client name"), validators=[DataRequired()]) client_name = StringField(lazy_gettext("Client name"), validators=[DataRequired()])
redirect_uris = TextAreaField( redirect_uris = TextAreaField(
lazy_gettext("Redirect URIs"), validators=[DataRequired()] lazy_gettext("Redirect URIs"), validators=[Optional()]
) )
scope = MultiCheckboxField( scope = MultiCheckboxField(
lazy_gettext("Scopes"), lazy_gettext("Scopes"),
validators=[DataRequired()], validators=[Optional()],
choices=[(k, k) for k, v in scopes.items()], choices=[(k, k) for k, v in scopes.items()],
) )

View File

@ -47,16 +47,7 @@ def create_initial_data():
"reference_request:delete", "reference_request:delete",
"reference_request:verify", "reference_request:verify",
] ]
early_adopter_permissions = [ early_adopter_permissions = []
"oauth2_client:create",
"oauth2_client:read",
"oauth2_client:update",
"oauth2_client:delete",
"oauth2_token:create",
"oauth2_token:read",
"oauth2_token:update",
"oauth2_token:delete",
]
upsert_admin_unit_member_role("admin", "Administrator", admin_permissions) upsert_admin_unit_member_role("admin", "Administrator", admin_permissions)
upsert_admin_unit_member_role("event_verifier", "Event expert", event_permissions) upsert_admin_unit_member_role("event_verifier", "Event expert", event_permissions)

View File

@ -276,7 +276,7 @@ class AdminUnit(db.Model, TrackableMixin):
server_default="0", server_default="0",
) )
) )
incoming_verification_requests_text = Column(UnicodeText()) incoming_verification_requests_text = deferred(Column(UnicodeText()))
can_invite_other = deferred( can_invite_other = deferred(
Column( Column(
Boolean(), Boolean(),

View File

@ -22,7 +22,7 @@ class OAuth2Client(db.Model, OAuth2ClientMixin):
@OAuth2ClientMixin.grant_types.getter @OAuth2ClientMixin.grant_types.getter
def grant_types(self): def grant_types(self):
return ["authorization_code", "refresh_token"] return ["authorization_code", "refresh_token", "client_credentials"]
@OAuth2ClientMixin.response_types.getter @OAuth2ClientMixin.response_types.getter
def response_types(self): def response_types(self):

View File

@ -71,6 +71,10 @@ class AuthorizationCodeGrant(grants.AuthorizationCodeGrant):
return db.session.get(User, authorization_code.user_id) return db.session.get(User, authorization_code.user_id)
class ClientCredentialsGrant(grants.ClientCredentialsGrant):
TOKEN_ENDPOINT_AUTH_METHODS = ["client_secret_basic", "client_secret_post"]
class OpenIDCode(_OpenIDCode): class OpenIDCode(_OpenIDCode):
def exists_nonce(self, nonce, request): def exists_nonce(self, nonce, request):
return exists_nonce(nonce, request) return exists_nonce(nonce, request)
@ -176,6 +180,7 @@ def config_oauth(app):
AuthorizationCodeGrant, AuthorizationCodeGrant,
[CodeChallenge(required=True), OpenIDCode()], [CodeChallenge(required=True), OpenIDCode()],
) )
authorization.register_grant(ClientCredentialsGrant)
authorization.register_grant(RefreshTokenGrant) authorization.register_grant(RefreshTokenGrant)
# support revocation # support revocation

View File

@ -44,6 +44,8 @@ def set_manage_admin_unit_cookie(response):
@app.after_request @app.after_request
def set_response_headers(response): def set_response_headers(response):
if request and request.endpoint: if request and request.endpoint:
if request.endpoint.startswith("api_"):
return response
if request.endpoint != "static" and request.endpoint != "widget_event_dates": if request.endpoint != "static" and request.endpoint != "widget_event_dates":
response.headers["X-Frame-Options"] = "SAMEORIGIN" response.headers["X-Frame-Options"] = "SAMEORIGIN"

View File

@ -411,7 +411,7 @@ const WidgetConfigurator = {
}), }),
computed: { computed: {
iFrameSource() { iFrameSource() {
return `${window.location.origin}/static/widget/${this.widgetType}.html`; return `${window.location.origin}/custom_widget/${this.widgetType}`;
}, },
organizationId() { organizationId() {
return this.$route.params.organization_id; return this.$route.params.organization_id;

View File

@ -38,11 +38,11 @@
var googleTagManager = false; var googleTagManager = false;
if (customId != null) { if (customId != null) {
var url = baseUrl + "/api/v1/custom-widgets/" + customId; var url = baseUrl + "/js/wlcw/" + customId;
customWidgetData = loadJSON(url); customWidgetData = loadJSON(url);
var settings = customWidgetData.settings; var settings = customWidgetData.settings;
src = baseUrl + "/static/widget/" + customWidgetData.widget_type + ".html"; src = baseUrl + "/custom_widget/" + customWidgetData.widget_type;
if (settings.hasOwnProperty('iFrameAutoResize') && settings.iFrameAutoResize != null) { if (settings.hasOwnProperty('iFrameAutoResize') && settings.iFrameAutoResize != null) {
resize = settings.iFrameAutoResize; resize = settings.iFrameAutoResize;
@ -233,6 +233,8 @@
xmlhttp.overrideMimeType(mimeType); xmlhttp.overrideMimeType(mimeType);
} }
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token() }}");
xmlhttp.send(); xmlhttp.send();
return xmlhttp.responseText; return xmlhttp.responseText;
} }

View File

@ -1687,24 +1687,6 @@ $('#allday').on('change', function() {
</script> </script>
{% endmacro %} {% endmacro %}
{% macro render_ajax_csrf_script() %}
<script type="text/javascript">
{{ render_ajax_csrf() }}
</script>
{% endmacro %}
{% macro render_ajax_csrf() %}
var csrf_token = "{{ csrf_token() }}";
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
}
}
});
{% endmacro %}
{% macro render_form_scripts() %} {% macro render_form_scripts() %}
<script src="{{ url_for('static', filename='ext/jquery-ui.1.12.1/jquery-ui.min.js')}}"></script> <script src="{{ url_for('static', filename='ext/jquery-ui.1.12.1/jquery-ui.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/jquery-ui-i18n.1.11.4.min.js')}}"></script> <script src="{{ url_for('static', filename='ext/jquery-ui-i18n.1.11.4.min.js')}}"></script>
@ -1712,8 +1694,6 @@ $('#allday').on('change', function() {
<script src="{{ url_for('static', filename='ext/select2.i18n.de.4.1.0-beta.1.min.js')}}"></script> <script src="{{ url_for('static', filename='ext/select2.i18n.de.4.1.0-beta.1.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/jquery.timepicker.1.13.18.min.js')}}"></script> <script src="{{ url_for('static', filename='ext/jquery.timepicker.1.13.18.min.js')}}"></script>
<script type="text/javascript"> <script type="text/javascript">
{{ render_ajax_csrf() }}
$.datepicker.setDefaults($.datepicker.regional["de"]); $.datepicker.setDefaults($.datepicker.regional["de"]);
$.fn.select2.defaults.set("language", "de"); $.fn.select2.defaults.set("language", "de");

View File

@ -96,6 +96,7 @@
<script src="/static/ext/moment.2.24.0.with-locales.min.js"></script> <script src="/static/ext/moment.2.24.0.with-locales.min.js"></script>
<script> <script>
axios.defaults.baseURL = window.location.origin; axios.defaults.baseURL = window.location.origin;
axios.defaults.headers.common["X-CSRFToken"] = "[% csrf_token() %]";
moment.locale("de"); moment.locale("de");
Vue.component('event-warning-pills', { Vue.component('event-warning-pills', {

View File

@ -234,6 +234,7 @@
</div> </div>
<script> <script>
axios.defaults.baseURL = window.location.origin; axios.defaults.baseURL = window.location.origin;
axios.defaults.headers.common["X-CSRFToken"] = "[% csrf_token() %]";
moment.locale("de"); moment.locale("de");
const localizedMessages = { const localizedMessages = {

View File

@ -138,6 +138,16 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
<script type="text/javascript">
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token() }}");
}
}
});
</script>
{% block header %} {% block header %}
{% endblock %} {% endblock %}
{%- endblock head %} {%- endblock head %}

View File

@ -331,6 +331,7 @@
}); });
axios.defaults.baseURL = "{{ get_base_url() }}"; axios.defaults.baseURL = "{{ get_base_url() }}";
axios.defaults.headers.common["X-CSRFToken"] = "{{ csrf_token() }}";
axios.interceptors.request.use( axios.interceptors.request.use(
function (config) { function (config) {
if (config) { if (config) {

View File

@ -1,10 +1,8 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% from "_macros.html" import render_ajax_csrf_script %}
{%- block title -%} {%- block title -%}
{{ _('Export') }} {{ _('Export') }}
{%- endblock -%} {%- endblock -%}
{% block header %} {% block header %}
{{ render_ajax_csrf_script() }}
<script> <script>
function submit_async() { function submit_async() {
$("#submit_async"). prop("disabled", true); $("#submit_async"). prop("disabled", true);

View File

@ -12,11 +12,9 @@
</ol> </ol>
</nav> </nav>
{% if current_user.has_permission('oauth2_client:create') %}
<div class="my-4"> <div class="my-4">
<a class="btn btn-outline-secondary my-1" href="{{ url_for('oauth2_client_create') }}" role="button"><i class="fa fa-plus"></i> {{ _('Create OAuth2 client') }}</a> <a class="btn btn-outline-secondary my-1" href="{{ url_for('oauth2_client_create') }}" role="button"><i class="fa fa-plus"></i> {{ _('Create OAuth2 client') }}</a>
</div> </div>
{% endif %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-sm table-bordered table-hover table-striped"> <table class="table table-sm table-bordered table-hover table-striped">

View File

@ -42,7 +42,6 @@
</a> </a>
</div> </div>
{% if current_user.has_permission('oauth2_client:read') %}
<h2>{{ _('Developer') }}</h2> <h2>{{ _('Developer') }}</h2>
<div class="list-group"> <div class="list-group">
@ -51,6 +50,5 @@
<i class="fa fa-caret-right"></i> <i class="fa fa-caret-right"></i>
</a> </a>
</div> </div>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -175,7 +175,7 @@ def admin_unit_update(id):
@auth_required() @auth_required()
@manage_required("admin_unit:update") @manage_required("admin_unit:update")
def admin_unit_request_deletion(id): def admin_unit_request_deletion(id):
admin_unit = g.admin_unit admin_unit = g.manage_admin_unit
if admin_unit.deletion_requested_at: # pragma: no cover if admin_unit.deletion_requested_at: # pragma: no cover
return redirect(url_for("admin_unit_cancel_deletion", id=admin_unit.id)) return redirect(url_for("admin_unit_cancel_deletion", id=admin_unit.id))
@ -208,7 +208,7 @@ def admin_unit_request_deletion(id):
@auth_required() @auth_required()
@manage_required("admin_unit:update") @manage_required("admin_unit:update")
def admin_unit_cancel_deletion(id): def admin_unit_cancel_deletion(id):
admin_unit = g.admin_unit admin_unit = g.manage_admin_unit
if not admin_unit.deletion_requested_at: # pragma: no cover if not admin_unit.deletion_requested_at: # pragma: no cover
return redirect(url_for("admin_unit_request_deletion", id=admin_unit.id)) return redirect(url_for("admin_unit_request_deletion", id=admin_unit.id))

View File

@ -0,0 +1,8 @@
from project import app
@app.route("/custom_widget/<string:type>")
def custom_widget_type(type: str):
env = app.jinja_env.overlay(variable_start_string="[%", variable_end_string="%]")
template = env.get_template(f"custom_widget/{type}.html")
return template.render()

View File

@ -1,12 +1,14 @@
from flask import request from flask import request
from flask.json import jsonify from flask.json import jsonify
from flask_babel import gettext from flask_babel import gettext
from flask_cors import cross_origin
from flask_security import url_for_security from flask_security import url_for_security
from flask_security.utils import localize_callback from flask_security.utils import localize_callback
from project import app, csrf from project import app, csrf
from project.api.custom_widget.schemas import CustomWidgetSchema
from project.maputils import find_gmaps_places, get_gmaps_place from project.maputils import find_gmaps_places, get_gmaps_place
from project.models import AdminUnit from project.models import AdminUnit, CustomWidget
from project.services.place import get_event_places from project.services.place import get_event_places
from project.services.user import find_user_by_email from project.services.user import find_user_by_email
from project.utils import get_place_str from project.utils import get_place_str
@ -124,3 +126,11 @@ def js_autocomplete_gmaps_place():
gmaps_id = request.args["gmaps_id"] gmaps_id = request.args["gmaps_id"]
place = get_gmaps_place(gmaps_id) place = get_gmaps_place(gmaps_id)
return jsonify(place) return jsonify(place)
@app.route("/js/wlcw/<int:id>")
@cross_origin()
def js_widget_loader_custom_widget(id: int):
widget = CustomWidget.query.get_or_404(id)
schema = CustomWidgetSchema()
return schema.dump(widget)

View File

@ -1,6 +1,6 @@
from flask import flash, redirect, render_template, url_for from flask import flash, redirect, render_template, url_for
from flask_babel import gettext from flask_babel import gettext
from flask_security import current_user, permissions_required from flask_security import current_user
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from project import app, db from project import app, db
@ -21,7 +21,6 @@ from project.views.utils import (
@app.route("/oauth2_client/create", methods=("GET", "POST")) @app.route("/oauth2_client/create", methods=("GET", "POST"))
@permissions_required("oauth2_client:create")
def oauth2_client_create(): def oauth2_client_create():
form = CreateOAuth2ClientForm() form = CreateOAuth2ClientForm()
@ -46,7 +45,6 @@ def oauth2_client_create():
@app.route("/oauth2_client/<int:id>/update", methods=("GET", "POST")) @app.route("/oauth2_client/<int:id>/update", methods=("GET", "POST"))
@permissions_required("oauth2_client:update")
def oauth2_client_update(id): def oauth2_client_update(id):
oauth2_client = OAuth2Client.query.get_or_404(id) oauth2_client = OAuth2Client.query.get_or_404(id)
owner_access_or_401(oauth2_client.user_id) owner_access_or_401(oauth2_client.user_id)
@ -73,7 +71,6 @@ def oauth2_client_update(id):
@app.route("/oauth2_client/<int:id>/delete", methods=("GET", "POST")) @app.route("/oauth2_client/<int:id>/delete", methods=("GET", "POST"))
@permissions_required("oauth2_client:delete")
def oauth2_client_delete(id): def oauth2_client_delete(id):
oauth2_client = OAuth2Client.query.get_or_404(id) oauth2_client = OAuth2Client.query.get_or_404(id)
owner_access_or_401(oauth2_client.user_id) owner_access_or_401(oauth2_client.user_id)
@ -101,7 +98,6 @@ def oauth2_client_delete(id):
@app.route("/oauth2_client/<int:id>") @app.route("/oauth2_client/<int:id>")
@permissions_required("oauth2_client:read")
def oauth2_client(id): def oauth2_client(id):
oauth2_client = OAuth2Client.query.get_or_404(id) oauth2_client = OAuth2Client.query.get_or_404(id)
owner_access_or_401(oauth2_client.user_id) owner_access_or_401(oauth2_client.user_id)
@ -113,7 +109,6 @@ def oauth2_client(id):
@app.route("/oauth2_clients") @app.route("/oauth2_clients")
@permissions_required("oauth2_client:read")
def oauth2_clients(): def oauth2_clients():
oauth2_clients = ( oauth2_clients = (
OAuth2Client.query.filter(OAuth2Client.user_id == current_user.id) OAuth2Client.query.filter(OAuth2Client.user_id == current_user.id)

View File

@ -317,8 +317,7 @@ def manage_required(permission=None):
url_for("manage_admin_unit", id=admin_unit.id) url_for("manage_admin_unit", id=admin_unit.id)
) )
g.admin_unit = admin_unit set_current_admin_unit(admin_unit)
return f(id, *args, **kwargs) return f(id, *args, **kwargs)
return decorated_function return decorated_function

View File

@ -1,5 +1,9 @@
def test_read(client, seeder, utils): from tests.seeder import Seeder
_, admin_unit_id = seeder.setup_base() from tests.utils import UtilActions
def test_read(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_api_access(user_access=False)
custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id) custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id)
url = utils.get_url("api_v1_custom_widget", id=custom_widget_id) url = utils.get_url("api_v1_custom_widget", id=custom_widget_id)
@ -8,7 +12,7 @@ def test_read(client, seeder, utils):
assert response.json["settings"]["color"] == "black" assert response.json["settings"]["color"] == "black"
def test_put(client, seeder, utils, app, db): def test_put(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id) custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id)
@ -24,7 +28,7 @@ def test_put(client, seeder, utils, app, db):
assert custom_widget.widget_type == "search" assert custom_widget.widget_type == "search"
def test_patch(client, seeder, utils, app, db): def test_patch(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id) custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id)
@ -40,7 +44,7 @@ def test_patch(client, seeder, utils, app, db):
assert custom_widget.widget_type == "search" assert custom_widget.widget_type == "search"
def test_delete(client, seeder, utils, app, db): def test_delete(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id) custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id)

View File

@ -1,3 +1,9 @@
def test_read(client, seeder, utils): from tests.seeder import Seeder
response = utils.get_endpoint("api_v1_dump") from tests.utils import UtilActions
def test_read(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_api_access()
url = utils.get_url("api_v1_dump")
response = utils.get_json(url)
utils.assert_response_notFound(response) utils.assert_response_notFound(response)

View File

@ -3,10 +3,11 @@ import base64
import pytest import pytest
from tests.seeder import Seeder from tests.seeder import Seeder
from tests.utils import UtilActions
def test_read(client, app, db, seeder, utils): def test_read(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
with app.app_context(): with app.app_context():
@ -20,12 +21,21 @@ def test_read(client, app, db, seeder, utils):
db.session.commit() db.session.commit()
url = utils.get_url("api_v1_event", id=event_id) url = utils.get_url("api_v1_event", id=event_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert response.json["status"] == "scheduled" assert response.json["status"] == "scheduled"
def test_read_otherDraft(client, app, db, seeder, utils): def test_read_anonym(client, app, db, seeder: Seeder, utils: UtilActions):
app.config["API_READ_ANONYM"] = True
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id)
url = utils.get_url("api_v1_event", id=event_id)
utils.get_json_ok(url)
def test_read_otherDraft(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id, draft=True) event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event", id=event_id) url = utils.get_url("api_v1_event", id=event_id)
@ -33,7 +43,7 @@ def test_read_otherDraft(client, app, db, seeder, utils):
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
def test_read_myDraft(client, app, db, seeder, utils): def test_read_myDraft(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id, draft=True) event_id = seeder.create_event(admin_unit_id, draft=True)
@ -43,7 +53,7 @@ def test_read_myDraft(client, app, db, seeder, utils):
assert response.json["public_status"] == "draft" assert response.json["public_status"] == "draft"
def test_read_otherUnverified(client, app, db, seeder, utils): def test_read_otherUnverified(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base(log_in=False, admin_unit_verified=False) user_id, admin_unit_id = seeder.setup_base(log_in=False, admin_unit_verified=False)
event_id = seeder.create_event(admin_unit_id, draft=True) event_id = seeder.create_event(admin_unit_id, draft=True)
@ -52,7 +62,7 @@ def test_read_otherUnverified(client, app, db, seeder, utils):
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
def test_read_myUnverified(client, app, db, seeder, utils): def test_read_myUnverified(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(admin_unit_verified=False) user_id, admin_unit_id = seeder.setup_api_access(admin_unit_verified=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
@ -61,8 +71,8 @@ def test_read_myUnverified(client, app, db, seeder, utils):
utils.assert_response_ok(response) utils.assert_response_ok(response)
def test_read_co_organizers(client, app, db, seeder, utils): def test_read_co_organizers(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id, organizer_a_id, organizer_b_id = seeder.create_event_with_co_organizers( event_id, organizer_a_id, organizer_b_id = seeder.create_event_with_co_organizers(
admin_unit_id admin_unit_id
) )
@ -74,20 +84,20 @@ def test_read_co_organizers(client, app, db, seeder, utils):
assert response.json["co_organizers"][1]["id"] == organizer_b_id assert response.json["co_organizers"][1]["id"] == organizer_b_id
def test_list(client, seeder, utils): def test_list(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
seeder.create_event_unverified() seeder.create_event_unverified()
url = utils.get_url("api_v1_event_list") url = utils.get_url("api_v1_event_list")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id assert response.json["items"][0]["id"] == event_id
def test_search(client, seeder, utils): def test_search(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
image_id = seeder.upsert_default_image() image_id = seeder.upsert_default_image()
seeder.assign_image_to_event(event_id, image_id) seeder.assign_image_to_event(event_id, image_id)
@ -95,49 +105,52 @@ def test_search(client, seeder, utils):
seeder.create_event_unverified() seeder.create_event_unverified()
url = utils.get_url("api_v1_event_search") url = utils.get_url("api_v1_event_search")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id assert response.json["items"][0]["id"] == event_id
def test_search_is_favored(client, seeder, utils): def test_search_is_favored(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.add_favorite_event(user_id, event_id) seeder.add_favorite_event(user_id, event_id)
url = utils.get_url("api_v1_event_search") url = utils.get_url("api_v1_event_search")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id assert response.json["items"][0]["id"] == event_id
assert response.json["items"][0]["is_favored"] assert response.json["items"][0]["is_favored"]
def test_dates(client, seeder, utils): def test_dates(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
url = utils.get_url("api_v1_event_dates", id=event_id) url = utils.get_url("api_v1_event_dates", id=event_id)
utils.get_ok(url) response = utils.get_json(url)
utils.assert_response_ok(response)
event_id = seeder.create_event(admin_unit_id, draft=True) event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_dates", id=event_id) url = utils.get_url("api_v1_event_dates", id=event_id)
response = utils.get(url) response = utils.get_json(url)
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
_, _, event_id = seeder.create_event_unverified() _, _, event_id = seeder.create_event_unverified()
url = utils.get_url("api_v1_event_dates", id=event_id) url = utils.get_url("api_v1_event_dates", id=event_id)
response = utils.get(url) response = utils.get_json(url)
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
event_id = seeder.create_event( event_id = seeder.create_event(
admin_unit_id, recurrence_rule="RRULE:FREQ=DAILY;COUNT=51" admin_unit_id, recurrence_rule="RRULE:FREQ=DAILY;COUNT=51"
) )
url = utils.get_url("api_v1_event_dates", id=event_id) url = utils.get_url("api_v1_event_dates", id=event_id)
utils.get_ok(url) response = utils.get_json(url)
utils.assert_response_ok(response)
url = utils.get_url("api_v1_event_dates", id=event_id, page=2) url = utils.get_url("api_v1_event_dates", id=event_id, page=2)
utils.get_ok(url) response = utils.get_json(url)
utils.assert_response_ok(response)
def test_dates_myDraft(client, seeder, utils): def test_dates_myDraft(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id, draft=True) event_id = seeder.create_event(admin_unit_id, draft=True)
@ -146,7 +159,7 @@ def test_dates_myDraft(client, seeder, utils):
utils.assert_response_ok(response) utils.assert_response_ok(response)
def test_dates_myUnverified(client, seeder, utils): def test_dates_myUnverified(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(admin_unit_verified=False) user_id, admin_unit_id = seeder.setup_api_access(admin_unit_verified=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
@ -180,7 +193,7 @@ def create_put(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"variant", ["normal", "legacy", "recurrence", "two_date_definitions"] "variant", ["normal", "legacy", "recurrence", "two_date_definitions"]
) )
def test_put(client, seeder, utils, app, db, mocker, variant): def test_put(client, seeder: Seeder, utils: UtilActions, app, db, mocker, variant):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -270,7 +283,7 @@ def test_put(client, seeder, utils, app, db, mocker, variant):
assert len_dates == 1 assert len_dates == 1
def test_put_invalidRecurrenceRule(client, seeder, utils, app): def test_put_invalidRecurrenceRule(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -284,7 +297,7 @@ def test_put_invalidRecurrenceRule(client, seeder, utils, app):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_put_missingName(client, seeder, utils, app): def test_put_missingName(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -298,7 +311,7 @@ def test_put_missingName(client, seeder, utils, app):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_put_missingPlace(client, seeder, utils, app): def test_put_missingPlace(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -312,7 +325,7 @@ def test_put_missingPlace(client, seeder, utils, app):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_put_placeFromAnotherAdminUnit(client, seeder, utils, app): def test_put_placeFromAnotherAdminUnit(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
@ -326,7 +339,7 @@ def test_put_placeFromAnotherAdminUnit(client, seeder, utils, app):
utils.assert_response_api_error(response, "Check Violation") utils.assert_response_api_error(response, "Check Violation")
def test_put_missingOrganizer(client, seeder, utils, app): def test_put_missingOrganizer(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -340,7 +353,9 @@ def test_put_missingOrganizer(client, seeder, utils, app):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_put_organizerFromAnotherAdminUnit(client, seeder, utils, app): def test_put_organizerFromAnotherAdminUnit(
client, seeder: Seeder, utils: UtilActions, app
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -354,7 +369,7 @@ def test_put_organizerFromAnotherAdminUnit(client, seeder, utils, app):
utils.assert_response_api_error(response, "Check Violation") utils.assert_response_api_error(response, "Check Violation")
def test_put_co_organizers(client, seeder, utils, app, db): def test_put_co_organizers(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -381,7 +396,9 @@ def test_put_co_organizers(client, seeder, utils, app, db):
assert event.co_organizers[1].id == organizer_b_id assert event.co_organizers[1].id == organizer_b_id
def test_put_co_organizerFromAnotherAdminUnit(client, seeder, utils, app): def test_put_co_organizerFromAnotherAdminUnit(
client, seeder: Seeder, utils: UtilActions, app
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -401,7 +418,7 @@ def test_put_co_organizerFromAnotherAdminUnit(client, seeder, utils, app):
utils.assert_response_api_error(response, "Check Violation") utils.assert_response_api_error(response, "Check Violation")
def test_put_invalidDateFormat(client, seeder, utils, app): def test_put_invalidDateFormat(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -414,7 +431,7 @@ def test_put_invalidDateFormat(client, seeder, utils, app):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_put_startAfterEnd(client, seeder: Seeder, utils, app): def test_put_startAfterEnd(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -429,7 +446,9 @@ def test_put_startAfterEnd(client, seeder: Seeder, utils, app):
utils.assert_response_bad_request(response) utils.assert_response_bad_request(response)
def test_put_durationMoreThanMaxAllowedDuration(client, seeder, utils, app): def test_put_durationMoreThanMaxAllowedDuration(
client, seeder: Seeder, utils: UtilActions, app
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -444,7 +463,7 @@ def test_put_durationMoreThanMaxAllowedDuration(client, seeder, utils, app):
utils.assert_response_bad_request(response) utils.assert_response_bad_request(response)
def test_put_categories(client, seeder, utils, app, db): def test_put_categories(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -465,7 +484,7 @@ def test_put_categories(client, seeder, utils, app, db):
assert event.category.name == "Art" assert event.category.name == "Art"
def test_put_dateWithTimezone(client, seeder, utils, app, db): def test_put_dateWithTimezone(client, seeder: Seeder, utils: UtilActions, app, db):
from project.dateutils import create_berlin_date from project.dateutils import create_berlin_date
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
@ -488,7 +507,7 @@ def test_put_dateWithTimezone(client, seeder, utils, app, db):
assert event.date_definitions[0].start == expected assert event.date_definitions[0].start == expected
def test_put_dateWithoutTimezone(client, seeder, utils, app, db): def test_put_dateWithoutTimezone(client, seeder: Seeder, utils: UtilActions, app, db):
from project.dateutils import create_berlin_date from project.dateutils import create_berlin_date
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
@ -511,7 +530,9 @@ def test_put_dateWithoutTimezone(client, seeder, utils, app, db):
assert event.date_definitions[0].start == expected assert event.date_definitions[0].start == expected
def test_put_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker): def test_put_referencedEventUpdate_sendsMail(
client, seeder: Seeder, utils: UtilActions, app, mocker
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event_via_api(admin_unit_id) event_id = seeder.create_event_via_api(admin_unit_id)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -532,7 +553,7 @@ def test_put_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker)
def test_put_referencedEventNonDirtyUpdate_doesNotSendMail( def test_put_referencedEventNonDirtyUpdate_doesNotSendMail(
client, seeder, utils, app, mocker client, seeder: Seeder, utils: UtilActions, app, mocker
): ):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event_via_api(admin_unit_id) event_id = seeder.create_event_via_api(admin_unit_id)
@ -553,7 +574,7 @@ def test_put_referencedEventNonDirtyUpdate_doesNotSendMail(
mail_mock.assert_not_called() mail_mock.assert_not_called()
def test_patch(client, seeder, utils, app, db): def test_patch(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
@ -569,7 +590,7 @@ def test_patch(client, seeder, utils, app, db):
assert event.description == "Neu" assert event.description == "Neu"
def test_patch_startAfterEnd(client, seeder, utils, app, db): def test_patch_startAfterEnd(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
@ -586,7 +607,9 @@ def test_patch_startAfterEnd(client, seeder, utils, app, db):
utils.assert_response_bad_request(response) utils.assert_response_bad_request(response)
def test_patch_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker): def test_patch_referencedEventUpdate_sendsMail(
client, seeder: Seeder, utils: UtilActions, app, mocker
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event_via_api(admin_unit_id) event_id = seeder.create_event_via_api(admin_unit_id)
@ -602,7 +625,9 @@ def test_patch_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocke
utils.assert_send_mail_called(mail_mock, "other@test.de") utils.assert_send_mail_called(mail_mock, "other@test.de")
def test_patch_photo(client, seeder, utils, app, db, requests_mock): def test_patch_photo(
client, seeder: Seeder, utils: UtilActions, app, db, requests_mock
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
@ -625,7 +650,7 @@ def test_patch_photo(client, seeder, utils, app, db, requests_mock):
assert event.photo.encoding_format == "image/png" assert event.photo.encoding_format == "image/png"
def test_patch_photo_copyright(client, db, seeder, utils, app): def test_patch_photo_copyright(client, db, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
image_id = seeder.upsert_default_image() image_id = seeder.upsert_default_image()
@ -647,7 +672,7 @@ def test_patch_photo_copyright(client, db, seeder, utils, app):
assert event.photo.copyright_text == "Heiner" assert event.photo.copyright_text == "Heiner"
def test_patch_photo_delete(client, db, seeder, utils, app): def test_patch_photo_delete(client, db, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
image_id = seeder.upsert_default_image() image_id = seeder.upsert_default_image()
@ -670,7 +695,7 @@ def test_patch_photo_delete(client, db, seeder, utils, app):
assert image is None assert image is None
def test_delete(client, seeder, utils, app, db): def test_delete(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
@ -685,8 +710,8 @@ def test_delete(client, seeder, utils, app, db):
assert event is None assert event is None
def test_report_mail(client, seeder, utils, app, mocker): def test_report_mail(client, seeder: Seeder, utils: UtilActions, app, mocker):
user_id, admin_unit_id = seeder.setup_base(admin=False, log_in=False) user_id, admin_unit_id = seeder.setup_api_access(admin=False, user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.create_user(email="admin@test.de", admin=True) seeder.create_user(email="admin@test.de", admin=True)
seeder.create_user(email="normal@test.de", admin=False) seeder.create_user(email="normal@test.de", admin=False)

View File

@ -1,6 +1,10 @@
def test_list(client, seeder, utils): from tests.seeder import Seeder
user_id, admin_unit_id = seeder.setup_base() from tests.utils import UtilActions
def test_list(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
seeder.create_event(admin_unit_id) seeder.create_event(admin_unit_id)
url = utils.get_url("api_v1_event_category_list") url = utils.get_url("api_v1_event_category_list")
utils.get_ok(url) utils.get_json_ok(url)

View File

@ -1,17 +1,22 @@
def test_read(client, seeder, utils): from tests.seeder import Seeder
user_id, admin_unit_id = seeder.setup_base(log_in=False) from tests.utils import UtilActions
def test_read(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
seeder.create_event(admin_unit_id) seeder.create_event(admin_unit_id)
url = utils.get_url("api_v1_event_date", id=1) url = utils.get_url("api_v1_event_date", id=1)
utils.get_ok(url) response = utils.get_json(url)
utils.assert_response_ok(response)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
draft_url = utils.get_url("api_v1_event_date", id=2) draft_url = utils.get_url("api_v1_event_date", id=2)
response = utils.get(draft_url) response = utils.get_json(draft_url)
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
seeder.create_event_unverified() seeder.create_event_unverified()
unverified_url = utils.get_url("api_v1_event_date", id=3) unverified_url = utils.get_url("api_v1_event_date", id=3)
response = utils.get(unverified_url) response = utils.get_json(unverified_url)
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
seeder.authorize_api_access(user_id, admin_unit_id) seeder.authorize_api_access(user_id, admin_unit_id)
@ -19,7 +24,7 @@ def test_read(client, seeder, utils):
utils.assert_response_ok(response) utils.assert_response_ok(response)
def test_read_myUnverified(client, seeder, utils): def test_read_myUnverified(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_api_access(admin_unit_verified=False) _, admin_unit_id = seeder.setup_api_access(admin_unit_verified=False)
seeder.create_event(admin_unit_id) seeder.create_event(admin_unit_id)
@ -28,75 +33,75 @@ def test_read_myUnverified(client, seeder, utils):
utils.assert_response_ok(response) utils.assert_response_ok(response)
def test_list(client, seeder, utils): def test_list(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
seeder.create_event(admin_unit_id) seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
seeder.create_event_unverified() seeder.create_event_unverified()
url = utils.get_url("api_v1_event_date_list") url = utils.get_url("api_v1_event_date_list")
response = utils.get_ok(url) response = utils.get_json(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == 1 assert response.json["items"][0]["id"] == 1
def test_search(client, seeder, utils, app, db): def test_search(client, seeder: Seeder, utils: UtilActions, app, db):
from project.dateutils import create_berlin_date from project.dateutils import create_berlin_date
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
start = create_berlin_date(2020, 10, 3, 10) start = create_berlin_date(2020, 10, 3, 10)
event_id = seeder.create_event(admin_unit_id, start=start) event_id = seeder.create_event(admin_unit_id, start=start)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
seeder.create_event_unverified() seeder.create_event_unverified()
url = utils.get_url("api_v1_event_date_search", sort="-rating") url = utils.get_url("api_v1_event_date_search", sort="-rating")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == event_id assert response.json["items"][0]["event"]["id"] == event_id
assert response.json["items"][0]["start"] == "2020-10-03T10:00:00+02:00" assert response.json["items"][0]["start"] == "2020-10-03T10:00:00+02:00"
url = utils.get_url("api_v1_event_date_search", keyword="name") url = utils.get_url("api_v1_event_date_search", keyword="name")
response = utils.get_ok(url) response = utils.get_json_ok(url)
url = utils.get_url("api_v1_event_date_search", category_id=0) url = utils.get_url("api_v1_event_date_search", category_id=0)
response = utils.get_ok(url) response = utils.get_json_ok(url)
url = utils.get_url("api_v1_event_date_search", category_id=2000) url = utils.get_url("api_v1_event_date_search", category_id=2000)
response = utils.get_ok(url) response = utils.get_json_ok(url)
url = utils.get_url("api_v1_event_date_search", weekday=1) url = utils.get_url("api_v1_event_date_search", weekday=1)
response = utils.get_ok(url) response = utils.get_json_ok(url)
url = utils.get_url( url = utils.get_url(
"api_v1_event_date_search", date_from="2020-10-03", date_to="2021-10-03" "api_v1_event_date_search", date_from="2020-10-03", date_to="2021-10-03"
) )
response = utils.get_ok(url) response = utils.get_json_ok(url)
url = utils.get_url( url = utils.get_url(
"api_v1_event_date_search", coordinate="51.9077888,10.4333312", distance=500 "api_v1_event_date_search", coordinate="51.9077888,10.4333312", distance=500
) )
response = utils.get_ok(url) response = utils.get_json_ok(url)
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
url = utils.get_url("api_v1_event_date_search", organizer_id=organizer_id) url = utils.get_url("api_v1_event_date_search", organizer_id=organizer_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
event_place_id = seeder.upsert_default_event_place(admin_unit_id) event_place_id = seeder.upsert_default_event_place(admin_unit_id)
url = utils.get_url("api_v1_event_date_search", event_place_id=event_place_id) url = utils.get_url("api_v1_event_date_search", event_place_id=event_place_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
url = utils.get_url("api_v1_event_date_search", organization_id=admin_unit_id) url = utils.get_url("api_v1_event_date_search", organization_id=admin_unit_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
listed_event_id = seeder.create_event(admin_unit_id) listed_event_id = seeder.create_event(admin_unit_id)
event_list_id = seeder.create_event_list(admin_unit_id, listed_event_id) event_list_id = seeder.create_event_list(admin_unit_id, listed_event_id)
url = utils.get_url("api_v1_event_date_search", event_list_id=event_list_id) url = utils.get_url("api_v1_event_date_search", event_list_id=event_list_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == listed_event_id assert response.json["items"][0]["event"]["id"] == listed_event_id
url = utils.get_url("api_v1_event_date_search", status="scheduled") url = utils.get_url("api_v1_event_date_search", status="scheduled")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 2 assert len(response.json["items"]) == 2
with app.app_context(): with app.app_context():
@ -107,18 +112,18 @@ def test_search(client, seeder, utils, app, db):
db.session.commit() db.session.commit()
url = utils.get_url("api_v1_event_date_search", status="scheduled") url = utils.get_url("api_v1_event_date_search", status="scheduled")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
url = utils.get_url("api_v1_event_date_search", status=["scheduled", "cancelled"]) url = utils.get_url("api_v1_event_date_search", status=["scheduled", "cancelled"])
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 2 assert len(response.json["items"]) == 2
def test_search_oneDay(client, seeder, utils): def test_search_oneDay(client, seeder: Seeder, utils: UtilActions):
from project.dateutils import create_berlin_date from project.dateutils import create_berlin_date
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
start = create_berlin_date(2020, 10, 3, 10) start = create_berlin_date(2020, 10, 3, 10)
end = create_berlin_date(2020, 10, 3, 11) end = create_berlin_date(2020, 10, 3, 11)
@ -128,18 +133,18 @@ def test_search_oneDay(client, seeder, utils):
url = utils.get_url( url = utils.get_url(
"api_v1_event_date_search", date_from="2020-10-03", date_to="2020-10-03" "api_v1_event_date_search", date_from="2020-10-03", date_to="2020-10-03"
) )
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == event_id assert response.json["items"][0]["event"]["id"] == event_id
def test_search_is_favored(client, seeder, utils): def test_search_is_favored(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.add_favorite_event(user_id, event_id) seeder.add_favorite_event(user_id, event_id)
url = utils.get_url("api_v1_event_date_search") url = utils.get_url("api_v1_event_date_search")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == event_id assert response.json["items"][0]["event"]["id"] == event_id
assert response.json["items"][0]["event"]["is_favored"] assert response.json["items"][0]["event"]["is_favored"]

View File

@ -1,13 +1,17 @@
def test_read(client, app, db, seeder, utils): from tests.seeder import Seeder
_, admin_unit_id = seeder.setup_base() from tests.utils import UtilActions
def test_read(client, app, db, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_api_access(user_access=False)
event_list_id = seeder.create_event_list(admin_unit_id) event_list_id = seeder.create_event_list(admin_unit_id)
url = utils.get_url("api_v1_event_list_model", id=event_list_id) url = utils.get_url("api_v1_event_list_model", id=event_list_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert response.json["id"] == event_list_id assert response.json["id"] == event_list_id
def test_put(client, seeder, utils, app, db): def test_put(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
event_list_id = seeder.create_event_list(admin_unit_id) event_list_id = seeder.create_event_list(admin_unit_id)
@ -22,7 +26,7 @@ def test_put(client, seeder, utils, app, db):
assert event_list.name == "Neuer Name" assert event_list.name == "Neuer Name"
def test_patch(client, seeder, utils, app, db): def test_patch(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
event_list_id = seeder.create_event_list(admin_unit_id) event_list_id = seeder.create_event_list(admin_unit_id)
@ -37,7 +41,7 @@ def test_patch(client, seeder, utils, app, db):
assert event_list.name == "Neuer Name" assert event_list.name == "Neuer Name"
def test_delete(client, seeder, utils, app, db): def test_delete(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
event_list_id = seeder.create_event_list(admin_unit_id) event_list_id = seeder.create_event_list(admin_unit_id)
@ -52,18 +56,18 @@ def test_delete(client, seeder, utils, app, db):
assert event_list is None assert event_list is None
def test_events(client, seeder, utils): def test_events(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_base() _, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
event_list_id = seeder.create_event_list(admin_unit_id, event_id) event_list_id = seeder.create_event_list(admin_unit_id, event_id)
url = utils.get_url("api_v1_event_list_event_list", id=event_list_id) url = utils.get_url("api_v1_event_list_event_list", id=event_list_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id assert response.json["items"][0]["id"] == event_id
def test_events_put(client, seeder, utils, app, db): def test_events_put(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
event_list_id = seeder.create_event_list(admin_unit_id) event_list_id = seeder.create_event_list(admin_unit_id)
@ -82,7 +86,7 @@ def test_events_put(client, seeder, utils, app, db):
assert event_list.events[0].id == event_id assert event_list.events[0].id == event_id
def test_events_delete(client, seeder, utils, app, db): def test_events_delete(client, seeder: Seeder, utils: UtilActions, app, db):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
event_list_id = seeder.create_event_list(admin_unit_id, event_id) event_list_id = seeder.create_event_list(admin_unit_id, event_id)

View File

@ -1,5 +1,9 @@
def test_read(client, seeder, utils): from tests.seeder import Seeder
user_id, admin_unit_id = seeder.setup_base() from tests.utils import UtilActions
def test_read(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
( (
other_user_id, other_user_id,
other_admin_unit_id, other_admin_unit_id,
@ -8,4 +12,4 @@ def test_read(client, seeder, utils):
) = seeder.create_any_reference(admin_unit_id) ) = seeder.create_any_reference(admin_unit_id)
url = utils.get_url("api_v1_event_reference", id=reference_id) url = utils.get_url("api_v1_event_reference", id=reference_id)
utils.get_ok(url) utils.get_json_ok(url)

View File

@ -1,27 +1,30 @@
import pytest import pytest
from tests.seeder import Seeder
from tests.utils import UtilActions
def test_read(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base(admin=True, log_in=False) def test_read(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
url = utils.get_url("api_v1_organization", id=admin_unit_id) url = utils.get_url("api_v1_organization", id=admin_unit_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert "can_verify_other" not in response.json assert "can_verify_other" not in response.json
seeder.authorize_api_access(user_id, admin_unit_id) seeder.authorize_api_access(user_id, admin_unit_id)
response = utils.get_json(url) response = utils.get_json_ok(url)
assert "can_verify_other" in response.json assert "can_verify_other" in response.json
def test_list(client, seeder, utils): def test_list(client, seeder: Seeder, utils: UtilActions):
seeder.setup_base() seeder.setup_api_access(user_access=False)
url = utils.get_url("api_v1_organization_list", keyword="crew") url = utils.get_url("api_v1_organization_list", keyword="crew")
utils.get_ok(url) utils.get_json_ok(url)
def test_list_unverified(client, app, seeder, utils): def test_list_unverified(client, app, seeder: Seeder, utils: UtilActions):
_, verified_admin_unit_id = seeder.setup_base( user_id, verified_admin_unit_id = seeder.setup_base(
email="verified@test.de", email="verified@test.de",
log_in=False, log_in=False,
name="Verified", name="Verified",
@ -33,17 +36,18 @@ def test_list_unverified(client, app, seeder, utils):
name="Unverified", name="Unverified",
admin_unit_verified=False, admin_unit_verified=False,
) )
seeder.grant_client_credentials_api_access(user_id)
# Unauthorisierte Nutzer sehen nur verifizierte Organisationen # Unauthorisierte Nutzer sehen nur verifizierte Organisationen
url = utils.get_url("api_v1_organization_list") url = utils.get_url("api_v1_organization_list")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == verified_admin_unit_id assert response.json["items"][0]["id"] == verified_admin_unit_id
# user_id1 sieht verified_admin_unit_id, weil sie verifiziert ist, # user_id1 sieht verified_admin_unit_id, weil sie verifiziert ist,
# aber nicht unverified_admin_unit_id, weil sie nicht verifiziert ist. # aber nicht unverified_admin_unit_id, weil sie nicht verifiziert ist.
utils.login("verified@test.de") utils.login("verified@test.de")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == verified_admin_unit_id assert response.json["items"][0]["id"] == verified_admin_unit_id
@ -56,7 +60,7 @@ def test_list_unverified(client, app, seeder, utils):
utils.logout() utils.logout()
utils.login("admin@eventcally.com") utils.login("admin@eventcally.com")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 3 assert len(response.json["items"]) == 3
assert response.json["items"][0]["id"] == eventcally_id assert response.json["items"][0]["id"] == eventcally_id
assert response.json["items"][1]["id"] == unverified_admin_unit_id assert response.json["items"][1]["id"] == unverified_admin_unit_id
@ -66,12 +70,12 @@ def test_list_unverified(client, app, seeder, utils):
seeder.create_user("admin@test.de", admin=True) seeder.create_user("admin@test.de", admin=True)
utils.logout() utils.logout()
utils.login("admin@test.de") utils.login("admin@test.de")
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 3 assert len(response.json["items"]) == 3
def test_event_date_search(client, seeder, utils): def test_event_date_search(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
seeder.create_event_unverified() seeder.create_event_unverified()
@ -79,7 +83,7 @@ def test_event_date_search(client, seeder, utils):
url = utils.get_url( url = utils.get_url(
"api_v1_organization_event_date_search", id=admin_unit_id, sort="-rating" "api_v1_organization_event_date_search", id=admin_unit_id, sort="-rating"
) )
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == event_id assert response.json["items"][0]["event"]["id"] == event_id
@ -90,14 +94,14 @@ def test_event_date_search(client, seeder, utils):
assert response.json["items"][1]["event"]["public_status"] == "draft" assert response.json["items"][1]["event"]["public_status"] == "draft"
def test_event_search(client, seeder, utils): def test_event_search(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
seeder.create_event_unverified() seeder.create_event_unverified()
url = utils.get_url("api_v1_organization_event_search", id=admin_unit_id) url = utils.get_url("api_v1_organization_event_search", id=admin_unit_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id assert response.json["items"][0]["id"] == event_id
@ -111,17 +115,17 @@ def test_event_search(client, seeder, utils):
) )
def test_organizers(client, seeder, utils): def test_organizers(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
seeder.upsert_default_event_organizer(admin_unit_id) seeder.upsert_default_event_organizer(admin_unit_id)
url = utils.get_url( url = utils.get_url(
"api_v1_organization_organizer_list", id=admin_unit_id, name="crew" "api_v1_organization_organizer_list", id=admin_unit_id, name="crew"
) )
utils.get_ok(url) utils.get_json_ok(url)
def test_organizers_post(client, seeder, utils, app): def test_organizers_post(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
url = utils.get_url("api_v1_organization_organizer_list", id=admin_unit_id) url = utils.get_url("api_v1_organization_organizer_list", id=admin_unit_id)
@ -140,13 +144,13 @@ def test_organizers_post(client, seeder, utils, app):
assert organizer is not None assert organizer is not None
def test_events(client, seeder, utils): def test_events(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True) seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_organization_event_list", id=admin_unit_id) url = utils.get_url("api_v1_organization_event_list", id=admin_unit_id)
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id assert response.json["items"][0]["id"] == event_id
@ -178,7 +182,7 @@ def prepare_events_post_data(seeder, utils, legacy=False):
@pytest.mark.parametrize("variant", ["allday", "legacy", "two_date_definitions"]) @pytest.mark.parametrize("variant", ["allday", "legacy", "two_date_definitions"])
def test_events_post(client, seeder, utils, app, variant): def test_events_post(client, seeder: Seeder, utils: UtilActions, app, variant):
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data( url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
seeder, utils, variant == "legacy" seeder, utils, variant == "legacy"
) )
@ -215,7 +219,7 @@ def test_events_post(client, seeder, utils, app, variant):
assert len(event.date_definitions) == 1 assert len(event.date_definitions) == 1
def test_events_post_co_organizers(client, seeder, utils, app, db): def test_events_post_co_organizers(client, seeder: Seeder, utils: UtilActions, app, db):
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data( url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
seeder, utils seeder, utils
) )
@ -239,7 +243,7 @@ def test_events_post_co_organizers(client, seeder, utils, app, db):
assert event.co_organizers[1].id == organizer_b_id assert event.co_organizers[1].id == organizer_b_id
def test_events_post_photo_no_data(client, seeder, utils, app): def test_events_post_photo_no_data(client, seeder: Seeder, utils: UtilActions, app):
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data( url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
seeder, utils seeder, utils
) )
@ -252,7 +256,7 @@ def test_events_post_photo_no_data(client, seeder, utils, app):
assert error["message"] == "Either image_url or image_base64 has to be defined." assert error["message"] == "Either image_url or image_base64 has to be defined."
def test_events_post_photo_too_small(client, seeder, utils, app): def test_events_post_photo_too_small(client, seeder: Seeder, utils: UtilActions, app):
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data( url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
seeder, utils seeder, utils
) )
@ -267,13 +271,15 @@ def test_events_post_photo_too_small(client, seeder, utils, app):
assert error["message"] == "Image is too small (1x1px). At least 320x320px." assert error["message"] == "Image is too small (1x1px). At least 320x320px."
def test_events_import(client, seeder, utils, app, db, shared_datadir): def test_events_import(
client, seeder: Seeder, utils: UtilActions, app, db, shared_datadir
):
external_url = "https://www.harzinfo.de/event/xy" external_url = "https://www.harzinfo.de/event/xy"
utils.mock_get_request_with_file( utils.mock_get_request_with_file(
external_url, shared_datadir, "harzinfo_biathlon.html" external_url, shared_datadir, "harzinfo_biathlon.html"
) )
_, admin_unit_id = seeder.setup_base() _, admin_unit_id = seeder.setup_api_access()
url = utils.get_url("api_v1_organization_event_import", id=admin_unit_id) url = utils.get_url("api_v1_organization_event_import", id=admin_unit_id)
response = utils.post_json(url, {"url": external_url}) response = utils.post_json(url, {"url": external_url})
@ -294,15 +300,15 @@ def test_events_import(client, seeder, utils, app, db, shared_datadir):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_places(client, seeder, utils): def test_places(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
seeder.upsert_default_event_place(admin_unit_id) seeder.upsert_default_event_place(admin_unit_id)
url = utils.get_url("api_v1_organization_place_list", id=admin_unit_id, name="crew") url = utils.get_url("api_v1_organization_place_list", id=admin_unit_id, name="crew")
utils.get_ok(url) utils.get_json_ok(url)
def test_places_post(client, seeder, utils, app): def test_places_post(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
url = utils.get_url("api_v1_organization_place_list", id=admin_unit_id) url = utils.get_url("api_v1_organization_place_list", id=admin_unit_id)
@ -331,19 +337,19 @@ def test_places_post(client, seeder, utils, app):
assert place.location.city == "Goslar" assert place.location.city == "Goslar"
def test_event_lists(client, seeder, utils): def test_event_lists(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_base() _, admin_unit_id = seeder.setup_api_access(user_access=False)
event_list_id = seeder.create_event_list(admin_unit_id, name="Meine Liste") event_list_id = seeder.create_event_list(admin_unit_id, name="Meine Liste")
url = utils.get_url( url = utils.get_url(
"api_v1_organization_event_list_list", id=admin_unit_id, name="meine" "api_v1_organization_event_list_list", id=admin_unit_id, name="meine"
) )
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_list_id assert response.json["items"][0]["id"] == event_list_id
def test_event_lists_post(client, seeder, utils, app): def test_event_lists_post(client, seeder: Seeder, utils: UtilActions, app):
_, admin_unit_id = seeder.setup_api_access() _, admin_unit_id = seeder.setup_api_access()
url = utils.get_url("api_v1_organization_event_list_list", id=admin_unit_id) url = utils.get_url("api_v1_organization_event_list_list", id=admin_unit_id)
@ -368,8 +374,8 @@ def test_event_lists_post(client, seeder, utils, app):
assert event_list.name == "Neue Liste" assert event_list.name == "Neue Liste"
def test_event_lists_status(client, seeder, utils): def test_event_lists_status(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_base() _, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
event_list_id = seeder.create_event_list( event_list_id = seeder.create_event_list(
admin_unit_id, event_id, name="Meine Liste" admin_unit_id, event_id, name="Meine Liste"
@ -381,14 +387,14 @@ def test_event_lists_status(client, seeder, utils):
event_id=event_id, event_id=event_id,
name="meine", name="meine",
) )
response = utils.get_ok(url) response = utils.get_json_ok(url)
assert len(response.json["items"]) == 1 assert len(response.json["items"]) == 1
assert response.json["items"][0]["event_list"]["id"] == event_list_id assert response.json["items"][0]["event_list"]["id"] == event_list_id
assert response.json["items"][0]["contains_event"] assert response.json["items"][0]["contains_event"]
def test_references_incoming(client, seeder, utils): def test_references_incoming(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
( (
other_user_id, other_user_id,
other_admin_unit_id, other_admin_unit_id,
@ -401,11 +407,11 @@ def test_references_incoming(client, seeder, utils):
id=admin_unit_id, id=admin_unit_id,
name="crew", name="crew",
) )
utils.get_ok(url) utils.get_json_ok(url)
def test_references_outgoing(client, seeder, utils): def test_references_outgoing(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
event_id = seeder.create_event(admin_unit_id) event_id = seeder.create_event(admin_unit_id)
other_user_id = seeder.create_user("other@test.de") other_user_id = seeder.create_user("other@test.de")
@ -417,13 +423,17 @@ def test_references_outgoing(client, seeder, utils):
id=admin_unit_id, id=admin_unit_id,
name="crew", name="crew",
) )
utils.get_ok(url) utils.get_json_ok(url)
@pytest.mark.parametrize("session_based", [True, False]) @pytest.mark.parametrize("session_based", [True, False])
def test_outgoing_relation_list(client, seeder, utils, session_based): def test_outgoing_relation_list(
client, seeder: Seeder, utils: UtilActions, session_based
):
user_id, admin_unit_id = ( user_id, admin_unit_id = (
seeder.setup_base() if session_based else seeder.setup_api_access() seeder.setup_api_access(user_access=False)
if session_based
else seeder.setup_api_access()
) )
( (
other_user_id, other_user_id,
@ -443,8 +453,10 @@ def test_outgoing_relation_list(client, seeder, utils, session_based):
assert response.json["items"][0]["target_organization"]["id"] == other_admin_unit_id assert response.json["items"][0]["target_organization"]["id"] == other_admin_unit_id
def test_outgoing_relation_list_notAuthenticated(client, seeder, utils): def test_outgoing_relation_list_notAuthenticated(
user_id, admin_unit_id = seeder.setup_base(log_in=False) client, seeder: Seeder, utils: UtilActions
):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
( (
other_user_id, other_user_id,
other_admin_unit_id, other_admin_unit_id,
@ -459,7 +471,7 @@ def test_outgoing_relation_list_notAuthenticated(client, seeder, utils):
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
def test_outgoing_relation_post(client, app, seeder, utils, db): def test_outgoing_relation_post(client, app, seeder: Seeder, utils: UtilActions, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
other_user_id = seeder.create_user("other@test.de") other_user_id = seeder.create_user("other@test.de")
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew") other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
@ -487,7 +499,9 @@ def test_outgoing_relation_post(client, app, seeder, utils, db):
assert relation.auto_verify_event_reference_requests assert relation.auto_verify_event_reference_requests
def test_outgoing_relation_post_unknownTarget(client, app, seeder, utils): def test_outgoing_relation_post_unknownTarget(
client, app, seeder: Seeder, utils: UtilActions
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
url = utils.get_url( url = utils.get_url(
@ -503,7 +517,9 @@ def test_outgoing_relation_post_unknownTarget(client, app, seeder, utils):
utils.assert_response_unprocessable_entity(response) utils.assert_response_unprocessable_entity(response)
def test_outgoing_relation_post_selfReference(client, app, seeder, utils): def test_outgoing_relation_post_selfReference(
client, app, seeder: Seeder, utils: UtilActions
):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
url = utils.get_url( url = utils.get_url(
@ -519,8 +535,8 @@ def test_outgoing_relation_post_selfReference(client, app, seeder, utils):
utils.assert_response_bad_request(response) utils.assert_response_bad_request(response)
def test_organization_invitation_list(client, seeder, utils): def test_organization_invitation_list(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_base() user_id, admin_unit_id = seeder.setup_api_access()
invitation_id = seeder.create_admin_unit_invitation(admin_unit_id) invitation_id = seeder.create_admin_unit_invitation(admin_unit_id)
url = utils.get_url( url = utils.get_url(
@ -573,17 +589,17 @@ def test_organization_invitation_list_post(client, app, seeder, db, utils, mocke
utils.assert_send_mail_called(mail_mock, "invited@test.de", invitation_url) utils.assert_send_mail_called(mail_mock, "invited@test.de", invitation_url)
def test_custom_widgets(client, seeder, utils): def test_custom_widgets(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_base() _, admin_unit_id = seeder.setup_api_access(user_access=False)
seeder.insert_event_custom_widget(admin_unit_id) seeder.insert_event_custom_widget(admin_unit_id)
url = utils.get_url( url = utils.get_url(
"api_v1_organization_custom_widget_list", id=admin_unit_id, name="mein" "api_v1_organization_custom_widget_list", id=admin_unit_id, name="mein"
) )
utils.get_ok(url) utils.get_json_ok(url)
def test_custom_widgets_post(client, seeder, utils, app): def test_custom_widgets_post(client, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
url = utils.get_url("api_v1_organization_custom_widget_list", id=admin_unit_id) url = utils.get_url("api_v1_organization_custom_widget_list", id=admin_unit_id)

View File

@ -1,12 +1,16 @@
def test_read(client, seeder, utils): from tests.seeder import Seeder
user_id, admin_unit_id = seeder.setup_base() from tests.utils import UtilActions
def test_read(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
url = utils.get_url("api_v1_organizer", id=organizer_id) url = utils.get_url("api_v1_organizer", id=organizer_id)
utils.get_ok(url) utils.get_json_ok(url)
def test_put(client, seeder, utils, app, db): def test_put(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
@ -21,7 +25,7 @@ def test_put(client, seeder, utils, app, db):
assert organizer.name == "Neuer Name" assert organizer.name == "Neuer Name"
def test_patch(client, seeder, utils, app, db): def test_patch(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
@ -37,7 +41,7 @@ def test_patch(client, seeder, utils, app, db):
assert organizer.phone == "55555" assert organizer.phone == "55555"
def test_delete(client, seeder, utils, app, db): def test_delete(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)

View File

@ -1,12 +1,16 @@
def test_read(client, app, db, seeder, utils): from tests.seeder import Seeder
user_id, admin_unit_id = seeder.setup_base() from tests.utils import UtilActions
def test_read(client, app, db, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access(user_access=False)
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
url = utils.get_url("api_v1_place", id=place_id) url = utils.get_url("api_v1_place", id=place_id)
utils.get_ok(url) utils.get_json_ok(url)
def test_put(client, seeder, utils, app, db): def test_put(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -37,7 +41,7 @@ def test_put_nonActiveReturnsUnauthorized(client, seeder, db, utils, app):
utils.assert_response_unauthorized(response) utils.assert_response_unauthorized(response)
def test_patch(client, seeder, utils, app, db): def test_patch(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -53,7 +57,7 @@ def test_patch(client, seeder, utils, app, db):
assert place.description == "Klasse" assert place.description == "Klasse"
def test_patch_location(db, seeder, utils, app): def test_patch_location(db, seeder: Seeder, utils: UtilActions, app):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)
@ -85,7 +89,7 @@ def test_patch_location(db, seeder, utils, app):
assert place.location.postalCode == "54321" assert place.location.postalCode == "54321"
def test_delete(client, seeder, utils, app, db): def test_delete(client, seeder: Seeder, utils: UtilActions, app, db):
user_id, admin_unit_id = seeder.setup_api_access() user_id, admin_unit_id = seeder.setup_api_access()
place_id = seeder.upsert_default_event_place(admin_unit_id) place_id = seeder.upsert_default_event_place(admin_unit_id)

View File

@ -1,5 +1,5 @@
def test_organization_invitation_list(client, seeder, utils): def test_organization_invitation_list(client, seeder, utils):
_, admin_unit_id = seeder.setup_base(log_in=False) _, admin_unit_id = seeder.setup_api_access(user_access=False)
invitation_id = seeder.create_admin_unit_invitation(admin_unit_id) invitation_id = seeder.create_admin_unit_invitation(admin_unit_id)
seeder.create_user("invited@test.de") seeder.create_user("invited@test.de")
@ -15,7 +15,7 @@ def test_organization_invitation_list(client, seeder, utils):
def test_organization_invitation_read(client, seeder, utils): def test_organization_invitation_read(client, seeder, utils):
_, admin_unit_id = seeder.setup_base(log_in=False) _, admin_unit_id = seeder.setup_api_access(user_access=False)
invitation_id = seeder.create_admin_unit_invitation(admin_unit_id) invitation_id = seeder.create_admin_unit_invitation(admin_unit_id)
seeder.create_user("invited@test.de") seeder.create_user("invited@test.de")
@ -33,7 +33,7 @@ def test_organization_invitation_read(client, seeder, utils):
def test_organization_invitation_read_wrongEmail(client, seeder, utils): def test_organization_invitation_read_wrongEmail(client, seeder, utils):
_, admin_unit_id = seeder.setup_base(log_in=False) _, admin_unit_id = seeder.setup_api_access(user_access=False)
invitation_id = seeder.create_admin_unit_invitation(admin_unit_id) invitation_id = seeder.create_admin_unit_invitation(admin_unit_id)
seeder.create_user("other@test.de") seeder.create_user("other@test.de")
@ -45,7 +45,7 @@ def test_organization_invitation_read_wrongEmail(client, seeder, utils):
def test_organization_invitation_delete(client, app, seeder, utils, db): def test_organization_invitation_delete(client, app, seeder, utils, db):
_, admin_unit_id = seeder.setup_base(log_in=False) _, admin_unit_id = seeder.setup_api_access(user_access=False)
invitation_id = seeder.create_admin_unit_invitation(admin_unit_id) invitation_id = seeder.create_admin_unit_invitation(admin_unit_id)
seeder.create_user("invited@test.de") seeder.create_user("invited@test.de")

View File

@ -33,6 +33,7 @@ def app():
app.config["SERVER_NAME"] = None app.config["SERVER_NAME"] = None
app.config["TESTING"] = True app.config["TESTING"] = True
app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = False app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = False
app.config["API_READ_ANONYM"] = False
app.testing = True app.testing = True
return app return app

View File

@ -1,5 +1,8 @@
from tests.utils import UtilActions
class Seeder(object): class Seeder(object):
def __init__(self, app, db, utils): def __init__(self, app, db, utils: UtilActions):
self._app = app self._app = app
self._db = db self._db = db
self._utils = utils self._utils = utils
@ -247,6 +250,25 @@ class Seeder(object):
return organizer_id return organizer_id
def upsert_admin_unit_api_key(self, admin_unit_id, name):
from project.services.api_key import upsert_api_key
with self._app.app_context():
api_key = upsert_api_key(admin_unit_id, name)
self._db.session.commit()
api_key_id = api_key.id
return api_key_id
def upsert_default_admin_unit_api_key(self, admin_unit_id):
from project.services.admin_unit import get_admin_unit_by_id
with self._app.app_context():
admin_unit = get_admin_unit_by_id(admin_unit_id)
api_key_id = self.upsert_admin_unit_api_key(admin_unit_id, admin_unit.name)
return api_key_id
def insert_event_custom_widget( def insert_event_custom_widget(
self, self,
admin_unit_id, admin_unit_id,
@ -282,9 +304,6 @@ class Seeder(object):
metadata = dict() metadata = dict()
metadata["client_name"] = "Mein Client" metadata["client_name"] = "Mein Client"
metadata["scope"] = " ".join(scope_list) metadata["scope"] = " ".join(scope_list)
metadata["grant_types"] = ["authorization_code", "refresh_token"]
metadata["response_types"] = ["code"]
metadata["token_endpoint_auth_method"] = "client_secret_post"
metadata["redirect_uris"] = [self._utils.get_url("swagger_oauth2_redirect")] metadata["redirect_uris"] = [self._utils.get_url("swagger_oauth2_redirect")]
client.set_client_metadata(metadata) client.set_client_metadata(metadata)
@ -294,11 +313,17 @@ class Seeder(object):
return client_id return client_id
def setup_api_access(self, admin=True, admin_unit_verified=True): def setup_api_access(self, admin=True, admin_unit_verified=True, user_access=True):
user_id, admin_unit_id = self.setup_base( user_id, admin_unit_id = self.setup_base(
admin=admin, log_in=False, admin_unit_verified=admin_unit_verified admin=admin, log_in=False, admin_unit_verified=admin_unit_verified
) )
return self.authorize_api_access(user_id, admin_unit_id)
if user_access:
self.authorize_api_access(user_id, admin_unit_id)
else:
self.grant_client_credentials_api_access(user_id)
return (user_id, admin_unit_id)
def authorize_api_access(self, user_id, admin_unit_id): def authorize_api_access(self, user_id, admin_unit_id):
oauth2_client_id = self.insert_default_oauth2_client(user_id) oauth2_client_id = self.insert_default_oauth2_client(user_id)
@ -316,6 +341,19 @@ class Seeder(object):
self._utils.logout() self._utils.logout()
return (user_id, admin_unit_id) return (user_id, admin_unit_id)
def grant_client_credentials_api_access(self, user_id):
oauth2_client_id = self.insert_default_oauth2_client(user_id)
with self._app.app_context():
from project.models import OAuth2Client
oauth2_client = self._db.session.get(OAuth2Client, oauth2_client_id)
client_id = oauth2_client.client_id
client_secret = oauth2_client.client_secret
scope = oauth2_client.scope
self._utils.grant_client_credentials(client_id, client_secret, scope)
def get_event_category_id(self, category_name): def get_event_category_id(self, category_name):
from project.services.event import get_event_category from project.services.event import get_event_category

View File

@ -105,7 +105,7 @@ class UtilActions(object):
) )
def get_ajax_csrf(self, response): def get_ajax_csrf(self, response):
pattern = 'var csrf_token = "(.*)";' pattern = r"xhr\.setRequestHeader\(\"X-CSRFToken\", \"(.*)\"\);"
match = re.search(pattern.encode("utf-8"), response.data) match = re.search(pattern.encode("utf-8"), response.data)
if not match: if not match:
@ -161,6 +161,11 @@ class UtilActions(object):
self.log_response(response) self.log_response(response)
return response return response
def get_json_ok(self, url):
response = self.get_json(url)
self.assert_response_ok(response)
return response
def post_json(self, url, data: dict): def post_json(self, url, data: dict):
self.log_json_request(url, data) self.log_json_request(url, data)
response = self._client.post(url, json=data, headers=self.get_headers()) response = self._client.post(url, json=data, headers=self.get_headers())
@ -374,30 +379,47 @@ class UtilActions(object):
code = params["code"] code = params["code"]
# Mit dem Code den Access-Token abfragen # Mit dem Code den Access-Token abfragen
token_url = self.get_url("issue_token") self._get_token(
response = self.post_form_data( client_id, client_secret, scope, "authorization_code", code, redirect_uri
token_url, )
def grant_client_credentials(self, client_id, client_secret, scope):
# Mit den Credentials den Access-Token abfragen
self._get_token(client_id, client_secret, scope, "client_credentials")
def _get_token(
self, client_id, client_secret, scope, grant_type, code=None, redirect_uri=None
):
data = { data = {
"client_id": client_id, "client_id": client_id,
"client_secret": client_secret, "client_secret": client_secret,
"grant_type": "authorization_code", "grant_type": grant_type,
"scope": scope, "scope": scope,
"code": code, }
"redirect_uri": redirect_uri,
}, if grant_type == "authorization_code":
) data["code"] = code
data["redirect_uri"] = redirect_uri
token_url = self.get_url("issue_token")
response = self.post_form_data(token_url, data=data)
self.assert_response_ok(response) self.assert_response_ok(response)
assert response.content_type == "application/json" assert response.content_type == "application/json"
assert "access_token" in response.json assert "access_token" in response.json
assert "expires_in" in response.json assert "expires_in" in response.json
if grant_type == "authorization_code":
assert "refresh_token" in response.json assert "refresh_token" in response.json
assert response.json["scope"] == scope assert response.json["scope"] == scope
assert response.json["token_type"] == "Bearer" assert response.json["token_type"] == "Bearer"
self._client_id = client_id self._client_id = client_id
self._client_secret = client_secret self._client_secret = client_secret
self._access_token = response.json["access_token"] self._access_token = response.json["access_token"]
if grant_type == "authorization_code":
self._refresh_token = response.json["refresh_token"] self._refresh_token = response.json["refresh_token"]
def refresh_token(self): def refresh_token(self):

View File

@ -0,0 +1,10 @@
from tests.seeder import Seeder
from tests.utils import UtilActions
def test_custom_widget_type(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_base()
custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id)
url = utils.get_url("custom_widget_type", type="search", id=custom_widget_id)
utils.get_ok(url)

View File

@ -2,7 +2,7 @@ from tests.seeder import Seeder
from tests.utils import UtilActions from tests.utils import UtilActions
def test_js_check_org_short_name(client, seeder, utils): def test_js_check_org_short_name(client, seeder, utils: UtilActions):
seeder.create_user(admin=True) seeder.create_user(admin=True)
utils.login() utils.login()
@ -210,3 +210,11 @@ def test_js_autocomplete_gmaps_place(client, seeder: Seeder, utils: UtilActions)
utils.assert_response_ok(response) utils.assert_response_ok(response)
assert response.json["place_id"] == "123" assert response.json["place_id"] == "123"
def test_js_widget_loader_custom_widget(client, seeder: Seeder, utils: UtilActions):
_, admin_unit_id = seeder.setup_base(log_in=False)
custom_widget_id = seeder.insert_event_custom_widget(admin_unit_id)
url = utils.get_url("js_widget_loader_custom_widget", id=custom_widget_id)
utils.get_ok(url)

View File

@ -1,7 +1,14 @@
def test_organizations(client, seeder, utils): from tests.seeder import Seeder
from tests.utils import UtilActions
def test_organizations(client, seeder: Seeder, utils: UtilActions):
url = utils.get_url("organizations") url = utils.get_url("organizations")
utils.get_ok(url) utils.get_ok(url)
url = utils.get_url("api_v1_organization_list")
utils.get_json_ok(url)
def test_ical(client, seeder, utils): def test_ical(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base(log_in=False) user_id, admin_unit_id = seeder.setup_base(log_in=False)