Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e20b963
added a function to hardware.py for cpu temp tracking, edited emissio…
Jargusb Apr 5, 2026
db8360f
added temp tracking test workflow
Jargusb Apr 6, 2026
29a0c9e
Fix flake8 f-string warnings in test file
Jargusb Apr 6, 2026
b60e032
Apply black and isort formatting fixes
Jargusb Apr 6, 2026
5e63763
Add cpu_temperature and gpu_temperature to test data CSV
Jargusb Apr 6, 2026
528a155
changed test_temp workflow naming from main to master
Jargusb Apr 6, 2026
a8ebc37
Added Documentation, can be found in /docs/Contributions
Pat3690 Apr 7, 2026
8ca4b86
Made a test to ensure changes to hardware.py produce expected output.
j-rebell Apr 7, 2026
591d2c1
Merge remote-tracking branch 'origin/master'
j-rebell Apr 7, 2026
0507f02
Made a test to ensure changes to hardware.py produce expected output.
j-rebell Apr 7, 2026
d9fc3df
removed test_temp.yml and test_temp.py, wew used for debugging purposes
Jargusb Apr 9, 2026
5b5fad0
Changed testing to test for psutil returning a value in test_cpu.py. …
j-rebell Apr 9, 2026
d6eedfc
Changed testing to test for psutil returning a value in test_cpu.py. …
j-rebell Apr 9, 2026
7a72419
Updated Documentation, can be found in /docs/Contributions
Pat3690 Apr 9, 2026
0047787
added accelerator.py file for added inferentia chip support, open to …
Jargusb Apr 18, 2026
76d59e6
added a function to hardware.py for cpu temp tracking, edited emissio…
Jargusb Apr 5, 2026
26819de
added temp tracking test workflow
Jargusb Apr 6, 2026
a31391a
Fix flake8 f-string warnings in test file
Jargusb Apr 6, 2026
87994fb
Apply black and isort formatting fixes
Jargusb Apr 6, 2026
694e24d
Add cpu_temperature and gpu_temperature to test data CSV
Jargusb Apr 6, 2026
28f1829
changed test_temp workflow naming from main to master
Jargusb Apr 6, 2026
75d0852
Made a test to ensure changes to hardware.py produce expected output.
j-rebell Apr 7, 2026
5d21493
Rebase on upstream/master
Pat3690 Apr 7, 2026
aba2f39
Made a test to ensure changes to hardware.py produce expected output.
j-rebell Apr 7, 2026
42561da
removed test_temp.yml and test_temp.py, wew used for debugging purposes
Jargusb Apr 9, 2026
6b161c8
Changed testing to test for psutil returning a value in test_cpu.py. …
j-rebell Apr 9, 2026
7769362
Changed testing to test for psutil returning a value in test_cpu.py. …
j-rebell Apr 9, 2026
5bdf6e6
Updated Documentation, can be found in /docs/Contributions
Pat3690 Apr 9, 2026
fb5d4b1
Merge remote-tracking branch 'origin/master'
m1savas Apr 19, 2026
1397119
rerun tests
m1savas Apr 19, 2026
6b99c6c
Merge branch 'master' of https://github.com/Jargusb/codecarbon
Jargusb Apr 24, 2026
1b2f921
retrying push
Jargusb Apr 24, 2026
da7aa9f
added user error check returning 401 authentication error to error.py
Jargusb May 5, 2026
2ec024a
Merge branch 'master' into master
m1savas May 6, 2026
aa48a11
reformatted auth_service call class to lower complexity rating, now s…
Jargusb May 8, 2026
f44c8c0
fix for last group issue, implemented class method in file.py for pri…
Jargusb May 10, 2026
0d14db3
added the 3 files in test directory for group issue #2, #3, and my so…
Jargusb May 10, 2026
6f4aaea
moved test_auth_fix to test folder within carbon server directory
Jargusb May 10, 2026
52e7134
added testing for 401 authentication error
Jargusb May 11, 2026
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
4 changes: 3 additions & 1 deletion carbonserver/carbonserver/api/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ def get_http_exception(exception) -> HTTPException:
take an internal exception and return a HTTPException
"""
if isinstance(exception, UserException):
if isinstance(error := exception.error, NotAllowedError):
if isinstance(error := exception.error, UserError):
return HTTPException(status_code=401, detail=error.message)
elif isinstance(error := exception.error, NotAllowedError):
return HTTPException(status_code=403, detail=error.message)
elif isinstance(error := exception.error, NotFoundError):
return HTTPException(status_code=404, detail=error.message)
Expand Down
7 changes: 5 additions & 2 deletions carbonserver/carbonserver/api/routers/authenticate.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ def check_login(
sign_up_service: SignUpService = Depends(Provide[ServerContainer.sign_up_service]),
):
"""
return user data or redirect to login screen
null value if not logged in
Return user data or null if not logged in.
Returns 401 if token is present but invalid/expired.
"""
if auth_user.auth_user is None:
return {"user": None}

sign_up_service.check_jwt_user(auth_user.auth_user, create=True)
return {"user": auth_user.auth_user}

Expand Down
88 changes: 52 additions & 36 deletions carbonserver/carbonserver/api/services/auth_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,53 +55,69 @@ async def __call__(
):
self.user_service = user_service
if cookie_token is not None:
self.auth_user = jwt.decode(
self.auth_user = self._decode_cookie_token(cookie_token)
elif bearer_token is not None:
await self._validate_bearer_token(bearer_token, auth_provider)
self.auth_user = self._decode_bearer_token(bearer_token)
else:
self.auth_user = None
if self.error_if_not_found:
raise HTTPException(
status_code=401,
detail="No token provided, please log in",
)
self.db_user = self._get_db_user(user_service)
return self

def _decode_cookie_token(self, cookie_token: str):
try:
return jwt.decode(
cookie_token,
options={"verify_signature": False},
algorithms=["HS256", "RS256"],
)
elif bearer_token is not None:
if settings.environment != "develop" and auth_provider is not None:
LOGGER.debug(
f"Validating token with auth provider. Token: {bearer_token}"
)
try:
await auth_provider.validate_access_token(bearer_token.credentials)
except Exception:
raise HTTPException(status_code=401, detail="Invalid token")
# cli user using auth provider token
self.auth_user = jwt.decode(
except Exception:
raise HTTPException(401, "Session expired, please log in")

async def _validate_bearer_token(self, bearer_token, auth_provider):
if settings.environment != "develop" and auth_provider is not None:
try:
await auth_provider.validate_access_token(bearer_token.credentials)
except Exception:
raise HTTPException(status_code=401, detail="Invalid token")

def _decode_bearer_token(self, bearer_token) -> dict:
try:
auth_user = jwt.decode(
bearer_token.credentials,
options={"verify_signature": False},
algorithms=[
"HS256",
"RS256",
],
algorithms=["HS256", "RS256"],
)
if settings.environment == "develop":
try:
# test user
self.auth_user = jwt.decode(
bearer_token.credentials,
settings.jwt_key,
algorithms=[
"HS256",
"RS256",
],
)
except Exception:
...
else:
self.auth_user = None
if self.error_if_not_found:
raise HTTPException(status_code=401, detail="Unauthorized")
except Exception:
LOGGER.warning("Failed to decode bearer token")
raise HTTPException(
status_code=401,
detail="Invalid or expired token, please log in again",
)
if settings.environment == "develop":
try:
auth_user = jwt.decode(
bearer_token.credentials,
settings.jwt_key,
algorithms=["HS256", "RS256"],
)
except Exception:
pass
return auth_user

def _get_db_user(self, user_service) -> Optional[dict]:
if self.auth_user is None:
return None
try:
self.db_user = user_service.get_user_by_id(self.auth_user["sub"])
return user_service.get_user_by_id(self.auth_user["sub"])
except Exception:
self.db_user = None

return self
return None


OptionalUserWithAuthDependency = UserWithAuthDependency(error_if_not_found=False)
Expand Down
1 change: 1 addition & 0 deletions carbonserver/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dependencies = [
"fastapi-oidc>=0.0.9",
"authlib>=1.6.6",
"itsdangerous>=2.2.0",
"pytest-asyncio>=1.3.0",
]

[project.optional-dependencies]
Expand Down
Empty file.
44 changes: 44 additions & 0 deletions carbonserver/tests/api/routers/test_auth_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
Tests for issue #692 - missing/invalid tokens returning generic 500 error
instead of proper 401.
"""


class TestGetHttpException:
"""Tests for errors.py get_http_exception() - core fix for issue #692."""

def test_user_error_api_key_unknown_returns_401(self):
from carbonserver.carbonserver.api.errors import (
UserError,
UserErrorEnum,
UserException,
get_http_exception,
)

error = UserError(
code=UserErrorEnum.API_KEY_UNKNOWN, message="API key not found"
)
result = get_http_exception(UserException(error))
assert result.status_code == 401
assert result.detail == "API key not found"

def test_user_error_api_key_disabled_returns_401(self):
from carbonserver.carbonserver.api.errors import (
UserError,
UserErrorEnum,
UserException,
get_http_exception,
)

error = UserError(
code=UserErrorEnum.API_KEY_DISABLE, message="API key disabled"
)
result = get_http_exception(UserException(error))
assert result.status_code == 401

def test_generic_exception_returns_500_with_detail(self):
from carbonserver.carbonserver.api.errors import get_http_exception

result = get_http_exception(Exception("unexpected"))
assert result.status_code == 500
assert result.detail == "Internal Server Error"
23 changes: 19 additions & 4 deletions carbonserver/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading