mirror of
https://github.com/bec-project/bec_atlas.git
synced 2025-07-13 22:51:49 +02:00
feat: enabled ldap
This commit is contained in:
@ -196,6 +196,8 @@ class MongoDBDatasource:
|
|||||||
if user is not None:
|
if user is not None:
|
||||||
data = self.add_user_filter(user, data, operation="w")
|
data = self.add_user_filter(user, data, operation="w")
|
||||||
out = self.db[collection].insert_one(data)
|
out = self.db[collection].insert_one(data)
|
||||||
|
if dtype is None:
|
||||||
|
return data
|
||||||
return dtype(**data)
|
return dtype(**data)
|
||||||
|
|
||||||
def patch(
|
def patch(
|
||||||
@ -229,6 +231,8 @@ class MongoDBDatasource:
|
|||||||
)
|
)
|
||||||
if out is None:
|
if out is None:
|
||||||
return None
|
return None
|
||||||
|
if dtype is None:
|
||||||
|
return out
|
||||||
return dtype(**out)
|
return dtype(**out)
|
||||||
|
|
||||||
def delete_one(self, collection: str, filter: dict, user: User | None = None) -> bool:
|
def delete_one(self, collection: str, filter: dict, user: User | None = None) -> bool:
|
||||||
|
@ -62,6 +62,7 @@ class User(MongoBaseModel, AccessProfile):
|
|||||||
groups: list[str]
|
groups: list[str]
|
||||||
first_name: str
|
first_name: str
|
||||||
last_name: str
|
last_name: str
|
||||||
|
username: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class UserInfo(BaseModel):
|
class UserInfo(BaseModel):
|
||||||
|
@ -8,7 +8,9 @@ from pydantic import BaseModel
|
|||||||
from bec_atlas.authentication import create_access_token, get_current_user, verify_password
|
from bec_atlas.authentication import create_access_token, get_current_user, verify_password
|
||||||
from bec_atlas.datasources.mongodb.mongodb import MongoDBDatasource
|
from bec_atlas.datasources.mongodb.mongodb import MongoDBDatasource
|
||||||
from bec_atlas.model import UserInfo
|
from bec_atlas.model import UserInfo
|
||||||
|
from bec_atlas.model.model import User
|
||||||
from bec_atlas.router.base_router import BaseRouter
|
from bec_atlas.router.base_router import BaseRouter
|
||||||
|
from bec_atlas.utils.ldap_auth import LDAPUserService
|
||||||
|
|
||||||
|
|
||||||
class UserLoginRequest(BaseModel):
|
class UserLoginRequest(BaseModel):
|
||||||
@ -20,6 +22,9 @@ class UserRouter(BaseRouter):
|
|||||||
def __init__(self, prefix="/api/v1", datasources=None):
|
def __init__(self, prefix="/api/v1", datasources=None):
|
||||||
super().__init__(prefix, datasources)
|
super().__init__(prefix, datasources)
|
||||||
self.db: MongoDBDatasource = self.datasources.datasources.get("mongodb")
|
self.db: MongoDBDatasource = self.datasources.datasources.get("mongodb")
|
||||||
|
self.ldap = LDAPUserService(
|
||||||
|
ldap_server="ldaps://d.psi.ch", base_dn="OU=users,OU=psi,DC=d,DC=psi,DC=ch"
|
||||||
|
)
|
||||||
self.router = APIRouter(prefix=prefix)
|
self.router = APIRouter(prefix=prefix)
|
||||||
self.router.add_api_route("/user/me", self.user_me, methods=["GET"])
|
self.router.add_api_route("/user/me", self.user_me, methods=["GET"])
|
||||||
self.router.add_api_route("/user/login", self.user_login, methods=["POST"], dependencies=[])
|
self.router.add_api_route("/user/login", self.user_login, methods=["POST"], dependencies=[])
|
||||||
@ -39,14 +44,48 @@ class UserRouter(BaseRouter):
|
|||||||
return {"access_token": out, "token_type": "bearer"}
|
return {"access_token": out, "token_type": "bearer"}
|
||||||
|
|
||||||
async def user_login(self, user_login: UserLoginRequest):
|
async def user_login(self, user_login: UserLoginRequest):
|
||||||
exc = HTTPException(status_code=401, detail="User not found or password is incorrect")
|
user = self._get_user(user_login)
|
||||||
|
if user is None:
|
||||||
|
raise HTTPException(status_code=401, detail="User not found or password is incorrect")
|
||||||
|
return create_access_token(data={"groups": list(user.groups), "email": user.email})
|
||||||
|
|
||||||
|
def _get_user(self, user_login: UserLoginRequest) -> UserInfo | None:
|
||||||
|
user = self._get_functional_account(user_login)
|
||||||
|
if user is None:
|
||||||
|
user = self._get_ad_account(user_login)
|
||||||
|
return user
|
||||||
|
|
||||||
|
def _get_functional_account(self, user_login: UserLoginRequest) -> UserInfo | None:
|
||||||
user = self.db.get_user_by_email(user_login.username)
|
user = self.db.get_user_by_email(user_login.username)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise exc
|
return None
|
||||||
credentials = self.db.get_user_credentials(user.id)
|
credentials = self.db.get_user_credentials(user.id)
|
||||||
if credentials is None:
|
if credentials is None:
|
||||||
raise exc
|
return None
|
||||||
if not verify_password(user_login.password, credentials.password):
|
if not verify_password(user_login.password, credentials.password):
|
||||||
raise exc
|
return None
|
||||||
|
return user
|
||||||
|
|
||||||
return create_access_token(data={"groups": list(user.groups), "email": user.email})
|
def _get_ad_account(self, user_login: UserLoginRequest) -> User | None:
|
||||||
|
user = self.ldap.authenticate_and_get_info(user_login.username, user_login.password)
|
||||||
|
if user is None:
|
||||||
|
return None
|
||||||
|
user_info = User(
|
||||||
|
owner_groups=["admin"],
|
||||||
|
email=user["email"],
|
||||||
|
first_name=user["first_name"],
|
||||||
|
last_name=user["last_name"],
|
||||||
|
username=user["username"],
|
||||||
|
groups=user["roles"],
|
||||||
|
)
|
||||||
|
# update the user info in the database
|
||||||
|
user = self.db.get_user_by_email(user_info.email)
|
||||||
|
if user is None:
|
||||||
|
self.db.post(
|
||||||
|
collection="users", data=user_info.model_dump(exclude_none=True), dtype=None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.db.patch(
|
||||||
|
collection="users", id=user.id, update={"groups": user_info.groups}, dtype=None
|
||||||
|
)
|
||||||
|
return user_info
|
||||||
|
Reference in New Issue
Block a user