Skip to content

Commit

Permalink
Merge remote-tracking branch 'equinor/main' into missing-modules-erro…
Browse files Browse the repository at this point in the history
…r-handling
  • Loading branch information
rubenthoms committed Sep 25, 2023
2 parents a77d6b7 + 73174d1 commit 4ff79bf
Show file tree
Hide file tree
Showing 72 changed files with 859 additions and 678 deletions.
17 changes: 10 additions & 7 deletions backend/src/backend/auth/auth_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ async def _authorized_callback_route(self, request: Request) -> Response:
def get_authenticated_user(
request_with_session: Request,
) -> Optional[AuthenticatedUser]:

timer = PerfTimer()

# We may already have created and stored the AuthenticatedUser object on the request
Expand Down Expand Up @@ -173,6 +172,9 @@ def get_authenticated_user(
# print("-------------------------------------------------")
smda_token = token_dict.get("access_token") if token_dict else None

token_dict = cca.acquire_token_silent(scopes=config.GRAPH_SCOPES, account=accounts[0])
graph_token = token_dict.get("access_token") if token_dict else None

# print(f" get tokens {timer.lap_ms():.1f}ms")

_save_token_cache_in_session(request_with_session, token_cache)
Expand All @@ -187,10 +189,13 @@ def get_authenticated_user(
authenticated_user = AuthenticatedUser(
user_id=user_id,
username=user_name,
sumo_access_token=sumo_token,
smda_access_token=smda_token,
pdm_access_token=None,
ssdl_access_token=None,
access_tokens={
"graph_access_token": graph_token,
"sumo_access_token": sumo_token,
"smda_access_token": smda_token,
"pdm_access_token": None,
"ssdl_access_token": None,
},
)

request_with_session.state.authenticated_user_obj = authenticated_user
Expand All @@ -203,7 +208,6 @@ def get_authenticated_user(
def _create_msal_confidential_client_app(
token_cache: msal.TokenCache,
) -> msal.ConfidentialClientApplication:

authority = f"https://login.microsoftonline.com/{config.TENANT_ID}"
return msal.ConfidentialClientApplication(
client_id=config.CLIENT_ID,
Expand All @@ -217,7 +221,6 @@ def _create_msal_confidential_client_app(
# Note that this function will NOT return the token itself, but rather a dict
# that typically has an "access_token" key
def _get_token_dict_from_session_token_cache(request_with_session: Request, scopes: List[str]) -> Optional[dict]:

token_cache = _load_token_cache_from_session(request_with_session)
cca = _create_msal_confidential_client_app(token_cache)

Expand Down
4 changes: 2 additions & 2 deletions backend/src/backend/primary/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .routers.correlations.router import router as correlations_router
from .routers.grid.router import router as grid_router
from .routers.pvt.router import router as pvt_router
from .routers.well_completion.router import router as well_completion_router
from .routers.well_completions.router import router as well_completions_router
from .routers.well.router import router as well_router
from .routers.surface_polygons.router import router as surface_polygons_router

Expand Down Expand Up @@ -53,7 +53,7 @@ def custom_generate_unique_id(route: APIRoute) -> str:
app.include_router(correlations_router, prefix="/correlations", tags=["correlations"])
app.include_router(grid_router, prefix="/grid", tags=["grid"])
app.include_router(pvt_router, prefix="/pvt", tags=["pvt"])
app.include_router(well_completion_router, prefix="/well_completion", tags=["well_completion"])
app.include_router(well_completions_router, prefix="/well_completions", tags=["well_completions"])
app.include_router(well_router, prefix="/well", tags=["well"])
app.include_router(surface_polygons_router, prefix="/surface_polygons", tags=["surface_polygons"])

Expand Down
33 changes: 31 additions & 2 deletions backend/src/backend/primary/routers/general.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import asyncio
import datetime
import logging

import httpx
import starsessions
from starlette.responses import StreamingResponse
from fastapi import APIRouter, HTTPException, Request, status, Depends
from fastapi import APIRouter, HTTPException, Request, status, Depends, Query
from pydantic import BaseModel

from src.backend.auth.auth_helper import AuthHelper, AuthenticatedUser
from src.backend.primary.user_session_proxy import proxy_to_user_session
from src.services.graph_access.graph_access import GraphApiAccess

LOGGER = logging.getLogger(__name__)


class UserInfo(BaseModel):
username: str
display_name: str | None
avatar_b64str: str | None
has_sumo_access: bool
has_smda_access: bool

Expand All @@ -34,7 +39,12 @@ def alive_protected() -> str:


@router.get("/logged_in_user", response_model=UserInfo)
async def logged_in_user(request: Request) -> UserInfo:
async def logged_in_user(
request: Request,
includeGraphApiInfo: bool = Query(
False, description="Set to true to include user avatar and display name from Microsoft Graph API"
),
) -> UserInfo:
print("entering logged_in_user route")

await starsessions.load_session(request)
Expand All @@ -47,10 +57,29 @@ async def logged_in_user(request: Request) -> UserInfo:

user_info = UserInfo(
username=authenticated_user.get_username(),
avatar_b64str=None,
display_name=None,
has_sumo_access=authenticated_user.has_sumo_access_token(),
has_smda_access=authenticated_user.has_smda_access_token(),
)

if authenticated_user.has_graph_access_token() and includeGraphApiInfo:
graph_api_access = GraphApiAccess(authenticated_user.get_graph_access_token())
try:
avatar_b64str_future = asyncio.create_task(graph_api_access.get_user_profile_photo())
graph_user_info_future = asyncio.create_task(graph_api_access.get_user_info())

avatar_b64str = await avatar_b64str_future
graph_user_info = await graph_user_info_future

user_info.avatar_b64str = avatar_b64str
if graph_user_info is not None:
user_info.display_name = graph_user_info.get("displayName", None)
except httpx.HTTPError as e:
print("Error while fetching user avatar and info from Microsoft Graph API (HTTP error):\n", e)
except httpx.InvalidURL as e:
print("Error while fetching user avatar and info from Microsoft Graph API (Invalid URL):\n", e)

return user_info


Expand Down
30 changes: 0 additions & 30 deletions backend/src/backend/primary/routers/well_completion/router.py

This file was deleted.

This file was deleted.

29 changes: 29 additions & 0 deletions backend/src/backend/primary/routers/well_completions/router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query

from src.backend.auth.auth_helper import AuthHelper
from src.services.utils.authenticated_user import AuthenticatedUser

from src.services.sumo_access.well_completions_access import WellCompletionsAccess
from src.services.sumo_access.well_completions_types import WellCompletionsData

router = APIRouter()


@router.get("/well_completions_data/")
def get_well_completions_data(
# fmt:off
authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
case_uuid: str = Query(description="Sumo case uuid"),
ensemble_name: str = Query(description="Ensemble name"),
realization: Optional[int] = Query(None, description="Optional realization to include. If not specified, all realizations will be returned."),
# fmt:on
) -> WellCompletionsData:
access = WellCompletionsAccess(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
well_completions_data = access.get_well_completions_data(realization=realization)

if not well_completions_data:
raise HTTPException(status_code=404, detail="Well completions data not found")

return well_completions_data
39 changes: 39 additions & 0 deletions backend/src/services/graph_access/graph_access.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import base64
from typing import Mapping

# Using the same http client as sumo
import httpx


class GraphApiAccess:
def __init__(self, access_token: str):
self._access_token = access_token

def _make_headers(self) -> Mapping[str, str]:
return {"Authorization": f"Bearer {self._access_token}"}

async def _request(self, url: str) -> httpx.Response:
async with httpx.AsyncClient() as client:
response = await client.get(
url,
headers=self._make_headers(),
)
return response

async def get_user_profile_photo(self) -> str | None:
print("entering get_user_profile_photo")
response = await self._request("https://graph.microsoft.com/v1.0/me/photo/$value")

if response.status_code == 200:
return base64.b64encode(response.content).decode("utf-8")
else:
return None

async def get_user_info(self) -> Mapping[str, str] | None:
print("entering get_user_info")
response = await self._request("https://graph.microsoft.com/v1.0/me")

if response.status_code == 200:
return response.json()
else:
return None
70 changes: 0 additions & 70 deletions backend/src/services/sumo_access/well_completion_access.py

This file was deleted.

Loading

0 comments on commit 4ff79bf

Please sign in to comment.