Skip to content
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
13 changes: 10 additions & 3 deletions apiserver/plane/authentication/utils/host.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
# Django imports
from django.conf import settings
from django.http import HttpRequest

# Third party imports
from rest_framework.request import Request

# Module imports
from plane.utils.ip_address import get_client_ip

def base_host(request: Request | HttpRequest, is_admin: bool = False, is_space: bool = False, is_app: bool = False) -> str:

def base_host(
request: Request | HttpRequest,
is_admin: bool = False,
is_space: bool = False,
is_app: bool = False,
) -> str:
"""Utility function to return host / origin from the request"""
# Calculate the base origin from request
base_origin = settings.WEB_URL or settings.APP_BASE_URL

# Admin redirections
# Admin redirection
if is_admin:
admin_base_path = getattr(settings, "ADMIN_BASE_PATH", "/god-mode/")
if not admin_base_path.startswith("/"):
Expand All @@ -25,7 +32,7 @@ def base_host(request: Request | HttpRequest, is_admin: bool = False, is_space:
else:
return base_origin + admin_base_path

# Space redirections
# Space redirection
if is_space:
space_base_path = getattr(settings, "SPACE_BASE_PATH", "/spaces/")
if not space_base_path.startswith("/"):
Expand Down
20 changes: 15 additions & 5 deletions apiserver/plane/bgtasks/copy_s3_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import base64
import requests
from bs4 import BeautifulSoup

from urllib.parse import urljoin
# Django imports
from django.conf import settings

Expand All @@ -12,6 +12,7 @@
from plane.utils.exception_logger import log_exception
from plane.settings.storage import S3Storage
from celery import shared_task
from plane.utils.url import get_url_components


def get_entity_id_field(entity_type, entity_id):
Expand Down Expand Up @@ -67,11 +68,20 @@ def sync_with_external_service(entity_name, description_html):
"description_html": description_html,
"variant": "rich" if entity_name == "PAGE" else "document",
}
response = requests.post(
f"{settings.LIVE_BASE_URL}/convert-document/",
json=data,
headers=None,

if not settings.LIVE_URL:
return {}

live_url = get_url_components(settings.LIVE_URL)
if not live_url:
return {}

base_url = (
f"{live_url.get('scheme')}://{live_url.get('netloc')}{live_url.get('path')}"
)
url = urljoin(base_url, "convert-document/")

response = requests.post(url, json=data, headers=None)
if response.status_code == 200:
return response.json()
except requests.RequestException as e:
Expand Down
40 changes: 32 additions & 8 deletions apiserver/plane/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Python imports
import os
from urllib.parse import urlparse

from urllib.parse import urljoin

# Third party imports
import dj_database_url
Expand All @@ -13,6 +13,10 @@
from corsheaders.defaults import default_headers


# Module imports
from plane.utils.url import is_valid_url


BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Secret Key
Expand Down Expand Up @@ -310,15 +314,35 @@
CSRF_COOKIE_DOMAIN = os.environ.get("COOKIE_DOMAIN", None)
CSRF_FAILURE_VIEW = "plane.authentication.views.common.csrf_failure"

# Base URLs
###### Base URLs ######

# Admin Base URL
ADMIN_BASE_URL = os.environ.get("ADMIN_BASE_URL", None)
ADMIN_BASE_PATH = os.environ.get("ADMIN_BASE_PATH", None)
if ADMIN_BASE_URL and not is_valid_url(ADMIN_BASE_URL):
ADMIN_BASE_URL = None
ADMIN_BASE_PATH = os.environ.get("ADMIN_BASE_PATH", "/god-mode/")

# Space Base URL
SPACE_BASE_URL = os.environ.get("SPACE_BASE_URL", None)
SPACE_BASE_PATH = os.environ.get("SPACE_BASE_PATH", None)
APP_BASE_URL = os.environ.get("APP_BASE_URL")
APP_BASE_PATH = os.environ.get("APP_BASE_PATH", None)
LIVE_BASE_URL = os.environ.get("LIVE_BASE_URL")
LIVE_BASE_PATH = os.environ.get("LIVE_BASE_PATH")
if SPACE_BASE_URL and not is_valid_url(SPACE_BASE_URL):
SPACE_BASE_URL = None
SPACE_BASE_PATH = os.environ.get("SPACE_BASE_PATH", "/spaces/")

# App Base URL
APP_BASE_URL = os.environ.get("APP_BASE_URL", None)
if APP_BASE_URL and not is_valid_url(APP_BASE_URL):
APP_BASE_URL = None
APP_BASE_PATH = os.environ.get("APP_BASE_PATH", "/")

# Live Base URL
LIVE_BASE_URL = os.environ.get("LIVE_BASE_URL", None)
if LIVE_BASE_URL and not is_valid_url(LIVE_BASE_URL):
LIVE_BASE_URL = None
LIVE_BASE_PATH = os.environ.get("LIVE_BASE_PATH", "/live/")

LIVE_URL = urljoin(LIVE_BASE_URL, LIVE_BASE_PATH) if LIVE_BASE_URL else None

# WEB URL
WEB_URL = os.environ.get("WEB_URL")

HARD_DELETE_AFTER_DAYS = int(os.environ.get("HARD_DELETE_AFTER_DAYS", 60))
Expand Down
12 changes: 9 additions & 3 deletions apiserver/plane/utils/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@
# Module imports
from plane.utils.ip_address import get_client_ip

def base_host(request: Request | HttpRequest, is_admin: bool = False, is_space: bool = False, is_app: bool = False) -> str:

def base_host(
request: Request | HttpRequest,
is_admin: bool = False,
is_space: bool = False,
is_app: bool = False,
) -> str:
"""Utility function to return host / origin from the request"""
# Calculate the base origin from request
base_origin = settings.WEB_URL or settings.APP_BASE_URL

if not base_origin:
raise ImproperlyConfigured("APP_BASE_URL or WEB_URL is not set")

# Admin redirections
# Admin redirection
if is_admin:
admin_base_path = getattr(settings, "ADMIN_BASE_PATH", "/god-mode/")
if not admin_base_path.startswith("/"):
Expand All @@ -30,7 +36,7 @@ def base_host(request: Request | HttpRequest, is_admin: bool = False, is_space:
else:
return base_origin + admin_base_path

# Space redirections
# Space redirection
if is_space:
space_base_path = getattr(settings, "SPACE_BASE_PATH", "/spaces/")
if not space_base_path.startswith("/"):
Expand Down
54 changes: 54 additions & 0 deletions apiserver/plane/utils/url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Python imports
from typing import Optional
from urllib.parse import urlparse


def is_valid_url(url: str) -> bool:
"""
Validates whether the given string is a well-formed URL.

Args:
url (str): The URL string to validate.

Returns:
bool: True if the URL is valid, False otherwise.

Example:
>>> is_valid_url("https://example.com")
True
>>> is_valid_url("not a url")
False
"""
try:
result = urlparse(url)
# A valid URL should have at least scheme and netloc
return all([result.scheme, result.netloc])
except TypeError:
return False


def get_url_components(url: str) -> Optional[dict]:
"""
Parses the URL and returns its components if valid.

Args:
url (str): The URL string to parse.

Returns:
Optional[dict]: A dictionary with URL components if valid, None otherwise.

Example:
>>> get_url_components("https://example.com/path?query=1")
{'scheme': 'https', 'netloc': 'example.com', 'path': '/path', 'params': '', 'query': 'query=1', 'fragment': ''}
"""
if not is_valid_url(url):
return None
result = urlparse(url)
return {
"scheme": result.scheme,
"netloc": result.netloc,
"path": result.path,
"params": result.params,
"query": result.query,
"fragment": result.fragment,
}