diff options
| author | 2024-07-09 20:08:44 +0100 | |
|---|---|---|
| committer | 2024-07-21 13:45:30 +0100 | |
| commit | a439ef0fefe9f171ca1568869820ee159036bdfc (patch) | |
| tree | 9d20fe840a7fdfd9e80424c99fd2f55ff707fc28 | |
| parent | Add alembic boiler plate for migrations (diff) | |
Add models and migration files for admins & forms
Diffstat (limited to '')
| -rw-r--r-- | backend/models/orm/__init__.py | 30 | ||||
| -rw-r--r-- | backend/models/orm/admins.py | 14 | ||||
| -rw-r--r-- | backend/models/orm/forms.py | 61 | ||||
| -rw-r--r-- | migrations/versions/1721486482-a9ea4b71d23a_add_admins_forms.py | 93 | 
4 files changed, 198 insertions, 0 deletions
| diff --git a/backend/models/orm/__init__.py b/backend/models/orm/__init__.py index 4c8a6b4..4db39ae 100644 --- a/backend/models/orm/__init__.py +++ b/backend/models/orm/__init__.py @@ -1,7 +1,37 @@  """Database models.""" +from .admins import Admin  from .base import Base +from .forms import Form, FormEditor, FormFeatures +from .questions import ( +    FormCheckboxQuestion, +    FormCodeQuestion, +    FormCodeQuestionTest, +    FormQuestion, +    FormRadioQuestion, +    FormRangeQuestion, +    FormSectionQuestion, +    FormSelectQuestion, +    FormTextQuestion, +    FormTimezoneQuestion, +    FormVoteQuestion, +)  __all__ = ( +    "Admin",      "Base", +    "Form", +    "FormCheckboxQuestion", +    "FormCodeQuestion", +    "FormCodeQuestionTest", +    "FormEditor", +    "FormFeatures", +    "FormQuestion", +    "FormRadioQuestion", +    "FormRangeQuestion", +    "FormSectionQuestion", +    "FormSelectQuestion", +    "FormTextQuestion", +    "FormTimezoneQuestion", +    "FormVoteQuestion",  ) diff --git a/backend/models/orm/admins.py b/backend/models/orm/admins.py new file mode 100644 index 0000000..7eee008 --- /dev/null +++ b/backend/models/orm/admins.py @@ -0,0 +1,14 @@ +"""Discord members who have admin access.""" + +from sqlalchemy.orm import Mapped, mapped_column +from sqlalchemy.types import BigInteger + +from .base import Base + + +class Admin(Base): +    """A discord user_id that has admin level access to forms.""" + +    __tablename__ = "admins" + +    user_id: Mapped[int] = mapped_column(BigInteger, primary_key=True) diff --git a/backend/models/orm/forms.py b/backend/models/orm/forms.py new file mode 100644 index 0000000..489b71b --- /dev/null +++ b/backend/models/orm/forms.py @@ -0,0 +1,61 @@ +"""All forms that can have submissions.""" + +import sqlalchemy.dialects.postgresql as pg +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.types import BigInteger, Enum, Text + +from backend.constants import FormFeatures + +from .base import Base + + +class Form(Base): +    """A form that users can submit responses to.""" + +    __tablename__ = "forms" + +    form_id: Mapped[int] = mapped_column(primary_key=True) + +    short_name: Mapped[str] = mapped_column(Text, nullable=False, index=True) +    name: Mapped[str] = mapped_column(Text, nullable=False) +    description: Mapped[str] = mapped_column(Text, nullable=False) +    submission_text: Mapped[str | None] = mapped_column(Text, nullable=True) + +    webhook_url: Mapped[str | None] = mapped_column(Text, nullable=True) +    webhook_message: Mapped[str | None] = mapped_column(Text, nullable=True) + +    discord_role: Mapped[int | None] = mapped_column(BigInteger, nullable=True) + +    features: Mapped[list[FormFeatures]] = mapped_column(pg.ARRAY(Enum(FormFeatures), dimensions=1)) + +    form_response_readers: Mapped[list["FormResponseReader"]] = relationship( +        cascade="all, delete", +        passive_deletes=True, +    ) +    form_editors: Mapped[list["FormEditor"]] = relationship( +        cascade="all, delete", +        passive_deletes=True, +    ) + + +class FormResponseReader(Base): +    """A Discord user that can read a given form.""" + +    __tablename__ = "form_response_readers" + +    form_id: Mapped[int] = mapped_column( +        ForeignKey("forms.form_id", ondelete="CASCADE"), primary_key=True +    ) +    user_id: Mapped[int] = mapped_column(BigInteger, primary_key=True) + + +class FormEditor(Base): +    """A Discord user that can edit a given form.""" + +    __tablename__ = "form_editors" + +    form_id: Mapped[int] = mapped_column( +        ForeignKey("forms.form_id", ondelete="CASCADE"), primary_key=True +    ) +    user_id: Mapped[int] = mapped_column(BigInteger, primary_key=True) diff --git a/migrations/versions/1721486482-a9ea4b71d23a_add_admins_forms.py b/migrations/versions/1721486482-a9ea4b71d23a_add_admins_forms.py new file mode 100644 index 0000000..c61944b --- /dev/null +++ b/migrations/versions/1721486482-a9ea4b71d23a_add_admins_forms.py @@ -0,0 +1,93 @@ +""" +Add admins & forms. + +Revision ID: a9ea4b71d23a +Revises: +Create Date: 2024-07-20 14:41:22.166383+00:00 +""" + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = "a9ea4b71d23a" +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade() -> None: +    """Apply this migration.""" +    # ### commands auto generated by Alembic - please adjust! ### +    op.create_table( +        "admins", +        sa.Column("user_id", sa.BigInteger(), nullable=False), +        sa.PrimaryKeyConstraint("user_id", name=op.f("admins_pk")), +    ) +    op.create_table( +        "forms", +        sa.Column("form_id", sa.Integer(), nullable=False), +        sa.Column("short_name", sa.Text(), nullable=False), +        sa.Column("name", sa.Text(), nullable=False), +        sa.Column("description", sa.Text(), nullable=False), +        sa.Column("submission_text", sa.Text(), nullable=True), +        sa.Column("webhook_url", sa.Text(), nullable=True), +        sa.Column("webhook_message", sa.Text(), nullable=True), +        sa.Column("discord_role", sa.BigInteger(), nullable=True), +        sa.Column( +            "features", +            postgresql.ARRAY( +                sa.Enum( +                    "DISCOVERABLE", +                    "REQUIRES_LOGIN", +                    "OPEN", +                    "COLLECT_EMAIL", +                    "DISABLE_ANTISPAM", +                    "WEBHOOK_ENABLED", +                    "ASSIGN_ROLE", +                    name="formfeatures", +                ), +                dimensions=1, +            ), +            nullable=False, +        ), +        sa.PrimaryKeyConstraint("form_id", name=op.f("forms_pk")), +    ) +    op.create_index(op.f("forms_short_name_ix"), "forms", ["short_name"], unique=False) +    op.create_table( +        "form_editors", +        sa.Column("form_id", sa.Integer(), nullable=False), +        sa.Column("user_id", sa.BigInteger(), nullable=False), +        sa.ForeignKeyConstraint( +            ["form_id"], +            ["forms.form_id"], +            name=op.f("form_editors_form_id_forms_fk"), +            ondelete="CASCADE", +        ), +        sa.PrimaryKeyConstraint("form_id", "user_id", name=op.f("form_editors_pk")), +    ) +    op.create_table( +        "form_response_readers", +        sa.Column("form_id", sa.Integer(), nullable=False), +        sa.Column("user_id", sa.BigInteger(), nullable=False), +        sa.ForeignKeyConstraint( +            ["form_id"], +            ["forms.form_id"], +            name=op.f("form_response_readers_form_id_forms_fk"), +            ondelete="CASCADE", +        ), +        sa.PrimaryKeyConstraint("form_id", "user_id", name=op.f("form_response_readers_pk")), +    ) +    # ### end Alembic commands ### + + +def downgrade() -> None: +    """Revert this migration.""" +    # ### commands auto generated by Alembic - please adjust! ### +    op.drop_table("form_response_readers") +    op.drop_table("form_editors") +    op.drop_index(op.f("forms_short_name_ix"), table_name="forms") +    op.drop_table("forms") +    op.drop_table("admins") +    # ### end Alembic commands ### | 
