Skip to content
This repository was archived by the owner on Nov 5, 2022. It is now read-only.

Commit 2523ded

Browse files
faysal-ishtiaqisedwards
authored andcommitted
use mysql.user table for climsoft auth
1 parent af7c72f commit 2523ded

File tree

7 files changed

+98
-7
lines changed

7 files changed

+98
-7
lines changed

playground.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from sqlalchemy import create_engine
2+
from sqlalchemy import text as sa_text
3+
from sqlalchemy.orm import sessionmaker, Session
4+
5+
if __name__ == "__main__":
6+
climsoft_engine = create_engine("mysql+mysqldb://root:password@127.0.0.1:23306/mariadb_climsoft_test_db_v4")
7+
ClimsoftSessionLocal = sessionmaker(climsoft_engine)
8+
session: Session = ClimsoftSessionLocal()
9+
username = "root"
10+
password = "password"
11+
user = session.execute(sa_text(f'''
12+
SELECT *
13+
FROM mysql.user
14+
WHERE User="{username}" AND Password=password("{password}")
15+
'''))
16+
17+
print(user.all())

src/opencdms_api/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Settings(BaseSettings):
2525

2626
AUTH_ENABLED: bool
2727

28+
CLIMSOFT_DATABASE_URI: str
2829
DATABASE_URI: Optional[PostgresDsn] = None
2930

3031
@validator("DATABASE_URI", pre=True)

src/opencdms_api/db.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010

1111
engine = create_engine(settings.DATABASE_URI)
12-
12+
climsoft_engine = create_engine(settings.CLIMSOFT_DATABASE_URI)
1313
SessionLocal = sessionmaker(engine)
14-
14+
ClimsoftSessionLocal = sessionmaker(climsoft_engine)
1515
Base = declarative_base()
1616

1717
ScopedSession = scoped_session(SessionLocal)

src/opencdms_api/deps.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from sqlalchemy.orm.session import Session
2-
from src.opencdms_api.db import SessionLocal
2+
from src.opencdms_api.db import SessionLocal, ClimsoftSessionLocal
33

44

55
def get_session():
@@ -15,3 +15,19 @@ def get_session():
1515
raise e
1616
finally:
1717
session.close()
18+
19+
20+
def get_climsoft_session():
21+
"""
22+
Api dependency to provide climsoft database session to a request
23+
"""
24+
session: Session = ClimsoftSessionLocal()
25+
try:
26+
yield session
27+
session.commit()
28+
except Exception as e:
29+
session.rollback()
30+
raise e
31+
finally:
32+
session.close()
33+

src/opencdms_api/middleware.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from src.opencdms_api.config import settings
1313
from src.opencdms_api.db import db_session_scope
1414
from src.opencdms_api import climsoft_rbac_config
15-
from src.opencdms_api.schema import CurrentUserSchema
15+
from src.opencdms_api.schema import CurrentUserSchema, CurrentClimsoftUserSchema
1616
from opencdms.models.climsoft import v4_1_1_core as climsoft_models
1717
from fastapi import Header, Depends
1818
from fastapi.security import OAuth2PasswordBearer
@@ -98,6 +98,23 @@ class ClimsoftRBACMiddleware(AuthMiddleWare):
9898
def __init__(self, app: ASGIApp):
9999
super().__init__(app)
100100

101+
def authenticate_request(self, request: Request):
102+
authorization_header = request.headers.get("authorization")
103+
if authorization_header is None:
104+
raise HTTPException(401, "Unauthorized request")
105+
scheme, token = get_authorization_scheme_param(authorization_header)
106+
if scheme.lower() != "bearer":
107+
raise HTTPException(401, "Invalid authorization header scheme")
108+
try:
109+
claims = jwt.decode(token, settings.SURFACE_SECRET_KEY)
110+
except JWTError:
111+
raise HTTPException(401, "Unauthorized request")
112+
username = claims["sub"]
113+
user = CurrentClimsoftUserSchema(username=username)
114+
if user is None:
115+
raise HTTPException(401, "Unauthorized request")
116+
return user
117+
101118
async def __call__(self, scope: Scope, receive: Receive, send: Send):
102119
request = Request(scope, receive, send)
103120
user = None
@@ -134,7 +151,7 @@ def get_authorized_climsoft_user(
134151

135152
username = claims["sub"]
136153

137-
user = get_user(username)
154+
user = CurrentClimsoftUserSchema(username=username)
138155

139156
if user is None:
140157
raise HTTPException(401, "Unauthorized request")

src/opencdms_api/router.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
from uuid import uuid4
33
from fastapi import APIRouter, Depends
44
from fastapi.exceptions import HTTPException
5+
from sqlalchemy import text as sa_text
56
from sqlalchemy.orm.session import Session
67
from passlib.hash import django_pbkdf2_sha256 as handler
78
from src.opencdms_api import deps, models
89
from src.opencdms_api.schema import (
910
UserCreateSchema,
1011
AuthenticationSchema,
11-
TokenSchema
12+
TokenSchema,
13+
ClimsoftTokenSchema
1214
)
1315
from src.opencdms_api.config import settings
1416
from jose import jwt
@@ -66,3 +68,32 @@ def authenticate(
6668
)
6769
return TokenSchema(access_token=access_token, first_name=user.first_name, last_name=user.last_name)
6870

71+
72+
@router.post("/climsoft-auth", response_model=TokenSchema)
73+
def authenticate(
74+
payload: OAuth2PasswordRequestForm = Depends(),
75+
session: Session = Depends(deps.get_climsoft_session())
76+
):
77+
user = session.execute(sa_text(f'''
78+
SELECT User
79+
FROM mysql.user
80+
WHERE User="{payload.username}" AND Password=password("{payload.password}")
81+
''')).all()
82+
83+
if not user:
84+
raise HTTPException(400, "Invalid login credentials")
85+
86+
user = user[0]
87+
88+
access_token = jwt.encode(
89+
{
90+
"sub": user[1],
91+
"exp": datetime.utcnow() + timedelta(hours=24),
92+
"token_type": "access",
93+
"jti": str(uuid4()),
94+
"user_id": int(user.id)
95+
},
96+
key=settings.SURFACE_SECRET_KEY,
97+
)
98+
return ClimsoftTokenSchema(access_token=access_token, username=user[1])
99+

src/opencdms_api/schema.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,20 @@ class TokenSchema(BaseModel):
5858
last_name: str
5959

6060

61+
class ClimsoftTokenSchema(BaseModel):
62+
access_token: str
63+
username: str
64+
65+
6166
class CurrentUserSchema(BaseSchema):
6267
email: EmailStr
6368
username: str
6469
first_name: str
6570
last_name: str
6671

6772
class Config:
68-
orm_mode = True
73+
orm_mode = True
74+
75+
76+
class CurrentClimsoftUserSchema(BaseModel):
77+
username: str

0 commit comments

Comments
 (0)