SECURITY - TASKER: cleanup access and invite approval
This commit is contained in:
@@ -6,6 +6,7 @@ from secrets import compare_digest
|
||||
from django.contrib.auth import logout
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.db import transaction
|
||||
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
@@ -13,7 +14,7 @@ from django.views import View
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from plane.authentication.utils.host import user_ip
|
||||
from plane.db.models import ExternalIdentityLink, Session, User
|
||||
from plane.db.models import ExternalIdentityLink, IssueAssignee, ProjectMember, Session, User, WorkspaceMember
|
||||
|
||||
|
||||
OIDC_PROVIDER = "authentik"
|
||||
@@ -33,7 +34,6 @@ def get_nodedc_internal_token():
|
||||
return (
|
||||
os.environ.get("PLANE_NODEDC_ACCESS_TOKEN", "").strip()
|
||||
or os.environ.get("NODEDC_INTERNAL_ACCESS_TOKEN", "").strip()
|
||||
or os.environ.get("PLANE_OIDC_CLIENT_SECRET", "").strip()
|
||||
)
|
||||
|
||||
|
||||
@@ -225,6 +225,32 @@ def invalidate_user_sessions(user, request):
|
||||
return deleted_count
|
||||
|
||||
|
||||
def revoke_user_external_identity_links(user):
|
||||
deleted_count, _ = ExternalIdentityLink.objects.filter(
|
||||
provider=OIDC_PROVIDER,
|
||||
user=user,
|
||||
status=ExternalIdentityLink.Status.ACTIVE,
|
||||
).delete()
|
||||
return deleted_count
|
||||
|
||||
|
||||
def delete_queryset(queryset):
|
||||
result = queryset.delete()
|
||||
return result[0] if isinstance(result, tuple) else result
|
||||
|
||||
|
||||
def revoke_user_tasker_access(user):
|
||||
deleted_issue_assignees = delete_queryset(IssueAssignee.objects.filter(assignee=user))
|
||||
deleted_project_memberships = delete_queryset(ProjectMember.objects.filter(member=user))
|
||||
deleted_workspace_memberships = delete_queryset(WorkspaceMember.objects.filter(member=user))
|
||||
|
||||
return {
|
||||
"workspaceMemberships": deleted_workspace_memberships,
|
||||
"projectMemberships": deleted_project_memberships,
|
||||
"issueAssignees": deleted_issue_assignees,
|
||||
}
|
||||
|
||||
|
||||
class NodeDCFrontChannelLogoutEndpoint(View):
|
||||
def get(self, request):
|
||||
logout_current_user(request)
|
||||
@@ -269,12 +295,27 @@ class NodeDCInternalSessionLogoutEndpoint(View):
|
||||
return JsonResponse({"ok": True, "deletedSessions": 0, "user": None})
|
||||
|
||||
guard_keys = mark_logout_guard(user=user, payload=payload)
|
||||
deleted_sessions = invalidate_user_sessions(user, request)
|
||||
with transaction.atomic():
|
||||
deleted_sessions = invalidate_user_sessions(user, request)
|
||||
deleted_identity_links = 0
|
||||
deleted_tasker_access = {
|
||||
"workspaceMemberships": 0,
|
||||
"projectMemberships": 0,
|
||||
"issueAssignees": 0,
|
||||
}
|
||||
|
||||
if payload.get("revokeIdentityLinks") is True or payload.get("revokeIdentityLink") is True:
|
||||
deleted_identity_links = revoke_user_external_identity_links(user)
|
||||
|
||||
if payload.get("revokeTaskerAccess") is True or payload.get("revokeMemberships") is True:
|
||||
deleted_tasker_access = revoke_user_tasker_access(user)
|
||||
|
||||
return JsonResponse(
|
||||
{
|
||||
"ok": True,
|
||||
"deletedSessions": deleted_sessions,
|
||||
"deletedIdentityLinks": deleted_identity_links,
|
||||
"deletedTaskerAccess": deleted_tasker_access,
|
||||
"guardKeys": len(guard_keys),
|
||||
"user": {
|
||||
"id": str(user.id),
|
||||
|
||||
Reference in New Issue
Block a user