diff --git a/.gitignore b/.gitignore
index 5d381cc..02cdc69 100644
--- a/.gitignore
+++ b/.gitignore
@@ -160,3 +160,18 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
+# Mac OSX OS generated files
+.DS_Store?
+Thumbs.db
+*.DS_Store
+
+
+# VS Code
+.vscode/
+*.code-workspace
+
+# Symlinks static ScoDoc
+app/static/links/[0-9]*.*
+
+# Essais locaux
+xp/
diff --git a/app/__init__.py b/app/__init__.py
new file mode 100644
index 0000000..fa80920
--- /dev/null
+++ b/app/__init__.py
@@ -0,0 +1,30 @@
+from flask import current_app, g, request
+from flask import Flask
+
+from config import DevConfig
+
+
+class ReverseProxied:
+ """Adaptateur wsgi qui nous permet d'avoir toutes les URL calculées en https
+ sauf quand on est en dev.
+ La variable HTTP_X_FORWARDED_PROTO est positionnée par notre config nginx"""
+
+ def __init__(self, app):
+ self.app = app
+
+ def __call__(self, environ, start_response):
+ scheme = environ.get("HTTP_X_FORWARDED_PROTO")
+ if scheme:
+ environ["wsgi.url_scheme"] = scheme # ou forcer à https ici ?
+ return self.app(environ, start_response)
+
+
+def create_app(config_class=DevConfig):
+ app = Flask(__name__, static_url_path="/AutoSco/static", static_folder="static")
+ app.config.from_object(config_class)
+ app.wsgi_app = ReverseProxied(app.wsgi_app)
+
+ from app.views import bp
+
+ app.register_blueprint(bp)
+ return app
diff --git a/app/cli.py b/app/cli.py
new file mode 100644
index 0000000..25ae4d4
--- /dev/null
+++ b/app/cli.py
@@ -0,0 +1,7 @@
+# -*- coding: UTF-8 -*
+import os
+import click
+
+
+def register(app):
+ pass
diff --git a/app/templates/base.j2 b/app/templates/base.j2
new file mode 100644
index 0000000..71beceb
--- /dev/null
+++ b/app/templates/base.j2
@@ -0,0 +1,27 @@
+{%- block doc -%}{# Base de toutes les pages AutoSco #}
+
+{%- block html %}
+
+ {%- block head %}
+ {% block title %}{{title|default}}{% endblock title %}
+
+ {%- block metas %}
+
+ {%- endblock metas %}
+
+ {%- endblock head %}
+
+
+ {% block body -%}
+ {% block navbar %}
+ {%- endblock navbar %}
+ {% block content -%}
+ {%- endblock content %}
+
+ {% block scripts %}
+ {%- endblock scripts %}
+ {%- endblock body %}
+
+{%- endblock html %}
+
+{% endblock doc -%}
diff --git a/app/utils/utils.py b/app/utils/utils.py
new file mode 100644
index 0000000..d0ed8fd
--- /dev/null
+++ b/app/utils/utils.py
@@ -0,0 +1,10 @@
+"""AutoSco / utils.py
+"""
+
+import os
+import version
+
+# le répertoire static, lié à chaque release pour éviter les problèmes de caches
+STATIC_DIR = (
+ os.environ.get("SCRIPT_NAME", "") + "/AutoSco/static/links/" + version.VERSION
+)
diff --git a/app/views/__init__.py b/app/views/__init__.py
new file mode 100644
index 0000000..2dce013
--- /dev/null
+++ b/app/views/__init__.py
@@ -0,0 +1,8 @@
+"""AutoSco Flask views"""
+
+from flask import Blueprint
+from flask import g, current_app, request
+
+bp = Blueprint("autosco", __name__)
+
+from app.views import views
diff --git a/app/views/views.py b/app/views/views.py
new file mode 100644
index 0000000..3a51732
--- /dev/null
+++ b/app/views/views.py
@@ -0,0 +1,9 @@
+"""AutoSco / views
+"""
+
+from app.views import bp
+
+
+@bp.route("/")
+def index():
+ return "hello"
diff --git a/autosco.py b/autosco.py
new file mode 100755
index 0000000..c938aba
--- /dev/null
+++ b/autosco.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+"""Application Flask: AutoSco"""
+
+import os
+from pprint import pprint as pp
+
+import click
+import flask
+from flask.cli import with_appcontext
+from flask.templating import render_template
+
+import app as mapp
+from app import create_app, cli
+from app.utils import utils as scu
+
+from config import RunningConfig
+
+app = create_app(RunningConfig)
+cli.register(app)
+
+
+@app.context_processor
+def inject_utils():
+ "Make scu available in all Jinja templates"
+ # if modified, put the same in conftest.py#27
+ return {
+ "DEBUG": flask.current_app.config["DEBUG"],
+ "scu": scu,
+ }
+
+
+@app.shell_context_processor
+def make_shell_context():
+ import app as mapp # le package app
+ from app.utils import sco_utils as scu
+
+ return {
+ "ctx": app.test_request_context(),
+ "current_app": flask.current_app,
+ "current_user": current_user,
+ "datetime": datetime,
+ "flask": flask,
+ "mapp": mapp,
+ "pp": pp,
+ "scu": scu,
+ }
+
+
+if __name__ == "__main__":
+ port = os.environ.get("PORT", 5001)
+ app.run(debug=True, port=port)
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..10b2b85
--- /dev/null
+++ b/config.py
@@ -0,0 +1,82 @@
+import os
+import logging
+from dotenv import load_dotenv
+
+BASEDIR = os.path.abspath(os.path.dirname(__file__))
+load_dotenv(os.path.join(BASEDIR, ".env"))
+
+
+class Config:
+ """General configuration. Mostly loaded from environment via .env"""
+
+ FLASK_ENV = None # # set in subclass
+ SECRET_KEY = os.environ.get("SECRET_KEY") or "90e01e751977d4276a4c70d98564b425e"
+ LOG_TO_STDOUT = os.environ.get("LOG_TO_STDOUT")
+ LOG_LEVEL = getattr(logging, os.environ.get("LOG_LEVEL", "INFO"), "INFO")
+ MAIL_SERVER = os.environ.get("MAIL_SERVER", "localhost")
+ LANGUAGES = ["fr", "en"] # unused for now
+ ADMIN_MAIL = os.environ.get("ADMIN_MAIL")
+ ADMIN_LOGIN = os.environ.get("ADMIN_LOGIN") or "admin"
+ ADMINS = [ADMIN_MAIL]
+ ERR_MAIL = os.environ.get("ERR_MAIL")
+ # Le "from" des mails émis. Attention: peut être remplacée par la préférence email_from_addr:
+ MAIL_FROM = os.environ.get("MAIL_FROM") or ("no-reply@" + MAIL_SERVER)
+
+ AUTOSCO_DIR = os.environ.get("AUTOSCO_DIR", "/opt/autosco")
+ AUTOSCO_VAR_DIR = os.environ.get("AUTOSCO_VAR_DIR", "/opt/autosco-data")
+ AUTOSCO_LOG_FILE = os.path.join(AUTOSCO_VAR_DIR, "log", "autosco.log")
+ # evite confusion avec le log nginx scodoc_error.log:
+ AUTOSCO_ERR_FILE = os.path.join(AUTOSCO_VAR_DIR, "log", "autosco_exc.log")
+ #
+ MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # Flask uploads (16Mo, en ligne avec nginx)
+ # flask_json:
+ JSON_ADD_STATUS = False
+ JSON_USE_ENCODE_METHODS = True
+ JSON_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z" # "%Y-%m-%dT%H:%M:%S"
+
+
+class ProdConfig(Config):
+ "mode production, normalement derrière nginx/gunicorn"
+
+ FLASK_ENV = "production"
+ DEBUG = False
+ TESTING = False
+ PREFERRED_URL_SCHEME = "https"
+
+
+class DevConfig(Config):
+ "mode développement"
+
+ FLASK_ENV = "development"
+ DEBUG = True
+ TESTING = False
+ SECRET_KEY = os.environ.get("DEV_SECRET_KEY") or "cc4fbec7d9a34eb69a7e3e710087d87a"
+
+
+class TestConfig(DevConfig):
+ "Pour les tests unitaires"
+
+ TESTING = True
+ DEBUG = False
+ SERVER_NAME = os.environ.get("AUTOSCO_TEST_SERVER_NAME") or "autotest.gr"
+ SECRET_KEY = os.environ.get("TEST_SECRET_KEY") or "c8ecff5db1592c308f563ff30e0f6bbc"
+
+
+class TestAPIConfig(Config):
+ "Pour les tests de l'API"
+
+ FLASK_ENV = "test_api"
+ TESTING = False
+ DEBUG = True
+ SECRET_KEY = os.environ.get("TEST_SECRET_KEY") or "d8ecff5db15946789Hhahbh88aja276"
+
+
+mode = os.environ.get("FLASK_ENV", "production")
+if mode == "production":
+ RunningConfig = ProdConfig
+elif mode == "development":
+ RunningConfig = DevConfig
+elif mode == "test":
+ RunningConfig = TestConfig
+elif mode == "test_api":
+ RunningConfig = TestAPIConfig
diff --git a/version.py b/version.py
new file mode 100644
index 0000000..cb95558
--- /dev/null
+++ b/version.py
@@ -0,0 +1,3 @@
+VERSION = "0.0.0"
+
+NAME = "AutoSco"