diff --git a/README.md b/README.md index 543651f..b2c1e44 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Weblate is a libre web-based translation tool with tight version control integration. It provides two user interfaces, propagation of translations across components, quality checks and automatic linking to source files. -**Shipped version:** 3.11.3 +**Shipped version:** 4.3.1 ## Screenshots diff --git a/check_process b/check_process index 1024265..84b8ca1 100644 --- a/check_process +++ b/check_process @@ -19,9 +19,7 @@ setup_private=1 setup_public=1 upgrade=1 - upgrade=1 from_commit=565bfc66719f55b9c6a03cba8ac9991111992c9b - upgrade=1 from_commit=73a808f7a93e063e652533244fa1657fbc41c4f3 - upgrade=1 from_commit=31b82950959699478f2372259116b6d117a85d69 + upgrade=1 from_commit=cef22ac5634565cecd2d8545229efe3fe79d85bc backup_restore=1 multi_instance=1 port_already_use=0 @@ -33,12 +31,6 @@ Email=jean-baptiste@holcroft.fr Notification=all ;;; Upgrade options - ; commit=565bfc66719f55b9c6a03cba8ac9991111992c9b - name=Upgrade from 3.5.1 -manifest_arg=domain=DOMAIN&path=PATH&admin=USER&is_public=1&github_account=fake&github_token=fake - ; commit=73a808f7a93e063e652533244fa1657fbc41c4f3 - name=Upgrade from 3.6.1 -manifest_arg=domain=DOMAIN&path=PATH&admin=USER&is_public=1&github_account=fake&github_token=fake - ; commit=31b82950959699478f2372259116b6d117a85d69 - name=Upgrade from 3.7.0 + ; commit=cef22ac5634565cecd2d8545229efe3fe79d85bc + name=Upgrade from 3.11.3 manifest_arg=domain=DOMAIN&path=PATH&admin=USER&is_public=1&github_account=fake&github_token=fake diff --git a/conf/celery-weblate b/conf/celery-weblate index cc9014c..4624a9b 100644 --- a/conf/celery-weblate +++ b/conf/celery-weblate @@ -1,5 +1,5 @@ # Name of nodes to start -CELERYD_NODES="celery notify search memory backup translate" +CELERYD_NODES="celery notify memory backup translate" # Absolute or relative path to the 'celery' command: CELERY_BIN="__FINALPATH__/venv/bin/celery" @@ -10,11 +10,10 @@ CELERY_APP="weblate.utils" # Extra command-line arguments to the worker, # increase concurency if you get weblate.E019 -CELERYD_OPTS="--beat:celery --concurrency:celery=4 --queues:celery=celery --prefetch-multiplier:celery=4 \ - --concurrency:notify=4 --queues:notify=notify --prefetch-multiplier:notify=10 \ - --concurrency:search=1 --queues:search=search --prefetch-multiplier:search=2000 \ - --concurrency:memory=1 --queues:memory=memory --prefetch-multiplier:memory=2000 \ - --concurrency:translate=4 --queues:translate=translate --prefetch-multiplier:translate=4 \ +CELERYD_OPTS="--beat:celery --queues:celery=celery --prefetch-multiplier:celery=4 \ + --queues:notify=notify --prefetch-multiplier:notify=10 \ + --queues:memory=memory --prefetch-multiplier:memory=10 \ + --queues:translate=translate --prefetch-multiplier:translate=4 \ --concurrency:backup=1 --queues:backup=backup --prefetch-multiplier:backup=2" # Logging configuration diff --git a/conf/settings.4.1.1.py b/conf/settings.4.1.1.py new file mode 100644 index 0000000..52fe16b --- /dev/null +++ b/conf/settings.4.1.1.py @@ -0,0 +1,877 @@ +# +# Copyright © 2012 - 2020 Michal Čihař +# +# This file is part of Weblate +# +# This program 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. +# +# This program 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 this program. If not, see . +# + + +import os +import platform +from logging.handlers import SysLogHandler + +# +# Django settings for Weblate project. +# + +DEBUG = False + +ADMINS = ( + ('__ADMIN__', '__ADMINMAIL__'), +) + +MANAGERS = ADMINS + +DATABASES = { + "default": { + # Use "postgresql" or "mysql". + "ENGINE": "django.db.backends.postgresql", + # Database name. + "NAME": "__NAME__", + # Database user. + "USER": "__NAME__", + # Database password. + "PASSWORD": "__DB_PWD__", + # Set to empty string for localhost. + "HOST": "127.0.0.1", + # Set to empty string for default. + "PORT": "", + # Customizations for databases. + "OPTIONS": { + # In case of using an older MySQL server, + # which has MyISAM as a default storage + # "init_command": "SET storage_engine=INNODB", + # Uncomment for MySQL older than 5.7: + # "init_command": "SET sql_mode='STRICT_TRANS_TABLES'", + # Set emoji capable charset for MySQL: + # "charset": "utf8mb4", + # Change connection timeout in case you get MySQL gone away error: + # "connect_timeout": 28800, + }, + } +} + +BASE_DIR = "__FINALPATH__" + +# Data directory +DATA_DIR = os.path.join(BASE_DIR, "data") + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# In a Windows environment this must be set to your system time zone. +TIME_ZONE = "UTC" + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = "en-us" + +LANGUAGES = ( + ("ar", "العربية"), + ("az", "Azərbaycan"), + ("be", "Беларуская"), + ("be@latin", "Biełaruskaja"), + ("bg", "Български"), + ("br", "Brezhoneg"), + ("ca", "Català"), + ("cs", "Čeština"), + ("da", "Dansk"), + ("de", "Deutsch"), + ("en", "English"), + ("el", "Ελληνικά"), + ("en-gb", "English (United Kingdom)"), + ("es", "Español"), + ("fi", "Suomi"), + ("fr", "Français"), + ("gl", "Galego"), + ("he", "עברית"), + ("hu", "Magyar"), + ("hr", "Hrvatski"), + ("id", "Indonesia"), + ("it", "Italiano"), + ("ja", "日本語"), + ("kab", "Taqbaylit"), + ("kk", "Қазақ тілі"), + ("ko", "한국어"), + ("nb", "Norsk bokmål"), + ("nl", "Nederlands"), + ("pl", "Polski"), + ("pt", "Português"), + ("pt-br", "Português brasileiro"), + ("ru", "Русский"), + ("sk", "Slovenčina"), + ("sl", "Slovenščina"), + ("sq", "Shqip"), + ("sr", "Српски"), + ("sv", "Svenska"), + ("tr", "Türkçe"), + ("uk", "Українська"), + ("zh-hans", "简体字"), + ("zh-hant", "正體字"), +) + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale. +USE_L10N = True + +# If you set this to False, Django will not use timezone-aware datetimes. +USE_TZ = True + +# URL prefix to use, please see documentation for more details +URL_PREFIX = "__PATHURL__" + +# Absolute filesystem path to the directory that will hold user-uploaded files. +MEDIA_ROOT = os.path.join(DATA_DIR, "media") + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +MEDIA_URL = f"{URL_PREFIX}/media/" + +# 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. +STATIC_ROOT = os.path.join(DATA_DIR, "static") + +# URL prefix for static files. +STATIC_URL = f"{URL_PREFIX}/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. +) + +# 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", + "compressor.finders.CompressorFinder", +) + +# Make this unique, and don't share it with anybody. +# You can generate it using weblate/examples/generate-secret-key +SECRET_KEY = "__KEY__" # noqa + +_TEMPLATE_LOADERS = [ + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", +] +if not DEBUG: + _TEMPLATE_LOADERS = [("django.template.loaders.cached.Loader", _TEMPLATE_LOADERS)] +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "OPTIONS": { + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.request", + "django.template.context_processors.csrf", + "django.contrib.messages.context_processors.messages", + "weblate.trans.context_processors.weblate_context", + ], + "loaders": _TEMPLATE_LOADERS, + }, + } +] + + +# GitHub username for sending pull requests. +# Please see the documentation for more details. +GITHUB_USERNAME = None + +# GitLab username for sending merge requests. +# Please see the documentation for more details. +GITLAB_USERNAME = None + +# Authentication configuration +AUTHENTICATION_BACKENDS = ( + "social_core.backends.email.EmailAuth", + # "social_core.backends.google.GoogleOAuth2", + # "social_core.backends.github.GithubOAuth2", + # "social_core.backends.bitbucket.BitbucketOAuth", + # "social_core.backends.suse.OpenSUSEOpenId", + # "social_core.backends.ubuntu.UbuntuOpenId", + # "social_core.backends.fedora.FedoraOpenId", + # "social_core.backends.facebook.FacebookOAuth2", + "weblate.accounts.auth.WeblateUserBackend", +) + +# Custom user model +AUTH_USER_MODEL = "weblate_auth.User" + +# Social auth backends setup +SOCIAL_AUTH_GITHUB_KEY = "" +SOCIAL_AUTH_GITHUB_SECRET = "" +SOCIAL_AUTH_GITHUB_SCOPE = ["user:email"] + +SOCIAL_AUTH_BITBUCKET_KEY = "" +SOCIAL_AUTH_BITBUCKET_SECRET = "" +SOCIAL_AUTH_BITBUCKET_VERIFIED_EMAILS_ONLY = True + +SOCIAL_AUTH_FACEBOOK_KEY = "" +SOCIAL_AUTH_FACEBOOK_SECRET = "" +SOCIAL_AUTH_FACEBOOK_SCOPE = ["email", "public_profile"] +SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {"fields": "id,name,email"} +SOCIAL_AUTH_FACEBOOK_API_VERSION = "3.1" + +SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "" +SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "" + +# Social auth settings +SOCIAL_AUTH_PIPELINE = ( + "social_core.pipeline.social_auth.social_details", + "social_core.pipeline.social_auth.social_uid", + "social_core.pipeline.social_auth.auth_allowed", + "social_core.pipeline.social_auth.social_user", + "weblate.accounts.pipeline.store_params", + "weblate.accounts.pipeline.verify_open", + "social_core.pipeline.user.get_username", + "weblate.accounts.pipeline.require_email", + "social_core.pipeline.mail.mail_validation", + "weblate.accounts.pipeline.revoke_mail_code", + "weblate.accounts.pipeline.ensure_valid", + "weblate.accounts.pipeline.remove_account", + "social_core.pipeline.social_auth.associate_by_email", + "weblate.accounts.pipeline.reauthenticate", + "weblate.accounts.pipeline.verify_username", + "social_core.pipeline.user.create_user", + "social_core.pipeline.social_auth.associate_user", + "social_core.pipeline.social_auth.load_extra_data", + "weblate.accounts.pipeline.cleanup_next", + "weblate.accounts.pipeline.user_full_name", + "weblate.accounts.pipeline.store_email", + "weblate.accounts.pipeline.notify_connect", + "weblate.accounts.pipeline.password_reset", +) +SOCIAL_AUTH_DISCONNECT_PIPELINE = ( + "social_core.pipeline.disconnect.allowed_to_disconnect", + "social_core.pipeline.disconnect.get_entries", + "social_core.pipeline.disconnect.revoke_tokens", + "weblate.accounts.pipeline.cycle_session", + "weblate.accounts.pipeline.adjust_primary_mail", + "weblate.accounts.pipeline.notify_disconnect", + "social_core.pipeline.disconnect.disconnect", + "weblate.accounts.pipeline.cleanup_next", +) + +# Custom authentication strategy +SOCIAL_AUTH_STRATEGY = "weblate.accounts.strategy.WeblateStrategy" + +# Raise exceptions so that we can handle them later +SOCIAL_AUTH_RAISE_EXCEPTIONS = True + +SOCIAL_AUTH_EMAIL_VALIDATION_FUNCTION = "weblate.accounts.pipeline.send_validation" +SOCIAL_AUTH_EMAIL_VALIDATION_URL = "{0}/accounts/email-sent/".format(URL_PREFIX) +SOCIAL_AUTH_LOGIN_ERROR_URL = "{0}/accounts/login/".format(URL_PREFIX) +SOCIAL_AUTH_EMAIL_FORM_URL = "{0}/accounts/email/".format(URL_PREFIX) +SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = "{0}/accounts/profile/#account".format( + URL_PREFIX +) +SOCIAL_AUTH_PROTECTED_USER_FIELDS = ("email",) +SOCIAL_AUTH_SLUGIFY_USERNAMES = True +SOCIAL_AUTH_SLUGIFY_FUNCTION = "weblate.accounts.pipeline.slugify_username" + +# Password validation configuration +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" # noqa: E501, pylint: disable=line-too-long + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + "OPTIONS": {"min_length": 10}, + }, + {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, + {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, + {"NAME": "weblate.accounts.password_validation.CharsPasswordValidator"}, + {"NAME": "weblate.accounts.password_validation.PastPasswordsValidator"}, + # Optional password strength validation by django-zxcvbn-password + # { + # "NAME": "zxcvbn_password.ZXCVBNValidator", + # "OPTIONS": { + # "min_score": 3, + # "user_attributes": ("username", "email", "full_name") + # } + # }, +] + +# Allow new user registrations +REGISTRATION_OPEN = True + +# Shortcut for login required setting +REQUIRE_LOGIN = False + +# Middleware +MIDDLEWARE = [ + "weblate.middleware.ProxyMiddleware", + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "weblate.accounts.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "social_django.middleware.SocialAuthExceptionMiddleware", + "weblate.accounts.middleware.RequireLoginMiddleware", + "weblate.api.middleware.ThrottlingMiddleware", + "weblate.middleware.SecurityMiddleware", +] + +ROOT_URLCONF = "weblate.urls" + +# Django and Weblate apps +INSTALLED_APPS = [ + # Weblate apps on top to override Django locales and templates + "weblate.addons", + "weblate.auth", + "weblate.checks", + "weblate.formats", + "weblate.glossary", + "weblate.machinery", + "weblate.trans", + "weblate.lang", + "weblate.langdata", + "weblate.memory", + "weblate.screenshots", + "weblate.fonts", + "weblate.accounts", + "weblate.utils", + "weblate.vcs", + "weblate.wladmin", + "weblate", + # Optional: Git exporter + "weblate.gitexport", + # Standard Django modules + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.admin.apps.SimpleAdminConfig", + "django.contrib.admindocs", + "django.contrib.sitemaps", + "django.contrib.humanize", + # Third party Django modules + "social_django", + "crispy_forms", + "compressor", + "rest_framework", + "rest_framework.authtoken", + "django_filters", +] + +# Custom exception reporter to include some details +DEFAULT_EXCEPTION_REPORTER_FILTER = "weblate.trans.debug.WeblateExceptionReporterFilter" + +# Default logging of Weblate messages +# - to syslog in production (if available) +# - otherwise to console +# - you can also choose "logfile" to log into separate file +# after configuring it below + +# Detect if we can connect to syslog +HAVE_SYSLOG = False +if platform.system() != "Windows": + try: + handler = SysLogHandler(address="/dev/log", facility=SysLogHandler.LOG_LOCAL2) + handler.close() + HAVE_SYSLOG = True + except IOError: + HAVE_SYSLOG = False + +if DEBUG or not HAVE_SYSLOG: + DEFAULT_LOG = "console" +else: + DEFAULT_LOG = "syslog" + +# 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/stable/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + "version": 1, + "disable_existing_loggers": True, + "filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}}, + "formatters": { + "syslog": {"format": "weblate[%(process)d]: %(levelname)s %(message)s"}, + "simple": {"format": "%(levelname)s %(message)s"}, + "logfile": {"format": "%(asctime)s %(levelname)s %(message)s"}, + "django.server": { + "()": "django.utils.log.ServerFormatter", + "format": "[%(server_time)s] %(message)s", + }, + }, + "handlers": { + "mail_admins": { + "level": "ERROR", + "filters": ["require_debug_false"], + "class": "django.utils.log.AdminEmailHandler", + "include_html": True, + }, + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "simple", + }, + "django.server": { + "level": "INFO", + "class": "logging.StreamHandler", + "formatter": "django.server", + }, + "syslog": { + "level": "DEBUG", + "class": "logging.handlers.SysLogHandler", + "formatter": "syslog", + "address": "/dev/log", + "facility": SysLogHandler.LOG_LOCAL2, + }, + # Logging to a file + # "logfile": { + # "level":"DEBUG", + # "class":"logging.handlers.RotatingFileHandler", + # "filename": "/var/log/weblate/weblate.log", + # "maxBytes": 100000, + # "backupCount": 3, + # "formatter": "logfile", + # }, + }, + "loggers": { + "django.request": { + "handlers": ["mail_admins", DEFAULT_LOG], + "level": "ERROR", + "propagate": True, + }, + "django.server": { + "handlers": ["django.server"], + "level": "INFO", + "propagate": False, + }, + # Logging database queries + # "django.db.backends": { + # "handlers": [DEFAULT_LOG], + # "level": "DEBUG", + # }, + "weblate": {"handlers": [DEFAULT_LOG], "level": "DEBUG"}, + # Logging search operations + "weblate.search": {"handlers": [DEFAULT_LOG], "level": "INFO"}, + # Logging VCS operations + "weblate.vcs": {"handlers": [DEFAULT_LOG], "level": "WARNING"}, + # Python Social Auth + "social": {"handlers": [DEFAULT_LOG], "level": "DEBUG" if DEBUG else "WARNING"}, + # Django Authentication Using LDAP + "django_auth_ldap": { + "level": "DEBUG" if DEBUG else "WARNING", + "handlers": [DEFAULT_LOG], + }, + }, +} + +# Remove syslog setup if it's not present +if not HAVE_SYSLOG: + del LOGGING["handlers"]["syslog"] + +# List of machine translations +# MT_SERVICES = ( +# "weblate.machinery.apertium.ApertiumAPYTranslation", +# "weblate.machinery.baidu.BaiduTranslation", +# "weblate.machinery.deepl.DeepLTranslation", +# "weblate.machinery.glosbe.GlosbeTranslation", +# "weblate.machinery.google.GoogleTranslation", +# "weblate.machinery.googlev3.GoogleV3Translation", +# "weblate.machinery.microsoft.MicrosoftCognitiveTranslation", +# "weblate.machinery.microsoftterminology.MicrosoftTerminologyService", +# "weblate.machinery.mymemory.MyMemoryTranslation", +# "weblate.machinery.netease.NeteaseSightTranslation", +# "weblate.machinery.tmserver.AmagamaTranslation", +# "weblate.machinery.tmserver.TMServerTranslation", +# "weblate.machinery.yandex.YandexTranslation", +# "weblate.machinery.saptranslationhub.SAPTranslationHub", +# "weblate.machinery.youdao.YoudaoTranslation", +# "weblate.machinery.weblatetm.WeblateTranslation", +# "weblate.memory.machine.WeblateMemory", +# ) + +# Machine translation API keys + +# URL of the Apertium APy server +MT_APERTIUM_APY = None + +# DeepL API key +MT_DEEPL_KEY = None + +# Microsoft Cognitive Services Translator API, register at +# https://portal.azure.com/ +MT_MICROSOFT_COGNITIVE_KEY = None +MT_MICROSOFT_REGION = None + +# MyMemory identification email, see +# https://mymemory.translated.net/doc/spec.php +MT_MYMEMORY_EMAIL = None + +# Optional MyMemory credentials to access private translation memory +MT_MYMEMORY_USER = None +MT_MYMEMORY_KEY = None + +# Google API key for Google Translate API v2 +MT_GOOGLE_KEY = None + +# Google Translate API3 credentials and project id +MT_GOOGLE_CREDENTIALS = None +MT_GOOGLE_PROJECT = None + +# Baidu app key and secret +MT_BAIDU_ID = None +MT_BAIDU_SECRET = None + +# Youdao Zhiyun app key and secret +MT_YOUDAO_ID = None +MT_YOUDAO_SECRET = None + +# Netease Sight (Jianwai) app key and secret +MT_NETEASE_KEY = None +MT_NETEASE_SECRET = None + +# API key for Yandex Translate API +MT_YANDEX_KEY = None + +# tmserver URL +MT_TMSERVER = None + +# SAP Translation Hub +MT_SAP_BASE_URL = None +MT_SAP_SANDBOX_APIKEY = None +MT_SAP_USERNAME = None +MT_SAP_PASSWORD = None +MT_SAP_USE_MT = True + +# Title of site to use +SITE_TITLE = "Weblate" + +# Whether site uses https +ENABLE_HTTPS = False + +# Use HTTPS when creating redirect URLs for social authentication, see +# documentation for more details: +# https://python-social-auth-docs.readthedocs.io/en/latest/configuration/settings.html#processing-redirects-and-urlopen +SOCIAL_AUTH_REDIRECT_IS_HTTPS = ENABLE_HTTPS + +# Make CSRF cookie HttpOnly, see documentation for more details: +# https://docs.djangoproject.com/en/1.11/ref/settings/#csrf-cookie-httponly +CSRF_COOKIE_HTTPONLY = True +CSRF_COOKIE_SECURE = ENABLE_HTTPS +# Store CSRF token in session +CSRF_USE_SESSIONS = True +# Customize CSRF failure view +CSRF_FAILURE_VIEW = "weblate.trans.views.error.csrf_failure" +SESSION_COOKIE_SECURE = ENABLE_HTTPS +SESSION_COOKIE_HTTPONLY = True +# SSL redirect +SECURE_SSL_REDIRECT = ENABLE_HTTPS +# Sent referrrer only for same origin links +SECURE_REFERRER_POLICY = "same-origin" +# SSL redirect URL exemption list +SECURE_REDIRECT_EXEMPT = (r"healthz/$",) # Allowing HTTP access to health check +# Session cookie age (in seconds) +SESSION_COOKIE_AGE = 1209600 +# Increase allowed upload size +DATA_UPLOAD_MAX_MEMORY_SIZE = 50000000 + +# Apply session coookie settings to language cookie as ewll +LANGUAGE_COOKIE_SECURE = SESSION_COOKIE_SECURE +LANGUAGE_COOKIE_HTTPONLY = SESSION_COOKIE_HTTPONLY +LANGUAGE_COOKIE_AGE = SESSION_COOKIE_AGE * 10 + +# Some security headers +SECURE_BROWSER_XSS_FILTER = True +X_FRAME_OPTIONS = "DENY" +SECURE_CONTENT_TYPE_NOSNIFF = True + +# Optionally enable HSTS +SECURE_HSTS_SECONDS = 31536000 if ENABLE_HTTPS else 0 +SECURE_HSTS_PRELOAD = ENABLE_HTTPS +SECURE_HSTS_INCLUDE_SUBDOMAINS = False + +# URL of login +LOGIN_URL = "{0}/accounts/login/".format(URL_PREFIX) + +# URL of logout +LOGOUT_URL = "{0}/accounts/logout/".format(URL_PREFIX) + +# Default location for login +LOGIN_REDIRECT_URL = "{0}/".format(URL_PREFIX) + +# Anonymous user name +ANONYMOUS_USER_NAME = "anonymous" + +# Reverse proxy settings +IP_PROXY_HEADER = "HTTP_X_FORWARDED_FOR" +IP_BEHIND_REVERSE_PROXY = False +IP_PROXY_OFFSET = 0 + +# Sending HTML in mails +EMAIL_SEND_HTML = True + +# Subject of emails includes site title +EMAIL_SUBJECT_PREFIX = "[{0}] ".format(SITE_TITLE) + +# Enable remote hooks +ENABLE_HOOKS = True + +# Number of nearby messages to show in each direction +NEARBY_MESSAGES = 5 + +# By default the length of a given translation is limited to the length of +# the source string * 10 characters. Set this option to False to allow longer +# translations (up to 10.000 characters) +LIMIT_TRANSLATION_LENGTH_BY_SOURCE_LENGTH = True + +# Use simple language codes for default language/country combinations +SIMPLIFY_LANGUAGES = True + +# Render forms using bootstrap +CRISPY_TEMPLATE_PACK = "bootstrap3" + +# List of quality checks +# CHECK_LIST = ( +# "weblate.checks.same.SameCheck", +# "weblate.checks.chars.BeginNewlineCheck", +# "weblate.checks.chars.EndNewlineCheck", +# "weblate.checks.chars.BeginSpaceCheck", +# "weblate.checks.chars.EndSpaceCheck", +# "weblate.checks.chars.DoubleSpaceCheck", +# "weblate.checks.chars.EndStopCheck", +# "weblate.checks.chars.EndColonCheck", +# "weblate.checks.chars.EndQuestionCheck", +# "weblate.checks.chars.EndExclamationCheck", +# "weblate.checks.chars.EndEllipsisCheck", +# "weblate.checks.chars.EndSemicolonCheck", +# "weblate.checks.chars.MaxLengthCheck", +# "weblate.checks.chars.KashidaCheck", +# "weblate.checks.chars.PuctuationSpacingCheck", +# "weblate.checks.format.PythonFormatCheck", +# "weblate.checks.format.PythonBraceFormatCheck", +# "weblate.checks.format.PHPFormatCheck", +# "weblate.checks.format.CFormatCheck", +# "weblate.checks.format.PerlFormatCheck", +# "weblate.checks.format.JavaScriptFormatCheck", +# "weblate.checks.format.CSharpFormatCheck", +# "weblate.checks.format.JavaFormatCheck", +# "weblate.checks.format.JavaMessageFormatCheck", +# "weblate.checks.format.PercentPlaceholdersCheck", +# "weblate.checks.format.I18NextInterpolationCheck", +# "weblate.checks.angularjs.AngularJSInterpolationCheck", +# "weblate.checks.qt.QtFormatCheck", +# "weblate.checks.qt.QtPluralCheck", +# "weblate.checks.ruby.RubyFormatCheck", +# "weblate.checks.consistency.PluralsCheck", +# "weblate.checks.consistency.SamePluralsCheck", +# "weblate.checks.consistency.ConsistencyCheck", +# "weblate.checks.consistency.TranslatedCheck", +# "weblate.checks.chars.EscapedNewlineCountingCheck", +# "weblate.checks.chars.NewLineCountCheck", +# "weblate.checks.markup.BBCodeCheck", +# "weblate.checks.chars.ZeroWidthSpaceCheck", +# "weblate.checks.render.MaxSizeCheck", +# "weblate.checks.markup.XMLValidityCheck", +# "weblate.checks.markup.XMLTagsCheck", +# "weblate.checks.markup.MarkdownRefLinkCheck", +# "weblate.checks.markup.MarkdownLinkCheck", +# "weblate.checks.markup.MarkdownSyntaxCheck", +# "weblate.checks.markup.URLCheck", +# "weblate.checks.markup.SafeHTMLCheck", +# "weblate.checks.placeholders.PlaceholderCheck", +# "weblate.checks.placeholders.RegexCheck", +# "weblate.checks.duplicate.DuplicateCheck", +# "weblate.checks.source.OptionalPluralCheck", +# "weblate.checks.source.EllipsisCheck", +# "weblate.checks.source.MultipleFailingCheck", +# "weblate.checks.source.LongUntranslatedCheck", +# "weblate.checks.format.MultipleUnnamedFormatsCheck", +# ) + +# List of automatic fixups +# AUTOFIX_LIST = ( +# "weblate.trans.autofixes.whitespace.SameBookendingWhitespace", +# "weblate.trans.autofixes.chars.ReplaceTrailingDotsWithEllipsis", +# "weblate.trans.autofixes.chars.RemoveZeroSpace", +# "weblate.trans.autofixes.chars.RemoveControlChars", +# ) + +# List of enabled addons +# WEBLATE_ADDONS = ( +# "weblate.addons.gettext.GenerateMoAddon", +# "weblate.addons.gettext.UpdateLinguasAddon", +# "weblate.addons.gettext.UpdateConfigureAddon", +# "weblate.addons.gettext.MsgmergeAddon", +# "weblate.addons.gettext.GettextCustomizeAddon", +# "weblate.addons.gettext.GettextAuthorComments", +# "weblate.addons.cleanup.CleanupAddon", +# "weblate.addons.consistency.LangaugeConsistencyAddon", +# "weblate.addons.discovery.DiscoveryAddon", +# "weblate.addons.flags.SourceEditAddon", +# "weblate.addons.flags.TargetEditAddon", +# "weblate.addons.flags.SameEditAddon", +# "weblate.addons.flags.BulkEditAddon", +# "weblate.addons.generate.GenerateFileAddon", +# "weblate.addons.json.JSONCustomizeAddon", +# "weblate.addons.properties.PropertiesSortAddon", +# "weblate.addons.git.GitSquashAddon", +# "weblate.addons.removal.RemoveComments", +# "weblate.addons.removal.RemoveSuggestions", +# "weblate.addons.resx.ResxUpdateAddon", +# "weblate.addons.yaml.YAMLCustomizeAddon", +# "weblate.addons.autotranslate.AutoTranslateAddon", +# ) + +# E-mail address that error messages come from. +SERVER_EMAIL = "noreply@__DOMAIN__" + +# Default email address to use for various automated correspondence from +# the site managers. Used for registration emails. +DEFAULT_FROM_EMAIL = "noreply@__ADMINMAIL__" + +# List of URLs your site is supposed to serve +ALLOWED_HOSTS = ["__DOMAIN__"] + +# Configuration for caching +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "redis://127.0.0.1:6379/__REDIS_DB__", + # If redis is running on same host as Weblate, you might + # want to use unix sockets instead: + # "LOCATION": "unix:///var/run/redis/redis.sock?db=1", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + "PARSER_CLASS": "redis.connection.HiredisParser", + "PASSWORD": None, + "CONNECTION_POOL_KWARGS": {}, + }, + "KEY_PREFIX": "weblate", + }, + "avatar": { + "BACKEND": "django.core.cache.backends.filebased.FileBasedCache", + "LOCATION": os.path.join(DATA_DIR, "avatar-cache"), + "TIMEOUT": 86400, + "OPTIONS": {"MAX_ENTRIES": 1000}, + }, +} + +# Store sessions in cache +SESSION_ENGINE = "django.contrib.sessions.backends.cache" +# Store messages in session +MESSAGE_STORAGE = "django.contrib.messages.storage.session.SessionStorage" + +# REST framework settings for API +REST_FRAMEWORK = { + # Use Django's standard `django.contrib.auth` permissions, + # or allow read-only access for unauthenticated users. + "DEFAULT_PERMISSION_CLASSES": [ + # Require authentication for login required sites + "rest_framework.permissions.IsAuthenticated" + if REQUIRE_LOGIN + else "rest_framework.permissions.IsAuthenticatedOrReadOnly" + ], + "DEFAULT_AUTHENTICATION_CLASSES": ( + "rest_framework.authentication.TokenAuthentication", + "weblate.api.authentication.BearerAuthentication", + "rest_framework.authentication.SessionAuthentication", + ), + "DEFAULT_THROTTLE_CLASSES": ( + "weblate.api.throttling.UserRateThrottle", + "weblate.api.throttling.AnonRateThrottle", + ), + "DEFAULT_THROTTLE_RATES": {"anon": "100/day", "user": "5000/hour"}, + "DEFAULT_PAGINATION_CLASS": ("rest_framework.pagination.PageNumberPagination"), + "PAGE_SIZE": 20, + "VIEW_DESCRIPTION_FUNCTION": "weblate.api.views.get_view_description", + "UNAUTHENTICATED_USER": "weblate.auth.models.get_anonymous", +} + +# Require login for all URLs +if REQUIRE_LOGIN: + LOGIN_REQUIRED_URLS = (r"/(.*)$",) + +# In such case you will want to include some of the exceptions +# LOGIN_REQUIRED_URLS_EXCEPTIONS = ( +# rf"{URL_PREFIX}/accounts/(.*)$", # Required for login +# rf"{URL_PREFIX}/admin/login/(.*)$", # Required for admin login +# rf"{URL_PREFIX}/static/(.*)$", # Required for development mode +# rf"{URL_PREFIX}/widgets/(.*)$", # Allowing public access to widgets +# rf"{URL_PREFIX}/data/(.*)$", # Allowing public access to data exports +# rf"{URL_PREFIX}/hooks/(.*)$", # Allowing public access to notification hooks +# rf"{URL_PREFIX}/healthz/$", # Allowing public access to health check +# rf"{URL_PREFIX}/api/(.*)$", # Allowing access to API +# rf"{URL_PREFIX}/js/i18n/$", # JavaScript localization +# rf"{URL_PREFIX}/contact/$", # Optional for contact form +# rf"{URL_PREFIX}/legal/(.*)$", # Optional for legal app +# ) + +# Silence some of the Django system checks +SILENCED_SYSTEM_CHECKS = [ + # We have modified django.contrib.auth.middleware.AuthenticationMiddleware + # as weblate.accounts.middleware.AuthenticationMiddleware + "admin.E408" +] + +# Celery worker configuration for testing +# CELERY_TASK_ALWAYS_EAGER = True +# CELERY_BROKER_URL = "memory://" +# CELERY_TASK_EAGER_PROPAGATES = True +# Celery worker configuration for production +CELERY_TASK_ALWAYS_EAGER = False +CELERY_BROKER_URL = "redis://127.0.0.1:6379" +CELERY_RESULT_BACKEND = CELERY_BROKER_URL + +# Celery settings, it is not recommended to change these +CELERY_WORKER_MAX_MEMORY_PER_CHILD = 200000 +CELERY_BEAT_SCHEDULE_FILENAME = os.path.join(DATA_DIR, "celery", "beat-schedule") +CELERY_TASK_ROUTES = { + "weblate.trans.tasks.auto_translate": {"queue": "translate"}, + "weblate.memory.tasks.*": {"queue": "memory"}, + "weblate.accounts.tasks.notify_*": {"queue": "notify"}, + "weblate.accounts.tasks.send_mails": {"queue": "notify"}, + "weblate.utils.tasks.settings_backup": {"queue": "backup"}, + "weblate.utils.tasks.database_backup": {"queue": "backup"}, + "weblate.wladmin.tasks.backup": {"queue": "backup"}, + "weblate.wladmin.tasks.backup_service": {"queue": "backup"}, +} + +# Enable plain database backups +DATABASE_BACKUP = "plain" + +# Enable auto updating +AUTO_UPDATE = False + +# PGP commits signing +WEBLATE_GPG_IDENTITY = None + +# Third party services integration +MATOMO_SITE_ID = None +MATOMO_URL = None +GOOGLE_ANALYTICS_ID = None +SENTRY_DSN = None +AKISMET_API_KEY = None \ No newline at end of file diff --git a/conf/settings.py b/conf/settings.py index 8f0465a..bac3b5f 100644 --- a/conf/settings.py +++ b/conf/settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ################################################################################ ################################################################################ ## FOR YUNOHOST USERS ## @@ -12,7 +11,6 @@ ################################################################################ ################################################################################ - # # Copyright © 2012 - 2020 Michal Čihař # @@ -32,7 +30,6 @@ # along with this program. If not, see . # -from __future__ import unicode_literals import os import platform @@ -52,29 +49,32 @@ MANAGERS = ADMINS DATABASES = { "default": { - # Use 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + # Use "postgresql" or "mysql". "ENGINE": "django.db.backends.postgresql", - # Database name or path to database file if using sqlite3. + # Database name. "NAME": "__NAME__", - # Database user, not used with sqlite3. + # Database user. "USER": "__NAME__", - # Database password, not used with sqlite3. + # Name of role to alter to set parameters in PostgreSQL, + # use in case role name is different than user used for authentication. + # "ALTER_ROLE": "weblate", + # Database password. "PASSWORD": "__DB_PWD__", - # Set to empty string for localhost. Not used with sqlite3. + # Set to empty string for localhost. "HOST": "127.0.0.1", - # Set to empty string for default. Not used with sqlite3. + # Set to empty string for default. "PORT": "", - # Customizations for databases + # Customizations for databases. "OPTIONS": { # In case of using an older MySQL server, # which has MyISAM as a default storage - # 'init_command': 'SET storage_engine=INNODB', + # "init_command": "SET storage_engine=INNODB", # Uncomment for MySQL older than 5.7: - # 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", + # "init_command": "SET sql_mode='STRICT_TRANS_TABLES'", # Set emoji capable charset for MySQL: - # 'charset': 'utf8mb4', + # "charset": "utf8mb4", # Change connection timeout in case you get MySQL gone away error: - # 'connect_timeout': 28800, + # "connect_timeout": 28800, }, } } @@ -116,8 +116,10 @@ LANGUAGES = ( ("hu", "Magyar"), ("hr", "Hrvatski"), ("id", "Indonesia"), + ("is", "Íslenska"), ("it", "Italiano"), ("ja", "日本語"), + ("kab", "Taqbaylit"), ("kk", "Қазақ тілі"), ("ko", "한국어"), ("nb", "Norsk bokmål"), @@ -158,7 +160,7 @@ MEDIA_ROOT = os.path.join(DATA_DIR, "media") # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash. -MEDIA_URL = "{0}/media/".format(URL_PREFIX) +MEDIA_URL = f"{URL_PREFIX}/media/" # Absolute path to the directory static files should be collected to. # Don't put anything in this directory yourself; store your static files @@ -166,7 +168,7 @@ MEDIA_URL = "{0}/media/".format(URL_PREFIX) STATIC_ROOT = os.path.join(DATA_DIR, "static") # URL prefix for static files. -STATIC_URL = "{0}/static/".format(URL_PREFIX) +STATIC_URL = f"{URL_PREFIX}/static/" # Additional locations of static files STATICFILES_DIRS = ( @@ -185,7 +187,7 @@ STATICFILES_FINDERS = ( # Make this unique, and don't share it with anybody. # You can generate it using weblate/examples/generate-secret-key -SECRET_KEY = "__KEY__" # noqa +SECRET_KEY = "__KEY__" _TEMPLATE_LOADERS = [ "django.template.loaders.filesystem.Loader", @@ -196,7 +198,6 @@ if not DEBUG: TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [os.path.join(BASE_DIR, "weblate", "templates")], "OPTIONS": { "context_processors": [ "django.contrib.auth.context_processors.auth", @@ -216,21 +217,23 @@ TEMPLATES = [ # GitHub username for sending pull requests. # Please see the documentation for more details. GITHUB_USERNAME = "__GITHUBUSER__" +GITHUB_TOKEN = "__GITHUBTOKEN__" # GitLab username for sending merge requests. # Please see the documentation for more details. GITLAB_USERNAME = None +GITLAB_TOKEN = None # Authentication configuration AUTHENTICATION_BACKENDS = ( "social_core.backends.email.EmailAuth", - # 'social_core.backends.google.GoogleOAuth2', - # 'social_core.backends.github.GithubOAuth2', - # 'social_core.backends.bitbucket.BitbucketOAuth', - # 'social_core.backends.suse.OpenSUSEOpenId', - # 'social_core.backends.ubuntu.UbuntuOpenId', - # 'social_core.backends.fedora.FedoraOpenId', - # 'social_core.backends.facebook.FacebookOAuth2', + # "social_core.backends.google.GoogleOAuth2", + # "social_core.backends.github.GithubOAuth2", + # "social_core.backends.bitbucket.BitbucketOAuth", + # "social_core.backends.suse.OpenSUSEOpenId", + # "social_core.backends.ubuntu.UbuntuOpenId", + # "social_core.backends.fedora.FedoraOpenId", + # "social_core.backends.facebook.FacebookOAuth2", "weblate.accounts.auth.WeblateUserBackend", ) @@ -250,7 +253,6 @@ SOCIAL_AUTH_FACEBOOK_KEY = "" SOCIAL_AUTH_FACEBOOK_SECRET = "" SOCIAL_AUTH_FACEBOOK_SCOPE = ["email", "public_profile"] SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {"fields": "id,name,email"} -SOCIAL_AUTH_FACEBOOK_API_VERSION = "3.1" SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "" SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "" @@ -316,7 +318,7 @@ AUTH_PASSWORD_VALIDATORS = [ }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", - "OPTIONS": {"min_length": 6}, + "OPTIONS": {"min_length": 10}, }, {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, @@ -324,10 +326,10 @@ AUTH_PASSWORD_VALIDATORS = [ {"NAME": "weblate.accounts.password_validation.PastPasswordsValidator"}, # Optional password strength validation by django-zxcvbn-password # { - # 'NAME': 'zxcvbn_password.ZXCVBNValidator', - # 'OPTIONS': { - # 'min_score': 3, - # 'user_attributes': ('username', 'email', 'full_name') + # "NAME": "zxcvbn_password.ZXCVBNValidator", + # "OPTIONS": { + # "min_score": 3, + # "user_attributes": ("username", "email", "full_name") # } # }, ] @@ -335,19 +337,23 @@ AUTH_PASSWORD_VALIDATORS = [ # Allow new user registrations REGISTRATION_OPEN = True +# Shortcut for login required setting +REQUIRE_LOGIN = False + # Middleware MIDDLEWARE = [ + "weblate.middleware.RedirectMiddleware", "weblate.middleware.ProxyMiddleware", "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", - "django.middleware.locale.LocaleMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "weblate.accounts.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "social_django.middleware.SocialAuthExceptionMiddleware", "weblate.accounts.middleware.RequireLoginMiddleware", + "weblate.api.middleware.ThrottlingMiddleware", "weblate.middleware.SecurityMiddleware", ] @@ -355,29 +361,16 @@ ROOT_URLCONF = "weblate.urls" # Django and Weblate apps INSTALLED_APPS = [ - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.sites", - "django.contrib.messages", - "django.contrib.staticfiles", - "django.contrib.admin.apps.SimpleAdminConfig", - "django.contrib.admindocs", - "django.contrib.sitemaps", - "django.contrib.humanize", - "social_django", - "crispy_forms", - "compressor", - "rest_framework", - "rest_framework.authtoken", + # Weblate apps on top to override Django locales and templates "weblate.addons", "weblate.auth", "weblate.checks", "weblate.formats", + "weblate.glossary", "weblate.machinery", "weblate.trans", "weblate.lang", - "weblate.langdata", + "weblate_language_data", "weblate.memory", "weblate.screenshots", "weblate.fonts", @@ -388,18 +381,32 @@ INSTALLED_APPS = [ "weblate", # Optional: Git exporter "weblate.gitexport", + # Standard Django modules + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.admin.apps.SimpleAdminConfig", + "django.contrib.admindocs", + "django.contrib.sitemaps", + "django.contrib.humanize", + # Third party Django modules + "social_django", + "crispy_forms", + "compressor", + "rest_framework", + "rest_framework.authtoken", + "django_filters", ] -# Path to locales -LOCALE_PATHS = (os.path.join(BASE_DIR, "weblate", "locale"),) - # Custom exception reporter to include some details DEFAULT_EXCEPTION_REPORTER_FILTER = "weblate.trans.debug.WeblateExceptionReporterFilter" # Default logging of Weblate messages # - to syslog in production (if available) # - otherwise to console -# - you can also choose 'logfile' to log into separate file +# - you can also choose "logfile" to log into separate file # after configuring it below # Detect if we can connect to syslog @@ -416,6 +423,7 @@ if DEBUG or not HAVE_SYSLOG: DEFAULT_LOG = "console" else: DEFAULT_LOG = "syslog" +DEFAULT_LOGLEVEL = "DEBUG" if DEBUG else "INFO" # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to @@ -460,13 +468,13 @@ LOGGING = { "facility": SysLogHandler.LOG_LOCAL2, }, # Logging to a file - # 'logfile': { - # 'level':'DEBUG', - # 'class':'logging.handlers.RotatingFileHandler', - # 'filename': "/var/log/weblate/weblate.log", - # 'maxBytes': 100000, - # 'backupCount': 3, - # 'formatter': 'logfile', + # "logfile": { + # "level":"DEBUG", + # "class":"logging.handlers.RotatingFileHandler", + # "filename": "/var/log/weblate/weblate.log", + # "maxBytes": 100000, + # "backupCount": 3, + # "formatter": "logfile", # }, }, "loggers": { @@ -481,22 +489,17 @@ LOGGING = { "propagate": False, }, # Logging database queries - # 'django.db.backends': { - # 'handlers': [DEFAULT_LOG], - # 'level': 'DEBUG', + # "django.db.backends": { + # "handlers": [DEFAULT_LOG], + # "level": "DEBUG", # }, - "weblate": {"handlers": [DEFAULT_LOG], "level": "DEBUG"}, - # Logging search operations - "weblate.search": {"handlers": [DEFAULT_LOG], "level": "INFO"}, + "weblate": {"handlers": [DEFAULT_LOG], "level": DEFAULT_LOGLEVEL}, # Logging VCS operations - "weblate.vcs": {"handlers": [DEFAULT_LOG], "level": "WARNING"}, + "weblate.vcs": {"handlers": [DEFAULT_LOG], "level": DEFAULT_LOGLEVEL}, # Python Social Auth - "social": {"handlers": [DEFAULT_LOG], "level": "DEBUG" if DEBUG else "WARNING"}, + "social": {"handlers": [DEFAULT_LOG], "level": DEFAULT_LOGLEVEL}, # Django Authentication Using LDAP - "django_auth_ldap": { - "level": "DEBUG" if DEBUG else "WARNING", - "handlers": [DEFAULT_LOG], - }, + "django_auth_ldap": {"handlers": [DEFAULT_LOG], "level": DEFAULT_LOGLEVEL}, }, } @@ -505,24 +508,26 @@ if not HAVE_SYSLOG: del LOGGING["handlers"]["syslog"] # List of machine translations -# MT_SERVICES = ( -# 'weblate.machinery.apertium.ApertiumAPYTranslation', -# 'weblate.machinery.baidu.BaiduTranslation', -# 'weblate.machinery.deepl.DeepLTranslation', -# 'weblate.machinery.glosbe.GlosbeTranslation', -# 'weblate.machinery.google.GoogleTranslation', -# 'weblate.machinery.microsoft.MicrosoftCognitiveTranslation', -# 'weblate.machinery.microsoftterminology.MicrosoftTerminologyService', -# 'weblate.machinery.mymemory.MyMemoryTranslation', -# 'weblate.machinery.netease.NeteaseSightTranslation', -# 'weblate.machinery.tmserver.AmagamaTranslation', -# 'weblate.machinery.tmserver.TMServerTranslation', -# 'weblate.machinery.yandex.YandexTranslation', -# 'weblate.machinery.weblatetm.WeblateTranslation', -# 'weblate.machinery.saptranslationhub.SAPTranslationHub', -# 'weblate.machinery.youdao.YoudaoTranslation', -# 'weblate.memory.machine.WeblateMemory', -# ) +MT_SERVICES = ( + # "weblate.machinery.apertium.ApertiumAPYTranslation", + # "weblate.machinery.baidu.BaiduTranslation", + # "weblate.machinery.deepl.DeepLTranslation", + # "weblate.machinery.glosbe.GlosbeTranslation", + # "weblate.machinery.google.GoogleTranslation", + # "weblate.machinery.googlev3.GoogleV3Translation", + # "weblate.machinery.microsoft.MicrosoftCognitiveTranslation", + # "weblate.machinery.microsoftterminology.MicrosoftTerminologyService", + # "weblate.machinery.modernmt.ModernMTTranslation", + # "weblate.machinery.mymemory.MyMemoryTranslation", + # "weblate.machinery.netease.NeteaseSightTranslation", + # "weblate.machinery.tmserver.AmagamaTranslation", + # "weblate.machinery.tmserver.TMServerTranslation", + # "weblate.machinery.yandex.YandexTranslation", + # "weblate.machinery.saptranslationhub.SAPTranslationHub", + # "weblate.machinery.youdao.YoudaoTranslation", + "weblate.machinery.weblatetm.WeblateTranslation", + "weblate.memory.machine.WeblateMemory", +) # Machine translation API keys @@ -535,6 +540,10 @@ MT_DEEPL_KEY = None # Microsoft Cognitive Services Translator API, register at # https://portal.azure.com/ MT_MICROSOFT_COGNITIVE_KEY = None +MT_MICROSOFT_REGION = None + +# ModernMT +MT_MODERNMT_KEY = None # MyMemory identification email, see # https://mymemory.translated.net/doc/spec.php @@ -544,9 +553,13 @@ MT_MYMEMORY_EMAIL = None MT_MYMEMORY_USER = None MT_MYMEMORY_KEY = None -# Google API key for Google Translate API +# Google API key for Google Translate API v2 MT_GOOGLE_KEY = None +# Google Translate API3 credentials and project id +MT_GOOGLE_CREDENTIALS = None +MT_GOOGLE_PROJECT = None + # Baidu app key and secret MT_BAIDU_ID = None MT_BAIDU_SECRET = None @@ -575,6 +588,9 @@ MT_SAP_USE_MT = True # Title of site to use SITE_TITLE = "Weblate" +# Site domain +SITE_DOMAIN = "__DOMAIN__" + # Whether site uses https ENABLE_HTTPS = True @@ -592,6 +608,7 @@ CSRF_USE_SESSIONS = True # Customize CSRF failure view CSRF_FAILURE_VIEW = "weblate.trans.views.error.csrf_failure" SESSION_COOKIE_SECURE = ENABLE_HTTPS +SESSION_COOKIE_HTTPONLY = True # SSL redirect SECURE_SSL_REDIRECT = ENABLE_HTTPS # Sent referrrer only for same origin links @@ -599,19 +616,28 @@ SECURE_REFERRER_POLICY = "same-origin" # SSL redirect URL exemption list SECURE_REDIRECT_EXEMPT = (r"healthz/$",) # Allowing HTTP access to health check # Session cookie age (in seconds) -SESSION_COOKIE_AGE = 1209600 +SESSION_COOKIE_AGE = 1000 +SESSION_COOKIE_AGE_AUTHENTICATED = 1209600 # Increase allowed upload size DATA_UPLOAD_MAX_MEMORY_SIZE = 50000000 +# Apply session coookie settings to language cookie as ewll +LANGUAGE_COOKIE_SECURE = SESSION_COOKIE_SECURE +LANGUAGE_COOKIE_HTTPONLY = SESSION_COOKIE_HTTPONLY +LANGUAGE_COOKIE_AGE = SESSION_COOKIE_AGE_AUTHENTICATED * 10 + # Some security headers SECURE_BROWSER_XSS_FILTER = True X_FRAME_OPTIONS = "DENY" SECURE_CONTENT_TYPE_NOSNIFF = True # Optionally enable HSTS -SECURE_HSTS_SECONDS = 0 -SECURE_HSTS_PRELOAD = False -SECURE_HSTS_INCLUDE_SUBDOMAINS = False +SECURE_HSTS_SECONDS = 31536000 if ENABLE_HTTPS else 0 +SECURE_HSTS_PRELOAD = ENABLE_HTTPS +SECURE_HSTS_INCLUDE_SUBDOMAINS = ENABLE_HTTPS + +# HTTPS detection behind reverse proxy +SECURE_PROXY_SSL_HEADER = None # URL of login LOGIN_URL = "{0}/accounts/login/".format(URL_PREFIX) @@ -639,9 +665,6 @@ EMAIL_SUBJECT_PREFIX = "[{0}] ".format(SITE_TITLE) # Enable remote hooks ENABLE_HOOKS = True -# Number of nearby messages to show in each direction -NEARBY_MESSAGES = 5 - # By default the length of a given translation is limited to the length of # the source string * 10 characters. Set this option to False to allow longer # translations (up to 10.000 characters) @@ -655,89 +678,97 @@ CRISPY_TEMPLATE_PACK = "bootstrap3" # List of quality checks # CHECK_LIST = ( -# 'weblate.checks.same.SameCheck', -# 'weblate.checks.chars.BeginNewlineCheck', -# 'weblate.checks.chars.EndNewlineCheck', -# 'weblate.checks.chars.BeginSpaceCheck', -# 'weblate.checks.chars.EndSpaceCheck', -# 'weblate.checks.chars.DoubleSpaceCheck', -# 'weblate.checks.chars.EndStopCheck', -# 'weblate.checks.chars.EndColonCheck', -# 'weblate.checks.chars.EndQuestionCheck', -# 'weblate.checks.chars.EndExclamationCheck', -# 'weblate.checks.chars.EndEllipsisCheck', -# 'weblate.checks.chars.EndSemicolonCheck', -# 'weblate.checks.chars.MaxLengthCheck', -# 'weblate.checks.chars.KashidaCheck', -# 'weblate.checks.chars.PuctuationSpacingCheck', -# 'weblate.checks.format.PythonFormatCheck', -# 'weblate.checks.format.PythonBraceFormatCheck', -# 'weblate.checks.format.PHPFormatCheck', -# 'weblate.checks.format.CFormatCheck', -# 'weblate.checks.format.PerlFormatCheck', -# 'weblate.checks.format.JavaScriptFormatCheck', -# 'weblate.checks.format.CSharpFormatCheck', -# 'weblate.checks.format.JavaFormatCheck', -# 'weblate.checks.format.JavaMessageFormatCheck', -# 'weblate.checks.angularjs.AngularJSInterpolationCheck', -# 'weblate.checks.qt.QtFormatCheck', -# 'weblate.checks.qt.QtPluralCheck', -# 'weblate.checks.ruby.RubyFormatCheck', -# 'weblate.checks.consistency.PluralsCheck', -# 'weblate.checks.consistency.SamePluralsCheck', -# 'weblate.checks.consistency.ConsistencyCheck', -# 'weblate.checks.consistency.TranslatedCheck', -# 'weblate.checks.chars.EscapedNewlineCountingCheck', -# 'weblate.checks.chars.NewLineCountCheck', -# 'weblate.checks.markup.BBCodeCheck', -# 'weblate.checks.chars.ZeroWidthSpaceCheck', -# 'weblate.checks.render.MaxSizeCheck', -# 'weblate.checks.markup.XMLValidityCheck', -# 'weblate.checks.markup.XMLTagsCheck', -# 'weblate.checks.markup.MarkdownRefLinkCheck', -# 'weblate.checks.markup.MarkdownLinkCheck', -# 'weblate.checks.markup.MarkdownSyntaxCheck', -# 'weblate.checks.markup.URLCheck', -# 'weblate.checks.markup.SafeHTMLCheck', -# 'weblate.checks.placeholders.PlaceholderCheck', -# 'weblate.checks.placeholders.RegexCheck', -# 'weblate.checks.source.OptionalPluralCheck', -# 'weblate.checks.source.EllipsisCheck', -# 'weblate.checks.source.MultipleFailingCheck', +# "weblate.checks.same.SameCheck", +# "weblate.checks.chars.BeginNewlineCheck", +# "weblate.checks.chars.EndNewlineCheck", +# "weblate.checks.chars.BeginSpaceCheck", +# "weblate.checks.chars.EndSpaceCheck", +# "weblate.checks.chars.DoubleSpaceCheck", +# "weblate.checks.chars.EndStopCheck", +# "weblate.checks.chars.EndColonCheck", +# "weblate.checks.chars.EndQuestionCheck", +# "weblate.checks.chars.EndExclamationCheck", +# "weblate.checks.chars.EndEllipsisCheck", +# "weblate.checks.chars.EndSemicolonCheck", +# "weblate.checks.chars.MaxLengthCheck", +# "weblate.checks.chars.KashidaCheck", +# "weblate.checks.chars.PunctuationSpacingCheck", +# "weblate.checks.format.PythonFormatCheck", +# "weblate.checks.format.PythonBraceFormatCheck", +# "weblate.checks.format.PHPFormatCheck", +# "weblate.checks.format.CFormatCheck", +# "weblate.checks.format.PerlFormatCheck", +# "weblate.checks.format.JavaScriptFormatCheck", +# "weblate.checks.format.CSharpFormatCheck", +# "weblate.checks.format.JavaFormatCheck", +# "weblate.checks.format.JavaMessageFormatCheck", +# "weblate.checks.format.PercentPlaceholdersCheck", +# "weblate.checks.format.VueFormattingCheck", +# "weblate.checks.format.I18NextInterpolationCheck", +# "weblate.checks.format.ESTemplateLiteralsCheck", +# "weblate.checks.angularjs.AngularJSInterpolationCheck", +# "weblate.checks.qt.QtFormatCheck", +# "weblate.checks.qt.QtPluralCheck", +# "weblate.checks.ruby.RubyFormatCheck", +# "weblate.checks.consistency.PluralsCheck", +# "weblate.checks.consistency.SamePluralsCheck", +# "weblate.checks.consistency.ConsistencyCheck", +# "weblate.checks.consistency.TranslatedCheck", +# "weblate.checks.chars.EscapedNewlineCountingCheck", +# "weblate.checks.chars.NewLineCountCheck", +# "weblate.checks.markup.BBCodeCheck", +# "weblate.checks.chars.ZeroWidthSpaceCheck", +# "weblate.checks.render.MaxSizeCheck", +# "weblate.checks.markup.XMLValidityCheck", +# "weblate.checks.markup.XMLTagsCheck", +# "weblate.checks.markup.MarkdownRefLinkCheck", +# "weblate.checks.markup.MarkdownLinkCheck", +# "weblate.checks.markup.MarkdownSyntaxCheck", +# "weblate.checks.markup.URLCheck", +# "weblate.checks.markup.SafeHTMLCheck", +# "weblate.checks.placeholders.PlaceholderCheck", +# "weblate.checks.placeholders.RegexCheck", +# "weblate.checks.duplicate.DuplicateCheck", +# "weblate.checks.source.OptionalPluralCheck", +# "weblate.checks.source.EllipsisCheck", +# "weblate.checks.source.MultipleFailingCheck", +# "weblate.checks.source.LongUntranslatedCheck", +# "weblate.checks.format.MultipleUnnamedFormatsCheck", # ) # List of automatic fixups # AUTOFIX_LIST = ( -# 'weblate.trans.autofixes.whitespace.SameBookendingWhitespace', -# 'weblate.trans.autofixes.chars.ReplaceTrailingDotsWithEllipsis', -# 'weblate.trans.autofixes.chars.RemoveZeroSpace', -# 'weblate.trans.autofixes.chars.RemoveControlChars', +# "weblate.trans.autofixes.whitespace.SameBookendingWhitespace", +# "weblate.trans.autofixes.chars.ReplaceTrailingDotsWithEllipsis", +# "weblate.trans.autofixes.chars.RemoveZeroSpace", +# "weblate.trans.autofixes.chars.RemoveControlChars", # ) # List of enabled addons # WEBLATE_ADDONS = ( -# 'weblate.addons.gettext.GenerateMoAddon', -# 'weblate.addons.gettext.UpdateLinguasAddon', -# 'weblate.addons.gettext.UpdateConfigureAddon', -# 'weblate.addons.gettext.MsgmergeAddon', -# 'weblate.addons.gettext.GettextCustomizeAddon', -# 'weblate.addons.gettext.GettextAuthorComments', -# 'weblate.addons.cleanup.CleanupAddon', -# 'weblate.addons.consistency.LangaugeConsistencyAddon', -# 'weblate.addons.discovery.DiscoveryAddon', -# 'weblate.addons.flags.SourceEditAddon', -# 'weblate.addons.flags.TargetEditAddon', -# 'weblate.addons.flags.SameEditAddon', +# "weblate.addons.gettext.GenerateMoAddon", +# "weblate.addons.gettext.UpdateLinguasAddon", +# "weblate.addons.gettext.UpdateConfigureAddon", +# "weblate.addons.gettext.MsgmergeAddon", +# "weblate.addons.gettext.GettextCustomizeAddon", +# "weblate.addons.gettext.GettextAuthorComments", +# "weblate.addons.cleanup.CleanupAddon", +# "weblate.addons.consistency.LangaugeConsistencyAddon", +# "weblate.addons.discovery.DiscoveryAddon", +# "weblate.addons.flags.SourceEditAddon", +# "weblate.addons.flags.TargetEditAddon", +# "weblate.addons.flags.SameEditAddon", # "weblate.addons.flags.BulkEditAddon", -# 'weblate.addons.generate.GenerateFileAddon', -# 'weblate.addons.json.JSONCustomizeAddon', -# 'weblate.addons.properties.PropertiesSortAddon', -# 'weblate.addons.git.GitSquashAddon', -# 'weblate.addons.removal.RemoveComments', -# 'weblate.addons.removal.RemoveSuggestions', -# 'weblate.addons.resx.ResxUpdateAddon', -# 'weblate.addons.yaml.YAMLCustomizeAddon', -# 'weblate.addons.autotranslate.AutoTranslateAddon', +# "weblate.addons.generate.GenerateFileAddon", +# "weblate.addons.json.JSONCustomizeAddon", +# "weblate.addons.properties.PropertiesSortAddon", +# "weblate.addons.git.GitSquashAddon", +# "weblate.addons.removal.RemoveComments", +# "weblate.addons.removal.RemoveSuggestions", +# "weblate.addons.resx.ResxUpdateAddon", +# "weblate.addons.yaml.YAMLCustomizeAddon", +# "weblate.addons.cdn.CDNJSAddon", +# "weblate.addons.autotranslate.AutoTranslateAddon", # ) # E-mail address that error messages come from. @@ -757,7 +788,7 @@ CACHES = { "LOCATION": "redis://127.0.0.1:6379/__REDIS_DB__", # If redis is running on same host as Weblate, you might # want to use unix sockets instead: - # 'LOCATION': 'unix:///var/run/redis/redis.sock?db=1', + # "LOCATION": "unix:///var/run/redis/redis.sock?db=1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "PARSER_CLASS": "redis.connection.HiredisParser", @@ -776,15 +807,18 @@ CACHES = { # Store sessions in cache SESSION_ENGINE = "django.contrib.sessions.backends.cache" +# Store messages in session +MESSAGE_STORAGE = "django.contrib.messages.storage.session.SessionStorage" # REST framework settings for API REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. "DEFAULT_PERMISSION_CLASSES": [ - "rest_framework.permissions.IsAuthenticatedOrReadOnly" - # Use following with LOGIN_REQUIRED_URLS - # "rest_framework.permissions.IsAuthenticated" + # Require authentication for login required sites + "rest_framework.permissions.IsAuthenticated" + if REQUIRE_LOGIN + else "rest_framework.permissions.IsAuthenticatedOrReadOnly" ], "DEFAULT_AUTHENTICATION_CLASSES": ( "rest_framework.authentication.TokenAuthentication", @@ -792,8 +826,8 @@ REST_FRAMEWORK = { "rest_framework.authentication.SessionAuthentication", ), "DEFAULT_THROTTLE_CLASSES": ( - "rest_framework.throttling.AnonRateThrottle", - "rest_framework.throttling.UserRateThrottle", + "weblate.api.throttling.UserRateThrottle", + "weblate.api.throttling.AnonRateThrottle", ), "DEFAULT_THROTTLE_RATES": {"anon": "100/day", "user": "5000/hour"}, "DEFAULT_PAGINATION_CLASS": ("rest_framework.pagination.PageNumberPagination"), @@ -802,24 +836,33 @@ REST_FRAMEWORK = { "UNAUTHENTICATED_USER": "weblate.auth.models.get_anonymous", } -# Example for restricting access to logged in users -# LOGIN_REQUIRED_URLS = ( -# r'/(.*)$', -# ) +# Fonts CDN URL +FONTS_CDN_URL = None + +# Django compressor offline mode +COMPRESS_OFFLINE = False +COMPRESS_OFFLINE_CONTEXT = [ + {"fonts_cdn_url": FONTS_CDN_URL, "STATIC_URL": STATIC_URL, "LANGUAGE_BIDI": True}, + {"fonts_cdn_url": FONTS_CDN_URL, "STATIC_URL": STATIC_URL, "LANGUAGE_BIDI": False}, +] + +# Require login for all URLs +if REQUIRE_LOGIN: + LOGIN_REQUIRED_URLS = (r"/(.*)$",) # In such case you will want to include some of the exceptions # LOGIN_REQUIRED_URLS_EXCEPTIONS = ( -# r'/accounts/(.*)$', # Required for login -# r'/admin/login/(.*)$', # Required for admin login -# r'/static/(.*)$', # Required for development mode -# r'/widgets/(.*)$', # Allowing public access to widgets -# r'/data/(.*)$', # Allowing public access to data exports -# r'/hooks/(.*)$', # Allowing public access to notification hooks -# r'/healthz/$', # Allowing public access to health check -# r'/api/(.*)$', # Allowing access to API -# r'/js/i18n/$', # JavaScript localization -# r'/contact/$', # Optional for contact form -# r'/legal/(.*)$', # Optional for legal app +# rf"{URL_PREFIX}/accounts/(.*)$", # Required for login +# rf"{URL_PREFIX}/admin/login/(.*)$", # Required for admin login +# rf"{URL_PREFIX}/static/(.*)$", # Required for development mode +# rf"{URL_PREFIX}/widgets/(.*)$", # Allowing public access to widgets +# rf"{URL_PREFIX}/data/(.*)$", # Allowing public access to data exports +# rf"{URL_PREFIX}/hooks/(.*)$", # Allowing public access to notification hooks +# rf"{URL_PREFIX}/healthz/$", # Allowing public access to health check +# rf"{URL_PREFIX}/api/(.*)$", # Allowing access to API +# rf"{URL_PREFIX}/js/i18n/$", # JavaScript localization +# rf"{URL_PREFIX}/contact/$", # Optional for contact form +# rf"{URL_PREFIX}/legal/(.*)$", # Optional for legal app # ) # Silence some of the Django system checks @@ -831,7 +874,7 @@ SILENCED_SYSTEM_CHECKS = [ # Celery worker configuration for testing # CELERY_TASK_ALWAYS_EAGER = True -# CELERY_BROKER_URL = 'memory://' +# CELERY_BROKER_URL = "memory://" # CELERY_TASK_EAGER_PROPAGATES = True # Celery worker configuration for production CELERY_TASK_ALWAYS_EAGER = False @@ -842,18 +885,14 @@ CELERY_RESULT_BACKEND = CELERY_BROKER_URL CELERY_WORKER_MAX_MEMORY_PER_CHILD = 200000 CELERY_BEAT_SCHEDULE_FILENAME = os.path.join(DATA_DIR, "celery", "beat-schedule") CELERY_TASK_ROUTES = { - "weblate.trans.search.*": {"queue": "search"}, - "weblate.trans.tasks.optimize_fulltext": {"queue": "search"}, - "weblate.trans.tasks.cleanup_fulltext": {"queue": "search"}, "weblate.trans.tasks.auto_translate": {"queue": "translate"}, - "weblate.memory.tasks.*": {"queue": "memory"}, "weblate.accounts.tasks.notify_*": {"queue": "notify"}, "weblate.accounts.tasks.send_mails": {"queue": "notify"}, - "weblate.memory.tasks.memory_backup": {"queue": "backup"}, "weblate.utils.tasks.settings_backup": {"queue": "backup"}, "weblate.utils.tasks.database_backup": {"queue": "backup"}, "weblate.wladmin.tasks.backup": {"queue": "backup"}, "weblate.wladmin.tasks.backup_service": {"queue": "backup"}, + "weblate.memory.tasks.*": {"queue": "memory"}, } # Enable plain database backups diff --git a/manifest.json b/manifest.json index b6672a4..0048042 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "A translation platform using Git and Python", "fr": "Une plateforme de traduction utilisant Git et Python" }, - "version": "3.11.3~ynh1", + "version": "4.3.1~ynh1", "url": "https://weblate.org", "license": "AGPL-3.0", "maintainer": { diff --git a/scripts/_common.sh b/scripts/_common.sh index ffbd489..4df9ede 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -12,7 +12,7 @@ pkg_dependencies="libxml2-dev libxslt-dev libfreetype6-dev libjpeg-dev libz-dev libpq-dev libglib2.0-dev mailutils python-celery-common hub" # Weblate's version for PIP and settings file -current_version="3.11.3" +weblate_version="4.3.1" debian_maj_version=$(sed 's/\..*//' /etc/debian_version) diff --git a/scripts/install b/scripts/install index 1f99ff8..04f2153 100755 --- a/scripts/install +++ b/scripts/install @@ -125,8 +125,7 @@ chown -R "$app": "$final_path" set -o nounset sudo -u $app $final_path/venv/bin/pip install --upgrade pip setuptools wheel # Still needed with latest version of weblate? - sudo -u $app $final_path/venv/bin/pip install celery==4.* - sudo -u $app $final_path/venv/bin/pip install Weblate=="$current_version" + sudo -u $app $final_path/venv/bin/pip install Weblate=="$weblate_version" sudo -u $app $final_path/venv/bin/pip install psycopg2-binary ruamel.yaml aeidon phply #pip install pytz python-bidi PyYaML Babel pyuca pylibravatar py3dns psycopg2-binary phply django-redis hiredis aeidon ruamel.yaml # specific to YunoHost package: diff --git a/scripts/upgrade b/scripts/upgrade index 9c4f2cb..5f40aea 100755 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -149,79 +149,104 @@ ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" ynh_add_systemd_config --service="$app-celery" --template="celery-weblate.service" #================================================= -# PIP INSTALLATION +# UPGRADE WEBLATE #================================================= -ynh_script_progression --message="Install weblate using PIP..." --time --weight=1 -virtualenv --python=python3 "${final_path}/venv" -#run source in a 'sub shell' -( - set +o nounset - source "${final_path}/venv/bin/activate" - set -o nounset - sudo -u $app $final_path/venv/bin/pip install --upgrade pip setuptools wheel - # Still needed with latest version of weblate? - sudo -u $app $final_path/venv/bin/pip install celery==4.* - sudo -u $app $final_path/venv/bin/pip install --upgrade Weblate=="$current_version" - sudo -u $app $final_path/venv/bin/pip install psycopg2-binary ruamel.yaml aeidon phply - #pip install pytz python-bidi PyYaML Babel pyuca pylibravatar py3dns psycopg2-binary phply django-redis hiredis aeidon ruamel.yaml - # specific to YunoHost package: - sudo -u $app $final_path/venv/bin/pip install django_sendmail_backend -) +upgrade() { + new_version=$1 + settings_template=$2 + #================================================= + # PIP INSTALLATION + #================================================= + ynh_script_progression --message="Install weblate using PIP..." --time --weight=1 -#================================================= -# MODIFY A CONFIG FILE -#================================================= -ynh_script_progression --message="Create weblate configuration file..." -# save old settings file -settings="$final_path/venv/lib/$weblate_pypath/site-packages/weblate/settings.py" + ynh_systemd_action --service_name="$app-celery" --action="stop" -ynh_backup_if_checksum_is_different --file="$settings" -cp "../conf/settings.py" "$settings" + virtualenv --python=python3 "${final_path}/venv" + #run source in a 'sub shell' + ( + set +o nounset + source "${final_path}/venv/bin/activate" + set -o nounset + sudo -u $app $final_path/venv/bin/pip install --upgrade pip setuptools wheel + # Still needed with latest version of weblate? + sudo -u $app $final_path/venv/bin/pip install --upgrade Weblate=="$new_version" + sudo -u $app $final_path/venv/bin/pip install psycopg2-binary ruamel.yaml aeidon phply + #pip install pytz python-bidi PyYaML Babel pyuca pylibravatar py3dns psycopg2-binary phply django-redis hiredis aeidon ruamel.yaml + # specific to YunoHost package: + sudo -u $app $final_path/venv/bin/pip install django_sendmail_backend + ) -ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$settings" -ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings" -ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings" -ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings" -ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings" -ynh_replace_string --match_string="__KEY__" --replace_string="$key" --target_file="$settings" -ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$settings" -ynh_replace_string --match_string="__GITHUBUSER__" --replace_string="$github_account" --target_file="$settings" -ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings" -ynh_replace_string --match_string="__PYTHONPATH__" --replace_string="$weblate_pypath" --target_file="$settings" + #================================================= + # MODIFY A CONFIG FILE + #================================================= + ynh_script_progression --message="Create weblate configuration file..." + # save old settings file + settings="$final_path/venv/lib/$weblate_pypath/site-packages/weblate/settings.py" -# remove last "/" of $path_url -ynh_replace_string --match_string="__PATHURL__" --replace_string="${path_url%/}" --target_file="$settings" + ynh_backup_if_checksum_is_different --file="$settings" + cp "$settings_template" "$settings" -ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db" + ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$settings" + ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings" + ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings" + ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings" + ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings" + ynh_replace_string --match_string="__KEY__" --replace_string="$key" --target_file="$settings" + ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$settings" + ynh_replace_string --match_string="__GITHUBUSER__" --replace_string="$github_account" --target_file="$settings" + ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings" + ynh_replace_string --match_string="__PYTHONPATH__" --replace_string="$weblate_pypath" --target_file="$settings" -# Recalculate and store the config file checksum into the app settings -ynh_store_file_checksum --file="$settings" + # remove last "/" of $path_url + ynh_replace_string --match_string="__PATHURL__" --replace_string="${path_url%/}" --target_file="$settings" -touch "$final_path/local_settings.py" -ln -sf "$final_path/local_settings.py" "$final_path/venv/lib/$weblate_pypath/site-packages/weblate/local_settings.py" + ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db" -#================================================= -# MIGRATE WEBLATE -#================================================= -ynh_script_progression --message="Run migration scripts..." --time --weight=1 + # Recalculate and store the config file checksum into the app settings + ynh_store_file_checksum --file="$settings" -ynh_systemd_action --service_name="$app-celery" --action="start" + touch "$final_path/local_settings.py" + ln -sf "$final_path/local_settings.py" "$final_path/venv/lib/$weblate_pypath/site-packages/weblate/local_settings.py" -( - set +o nounset - source "${final_path}/venv/bin/activate" - set -o nounset - export DJANGO_SETTINGS_MODULE="weblate.settings" - cd "${final_path}" + #================================================= + # MIGRATE WEBLATE + #================================================= + ynh_script_progression --message="Run migration scripts..." --time --weight=1 - sudo -u $app $final_path/venv/bin/weblate migrate --noinput - sudo -u $app $final_path/venv/bin/weblate collectstatic --noinput - sudo -u $app $final_path/venv/bin/weblate setuplang - sudo -u $app $final_path/venv/bin/weblate setupgroups - sudo -u $app $final_path/venv/bin/weblate compilemessages - sudo -u $app $final_path/venv/bin/weblate check --deploy -) + ynh_systemd_action --service_name="$app-celery" --action="start" + + ( + set +o nounset + source "${final_path}/venv/bin/activate" + set -o nounset + export DJANGO_SETTINGS_MODULE="weblate.settings" + cd "${final_path}" + + sudo -u $app $final_path/venv/bin/weblate migrate --noinput + sudo -u $app $final_path/venv/bin/weblate collectstatic --noinput + sudo -u $app $final_path/venv/bin/weblate setuplang + sudo -u $app $final_path/venv/bin/weblate setupgroups + sudo -u $app $final_path/venv/bin/weblate compilemessages + sudo -u $app $final_path/venv/bin/weblate check --deploy + ) +} + +file_version="${final_path}/venv/lib/$weblate_pypath/site-packages/weblate/__init__.py" +if [ -e $file_version ]; +then + current_version=$(cat $file_version | grep "^VERSION = " | grep -o "[0-9].[0-9]" | head -n1 | cut -d"." -f1) +else + current_version=3 +fi + +if [ "$current_version" -lt "4" ]; +then + ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS pg_trgm;" --database=$db_name + upgrade "4.1.1" "../conf/settings.4.1.1.py" +fi + +upgrade $weblate_version "../conf/settings.py" #================================================= # SETUP LOGROTATE