Skip to content

Commit caedf15

Browse files
authored
Merge pull request #37 from d4vidsha/d4vidsha/template-updates
chore: add template updates
2 parents 3b42e74 + 735189f commit caedf15

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2145
-246
lines changed

.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ BACKEND_CORS_ORIGINS="http://localhost,http://localhost:5173,https://localhost,h
1212
SECRET_KEY=changethis
1313
FIRST_SUPERUSER=[email protected]
1414
FIRST_SUPERUSER_PASSWORD=changethis
15-
USERS_OPEN_REGISTRATION=False
1615

1716
# emails
1817
SMTP_HOST=

.github/workflows/deploy-production.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ jobs:
2323
EMAILS_FROM_EMAIL: ${{ secrets.EMAILS_FROM_EMAIL }}
2424
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
2525
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
26-
USERS_OPEN_REGISTRATION: ${{ secrets.USERS_OPEN_REGISTRATION_PRODUCTION }}
2726
steps:
2827
- name: Checkout
2928
uses: actions/checkout@v4

.github/workflows/deploy-staging.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ jobs:
2323
EMAILS_FROM_EMAIL: ${{ secrets.EMAILS_FROM_EMAIL }}
2424
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
2525
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
26-
USERS_OPEN_REGISTRATION: ${{ secrets.USERS_OPEN_REGISTRATION_STAGING }}
2726
steps:
2827
- name: Checkout
2928
uses: actions/checkout@v4

.github/workflows/playwright.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Playwright Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
types:
9+
- opened
10+
- synchronize
11+
workflow_dispatch:
12+
inputs:
13+
debug_enabled:
14+
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
15+
required: false
16+
default: 'false'
17+
18+
jobs:
19+
20+
test:
21+
timeout-minutes: 60
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: actions/setup-node@v4
26+
with:
27+
node-version: lts/*
28+
- uses: actions/setup-python@v5
29+
with:
30+
python-version: '3.10'
31+
- name: Setup tmate session
32+
uses: mxschmitt/action-tmate@v3
33+
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
34+
with:
35+
limit-access-to-actor: true
36+
- name: Install dependencies
37+
run: npm ci
38+
working-directory: frontend
39+
- name: Install Playwright Browsers
40+
run: npx playwright install --with-deps
41+
working-directory: frontend
42+
- run: docker compose build
43+
- run: docker compose down -v --remove-orphans
44+
- run: docker compose up -d
45+
- name: Run Playwright tests
46+
run: npx playwright test
47+
working-directory: frontend
48+
- run: docker compose down -v --remove-orphans
49+
- uses: actions/upload-artifact@v4
50+
if: always()
51+
with:
52+
name: playwright-report
53+
path: frontend/playwright-report/
54+
retention-days: 30
55+
56+
# https://github.com/marketplace/actions/alls-green#why
57+
e2e-alls-green: # This job does nothing and is only used for the branch protection
58+
if: always()
59+
needs:
60+
- test
61+
runs-on: ubuntu-latest
62+
steps:
63+
- name: Decide whether the needed jobs succeeded or failed
64+
uses: re-actors/alls-green@release/v1
65+
with:
66+
jobs: ${{ toJSON(needs) }}

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Using TypeScript, hooks, Vite, and other parts of a modern frontend stack.
1818
- [Chakra UI](https://chakra-ui.com) for the frontend components.
1919
- An automatically generated frontend client.
20+
- [Playwright](https://playwright.dev) for End-to-End testing.
2021
- Dark mode support.
2122
- [Docker Compose](https://www.docker.com) for development and production.
2223
- Secure password hashing by default.

backend/README.md

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,6 @@ Make sure your editor is using the correct Python virtual environment.
6363

6464
Modify or add SQLModel models for data and SQL tables in `./backend/app/models.py`, API endpoints in `./backend/app/api/`, CRUD (Create, Read, Update, Delete) utils in `./backend/app/crud.py`.
6565

66-
### Enabling Open User Registration
67-
68-
By default the backend has user registration disabled, but there's already a route to register users. If you want to allow users to register themselves, you can set the environment variable `USERS_OPEN_REGISTRATION` to `True` in the `.env` file.
69-
70-
After modifying the environment variables, restart the Docker containers to apply the changes. You can do this by running:
71-
72-
```console
73-
docker compose up -d
74-
```
75-
7666
### VS Code
7767

7868
There are already configurations in place to run the backend through the VS Code debugger, so that you can use breakpoints, pause and explore variables, etc.

backend/app/alembic/env.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# target_metadata = None
2020

2121
from app.models import SQLModel # noqa
22+
from app.core.config import settings # noqa
2223

2324
target_metadata = SQLModel.metadata
2425

@@ -29,12 +30,7 @@
2930

3031

3132
def get_url():
32-
user = os.getenv("POSTGRES_USER", "postgres")
33-
password = os.getenv("POSTGRES_PASSWORD", "")
34-
server = os.getenv("POSTGRES_SERVER", "db")
35-
port = os.getenv("POSTGRES_PORT", "5432")
36-
db = os.getenv("POSTGRES_DB", "app")
37-
return f"postgresql+psycopg://{user}:{password}@{server}:{port}/{db}"
33+
return str(settings.SQLALCHEMY_DATABASE_URI)
3834

3935

4036
def run_migrations_offline():
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""feat: add cascade delete relationships
2+
3+
Revision ID: c48758dce0b3
4+
Revises: 119709b3f9bb
5+
Create Date: 2024-08-02 16:33:22.524259
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
12+
13+
# revision identifiers, used by Alembic.
14+
revision = 'c48758dce0b3'
15+
down_revision = '119709b3f9bb'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.alter_column('item', 'id',
23+
existing_type=sa.INTEGER(),
24+
type_=sa.Uuid(),
25+
existing_nullable=False)
26+
op.alter_column('item', 'owner_id',
27+
existing_type=sa.INTEGER(),
28+
type_=sa.Uuid(),
29+
existing_nullable=False)
30+
op.drop_constraint('item_owner_id_fkey', 'item', type_='foreignkey')
31+
op.create_foreign_key(None, 'item', 'user', ['owner_id'], ['id'], ondelete='CASCADE')
32+
op.alter_column('task', 'id',
33+
existing_type=sa.INTEGER(),
34+
type_=sa.Uuid(),
35+
existing_nullable=False)
36+
op.alter_column('task', 'owner_id',
37+
existing_type=sa.INTEGER(),
38+
type_=sa.Uuid(),
39+
existing_nullable=False)
40+
op.drop_constraint('task_owner_id_fkey', 'task', type_='foreignkey')
41+
op.create_foreign_key(None, 'task', 'user', ['owner_id'], ['id'], ondelete='CASCADE')
42+
op.alter_column('user', 'id',
43+
existing_type=sa.INTEGER(),
44+
type_=sa.Uuid(),
45+
existing_nullable=False,
46+
existing_server_default=sa.text("nextval('user_id_seq'::regclass)"))
47+
# ### end Alembic commands ###
48+
49+
50+
def downgrade():
51+
# ### commands auto generated by Alembic - please adjust! ###
52+
op.alter_column('user', 'id',
53+
existing_type=sa.Uuid(),
54+
type_=sa.INTEGER(),
55+
existing_nullable=False,
56+
existing_server_default=sa.text("nextval('user_id_seq'::regclass)"))
57+
op.drop_constraint(None, 'task', type_='foreignkey')
58+
op.create_foreign_key('task_owner_id_fkey', 'task', 'user', ['owner_id'], ['id'])
59+
op.alter_column('task', 'owner_id',
60+
existing_type=sa.Uuid(),
61+
type_=sa.INTEGER(),
62+
existing_nullable=False)
63+
op.alter_column('task', 'id',
64+
existing_type=sa.Uuid(),
65+
type_=sa.INTEGER(),
66+
existing_nullable=False)
67+
op.drop_constraint(None, 'item', type_='foreignkey')
68+
op.create_foreign_key('item_owner_id_fkey', 'item', 'user', ['owner_id'], ['id'])
69+
op.alter_column('item', 'owner_id',
70+
existing_type=sa.Uuid(),
71+
type_=sa.INTEGER(),
72+
existing_nullable=False)
73+
op.alter_column('item', 'id',
74+
existing_type=sa.Uuid(),
75+
type_=sa.INTEGER(),
76+
existing_nullable=False)
77+
# ### end Alembic commands ###

backend/app/api/routes/items.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import uuid
12
from typing import Any
23

34
from fastapi import APIRouter, HTTPException
@@ -41,7 +42,7 @@ def read_items(
4142

4243

4344
@router.get("/{id}", response_model=ItemPublic)
44-
def read_item(session: SessionDep, current_user: CurrentUser, id: int) -> Any:
45+
def read_item(session: SessionDep, current_user: CurrentUser, id: uuid.UUID) -> Any:
4546
"""
4647
Get item by ID.
4748
"""
@@ -69,7 +70,11 @@ def create_item(
6970

7071
@router.put("/{id}", response_model=ItemPublic)
7172
def update_item(
72-
*, session: SessionDep, current_user: CurrentUser, id: int, item_in: ItemUpdate
73+
*,
74+
session: SessionDep,
75+
current_user: CurrentUser,
76+
id: uuid.UUID,
77+
item_in: ItemUpdate,
7378
) -> Any:
7479
"""
7580
Update an item.
@@ -88,7 +93,9 @@ def update_item(
8893

8994

9095
@router.delete("/{id}")
91-
def delete_item(session: SessionDep, current_user: CurrentUser, id: int) -> Message:
96+
def delete_item(
97+
session: SessionDep, current_user: CurrentUser, id: uuid.UUID
98+
) -> Message:
9299
"""
93100
Delete an item.
94101
"""

backend/app/api/routes/users.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import uuid
12
from typing import Any
23

34
from fastapi import APIRouter, Depends, HTTPException
@@ -145,11 +146,6 @@ def register_user(session: SessionDep, user_in: UserRegister) -> Any:
145146
"""
146147
Create new user without the need to be logged in.
147148
"""
148-
if not settings.USERS_OPEN_REGISTRATION:
149-
raise HTTPException(
150-
status_code=403,
151-
detail="Open user registration is forbidden on this server",
152-
)
153149
user = crud.get_user_by_email(session=session, email=user_in.email)
154150
if user:
155151
raise HTTPException(
@@ -163,7 +159,7 @@ def register_user(session: SessionDep, user_in: UserRegister) -> Any:
163159

164160
@router.get("/{user_id}", response_model=UserPublic)
165161
def read_user_by_id(
166-
user_id: int, session: SessionDep, current_user: CurrentUser
162+
user_id: uuid.UUID, session: SessionDep, current_user: CurrentUser
167163
) -> Any:
168164
"""
169165
Get a specific user by id.
@@ -187,7 +183,7 @@ def read_user_by_id(
187183
def update_user(
188184
*,
189185
session: SessionDep,
190-
user_id: int,
186+
user_id: uuid.UUID,
191187
user_in: UserUpdate,
192188
) -> Any:
193189
"""
@@ -213,7 +209,7 @@ def update_user(
213209

214210
@router.delete("/{user_id}", dependencies=[Depends(get_current_active_superuser)])
215211
def delete_user(
216-
session: SessionDep, current_user: CurrentUser, user_id: int
212+
session: SessionDep, current_user: CurrentUser, user_id: uuid.UUID
217213
) -> Message:
218214
"""
219215
Delete a user.

0 commit comments

Comments
 (0)