Import urls.py and settings.py #1
@ -12,9 +12,12 @@ import sentry_sdk
|
|||||||
from pydantic import AnyUrl, BaseSettings, EmailStr, Field, validator
|
from pydantic import AnyUrl, BaseSettings, EmailStr, Field, validator
|
||||||
from sentry_sdk.integrations.django import DjangoIntegration
|
from sentry_sdk.integrations.django import DjangoIntegration
|
||||||
|
|
||||||
from takahe import __version__
|
from takahe.takahe import __version__
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
import saml2
|
||||||
|
from saml2.saml import NAMEID_FORMAT_PERSISTENT
|
||||||
|
|
||||||
|
BASE_DIR = '/srv/takahe'
|
||||||
|
|
||||||
|
|
||||||
class CacheBackendUrl(AnyUrl):
|
class CacheBackendUrl(AnyUrl):
|
||||||
@ -59,7 +62,7 @@ class Settings(BaseSettings):
|
|||||||
|
|
||||||
#: The currently running environment, used for things such as sentry
|
#: The currently running environment, used for things such as sentry
|
||||||
#: error reporting.
|
#: error reporting.
|
||||||
ENVIRONMENT: Environments = "development"
|
ENVIRONMENT: Environments = "production"
|
||||||
|
|
||||||
#: Should django run in debug mode?
|
#: Should django run in debug mode?
|
||||||
DEBUG: bool = False
|
DEBUG: bool = False
|
||||||
@ -99,7 +102,7 @@ class Settings(BaseSettings):
|
|||||||
ERROR_EMAILS: list[EmailStr] | None = None
|
ERROR_EMAILS: list[EmailStr] | None = None
|
||||||
|
|
||||||
MEDIA_URL: str = "/media/"
|
MEDIA_URL: str = "/media/"
|
||||||
MEDIA_ROOT: str = str(BASE_DIR / "media")
|
MEDIA_ROOT: str = os.path.join(BASE_DIR, "media")
|
||||||
MEDIA_BACKEND: MediaBackendUrl | None = None
|
MEDIA_BACKEND: MediaBackendUrl | None = None
|
||||||
|
|
||||||
#: Maximum filesize when uploading images. Increasing this may increase memory utilization
|
#: Maximum filesize when uploading images. Increasing this may increase memory utilization
|
||||||
@ -147,7 +150,7 @@ class Settings(BaseSettings):
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
env_prefix = "TAKAHE_"
|
env_prefix = "TAKAHE_"
|
||||||
env_file = str(BASE_DIR / TAKAHE_ENV_FILE)
|
env_file = '/etc/sysconfig/takahe'
|
||||||
env_file_encoding = "utf-8"
|
env_file_encoding = "utf-8"
|
||||||
# Case sensitivity doesn't work on Windows, so might as well be
|
# Case sensitivity doesn't work on Windows, so might as well be
|
||||||
# consistent from the get-go.
|
# consistent from the get-go.
|
||||||
@ -179,16 +182,17 @@ INSTALLED_APPS = [
|
|||||||
"django.contrib.staticfiles",
|
"django.contrib.staticfiles",
|
||||||
"django_htmx",
|
"django_htmx",
|
||||||
"corsheaders",
|
"corsheaders",
|
||||||
"core",
|
"takahe.core",
|
||||||
"activities",
|
"takahe.activities",
|
||||||
"api",
|
"takahe.api",
|
||||||
"mediaproxy",
|
"takahe.mediaproxy",
|
||||||
"stator",
|
"takahe.stator",
|
||||||
"users",
|
"takahe.users",
|
||||||
|
"djangosaml2",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"core.middleware.SentryTaggingMiddleware",
|
"takahe.core.middleware.SentryTaggingMiddleware",
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
"corsheaders.middleware.CorsMiddleware",
|
"corsheaders.middleware.CorsMiddleware",
|
||||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||||
@ -199,19 +203,20 @@ MIDDLEWARE = [
|
|||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
"django_htmx.middleware.HtmxMiddleware",
|
"django_htmx.middleware.HtmxMiddleware",
|
||||||
"core.middleware.HeadersMiddleware",
|
"takahe.core.middleware.HeadersMiddleware",
|
||||||
"core.middleware.ConfigLoadingMiddleware",
|
"takahe.core.middleware.ConfigLoadingMiddleware",
|
||||||
"api.middleware.ApiTokenMiddleware",
|
"takahe.api.middleware.ApiTokenMiddleware",
|
||||||
"users.middleware.IdentityMiddleware",
|
"takahe.users.middleware.IdentityMiddleware",
|
||||||
"activities.middleware.EmojiDefaultsLoadingMiddleware",
|
"takahe.activities.middleware.EmojiDefaultsLoadingMiddleware",
|
||||||
|
"djangosaml2.middleware.SamlSessionMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = "takahe.urls"
|
ROOT_URLCONF = "takahe.takahe.urls"
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
"DIRS": [BASE_DIR / "templates"],
|
"DIRS": [os.path.join(BASE_DIR, "templates")],
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"context_processors": [
|
"context_processors": [
|
||||||
@ -219,13 +224,13 @@ TEMPLATES = [
|
|||||||
"django.template.context_processors.request",
|
"django.template.context_processors.request",
|
||||||
"django.contrib.auth.context_processors.auth",
|
"django.contrib.auth.context_processors.auth",
|
||||||
"django.contrib.messages.context_processors.messages",
|
"django.contrib.messages.context_processors.messages",
|
||||||
"core.context.config_context",
|
"takahe.core.context.config_context",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = "takahe.wsgi.application"
|
WSGI_APPLICATION = "takahe.takahe.wsgi.application"
|
||||||
|
|
||||||
if SETUP.DATABASE_SERVER:
|
if SETUP.DATABASE_SERVER:
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
@ -272,7 +277,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|||||||
|
|
||||||
AUTH_USER_MODEL = "users.User"
|
AUTH_USER_MODEL = "users.User"
|
||||||
|
|
||||||
LOGIN_URL = "/auth/login/"
|
LOGIN_URL = "/saml2/login/"
|
||||||
LOGOUT_URL = "/auth/logout/"
|
LOGOUT_URL = "/auth/logout/"
|
||||||
LOGIN_REDIRECT_URL = "/"
|
LOGIN_REDIRECT_URL = "/"
|
||||||
LOGOUT_REDIRECT_URL = "/"
|
LOGOUT_REDIRECT_URL = "/"
|
||||||
@ -282,7 +287,7 @@ STATICFILES_FINDERS = [
|
|||||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||||
]
|
]
|
||||||
|
|
||||||
STATICFILES_DIRS = [BASE_DIR / "static"]
|
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
|
||||||
|
|
||||||
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
|
||||||
@ -290,7 +295,7 @@ SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
|
|||||||
|
|
||||||
WHITENOISE_MAX_AGE = 3600
|
WHITENOISE_MAX_AGE = 3600
|
||||||
|
|
||||||
STATIC_ROOT = BASE_DIR / "static-collected"
|
STATIC_ROOT = os.path.join(BASE_DIR, "static-collected")
|
||||||
|
|
||||||
ALLOWED_HOSTS = SETUP.ALLOWED_HOSTS
|
ALLOWED_HOSTS = SETUP.ALLOWED_HOSTS
|
||||||
|
|
||||||
@ -355,14 +360,14 @@ if SETUP.MEDIA_BACKEND:
|
|||||||
parsed = urllib.parse.urlparse(SETUP.MEDIA_BACKEND)
|
parsed = urllib.parse.urlparse(SETUP.MEDIA_BACKEND)
|
||||||
query = urllib.parse.parse_qs(parsed.query)
|
query = urllib.parse.parse_qs(parsed.query)
|
||||||
if parsed.scheme == "gs":
|
if parsed.scheme == "gs":
|
||||||
DEFAULT_FILE_STORAGE = "core.uploads.TakaheGoogleCloudStorage"
|
DEFAULT_FILE_STORAGE = "takahe.core.uploads.TakaheGoogleCloudStorage"
|
||||||
GS_BUCKET_NAME = parsed.path.lstrip("/")
|
GS_BUCKET_NAME = parsed.path.lstrip("/")
|
||||||
GS_QUERYSTRING_AUTH = False
|
GS_QUERYSTRING_AUTH = False
|
||||||
if parsed.hostname is not None:
|
if parsed.hostname is not None:
|
||||||
port = parsed.port or 443
|
port = parsed.port or 443
|
||||||
GS_CUSTOM_ENDPOINT = f"https://{parsed.hostname}:{port}"
|
GS_CUSTOM_ENDPOINT = f"https://{parsed.hostname}:{port}"
|
||||||
elif parsed.scheme == "s3":
|
elif parsed.scheme == "s3":
|
||||||
DEFAULT_FILE_STORAGE = "core.uploads.TakaheS3Storage"
|
DEFAULT_FILE_STORAGE = "takahe.core.uploads.TakaheS3Storage"
|
||||||
AWS_STORAGE_BUCKET_NAME = parsed.path.lstrip("/")
|
AWS_STORAGE_BUCKET_NAME = parsed.path.lstrip("/")
|
||||||
AWS_QUERYSTRING_AUTH = False
|
AWS_QUERYSTRING_AUTH = False
|
||||||
AWS_DEFAULT_ACL = "public-read"
|
AWS_DEFAULT_ACL = "public-read"
|
||||||
@ -393,3 +398,97 @@ TAKAHE_USER_AGENT = (
|
|||||||
f"python-httpx/{httpx.__version__} "
|
f"python-httpx/{httpx.__version__} "
|
||||||
f"(Takahe/{__version__}; +https://{SETUP.MAIN_DOMAIN}/)"
|
f"(Takahe/{__version__}; +https://{SETUP.MAIN_DOMAIN}/)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
'djangosaml2.backends.Saml2Backend',
|
||||||
|
)
|
||||||
|
|
||||||
|
SAML_SESSION_COOKIE_NAME = 'takahe_test_session'
|
||||||
|
SESSION_COOKIE_SECURE = False
|
||||||
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
||||||
|
SAML_DJANGO_USER_MAIN_ATTRIBUTE = 'email'
|
||||||
|
|
||||||
|
SAML_ATTRIBUTE_MAPPING = {
|
||||||
|
'email': ('email', ),
|
||||||
|
}
|
||||||
|
|
||||||
|
SAML_CONFIG = {
|
||||||
|
# full path to the xmlsec1 binary programm
|
||||||
|
'xmlsec_binary': '/usr/bin/xmlsec1',
|
||||||
|
|
||||||
|
# your entity id, usually your subdomain plus the url to the metadata view
|
||||||
|
'entityid': 'https://__REPLACE_ME__/saml2/metadata/',
|
||||||
|
|
||||||
|
'attribute_map_dir': os.path.join(BASE_DIR, 'attribute-maps'),
|
||||||
|
|
||||||
|
'allow_unknown_attributes': False,
|
||||||
|
|
||||||
|
'service': {
|
||||||
|
'sp' : {
|
||||||
|
'name': 'Federated Takahe sample SP',
|
||||||
|
'name_id_format': saml2.saml.NAMEID_FORMAT_PERSISTENT,
|
||||||
|
|
||||||
|
'endpoints': {
|
||||||
|
'assertion_consumer_service': [
|
||||||
|
('https://__REPLACE_ME__/saml2/acs/',
|
||||||
|
saml2.BINDING_HTTP_POST),
|
||||||
|
],
|
||||||
|
'single_logout_service': [
|
||||||
|
('https://__REPLACE_ME__/saml2/ls/',
|
||||||
|
saml2.BINDING_HTTP_REDIRECT),
|
||||||
|
('https://__REPLACE_ME__/saml2/ls/post',
|
||||||
|
saml2.BINDING_HTTP_POST),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
'signing_algorithm': saml2.xmldsig.SIG_RSA_SHA256,
|
||||||
|
'digest_algorithm': saml2.xmldsig.DIGEST_SHA256,
|
||||||
|
|
||||||
|
'force_authn': False,
|
||||||
|
|
||||||
|
'name_id_format_allow_create': False,
|
||||||
|
|
||||||
|
'required_attributes': ['uid',
|
||||||
|
'email'],
|
||||||
|
|
||||||
|
'want_response_signed': True,
|
||||||
|
'authn_requests_signed': True,
|
||||||
|
'logout_requests_signed': True,
|
||||||
|
'want_assertions_signed': True,
|
||||||
|
|
||||||
|
'only_use_keys_in_metadata': True,
|
||||||
|
|
||||||
|
'allow_unsolicited': False,
|
||||||
|
|
||||||
|
'metadata': {
|
||||||
|
# in production, use local file
|
||||||
|
# 'local': [os.path.join(BASE_DIR, 'remote_metadata.xml')],
|
||||||
|
'remote': [{"url": "https://libsso.net/realms/LibertaCasa/protocol/saml/descriptor"},],
|
||||||
|
},
|
||||||
|
|
||||||
|
'debug': 0,
|
||||||
|
|
||||||
|
'key_file': '__REPLACE_ME__', # private part
|
||||||
|
'cert_file': '__REPLACE_ME__', # public part
|
||||||
|
|
||||||
|
# Encryption
|
||||||
|
# 'encryption_keypairs': [{
|
||||||
|
# 'key_file': '__REPLACE_ME__', # private part
|
||||||
|
# 'cert_file': '__REPLACE_ME__', # public part
|
||||||
|
# }],
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGING = {
|
||||||
|
'version': 1,
|
||||||
|
'disable_existing_loggers': False,
|
||||||
|
'handlers': {
|
||||||
|
'console': {
|
||||||
|
'class': 'logging.StreamHandler',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'root': {
|
||||||
|
'handlers': ['console'],
|
||||||
|
'level': 'INFO',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -9,6 +9,9 @@ from mediaproxy import views as mediaproxy
|
|||||||
from stator import views as stator
|
from stator import views as stator
|
||||||
from users.views import activitypub, admin, auth, identity, report, settings
|
from users.views import activitypub, admin, auth, identity, report, settings
|
||||||
|
|
||||||
|
from django.conf.urls import include
|
||||||
|
from django.views.generic.base import RedirectView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", core.homepage),
|
path("", core.homepage),
|
||||||
path("manifest.json", core.AppManifest.as_view()),
|
path("manifest.json", core.AppManifest.as_view()),
|
||||||
@ -174,7 +177,7 @@ urlpatterns = [
|
|||||||
path("@<handle>/posts/<int:post_id>/report/", report.SubmitReport.as_view()),
|
path("@<handle>/posts/<int:post_id>/report/", report.SubmitReport.as_view()),
|
||||||
path("@<handle>/posts/<int:post_id>/edit/", compose.Compose.as_view()),
|
path("@<handle>/posts/<int:post_id>/edit/", compose.Compose.as_view()),
|
||||||
# Authentication
|
# Authentication
|
||||||
path("auth/login/", auth.Login.as_view(), name="login"),
|
path("auth/login/", RedirectView.as_view(url='/saml2/login', permanent=False), name='login'),
|
||||||
path("auth/logout/", auth.Logout.as_view(), name="logout"),
|
path("auth/logout/", auth.Logout.as_view(), name="logout"),
|
||||||
path("auth/signup/", auth.Signup.as_view(), name="signup"),
|
path("auth/signup/", auth.Signup.as_view(), name="signup"),
|
||||||
path("auth/reset/", auth.TriggerReset.as_view(), name="trigger_reset"),
|
path("auth/reset/", auth.TriggerReset.as_view(), name="trigger_reset"),
|
||||||
@ -248,4 +251,5 @@ urlpatterns = [
|
|||||||
core.custom_static_serve,
|
core.custom_static_serve,
|
||||||
kwargs={"document_root": djsettings.MEDIA_ROOT},
|
kwargs={"document_root": djsettings.MEDIA_ROOT},
|
||||||
),
|
),
|
||||||
|
path('saml2/', include('djangosaml2.urls')),
|
||||||
]
|
]
|
||||||
|
Reference in New Issue
Block a user