fix: Fix empty projects in profile

Fix empty projects in profile when using sso login

Change-Id: I2296cc88f04e3a3eeb2c51d8e83335923e0e5353
This commit is contained in:
yangsngshaoxue 2022-08-24 09:47:33 +08:00
parent 40b30101c3
commit 8fadde52bf
2 changed files with 72 additions and 46 deletions

View File

@ -15,6 +15,7 @@
from __future__ import annotations from __future__ import annotations
from pathlib import PurePath from pathlib import PurePath
from typing import Any, List, Optional, Tuple
from fastapi import APIRouter, Depends, Form, Header, HTTPException, Request, Response, status from fastapi import APIRouter, Depends, Form, Header, HTTPException, Request, Response, status
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
@ -45,14 +46,75 @@ from skyline_apiserver.types import constants
router = APIRouter() router = APIRouter()
async def _get_projects_and_unscope_token(
region: str,
domain: Optional[str] = None,
username: Optional[str] = None,
password: Optional[str] = None,
token: Optional[str] = None,
) -> Tuple[List[Any], str]:
try:
auth_url = await utils.get_endpoint(
region=region,
service="keystone",
session=get_system_session(),
)
if token:
unscope_auth = Token(
auth_url=auth_url,
token=token,
reauthenticate=False,
)
else:
unscope_auth = Password(
auth_url=auth_url,
user_domain_name=domain,
username=username,
password=password,
reauthenticate=False,
)
session = Session(auth=unscope_auth, verify=False, timeout=constants.DEFAULT_TIMEOUT)
unscope_client = KeystoneClient(
session=session,
endpoint=auth_url,
interface=CONF.openstack.interface_type,
)
project_scope = unscope_client.auth.projects()
unscope_token = token if token else session.get_token()
except Exception as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=str(e),
)
# we must get the project_scope with enabled project
project_scope = [scope for scope in project_scope if scope.enabled]
if not project_scope:
raise Exception("You are not authorized for any projects or domains.")
return project_scope, unscope_token
async def _patch_profile(profile: schemas.Profile, global_request_id: str) -> schemas.Profile: async def _patch_profile(profile: schemas.Profile, global_request_id: str) -> schemas.Profile:
try: try:
profile.endpoints = await get_endpoints(region=profile.region) profile.endpoints = await get_endpoints(region=profile.region)
profile.projects = await get_projects(
projects = await get_projects(
global_request_id=global_request_id, global_request_id=global_request_id,
region=profile.region, region=profile.region,
user=profile.user.id, user=profile.user.id,
) )
if not projects:
projects, _ = await _get_projects_and_unscope_token(
region=profile.region, token=profile.keystone_token
)
profile.projects = {i.id: {"name": i.name, "domain_id": i.domain_id} for i in projects}
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
@ -83,32 +145,15 @@ async def login(
), ),
): ):
try: try:
auth_url = await utils.get_endpoint( project_scope, unscope_token = await _get_projects_and_unscope_token(
region=credential.region, region=credential.region,
service="keystone", domain=credential.domain,
session=get_system_session(),
)
unscope_auth = Password(
auth_url=auth_url,
user_domain_name=credential.domain,
username=credential.username, username=credential.username,
password=credential.password, password=credential.password,
reauthenticate=False,
) )
session = Session(auth=unscope_auth, verify=False, timeout=constants.DEFAULT_TIMEOUT)
unscope_client = KeystoneClient(
session=session,
endpoint=auth_url,
interface=CONF.openstack.interface_type,
)
project_scope = unscope_client.auth.projects()
# we must get the project_scope with enabled project
project_scope = [scope for scope in project_scope if scope.enabled]
if not project_scope:
raise Exception("You are not authorized for any projects or domains.")
project_scope_token = await get_project_scope_token( project_scope_token = await get_project_scope_token(
keystone_token=session.get_token(), keystone_token=unscope_token,
region=credential.region, region=credential.region,
project_id=project_scope[0].id, project_id=project_scope[0].id,
) )
@ -196,27 +241,9 @@ async def websso(
), ),
) -> RedirectResponse: ) -> RedirectResponse:
try: try:
auth_url = await utils.get_endpoint( project_scope, _ = await _get_projects_and_unscope_token(
region=CONF.openstack.sso_region, region=CONF.openstack.sso_region, token=token
service="keystone",
session=get_system_session(),
) )
unscope_auth = Token(
auth_url=auth_url,
token=token,
reauthenticate=False,
)
session = Session(auth=unscope_auth, verify=False, timeout=constants.DEFAULT_TIMEOUT)
unscope_client = KeystoneClient(
session=session,
endpoint=auth_url,
interface=CONF.openstack.interface_type,
)
project_scope = unscope_client.auth.projects()
# we must get the project_scope with enabled project
project_scope = [scope for scope in project_scope if scope.enabled]
if not project_scope:
raise Exception("You are not authorized for any projects or domains.")
project_scope_token = await get_project_scope_token( project_scope_token = await get_project_scope_token(
keystone_token=token, keystone_token=token,

View File

@ -15,7 +15,7 @@
from __future__ import annotations from __future__ import annotations
from pathlib import PurePath from pathlib import PurePath
from typing import Any, Dict from typing import Any, Dict, List
from keystoneauth1.identity.v3 import Token from keystoneauth1.identity.v3 import Token
from keystoneauth1.session import Session from keystoneauth1.session import Session
@ -76,15 +76,14 @@ async def get_endpoints(region: str) -> Dict[str, Any]:
return endpoints return endpoints
async def get_projects(global_request_id: str, region: str, user: str) -> Dict[str, Any]: async def get_projects(global_request_id: str, region: str, user: str) -> List[Any]:
kc = await utils.keystone_client( kc = await utils.keystone_client(
session=get_system_session(), session=get_system_session(),
region=region, region=region,
global_request_id=global_request_id, global_request_id=global_request_id,
) )
projects = {
i.id: {"name": i.name, "domain_id": i.domain_id} for i in kc.projects.list(user=user) projects = kc.projects.list(user=user)
}
return projects return projects