Skip to content

Commit 7edb33c

Browse files
authored
Merge pull request #13 from manavgup/feature/auth-ui-updates
Resolve Conflicts on feature/auth-ui-updates
2 parents ef22e60 + dfa38d1 commit 7edb33c

Some content is hidden

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

48 files changed

+3278
-723
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,8 @@ poetry.lock
6363
# Temporary files
6464
*.tmp
6565
*.bak
66-
*.swp
66+
*.swp
67+
68+
# local dev files
69+
dev-env/
70+
webui/default.conf-dev

Makefile

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,26 @@ PYTHON_VERSION ?= 3.11
1616
PROJECT_VERSION ?= v$(shell poetry version -s)
1717

1818
# Tools
19-
DOCKER_COMPOSE := docker-compose
19+
DOCKER_COMPOSE := podman-compose
2020

2121
# Set a default value for VECTOR_DB if not already set
2222
VECTOR_DB ?= milvus
2323

2424
.DEFAULT_GOAL := help
2525

26-
.PHONY: init-env init check-toml format lint audit test run-services build-app run-app clean all info help
26+
.PHONY: init-env init check-toml format lint audit test run-services build-app run-app clean all info help api-test install-deps newman-test run-backend run-frontend
2727

2828
init-env:
2929
@touch .env
3030
@echo "PROJECT_NAME=${PROJECT_NAME}" >> .env
3131
@echo "PYTHON_VERSION=${PYTHON_VERSION}" >> .env
3232
@echo "VECTOR_DB=${VECTOR_DB}" >> .env
3333

34-
init: init-env
34+
install-deps:
3535
pip install -r requirements.txt
3636

37+
init: init-env install-deps
38+
3739
check-toml:
3840
# No equivalent for pip, so this can be left empty or removed
3941

@@ -53,6 +55,18 @@ test: run-services
5355
echo "Waiting for Docker containers to stop..."
5456
@while docker ps | grep -q "milvus-standalone"; do sleep 1; done
5557

58+
api-test: run-services
59+
pytest $(TEST_DIR)/api -v -m api || { echo "API Tests failed"; exit 1; }
60+
@trap '$(DOCKER_COMPOSE) down' EXIT; \
61+
echo "Waiting for Docker containers to stop..."
62+
@while docker ps | grep -q "milvus-standalone"; do sleep 1; done
63+
64+
newman-test: run-services
65+
newman run postman/rag_modulo_api_collection.json
66+
@trap '$(DOCKER_COMPOSE) down' EXIT; \
67+
echo "Waiting for Docker containers to stop..."
68+
@while docker ps | grep -q "milvus-standalone"; do sleep 1; done
69+
5670
create-volumes:
5771
@echo "Creating volume directories with correct permissions..."
5872
@mkdir -p ./volumes/postgres ./volumes/etcd ./volumes/minio ./volumes/milvus
@@ -68,7 +82,7 @@ run-services: create-volumes
6882
$(DOCKER_COMPOSE) up -d postgres
6983
@echo "Waiting for PostgreSQL to be ready..."
7084
@for i in $$(seq 1 30); do \
71-
if docker-compose exec postgres pg_isready -U ${COLLECTIONDB_USER} -d ${COLLECTIONDB_NAME}; then \
85+
if $(DOCKER_COMPOSE) exec postgres pg_isready -U ${COLLECTIONDB_USER} -d ${COLLECTIONDB_NAME}; then \
7286
echo "PostgreSQL is ready"; \
7387
break; \
7488
fi; \
@@ -85,7 +99,7 @@ run-services: create-volumes
8599
$(DOCKER_COMPOSE) up -d etcd minio milvus-standalone || { echo "Failed to start Milvus and its dependencies"; $(DOCKER_COMPOSE) logs; exit 1; }; \
86100
echo "Waiting for Milvus to be ready..."; \
87101
for i in $$(seq 1 30); do \
88-
if docker-compose exec milvus-standalone curl -s http://localhost:9091/healthz | grep -q "OK"; then \
102+
if $(DOCKER_COMPOSE) exec milvus-standalone curl -s http://localhost:9091/healthz | grep -q "OK"; then \
89103
echo "Milvus is ready"; \
90104
break; \
91105
fi; \
@@ -109,8 +123,6 @@ run-services: create-volumes
109123
echo "Unknown VECTOR_DB value: $(VECTOR_DB)"; \
110124
exit 1; \
111125
fi
112-
@echo "Starting backend and frontend..."
113-
$(DOCKER_COMPOSE) up -d backend frontend
114126
@echo "Docker containers status:"
115127
@docker ps
116128
@echo "Milvus logs saved to milvus.log:"
@@ -120,27 +132,38 @@ run-tests:
120132
$(DOCKER_COMPOSE) run --rm test pytest $(ARGS)
121133

122134
build-frontend:
123-
docker build -t $(PROJECT_NAME)-frontend \
124-
-f webui/Dockerfile.frontend ./webui
135+
docker build -t $(PROJECT_NAME)-frontend -f webui/Dockerfile.frontend ./webui
125136

126137
build-backend:
127-
docker build -t $(PROJECT_NAME)-backend \
128-
-f Dockerfile.backend .
138+
docker build --build-arg CACHEBUST=$(date +%s) -t $(PROJECT_NAME)-backend --no-cache -f Dockerfile.backend .
129139

130140
build-app:
131141
@echo "Building application containers..."
132142
$(DOCKER_COMPOSE) build
133143

134-
run-app: build-app run-services
135-
@echo "Starting remaining application containers..."
136-
$(DOCKER_COMPOSE) up -d
144+
run-backend: run-services
145+
@echo "Starting backend..."
146+
$(DOCKER_COMPOSE) up -d backend
147+
@echo "Backend is now running."
148+
149+
run-frontend: run-services
150+
@echo "Starting frontend..."
151+
$(DOCKER_COMPOSE) up -d frontend
152+
@echo "Frontend is now running."
153+
154+
run-app: build-app run-backend run-frontend
137155
@echo "All application containers are now running."
138156

139157
logs:
140158
$(DOCKER_COMPOSE) logs -f
141159

142160
clean:
161+
@echo "Cleaning up Docker Compose resources..."
143162
$(DOCKER_COMPOSE) down -v
163+
@echo "Cleaning up existing pods and containers..."
164+
-@podman pod rm -f $(podman pod ps -q) || true
165+
-@podman rm -f $(podman ps -a -q) || true
166+
-@podman volume prune -f || true
144167
rm -rf .pytest_cache .mypy_cache data volumes my_chroma_data tests
145168

146169
all: format lint audit test
@@ -156,15 +179,20 @@ help:
156179
@echo ""
157180
@echo "Targets:"
158181
@echo " init-env Initialize .env file with default values"
159-
@echo " init Install dependencies"
182+
@echo " init Initialize environment and install dependencies"
183+
@echo " install-deps Install project dependencies"
160184
@echo " check-toml Check TOML files for syntax errors"
161185
@echo " format Format code using ruff, black, and isort"
162186
@echo " lint Lint code using ruff and mypy"
163187
@echo " audit Audit code using bandit"
164-
@echo " test Run tests using pytest"
188+
@echo " test Run all tests using pytest"
189+
@echo " api-test Run API tests using pytest"
190+
@echo " newman-test Run API tests using Newman"
165191
@echo " run-services Start services using Docker Compose"
166192
@echo " build-app Build app using Docker Compose"
167-
@echo " run-app Run app using Docker Compose"
193+
@echo " run-backend Run backend using Docker Compose"
194+
@echo " run-frontend Run frontend using Docker Compose"
195+
@echo " run-app Run both backend and frontend using Docker Compose"
168196
@echo " logs View logs of running containers"
169197
@echo " clean Clean up Docker Compose volumes and cache"
170198
@echo " all Format, lint, audit, and test"

api_tests.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import requests
2+
import json
3+
import uuid
4+
5+
BASE_URL = "http://localhost:8000"
6+
7+
def test_health_check():
8+
response = requests.get(f"{BASE_URL}/api/health")
9+
assert response.status_code == 200, f"Health check failed with status code {response.status_code}"
10+
print("Health check passed")
11+
12+
def test_create_user():
13+
user_data = {
14+
"ibm_id": f"test_user_{uuid.uuid4()}",
15+
"email": f"test_{uuid.uuid4()}@example.com",
16+
"name": f"Test User {uuid.uuid4()}"
17+
}
18+
response = requests.post(f"{BASE_URL}/api/users/", json=user_data)
19+
assert response.status_code == 200, f"User creation failed with status code {response.status_code}"
20+
user = response.json()
21+
print(f"User created: {user['id']}")
22+
return user['id']
23+
24+
def test_create_collection(user_id):
25+
collection_data = {
26+
"name": f"Test Collection {uuid.uuid4()}",
27+
"is_private": True,
28+
"users": [user_id]
29+
}
30+
response = requests.post(f"{BASE_URL}/api/collections/create", json=collection_data)
31+
assert response.status_code == 200, f"Collection creation failed with status code {response.status_code}"
32+
collection = response.json()
33+
print(f"Collection created: {collection['id']}")
34+
return collection['id']
35+
36+
def test_upload_file(user_id, collection_id):
37+
# Create a dummy text file
38+
file_content = f"This is a test file content {uuid.uuid4()}"
39+
files = {'file': ('test_file.txt', file_content)}
40+
response = requests.post(f"{BASE_URL}/api/files/{user_id}/{collection_id}", files=files)
41+
assert response.status_code == 200, f"File upload failed with status code {response.status_code}"
42+
file_info = response.json()
43+
print(f"File uploaded: {file_info['id']}")
44+
return file_info['id']
45+
46+
def run_tests():
47+
test_health_check()
48+
user_id = test_create_user()
49+
collection_id = test_create_collection(user_id)
50+
file_id = test_upload_file(user_id, collection_id)
51+
print("All tests passed successfully")
52+
53+
if __name__ == "__main__":
54+
run_tests()

backend/.dockerignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Ignore Python bytecode and cache
2-
__pycache__/
3-
*.pyc
2+
**__pycache__/
3+
**/*.pyc
44
*.pyo
55
*.pyd
66

backend/Dockerfile.backend

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ RUN apt-get update && apt-get install -y \
4141
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
4242
COPY --from=builder /usr/local/bin /usr/local/bin
4343

44+
# Add a build argument for cache busting
45+
ARG CACHEBUST=1
46+
47+
# COPY backend /app/backend
4448
COPY . /app
4549

4650
# Add a delay and check permissions

backend/auth/oidc.py

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from fastapi import HTTPException, status, Request
2-
from authlib.integrations.starlette_client import OAuth
3-
from core.config import settings
2+
import jwt
43
import logging
54

5+
from authlib.integrations.starlette_client import OAuth, OAuthError
6+
from core.config import settings
7+
68
logging.basicConfig(level=logging.ERROR)
79
logger = logging.getLogger(__name__)
810

@@ -18,19 +20,42 @@
1820
}
1921
)
2022

21-
# oauth2_scheme = OAuth2AuthorizationCodeBearer(
22-
# authorizationUrl=settings.oidc_auth_url,
23-
# tokenUrl=settings.oidc_token_url,
24-
# )
23+
def verify_jwt_token(token: str):
24+
try:
25+
payload = jwt.decode(token, options={"verify_signature": False})
26+
return payload
27+
except jwt.PyJWTError:
28+
raise HTTPException(
29+
status_code=status.HTTP_401_UNAUTHORIZED,
30+
detail="Invalid authentication credentials",
31+
headers={"WWW-Authenticate": "Bearer"},
32+
)
2533

2634
async def get_current_user(request: Request):
27-
user = request.session.get('user')
28-
29-
if not user:
35+
auth_header = request.headers.get('Authorization')
36+
if not auth_header or not auth_header.startswith('Bearer '):
3037
raise HTTPException(
3138
status_code=status.HTTP_401_UNAUTHORIZED,
3239
detail="Not authenticated",
3340
headers={"WWW-Authenticate": "Bearer"},
3441
)
35-
logger.info(f"Got User: {user}")
36-
return user
42+
43+
token = auth_header.split(' ')[1]
44+
payload = verify_jwt_token(token)
45+
46+
logger.info(f"Got User: {payload}")
47+
return payload
48+
49+
async def authorize_redirect(request: Request, redirect_uri: str):
50+
try:
51+
return await oauth.ibm.authorize_redirect(request, redirect_uri)
52+
except OAuthError as error:
53+
logger.error(f"OAuth error during authorize_redirect: {str(error)}")
54+
raise HTTPException(status_code=500, detail="OAuth authorization error")
55+
56+
async def authorize_access_token(request: Request):
57+
try:
58+
return await oauth.ibm.authorize_access_token(request)
59+
except OAuthError as error:
60+
logger.error(f"OAuth error during authorize_access_token: {str(error)}")
61+
raise HTTPException(status_code=500, detail="OAuth token authorization error")

0 commit comments

Comments
 (0)