def get_app(config): """ :param config: the configuration dict :return: A new app """ # First, disable debug. It will be enabled in the configuration, later. web.config.debug = False config = _put_configuration_defaults(config) web.config.session_parameters.update(config['session_parameters']) mongo_client = MongoClient( host=config.get('mongo_opt', {}).get('host', 'localhost')) database = mongo_client[config.get('mongo_opt', {}).get('database', 'INGInious')] gridfs = GridFS(database) # Init database if needed db_version = database.db_version.find_one({}) if db_version is None: database.submissions.ensure_index([("username", pymongo.ASCENDING)]) database.submissions.ensure_index([("courseid", pymongo.ASCENDING)]) database.submissions.ensure_index([("courseid", pymongo.ASCENDING), ("taskid", pymongo.ASCENDING)]) database.submissions.ensure_index([("submitted_on", pymongo.DESCENDING) ]) # sort speed database.user_tasks.ensure_index([("username", pymongo.ASCENDING), ("courseid", pymongo.ASCENDING), ("taskid", pymongo.ASCENDING)], unique=True) database.user_tasks.ensure_index([("username", pymongo.ASCENDING), ("courseid", pymongo.ASCENDING)]) database.user_tasks.ensure_index([("courseid", pymongo.ASCENDING), ("taskid", pymongo.ASCENDING)]) database.user_tasks.ensure_index([("courseid", pymongo.ASCENDING)]) database.user_tasks.ensure_index([("username", pymongo.ASCENDING)]) appli = CookieLessCompatibleApplication(MongoStore(database, 'sessions')) # Init gettext available_translations = { "fr": "Français", "es": "Español", "pt": "Português", "el": "ελληνικά", "vi": "Tiếng Việt", "nl": "Nederlands", "de": "Deutsch" } available_languages = {"en": "English"} available_languages.update(available_translations) appli.add_translation( "en", gettext.NullTranslations()) # English does not need translation ;-) for lang in available_translations.keys(): appli.add_translation( lang, gettext.translation('messages', get_root_path() + '/frontend/i18n', [lang])) builtins.__dict__['_'] = appli.gettext if config.get("maintenance", False): template_helper = TemplateHelper(PluginManager(), None, 'frontend/templates', 'frontend/templates/layout', 'frontend/templates/layout_lti', config.get('use_minified_js', True)) template_helper.add_to_template_globals("get_homepath", appli.get_homepath) template_helper.add_to_template_globals("_", _) appli.template_helper = template_helper appli.init_mapping(urls_maintenance) return appli.wsgifunc(), appli.stop default_allowed_file_extensions = config['allowed_file_extensions'] default_max_file_size = config['max_file_size'] zmq_context, __ = start_asyncio_and_zmq(config.get('debug_asyncio', False)) # Init the different parts of the app plugin_manager = PluginManager() # Add the "agent types" inside the frontend, to allow loading tasks and managing envs register_base_env_types() # Create the FS provider if "fs" in config: fs_provider = filesystem_from_config_dict(config["fs"]) else: task_directory = config["tasks_directory"] fs_provider = LocalFSProvider(task_directory) default_task_dispensers = { task_dispenser.get_id(): task_dispenser for task_dispenser in [TableOfContents, CombinatoryTest] } default_problem_types = { problem_type.get_type(): problem_type for problem_type in [ DisplayableCodeProblem, DisplayableCodeSingleLineProblem, DisplayableFileProblem, DisplayableMultipleChoiceProblem, DisplayableMatchProblem ] } course_factory, task_factory = create_factories(fs_provider, default_task_dispensers, default_problem_types, plugin_manager) user_manager = UserManager(appli.get_session(), database, config.get('superadmins', [])) update_pending_jobs(database) client = create_arch(config, fs_provider, zmq_context, course_factory) lti_outcome_manager = LTIOutcomeManager(database, user_manager, course_factory) submission_manager = WebAppSubmissionManager(client, user_manager, database, gridfs, plugin_manager, lti_outcome_manager) template_helper = TemplateHelper(plugin_manager, user_manager, 'frontend/templates', 'frontend/templates/layout', 'frontend/templates/layout_lti', config.get('use_minified_js', True)) register_utils(database, user_manager, template_helper) is_tos_defined = config.get("privacy_page", "") and config.get( "terms_page", "") # Init web mail smtp_conf = config.get('smtp', None) if smtp_conf is not None: web.config.smtp_server = smtp_conf["host"] web.config.smtp_port = int(smtp_conf["port"]) web.config.smtp_starttls = bool(smtp_conf.get("starttls", False)) web.config.smtp_username = smtp_conf.get("username", "") web.config.smtp_password = smtp_conf.get("password", "") web.config.smtp_sendername = smtp_conf.get("sendername", "*****@*****.**") # Add some helpers for the templates template_helper.add_to_template_globals("_", _) template_helper.add_to_template_globals("str", str) template_helper.add_to_template_globals("available_languages", available_languages) template_helper.add_to_template_globals("get_homepath", appli.get_homepath) template_helper.add_to_template_globals( "allow_registration", config.get("allow_registration", True)) template_helper.add_to_template_globals("sentry_io_url", config.get("sentry_io_url")) template_helper.add_to_template_globals("user_manager", user_manager) template_helper.add_to_template_globals("default_allowed_file_extensions", default_allowed_file_extensions) template_helper.add_to_template_globals("default_max_file_size", default_max_file_size) template_helper.add_to_template_globals("is_tos_defined", is_tos_defined) template_helper.add_other( "course_admin_menu", lambda course, current: course_admin_utils.get_menu( course, current, template_helper.get_renderer(False), plugin_manager, user_manager)) template_helper.add_other( "preferences_menu", lambda current: preferences_utils.get_menu( appli, current, template_helper.get_renderer(False), plugin_manager, user_manager)) # Not found page appli.notfound = lambda message='Page not found': web.notfound( template_helper.get_renderer().notfound(message)) # Forbidden page appli.forbidden = lambda message='Forbidden': web.forbidden( template_helper.get_renderer().forbidden(message)) # Enable stacktrace display if needed web_debug = config.get('web_debug', False) appli.internalerror = internalerror_generator( template_helper.get_renderer(False)) if web_debug is True: web.config.debug = True appli.internalerror = debugerror elif isinstance(web_debug, str): web.config.debug = False appli.internalerror = emailerrors(web_debug, appli.internalerror) # Insert the needed singletons into the application, to allow pages to call them appli.plugin_manager = plugin_manager appli.course_factory = course_factory appli.task_factory = task_factory appli.submission_manager = submission_manager appli.user_manager = user_manager appli.template_helper = template_helper appli.database = database appli.gridfs = gridfs appli.client = client appli.default_allowed_file_extensions = default_allowed_file_extensions appli.default_max_file_size = default_max_file_size appli.backup_dir = config.get("backup_directory", './backup') appli.webterm_link = config.get("webterm", None) appli.lti_outcome_manager = lti_outcome_manager appli.allow_registration = config.get("allow_registration", True) appli.allow_deletion = config.get("allow_deletion", True) appli.available_languages = available_languages appli.welcome_page = config.get("welcome_page", None) appli.terms_page = config.get("terms_page", None) appli.privacy_page = config.get("privacy_page", None) appli.static_directory = config.get("static_directory", "./static") appli.webdav_host = config.get("webdav_host", None) # Init the mapping of the app appli.init_mapping(urls) # Loads plugins plugin_manager.load(client, appli, course_factory, task_factory, database, user_manager, submission_manager, config.get("plugins", [])) # Start the inginious.backend client.start() return appli.wsgifunc(), lambda: _close_app(appli, mongo_client, client)
def get_app(config): """ :param config: the configuration dict :return: A new app """ # First, disable debug. It will be enabled in the configuration, later. config = _put_configuration_defaults(config) mongo_client = MongoClient( host=config.get('mongo_opt', {}).get('host', 'localhost')) database = mongo_client[config.get('mongo_opt', {}).get('database', 'INGInious')] gridfs = GridFS(database) # Init database if needed db_version = database.db_version.find_one({}) if db_version is None: database.submissions.ensure_index([("username", pymongo.ASCENDING)]) database.submissions.ensure_index([("courseid", pymongo.ASCENDING)]) database.submissions.ensure_index([("courseid", pymongo.ASCENDING), ("taskid", pymongo.ASCENDING)]) database.submissions.ensure_index([("submitted_on", pymongo.DESCENDING) ]) # sort speed database.user_tasks.ensure_index([("username", pymongo.ASCENDING), ("courseid", pymongo.ASCENDING), ("taskid", pymongo.ASCENDING)], unique=True) database.user_tasks.ensure_index([("username", pymongo.ASCENDING), ("courseid", pymongo.ASCENDING)]) database.user_tasks.ensure_index([("courseid", pymongo.ASCENDING), ("taskid", pymongo.ASCENDING)]) database.user_tasks.ensure_index([("courseid", pymongo.ASCENDING)]) database.user_tasks.ensure_index([("username", pymongo.ASCENDING)]) flask_app = flask.Flask(__name__) flask_app.config.from_mapping(**config) flask_app.session_interface = MongoDBSessionInterface( mongo_client, config.get('mongo_opt', {}).get('database', 'INGInious'), "sessions", config.get('SESSION_USE_SIGNER', False), True # config.get('SESSION_PERMANENT', True) ) # Init gettext available_translations = { "fr": "Français", "es": "Español", "pt": "Português", "el": "ελληνικά", "vi": "Tiếng Việt", "nl": "Nederlands", "de": "Deutsch" } available_languages = {"en": "English"} available_languages.update(available_translations) l10n_manager = L10nManager() l10n_manager.translations["en"] = gettext.NullTranslations( ) # English does not need translation ;-) for lang in available_translations.keys(): l10n_manager.translations[lang] = gettext.translation( 'messages', get_root_path() + '/frontend/i18n', [lang]) builtins.__dict__['_'] = l10n_manager.gettext if config.get("maintenance", False): template_helper = TemplateHelper(PluginManager(), None, config.get('use_minified_js', True)) template_helper.add_to_template_globals("get_homepath", get_homepath) template_helper.add_to_template_globals("pkg_version", __version__) template_helper.add_to_template_globals("available_languages", available_languages) template_helper.add_to_template_globals("_", _) flask_app.template_helper = template_helper init_flask_maintenance_mapping(flask_app) return flask_app.wsgi_app, lambda: None default_allowed_file_extensions = config['allowed_file_extensions'] default_max_file_size = config['max_file_size'] zmq_context, __ = start_asyncio_and_zmq(config.get('debug_asyncio', False)) # Init the different parts of the app plugin_manager = PluginManager() # Add the "agent types" inside the frontend, to allow loading tasks and managing envs register_base_env_types() # Create the FS provider if "fs" in config: fs_provider = filesystem_from_config_dict(config["fs"]) else: task_directory = config["tasks_directory"] fs_provider = LocalFSProvider(task_directory) default_task_dispensers = { task_dispenser.get_id(): task_dispenser for task_dispenser in [TableOfContents, CombinatoryTest] } default_problem_types = { problem_type.get_type(): problem_type for problem_type in [ DisplayableCodeProblem, DisplayableCodeSingleLineProblem, DisplayableFileProblem, DisplayableMultipleChoiceProblem, DisplayableMatchProblem ] } course_factory, task_factory = create_factories(fs_provider, default_task_dispensers, default_problem_types, plugin_manager) user_manager = UserManager(database, config.get('superadmins', [])) update_pending_jobs(database) client = create_arch(config, fs_provider, zmq_context, course_factory) lti_outcome_manager = LTIOutcomeManager(database, user_manager, course_factory) submission_manager = WebAppSubmissionManager(client, user_manager, database, gridfs, plugin_manager, lti_outcome_manager) template_helper = TemplateHelper(plugin_manager, user_manager, config.get('use_minified_js', True)) register_utils(database, user_manager, template_helper) is_tos_defined = config.get("privacy_page", "") and config.get( "terms_page", "") # Init web mail mail.init_app(flask_app) # Add some helpers for the templates template_helper.add_to_template_globals("_", _) template_helper.add_to_template_globals("str", str) template_helper.add_to_template_globals("available_languages", available_languages) template_helper.add_to_template_globals("get_homepath", get_homepath) template_helper.add_to_template_globals("pkg_version", __version__) template_helper.add_to_template_globals( "allow_registration", config.get("allow_registration", True)) template_helper.add_to_template_globals("sentry_io_url", config.get("sentry_io_url")) template_helper.add_to_template_globals("user_manager", user_manager) template_helper.add_to_template_globals("default_allowed_file_extensions", default_allowed_file_extensions) template_helper.add_to_template_globals("default_max_file_size", default_max_file_size) template_helper.add_to_template_globals("is_tos_defined", is_tos_defined) template_helper.add_other( "course_admin_menu", lambda course, current: course_admin_utils.get_menu( course, current, template_helper.render, plugin_manager, user_manager)) template_helper.add_other( "preferences_menu", lambda current: preferences_utils.get_menu( config.get("allow_deletion", True), current, template_helper. render, plugin_manager, user_manager)) # Not found page def flask_not_found(e): return template_helper.render("notfound.html", message=e.description), 404 flask_app.register_error_handler(404, flask_not_found) # Forbidden page def flask_forbidden(e): return template_helper.render("forbidden.html", message=e.description), 403 flask_app.register_error_handler(403, flask_forbidden) # Enable stacktrace display if needed web_debug = config.get('web_debug', False) def flask_internalerror(e): return template_helper.render("internalerror.html", message=e.description), 500 flask_app.register_error_handler(InternalServerError, flask_internalerror) if web_debug is True: flask_app.debug = True elif isinstance(web_debug, str): flask_app.debug = False # Insert the needed singletons into the application, to allow pages to call them flask_app.get_homepath = get_homepath flask_app.plugin_manager = plugin_manager flask_app.course_factory = course_factory flask_app.task_factory = task_factory flask_app.submission_manager = submission_manager flask_app.user_manager = user_manager flask_app.l10n_manager = l10n_manager flask_app.template_helper = template_helper flask_app.database = database flask_app.gridfs = gridfs flask_app.client = client flask_app.default_allowed_file_extensions = default_allowed_file_extensions flask_app.default_max_file_size = default_max_file_size flask_app.backup_dir = config.get("backup_directory", './backup') flask_app.webterm_link = config.get("webterm", None) flask_app.lti_outcome_manager = lti_outcome_manager flask_app.allow_registration = config.get("allow_registration", True) flask_app.allow_deletion = config.get("allow_deletion", True) flask_app.available_languages = available_languages flask_app.welcome_page = config.get("welcome_page", None) flask_app.terms_page = config.get("terms_page", None) flask_app.privacy_page = config.get("privacy_page", None) flask_app.static_directory = config.get("static_directory", "./static") flask_app.webdav_host = config.get("webdav_host", None) # Init the mapping of the app init_flask_mapping(flask_app) # Loads plugins plugin_manager.load(client, flask_app, course_factory, task_factory, database, user_manager, submission_manager, config.get("plugins", [])) # Start the inginious.backend client.start() return flask_app.wsgi_app, lambda: _close_app(mongo_client, client)