diff --git a/.github/workflows/main_queryweaver.yml b/.github/workflows/main_queryweaver.yml deleted file mode 100644 index bd0011b3..00000000 --- a/.github/workflows/main_queryweaver.yml +++ /dev/null @@ -1,93 +0,0 @@ -# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy -# More GitHub Actions for Azure: https://github.com/Azure/actions -# More info on Python, GitHub Actions, and Azure App Service: https://aka.ms/python-webapps-actions - -name: Build and deploy Python app to Azure Web App - queryweaver - -on: - push: - branches: - - main - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read #This is required for actions/checkout - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python version - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Install pipenv - run: pip install pipenv - - - name: Install dependencies using make - run: make install - - - name: Build production assets - run: make build-prod - - - name: Generate requirements.txt for production - run: pipenv requirements > requirements.txt - - - name: Upload artifact for deployment jobs - uses: actions/upload-artifact@v4 - with: - name: python-app - path: | - . - !venv/ - !node_modules/ - !.git/ - !test-results/ - !playwright-report/ - !tests/e2e/screenshots/ - !__pycache__/ - !Pipfile - !Pipfile.lock - !Makefile - - deploy: - runs-on: ubuntu-latest - needs: build - permissions: - id-token: write #This is required for requesting the JWT - contents: read #This is required for actions/checkout - - steps: - - name: Download artifact from build job - uses: actions/download-artifact@v4 - with: - name: python-app - - - name: Set up Python version - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Login to Azure - uses: azure/login@v2 - with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_5A92CE0E3729470284DEBEC07BD71572 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_1EB63FFB73BB453DA5FC60781960C9E5 }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_5288D7A76CF3435AAEF4F034A1024F79 }} - - - name: 'Deploy to Azure Web App' - uses: azure/webapps-deploy@v3 - id: deploy-to-webapp - with: - app-name: 'queryweaver' - slot-name: 'production' - startup-command: 'python -m uvicorn api.index:app --host 0.0.0.0 --port $PORT' - diff --git a/.github/workflows/staging_queryweaver(staging).yml b/.github/workflows/staging_queryweaver(staging).yml deleted file mode 100644 index 87c04381..00000000 --- a/.github/workflows/staging_queryweaver(staging).yml +++ /dev/null @@ -1,93 +0,0 @@ -# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy -# More GitHub Actions for Azure: https://github.com/Azure/actions -# More info on Python, GitHub Actions, and Azure App Service: https://aka.ms/python-webapps-actions - -name: Build and deploy Python app to Azure Web App - queryweaver - -on: - push: - branches: - - staging - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read #This is required for actions/checkout - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python version - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Install pipenv - run: pip install pipenv - - - name: Install dependencies using make - run: make install - - - name: Build production assets - run: make build-prod - - - name: Generate requirements.txt for production - run: pipenv requirements > requirements.txt - - - name: Upload artifact for deployment jobs - uses: actions/upload-artifact@v4 - with: - name: python-app - path: | - . - !venv/ - !node_modules/ - !.git/ - !test-results/ - !playwright-report/ - !tests/e2e/screenshots/ - !__pycache__/ - !Pipfile - !Pipfile.lock - !Makefile - - deploy: - runs-on: ubuntu-latest - needs: build - permissions: - id-token: write #This is required for requesting the JWT - contents: read #This is required for actions/checkout - - steps: - - name: Download artifact from build job - uses: actions/download-artifact@v4 - with: - name: python-app - - - name: Set up Python version - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Login to Azure - uses: azure/login@v2 - with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_95C84156557F40AF875812F7C29CD989 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_B26FFD333BD44EE98C7ACED0A22637B7 }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_DEEC4D371D1547A6A3F63C9FE22DF791 }} - - - name: 'Deploy to Azure Web App' - uses: azure/webapps-deploy@v3 - id: deploy-to-webapp - with: - app-name: 'queryweaver' - slot-name: 'staging' - startup-command: 'python -m uvicorn api.index:app --host 0.0.0.0 --port $PORT' - diff --git a/TOKEN_MANAGEMENT.md b/TOKEN_MANAGEMENT.md deleted file mode 100644 index 81e73fdc..00000000 --- a/TOKEN_MANAGEMENT.md +++ /dev/null @@ -1,224 +0,0 @@ -# Token Management Feature - -This document describes the API token management feature implemented for QueryWeaver, allowing users to generate and manage API tokens for authentication. - -## Overview - -The token management system allows authenticated users to: - -1. **Generate API tokens** - Create secure tokens for API access -2. **View token list** - See all their tokens (with only last 4 digits visible) -3. **Delete tokens** - Remove tokens they no longer need -4. **Use tokens for API authentication** - Authenticate API calls using Bearer tokens - -## Architecture - -### Backend Components - -#### 1. Token Routes (`api/routes/tokens.py`) -- **POST `/tokens/generate`** - Generate a new token -- **GET `/tokens/list`** - List user's tokens -- **DELETE `/tokens/{token_id}`** - Delete a specific token - -#### 2. Authentication Enhancement (`api/auth/user_management.py`) -- Enhanced `token_required` decorator to support both OAuth and API token authentication -- New `validate_api_token_user()` function for token-based authentication - -#### 3. Database Schema -Tokens are stored as nodes in the Organizations graph with the following structure: -```cypher -(:Token { - token_id: "unique_token_identifier", - token_hash: "sha256_hash_of_token", - created_at: timestamp, - last_4_digits: "1234" -})-[:HAS_TOKEN]-(:User) -``` - -### Frontend Components - -#### 1. User Interface (`app/templates/components/`) -- **token_modal.j2** - Token management modal with generation and list views -- **user_profile.j2** - Added "API Tokens" button to user profile dropdown - -#### 2. TypeScript Module (`app/ts/modules/tokens.ts`) -- Token generation and management functions -- Modal handling and user interactions -- API communication for CRUD operations - -#### 3. Styling (`app/public/css/modals.css`) -- Modal styling for token management interface -- Token display and action button styles - -## Security Features - -### 1. Token Generation -- Uses `secrets.token_urlsafe(32)` for cryptographically secure random tokens -- Tokens are 43 characters long (URL-safe base64 encoding) - -### 2. Token Storage -- Only SHA-256 hashes of tokens are stored in the database -- Original tokens are never persisted -- Each token has a unique `token_id` for identification - -### 3. Token Display -- After generation, tokens are shown once in full -- In the token list, only last 4 digits are visible (e.g., "****1234") -- Copy-to-clipboard functionality for newly generated tokens - -### 4. Authentication -- API calls can use `Authorization: Bearer ` header -- Server validates by hashing received token and matching against stored hash -- Falls back to OAuth session authentication if no valid token provided - -## API Usage Examples - -### 1. Generate a Token -```bash -# Must be authenticated via OAuth session -curl -X POST http://localhost:5000/tokens/generate \ - -H "Content-Type: application/json" \ - --cookie "session_cookie=..." -``` - -Response: -```json -{ - "token": "6SxwdQ3vZeEE6xCVwTmD3AbKvWZY2eR_quUCP7eewEA", - "token_id": "G13pqOpPohhs2rnou56A2w", - "created_at": 1706096845, - "last_4_digits": "ewEA" -} -``` - -### 2. List Tokens -```bash -curl -X GET http://localhost:5000/tokens/list \ - -H "Authorization: Bearer 6SxwdQ3vZeEE6xCVwTmD3AbKvWZY2eR_quUCP7eewEA" -``` - -Response: -```json -{ - "tokens": [ - { - "token_id": "G13pqOpPohhs2rnou56A2w", - "created_at": 1706096845, - "last_4_digits": "ewEA" - } - ] -} -``` - -### 3. Delete a Token -```bash -curl -X DELETE http://localhost:5000/tokens/G13pqOpPohhs2rnou56A2w \ - -H "Authorization: Bearer 6SxwdQ3vZeEE6xCVwTmD3AbKvWZY2eR_quUCP7eewEA" -``` - -### 4. Use Token for API Access -```bash -# Any protected endpoint can now use token authentication -curl -X GET http://localhost:5000/graphs \ - -H "Authorization: Bearer 6SxwdQ3vZeEE6xCVwTmD3AbKvWZY2eR_quUCP7eewEA" -``` - -## User Interface Flow - -### 1. Accessing Token Management -1. User logs in via OAuth (Google/GitHub) -2. User clicks their profile picture in the top-right corner -3. User clicks "API Tokens" in the dropdown menu -4. Token management modal opens - -### 2. Generating a Token -1. User clicks "Generate New Token" button -2. System creates secure token and stores hash in database -3. Full token is displayed once with copy button -4. Token appears in user's token list (showing only last 4 digits) - -### 3. Managing Tokens -1. User sees list of all their tokens with creation dates -2. Each token shows only last 4 digits for security -3. User can delete tokens using the "Delete" button -4. Confirmation modal appears before deletion - -## Database Queries - -### Create Token -```cypher -MATCH (user:User {email: $user_email}) -CREATE (token:Token { - token_id: $token_id, - token_hash: $token_hash, - created_at: $created_at, - last_4_digits: $last_4_digits -}) -CREATE (user)-[:HAS_TOKEN]->(token) -RETURN token -``` - -### List User Tokens -```cypher -MATCH (user:User {email: $user_email})-[:HAS_TOKEN]->(token:Token) -RETURN token.token_id, token.created_at, token.last_4_digits -ORDER BY token.created_at DESC -``` - -### Validate Token -```cypher -MATCH (user:User)-[:HAS_TOKEN]->(token:Token {token_hash: $token_hash}) -RETURN user.email -``` - -### Delete Token -```cypher -MATCH (user:User {email: $user_email})-[r:HAS_TOKEN]->(token:Token {token_id: $token_id}) -DELETE r, token -``` - -## Testing - -The implementation includes comprehensive tests: - -- **Unit tests** for token generation and validation functions -- **API tests** for authentication and authorization -- **Integration tests** for token CRUD operations - -Run tests: -```bash -make test-unit # Run unit tests -pipenv run python -m pytest tests/test_tokens.py -v # Run token-specific tests -``` - -## Implementation Notes - -### 1. Graph Database Integration -- Leverages existing Organizations graph structure -- Tokens connect to User nodes via HAS_TOKEN relationships -- Maintains consistency with existing authentication patterns - -### 2. Backward Compatibility -- OAuth authentication continues to work unchanged -- API token authentication is additive, not replacement -- Existing protected routes automatically support both auth methods - -### 3. Error Handling -- Comprehensive error handling for database operations -- Proper HTTP status codes and error messages -- Graceful fallback between authentication methods - -### 4. Performance Considerations -- Efficient graph queries with proper indexing -- Minimal additional overhead for token validation -- Caching considerations for user email lookups - -## Future Enhancements - -Potential improvements for the token system: - -1. **Token Expiration** - Add configurable expiration dates -2. **Token Scopes** - Limit tokens to specific API operations -3. **Usage Analytics** - Track token usage and last access times -4. **Rate Limiting** - Implement per-token rate limiting -5. **Token Naming** - Allow users to name their tokens for easier management \ No newline at end of file diff --git a/apprunner.yaml b/apprunner.yaml deleted file mode 100644 index 577cc664..00000000 --- a/apprunner.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: 1.0 -runtime: python311 -build: - commands: - build: - - pip install pipenv - - pipenv install --deploy --ignore-pipfile -run: - command: pipenv run uvicorn main:app --host 0.0.0.0 --port 8000 - network: - port: 8000 \ No newline at end of file