view libervia/web/pages/g/page_meta.py @ 1599:197350e8bf3b

pages(g): fix guest session data: Following https://repos.goffi.org/libervia-web/rev/86c7a3a625d5, new session are now started on connection, as a result, guest data were lost on connection. This patch fixes it by storing those data after the connection.
author Goffi <goffi@goffi.org>
date Tue, 05 Mar 2024 16:40:25 +0100
parents eb00d593801d
children
line wrap: on
line source

#!/usr/bin/env python3


from libervia.web.server.constants import Const as C
from libervia.backend.core.i18n import _
from libervia.web.server import session_iface
from libervia.backend.core.log import getLogger

log = getLogger(__name__)

access = C.PAGES_ACCESS_PUBLIC
template = "invitation/welcome.html"


async def parse_url(self, request):
    """check invitation id in URL and start session if needed

    if a session already exists for an other guest/profile, it will be purged
    """
    try:
        invitation_id = self.next_path(request)
    except IndexError:
        self.page_error(request)
        return

    web_session, guest_session = self.host.get_session_data(
        request, session_iface.IWebSession, session_iface.IWebGuestSession
    )
    current_id = guest_session.id

    if current_id is not None and current_id != invitation_id:
        # we are already in a guest session, but not the one specified in URL, we reset id
        log.info(
            _(
                "killing guest session [{old_id}] because it is connecting with an other ID [{new_id}]"
            ).format(old_id=current_id, new_id=invitation_id)
        )
        self.host.purge_session(request)
        web_session, guest_session = self.host.get_session_data(
            request, session_iface.IWebSession, session_iface.IWebGuestSession
        )
        current_id = None  # FIXME: id not reset here
        profile = None

    profile = web_session.profile
    if profile is not None and current_id is None:
        log.info(
            _(
                "killing current profile session [{profile}] because a guest id is used"
            ).format(profile=profile)
        )
        self.host.purge_session(request)
        web_session, guest_session = self.host.get_session_data(
            request, session_iface.IWebSession, session_iface.IWebGuestSession
        )
        profile = None

    if current_id is None:
        log.debug(_("checking invitation [{id}]").format(id=invitation_id))
        try:
            data = await self.host.bridge_call("invitation_get", invitation_id)
        except Exception:
            self.page_error(request, C.HTTP_FORBIDDEN)
            return
    else:
        data = guest_session.data

    if profile is None:
        log.debug(_("connecting profile [{}]").format(profile))
        # we need to connect the profile
        profile = data["guest_profile"]
        password = data["password"]
        try:
            await self.host.connect(request, profile, password)
        except Exception as e:
            log.warning(_("Can't connect profile: {msg}").format(msg=e))
            # FIXME: no good error code correspond
            #        maybe use a custom one?
            self.page_error(request, code=C.HTTP_SERVICE_UNAVAILABLE)
        else:
            # a new session is created, we need to store guest session data
            __, guest_session = self.host.get_session_data(
                request, session_iface.IWebSession, session_iface.IWebGuestSession
            )
            guest_session.id = invitation_id
            guest_session.data = data

        log.info(
            _(
                "guest session started, connected with profile [{profile}]".format(
                    profile=profile
                )
            )
        )

    # we copy data useful in templates
    template_data = request.template_data
    template_data["norobots"] = True
    if "name" in data:
        template_data["name"] = data["name"]
    if "language" in data:
        template_data["locale"] = data["language"]

def handle_event_interest(self, interest):
    if C.bool(interest.get("creator", C.BOOL_FALSE)):
        page_name = "event_admin"
    else:
        page_name = "event_rsvp"

    interest["url"] = self.get_page_by_name(page_name).get_url(
        interest.get("service", ""),
        interest.get("node", ""),
        interest.get("item"),
        )

    if "thumb_url" not in interest and "image" in interest:
        interest["thumb_url"] = interest["image"]

def handle_fis_interest(self, interest):
    path = interest.get('path', '')
    path_args = [p for p in path.split('/') if p]
    subtype = interest.get('subtype')

    if subtype == 'files':
        page_name = "files_view"
    elif interest.get('subtype') == 'photos':
        page_name = "photos_album"
    else:
        log.warning("unknown interest subtype: {subtype}".format(subtype=subtype))
        return False

    interest["url"] = self.get_page_by_name(page_name).get_url(
        interest['service'], *path_args)

async def prepare_render(self, request):
    template_data = request.template_data
    profile = self.get_profile(request)

    # interests
    template_data['interests_map'] = interests_map = {}
    try:
        interests = await self.host.bridge_call(
            "interests_list", "", "", "", profile)
    except Exception:
        log.warning(_("Can't get interests list for {profile}").format(
            profile=profile))
    else:
        # we only want known interests (photos and events for now)
        # this dict map namespaces of interest to a callback which can manipulate
        # the data. If it returns False, the interest is skipped
        ns_data = {}

        for short_name, cb in (('event', handle_event_interest),
                               ('fis', handle_fis_interest),
                              ):
            try:
                namespace = self.host.ns_map[short_name]
            except KeyError:
                pass
            else:
                ns_data[namespace] = (cb, short_name)

        for interest in interests:
            namespace = interest.get('namespace')
            if namespace not in ns_data:
                continue
            cb, short_name = ns_data[namespace]
            if cb(self, interest) == False:
                continue
            key = interest.get('subtype', short_name)
            interests_map.setdefault(key, []).append(interest)

    # main URI
    guest_session = self.host.get_session_data(request, session_iface.IWebGuestSession)
    main_uri = guest_session.data.get("event_uri")
    if main_uri:
        include_url = self.get_page_path_from_uri(main_uri)
        if include_url is not None:
            template_data["include_url"] = include_url