mirror of
https://github.com/joaovitoriasilva/endurain.git
synced 2026-01-08 15:33:53 -05:00
Fix change user password + Strava callback
[docker] on build image process change frontend location from inside backend folder to specific frontend folder on /app [docker] added healthcheck to image [docker] fixed non-root user [docker] updated docker compose example file [docs] updated volumes [backend] added alembic migration to change database password field size from 100 to 250 in user table [backend] fixed issue on changing user password [backend] add Catch-All Route for the Frontend to ensure that requests to /api/v1/docs and other API routes take precedence
This commit is contained in:
40
backend/app/alembic/versions/446a199ddd37_v0_7_0.py
Normal file
40
backend/app/alembic/versions/446a199ddd37_v0_7_0.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""v0.7.0
|
||||
|
||||
Revision ID: 446a199ddd37
|
||||
Revises: 542605083c0c
|
||||
Create Date: 2024-12-26 21:43:01.958551
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '446a199ddd37'
|
||||
down_revision: Union[str, None] = '542605083c0c'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_constraint('activities_garminconnect_activity_id_key', 'activities', type_='unique')
|
||||
op.alter_column('users', 'password',
|
||||
existing_type=sa.VARCHAR(length=100),
|
||||
type_=sa.VARCHAR(length=250),
|
||||
existing_comment='User password (hash)',
|
||||
existing_nullable=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('users', 'password',
|
||||
existing_type=sa.VARCHAR(length=250),
|
||||
type_=sa.VARCHAR(length=100),
|
||||
existing_comment='User password (hash)',
|
||||
existing_nullable=False)
|
||||
op.create_unique_constraint('activities_garminconnect_activity_id_key', 'activities', ['garminconnect_activity_id'])
|
||||
# ### end Alembic commands ###
|
||||
@@ -4,6 +4,7 @@ from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi import Request
|
||||
|
||||
from alembic.config import Config
|
||||
from alembic import command
|
||||
@@ -98,7 +99,14 @@ def create_app() -> FastAPI:
|
||||
|
||||
# Add a route to serve the user images
|
||||
app.mount("/user_images", StaticFiles(directory="user_images"), name="user_images")
|
||||
app.mount("/", StaticFiles(directory="frontend/dist", html=True), name="static")
|
||||
app.mount(
|
||||
"/", StaticFiles(directory="/app/frontend/dist", html=True), name="frontend"
|
||||
)
|
||||
|
||||
@app.get("/{full_path:path}")
|
||||
async def catch_all(full_path: str, request: Request):
|
||||
# Serve the frontend's index.html for any unmatched routes
|
||||
return FileResponse("/app/frontend/dist/index.html")
|
||||
|
||||
return app
|
||||
|
||||
|
||||
@@ -50,14 +50,18 @@ def is_password_complexity_valid(password):
|
||||
|
||||
def hash_password(password: str):
|
||||
# Hash the password and return it
|
||||
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
|
||||
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
|
||||
|
||||
|
||||
def verify_password(plain_password: str, hashed_password: str):
|
||||
# Check if the password is equal to the hashed password
|
||||
return bcrypt.checkpw(
|
||||
plain_password.encode("utf-8"), hashed_password.encode("utf-8")
|
||||
)
|
||||
try:
|
||||
return bcrypt.checkpw(
|
||||
plain_password.encode("utf-8"), hashed_password.encode("utf-8")
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Error verifying password: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def decode_token(token: Annotated[str, Depends(oauth2_scheme)]):
|
||||
|
||||
@@ -35,7 +35,7 @@ class User(Base):
|
||||
comment="User email (max 250 characters)",
|
||||
)
|
||||
password = Column(
|
||||
String(length=100), nullable=False, comment="User password (hash)"
|
||||
String(length=250), nullable=False, comment="User password (hash)"
|
||||
)
|
||||
city = Column(String(length=250), nullable=True, comment="User city")
|
||||
birthdate = Column(Date, nullable=True, comment="User birthdate (date)")
|
||||
|
||||
@@ -17,10 +17,10 @@ services:
|
||||
- BEHIND_PROXY=false # default value is false. Change to true if behind reverse proxy
|
||||
volumes:
|
||||
# - <local_path>/endurain/backend/app:/app # Configure volume if you want to edit the code locally by cloning the repo
|
||||
- <local_path>/endurain/backend/user_images:/app/user_images # necessary for user image persistence on container image updates
|
||||
- <local_path>/endurain/backend/files/bulk_import:/app/files/bulk_import # necessary to enable bulk import of activities. Place here your activities files
|
||||
- <local_path>/endurain/backend/files/processed:/app/files/processed # necessary for processed original files persistence on container image updates
|
||||
- <local_path>/endurain/backend/logs:/app/logs # log files for the backend
|
||||
- <local_path>/endurain/backend/user_images:/app/backend/user_images # necessary for user image persistence on container image updates
|
||||
- <local_path>/endurain/backend/files/bulk_import:/app/backend/files/bulk_import # necessary to enable bulk import of activities. Place here your activities files
|
||||
- <local_path>/endurain/backend/files/processed:/app/backend/files/processed # necessary for processed original files persistence on container image updates
|
||||
- <local_path>/endurain/backend/logs:/app/backend/logs # log files for the backend
|
||||
ports:
|
||||
- "8080:80" # Endurain port, change per your needs
|
||||
depends_on:
|
||||
|
||||
@@ -55,11 +55,20 @@ ENV TZ="UTC" \
|
||||
GEOCODES_MAPS_API="changeme" \
|
||||
BEHIND_PROXY=false
|
||||
|
||||
# Set a non-root user
|
||||
RUN adduser --disabled-password --gecos '' endurain
|
||||
|
||||
# Set the working directory to /app/frontend
|
||||
WORKDIR /app/frontend
|
||||
|
||||
# Copy the directory app contents to /app
|
||||
COPY --from=frontend-build /tmp/frontend/dist ./dist
|
||||
|
||||
# Set the working directory to /app/backend
|
||||
WORKDIR /app/backend
|
||||
|
||||
# Add a non-root user
|
||||
RUN useradd -m endurain
|
||||
#RUN useradd -m endurain
|
||||
|
||||
# Copy requirements.txt from requirements-stage to /app/backend
|
||||
COPY --from=requirements-stage /tmp/backend/requirements.txt ./requirements.txt
|
||||
@@ -70,9 +79,6 @@ RUN pip install --no-cache-dir --upgrade -r ./requirements.txt
|
||||
# Copy the directory app contents to /app
|
||||
COPY backend/app ./
|
||||
|
||||
# Copy the directory app contents to /app
|
||||
COPY --from=frontend-build /tmp/frontend/dist ./frontend/dist
|
||||
|
||||
# Copy the entrypoint script for starting the FastAPI app
|
||||
COPY docker/start.sh /docker-entrypoint.d/start.sh
|
||||
|
||||
@@ -80,7 +86,8 @@ COPY docker/start.sh /docker-entrypoint.d/start.sh
|
||||
RUN chmod +x /docker-entrypoint.d/start.sh
|
||||
|
||||
# Change ownership to non-root user
|
||||
RUN chown -R endurain:endurain ./
|
||||
#RUN chown -R endurain:endurain ./
|
||||
RUN chown -R endurain /app
|
||||
|
||||
# Switch to non-root user
|
||||
USER endurain
|
||||
@@ -88,5 +95,8 @@ USER endurain
|
||||
# Make port 80 available to the world outside this container
|
||||
EXPOSE 80
|
||||
|
||||
# Add a healthcheck
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s CMD curl -f http://localhost/api/v1/about || exit 1
|
||||
|
||||
# Run the FastAPI app
|
||||
ENTRYPOINT ["/docker-entrypoint.d/start.sh"]
|
||||
@@ -4,13 +4,13 @@ set -e
|
||||
# Substitute MY_APP_ENDURAIN_HOST with the value of ENDURAIN_HOST
|
||||
if [ ! -z "$ENDURAIN_HOST" ]; then
|
||||
echo "Substituting MY_APP_ENDURAIN_HOST with $ENDURAIN_HOST"
|
||||
find /app/backend/frontend/dist -type f \( -name '*.js' -o -name '*.css' \) -exec sed -i "s|MY_APP_ENDURAIN_HOST|${ENDURAIN_HOST}|g" '{}' +
|
||||
find /app/frontend/dist -type f \( -name '*.js' -o -name '*.css' \) -exec sed -i "s|MY_APP_ENDURAIN_HOST|${ENDURAIN_HOST}|g" '{}' +
|
||||
fi
|
||||
|
||||
# Substitute MY_APP_STRAVA_CLIENT_ID with the value of STRAVA_CLIENT_ID
|
||||
if [ ! -z "$STRAVA_CLIENT_ID" ]; then
|
||||
echo "Substituting MY_APP_STRAVA_CLIENT_ID with $STRAVA_CLIENT_ID"
|
||||
find /app/backend/frontend/dist -type f \( -name '*.js' -o -name '*.css' \) -exec sed -i "s|MY_APP_STRAVA_CLIENT_ID|${STRAVA_CLIENT_ID}|g" '{}' +
|
||||
find /app/frontend/dist -type f \( -name '*.js' -o -name '*.css' \) -exec sed -i "s|MY_APP_STRAVA_CLIENT_ID|${STRAVA_CLIENT_ID}|g" '{}' +
|
||||
fi
|
||||
|
||||
echo "Starting FastAPI with BEHIND_PROXY=$BEHIND_PROXY"
|
||||
|
||||
@@ -75,10 +75,10 @@ It is recommended to configure the following volumes for data persistence:
|
||||
|
||||
| Volume | Path | Notes |
|
||||
| --- | --- | --- |
|
||||
| /app/files/bulk_import | <local_path>/endurain/backend/files/bulk_import:/app/files/bulk_import | Necessary to enable bulk import of activities. Place here your activities files |
|
||||
| /app/files/processed | <local_path>/endurain/backend/files/processed:/app/files/processed | Necessary for processed original files persistence on container image updates |
|
||||
| /app/user_images | <local_path>/endurain/backend/user_images:/app/user_images | Necessary for user image persistence on container image updates |
|
||||
| /app/logs | <local_path>/endurain/backend/logs:/app/logs | Log files for the backend |
|
||||
| /app/backend/files/bulk_import | <local_path>/endurain/backend/files/bulk_import:/app/files/bulk_import | Necessary to enable bulk import of activities. Place here your activities files |
|
||||
| /app/backend/files/processed | <local_path>/endurain/backend/files/processed:/app/files/processed | Necessary for processed original files persistence on container image updates |
|
||||
| /app/backend/user_images | <local_path>/endurain/backend/user_images:/app/user_images | Necessary for user image persistence on container image updates |
|
||||
| /app/backend/logs | <local_path>/endurain/backend/logs:/app/logs | Log files for the backend |
|
||||
|
||||
## Bulk import and file upload
|
||||
|
||||
|
||||
Reference in New Issue
Block a user