comparison libervia/server/pages.py @ 1483:595e7fef41f3

merge bookmark @
author Goffi <goffi@goffi.org>
date Fri, 12 Nov 2021 17:48:30 +0100
parents 095e94ca6728
children 774a81a6e8b5
comparison
equal deleted inserted replaced
1454:fc91b78b71db 1483:595e7fef41f3
544 log.info(_("{page} created").format(page=resource)) 544 log.info(_("{page} created").format(page=resource))
545 else: 545 else:
546 log.info(_("{page} reloaded").format(page=resource)) 546 log.info(_("{page} reloaded").format(page=resource))
547 547
548 def checkCSRF(self, request): 548 def checkCSRF(self, request):
549 csrf_token = self.host.getSessionData( 549 session = self.host.getSessionData(
550 request, session_iface.ISATSession 550 request, session_iface.ISATSession
551 ).csrf_token 551 )
552 if session.profile is None:
553 # CSRF doesn't make sense when no user is logged
554 log.debug("disabling CSRF check because service profile is used")
555 return
556 csrf_token = session.csrf_token
552 given_csrf = request.getHeader("X-Csrf-Token") 557 given_csrf = request.getHeader("X-Csrf-Token")
553 if given_csrf is None: 558 if given_csrf is None:
554 try: 559 try:
555 given_csrf = self.getPostedData(request, "csrf_token") 560 given_csrf = self.getPostedData(request, "csrf_token")
556 except KeyError: 561 except KeyError:
575 template_data = request.template_data 580 template_data = request.template_data
576 scripts = template_data.setdefault("scripts", utils.OrderedSet()) 581 scripts = template_data.setdefault("scripts", utils.OrderedSet())
577 for name, value in kwargs.items(): 582 for name, value in kwargs.items():
578 if value is None: 583 if value is None:
579 value = "null" 584 value = "null"
585 elif isinstance(value, str):
586 # FIXME: workaround for subtype used by python-dbus (dbus.String)
587 # to be removed when we get rid of python-dbus
588 value = repr(str(value))
580 else: 589 else:
581 value = repr(value) 590 value = repr(value)
582 scripts.add(Script(content=f"var {name}={value};")) 591 scripts.add(Script(content=f"var {name}={value};"))
583 592
584 def registerURI(self, uri_tuple, get_uri_cb): 593 def registerURI(self, uri_tuple, get_uri_cb):
663 redirect_url=urllib.parse.quote_plus(request.uri) 672 redirect_url=urllib.parse.quote_plus(request.uri)
664 if url is None 673 if url is None
665 else url.encode("utf-8"), 674 else url.encode("utf-8"),
666 ) 675 )
667 676
668 def getURL(self, *args): 677 def getURL(self, *args: str, **kwargs: str) -> str:
669 """retrieve URL of the page set arguments 678 """retrieve URL of the page set arguments
670 679
671 *args(list[unicode]): argument to add to the URL as path elements 680 @param *args: arguments to add to the URL as path elements empty or None
672 empty or None arguments will be ignored 681 arguments will be ignored
682 @param **kwargs: query parameters
673 """ 683 """
674 url_args = [quote(a) for a in args if a] 684 url_args = [quote(a) for a in args if a]
675 685
676 if self.name is not None and self.name in self.pages_redirects: 686 if self.name is not None and self.name in self.pages_redirects:
677 #  we check for redirection 687 #  we check for redirection
678 redirect_data = self.pages_redirects[self.name] 688 redirect_data = self.pages_redirects[self.name]
679 args_hash = tuple(args) 689 args_hash = tuple(args)
680 for limit in range(len(args) + 1): 690 for limit in range(len(args), -1, -1):
681 current_hash = args_hash[:limit] 691 current_hash = args_hash[:limit]
682 if current_hash in redirect_data: 692 if current_hash in redirect_data:
683 url_base = redirect_data[current_hash] 693 url_base = redirect_data[current_hash]
684 remaining = args[limit:] 694 remaining = args[limit:]
685 remaining_url = "/".join(remaining) 695 remaining_url = "/".join(remaining)
686 return os.path.join("/", url_base, remaining_url) 696 url = urllib.parse.urljoin(url_base, remaining_url)
687 697 break
688 return os.path.join(self.url, *url_args) 698 else:
699 url = os.path.join(self.url, *url_args)
700 else:
701 url = os.path.join(self.url, *url_args)
702
703 if kwargs:
704 encoded = urllib.parse.urlencode(
705 {k: v for k, v in kwargs.items()}
706 )
707 url += f"?{encoded}"
708
709 return self.host.checkRedirection(
710 self.vhost_root,
711 url
712 )
689 713
690 def getCurrentURL(self, request): 714 def getCurrentURL(self, request):
691 """retrieve URL used to access this page 715 """retrieve URL used to access this page
692 716
693 @return(unicode): current URL 717 @return(unicode): current URL
959 if extra is None: 983 if extra is None:
960 extra = {} 984 extra = {}
961 else: 985 else:
962 assert not {"rsm_max", "rsm_after", "rsm_before", 986 assert not {"rsm_max", "rsm_after", "rsm_before",
963 C.KEY_ORDER_BY}.intersection(list(extra.keys())) 987 C.KEY_ORDER_BY}.intersection(list(extra.keys()))
964 extra["rsm_max"] = str(page_max) 988 extra["rsm_max"] = params.get("page_max", str(page_max))
965 if order_by is not None: 989 if order_by is not None:
966 extra[C.KEY_ORDER_BY] = order_by 990 extra[C.KEY_ORDER_BY] = order_by
967 if 'after' in params: 991 if 'after' in params:
968 extra['rsm_after'] = params['after'] 992 extra['rsm_after'] = params['after']
969 elif 'before' in params: 993 elif 'before' in params:
972 # RSM returns list in order (oldest first), but we want most recent first 996 # RSM returns list in order (oldest first), but we want most recent first
973 # so we start by the end 997 # so we start by the end
974 extra['rsm_before'] = "" 998 extra['rsm_before'] = ""
975 return extra 999 return extra
976 1000
977 def setPagination(self, request, pubsub_data): 1001 def setPagination(self, request: server.Request, pubsub_data: dict) -> None:
978 """Add to template_data if suitable 1002 """Add to template_data if suitable
979 1003
980 "previous_page_url" and "next_page_url" will be added using respectively 1004 "previous_page_url" and "next_page_url" will be added using respectively
981 "before" and "after" URL parameters 1005 "before" and "after" URL parameters
982 @param request(server.Request): current HTTP request 1006 @param request: current HTTP request
983 @param pubsub_data(dict): pubsub metadata 1007 @param pubsub_data: pubsub metadata
984 """ 1008 """
985 template_data = request.template_data 1009 template_data = request.template_data
986 extra = {} 1010 extra = {}
987 try: 1011 try:
988 rsm = pubsub_data["rsm"] 1012 rsm = pubsub_data["rsm"]
993 1017
994 # if we have a search query, we must keep it 1018 # if we have a search query, we must keep it
995 search = self.getPostedData(request, 'search', raise_on_missing=False) 1019 search = self.getPostedData(request, 'search', raise_on_missing=False)
996 if search is not None: 1020 if search is not None:
997 extra['search'] = search.strip() 1021 extra['search'] = search.strip()
1022
1023 # same for page_max
1024 page_max = self.getPostedData(request, 'page_max', raise_on_missing=False)
1025 if page_max is not None:
1026 extra['page_max'] = page_max
998 1027
999 if rsm.get("index", 1) > 0: 1028 if rsm.get("index", 1) > 0:
1000 # We only show previous button if it's not the first page already. 1029 # We only show previous button if it's not the first page already.
1001 # If we have no index, we default to display the button anyway 1030 # If we have no index, we default to display the button anyway
1002 # as we can't know if we are on the first page or not. 1031 # as we can't know if we are on the first page or not.
1707 matching value with available translations. 1736 matching value with available translations.
1708 """ 1737 """
1709 accept_language = request.getHeader("accept-language") 1738 accept_language = request.getHeader("accept-language")
1710 if not accept_language: 1739 if not accept_language:
1711 return 1740 return
1712 accepted = {a.strip() for a in accept_language.split(',')} 1741 accepted = [a.strip() for a in accept_language.split(',')]
1713 available = [str(l) for l in self.host.renderer.translations] 1742 available = [str(l) for l in self.host.renderer.translations]
1714 for lang in accepted: 1743 for lang in accepted:
1715 lang = lang.split(';')[0].strip().lower() 1744 lang = lang.split(';')[0].strip().lower()
1716 if not lang: 1745 if not lang:
1717 continue 1746 continue
1783 # template_data are the variables passed to template 1812 # template_data are the variables passed to template
1784 if not hasattr(request, "template_data"): 1813 if not hasattr(request, "template_data"):
1785 # if template_data doesn't exist, it's the beginning of the request workflow 1814 # if template_data doesn't exist, it's the beginning of the request workflow
1786 # so we fill essential data 1815 # so we fill essential data
1787 session_data = self.host.getSessionData(request, session_iface.ISATSession) 1816 session_data = self.host.getSessionData(request, session_iface.ISATSession)
1817 profile = session_data.profile
1788 request.template_data = { 1818 request.template_data = {
1789 "profile": session_data.profile, 1819 "profile": profile,
1790 "csrf_token": session_data.csrf_token, 1820 # it's important to not add CSRF token and session uuid if service profile
1791 "session_uuid": session_data.uuid, 1821 # is used because the page may be cached, and the token then leaked
1822 "csrf_token": "" if profile is None else session_data.csrf_token,
1823 "session_uuid": "public" if profile is None else session_data.uuid,
1792 "breadcrumbs": [] 1824 "breadcrumbs": []
1793 } 1825 }
1794 1826
1795 # XXX: here is the code which need to be executed once 1827 # XXX: here is the code which need to be executed once
1796 # at the beginning of the request hanling 1828 # at the beginning of the request hanling