forked from enviPath/enviPy
Compare commits
1 Commits
0033513d99
...
develop-ba
| Author | SHA1 | Date | |
|---|---|---|---|
| 67aa3731cb |
@ -85,6 +85,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
libxext6 \
|
libxext6 \
|
||||||
libfontconfig1 \
|
libfontconfig1 \
|
||||||
nano \
|
nano \
|
||||||
|
openjdk-21-jre-headless \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN useradd -ms /bin/bash django
|
RUN useradd -ms /bin/bash django
|
||||||
|
|||||||
120
bayer/views.py
120
bayer/views.py
@ -8,7 +8,7 @@ from django.shortcuts import redirect
|
|||||||
|
|
||||||
from bayer.models import PESCompound
|
from bayer.models import PESCompound
|
||||||
from epdb.logic import PackageManager
|
from epdb.logic import PackageManager
|
||||||
from epdb.models import Pathway, Node
|
from epdb.models import Pathway, Node, Group
|
||||||
from epdb.views import _anonymous_or_real, error
|
from epdb.views import _anonymous_or_real, error
|
||||||
from utilities.decorators import package_permission_required
|
from utilities.decorators import package_permission_required
|
||||||
|
|
||||||
@ -18,6 +18,23 @@ Package = s.GET_PACKAGE_MODEL()
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def has_secret_group(user):
|
||||||
|
"""
|
||||||
|
Determines if the specified user belongs to any secret group.
|
||||||
|
|
||||||
|
This function checks whether the given user is a member of any group
|
||||||
|
that is marked as secret.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user: The user for whom the check is performed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the user belongs to at least one secret group,
|
||||||
|
False otherwise.
|
||||||
|
"""
|
||||||
|
return Group.objects.filter(secret=True, user_member=user).exists()
|
||||||
|
|
||||||
|
|
||||||
@package_permission_required()
|
@package_permission_required()
|
||||||
def create_pes(request, package_uuid):
|
def create_pes(request, package_uuid):
|
||||||
current_user = _anonymous_or_real(request)
|
current_user = _anonymous_or_real(request)
|
||||||
@ -38,7 +55,7 @@ def create_pes(request, package_uuid):
|
|||||||
|
|
||||||
if pes_link:
|
if pes_link:
|
||||||
try:
|
try:
|
||||||
pes_data = fetch_pes(request, pes_link)
|
pes_data = fetch_pes(request, pes_link, current_user)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return error(
|
return error(
|
||||||
request,
|
request,
|
||||||
@ -98,7 +115,7 @@ def create_pes_node(request, package_uuid, pathway_uuid):
|
|||||||
|
|
||||||
if pes_link:
|
if pes_link:
|
||||||
try:
|
try:
|
||||||
pes_data = fetch_pes(request, pes_link)
|
pes_data = fetch_pes(request, pes_link, current_user)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return error(
|
return error(
|
||||||
request,
|
request,
|
||||||
@ -157,53 +174,82 @@ def create_pes_node(request, package_uuid, pathway_uuid):
|
|||||||
return HttpResponseNotAllowed(["POST"])
|
return HttpResponseNotAllowed(["POST"])
|
||||||
|
|
||||||
|
|
||||||
def fetch_pes(request, pes_url) -> dict:
|
def get_application_token(prod: bool) -> str:
|
||||||
from epauth.views import get_access_token_from_request
|
scope = f"{s.PROD_PES_SCOPE if prod else s.NON_PROD_PES_SCOPE}/.default"
|
||||||
token = get_access_token_from_request(request)
|
|
||||||
|
|
||||||
if token is None:
|
url = f"https://login.microsoftonline.com/{s.MS_TENANT_ID}/oauth2/v2.0/token"
|
||||||
token = pes_url.split('/')[-1] == 'dummy'
|
data = {
|
||||||
|
"grant_type": "client_credentials",
|
||||||
|
"client_id": s.MS_ENTRA_CLIENT_ID,
|
||||||
|
"client_secret": s.MS_ENTRA_CLIENT_SECRET,
|
||||||
|
"scope": scope,
|
||||||
|
}
|
||||||
|
|
||||||
if token:
|
try:
|
||||||
for k, v in s.PES_API_MAPPING.items():
|
response = requests.post(url, data=data)
|
||||||
if pes_url.startswith(k):
|
response.raise_for_status()
|
||||||
pes_id = pes_url.split('/')[-1]
|
return response.json()["access_token"]
|
||||||
|
except requests.exceptions.HTTPError as e:
|
||||||
|
logger.error(f"Could not fetch application token: {e}")
|
||||||
|
raise ValueError(f"Could not fetch application token!")
|
||||||
|
|
||||||
if pes_id == 'dummy':
|
|
||||||
import json
|
def fetch_pes(request, pes_url, user) -> dict:
|
||||||
res_data = json.load(open(s.BASE_DIR / "fixtures/pes.json"))
|
|
||||||
|
for k, v in s.PES_API_MAPPING.items():
|
||||||
|
if pes_url.startswith(k):
|
||||||
|
|
||||||
|
prod = "cropkey-np" not in pes_url
|
||||||
|
|
||||||
|
pes_id = pes_url.split('/')[-1]
|
||||||
|
|
||||||
|
if pes_id == 'dummy':
|
||||||
|
import json
|
||||||
|
res_data = json.load(open(s.BASE_DIR / "fixtures/pes.json"))
|
||||||
|
res_data["pes_url"] = pes_url
|
||||||
|
return res_data
|
||||||
|
else:
|
||||||
|
headers = {
|
||||||
|
"accept": "*/*",
|
||||||
|
"authorization": "Bearer " + get_application_token(prod),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restrict request if user is not part of any secret group
|
||||||
|
if not has_secret_group(user):
|
||||||
|
headers["app-classification-level-restriction"] = "restrict-pes-secret-structure-access"
|
||||||
|
|
||||||
|
|
||||||
|
params = {"pes_reg_entity_corporate_id": pes_id}
|
||||||
|
|
||||||
|
res = requests.get(v, headers=headers, params=params, proxies=s.PROXIES or None)
|
||||||
|
|
||||||
|
try:
|
||||||
|
res.raise_for_status()
|
||||||
|
pes_data = res.json()
|
||||||
|
|
||||||
|
# Handle missing response
|
||||||
|
if "detail" in pes_data and "The following PES Reg Entities Corporate Ids could not be found" in pes_data["detail"]:
|
||||||
|
raise ValueError(f"PES with id {pes_id} not found")
|
||||||
|
|
||||||
|
# Ensure we have a entity
|
||||||
|
if len(pes_data) == 0:
|
||||||
|
raise ValueError(f"PES with id {pes_id} not found")
|
||||||
|
|
||||||
|
res_data = pes_data[0]
|
||||||
res_data["pes_url"] = pes_url
|
res_data["pes_url"] = pes_url
|
||||||
return res_data
|
return res_data
|
||||||
else:
|
|
||||||
headers = {"Authorization": f"Bearer {token['access_token']}"}
|
|
||||||
params = {"pes_reg_entity_corporate_id": pes_id}
|
|
||||||
|
|
||||||
res = requests.get(v, headers=headers, params=params, proxies=s.PROXIES or None)
|
except requests.exceptions.HTTPError as e:
|
||||||
|
raise ValueError(f"Error fetching PES with id {pes_id}: {e}")
|
||||||
|
|
||||||
try:
|
raise ValueError(f"Unknown URL {pes_url}")
|
||||||
res.raise_for_status()
|
|
||||||
pes_data = res.json()
|
|
||||||
|
|
||||||
if len(pes_data) == 0:
|
|
||||||
raise ValueError(f"PES with id {pes_id} not found")
|
|
||||||
|
|
||||||
res_data = pes_data[0]
|
|
||||||
res_data["pes_url"] = pes_url
|
|
||||||
return res_data
|
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
raise ValueError(f"Error fetching PES with id {pes_id}: {e}")
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unknown URL {pes_url}")
|
|
||||||
else:
|
|
||||||
raise ValueError("Could not fetch access token from request.")
|
|
||||||
|
|
||||||
|
|
||||||
def visualize_pes(request):
|
def visualize_pes(request):
|
||||||
pes_link = request.GET.get('pesLink')
|
pes_link = request.GET.get('pesLink')
|
||||||
|
|
||||||
if pes_link:
|
if pes_link:
|
||||||
pes_data = fetch_pes(request, pes_link)
|
pes_data = fetch_pes(request, pes_link, request.user)
|
||||||
|
|
||||||
representations = pes_data.get('representations')
|
representations = pes_data.get('representations')
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from django.shortcuts import redirect
|
|||||||
|
|
||||||
from epdb.logic import UserManager, GroupManager
|
from epdb.logic import UserManager, GroupManager
|
||||||
from epdb.models import Group
|
from epdb.models import Group
|
||||||
from epdb.views import get_remote_address
|
from epdb.views import get_remote_address, error
|
||||||
|
|
||||||
auth_log = logging.getLogger("auth")
|
auth_log = logging.getLogger("auth")
|
||||||
|
|
||||||
@ -72,6 +72,15 @@ def entra_callback(request):
|
|||||||
|
|
||||||
claims = result["id_token_claims"]
|
claims = result["id_token_claims"]
|
||||||
|
|
||||||
|
if claims.get("roles") is None or claims.get("roles") == [] or "envipath_registered_user" not in claims.get("roles"):
|
||||||
|
auth_log.error(f"Login attempt by {get_remote_address(request)} failed due to missing role")
|
||||||
|
return error(
|
||||||
|
request,
|
||||||
|
"Login Failed",
|
||||||
|
"The user is not authenticated. A reason for this might be a missing assignment to the respective enviPath group.",
|
||||||
|
403,
|
||||||
|
)
|
||||||
|
|
||||||
user_name = claims.get("name")
|
user_name = claims.get("name")
|
||||||
# preferred_username is a fallback for 2nd CWID
|
# preferred_username is a fallback for 2nd CWID
|
||||||
user_email = claims.get("emailaddress", claims.get("email", claims.get("preferred_username")))
|
user_email = claims.get("emailaddress", claims.get("email", claims.get("preferred_username")))
|
||||||
|
|||||||
@ -889,7 +889,7 @@ def create_package_compound(
|
|||||||
from bayer.models import PESCompound
|
from bayer.models import PESCompound
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pes_data = fetch_pes(request, c.pesLink)
|
pes_data = fetch_pes(request, c.pesLink, request.user)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return 400, {"message": f"Could not fetch PES data for {c.pesLink}"}
|
return 400, {"message": f"Could not fetch PES data for {c.pesLink}"}
|
||||||
|
|
||||||
@ -2014,7 +2014,7 @@ def add_pathway_node(request, package_uuid, pathway_uuid, n: Form[CreateNode]):
|
|||||||
from bayer.models import PESCompound
|
from bayer.models import PESCompound
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pes_data = fetch_pes(request, n.pesLink)
|
pes_data = fetch_pes(request, n.pesLink, request.user)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return 400, {"message": f"Could not fetch PES data for {n.pesLink}"}
|
return 400, {"message": f"Could not fetch PES data for {n.pesLink}"}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user