Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .env.old
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# ============================================
# DOCKER & ENTWICKLER
# ============================================
COMPOSE_PROJECT_NAME=usecase-mgmt-dev-user1


DEV_USER=user1
DB_PORT=5433
BACKEND_PORT=8001
FRONTEND_PORT=3001

# ============================================
# DATENBANK
# ============================================
POSTGRES_USER=user
POSTGRES_PASSWORD=dev_pass_user1
POSTGRES_DB=appdb_dev_user1

DB_READER_USER=reader
DB_READER_PASS=reader-pass
DB_ADMIN_USER=admin
DB_ADMIN_PASS=admin-pass

# ============================================
# BACKEND
# ============================================
DATABASE_URL=postgresql://user:dev_pass_user1@db:5432/appdb_dev_user1
IMAGE_DIR=/app/static/images
ENV=development
ALLOWED_ORIGINS='http://localhost:3001, http://localhost:8001, http://132.195.69.123:3001, http://132.195.69.123:8001, http://132.195.69.123:80, http://132.195.178.126'
SECRET_KEY = "9a6f88adad60f8dc9cae15ea76b9e363a21a051020268f1b2158004ddd5160f4"
# run openssl rand -hex 32

# ============================================
# FRONTEND
# ============================================
VITE_API_URL=http://localhost:8001
VITE_HMR_PORT=3001
157 changes: 157 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Construct-X CI Pipeline

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop

permissions:
contents: read
packages: write
pull-requests: read

env:
REGISTRY: ghcr.io
IMAGE_BASE: ghcr.io/project-construct-x/usecase-management

jobs:
changes:
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.filter.outputs.backend }}
frontend: ${{ steps.filter.outputs.frontend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'backend/**'
frontend:
- 'frontend/**'

test-backend:
needs: changes
if: ${{ always() }}
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
steps:
- if: needs.changes.outputs.backend != 'true'
run: exit 0
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: backend/requirements.txt
- name: Install dependencies
run: pip install -r requirements.txt
- name: Lint (ruff)
run: |
pip install ruff
ruff check .
- name: Run tests
run: pytest

test-frontend:
needs: changes
if: ${{ always() }}
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- if: needs.changes.outputs.frontend != 'true'
run: exit 0
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- run: npm ci
- name: Lint
run: npm run lint
- name: Type Check
run: npm run type-check
- name: Build (Smoke-Test)
run: npm run build

build-backend:
needs: [changes, test-backend]
if: |
always() &&
needs.changes.outputs.backend == 'true' &&
(needs.test-backend.result == 'success') &&
github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.IMAGE_BASE }}-backend
tags: |
type=sha,prefix=
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- uses: docker/build-push-action@v6
with:
context: ./backend
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

build-frontend:
needs: [changes, test-frontend]
if: |
always() &&
needs.changes.outputs.frontend == 'true' &&
(needs.test-frontend.result == 'success') &&
github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.IMAGE_BASE }}-frontend
tags: |
type=sha,prefix=
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- uses: docker/build-push-action@v6
with:
context: ./frontend
file: ./frontend/Dockerfile.prod
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
30 changes: 4 additions & 26 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,12 @@ backend/*.py[cod]
backend/*$py.class
backend/.Python
backend/venv/
backend/.venv/
backend/env/
backend/ENV/
backend/.env
backend/.env.*
backend/!.env.example
backend/*.env
backend/*.db
backend/*.sqlite3

# Backend Environment
backend/.env
backend/.env.local

# Backend input data
*.xlsx
backend/data/input/
Expand All @@ -35,15 +28,8 @@ frontend/.next/
frontend/out/

# Frontend Environment
frontend/.env
frontend/.env.*
frontend/!.env.example
frontend/*.env
frontend/.env.production
.env.prod
frontend/.env.local
frontend/.env.development.local
frontend/.env.test.local
frontend/.env.production.local

# Frontend logs
frontend/npm-debug.log*
Expand Down Expand Up @@ -100,17 +86,9 @@ Thumbs.db
*.tmp
*.temp
.cache/
docker-compose.prod.yml


# Environment variables
.env
.env.*
!.env.example
*.env

# Environment-specific
.env.local
.env.development
.env.production
.env.prod
.env.dev
!.env.example
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ COPY . .

RUN mkdir -p /app/static/images && chmod 777 /app/static/images

EXPOSE 8000
EXPOSE 8080
6 changes: 4 additions & 2 deletions backend/alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import os
from app.config import get_settings
from app.db import Base
from app.models.models import *
from app.models.users import *
Expand Down Expand Up @@ -30,7 +30,9 @@
# my_important_option = config.get_main_option("my_important_option")
# ... etc.

config.set_main_option("sqlalchemy.url", os.environ.get("DATABASE_URL"))
settings = get_settings()
if settings.database_url:
config.set_main_option("sqlalchemy.url", settings.database_url)


def run_migrations_offline() -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '173205317f0f'
Expand Down
2 changes: 0 additions & 2 deletions backend/alembic/versions/1e210cc245e7_fix_dataformat_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
Expand Down
26 changes: 26 additions & 0 deletions backend/app/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
DEV_USER=user1
DB_PORT=5433
BACKEND_PORT=8001

# ============================================
# DATENBANK
# ============================================
POSTGRES_USER=user
POSTGRES_PASSWORD=dev_pass_user1
POSTGRES_DB=appdb_dev_user1

DB_READER_USER=reader
DB_READER_PASS=reader-pass
DB_ADMIN_USER=admin
DB_ADMIN_PASS=admin-pass

# ============================================
# BACKEND
# ============================================
DATABASE_URL=postgresql://user:dev_pass_user1@db:5432/appdb_dev_user1
IMAGE_DIR=/app/static/images
CORS_ORIGINS=http://localhost:3000
# CORS_ORIGINS=http://localhost:3001, http://localhost:8001, http://132.195.69.123:3001, http://132.195.69.123:8001, http://132.195.69.123:80, http://132.195.178.126
SECRET_KEY = "9a6f88adad60f8dc9cae15ea76b9e363a21a051020268f1b2158004ddd5160f4"

LOG_LEVEL=INFO
46 changes: 45 additions & 1 deletion backend/app/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,48 @@
import os
from functools import lru_cache
from pathlib import Path

from pydantic_settings import BaseSettings, SettingsConfigDict

BACKEND_DIR = Path(__file__).resolve().parent
IMAGE_DIR = "/app/static/images"
os.makedirs(IMAGE_DIR, exist_ok=True)
os.makedirs(IMAGE_DIR, exist_ok=True)

def _env_files() -> tuple[Path, ...]:
stage = os.environ.get("APP_ENV", "development")
candidates = (
BACKEND_DIR / f".env.{stage}.local",
BACKEND_DIR / f".env.{stage}",
BACKEND_DIR / ".env",
)
return tuple(path for path in candidates if path.is_file())


class Settings(BaseSettings):
app_env: str = "development"
log_level: str = "INFO"
cors_origins: str = "*"
database_url: str = ""
secret_key: str = ""

model_config = SettingsConfigDict(
env_file_encoding="utf-8",
extra="ignore",
)

@property
def cors_origins_list(self) -> list[str]:
if self.cors_origins.strip() == "*":
return ["*"]
return [
origin.strip()
for origin in self.cors_origins.split(",")
if origin.strip()
]

@lru_cache
def get_settings() -> Settings:
files = _env_files()
return Settings(_env_file=files or None)

settings = get_settings()
6 changes: 3 additions & 3 deletions backend/app/crud/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from ..db import get_db
from ..models.users import User, APIKey, RoleEnum
from ..schemas.users import TokenData
import os
from ..config import get_settings

SECRET_KEY = os.getenv("SECRET_KEY")
SECRET_KEY = get_settings().secret_key
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

Expand Down Expand Up @@ -83,7 +83,7 @@ async def get_user_from_api_key(

key_obj = db.query(APIKey).filter(
APIKey.key == api_key,
APIKey.is_active == True
APIKey.is_active.is_(True)
).first()

if not key_obj:
Expand Down
Loading
Loading