forked from enviPath/enviPy
First Issues / Improvements detected in Beta (#36)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#36
This commit is contained in:
@ -21,6 +21,7 @@ class UserManager(object):
|
||||
return bool(re.findall(UserManager.user_pattern, url))
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
def create_user(username, email, password, set_setting=True, add_to_group=True, *args, **kwargs):
|
||||
# avoid circular import :S
|
||||
from .tasks import send_registration_mail
|
||||
@ -59,19 +60,24 @@ class UserManager(object):
|
||||
def get_user(user_url):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_user_by_id(user, user_uuid: str):
|
||||
if user.uuid != user_uuid and not user.is_superuser:
|
||||
raise ValueError("Getting user failed!")
|
||||
return get_user_model().objects.get(uuid=user_uuid)
|
||||
|
||||
@staticmethod
|
||||
def get_user_lp(user_url: str):
|
||||
uuid = user_url.strip().split('/')[-1]
|
||||
return get_user_model().objects.get(uuid=uuid)
|
||||
|
||||
@staticmethod
|
||||
def get_users_lp():
|
||||
return get_user_model().objects.all()
|
||||
|
||||
@staticmethod
|
||||
def get_users():
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def get_user_lp(user_url: str):
|
||||
uuid = user_url.strip().split('/')[-1]
|
||||
return get_user_model().objects.get(uuid=uuid)
|
||||
raise ValueError("")
|
||||
|
||||
@staticmethod
|
||||
def writable(current_user, user):
|
||||
@ -102,6 +108,10 @@ class GroupManager(object):
|
||||
uuid = group_url.strip().split('/')[-1]
|
||||
return Group.objects.get(uuid=uuid)
|
||||
|
||||
@staticmethod
|
||||
def get_groups_lp():
|
||||
return Group.objects.all()
|
||||
|
||||
@staticmethod
|
||||
def get_group_by_url(user, group_url):
|
||||
return GroupManager.get_group_by_id(user, group_url.split('/')[-1])
|
||||
@ -173,6 +183,30 @@ class PackageManager(object):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def has_package_permission(user: 'User', package: Union[str, 'Package'], permission: str):
|
||||
|
||||
if isinstance(package, str):
|
||||
package = Package.objects.get(uuid=package)
|
||||
|
||||
groups = GroupManager.get_groups(user)
|
||||
|
||||
perms = {
|
||||
'all': ['all'],
|
||||
'write': ['all', 'write'],
|
||||
'read': ['all', 'write', 'read']
|
||||
}
|
||||
|
||||
valid_perms = perms.get(permission)
|
||||
|
||||
if UserPackagePermission.objects.filter(package=package, user=user, permission__in=valid_perms).exists() or \
|
||||
GroupPackagePermission.objects.filter(package=package, group__in=groups,
|
||||
permission__in=valid_perms).exists() or \
|
||||
user.is_superuser:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_package_lp(package_url):
|
||||
match = re.findall(PackageManager.package_pattern, package_url)
|
||||
@ -701,8 +735,9 @@ class SettingManager(object):
|
||||
|
||||
@staticmethod
|
||||
def get_all_settings(user):
|
||||
sp = UserSettingPermission.objects.filter(user=user).values('setting').distinct()
|
||||
return Setting.objects.filter(id__in=sp)
|
||||
sp = UserSettingPermission.objects.filter(user=user).values('setting')
|
||||
return (Setting.objects.filter(id__in=sp) | Setting.objects.filter(public=True) | Setting.objects.filter(
|
||||
global_default=True)).distinct()
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
|
||||
224
epdb/views.py
224
epdb/views.py
@ -1,6 +1,5 @@
|
||||
import json
|
||||
import logging
|
||||
from functools import wraps
|
||||
from typing import List, Dict, Any
|
||||
|
||||
from django.conf import settings as s
|
||||
@ -10,6 +9,7 @@ from django.shortcuts import render, redirect
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from utilities.chem import FormatConverter, IndigoUtils
|
||||
from utilities.decorators import package_permission_required
|
||||
from .logic import GroupManager, PackageManager, UserManager, SettingManager, SearchManager
|
||||
from .models import Package, GroupPackagePermission, Group, CompoundStructure, Compound, Reaction, Rule, Pathway, Node, \
|
||||
EPModel, EnviFormer, MLRelativeReasoning, RuleBaseRelativeReasoning, Scenario, SimpleAmbitRule, APIToken, \
|
||||
@ -24,6 +24,20 @@ def log_post_params(request):
|
||||
logger.debug(f"{k}\t{v}")
|
||||
|
||||
|
||||
def error(request, message: str, detail: str, code: int = 400):
|
||||
context = get_base_context(request)
|
||||
error_context = {
|
||||
'error_message': message,
|
||||
'error_detail': detail,
|
||||
}
|
||||
|
||||
if request.headers.get('Accept') == 'application/json':
|
||||
return JsonResponse(error_context, status=500)
|
||||
|
||||
context.update(**error_context)
|
||||
return render(request, "errors/error.html", context, status=code)
|
||||
|
||||
|
||||
def login(request):
|
||||
current_user = _anonymous_or_real(request)
|
||||
context = get_base_context(request)
|
||||
@ -55,8 +69,11 @@ def login(request):
|
||||
except get_user_model().DoesNotExist:
|
||||
context['message'] = "Login failed!"
|
||||
return render(request, 'login.html', context)
|
||||
|
||||
try:
|
||||
user = authenticate(username=email, password=password)
|
||||
except Exception as e:
|
||||
context['message'] = "Login failed!"
|
||||
return render(request, 'login.html', context)
|
||||
|
||||
if user is not None:
|
||||
login(request, user)
|
||||
@ -68,15 +85,23 @@ def login(request):
|
||||
elif is_register:
|
||||
username = request.POST.get('username')
|
||||
email = request.POST.get('email')
|
||||
password = request.POST.get('password')
|
||||
rpassword = request.POST.get('rpassword')
|
||||
password = request.POST.get('password', '').strip()
|
||||
rpassword = request.POST.get('rpassword', '').strip()
|
||||
|
||||
if password != rpassword:
|
||||
pass
|
||||
if password != rpassword or password == '':
|
||||
context['message'] = "Registration failed, provided passwords differ!"
|
||||
return render(request, 'login.html', context)
|
||||
|
||||
try:
|
||||
u = UserManager.create_user(username, email, password)
|
||||
except Exception:
|
||||
context['message'] = "Registration failed! Couldn't create User Account."
|
||||
return render(request, 'login.html', context)
|
||||
|
||||
if s.ADMIN_APPROVAL_REQUIRED:
|
||||
context['message'] = "Your account has been created! An admin will activate it soon!"
|
||||
else:
|
||||
context['message'] = "Account has been created! You'll receive a mail to activate your account shortly."
|
||||
return render(request, 'login.html', context)
|
||||
|
||||
|
||||
@ -92,25 +117,11 @@ def logout(request):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
|
||||
def catch_exceptions(view_func):
|
||||
@wraps(view_func)
|
||||
def _wrapped_view(request, *args, **kwargs):
|
||||
try:
|
||||
return view_func(request, *args, **kwargs)
|
||||
except Exception as e:
|
||||
# Optionally return JSON or plain HttpResponse
|
||||
if request.headers.get('Accept') == 'application/json':
|
||||
return JsonResponse(
|
||||
{'error': 'Internal server error. Please try again later.'},
|
||||
status=500
|
||||
)
|
||||
else:
|
||||
return render(request, 'errors/error.html', get_base_context(request))
|
||||
|
||||
return _wrapped_view
|
||||
|
||||
|
||||
def editable(request, user):
|
||||
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
url = request.build_absolute_uri(request.path)
|
||||
if PackageManager.is_package_url(url):
|
||||
_package = PackageManager.get_package_lp(request.build_absolute_uri())
|
||||
@ -129,11 +140,13 @@ def editable(request, user):
|
||||
return False
|
||||
|
||||
|
||||
def get_base_context(request) -> Dict[str, Any]:
|
||||
def get_base_context(request, for_user=None) -> Dict[str, Any]:
|
||||
current_user = _anonymous_or_real(request)
|
||||
|
||||
can_edit = editable(request, current_user)
|
||||
|
||||
if for_user:
|
||||
current_user = for_user
|
||||
|
||||
ctx = {
|
||||
'title': 'enviPath',
|
||||
'meta': {
|
||||
@ -183,8 +196,6 @@ def breadcrumbs(first_level_object=None, second_level_namespace=None, second_lev
|
||||
return bread
|
||||
|
||||
|
||||
# @catch_exceptions
|
||||
|
||||
def index(request):
|
||||
context = get_base_context(request)
|
||||
context['title'] = 'enviPath - Home'
|
||||
@ -269,6 +280,9 @@ def compounds(request):
|
||||
default_package = current_user.default_package
|
||||
return package_compounds(request, default_package.uuid)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def rules(request):
|
||||
if request.method == 'GET':
|
||||
@ -305,6 +319,9 @@ def rules(request):
|
||||
default_package = current_user.default_package
|
||||
return package_rules(request, default_package.uuid)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def reactions(request):
|
||||
if request.method == 'GET':
|
||||
@ -341,6 +358,9 @@ def reactions(request):
|
||||
default_package = current_user.default_package
|
||||
return package_reactions(request, default_package.uuid)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def pathways(request):
|
||||
if request.method == 'GET':
|
||||
@ -378,6 +398,9 @@ def pathways(request):
|
||||
default_package = current_user.default_package
|
||||
return package_pathways(request, default_package.uuid)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def scenarios(request):
|
||||
if request.method == 'GET':
|
||||
@ -408,11 +431,14 @@ def scenarios(request):
|
||||
|
||||
context['reviewed_objects'] = reviewed_scenario_qs
|
||||
return render(request, 'collections/objects_list.html', context)
|
||||
# TODO
|
||||
# elif request.method == 'POST':
|
||||
# # delegate to default package
|
||||
# default_package = request.user.default_package
|
||||
# return package_scenarios(request, default_package.uuid)
|
||||
|
||||
elif request.method == 'POST':
|
||||
# delegate to default package
|
||||
default_package = request.user.default_package
|
||||
return package_scenarios(request, default_package.uuid)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def models(request):
|
||||
@ -459,6 +485,9 @@ def models(request):
|
||||
default_package = current_user.default_package
|
||||
return package_models(request, default_package.uuid)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def search(request):
|
||||
current_user = _anonymous_or_real(request)
|
||||
@ -504,7 +533,11 @@ def search(request):
|
||||
|
||||
return render(request, 'search.html', context)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET'])
|
||||
|
||||
|
||||
@package_permission_required()
|
||||
def package_models(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -587,10 +620,15 @@ def package_models(request, package_uuid):
|
||||
mod = RuleBaseRelativeReasoning()
|
||||
|
||||
mod.save()
|
||||
|
||||
else:
|
||||
return error(request, 'Invalid model type.', f'Model type "{model_type}" is not supported."')
|
||||
return redirect(mod.url)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
@package_permission_required()
|
||||
def package_model(request, package_uuid, model_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -641,9 +679,10 @@ def package_model(request, package_uuid, model_uuid):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
@package_permission_required()
|
||||
def package(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -751,10 +790,10 @@ def package(request, package_uuid):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/compound
|
||||
@package_permission_required()
|
||||
def package_compounds(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -797,8 +836,11 @@ def package_compounds(request, package_uuid):
|
||||
|
||||
return redirect(c.url)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
# https://envipath.org/package/<id>/compound/<id>
|
||||
|
||||
@package_permission_required()
|
||||
def package_compound(request, package_uuid, compound_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -838,11 +880,12 @@ def package_compound(request, package_uuid, compound_uuid):
|
||||
return redirect(current_compound.url)
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<uuid>/compound/<uuid>/structure
|
||||
@package_permission_required()
|
||||
def package_compound_structures(request, package_uuid, compound_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -878,10 +921,10 @@ def package_compound_structures(request, package_uuid, compound_uuid):
|
||||
return redirect(cs.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/compound/<id>/structure/<id>
|
||||
@package_permission_required()
|
||||
def package_compound_structure(request, package_uuid, compound_uuid, structure_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -899,8 +942,11 @@ def package_compound_structure(request, package_uuid, compound_uuid, structure_u
|
||||
|
||||
return render(request, 'objects/compound_structure.html', context)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', ])
|
||||
|
||||
# https://envipath.org/package/<id>/rule
|
||||
|
||||
@package_permission_required()
|
||||
def package_rules(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -965,10 +1011,10 @@ def package_rules(request, package_uuid):
|
||||
return redirect(r.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/rule/<id>
|
||||
@package_permission_required()
|
||||
def package_rule(request, package_uuid, rule_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1012,10 +1058,10 @@ def package_rule(request, package_uuid, rule_uuid):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/reaction
|
||||
@package_permission_required()
|
||||
def package_reactions(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1063,10 +1109,10 @@ def package_reactions(request, package_uuid):
|
||||
return redirect(r.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/reaction/<id>
|
||||
@package_permission_required()
|
||||
def package_reaction(request, package_uuid, reaction_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1108,10 +1154,10 @@ def package_reaction(request, package_uuid, reaction_uuid):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/pathway
|
||||
@package_permission_required()
|
||||
def package_pathways(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1154,13 +1200,22 @@ def package_pathways(request, package_uuid):
|
||||
pw_mode = request.POST.get('predict', 'predict')
|
||||
smiles = request.POST.get('smiles')
|
||||
|
||||
if smiles is None or smiles == '':
|
||||
return HttpResponseBadRequest()
|
||||
if smiles is None or smiles.strip() == '':
|
||||
return error(request, "Pathway prediction failed!",
|
||||
"Pathway prediction failed due to missing or empty SMILES")
|
||||
|
||||
smiles = smiles.strip()
|
||||
|
||||
try:
|
||||
stand_smiles = FormatConverter.standardize(smiles)
|
||||
except ValueError:
|
||||
return error(request, "Pathway prediction failed!",
|
||||
f'Pathway prediction failed as standardization of SMILES "{smiles}" failed!')
|
||||
|
||||
if pw_mode not in ['predict', 'build', 'incremental']:
|
||||
return HttpResponseBadRequest()
|
||||
modes = ['predict', 'build', 'incremental']
|
||||
if pw_mode not in modes:
|
||||
return error(request, "Pathway prediction failed!",
|
||||
f'Pathway prediction failed as received mode "{pw_mode}" is none of {modes}')
|
||||
|
||||
pw = Pathway.create(current_package, stand_smiles, name=name, description=description)
|
||||
# set mode
|
||||
@ -1185,10 +1240,10 @@ def package_pathways(request, package_uuid):
|
||||
return redirect(pw.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/pathway/<id>
|
||||
@package_permission_required()
|
||||
def package_pathway(request, package_uuid, pathway_uuid):
|
||||
current_user: User = _anonymous_or_real(request)
|
||||
current_package: Package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1257,10 +1312,10 @@ def package_pathway(request, package_uuid, pathway_uuid):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/pathway/<id>/node
|
||||
@package_permission_required()
|
||||
def package_pathway_nodes(request, package_uuid, pathway_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1313,10 +1368,10 @@ def package_pathway_nodes(request, package_uuid, pathway_uuid):
|
||||
return redirect(current_pathway.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/pathway/<id>/node/<id>
|
||||
@package_permission_required()
|
||||
def package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1361,10 +1416,10 @@ def package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
|
||||
return redirect(current_pathway.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/pathway/<id>/edge
|
||||
@package_permission_required()
|
||||
def package_pathway_edges(request, package_uuid, pathway_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1422,10 +1477,10 @@ def package_pathway_edges(request, package_uuid, pathway_uuid):
|
||||
return redirect(current_pathway.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/pathway/<id>/edge/<id>
|
||||
@package_permission_required()
|
||||
def package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1440,7 +1495,8 @@ def package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||
return HttpResponse(svg_data, content_type="image/svg+xml")
|
||||
|
||||
context = get_base_context(request)
|
||||
context['title'] = f'enviPath - {current_package.name} - {current_pathway.name} - {current_edge.edge_label.name}'
|
||||
context[
|
||||
'title'] = f'enviPath - {current_package.name} - {current_pathway.name} - {current_edge.edge_label.name}'
|
||||
|
||||
context['meta']['current_package'] = current_package
|
||||
context['object_type'] = 'reaction'
|
||||
@ -1460,10 +1516,10 @@ def package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||
return redirect(current_pathway.url)
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
# https://envipath.org/package/<id>/scenario
|
||||
@package_permission_required()
|
||||
def package_scenarios(request, package_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1497,8 +1553,11 @@ def package_scenarios(request, package_uuid):
|
||||
|
||||
return render(request, 'collections/objects_list.html', context)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', ])
|
||||
|
||||
# https://envipath.org/package/<id>/scenario/<id>
|
||||
|
||||
@package_permission_required()
|
||||
def package_scenario(request, package_uuid, scenario_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||
@ -1516,6 +1575,9 @@ def package_scenario(request, package_uuid, scenario_uuid):
|
||||
|
||||
return render(request, 'objects/scenario.html', context)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', ])
|
||||
|
||||
|
||||
##############
|
||||
# User/Group #
|
||||
@ -1536,6 +1598,9 @@ def users(request):
|
||||
|
||||
return render(request, 'collections/objects_list.html', context)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET'])
|
||||
|
||||
|
||||
def user(request, user_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
@ -1546,6 +1611,8 @@ def user(request, user_uuid):
|
||||
if str(current_user.uuid) != user_uuid and not current_user.is_superuser:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
user = UserManager.get_user_by_id(current_user, user_uuid)
|
||||
|
||||
context = get_base_context(request)
|
||||
context['title'] = f'enviPath - User'
|
||||
|
||||
@ -1556,7 +1623,7 @@ def user(request, user_uuid):
|
||||
{current_user.username: current_user.url}
|
||||
]
|
||||
|
||||
context['user'] = current_user
|
||||
context['user'] = user
|
||||
|
||||
model_qs = EPModel.objects.none()
|
||||
for p in PackageManager.get_all_readable_packages(current_user, include_reviewed=True):
|
||||
@ -1637,6 +1704,9 @@ def user(request, user_uuid):
|
||||
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def groups(request):
|
||||
current_user = _anonymous_or_real(request)
|
||||
@ -1663,6 +1733,9 @@ def groups(request):
|
||||
|
||||
return redirect(g.url)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def group(request, group_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
@ -1681,9 +1754,8 @@ def group(request, group_uuid):
|
||||
|
||||
context['group'] = current_group
|
||||
|
||||
# TODO use managers
|
||||
context['users'] = get_user_model().objects.exclude(id__in=current_group.user_member.all())
|
||||
context['groups'] = Group.objects.exclude(id__in=current_group.group_member.all()).exclude(id=current_group.pk)
|
||||
context['users'] = UserManager.get_users_lp().exclude(id__in=current_group.user_member.all())
|
||||
context['groups'] = GroupManager.get_groups_lp().exclude(id__in=current_group.group_member.all()).exclude(id=current_group.pk)
|
||||
|
||||
context['packages'] = Package.objects.filter(
|
||||
id__in=GroupPackagePermission.objects.filter(group=current_group).values('package').distinct())
|
||||
@ -1716,6 +1788,9 @@ def group(request, group_uuid):
|
||||
|
||||
return redirect(current_group.url)
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def settings(request):
|
||||
current_user = _anonymous_or_real(request)
|
||||
@ -1775,6 +1850,9 @@ def settings(request):
|
||||
|
||||
return HttpResponse("Success!")
|
||||
|
||||
else:
|
||||
return HttpResponseNotAllowed(['GET', 'POST'])
|
||||
|
||||
|
||||
def setting(request, setting_uuid):
|
||||
pass
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h4 class="alert-heading">Something went wrong!</h4>
|
||||
<p>An unexpected Error occurred...</p>
|
||||
<h4 class="alert-heading">{{ error_message }}</h4>
|
||||
<hr>
|
||||
<p class="mb-0">
|
||||
{{ error_detail }}<br>
|
||||
The error was logged and will be investigated.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
{% load static %}
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@ -29,17 +28,6 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* Optional: dim layer */
|
||||
.bg-dim {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.center-button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@ -47,6 +35,15 @@
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.center-message {
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -55,17 +52,28 @@
|
||||
<div class="bg-blur"></div>
|
||||
<div class="bg-dim"></div>
|
||||
|
||||
{% if message %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Trigger Button -->
|
||||
<div class="center-button">
|
||||
<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#signupmodal">Login / Sign Up</button>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="center-message">
|
||||
{% if message %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-success" role="alert">
|
||||
Kia ora! We are running our closed beta tests at the moment. It would be great to get your help as tester,
|
||||
you
|
||||
can apply to become tester by registering for this page, just hit the button below. More information on the
|
||||
beta
|
||||
test is available in our <a href="https://community.envipath.org/t/apply-to-join-our-closed-beta/95">
|
||||
community
|
||||
form</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- Bootstrap Modal -->
|
||||
<div class="modal fade bs-modal-sm" id="signupmodal" tabindex="-1" role="dialog"
|
||||
aria-labelledby="mySmallModalLabel"
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% if request.user.is_authenticated %}
|
||||
<p>You are already logged in as {{ request.user.email }}.</p>
|
||||
{% endif %}
|
||||
<form action="{{ request.path }}" method="POST">
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
{{ form }}
|
||||
<input type="submit" value="Send log in link">
|
||||
</p>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
@ -1,5 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<p>We sent a log in link. Check your email.</p>
|
||||
{% endblock content %}
|
||||
@ -1,7 +1,7 @@
|
||||
{% extends "framework.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
{% load static %}
|
||||
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<style>
|
||||
svg {
|
||||
@ -141,7 +141,7 @@
|
||||
<div id="tooltip" class="tooltip"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="panel panel-default panel-heading list-group-item" style="background-color:silver">
|
||||
<h4 class="panel-title">
|
||||
<a id="DescriptionLink" data-toggle="collapse" data-parent="#pathwayAccordion"
|
||||
@ -152,6 +152,96 @@
|
||||
{{ pathway.description | safe }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if pathway.setting %}
|
||||
<div class="panel panel-default panel-heading list-group-item" style="background-color:silver">
|
||||
<h4 class="panel-title">
|
||||
<a id="pathwaySettingLink" data-toggle="collapse" data-parent="#pathwayAccordion"
|
||||
href="#pathwaySetting">Setting</a></h4>
|
||||
</div>
|
||||
<div id="pathwaySetting" class="panel-collapse collapse in">
|
||||
<div class="panel-body list-group-item" id="pathwaySettingContent">
|
||||
<table class="table table-bordered table-hover">
|
||||
<tr style="background-color: rgba(0, 0, 0, 0.08);">
|
||||
<th scope="col" width="20%">Parameter</th>
|
||||
<th scope="col" width="80%">Value</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
{% if pathway.setting.model %}
|
||||
<tr>
|
||||
<td width="20%">Model</td>
|
||||
<td width="80%">
|
||||
<table width="100%" class="table table-bordered table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<li class="list-group-item">
|
||||
<a href="{{ pathway.setting.model.url }}">
|
||||
{{ pathway.setting.model.name }}
|
||||
</a>
|
||||
</li>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="20%">Model Parameter</th>
|
||||
<th width="80%">Parameter Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%">
|
||||
Threshold
|
||||
</td>
|
||||
<td width="80%">
|
||||
{{ pathway.setting.model_threshold }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if pathway.setting.rule_packages.all %}
|
||||
<tr>
|
||||
<td width="20%">Rule Packages</td>
|
||||
<td width="80%">
|
||||
<table width="100%" class="table table-bordered table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% for p in pathway.setting.rule_packages.all %}
|
||||
<li class="list-group-item">
|
||||
<a href="{{ p.url }}">
|
||||
{{ p.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>Max Nodes</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{{ pathway.setting.max_nodes }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Max Depth</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{{ pathway.setting.max_depth }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
40
utilities/decorators.py
Normal file
40
utilities/decorators.py
Normal file
@ -0,0 +1,40 @@
|
||||
# decorators.py
|
||||
from functools import wraps
|
||||
|
||||
from django.shortcuts import render
|
||||
|
||||
from epdb.logic import PackageManager
|
||||
|
||||
# Map HTTP methods to required permissions
|
||||
DEFAULT_METHOD_PERMISSIONS = {
|
||||
'GET': 'read',
|
||||
'POST': 'write',
|
||||
'DELETE': 'write',
|
||||
}
|
||||
|
||||
|
||||
def package_permission_required(method_permissions=None):
|
||||
if method_permissions is None:
|
||||
method_permissions = DEFAULT_METHOD_PERMISSIONS
|
||||
|
||||
def decorator(view_func):
|
||||
@wraps(view_func)
|
||||
def _wrapped_view(request, package_uuid, *args, **kwargs):
|
||||
from epdb.views import _anonymous_or_real
|
||||
user = _anonymous_or_real(request)
|
||||
permission_required = method_permissions[request.method]
|
||||
|
||||
if not PackageManager.has_package_permission(user, package_uuid, permission_required):
|
||||
from epdb.views import error
|
||||
return error(
|
||||
request,
|
||||
"Operation failed!",
|
||||
f"Couldn't perform the desired operation as {user.username} does not have the required permissions!",
|
||||
code=403
|
||||
)
|
||||
|
||||
return view_func(request, package_uuid, *args, **kwargs)
|
||||
|
||||
return _wrapped_view
|
||||
|
||||
return decorator
|
||||
Reference in New Issue
Block a user