Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal_use_only decorator added and login url changed #229

Merged
merged 5 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ pytz==2024.1
django-session-security==2.6.7
beautifulsoup4==4.12.3
python3-saml==1.16.0
django-ipware==7.0.1
django-decorator-include==3.0
30 changes: 7 additions & 23 deletions backend/src/zango/apps/shared/platformauth/urls.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
from django.urls import re_path
from django.views.decorators.csrf import csrf_exempt

from .views import *
from zango.apps.shared.platformauth.views import (
PlatformUserLoginView,
PlatformUserLogoutView,
)


urlpatterns = [
re_path(
r'^login/',
PlatformUserLoginView.as_view(),
name='platform-login'
),
re_path(
r'^api/v1/login/',
PlatformUserLoginAPIV1.as_view(),
name='platform-api-v1-login'
),
# url(
# regex=r'^api/v1/register-user/',
# view=PlatformUserRegisterAPIV1.as_view(),
# name='platform-api-v1-registeruser'
# ),
re_path(
r'^api/v1/profile/',
PlatformUserProfileAPIV1.as_view(),
name='platform-api-v1-userprofile'
)

]
re_path(r"^login/", PlatformUserLoginView.as_view(), name="platform-login"),
re_path(r"^logout/", PlatformUserLogoutView.as_view(), name="platform-logout"),
]
27 changes: 7 additions & 20 deletions backend/src/zango/apps/shared/platformauth/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from django.contrib.auth.views import LoginView
from django.contrib.auth.views import LoginView, LogoutView
from django.shortcuts import redirect
from rest_framework.views import APIView
from zango.core.api import ZangoSessionPlatformAPIView, get_api_response


# Create your views here.
Expand All @@ -17,22 +15,11 @@ def post(self, request, *args, **kwargs):
return redirect("/platform")


class PlatformUserLoginAPIV1(APIView):
pass


class PlatformUserProfileAPIV1(ZangoSessionPlatformAPIView):
""" """

def get_profile_data(self, request):
data = {}
data["name"] = request.user.platform_user.name
data["email"] = request.user.platform_user.email
data["mobile"] = request.user.platform_user.mobile
data["role"] = "Platform User"
data["user_uuid"] = request.user.username
return data
class PlatformUserLogoutView(LogoutView):
"""
View to logout the user.
"""

def get(self, request, *args, **kwargs):
data = self.get_profile_data(request)
return get_api_response(True, data, 200)
super().get(request, *args, **kwargs)
return redirect("/auth/login")
3 changes: 1 addition & 2 deletions backend/src/zango/apps/shared/tenancy/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@

from .views import AppPanelView


urlpatterns = [re_path(r"^platform/", AppPanelView.as_view(), name="platform")]
urlpatterns = [re_path(r"^", AppPanelView.as_view(), name="platform")]
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
REDIS_PORT=(str, "6379"),
SESSION_SECURITY_WARN_AFTER=(int, 1700),
SESSION_SECURITY_EXPIRE_AFTER=(int, 1800),
INTERNAL_IPS=(list, []),
)
environ.Env.read_env(os.path.join(BASE_DIR.parent, ".env"))

Expand Down Expand Up @@ -130,3 +131,7 @@
# to simplify troubleshooting and testing.
SESSION_COOKIE_SECURE = False
CSRF_COOKIE_SECURE = False

# INTERNAL_IPS can contain a list of IP addresses or CIDR blocks that are considered internal.
# Both individual IP addresses and CIDR notation (e.g., '192.168.1.1' or '192.168.1.0/24') can be provided.
INTERNAL_IPS = env("INTERNAL_IPS")
2 changes: 1 addition & 1 deletion backend/src/zango/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

LOGOUT_REDIRECT_URL = "/admin/login"
LOGOUT_REDIRECT_URL = "/auth/login"

PASSWORD_MIN_LENGTH = 8
PASSWORD_NO_REPEAT_DAYS = 180
Expand Down
18 changes: 12 additions & 6 deletions backend/src/zango/config/urls_public.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from decorator_include import decorator_include

from zango.apps.shared.platformauth.views import (
PlatformUserLoginView,
)
from zango.core.decorators import internal_access_only

urlpatterns = [
re_path(
r"^admin/login/$",
PlatformUserLoginView.as_view(),
name="login",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should enforce internal_ip in a blanket way for all platform endpoints.

r"^auth/",
decorator_include(internal_access_only, "zango.apps.shared.platformauth.urls"),
),
re_path(
r"^api/", decorator_include(internal_access_only, "zango.api.platform.urls")
),
re_path(r"^admin/", admin.site.urls),
re_path(r"^api/", include("zango.api.platform.urls")),
re_path(r"api/auth/", include("knox.urls")),
re_path(r"session_security/", include("session_security.urls")),
re_path(r"^", include("zango.apps.shared.tenancy.urls")),
re_path(
r"^platform/",
decorator_include(internal_access_only, "zango.apps.shared.tenancy.urls"),
),
]

if settings.DEBUG:
urlpatterns += [
path("__debug__/", include("debug_toolbar.urls")),
Expand Down
33 changes: 33 additions & 0 deletions backend/src/zango/core/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import ipaddress

from django.conf import settings
from django.http import Http404
from ipware.ip import get_client_ip


def internal_access_only(f):
"""
Decorator to restrict access to views based on internal IP addresses.

Args:
f (callable): The view function to decorate.

Returns:
callable: Decorated view function.

Raises:
Http404: If the client's IP is not in the list of allowed IPs and the environment is 'staging' or 'prod'.

"""

def decorate_view(request, *args, **kwargs):
client_ip, is_routable = get_client_ip(request)
allowed_ips = [ipaddress.ip_network(ip) for ip in settings.INTERNAL_IPS]
if settings.ENV in ["staging", "prod"]:
# Check if the client's IP is not in the allowed IPs
if not any(ipaddress.ip_address(client_ip) in ip for ip in allowed_ips):
# Raise a 404 error if the condition is met
raise Http404
return f(request, *args, **kwargs)

return decorate_view
2 changes: 1 addition & 1 deletion backend/src/zango/core/generic_views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ZangoSessionPlatformTemplateView(IsAuthenticatedPlatformUser, TemplateView

@classmethod
def as_view(cls):
login_url = "/admin/login/"
login_url = "/auth/login/"
return login_required(
super(ZangoSessionPlatformTemplateView, cls).as_view(), login_url=login_url
)
Expand Down