forked from enviPath/enviPy
Auth log
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
import msal
|
||||
from django.conf import settings as s
|
||||
from django.contrib.auth import get_user_model
|
||||
@ -8,6 +10,7 @@ from django.shortcuts import redirect
|
||||
from epdb.logic import UserManager, GroupManager
|
||||
from epdb.models import Group
|
||||
|
||||
auth_log = logging.getLogger("auth")
|
||||
|
||||
def get_msal_app_with_cache(request):
|
||||
"""
|
||||
@ -28,8 +31,21 @@ def get_msal_app_with_cache(request):
|
||||
|
||||
return msal_app, cache
|
||||
|
||||
def get_remote_address(request):
|
||||
remote_address = ""
|
||||
|
||||
if request is not None:
|
||||
remote_address = request.META.get("HTTP_X_FORWARDED_FOR")
|
||||
|
||||
if not remote_address:
|
||||
remote_address = request.META.get("REMOTE_ADDR", "")
|
||||
|
||||
return remote_address
|
||||
|
||||
def entra_login(request):
|
||||
|
||||
auth_log.info(f"Login request from {get_remote_address(request)}")
|
||||
|
||||
msal_app = msal.ConfidentialClientApplication(
|
||||
client_id=s.MS_ENTRA_CLIENT_ID,
|
||||
client_credential=s.MS_ENTRA_CLIENT_SECRET,
|
||||
@ -54,6 +70,10 @@ def entra_callback(request):
|
||||
# Acquire token using the flow and callback request
|
||||
result = msal_app.acquire_token_by_auth_code_flow(flow, request.GET)
|
||||
|
||||
if "error" in result:
|
||||
auth_log.error(f"Login attempt by {get_remote_address(request)} failed due to {result['error']}")
|
||||
return redirect("/")
|
||||
|
||||
# Save the token cache to session
|
||||
if cache.has_state_changed:
|
||||
request.session["msal_token_cache"] = cache.serialize()
|
||||
@ -61,7 +81,8 @@ def entra_callback(request):
|
||||
claims = result["id_token_claims"]
|
||||
|
||||
user_name = claims.get("name")
|
||||
user_email = claims.get("emailaddress", claims.get("email"))
|
||||
# preferred_username is a fallback for 2nd CWID
|
||||
user_email = claims.get("emailaddress", claims.get("email", claims.get("preferred_username")))
|
||||
user_oid = claims.get("oid")
|
||||
|
||||
if not all([user_name, user_email, user_oid]):
|
||||
@ -78,8 +99,10 @@ def entra_callback(request):
|
||||
u.save()
|
||||
|
||||
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)
|
||||
|
||||
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)}")
|
||||
login(request, u)
|
||||
|
||||
# EDIT START
|
||||
@ -102,10 +125,20 @@ def entra_callback(request):
|
||||
else:
|
||||
g = Group.objects.get(uuid=id)
|
||||
|
||||
for group_uuid in claims.get("groups", []):
|
||||
if Group.objects.filter(uuid=group_uuid).exists():
|
||||
g = Group.objects.get(uuid=group_uuid)
|
||||
g.user_member.add(u)
|
||||
sync_groups = list(s.ENTRA_GROUPS.keys()) + list(s.ENTRA_SECRET_GROUPS.keys())
|
||||
user_groups = claims.get("groups", [])
|
||||
|
||||
for uuid in sync_groups:
|
||||
if uuid in user_groups:
|
||||
g = Group.objects.get(uuid=uuid)
|
||||
if not g.user_member.contains(u):
|
||||
g.user_member.add(u)
|
||||
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):
|
||||
g.user_member.remove(u)
|
||||
auth_log.info(f"Login Group Sync: Removing {u.username} from Group {g.name} ({ uuid })")
|
||||
|
||||
# EDIT END
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ from utilities.chem import FormatConverter
|
||||
from utilities.misc import PackageExporter, PackageImporter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
auth_log = logging.getLogger("auth")
|
||||
|
||||
Package = s.GET_PACKAGE_MODEL()
|
||||
|
||||
@ -316,13 +317,19 @@ class GroupManager(object):
|
||||
if isinstance(member, Group):
|
||||
if add_or_remove == "add":
|
||||
group.group_member.add(member)
|
||||
auth_log.info(f"{caller.username} ({caller.url}) adds {member.name} ({member.url}) to {group.name} ({group.url})")
|
||||
else:
|
||||
group.group_member.remove(member)
|
||||
auth_log.info(
|
||||
f"{caller.username} ({caller.url}) removes {member.name} ({member.url}) to {group.name} ({group.url})")
|
||||
else:
|
||||
if add_or_remove == "add":
|
||||
group.user_member.add(member)
|
||||
auth_log.info(f"{caller.username} ({caller.url}) adds {member.username} ({member.url}) to {group.name} ({group.url})")
|
||||
else:
|
||||
group.user_member.remove(member)
|
||||
auth_log.info(
|
||||
f"{caller.username} ({caller.url}) adds {member.username} ({member.url}) to {group.name} ({group.url})")
|
||||
|
||||
group.save()
|
||||
|
||||
@ -589,11 +596,25 @@ class PackageManager(object):
|
||||
if qs.count() != 0:
|
||||
logger.info(f"Deleting Perm {qs.first()}")
|
||||
qs.delete()
|
||||
auth_log.info(f"{caller.username} ({caller.url}) revokes {grantee.name} ({grantee.url}) all Permissions on {package.name} ({package.url})")
|
||||
else:
|
||||
logger.debug(f"No Permission object for {perm_cls} with filter {data} found!")
|
||||
else:
|
||||
old_perm = None
|
||||
old_perms_qs = perm_cls.objects.filter(**data)
|
||||
|
||||
if old_perms_qs.exists():
|
||||
old_perm = old_perms_qs.first().permission
|
||||
|
||||
_ = perm_cls.objects.update_or_create(defaults={"permission": new_perm}, **data)
|
||||
|
||||
grantee_name = grantee.username if isinstance(grantee, User) else grantee.name
|
||||
|
||||
if old_perm is None:
|
||||
auth_log.info(f"{caller.username} ({caller.url}) grants {grantee_name} ({grantee.url}) '{new_perm}' Permissions on {package.name} ({package.url})")
|
||||
else:
|
||||
auth_log.info(f"{caller.username} ({caller.url}) set {grantee_name} ({grantee.url}) Permissions from '{old_perm}' to '{new_perm}' on {package.name} ({package.url})")
|
||||
|
||||
@staticmethod
|
||||
def grant_read(caller: User, package: Package, grantee: Union[User, Group]):
|
||||
PackageManager.update_permissions(caller, package, grantee, Permission.READ[0])
|
||||
|
||||
@ -61,6 +61,7 @@ from .models import (
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
auth_log = logging.getLogger("auth")
|
||||
|
||||
Package = s.GET_PACKAGE_MODEL()
|
||||
|
||||
@ -147,6 +148,19 @@ def handler500(request):
|
||||
return render(request, "errors/error.html", context, status=500)
|
||||
|
||||
|
||||
def delete_with_log(request, obj):
|
||||
caller = request.user
|
||||
obj_type = obj.__class__.__name__
|
||||
|
||||
try:
|
||||
obj.delete()
|
||||
except Exception as e:
|
||||
logger.info(f"Tried to delete {obj_type}: {obj.name} ({obj.url}) but deletion failed! Exception {e}")
|
||||
auth_log.error(
|
||||
f"{caller.username} ({caller.url}) tried to delete {obj_type}: {obj.name} ({obj.url}) but deletion failed!")
|
||||
raise e
|
||||
|
||||
|
||||
def login(request):
|
||||
context = get_base_context(request)
|
||||
|
||||
@ -1282,7 +1296,8 @@ def package(request, package_uuid):
|
||||
"You cannot delete the default package. If you want to delete this package you have to set another default package first.",
|
||||
)
|
||||
|
||||
logger.debug(current_package.delete())
|
||||
delete_with_log(request, current_package)
|
||||
|
||||
return redirect(s.SERVER_URL + "/package")
|
||||
elif hidden == "publish-package":
|
||||
for g in Group.objects.filter(public=True):
|
||||
@ -2273,7 +2288,7 @@ def package_pathway(request, package_uuid, pathway_uuid):
|
||||
elif request.method == "POST":
|
||||
if hidden := request.POST.get("hidden", None):
|
||||
if hidden == "delete":
|
||||
current_pathway.delete()
|
||||
delete_with_log(request, current_pathway)
|
||||
return redirect(current_package.url + "/pathway")
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
@ -2491,7 +2506,7 @@ def package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
|
||||
if hidden := request.POST.get("hidden", None):
|
||||
if hidden == "delete":
|
||||
# pre_delete signal will take care of edge deletion
|
||||
current_node.delete()
|
||||
delete_with_log(request, current_node)
|
||||
|
||||
return redirect(current_pathway.url)
|
||||
else:
|
||||
@ -2645,7 +2660,7 @@ def package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||
|
||||
if hidden := request.POST.get("hidden", None):
|
||||
if hidden == "delete":
|
||||
current_edge.delete()
|
||||
delete_with_log(request, current_edge)
|
||||
return redirect(current_pathway.url)
|
||||
|
||||
if "selected-scenarios" in request.POST:
|
||||
@ -3007,7 +3022,7 @@ def group(request, group_uuid):
|
||||
|
||||
if hidden := request.POST.get("hidden", None):
|
||||
if hidden == "delete":
|
||||
current_group.delete()
|
||||
delete_with_log(request, current_group)
|
||||
return redirect(s.SERVER_URL + "/group")
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
<i class="glyphicon glyphicon-user"></i> Edit Permissions</a
|
||||
>
|
||||
</li>
|
||||
{% if meta.current_package.get_classification_level_display != "Secret" %}
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
@ -23,6 +24,7 @@
|
||||
<i class="glyphicon glyphicon-bullhorn"></i> Publish Package</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li>
|
||||
<a
|
||||
|
||||
Reference in New Issue
Block a user