#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2025 Étienne Loks # 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 . # See the file COPYING for details. import datetime import os import re from django.conf import settings from django.core.cache import cache from django.contrib.sites.models import Site from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from ishtar_common.version import __version__ from ishtar_common.models import get_current_profile from ishtar_common.models_rest import ApiExternalSource, ApiKeyMatch from bootstrap_datepicker.widgets import DatePicker from .menus import Menu def _get_changelog_version_from_file(): changelog_dir = os.path.join( settings.SHARE_BASE_PATH, "changelog", settings.LANGUAGE_CODE.split('-')[0] ) if not os.path.exists(changelog_dir): return "no-version" filename = "" for fle in reversed(sorted(os.listdir(changelog_dir))): if not fle.startswith("changelog_") or not fle.endswith(".md"): continue filename = fle break if not filename: return "no-version" changelog_file = os.path.join(changelog_dir, filename) current_version = None with open(changelog_file, "r", encoding="utf-8") as changelog: for line in changelog.readlines(): m = re.match(r"v(\d+)\.(\d+)\.(\d+)", line) if not m: continue g = m.groups() if len(g) != 3: continue current_version = ".".join(g) break if not current_version: return "no-version" return current_version def get_changelog_version(): cache_key = f"{settings.PROJECT_SLUG}-news-version" current_version = cache.get(cache_key) if current_version: return current_version if not current_version: current_version = _get_changelog_version_from_file() cache.set(cache_key, current_version, settings.CACHE_LONGTIMEOUT) return current_version def get_base_context(request): dct = { "URL_PATH": settings.URL_PATH, "BASE_URL": "", "ISHTAR_MAP_MAX_ITEMS": settings.ISHTAR_MAP_MAX_ITEMS, } if "HTTP_HOST" in request.META: dct["BASE_URL"] = "{}://{}".format(request.scheme, request.META["HTTP_HOST"]) try: dct["APP_NAME"] = Site.objects.get_current().name except Site.DoesNotExist: dct["APP_NAME"] = settings.APP_NAME dct["COUNTRY"] = settings.COUNTRY current_action = None if "CURRENT_ACTION" in request.session: dct["CURRENT_ACTION"] = request.session["CURRENT_ACTION"] current_action = dct["CURRENT_ACTION"] dct["CURRENT_PATH"] = request.path dct["SITE_PROFILE"] = get_current_profile() is_main_page = not request.is_ajax() and not getattr(request, "is_js", False) # messages dct["MESSAGES"] = [] if ( is_main_page and "messages" in request.session and request.session["messages"] ): for message, message_type in request.session["messages"]: dct["MESSAGES"].append((message, message_type)) request.session["messages"] = [] menu = Menu(request.user, current_action=current_action, session=request.session) menu.init() if is_main_page and hasattr(request.user, "ishtaruser") \ and request.user.ishtaruser: # check password expiration date if settings.ISHTAR_PASSWORD_EXPIRATION_DAYS and \ isinstance(settings.ISHTAR_PASSWORD_EXPIRATION_DAYS, int): key = f"{settings.PROJECT_SLUG}-password_expired-{request.user.pk}" password_expired = cache.get(key) if password_expired is None: password_expired = True d = datetime.date.today() - request.user.ishtaruser.password_last_update if d.days < settings.ISHTAR_PASSWORD_EXPIRATION_DAYS: password_expired = False cache.set(key, password_expired, settings.CACHE_TIMEOUT) if password_expired and not request.path.endswith("password_change/"): msg = str(_("Your password has expired. Please update it using this " "
.")) form_str = _("form") msg = msg.replace( "", f'' f'{form_str} ' f'' '' ) dct["MESSAGES"].append((msg, "warning")) # check changelog if request.user.ishtaruser.display_news: user_version = request.user.ishtaruser.latest_news_version current_version = get_changelog_version() if current_version != user_version and "changelog" not in dct["CURRENT_PATH"]: if "info_version_displayed" not in request.session: request.session["info_version_displayed"] = 0 request.session["info_version_displayed"] += 1 if request.session["info_version_displayed"] >= 10: request.user.ishtaruser.latest_news_version = current_version request.user.ishtaruser.save() request.session['info_version_displayed'] = 0 if user_version: msg = str(_("Since your last login, Ishtar has been updated from version to " ". Check the .")) else: msg = str(_("Since your last login, Ishtar has been updated to version . " "Check the .")) changelog_str = _("changelog") msg = msg.replace( "", f'' f'{changelog_str} ' f'' f'' ).replace("", user_version).replace("", current_version) dct["MESSAGES"].append((msg, "info")) # external sources if ( request.user.ishtaruser.current_profile and "EXTERNAL_SOURCES" not in request.session ): q = ApiExternalSource.objects.filter( profiles=request.user.ishtaruser.current_profile ) request.session["EXTERNAL_SOURCES"] = {} if q.count(): for source in q.all(): request.session["EXTERNAL_SOURCES"][ f"{source.id}||{source.name}" ] = [ f"{app_label}-{model_name}" for app_label, model_name in ApiKeyMatch.objects.values_list( "search_model__app_label", "search_model__model" ).distinct() ] if request.user.ishtaruser.has_permission("ishtaradmin"): dct["ADMIN"] = True if ( request.user.ishtaruser.current_profile and request.user.ishtaruser.current_profile.display_pin_menu ): dct["DISPLAY_PIN_MENU"] = True if menu.selected_idx is not None: dct["current_theme"] = "theme-%d" % (menu.selected_idx + 1) dct["MENU"] = menu menu.get_current_selection(request.path) dct["JQUERY_URL"] = settings.JQUERY_URL dct["JQUERY_UI_URL"] = settings.JQUERY_UI_URL dct["COUNTRY"] = settings.COUNTRY dct["VERSION"] = __version__ dct["DEBUG"] = settings.DEBUG medias = [DatePicker().media] dct["EXTRA_CSS"] = "" dct["EXTRA_JS"] = "" for media in medias: dct["EXTRA_CSS"] += "\n" + "\n".join(media.render_css()) dct["EXTRA_JS"] += "\n" + "\n".join(media.render_js()) if settings.EXTRA_VERSION: dct["VERSION"] += "-" + str(settings.EXTRA_VERSION) return dct