forked from enviPath/enviPy
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dc0e5e7a3 | ||
|
|
ff37a17edb | ||
|
|
c60eac879e | ||
|
|
b269b7dfd8 | ||
|
|
b12c2dda69 | ||
|
|
0b325a30b7 |
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 6.0.3 on 2026-09-08 08:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('bayer', '0003_pescompound_pesstructure_package_data_pool'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='package',
|
||||
name='shareable',
|
||||
field=models.BooleanField(default=True, verbose_name='Shareable'),
|
||||
),
|
||||
]
|
||||
@@ -23,6 +23,7 @@ class Package(EnviPathModel):
|
||||
license = models.ForeignKey(
|
||||
"epdb.License", on_delete=models.SET_NULL, blank=True, null=True, verbose_name="License"
|
||||
)
|
||||
shareable = models.BooleanField(verbose_name="Shareable", default=True)
|
||||
|
||||
class Classification(models.IntegerChoices):
|
||||
INTERNAL = 0, "Internal"
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
img.onerror = () => {
|
||||
this.pesVizHtml = `
|
||||
<div class='alert alert-error' role='alert'>
|
||||
<h4 class='alert-heading'>Could not render PES!</h4>
|
||||
<p>Could not render PES - Do you have access?</p>
|
||||
<h4 class='alert-heading'>Failed to fetch this PES!</h4>
|
||||
<p>Either the PES-ID is incorrect, or you're missing sufficient permissions to access this (potentially secret) item. In case you're missing permissions you can request the entitlement cs.u.enviPath_secret_data_user_group on go/idnow to gain access.</p>
|
||||
</div>`;
|
||||
};
|
||||
},
|
||||
|
||||
+2
-2
@@ -119,8 +119,8 @@ def create_pes_node(request, package_uuid, pathway_uuid):
|
||||
except ValueError as e:
|
||||
return error(
|
||||
request,
|
||||
"Could not fetch PES",
|
||||
f"Could not fetch PES data for {pes_link}"
|
||||
"Failed to fetch this PES",
|
||||
"Either the PES-ID is incorrect, or you're missing sufficient permissions to access this (potentially secret) item. In case you're missing permissions you can request the entitlement cs.u.enviPath_secret_data_user_group on go/idnow to gain access."
|
||||
)
|
||||
|
||||
classification = pes_data.get("classificationLevel", "")
|
||||
|
||||
+9
-3
@@ -77,7 +77,7 @@ def entra_callback(request):
|
||||
return error(
|
||||
request,
|
||||
"Login Failed",
|
||||
"The user is not authenticated. A reason for this might be a missing assignment to the respective enviPath group.",
|
||||
"Request access to role 1230/MON/APPS/Envipath/Envipath_Prod on go/idnow",
|
||||
403,
|
||||
)
|
||||
|
||||
@@ -102,7 +102,7 @@ def entra_callback(request):
|
||||
|
||||
else:
|
||||
auth_log.info(f"Registering {user_name} with OID {user_oid}")
|
||||
u = UserManager.create_user(user_name, user_email, None, uuid=user_oid, is_active=True)
|
||||
u = UserManager.create_user(user_name, user_email, None, uuid=user_oid, is_active=True, add_to_group=False)
|
||||
registered = True
|
||||
|
||||
auth_log.info(f"User {user_name} {'(admin) ' if u.is_superuser else ''}with OID {user_oid} successfully logged in as {u.username} from {get_remote_address(request)}")
|
||||
@@ -139,10 +139,16 @@ def entra_callback(request):
|
||||
auth_log.info(f"Login Group Sync: Adding {u.username} to Group {g.name} ({ uuid })")
|
||||
else:
|
||||
g = Group.objects.get(uuid=uuid)
|
||||
if g.user_member.contains(u):
|
||||
# Do not remove users from All enviPath Users
|
||||
if g.user_member.contains(u) and g.name != 'All enviPath Users':
|
||||
g.user_member.remove(u)
|
||||
auth_log.info(f"Login Group Sync: Removing {u.username} from Group {g.name} ({ uuid })")
|
||||
|
||||
# Ensure people are part of All enviPath Users -> they have to as, envipath_registered_user is granted
|
||||
all_envipath_users = Group.objects.get(name="All enviPath Users")
|
||||
if not all_envipath_users.user_member.contains(u):
|
||||
all_envipath_users.user_member.add(u)
|
||||
|
||||
if registered:
|
||||
# #72 make package secret if user is part of a secret group
|
||||
for id, name in s.ENTRA_SECRET_GROUPS.items():
|
||||
|
||||
+8
-2
@@ -211,7 +211,7 @@ class UserManager(object):
|
||||
# Create package
|
||||
package_name = f"{u.username}{'’' if u.username[-1] in 'sxzß' else 's'} Package"
|
||||
package_description = "This package was generated during registration."
|
||||
p = PackageManager.create_package(u, package_name, package_description)
|
||||
p = PackageManager.create_package(u, package_name, package_description, shareable=False)
|
||||
u.default_package = p
|
||||
u.save()
|
||||
|
||||
@@ -547,7 +547,7 @@ class PackageManager(object):
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
def create_package(current_user, name: str, description: str = None):
|
||||
def create_package(current_user, name: str, description: str = None, *args, **kwargs):
|
||||
p = Package()
|
||||
|
||||
# Clean for potential XSS
|
||||
@@ -556,6 +556,9 @@ class PackageManager(object):
|
||||
if description is not None and description.strip() != "":
|
||||
p.description = nh3.clean(description.strip(), tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
if "shareable" in kwargs:
|
||||
p.shareable = kwargs["shareable"]
|
||||
|
||||
p.save()
|
||||
|
||||
up = UserPackagePermission()
|
||||
@@ -578,6 +581,9 @@ class PackageManager(object):
|
||||
if caller_perm != Permission.ALL[0] and not caller.is_superuser:
|
||||
raise ValueError("Only owner are allowed to modify permissions")
|
||||
|
||||
if isinstance(grantee, Group) and package.classification_level == package.Classification.SECRET:
|
||||
raise ValueError("Cannot grant permissions to a Group on a secret package")
|
||||
|
||||
data = {
|
||||
"package": package,
|
||||
}
|
||||
|
||||
@@ -2456,6 +2456,20 @@ class Node(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin)
|
||||
else:
|
||||
return self.default_node_label.name
|
||||
|
||||
def get_description(self, include_suffix=True):
|
||||
default_desc = False
|
||||
|
||||
if self.description == "no description":
|
||||
default_desc = True
|
||||
|
||||
if not default_desc:
|
||||
return self.description
|
||||
else:
|
||||
if include_suffix:
|
||||
return f"{self.default_node_label.description} (taken from underlying structure)"
|
||||
else:
|
||||
return self.default_node_label.description
|
||||
|
||||
def d3_json(self):
|
||||
app_domain_data = self.get_app_domain_assessment_data()
|
||||
|
||||
@@ -2773,6 +2787,20 @@ class Edge(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin)
|
||||
else:
|
||||
return self.edge_label.name
|
||||
|
||||
def get_description(self, include_suffix=True):
|
||||
default_desc = False
|
||||
|
||||
if self.description == "no description":
|
||||
default_desc = True
|
||||
|
||||
if not default_desc:
|
||||
return self.description
|
||||
else:
|
||||
if include_suffix:
|
||||
return f"{self.edge_label.description} (taken from underlying reaction)"
|
||||
else:
|
||||
return self.edge_label.description
|
||||
|
||||
|
||||
class EPModel(PolymorphicModel, EnviPathModel, AdditionalInformationMixin):
|
||||
package = models.ForeignKey(
|
||||
|
||||
+16
-1
@@ -1292,9 +1292,13 @@ def package(request, package_uuid):
|
||||
"user_id", flat=True
|
||||
)
|
||||
)
|
||||
users = users.filter(is_active=True)
|
||||
users = users.filter(is_active=True).exclude(username="anonymous")
|
||||
|
||||
group_perms = GroupPackagePermission.objects.filter(package=current_package)
|
||||
|
||||
if current_package.classification_level == current_package.Classification.SECRET:
|
||||
groups = Group.objects.none()
|
||||
else:
|
||||
groups = Group.objects.exclude(
|
||||
id__in=GroupPackagePermission.objects.filter(package=current_package).values_list(
|
||||
"group_id", flat=True
|
||||
@@ -1324,6 +1328,12 @@ def package(request, package_uuid):
|
||||
|
||||
return redirect(s.SERVER_URL + "/package")
|
||||
elif hidden == "publish-package":
|
||||
if current_package.classification_level == current_package.Classification.SECRET:
|
||||
return error(
|
||||
request,
|
||||
"Cannot publish a secret package",
|
||||
"You cannot publish a secret package.",
|
||||
)
|
||||
for g in Group.objects.filter(public=True):
|
||||
PackageManager.grant_read(current_user, current_package, g)
|
||||
return redirect(current_package.url)
|
||||
@@ -3314,6 +3324,11 @@ def jobs(request):
|
||||
"This Package was generated automatically for the batch prediction task.",
|
||||
)
|
||||
|
||||
if current_user.default_package.classification_level == current_user.default_package.Classification.SECRET:
|
||||
target_package.classification_level = current_user.default_package.Classification.SECRET
|
||||
target_package.data_pool = current_user.default_package.data_pool
|
||||
target_package.save()
|
||||
|
||||
from .tasks import batch_predict, dispatch
|
||||
|
||||
res = dispatch(
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Package</a
|
||||
>
|
||||
</li>
|
||||
{% if meta.current_package.shareable %}
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
@@ -15,6 +16,7 @@
|
||||
<i class="glyphicon glyphicon-user"></i> Edit Permissions</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if meta.current_package.get_classification_level_display != "Secret" %}
|
||||
<li>
|
||||
<a
|
||||
@@ -52,7 +54,7 @@
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if not meta.can_edit %}
|
||||
{% if not meta.can_edit and meta.current_package.shareable %}
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<i class="glyphicon glyphicon-edit"></i> Update</a
|
||||
>
|
||||
</li>
|
||||
{% if 1 == 0 %}
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
@@ -15,6 +16,7 @@
|
||||
<i class="glyphicon glyphicon-lock"></i> Update Password</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
|
||||
@@ -180,12 +180,25 @@
|
||||
>Aspartame</a
|
||||
>
|
||||
</div>
|
||||
<a
|
||||
class="absolute top-0 left-[calc(100%-5.4rem)]"
|
||||
href="/predict"
|
||||
>Advanced</a
|
||||
>
|
||||
</div>
|
||||
{% if meta.current_package %}
|
||||
<div
|
||||
class="mt-4 rounded-lg border border-base-300 bg-base-50 px-4 py-2.5 text-sm text-base-content/70"
|
||||
>
|
||||
Prediction will be stored in Package
|
||||
<strong class="text-base-content"
|
||||
><a class="link" href="{{ meta.current_package.url }}">{{ meta.current_package.name|safe }}</a></strong
|
||||
>
|
||||
{% if meta.user.default_setting %}
|
||||
using setting
|
||||
<strong class="text-base-content"
|
||||
><a class="link" href="{{ meta.user.default_setting.url}}">{{ meta.user.default_setting.name|safe }}</a></strong
|
||||
>
|
||||
{% endif %}
|
||||
To use a different setting click
|
||||
<a class="link" href="/predict">here</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div
|
||||
id="ketcher-container"
|
||||
@@ -208,9 +221,24 @@
|
||||
>
|
||||
Predict!
|
||||
</button>
|
||||
<div class="mt-1 flex w-full justify-end">
|
||||
<a class="label justify-end" href="/predict">Advanced</a>
|
||||
{% if meta.current_package %}
|
||||
<div
|
||||
class="mt-4 rounded-lg border border-base-300 bg-base-50 px-4 py-2.5 text-sm text-base-content/70"
|
||||
>
|
||||
Prediction will be stored in Package
|
||||
<strong class="text-base-content"
|
||||
><a class="link" href="{{ meta.current_package.url }}">{{ meta.current_package.name|safe }}</a></strong
|
||||
>
|
||||
{% if meta.user.default_setting %}
|
||||
using setting
|
||||
<strong class="text-base-content"
|
||||
><a class="link" href="{{ meta.user.default_setting.url}}">{{ meta.user.default_setting.name|safe }}</a></strong
|
||||
>
|
||||
{% endif %}
|
||||
To use a different setting click
|
||||
<a class="link" href="/predict">here</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<input
|
||||
type="hidden"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
{% if 1 == 0 %}
|
||||
<label class="label" for="default-package">
|
||||
<span class="label-text">Default Package</span>
|
||||
</label>
|
||||
@@ -50,7 +51,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="default-group">
|
||||
<span class="label-text">Default Group</span>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">{{ edge.description }}</div>
|
||||
<div class="collapse-content">{{ edge.get_description }}</div>
|
||||
</div>
|
||||
|
||||
{% if edge.aliases %}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">{{ node.description }}</div>
|
||||
<div class="collapse-content">{{ node.get_description }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% epdb_slot_templates "epdb.objects.node.viz" as viz_templates %}
|
||||
|
||||
@@ -2,11 +2,23 @@
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="mx-auto w-full p-8">
|
||||
<h1 class="h1 mb-4 text-3xl font-bold">
|
||||
<h1 class="h1 mb-4 flex items-center gap-2 text-3xl font-bold">
|
||||
Predict a Pathway
|
||||
|
||||
<span class="text-base-content/50 text-xs"
|
||||
>in <strong>{{ meta.current_package.name|safe }}</strong>
|
||||
<span class="inline-flex items-center gap-1 text-base-content/50 text-xs"
|
||||
>in <strong>{{ meta.current_package.name|safe }}</strong>{% if meta.url_contains_package %}
|
||||
{% if meta.current_package.get_classification_level_display == "Restricted" %}
|
||||
<img src="{% static 'images/restricted_mid.png' %}" width="100">
|
||||
{% elif meta.current_package.get_classification_level_display == "Secret" %}
|
||||
<img src="{% static 'images/secret_mid.png' %}" width="60">
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if meta.user.default_package.get_classification_level_display == "Restricted" %}
|
||||
<img src="{% static 'images/restricted_mid.png' %}" width="100">
|
||||
{% elif meta.user.default_package.get_classification_level_display == "Secret" %}
|
||||
<img src="{% static 'images/secret_mid.png' %}" width="60">
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -894,7 +894,7 @@ provides-extras = ["ms-login", "dev", "pepper-plugin"]
|
||||
[[package]]
|
||||
name = "envipy-additional-information"
|
||||
version = "0.4.2"
|
||||
source = { git = "ssh://git@git.envipath.com/enviPath/enviPy-additional-information.git?branch=develop#ad825570480bbe2f1a35c04923fede756c450751" }
|
||||
source = { git = "ssh://git@git.envipath.com/enviPath/enviPy-additional-information.git?branch=develop#4909e35aac5a0a3969ac2a01f8d4ad8bdadae04c" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user