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
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""add selected_repo to User model

Revision ID: 0110b0fe23e2
Revises: dd6498244230
Create Date: 2025-04-11 10:02:54.906969

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '0110b0fe23e2'
down_revision: Union[str, None] = 'dd6498244230'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('users', 'github_id',
existing_type=sa.INTEGER(),
type_=sa.String(),
existing_nullable=True)
# ### end Alembic commands ###


def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('users', 'github_id',
existing_type=sa.String(),
type_=sa.INTEGER(),
existing_nullable=True)
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""add selected_repo to User model

Revision ID: 3941b5ea8743
Revises: 0110b0fe23e2
Create Date: 2025-04-11 10:32:09.102609

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '3941b5ea8743'
down_revision: Union[str, None] = '0110b0fe23e2'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###


def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""add selected_repo to users

Revision ID: a37610476ce3
Revises: 3941b5ea8743
Create Date: 2025-04-11 17:07:29.751848

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'a37610476ce3'
down_revision: Union[str, None] = '3941b5ea8743'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('selected_repo', sa.String(), nullable=True))
# ### end Alembic commands ###


def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('users', 'selected_repo')
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""make last_push and last_login nullable

Revision ID: fffe4c516230
Revises: a37610476ce3
Create Date: 2025-04-11 18:32:12.060038

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'fffe4c516230'
down_revision: Union[str, None] = 'a37610476ce3'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###


def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
13 changes: 11 additions & 2 deletions backend/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from fastapi import Header, HTTPException
import os
from dotenv import load_dotenv
import traceback

# Load environment variables
def get_database_url():
Expand Down Expand Up @@ -31,14 +32,17 @@ def create_jwt_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
jwt_token = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
print(f"[auth.py] Created JWT token: {jwt_token[:20]}...")
return jwt_token

def create_access_token(data: dict):
"""Alias for create_jwt_token for backward compatibility"""
return create_jwt_token(data)

def verify_token(token: str):
"""Verify and decode a JWT token"""

try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
if "exp" not in payload:
Expand All @@ -51,21 +55,26 @@ def verify_token(token: str):
return None
except Exception as e:
print(f"Token verification error: {str(e)}")

return None

async def get_current_user(authorization: str = Header(...)):
"""Get current user from authorization header"""
try:

token = authorization.replace("Bearer ", "")
payload = verify_token(token)
if not payload:

raise HTTPException(
status_code=401,
detail="Invalid or expired token"
)

return payload
except Exception as e:
raise HTTPException(
status_code=401,
detail=f"Authorization failed: {str(e)}"
)
)

14 changes: 11 additions & 3 deletions backend/github_oauth.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import os
import httpx
from fastapi import Request
import logging
from fastapi import Request, HTTPException

logger = logging.getLogger(__name__)

GITHUB_CLIENT_ID = os.getenv("GITHUB_CLIENT_ID")
GITHUB_CLIENT_SECRET = os.getenv("GITHUB_CLIENT_SECRET")

if not GITHUB_CLIENT_ID or not GITHUB_CLIENT_SECRET:
logger.error("GitHub OAuth credentials missing!")
logger.error(f"GITHUB_CLIENT_ID: {'present' if GITHUB_CLIENT_ID else 'missing'}")
logger.error(f"GITHUB_CLIENT_SECRET: {'present' if GITHUB_CLIENT_SECRET else 'missing'}")
raise ValueError("❌ GitHub OAuth credentials not found")

print(f"🔑 GitHub OAuth Configuration: Client ID: {GITHUB_CLIENT_ID[:5]}...")

async def exchange_code_for_token(code: str):

"""Exchange GitHub OAuth code for token data"""
try:
async with httpx.AsyncClient() as client:
Expand All @@ -26,13 +33,14 @@ async def exchange_code_for_token(code: str):
headers={
"Accept": "application/json"
},

data={
"client_id": GITHUB_CLIENT_ID,
"client_secret": GITHUB_CLIENT_SECRET,
"code": code
}
)

print(f"✅ GitHub token exchange status: {response.status_code}")
print(f"Response headers: {dict(response.headers)}")

Expand Down Expand Up @@ -132,4 +140,4 @@ async def get_user_info(access_token: str):

except Exception as e:
print(f"❌ Error getting user info: {str(e)}")
raise
raise
Loading