From: Gael Le Mignot Date: Thu, 16 Dec 2021 10:40:43 +0000 (+0100) Subject: First shot at dockerisation X-Git-Tag: 2.8.1-pro~146 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=c38805853eb53224115f820f0c125146010c83a5;p=teleforma.git First shot at dockerisation --- diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..f9aa7807 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,68 @@ +# Copyright 2013 Thatcher Peskens +# Copyright 2014-2015 Guillaume Pellerin +# Copyright 2014-2015 Thomas Fillon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM python:3 + +MAINTAINER Guillaume Pellerin + +ENV PYTHONUNBUFFERED 1 + +RUN mkdir -p /srv/app +RUN mkdir -p /srv/lib/teleforma + +WORKDIR /srv + +RUN apt-get update && apt-get install -y apt-transport-https +# COPY etc/apt/sources.list /etc/apt/ +COPY debian-packages.txt /srv +RUN apt-get update && \ + DEBIAN_PACKAGES=$(egrep -v "^\s*(#|$)" /srv/debian-packages.txt) && \ + apt-get install -y --force-yes $DEBIAN_PACKAGES && \ + echo fr_FR.UTF-8 UTF-8 >> /etc/locale.gen && \ + locale-gen && \ + apt-get clean + +RUN pip3 install -U pip + +ENV LANG fr_FR.UTF-8 +ENV LANGUAGE fr_FR:fr +ENV LC_ALL fr_FR.UTF-8 + +COPY requirements.txt /srv +RUN pip3 install -r requirements.txt + +COPY requirements-dev.txt /srv +ARG dev=0 +RUN if [ "${dev}" = "1" ]; then pip3 install -r requirements-dev.txt; fi +RUN if [ "${dev}" = "1" ]; then apt-get -y install less nano postgresql-client redis-tools; fi + +COPY lib /srv/lib +COPY bin/build/local/setup_lib.sh /srv +RUN /srv/setup_lib.sh + +WORKDIR /srv/src/teleforma +COPY setup.py /srv/src/teleforma +COPY teleforma /srv/src/teleforma +COPY README.rst /srv/src/teleforma +RUN python setup.py develop + +# Workaround for django installation bugs +# RUN cp -ra /usr/local/django/* /usr/local/lib/python2.7/site-packages/django/ +# RUN cp -ra /usr/local/django_extensions/* /usr/local/lib/python2.7/site-packages/django_extensions/ + +WORKDIR /srv/app + +EXPOSE 8000 diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 00000000..12176181 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016-2017 Ircam +# Copyright (c) 2016-2017 Guillaume Pellerin +# Copyright (c) 2016-2017 Emilie Zawadzki + +# This file is part of mezzanine-organization. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + diff --git a/app/asgi.py b/app/asgi.py new file mode 100644 index 00000000..fd5bbdc9 --- /dev/null +++ b/app/asgi.py @@ -0,0 +1,30 @@ +import os, sys +from django.core.asgi import get_asgi_application + +#sys.path.append(os.path.dirname('.')) +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') +django_asgi_app = get_asgi_application() + +from channels.auth import AuthMiddlewareStack +from channels.routing import ProtocolTypeRouter, URLRouter +from django.urls import re_path +from teleforma.ws import chat + +websocket_urlpatterns = [ + re_path(r'ws/chat/(?P\w+)/$', chat.ChatConsumer.as_asgi()), +] + + +application = ProtocolTypeRouter({ + "http": django_asgi_app, + "websocket": AuthMiddlewareStack( + URLRouter( + websocket_urlpatterns + ) + ), +}) + + + + + diff --git a/app/asgi.sh b/app/asgi.sh new file mode 100755 index 00000000..ec155187 --- /dev/null +++ b/app/asgi.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# paths +app='/srv/app' +manage=$app'/manage.py' +static='/srv/static/' +media='/srv/media/' +src='/srv/src/' + +if [ "$1" = "--runserver" ]; then + python $manage runserver 0.0.0.0:8000 +else + # static files auto update + # watchmedo shell-command --patterns="$patterns" --recursive \ + # --command='python '$manage' collectstatic --noinput' $app & + daphne -b 0.0.0.0 -p 8000 asgi:application +fi + + diff --git a/app/init.sh b/app/init.sh new file mode 100755 index 00000000..1aa59bf6 --- /dev/null +++ b/app/init.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# paths +app='/srv/app' +manage=$app'/manage.py' + +python $manage migrate --noinput +python $manage create-admin-user +python $manage create-default-organization +python $manage build-front + +# @todo searching every fixtures file in each folder +python $manage loaddata $app/organization/job/fixtures/organization-job.json +python $manage loaddata $app/organization/projects/fixtures/organization-projects-repositorysystems.json + +bash /srv/doc/build.sh diff --git a/app/local_settings.py b/app/local_settings.py new file mode 100644 index 00000000..fcab949f --- /dev/null +++ b/app/local_settings.py @@ -0,0 +1,11 @@ +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +# EMAIL_HOST = 'smtp.pilotsystems.net' +# EMAIL_PORT = 25 +# EMAIL_HOST_USER = '' +# EMAIL_HOST_PASSWORD = '' +# EMAIL_USE_TLS = False + + +USE_WEBPACK_DEV_SERVER = True +WEBPACK_DEV_SERVER_URL = "https://npm3000.dockdev.pilotsystems.net/" \ No newline at end of file diff --git a/app/local_settings.py.sample b/app/local_settings.py.sample new file mode 100644 index 00000000..054934a0 --- /dev/null +++ b/app/local_settings.py.sample @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016-2017 Ircam +# Copyright (c) 2016-2017 Guillaume Pellerin +# Copyright (c) 2016-2017 Emilie Zawadzki + +# This file is part of mezzanine-organization. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import os +from django.utils.translation import ugettext_lazy as _ +from datetime import datetime, date + +DEBUG = True if os.environ.get('DEBUG') == 'True' else False + +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016-2017 Ircam +# Copyright (c) 2016-2017 Guillaume Pellerin +# Copyright (c) 2016-2017 Emilie Zawadzki + +# This file is part of mezzanine-organization. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import os +from django.utils.translation import ugettext_lazy as _ +from datetime import datetime, date + +DEBUG = True if os.environ.get('DEBUG') == 'True' else False + +ADMINS = ( + ('Your Name', 'contact@you.org'), +) + +# Make these unique, and don't share it with anybody. +SECRET_KEY = "H7665jhuyUTGuhuUYT6è-ertyezçuàçi'09Iikrpokfàçir" +NEVERCACHE_KEY = "87654RFGhju7665rdfGyuàiPOpkM;?NbGFr'(3(ezrTYuiJK" + +EMAIL_HOST = 'localhost' # please specify your smtp server address +EMAIL_PORT = '25' +SERVER_EMAIL = 'no-reply@no-reply.org' # a no reply address +DEFAULT_FROM_EMAIL = 'default@default.org' # another address, default one +DEFAULT_TO_EMAIL = 'recipient@recipient.org' # default recipient, for your tests +EMAIL_SUBJECT_PREFIX = "[PREFIX]" # prefix title in email +SITE_TITLE = 'Your Site' +SITE_TAGLINE = 'This is a Mezzo site' + +AUTHENTICATION_BACKENDS = ( + # "organization.core.backend.OrganizationLDAPBackend", + "mezzanine.core.auth_backends.MezzanineBackend", + "guardian.backends.ObjectPermissionBackend", +) diff --git a/app/manage.py b/app/manage.py new file mode 100755 index 00000000..46e20ddd --- /dev/null +++ b/app/manage.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016-2017 Ircam +# Copyright (c) 2016-2017 Guillaume Pellerin +# Copyright (c) 2016-2017 Emilie Zawadzki + +# This file is part of mezzanine-organization. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/app/run/.placeholer b/app/run/.placeholer new file mode 100644 index 00000000..e69de29b diff --git a/app/settings.py b/app/settings.py new file mode 100644 index 00000000..0a34e1a4 --- /dev/null +++ b/app/settings.py @@ -0,0 +1,520 @@ +# -*- coding: utf-8 -*- +# Django settings for sandbox project. + +from django.utils.encoding import force_text +import warnings +import os +import sys +from django.urls import reverse_lazy +# import environ + +sys.dont_write_bytecode = True + +DEBUG_ENV = os.environ.get('DEBUG') == 'True' +DEBUG = DEBUG_ENV +TEMPLATE_DEBUG = DEBUG + +RECOVERY = True + +# disable to debug websocket and improve performance +DEBUG_TOOLBAR = False + + +BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + +warnings.showwarning = lambda *x: None + +ADMINS = ( + ('Guillaume Pellerin', 'webmaster@parisson.com'), + ('Gael le Mignot', 'gael@pilotsystems.net'), + # ('Admin CRFPA', 'admin-crfpa@pre-barreau.com'), +) + +MANAGERS = ADMINS + +ALLOWED_HOSTS = ['localhost', 'crfpa.dockdev.pilotsystems.net', + 'staging.docker.e-learning.crfpa.pre-barreau.parisson.com', + 'e-learning.crfpa.pre-barreau.com', + 'prod.docker.e-learning.crfpa.pre-barreau.parisson.com', + 'recovery.docker.e-learning.crfpa.pre-barreau.parisson.com', +] + +ASGI_APPLICATION = "teleforma.ws.routing.application" + +REDIS_HOST = "redis" +REDIS_PORT = 6379 + +CHANNEL_LAYERS = { + 'default': { + 'BACKEND': 'channels_redis.core.RedisChannelLayer', + 'CONFIG': { + "hosts": [(REDIS_HOST, REDIS_PORT)], + }, + }, +} + +ENABLE_CHAT = True + +DATABASES = { + 'default': { + # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + # Or path to database file if using sqlite3. + 'NAME': os.environ.get('POSTGRES_DATABASE'), + # Not used with sqlite3. + 'USER': os.environ.get('POSTGRES_USER'), + # Not used with sqlite3. + 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), + # Set to empty string for localhost. Not used with sqlite3. + 'HOST': os.environ.get('DB_HOST'), + # Set to empty string for default. Not used with sqlite3. + 'PORT': os.environ.get('DB_PORT'), + }, +} + +if RECOVERY: + DATABASES['recovery'] = { + # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + # Or path to database file if using sqlite3. + 'NAME': os.environ.get('POSTGRES_DATABASE'), + # Not used with sqlite3. + 'USER': os.environ.get('POSTGRES_USER'), + # Not used with sqlite3. + 'PASSWORD': os.environ.get('POSTGRES_PASSWORD_RECOVERY'), + # Set to empty string for localhost. Not used with sqlite3. + 'HOST': os.environ.get('DB_HOST_RECOVERY'), + # Set to empty string for default. Not used with sqlite3. + 'PORT': os.environ.get('DB_PORT'), + } + +# 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. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Paris' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'fr' +LANGUAGES = [ + ('fr', 'French'), + ('en', 'English'), +] + +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 + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '/srv/media/' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +#MEDIA_URL = 'http://pre-barreau.com/archives/' +MEDIA_URL = '/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. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = '/srv/static/' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +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. +) + +# 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', +) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'a8l7%06wr2k+3=%#*#@#rvop2mmzko)44%7k(zx%lls^ihm9^5' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + ('django.template.loaders.cached.Loader', ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + )), +) + +MIDDLEWARE = (('debug_toolbar.middleware.DebugToolbarMiddleware',) if DEBUG_TOOLBAR else ()) + ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'dj_pagination.middleware.PaginationMiddleware', + 'teleforma.middleware.XsSharing', + 'django_user_agents.middleware.UserAgentMiddleware', +) + +ROOT_URLCONF = 'urls' + + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'teleforma', + 'jazzmin', + 'django.contrib.admin', + 'channels', + 'teleforma.webclass', + 'teleforma.exam', + 'jsonrpc', + 'sorl.thumbnail', + 'dj_pagination', + 'postman', + 'captcha', + 'django_nvd3', + 'tinymce', + 'pdfannotator', + 'rest_framework', + 'rest_framework.authtoken', +) + + +if DEBUG_TOOLBAR: + INSTALLED_APPS += ('debug_toolbar',) + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + 'postman.context_processors.inbox', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'teleforma.context_processors.periods', + + ], + }, + }, +] + +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' + +AUTH_PROFILE_MODULE = 'telemeta.userprofile' +LOGIN_URL = '/login/' +LOGIN_REDIRECT_URL = reverse_lazy('teleforma-desk') + +#if DEBUG: +# EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +POSTMAN_AUTO_MODERATE_AS = True +POSTMAN_DISALLOW_ANONYMOUS = True + +#FILE_PROTECTION_METHOD = 'xsendfile' + +TELEFORMA_ORGANIZATION = 'Pré-Barreau - CRFPA' +TELEFORMA_SUBJECTS = ('Barreau', 'CRFPA', 'e-learning') +TELEFORMA_DESCRIPTION = "E-learning Pré-Barreau - CRFPA" +TELEFORMA_E_LEARNING_TYPE = 'CRFPA' +TELEFORMA_GLOBAL_TWEETER = False +TELEFORMA_PERIOD_TWEETER = True +TELEFORMA_EXAM_TOPIC_DEFAULT_DOC_TYPE_ID = 4 +TELEFORMA_EXAM_SCRIPT_UPLOAD = True +TELEFORMA_REGISTER_DEFAULT_DOC_ID = 5506 +TELEFORMA_PERIOD_DEFAULT_ID = 21 +TELEFORMA_EXAM_MAX_SESSIONS = 99 +TELEFORMA_EXAM_SCRIPT_MAX_SIZE = 20480000 +TELEFORMA_EXAM_SCRIPT_SERVICE_URL = '/webviewer/teleforma.html' + +EMAIL_HOST = 'angus.parisson.com' +DEFAULT_FROM_EMAIL = 'crfpa@pre-barreau.com' +SERVER_EMAIL = 'crfpa@pre-barreau.com' +EMAIL_SUBJECT_PREFIX = '[' + TELEFORMA_ORGANIZATION + '] ' + +TELECASTER_LIVE_STREAMING_PROTOCOL = 'https' +TELECASTER_LIVE_STREAMING_SERVER = 'stream7.parisson.com' +TELECASTER_LIVE_STREAMING_PORT = 443 +TELECASTER_LIVE_ICECAST_STREAMING_PORT = 443 +TELECASTER_LIVE_ICECAST_STREAMING_PATH = '/stream/audio/' +TELECASTER_LIVE_STREAM_M_STREAMING_PORT = 443 +TELECASTER_LIVE_STREAM_M_STREAMING_PATH = '/stream/video/' + +PASSWORD_HASHERS = [ + 'django.contrib.auth.hashers.PBKDF2PasswordHasher', +] + +BOX_API_TOKEN = 'D2pBaN8YqjGIfS0tKrgnMP93' + +FILE_UPLOAD_TEMP_DIR = '/tmp' + +SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" +#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" +#SESSION_ENGINE = "unique_session.backends.session_backend" +UNIQUE_SESSION_WHITELIST = (1, 2042) +SESSION_EXPIRE_AT_BROWSER_CLOSE = False + +RECAPTCHA_PUBLIC_KEY = '6Ldq5DgbAAAAADkKg19JXlhx6F1XUQDsrXfXqSP6' +RECAPTCHA_PRIVATE_KEY = '6Ldq5DgbAAAAAOVDOeF2kH8i2e2VSNHpqlinbpAJ' +RECAPTCHA_REQUIRED_SCORE = 0.85 + +# Cache backend is optional, but recommended to speed up user agent parsing +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache', + 'LOCATION': 'memcached:11211', + 'TIMEOUT': None, + 'OPTIONS': { + 'no_delay': True, + 'ignore_exc': True, + 'max_pool_size': 16, + 'use_pooling': True, + } + } +} + +CACHE_TIMEOUT = None + +# Name of cache backend to cache user agents. If it not specified default +# cache alias will be used. Set to `None` to disable caching. +USER_AGENTS_CACHE = 'default' + +AUTH_USER_MODEL = 'auth.User' + +TINYMCE_DEFAULT_CONFIG = { + "height": "320px", + "width": "960px", + "menubar": "file edit view insert format tools table help", + "plugins": "advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code " + "fullscreen insertdatetime media table paste code help wordcount spellchecker", + "toolbar": "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft " + "aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | forecolor " + "backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | " + "fullscreen preview save print | insertfile image media pageembed template link anchor codesample | " + "a11ycheck ltr rtl | showcomments addcomment code", + "custom_undo_redo_levels": 10, +} + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.TokenAuthentication', + 'rest_framework.authentication.BasicAuthentication', + 'rest_framework.authentication.SessionAuthentication' + ] +} + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' + }, + 'simple': { + 'format': '%(levelname)s %(asctime)s %(module)s %(message)s' + }, + }, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': "/var/log/app/app.log", + 'formatter': 'simple', + }, + 'console': { + 'class': 'logging.StreamHandler', + }, + }, + 'loggers': { + 'payment': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + 'websocket': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} + + +def show_user_as(user): + professor = user.professor.all() + is_corrector = False + if user.quotas.count() and not professor and not user.is_superuser: + return "#"+str(user.id) + else: + return force_text(user) + + +POSTMAN_SHOW_USER_AS = show_user_as + +#THUMBNAIL_FORCE_OVERWRITE = True + +JAZZMIN_SETTINGS = { + "site_title": "CRFPA", + "site_header": "CRFPA", + "site_logo": "teleforma/images/logo_pb.png", + + # # Links to put along the top menu + # "topmenu_links": [ + + # # Url that gets reversed (Permissions can be added) + # {"name": "Home", "url": "admin:index", "permissions": ["auth.view_user"]}, + + # # external url that opens in a new window (Permissions can be added) + # {"name": "Support", "url": "https://github.com/farridav/django-jazzmin/issues", "new_window": True}, + + # # model admin to link to (Permissions checked against model) + # {"model": "auth.User"}, + + # # App with dropdown menu to all its models pages (Permissions checked against models) + # {"app": "books"}, + # ], + + "hide_apps": [], + "hide_models": [], + "order_with_respect_to": ["auth", "teleforma", "teleforma.webclass", "teleforma.exam", "pdfannotator"], + + # Custom links to append to app groups, keyed on app name + # "custom_links": { + # "teleforma": [{ + # "name": "Make Messages", + # "url": "make_messages", + # "icon": "fas fa-comments", + # "permissions": ["books.view_book"] + # }] + # }, + "icons": { + "auth": "fas fa-users-cog", + "auth.user": "fas fa-user", + "auth.Group": "fas fa-users", + "teleforma.newsitem": "fas fa-newspaper", + "teleforma.conference": "fas fa-users", + "teleforma.document": "fas fa-file", + "teleforma.student": "fas fa-user-graduate", + "teleforma.professor": "fas fa-user-tie", + "webclass.webclass": "fas fa-phone", + }, + "related_modal_active": True, + + "custom_css": None, + "custom_js": None, + "show_ui_builder": False, + + ############### + # Change view # + ############### + # Render out the change view as a single form, or in tabs, current options are + # - single + # - horizontal_tabs (default) + # - vertical_tabs + # - collapsible + # - carousel + "changeform_format": "horizontal_tabs", + # override change forms on a per modeladmin basis + "changeform_format_overrides": {"auth.user": "collapsible", "auth.group": "vertical_tabs"}, + "language_chooser": False, +} + +JAZZMIN_UI_TWEAKS = { + "navbar_small_text": False, + "footer_small_text": False, + "body_small_text": False, + "brand_small_text": False, + "brand_colour": False, + "accent": "accent-primary", + "navbar": "navbar-white navbar-light", + "no_navbar_border": False, + "navbar_fixed": False, + "layout_boxed": False, + "footer_fixed": False, + "sidebar_fixed": True, + "sidebar": "sidebar-dark-primary", + "sidebar_nav_small_text": True, + "sidebar_disable_expand": False, + "sidebar_nav_child_indent": False, + "sidebar_nav_compact_style": True, + "sidebar_nav_legacy_style": False, + "sidebar_nav_flat_style": False, + "theme": "default", + "dark_mode_theme": "darkly", + "button_classes": { + "primary": "btn-outline-primary", + "secondary": "btn-outline-secondary", + "info": "btn-outline-info", + "warning": "btn-outline-warning", + "danger": "btn-outline-danger", + "success": "btn-outline-success" + }, + "actions_sticky_top": True +} +# Sherlock's online payment +PAYMENT_SHERLOCKS_PATH='/srv/sherlocks' + +PAYMENT_PARAMETERS = { 'merchant_id' : { 'Semestrielle': "040109417200053", + 'Annuelle': "040109417200053", + 'Estivale': "040109417200054", }, + 'merchant_country': 'fr', + 'currency_code': '978', + 'language': 'fr' +} + + +ORAL_OPTION_PRICE = 250 + +if DEBUG_TOOLBAR: + def show_toolbar(request): + return True + DEBUG_TOOLBAR_CONFIG = { + "SHOW_TOOLBAR_CALLBACK" : show_toolbar, + } + + +USE_WEBPACK_DEV_SERVER = False +WEBPACK_DEV_SERVER_URL = "http://172.24.104.152:3000/" + + +################## +# LOCAL SETTINGS # +################## + +# Allow any settings to be defined in local_settings.py which should be +# ignored in your version control system allowing for settings to be +# defined per machine. +try: + from local_settings import * +except ImportError as e: + if "local_settings" not in str(e): + raise e + diff --git a/app/urls.py b/app/urls.py new file mode 100644 index 00000000..e601f98d --- /dev/null +++ b/app/urls.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import os + +from django.conf.urls import include, url +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +from django.http import HttpResponse +from django.views.i18n import JavaScriptCatalog + +admin.autodiscover() + +js_info_dict = ['teleforma'] + +DEBUG_ENV = os.environ.get('DEBUG') == 'True' + +if DEBUG_ENV: + import debug_toolbar + +urlpatterns = [ + # Example: + # (r'^sandbox/', include('sandbox.foo.urls')), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + url(r'^admin/', admin.site.urls), + + # TeleForma + url(r'^', include('teleforma.urls')), + + # Languages + url(r'^i18n/', include('django.conf.urls.i18n')), + url(r'^jsi18n/$', JavaScriptCatalog.as_view(packages=js_info_dict), name="js_catalog"), + url(r'^robots\.txt$', lambda r: HttpResponse( + "User-agent: *\nDisallow: /", mimetype="text/plain")), + + url(r'^tinymce/', include('tinymce.urls')), + #url(r'^pdfviewer/', include('webviewer.urls')), + url(r'^pdfannotator/', include('pdfannotator.urls')), + url(r'^messages/', include('postman.urls', namespace='postman')), +] + ([url(r'^__debug__/', include(debug_toolbar.urls)),] if DEBUG_ENV else []) + diff --git a/app/wait.sh b/app/wait.sh new file mode 100755 index 00000000..c4f0a4d4 --- /dev/null +++ b/app/wait.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +/srv/bin/misc/wait-for-it/wait-for-it.sh -h $DB_HOST -p $DB_PORT; + diff --git a/app/worker.py b/app/worker.py new file mode 100644 index 00000000..6d06656d --- /dev/null +++ b/app/worker.py @@ -0,0 +1,24 @@ +from __future__ import absolute_import +import os, sys +from celery import Celery +from django.conf import settings + +sys.path.append(os.path.dirname('.')) +sys.path.append(os.path.dirname('..')) + +# set the default Django settings module for the 'celery' program. +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') + +app = Celery('app') + +# Using a string here means the worker will not have to +# pickle the object when using Windows. +app.config_from_object('django.conf:settings') +app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) +# app.conf.update( +# CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend', +# ) + +@app.task(bind=True) +def debug_task(self): + print('Request: {0!r}'.format(self.request)) diff --git a/app/wsgi.ini b/app/wsgi.ini new file mode 100644 index 00000000..1f18bf1d --- /dev/null +++ b/app/wsgi.ini @@ -0,0 +1,45 @@ +[uwsgi] + +socket = /srv/app/run/wsgi.sock +chdir = /srv/app/ +module = wsgi +touch-reload = /srv/app/wsgi.py +chmod-socket = 664 + +uid = www-data +gid = www-data + +strict = true +master = true +enable-threads = false +vacuum = true ; Delete sockets during shutdown +single-interpreter = true +die-on-term = true ; Shutdown when receiving SIGTERM (default is respawn) +need-app = true + +disable-logging = true ; Disable built-in logging +log-4xx = true ; but log 4xx's anyway +log-5xx = true ; and 5xx's + +harakiri = 300 ; forcefully kill workers after 60 seconds +#py-callos-afterfork = true ; allow workers to trap signals + +max-requests = 20000 ; Restart workers after this many requests +max-worker-lifetime = 18000 ; Restart workers after this many seconds +reload-on-rss = 4096 ; Restart workers after this much resident memory +worker-reload-mercy = 300 ; How long to wait before forcefully killing workers + +cheaper-algo = busyness +processes = 64 ; Maximum number of workers allowed +cheaper = 24 ; Minimum number of workers allowed +cheaper-initial = 24 ; Workers created at startup +cheaper-overload = 1 ; Length of a cycle in seconds +cheaper-step = 8 ; How many workers to spawn at a time + +cheaper-busyness-multiplier = 30 ; How many cycles to wait before killing workers +cheaper-busyness-min = 20 ; Below this threshold, kill workers (if stable for multiplier cycles) +cheaper-busyness-max = 70 ; Above this threshold, spawn new workers +cheaper-busyness-backlog-alert = 10 ; Spawn emergency workers if more than this many requests are waiting in the queue +cheaper-busyness-backlog-step = 2 ; How many emergency workers to create if there are too many requests in the queue + + diff --git a/app/wsgi.py b/app/wsgi.py new file mode 100644 index 00000000..e63f8351 --- /dev/null +++ b/app/wsgi.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016-2017 Ircam +# Copyright (c) 2016-2017 Guillaume Pellerin +# Copyright (c) 2016-2017 Emilie Zawadzki + +# This file is part of mezzanine-organization. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- + +import os +import sys +from django.core.wsgi import get_wsgi_application + +sys.path.append(os.path.dirname('.')) +os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'settings') +application = get_wsgi_application() diff --git a/app/wsgi.sh b/app/wsgi.sh new file mode 100755 index 00000000..43859828 --- /dev/null +++ b/app/wsgi.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# paths +app='/srv/app' +manage=$app'/manage.py' +static='/srv/static/' +media='/srv/media/' +src='/srv/src/' +uwsgi_log='/var/log/uwsgi/app.log' +debug_log='/var/log/app/debug.log' + +# patterns='*.js;*.css;*.jpg;*.jpeg;*.gif;*.png;*.svg;*.ttf;*.eot;*.woff;*.woff2' + +# Install a package in development mode +# without rebuidling docker image. +# You need at first checkout your sources in 'lib' folder +# in host project side, then run : +# pip install -e /srv/lib/mypackage... +# pip3 install -U uwsgi + +# Install (staging) libs +# /srv/bin/build/local/setup_lib.sh + +# waiting for other services +sh $app/wait.sh + +# django setup +#python $manage wait-for-db + +# initial setup +# if [ ! -f .init ]; then +# bash $app/bin/init.sh +# touch .init +# fi + +# app start +if [ "$1" = "--runserver" ]; then + python $manage runserver 0.0.0.0:8000 --noasgi +else + # static files auto update + # watchmedo shell-command --patterns="$patterns" --recursive \ + # --command='python '$manage' collectstatic --noinput' $app & + + python $manage collectstatic --noinput + + chown -R www-data: $debug_log + + uwsgi /srv/app/wsgi.ini +fi diff --git a/debian-packages.txt b/debian-packages.txt new file mode 100644 index 00000000..9d5d5df1 --- /dev/null +++ b/debian-packages.txt @@ -0,0 +1,10 @@ +git +netcat +vim +locales +ipython +python3-setuptools +python3-mysqldb +python3-psycopg2 +python3-yaml +uwsgi diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..d1cc50e1 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,2 @@ +ipdb==0.13.8 +django-debug-toolbar \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..0259f328 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,37 @@ +bigbluebutton-api-python==0.0.11 +channels==3.0.3 +channels_redis==3.2.0 +docutils==0.17.1 +Django==3.2.3 +djangorestframework==3.12.4 +# django-extensions==1.2.1 +# django-timezones==0.2 +# django-registration==3.1.2 +dj_pagination==2.5.0 # used by postman +django-jazzmin==2.4.7 +django-json-rpc==0.7.1 +# django-google-tools==1.1.0 +django-nvd3==0.8.2 +django-postman==4.2 +django-tinymce==3.3.0 +-e git+https://git.parisson.com/git/django-unique-session.git@master#egg=django-unique-session +django-user-agents==0.4.0 +django-recaptcha==2.0.6 +jxmlease==1.0.3 +mysqlclient==2.0.3 +numpy==1.20.3 +# django-user-agents==0.3.0 +# html5lib==1.1 +requests +sorl-thumbnail==12.7.0 +unidecode==1.2.0 +weasyprint==52.5 +xlrd==2.0.1 +xlwt==1.3.0 +psycopg2==2.8.6 +redis==3.5.3 +uwsgi==2.0.19 +daphne==3.0.2 +pymemcache==3.4.4 +django-debug-toolbar==3.2.1 +ipython diff --git a/setup.py b/setup.py index 405120ee..751e2bc7 100644 --- a/setup.py +++ b/setup.py @@ -11,22 +11,7 @@ setup( long_description = open('README.rst').read(), author = "Guillaume Pellerin", author_email = "yomguy@parisson.com", - version = '1.0', - install_requires = [ - 'django>=1.4', - 'telemeta', - 'south', - 'django-pagination', - 'django-postman', - 'django-extensions', - 'django-notes', - 'django-timezones', - 'django-tinymce', - 'django-forms-builder', - 'xhtml2pdf', - 'xlwt', - 'django-google-tools', - ], + version = '2.4.4', platforms=['OS Independent'], license='CeCILL v2', classifiers = CLASSIFIERS, diff --git a/teleforma/4.0.5.zip b/teleforma/4.0.5.zip deleted file mode 100644 index db83dbe4..00000000 Binary files a/teleforma/4.0.5.zip and /dev/null differ diff --git a/wsgi.py b/wsgi.py deleted file mode 100644 index e69de29b..00000000