mailman-web: use upstream, improve NixOS module
Previously, some files were copied into the Nixpkgs tree, which meant we wouldn't easily be able to update them, and was also just messy. The reason it was done that way before was so that a few NixOS options could be substituted in. Some problems with doing it this way were that the _package_ changed depending on the values of the settings, which is pretty strange, and also that it only allowed those few settings to be set. In the new model, mailman-web is a usable package without needing to override, and I've implemented the NixOS options in a much more flexible way. NixOS' mailman-web config file first reads the mailman-web settings to use as defaults, but then it loads another configuration file generated from the new services.mailman.webSettings option, so _any_ mailman-web Django setting can be customised by the user, rather than just the three that were supported before. I've kept the old options, but there might not really be any good reason to keep them.
This commit is contained in:
parent
a8538a73a7
commit
881dd9963f
|
@ -6,24 +6,18 @@ let
|
|||
|
||||
cfg = config.services.mailman;
|
||||
|
||||
mailmanWeb = pkgs.python3Packages.mailman-web.override {
|
||||
serverEMail = cfg.siteOwner;
|
||||
archiverKey = cfg.hyperkittyApiKey;
|
||||
allowedHosts = cfg.webHosts;
|
||||
};
|
||||
# This deliberately doesn't use recursiveUpdate so users can
|
||||
# override the defaults.
|
||||
settings = {
|
||||
DEFAULT_FROM_EMAIL = cfg.siteOwner;
|
||||
SERVER_EMAIL = cfg.siteOwner;
|
||||
ALLOWED_HOSTS = [ "localhost" "127.0.0.1" ] ++ cfg.webHosts;
|
||||
COMPRESS_OFFLINE = true;
|
||||
STATIC_ROOT = "/var/lib/mailman-web/static";
|
||||
MEDIA_ROOT = "/var/lib/mailman-web/media";
|
||||
} // cfg.webSettings;
|
||||
|
||||
mailmanWebPyEnv = pkgs.python3.withPackages (x: with x; [mailman-web]);
|
||||
|
||||
mailmanWebExe = with pkgs; stdenv.mkDerivation {
|
||||
inherit (mailmanWeb) name;
|
||||
buildInputs = [makeWrapper];
|
||||
unpackPhase = ":";
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper ${mailmanWebPyEnv}/bin/django-admin $out/bin/mailman-web \
|
||||
--set DJANGO_SETTINGS_MODULE settings
|
||||
'';
|
||||
};
|
||||
settingsJSON = pkgs.writeText "settings.json" (builtins.toJSON settings);
|
||||
|
||||
mailmanCfg = ''
|
||||
[mailman]
|
||||
|
@ -98,8 +92,8 @@ in {
|
|||
|
||||
webRoot = mkOption {
|
||||
type = types.path;
|
||||
default = "${mailmanWeb}/${pkgs.python3.sitePackages}";
|
||||
defaultText = "pkgs.python3Packages.mailman-web";
|
||||
default = "${pkgs.mailman-web}/${pkgs.python3.sitePackages}";
|
||||
defaultText = "\${pkgs.mailman-web}/\${pkgs.python3.sitePackages}";
|
||||
description = ''
|
||||
The web root for the Hyperkity + Postorius apps provided by Mailman.
|
||||
This variable can be set, of course, but it mainly exists so that site
|
||||
|
@ -128,6 +122,14 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
webSettings = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
Overrides for the default mailman-web Django settings.
|
||||
'';
|
||||
};
|
||||
|
||||
hyperkitty = {
|
||||
enable = mkEnableOption "the Hyperkitty archiver for Mailman";
|
||||
|
||||
|
@ -175,10 +177,27 @@ in {
|
|||
|
||||
users.users.mailman = { description = "GNU Mailman"; isSystemUser = true; };
|
||||
|
||||
environment = {
|
||||
systemPackages = [ pkgs.mailman mailmanWebExe pkgs.sassc ];
|
||||
etc."mailman.cfg".text = mailmanCfg;
|
||||
};
|
||||
environment.etc."mailman.cfg".text = mailmanCfg;
|
||||
|
||||
environment.etc."mailman3/settings.py".text = ''
|
||||
import os
|
||||
|
||||
# Required by mailman_web.settings, but will be overridden when
|
||||
# settings_local.json is loaded.
|
||||
os.environ["SECRET_KEY"] = ""
|
||||
|
||||
from mailman_web.settings import *
|
||||
|
||||
import json
|
||||
|
||||
with open('${settingsJSON}') as f:
|
||||
globals().update(json.load(f))
|
||||
|
||||
with open('/var/lib/mailman-web/settings_local.json') as f:
|
||||
globals().update(json.load(f))
|
||||
'';
|
||||
|
||||
environment.systemPackages = [ cfg.package ] ++ (with pkgs; [ mailman-web ]);
|
||||
|
||||
services.postfix = {
|
||||
recipientDelimiter = "+"; # bake recipient addresses in mail envelopes via VERP
|
||||
|
@ -201,36 +220,39 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
systemd.services.mailman-secrets = {
|
||||
description = "Generate Hyperkitty API key";
|
||||
systemd.services.mailman-settings = {
|
||||
description = "Generate settings files (including secrets) for Mailman";
|
||||
before = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ];
|
||||
requiredBy = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ];
|
||||
path = with pkgs; [ jq ];
|
||||
script = ''
|
||||
mailmanDir=/var/lib/mailman
|
||||
mailmanWebDir=/var/lib/mailman-web
|
||||
|
||||
mailmanCfg=$mailmanDir/mailman-hyperkitty.cfg
|
||||
hyperkittyCfg=$mailmanWebDir/settings_local.py
|
||||
|
||||
[ -e $mailmanCfg -o -e $hyperkittyCfg ] && exit 0
|
||||
mailmanWebCfg=$mailmanWebDir/settings_local.json
|
||||
|
||||
install -m 0700 -o mailman -g nogroup -d $mailmanDir
|
||||
install -m 0700 -o ${cfg.webUser} -g nogroup -d $mailmanWebDir
|
||||
|
||||
hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
|
||||
secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
|
||||
if [ ! -e $mailmanWebCfg ]; then
|
||||
hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
|
||||
secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
|
||||
|
||||
hyperkittyCfgTmp=$(mktemp)
|
||||
echo "MAILMAN_ARCHIVER_KEY='$hyperkittyApiKey'" >>"$hyperkittyCfgTmp"
|
||||
echo "SECRET_KEY='$secretKey'" >>"$hyperkittyCfgTmp"
|
||||
chown ${cfg.webUser} "$hyperkittyCfgTmp"
|
||||
mailmanWebCfgTmp=$(mktemp)
|
||||
jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
|
||||
--arg archiver_key "$hyperkittyApiKey" \
|
||||
--arg secret_key "$secretKey" \
|
||||
>"$mailmanWebCfgTmp"
|
||||
chown ${cfg.webUser} "$mailmanWebCfgTmp"
|
||||
mv -n "$mailmanWebCfgTmp" $mailmanWebCfg
|
||||
fi
|
||||
|
||||
hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY $mailmanWebCfg)"
|
||||
mailmanCfgTmp=$(mktemp)
|
||||
sed "s/@API_KEY@/$hyperkittyApiKey/g" ${mailmanHyperkittyCfg} >"$mailmanCfgTmp"
|
||||
chown mailman "$mailmanCfgTmp"
|
||||
|
||||
mv -n "$hyperkittyCfgTmp" $hyperkittyCfg
|
||||
mv -n "$mailmanCfgTmp" $mailmanCfg
|
||||
mv "$mailmanCfgTmp" $mailmanCfg
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
@ -241,11 +263,12 @@ in {
|
|||
description = "Init Postorius DB";
|
||||
before = [ "httpd.service" "uwsgi.service" ];
|
||||
requiredBy = [ "httpd.service" "uwsgi.service" ];
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
script = ''
|
||||
${mailmanWebExe}/bin/mailman-web migrate
|
||||
${pkgs.mailman-web}/bin/mailman-web migrate
|
||||
rm -rf static
|
||||
${mailmanWebExe}/bin/mailman-web collectstatic
|
||||
${mailmanWebExe}/bin/mailman-web compress
|
||||
${pkgs.mailman-web}/bin/mailman-web collectstatic
|
||||
${pkgs.mailman-web}/bin/mailman-web compress
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = cfg.webUser;
|
||||
|
@ -267,9 +290,10 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "GNU Hyperkitty QCluster Process";
|
||||
after = [ "network.target" ];
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
wantedBy = [ "mailman.service" "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web qcluster";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web qcluster";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
@ -279,8 +303,9 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "Trigger minutely Hyperkitty events";
|
||||
startAt = "minutely";
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs minutely";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs minutely";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
@ -290,8 +315,9 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "Trigger quarter-hourly Hyperkitty events";
|
||||
startAt = "*:00/15";
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs quarter_hourly";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs quarter_hourly";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
@ -301,8 +327,9 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "Trigger hourly Hyperkitty events";
|
||||
startAt = "hourly";
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs hourly";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs hourly";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
@ -312,8 +339,9 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "Trigger daily Hyperkitty events";
|
||||
startAt = "daily";
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs daily";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs daily";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
@ -323,8 +351,9 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "Trigger weekly Hyperkitty events";
|
||||
startAt = "weekly";
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs weekly";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs weekly";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
@ -334,8 +363,9 @@ in {
|
|||
inherit (cfg.hyperkitty) enable;
|
||||
description = "Trigger yearly Hyperkitty events";
|
||||
startAt = "yearly";
|
||||
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs yearly";
|
||||
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs yearly";
|
||||
User = cfg.webUser;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
|
|
|
@ -1,508 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 1998-2019 by the Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of Postorius.
|
||||
#
|
||||
# Postorius is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Postorius is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Postorius. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Django settings for postorius project.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.9/ref/settings/
|
||||
"""
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
# Compatibility with Bootstrap 3
|
||||
from django.contrib.messages import constants as messages
|
||||
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
|
||||
ADMINS = (
|
||||
#('Admin', 'webmaster@example.com'),
|
||||
)
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
||||
# See https://docs.djangoproject.com/en/1.8/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = [
|
||||
"localhost", # Archiving API from Mailman, keep it.
|
||||
"127.0.0.1",
|
||||
# Add here all production URLs you may have.
|
||||
@ALLOWED_HOSTS@
|
||||
]
|
||||
|
||||
# Mailman API credentials
|
||||
MAILMAN_REST_API_URL = 'http://localhost:8001'
|
||||
MAILMAN_REST_API_USER = 'restadmin'
|
||||
MAILMAN_REST_API_PASS = 'restpass'
|
||||
MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1')
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'hyperkitty',
|
||||
'postorius',
|
||||
'django_mailman3',
|
||||
# Uncomment the next line to enable the admin:
|
||||
'django.contrib.admin',
|
||||
# Uncomment the next line to enable admin documentation:
|
||||
# 'django.contrib.admindocs',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'django_gravatar',
|
||||
'compressor',
|
||||
'haystack',
|
||||
'django_extensions',
|
||||
'django_q',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'allauth.socialaccount',
|
||||
'django_mailman3.lib.auth.fedora',
|
||||
'allauth.socialaccount.providers.openid',
|
||||
'allauth.socialaccount.providers.github',
|
||||
'allauth.socialaccount.providers.gitlab',
|
||||
'allauth.socialaccount.providers.google',
|
||||
#'allauth.socialaccount.providers.facebook',
|
||||
#'allauth.socialaccount.providers.twitter',
|
||||
'allauth.socialaccount.providers.stackexchange',
|
||||
)
|
||||
|
||||
|
||||
MIDDLEWARE = (
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django_mailman3.middleware.TimezoneMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'urls'
|
||||
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.static',
|
||||
'django.template.context_processors.tz',
|
||||
'django.template.context_processors.csrf',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django_mailman3.context_processors.common',
|
||||
'hyperkitty.context_processors.common',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': '/var/lib/mailman-web/mailman-web.db'
|
||||
}
|
||||
}
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# If you're behind a proxy, use the X-Forwarded-Host header
|
||||
# See https://docs.djangoproject.com/en/1.8/ref/settings/#use-x-forwarded-host
|
||||
# USE_X_FORWARDED_HOST = True
|
||||
|
||||
# And if your proxy does your SSL encoding for you, set SECURE_PROXY_SSL_HEADER
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#secure-proxy-ssl-header
|
||||
# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_SCHEME', 'https')
|
||||
|
||||
# Other security settings
|
||||
# SECURE_SSL_REDIRECT = True
|
||||
# If you set SECURE_SSL_REDIRECT to True, make sure the SECURE_REDIRECT_EXEMPT
|
||||
# contains at least this line:
|
||||
# SECURE_REDIRECT_EXEMPT = [
|
||||
# "archives/api/mailman/.*", # Request from Mailman.
|
||||
# ]
|
||||
# SESSION_COOKIE_SECURE = True
|
||||
# SECURE_CONTENT_TYPE_NOSNIFF = True
|
||||
# SECURE_BROWSER_XSS_FILTER = True
|
||||
# CSRF_COOKIE_SECURE = True
|
||||
# CSRF_COOKIE_HTTPONLY = True
|
||||
# X_FRAME_OPTIONS = 'DENY'
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.9/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
|
||||
|
||||
|
||||
# Absolute path to the directory static files should be collected to.
|
||||
# Don't put anything in this directory yourself; store your static files
|
||||
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
||||
# Example: "/var/www/example.com/static/"
|
||||
STATIC_ROOT = 'static'
|
||||
|
||||
# URL prefix for static files.
|
||||
# Example: "http://example.com/static/", "http://static.example.com/"
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Additional locations of static files
|
||||
STATICFILES_DIRS = (
|
||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
# BASE_DIR + '/static/',
|
||||
)
|
||||
|
||||
# List of finder classes that know how to find static files in
|
||||
# various locations.
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
# Django 1.6+ defaults to a JSON serializer, but it won't work with
|
||||
# django-openid, see
|
||||
# https://bugs.launchpad.net/django-openid-auth/+bug/1252826
|
||||
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
|
||||
|
||||
|
||||
LOGIN_URL = 'account_login'
|
||||
LOGIN_REDIRECT_URL = 'hk_root'
|
||||
LOGOUT_URL = 'account_logout'
|
||||
|
||||
|
||||
# If you enable internal authentication, this is the address that the emails
|
||||
# will appear to be coming from. Make sure you set a valid domain name,
|
||||
# otherwise the emails may get rejected.
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#default-from-email
|
||||
DEFAULT_FROM_EMAIL = "@SERVER_EMAIL@"
|
||||
|
||||
# If you enable email reporting for error messages, this is where those emails
|
||||
# will appear to be coming from. Make sure you set a valid domain name,
|
||||
# otherwise the emails may get rejected.
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-SERVER_EMAIL
|
||||
SERVER_EMAIL = "@SERVER_EMAIL@"
|
||||
|
||||
|
||||
MESSAGE_TAGS = {
|
||||
messages.ERROR: 'danger'
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Social auth
|
||||
#
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'allauth.account.auth_backends.AuthenticationBackend',
|
||||
)
|
||||
|
||||
# Django Allauth
|
||||
ACCOUNT_AUTHENTICATION_METHOD = "username_email"
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
||||
ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"
|
||||
ACCOUNT_UNIQUE_EMAIL = True
|
||||
|
||||
SOCIALACCOUNT_PROVIDERS = {
|
||||
'openid': {
|
||||
'SERVERS': [
|
||||
dict(id='yahoo',
|
||||
name='Yahoo',
|
||||
openid_url='http://me.yahoo.com'),
|
||||
],
|
||||
},
|
||||
'google': {
|
||||
'SCOPE': ['profile', 'email'],
|
||||
'AUTH_PARAMS': {'access_type': 'online'},
|
||||
},
|
||||
'facebook': {
|
||||
'METHOD': 'oauth2',
|
||||
'SCOPE': ['email'],
|
||||
'FIELDS': [
|
||||
'email',
|
||||
'name',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'locale',
|
||||
'timezone',
|
||||
],
|
||||
'VERSION': 'v2.4',
|
||||
},
|
||||
'gitlab': {
|
||||
'GITLAB_URL': 'https://gitlab.com',
|
||||
'SCOPE': ['read_user'],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Gravatar
|
||||
# https://github.com/twaddington/django-gravatar
|
||||
#
|
||||
# Gravatar base url.
|
||||
# GRAVATAR_URL = 'http://cdn.libravatar.org/'
|
||||
# Gravatar base secure https url.
|
||||
# GRAVATAR_SECURE_URL = 'https://seccdn.libravatar.org/'
|
||||
# Gravatar size in pixels.
|
||||
# GRAVATAR_DEFAULT_SIZE = '80'
|
||||
# An image url or one of the following: 'mm', 'identicon', 'monsterid',
|
||||
# 'wavatar', 'retro'.
|
||||
# GRAVATAR_DEFAULT_IMAGE = 'mm'
|
||||
# One of the following: 'g', 'pg', 'r', 'x'.
|
||||
# GRAVATAR_DEFAULT_RATING = 'g'
|
||||
# True to use https by default, False for plain http.
|
||||
# GRAVATAR_DEFAULT_SECURE = True
|
||||
|
||||
# These can be set to override the defaults but are not mandatory:
|
||||
# EMAIL_CONFIRMATION_TEMPLATE = 'postorius/address_confirmation_message.txt'
|
||||
# EMAIL_CONFIRMATION_SUBJECT = 'Confirmation needed'
|
||||
|
||||
#
|
||||
# django-compressor
|
||||
# https://pypi.python.org/pypi/django_compressor
|
||||
#
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/x-scss', '/run/current-system/sw/bin/sassc -t compressed {infile} {outfile}'),
|
||||
('text/x-sass', '/run/current-system/sw/bin/sassc -t compressed {infile} {outfile}'),
|
||||
)
|
||||
# On a production setup, setting COMPRESS_OFFLINE to True will bring a
|
||||
# significant performance improvement, as CSS files will not need to be
|
||||
# recompiled on each requests. It means running an additional "compress"
|
||||
# management command after each code upgrade.
|
||||
# http://django-compressor.readthedocs.io/en/latest/usage/#offline-compression
|
||||
COMPRESS_ENABLED = True
|
||||
COMPRESS_OFFLINE = True
|
||||
|
||||
# Needed for debug mode
|
||||
# INTERNAL_IPS = ('127.0.0.1',)
|
||||
|
||||
|
||||
#
|
||||
# Full-text search engine
|
||||
#
|
||||
HAYSTACK_CONNECTIONS = {
|
||||
'default': {
|
||||
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
|
||||
'PATH': "/var/lib/mailman-web/fulltext_index",
|
||||
# You can also use the Xapian engine, it's faster and more accurate,
|
||||
# but requires another library.
|
||||
# http://django-haystack.readthedocs.io/en/v2.4.1/installing_search_engines.html#xapian
|
||||
# Example configuration for Xapian:
|
||||
#'ENGINE': 'xapian_backend.XapianEngine'
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# REST framework
|
||||
#
|
||||
REST_FRAMEWORK = {
|
||||
'PAGE_SIZE': 10,
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
|
||||
'DEFAULT_FILTER_BACKENDS': (
|
||||
'rest_framework.filters.OrderingFilter',
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Asynchronous tasks
|
||||
#
|
||||
Q_CLUSTER = {
|
||||
'timeout': 300,
|
||||
'save_limit': 100,
|
||||
'orm': 'default',
|
||||
}
|
||||
|
||||
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple',
|
||||
},
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
},
|
||||
'file':{
|
||||
'level': 'INFO',
|
||||
#'class': 'logging.handlers.RotatingFileHandler',
|
||||
'class': 'logging.handlers.WatchedFileHandler',
|
||||
'filename': 'mailman-web.log',
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
'handlers': ['console', 'file'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
'django.request': {
|
||||
'handlers': ['console', 'mail_admins', 'file'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
'postorius': {
|
||||
'handlers': ['console', 'file'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
'django': {
|
||||
'handlers': ['file'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
'hyperkitty': {
|
||||
'handlers': ['file'],
|
||||
'level': 'DEBUG',
|
||||
'propagate': True,
|
||||
},
|
||||
},
|
||||
'formatters': {
|
||||
'simple': {
|
||||
'format': '%(levelname)s: %(message)s'
|
||||
},
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(process)d %(name)s %(message)s'
|
||||
},
|
||||
'simple': {
|
||||
'format': '%(levelname)s %(message)s'
|
||||
},
|
||||
},
|
||||
#'root': {
|
||||
# 'handlers': ['file'],
|
||||
# 'level': 'INFO',
|
||||
#},
|
||||
}
|
||||
|
||||
|
||||
POSTORIUS_TEMPLATE_BASE_URL = "http://localhost:8000"
|
||||
|
||||
|
||||
# Using the cache infrastructure can significantly improve performance on a
|
||||
# production setup. This is an example with a local Memcached server.
|
||||
#CACHES = {
|
||||
# 'default': {
|
||||
# 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
|
||||
# 'LOCATION': '127.0.0.1:11211',
|
||||
# }
|
||||
#}
|
||||
|
||||
|
||||
# When DEBUG is True, don't actually send emails to the SMTP server, just store
|
||||
# them in a directory. This way you won't accidentally spam your mailing-lists
|
||||
# while you're fiddling with the code.
|
||||
if DEBUG == True:
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
|
||||
EMAIL_FILE_PATH = '/tmp/hyperkitty-emails'
|
||||
|
||||
|
||||
#
|
||||
# HyperKitty-specific
|
||||
#
|
||||
# Only display mailing-lists from the same virtual host as the webserver
|
||||
FILTER_VHOST = False
|
||||
# Disable singleton locking for Django-Q tasks.
|
||||
HYPERKITTY_DISABLE_SINGLETON_TASKS = False
|
||||
# Maximum time between two task runs with same function and arguments.
|
||||
# This setting is mostly meant for Mailman Developers and should be used
|
||||
# with caution.
|
||||
# Default set to 10mins.
|
||||
HYPERKITTY_TASK_LOCK_TIMEOUT = 10 * 60
|
||||
|
||||
|
||||
try:
|
||||
from settings_local import *
|
||||
except ImportError:
|
||||
pass
|
|
@ -1,34 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 1998-2019 by the Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of Postorius.
|
||||
#
|
||||
# Postorius is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Postorius is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Postorius. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from django.conf.urls import include, url
|
||||
from django.contrib import admin
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import RedirectView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', RedirectView.as_view(url=reverse_lazy('hk_root'))),
|
||||
url(r'^hyperkitty/', include('hyperkitty.urls')),
|
||||
url(r'^postorius/', include('postorius.urls')),
|
||||
url(r'', include('django_mailman3.urls')),
|
||||
url(r'^accounts/', include('allauth.urls')),
|
||||
# Django admin
|
||||
url(r'^admin/', admin.site.urls),
|
||||
]
|
|
@ -1,38 +1,39 @@
|
|||
{ stdenv, python, hyperkitty, postorius, buildPythonPackage, isPy3k
|
||||
, serverEMail ? "postmaster@example.org"
|
||||
, archiverKey ? "SecretArchiverAPIKey"
|
||||
, allowedHosts ? []
|
||||
{ buildPythonPackage, lib, fetchgit, isPy3k
|
||||
, git, makeWrapper, sassc, hyperkitty, postorius, whoosh
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
allowedHostsString = stdenv.lib.concatMapStringsSep ", " (x: "\""+x+"\"") allowedHosts;
|
||||
|
||||
in
|
||||
|
||||
# We turn those Djando configuration files into a make-shift Python library so
|
||||
# that Nix users can use this package as a part of their buildInputs to import
|
||||
# the code. Also, this package implicitly provides an environment in which the
|
||||
# Django app can be run.
|
||||
|
||||
buildPythonPackage {
|
||||
name = "mailman-web-0";
|
||||
buildPythonPackage rec {
|
||||
pname = "mailman-web-unstable";
|
||||
version = "2019-09-29";
|
||||
disabled = !isPy3k;
|
||||
|
||||
propagatedBuildInputs = [ hyperkitty postorius ];
|
||||
src = fetchgit {
|
||||
url = "https://gitlab.com/mailman/mailman-web";
|
||||
rev = "d17203b4d6bdc71c2b40891757f57a32f3de53d5";
|
||||
sha256 = "124cxr4vfi1ibgxygk4l74q4fysx0a6pga1kk9p5wq2yvzwg9z3n";
|
||||
leaveDotGit = true;
|
||||
};
|
||||
|
||||
unpackPhase = ":";
|
||||
buildPhase = ":";
|
||||
setuptoolsCheckPhase = ":";
|
||||
|
||||
installPhase = ''
|
||||
d=$out/${python.sitePackages}
|
||||
install -D -m 444 ${./urls.py} $d/urls.py
|
||||
install -D -m 444 ${./wsgi.py} $d/wsgi.py
|
||||
substitute ${./settings.py} $d/settings.py \
|
||||
--subst-var-by SERVER_EMAIL '${serverEMail}' \
|
||||
--subst-var-by ARCHIVER_KEY '${archiverKey}' \
|
||||
--subst-var-by ALLOWED_HOSTS '${allowedHostsString}'
|
||||
chmod 444 $d/settings.py
|
||||
# This is just so people installing from pip also get uwsgi
|
||||
# installed, AFAICT.
|
||||
postPatch = ''
|
||||
sed -i '/^ uwsgi$/d' setup.cfg
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [ git makeWrapper ];
|
||||
propagatedBuildInputs = [ hyperkitty postorius whoosh ];
|
||||
|
||||
# Tries to check runtime configuration.
|
||||
doCheck = false;
|
||||
|
||||
postInstall = ''
|
||||
wrapProgram $out/bin/mailman-web \
|
||||
--suffix PATH : ${lib.makeBinPath [ sassc ]}
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Django project for Mailman 3 web interface";
|
||||
license = licenses.gpl3;
|
||||
maintainers = with maintainers; [ qyliss ];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
"""
|
||||
WSGI config for meh project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
|
||||
|
||||
application = get_wsgi_application()
|
|
@ -15325,6 +15325,8 @@ in
|
|||
|
||||
mailman-rss = callPackage ../development/python-modules/mailman-rss { };
|
||||
|
||||
mailman-web = with python3.pkgs; toPythonApplication mailman-web;
|
||||
|
||||
mattermost = callPackage ../servers/mattermost { };
|
||||
matterircd = callPackage ../servers/mattermost/matterircd.nix { };
|
||||
matterbridge = callPackage ../servers/matterbridge { };
|
||||
|
|
Loading…
Reference in a new issue