diff --git a/alembic/versions/45b6be09b41d_multitenant_test_2.py b/alembic/versions/45b6be09b41d_multitenant_test_2.py new file mode 100644 index 0000000..aaed536 --- /dev/null +++ b/alembic/versions/45b6be09b41d_multitenant_test_2.py @@ -0,0 +1,65 @@ +"""multitenant test 2 + +Revision ID: 45b6be09b41d +Revises: b648caf8d8fb +Create Date: 2025-09-20 09:06:00.040599 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '45b6be09b41d' +down_revision = 'b648caf8d8fb' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('event_brand', + sa.Column('uuid', sa.UUID(), nullable=False), + sa.Column('name', sa.Text(), nullable=False), + sa.PrimaryKeyConstraint('uuid', name=op.f('pk_event_brand')), + sa.UniqueConstraint('uuid', name=op.f('uq_event_brand_uuid')) + ) + op.add_column('crew', sa.Column('event_brand', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_crew_event_brand_event_brand'), 'crew', 'event_brand', ['event_brand'], ['uuid']) + op.add_column('event', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_event_event_brand_uuid_event_brand'), 'event', 'event_brand', ['event_brand_uuid'], ['uuid']) + op.add_column('location', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_location_event_brand_uuid_event_brand'), 'location', 'event_brand', ['event_brand_uuid'], ['uuid']) + op.add_column('position', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_position_event_brand_uuid_event_brand'), 'position', 'event_brand', ['event_brand_uuid'], ['uuid']) + op.add_column('seatmap', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_seatmap_event_brand_uuid_event_brand'), 'seatmap', 'event_brand', ['event_brand_uuid'], ['uuid']) + op.add_column('seatmap_background', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_seatmap_background_event_brand_uuid_event_brand'), 'seatmap_background', 'event_brand', ['event_brand_uuid'], ['uuid']) + op.add_column('ticket_type', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_ticket_type_event_brand_uuid_event_brand'), 'ticket_type', 'event_brand', ['event_brand_uuid'], ['uuid']) + op.add_column('user_positions', sa.Column('event_brand_uuid', sa.UUID(), nullable=True)) + op.create_foreign_key(op.f('fk_user_positions_event_brand_uuid_event_brand'), 'user_positions', 'event_brand', ['event_brand_uuid'], ['uuid']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(op.f('fk_user_positions_event_brand_uuid_event_brand'), 'user_positions', type_='foreignkey') + op.drop_column('user_positions', 'event_brand_uuid') + op.drop_constraint(op.f('fk_ticket_type_event_brand_uuid_event_brand'), 'ticket_type', type_='foreignkey') + op.drop_column('ticket_type', 'event_brand_uuid') + op.drop_constraint(op.f('fk_seatmap_background_event_brand_uuid_event_brand'), 'seatmap_background', type_='foreignkey') + op.drop_column('seatmap_background', 'event_brand_uuid') + op.drop_constraint(op.f('fk_seatmap_event_brand_uuid_event_brand'), 'seatmap', type_='foreignkey') + op.drop_column('seatmap', 'event_brand_uuid') + op.drop_constraint(op.f('fk_position_event_brand_uuid_event_brand'), 'position', type_='foreignkey') + op.drop_column('position', 'event_brand_uuid') + op.drop_constraint(op.f('fk_location_event_brand_uuid_event_brand'), 'location', type_='foreignkey') + op.drop_column('location', 'event_brand_uuid') + op.drop_constraint(op.f('fk_event_event_brand_uuid_event_brand'), 'event', type_='foreignkey') + op.drop_column('event', 'event_brand_uuid') + op.drop_constraint(op.f('fk_crew_event_brand_event_brand'), 'crew', type_='foreignkey') + op.drop_column('crew', 'event_brand') + op.drop_table('event_brand') + # ### end Alembic commands ### diff --git a/phoenixRest/models/core/event.py b/phoenixRest/models/core/event.py index ae980f4..229dd04 100644 --- a/phoenixRest/models/core/event.py +++ b/phoenixRest/models/core/event.py @@ -17,6 +17,7 @@ from phoenixRest.models import Base +from phoenixRest.models.core.event_brand import EventBrand from phoenixRest.models.core.user import User from phoenixRest.models.tickets.ticket import Ticket from phoenixRest.models.tickets.ticket_type import TicketType @@ -41,6 +42,9 @@ class Event(Base): __tablename__ = "event" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + booking_time = Column(DateTime, nullable=False) # Delta in seconds from booking time @@ -83,6 +87,7 @@ def __json__(self, request): return { 'name': str(self.name), 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'participant_age_limit_inclusive': self.participant_age_limit_inclusive, 'crew_age_limit_inclusive': self.crew_age_limit_inclusive, 'booking_time': int(self.booking_time.timestamp()), diff --git a/phoenixRest/models/core/event_brand.py b/phoenixRest/models/core/event_brand.py new file mode 100644 index 0000000..74de14a --- /dev/null +++ b/phoenixRest/models/core/event_brand.py @@ -0,0 +1,39 @@ +from sqlalchemy import ( + Column, + DateTime, + ForeignKey, + Integer, + UniqueConstraint, + Text, + Integer, + Boolean, + Enum, + Table +) +from sqlalchemy.dialects.postgresql import UUID + +from sqlalchemy.orm import relationship +from sqlalchemy import and_ + +from phoenixRest.models import Base + +import logging +log = logging.getLogger(__name__) + +import uuid + +class EventBrand(Base): + __tablename__ = "event_brand" + + uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + + name = Column(Text, nullable=False) + + def __init__(self, name: str): + self.name = name + + def __json__(self, request): + return { + 'uuid': str(self.uuid), + 'name': str(self.name) + } \ No newline at end of file diff --git a/phoenixRest/models/core/location.py b/phoenixRest/models/core/location.py index 403fe64..832d0cd 100644 --- a/phoenixRest/models/core/location.py +++ b/phoenixRest/models/core/location.py @@ -13,6 +13,8 @@ ) from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship + from phoenixRest.models import Base import uuid @@ -21,6 +23,9 @@ class Location(Base): __tablename__ = "location" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + name = Column(Text, nullable=False) address = Column(Text, nullable=False) @@ -31,6 +36,7 @@ def __init__(self, name: str, address: str): def __json__(self, request): return { 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'name': self.name, 'address': self.address, } \ No newline at end of file diff --git a/phoenixRest/models/crew/crew.py b/phoenixRest/models/crew/crew.py index 2c36a59..05719d5 100644 --- a/phoenixRest/models/crew/crew.py +++ b/phoenixRest/models/crew/crew.py @@ -17,6 +17,7 @@ from phoenixRest.models import Base +from phoenixRest.models.core.event_brand import EventBrand from phoenixRest.models.core.user import User from datetime import datetime, timedelta @@ -27,7 +28,10 @@ class Crew(Base): __tablename__ = "crew" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) - + + event_brand = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event = relationship("EventBrand") + name = Column(Text, nullable=False) description = Column(Text, nullable=False) @@ -49,6 +53,7 @@ def __init__(self, name: str, description: str): def __json__(self, request): return { 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'name': self.name, 'description': self.description, 'active': self.active, diff --git a/phoenixRest/models/crew/position.py b/phoenixRest/models/crew/position.py index aeb06ef..fdd711f 100644 --- a/phoenixRest/models/crew/position.py +++ b/phoenixRest/models/crew/position.py @@ -25,6 +25,9 @@ class Position(Base): __tablename__ = "position" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + crew_uuid = Column(UUID(as_uuid=True), ForeignKey("crew.uuid"), nullable=True) crew = relationship("Crew") @@ -49,6 +52,7 @@ def __init__(self, name: str, description: str): def __json__(self, request): return { 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'name': self.name, 'description': self.description, 'is_vanity': self.is_vanity, diff --git a/phoenixRest/models/crew/position_mapping.py b/phoenixRest/models/crew/position_mapping.py index 84ed28a..03e4785 100644 --- a/phoenixRest/models/crew/position_mapping.py +++ b/phoenixRest/models/crew/position_mapping.py @@ -22,6 +22,9 @@ class PositionMapping(Base): __tablename__ = "user_positions" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + position_uuid = Column(UUID(as_uuid=True), ForeignKey("position.uuid"), nullable=False) position = relationship("Position", back_populates="position_mappings", uselist=False) @@ -46,6 +49,7 @@ def __init__(self, user, position, event=None): def __json__(self, request): return { 'uuid': self.uuid, + 'event_brand_uuid': str(self.event_brand_uuid), 'position_uuid': self.position_uuid, 'user_uuid': self.user_uuid, 'event_uuid': self.event_uuid, diff --git a/phoenixRest/models/tickets/seatmap.py b/phoenixRest/models/tickets/seatmap.py index 4010bc2..cf6f578 100644 --- a/phoenixRest/models/tickets/seatmap.py +++ b/phoenixRest/models/tickets/seatmap.py @@ -29,6 +29,9 @@ class Seatmap(Base): __tablename__ = "seatmap" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + name = Column(Text, nullable=False) description = Column(Text, nullable=False) @@ -50,6 +53,7 @@ def __init__(self, name: str, description: str): def __json__(self, request): return { 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'name': str(self.name), 'description': str(self.description), 'background': map_seatmap_background_no_metadata(self.background, request) if self.background is not None else None, diff --git a/phoenixRest/models/tickets/seatmap_background.py b/phoenixRest/models/tickets/seatmap_background.py index b7a8ea5..46947bd 100644 --- a/phoenixRest/models/tickets/seatmap_background.py +++ b/phoenixRest/models/tickets/seatmap_background.py @@ -24,6 +24,9 @@ class SeatmapBackground(Base): __tablename__ = "seatmap_background" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + created = Column(DateTime, nullable=False, server_default='NOW()') extension = Column(Text, nullable=False) @@ -47,6 +50,7 @@ def get_fs_location(self, request): def __json__(self, request): return { 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'uploader_uuid': self.uploader_uuid, 'created': int(self.created.timestamp()), 'url': self.get_url(request) diff --git a/phoenixRest/models/tickets/ticket_type.py b/phoenixRest/models/tickets/ticket_type.py index 98c794c..9d01ee0 100644 --- a/phoenixRest/models/tickets/ticket_type.py +++ b/phoenixRest/models/tickets/ticket_type.py @@ -12,6 +12,8 @@ ) from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship + from phoenixRest.models import Base import uuid @@ -20,6 +22,9 @@ class TicketType(Base): __tablename__ = "ticket_type" uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + event_brand_uuid = Column(UUID(as_uuid=True), ForeignKey("event_brand.uuid"), nullable=True) + event_brand = relationship("EventBrand") + name = Column(Text, nullable=False) price = Column(Integer, nullable=False) @@ -45,6 +50,7 @@ def __init__(self, name: str, price: int, description: str, refundable: bool, se def __json__(self, request): return { 'uuid': str(self.uuid), + 'event_brand_uuid': str(self.event_brand_uuid), 'name': self.name, 'price': self.price, 'refundable': self.refundable, diff --git a/phoenixRest/views/event_brand/__init__.py b/phoenixRest/views/event_brand/__init__.py new file mode 100644 index 0000000..e81838e --- /dev/null +++ b/phoenixRest/views/event_brand/__init__.py @@ -0,0 +1,33 @@ +from pyramid.view import view_config, view_defaults +from pyramid.httpexceptions import ( + HTTPForbidden, +) +from pyramid.authorization import Authenticated, Everyone, Deny, Allow + + +from phoenixRest.models.core.event_brand import EventBrand + +from phoenixRest.resource import resource + +from phoenixRest.roles import ADMIN + +import logging +log = logging.getLogger(__name__) + + +@view_defaults(context='.EventBrandResource') +@resource(name='event_brand') +class EventBrandResource(object): + __acl__ = [ + (Allow, Everyone, 'get'), + (Allow, ADMIN, 'create'), + ] + def __init__(self, request): + self.request = request + log.info("event type class init") + +@view_config(context=EventBrandResource, request_method='GET', renderer='json', permission='get') +def get_event_types(request): + # Find all events and sort them by start time + event_types = request.db.query(EventBrand).all() + return event_types