feat(api): setup database migrations
This commit is contained in:
parent
627f104101
commit
b80883bec0
@ -64,5 +64,6 @@ start = {cmd = "uvicorn --workers 2 neo_neo_todo.main:app", env_file = "developm
|
|||||||
dev = {cmd = "uvicorn neo_neo_todo.main:app --reload", env_file = "development.env"}
|
dev = {cmd = "uvicorn neo_neo_todo.main:app --reload", env_file = "development.env"}
|
||||||
|
|
||||||
recreate-db-base = "python3 src/neo_neo_todo/utils/database.py"
|
recreate-db-base = "python3 src/neo_neo_todo/utils/database.py"
|
||||||
recreate-db = {composite = ["recreate-db-base"], env_file = "development.env"}
|
migration-base = "python3 src/neo_neo_todo/migrations/0.py"
|
||||||
|
recreate-db = {composite = ["recreate-db-base", "migration-base"], env_file = "development.env"}
|
||||||
test = {composite = ["recreate-db-base", "pytest tests/"], env_file = "testing.env"}
|
test = {composite = ["recreate-db-base", "pytest tests/"], env_file = "testing.env"}
|
||||||
|
71
backend/src/neo_neo_todo/migrations/0.py
Normal file
71
backend/src/neo_neo_todo/migrations/0.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import os
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import psycopg
|
||||||
|
from psycopg import sql
|
||||||
|
|
||||||
|
|
||||||
|
def migrate() -> None:
|
||||||
|
"""
|
||||||
|
Migrate the PostgreSQL database
|
||||||
|
|
||||||
|
Watch for PostgreSQL version changes
|
||||||
|
"""
|
||||||
|
url_parts = urlparse(os.environ["TODO_DB_DATABASE_URL"])
|
||||||
|
|
||||||
|
# Extract connection parameters
|
||||||
|
dbname = url_parts.path[1:]
|
||||||
|
user_name = url_parts.username
|
||||||
|
password = url_parts.password
|
||||||
|
host = url_parts.hostname
|
||||||
|
port = url_parts.port
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"The database name is {dbname}, the username is {user_name}, the password is {password}, the host is {host}, the port is {port}"
|
||||||
|
)
|
||||||
|
|
||||||
|
with psycopg.connect(
|
||||||
|
dbname=dbname, user=user_name, password=password, host=host, port=port
|
||||||
|
) as conn:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
# create the members table
|
||||||
|
cur.execute(
|
||||||
|
sql.SQL(
|
||||||
|
"""CREATE TABLE members (
|
||||||
|
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||||
|
created TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
email_verified TIMESTAMP,
|
||||||
|
password_hash TEXT NOT NULL
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
cur.execute(
|
||||||
|
sql.SQL(
|
||||||
|
"""CREATE UNIQUE INDEX members_unique_email_idx
|
||||||
|
ON members (LOWER(email)
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
cur.execute(
|
||||||
|
sql.SQL(
|
||||||
|
"""CREATE TABLE todos (
|
||||||
|
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||||
|
complete BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
due TIMESTAMPTZ,
|
||||||
|
member_id INT NOT NULL REFERENCES members(id),
|
||||||
|
task TEXT NOT NULL
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Commit the changes
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
print("Finished PostgreSQL migration number 0")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
migrate()
|
11
backend/src/neo_neo_todo/models/member.py
Normal file
11
backend/src/neo_neo_todo/models/member.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Member:
|
||||||
|
id: int
|
||||||
|
email: str
|
||||||
|
password_hash: str
|
||||||
|
created: datetime
|
||||||
|
email_verified: datetime | None
|
@ -58,7 +58,7 @@ def recreate_db() -> None:
|
|||||||
|
|
||||||
# Create a new user
|
# Create a new user
|
||||||
cur.execute(
|
cur.execute(
|
||||||
sql.SQL("CREATE USER {} WITH PASSWORD {}").format(
|
sql.SQL("CREATE USER {} WITH PASSWORD {} CREATEDB").format(
|
||||||
sql.Identifier(user_name), password # type: ignore
|
sql.Identifier(user_name), password # type: ignore
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -73,6 +73,13 @@ def recreate_db() -> None:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cur.execute(
|
||||||
|
sql.SQL("ALTER DATABASE {} OWNER TO {}").format(
|
||||||
|
sql.Identifier(dbname),
|
||||||
|
sql.Identifier(user_name), # type: ignore
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Commit the changes
|
# Commit the changes
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user