]> git.parisson.com Git - teleforma.git/commitdiff
First shot at dockerisation
authorGael Le Mignot <gael@pilotsystems.net>
Thu, 16 Dec 2021 10:40:43 +0000 (11:40 +0100)
committerGael Le Mignot <gael@pilotsystems.net>
Thu, 16 Dec 2021 10:40:43 +0000 (11:40 +0100)
22 files changed:
Dockerfile [new file with mode: 0644]
app/__init__.py [new file with mode: 0644]
app/asgi.py [new file with mode: 0644]
app/asgi.sh [new file with mode: 0755]
app/init.sh [new file with mode: 0755]
app/local_settings.py [new file with mode: 0644]
app/local_settings.py.sample [new file with mode: 0644]
app/manage.py [new file with mode: 0755]
app/run/.placeholer [new file with mode: 0644]
app/settings.py [new file with mode: 0644]
app/urls.py [new file with mode: 0644]
app/wait.sh [new file with mode: 0755]
app/worker.py [new file with mode: 0644]
app/wsgi.ini [new file with mode: 0644]
app/wsgi.py [new file with mode: 0644]
app/wsgi.sh [new file with mode: 0755]
debian-packages.txt [new file with mode: 0644]
requirements-dev.txt [new file with mode: 0644]
requirements.txt [new file with mode: 0644]
setup.py
teleforma/4.0.5.zip [deleted file]
wsgi.py [deleted file]

diff --git a/Dockerfile b/Dockerfile
new file mode 100644 (file)
index 0000000..f9aa780
--- /dev/null
@@ -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 <yomguy@parisson.com>
+
+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 (file)
index 0000000..1217618
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
diff --git a/app/asgi.py b/app/asgi.py
new file mode 100644 (file)
index 0000000..fd5bbdc
--- /dev/null
@@ -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<room_name>\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 (executable)
index 0000000..ec15518
--- /dev/null
@@ -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 (executable)
index 0000000..1aa59bf
--- /dev/null
@@ -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 (file)
index 0000000..fcab949
--- /dev/null
@@ -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 (file)
index 0000000..054934a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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 (executable)
index 0000000..46e20dd
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+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 (file)
index 0000000..e69de29
diff --git a/app/settings.py b/app/settings.py
new file mode 100644 (file)
index 0000000..0a34e1a
--- /dev/null
@@ -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 (file)
index 0000000..e601f98
--- /dev/null
@@ -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 (executable)
index 0000000..c4f0a4d
--- /dev/null
@@ -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 (file)
index 0000000..6d06656
--- /dev/null
@@ -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 (file)
index 0000000..1f18bf1
--- /dev/null
@@ -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 (file)
index 0000000..e63f835
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+# -*- 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 (executable)
index 0000000..4385982
--- /dev/null
@@ -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 (file)
index 0000000..9d5d5df
--- /dev/null
@@ -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 (file)
index 0000000..d1cc50e
--- /dev/null
@@ -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 (file)
index 0000000..0259f32
--- /dev/null
@@ -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
index 405120ee3d70c5758f93e5a5c7d139cb9d78daf8..751e2bc76645800cdf9f24346eafb236320d1bf5 100644 (file)
--- 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 (file)
index db83dbe..0000000
Binary files a/teleforma/4.0.5.zip and /dev/null differ
diff --git a/wsgi.py b/wsgi.py
deleted file mode 100644 (file)
index e69de29..0000000