Skip to content

Commit b8cfff6

Browse files
committed
feat(dev): login domains, qualified locale;
- Fix local_url patch method to allow for qualified domains with passed locale. - Fix the lang domain index method. - Added monkey patch for the `HostHeaderMiddleware` class to allow for language domains on the user authentication routes.
1 parent cf3db27 commit b8cfff6

File tree

2 files changed

+50
-25
lines changed

2 files changed

+50
-25
lines changed

ckanext/language_domains/helpers.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from urllib.parse import urlsplit
77
import re
88

9-
from typing import Any, cast, Union, Tuple, Dict
9+
from typing import Any, cast, Union, Tuple, Dict, Optional
1010
from ckan.types import Response
1111

1212
from ckan.exceptions import CkanUrlException
@@ -20,11 +20,11 @@ def _get_domain_index(current_domain: str, language_domains: Dict[str, str]) ->
2020
try:
2121
return lang_domains.index(current_domain)
2222
except ValueError:
23-
return 0
23+
continue
2424
return 0
2525

2626

27-
def _get_correct_language_domain() -> Tuple[str, str]:
27+
def _get_correct_language_domain(locale: Optional[str] = None) -> Tuple[str, str]:
2828
"""
2929
Returns the HTTP scheme and mapped domain for the current language.
3030
@@ -38,7 +38,7 @@ def _get_correct_language_domain() -> Tuple[str, str]:
3838
uri_parts = urlsplit(default_domain)
3939
default_scheme = uri_parts.scheme
4040
language_domains = config.get('ckanext.language_domains.domain_map')
41-
current_lang = h.lang()
41+
current_lang = locale or h.lang()
4242
correct_lang_domain = current_domain
4343
domain_index_match = _get_domain_index(current_domain, language_domains)
4444
for lang_code, lang_domains in language_domains.items():
@@ -84,12 +84,13 @@ def redirect_to(*args: Any, **kw: Any) -> Response:
8484
return cast(Response, _flask_redirect(_url, code=status_code))
8585

8686

87-
def get_site_protocol_and_host() -> Union[Tuple[str, str], Tuple[None, None]]:
87+
def get_site_protocol_and_host(locale: Optional[str] = None) -> Union[
88+
Tuple[str, str], Tuple[None, None]]:
8889
"""
8990
Overrides and monkey patches the Core helper get_site_protocol_and_host
9091
to use ckanext.language_domains.domain_map instead of ckan.site_url
9192
"""
92-
return _get_correct_language_domain()
93+
return _get_correct_language_domain(locale=locale)
9394

9495

9596
def local_url(url_to_amend: str, **kw: Any):
@@ -120,7 +121,7 @@ def local_url(url_to_amend: str, **kw: Any):
120121
default_locale = True
121122

122123
root = ''
123-
protocol, host = get_site_protocol_and_host()
124+
protocol, host = get_site_protocol_and_host(locale)
124125
if kw.get('qualified', False) or kw.get('_external', False):
125126
# if qualified is given we want the full url ie http://...
126127
parts = urlparse(
@@ -139,24 +140,18 @@ def local_url(url_to_amend: str, **kw: Any):
139140
# position in the url
140141
root_paths = config.get('ckanext.language_domains.root_paths')
141142
root_path = root_paths.get(host, '').rstrip('/')
142-
if root_path:
143-
# FIXME this can be written better once
144-
# the merge into the portal core is done
145-
# we have a special root specified so use that
146-
if default_locale:
147-
root_path = re.sub('/{{LANG}}', '', root_path)
148-
else:
149-
root_path = re.sub('{{LANG}}', str(locale), root_path)
150-
# make sure we don't have a trailing / on the root
151-
if root_path[-1] == '/':
152-
root_path = root_path[:-1]
143+
if default_locale:
144+
root_path = re.sub('/{{LANG}}', '', root_path)
153145
else:
154-
if default_locale:
155-
root_path = ''
156-
else:
157-
root_path = '/' + str(locale)
158-
159-
url_path = url_to_amend[len(root):]
146+
root_path = re.sub('{{LANG}}', str(locale), root_path)
147+
# make sure we don't have a trailing / on the root
148+
if root_path and root_path[-1] == '/':
149+
root_path = root_path[:-1]
150+
151+
# root_path domain may be different from url_to_amend domain
152+
# if a different locale is provided. Just use urlsplit.path
153+
url_to_amend_parts = urlsplit(url_to_amend)
154+
url_path = url_to_amend_parts.path
160155
url = '%s%s%s' % (root, root_path, url_path)
161156

162157
# stop the root being added twice in redirects

ckanext/language_domains/plugin.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from logging import getLogger
2-
from urllib.parse import urlsplit
2+
from urllib.parse import urlparse, urlsplit
33

44
from typing import Any, Optional, List, Tuple, Callable, Dict
55
from flask import Blueprint
@@ -8,6 +8,7 @@
88

99
import ckan.plugins as plugins
1010
import ckan.lib.helpers as core_helpers
11+
from ckan.config.middleware import flask_app
1112

1213
from ckanext.language_domains import helpers, validators
1314
from ckanext.language_domains.blueprint import language_domain_views
@@ -26,6 +27,9 @@ class LanguageDomainsPlugin(plugins.SingletonPlugin):
2627

2728
# IMiddleware
2829
def make_middleware(self, app: CKANApp, config: 'CKANConfig') -> CKANApp:
30+
# NOTE: monkey patch the HostHeaderMiddleware to allow for
31+
# language domains on the user authentication routes.
32+
flask_app.HostHeaderMiddleware = LanguageDomainHostHeaderMiddleware
2933
return LanguageDomainMiddleware(app, config)
3034

3135
# IConfigurer
@@ -129,3 +133,29 @@ def _start_response(status: str,
129133
exc_info)
130134

131135
return self.app(environ, _start_response)
136+
137+
138+
class LanguageDomainHostHeaderMiddleware(object):
139+
"""
140+
Override the core HostHeaderMiddleware to allow for
141+
language domains on the user authentication routes.
142+
"""
143+
def __init__(self, app: CKANApp):
144+
self.app = app
145+
146+
def __call__(self, environ: Any, start_response: Any) -> Any:
147+
path_info = environ['PATH_INFO']
148+
if path_info in ['/login_generic', '/user/login',
149+
'/user/logout', '/user/logged_in',
150+
'/user/logged_out']:
151+
site_url = plugins.toolkit.config.get('ckan.site_url')
152+
parts = urlparse(site_url)
153+
host = str(parts.netloc)
154+
lang_domains = plugins.toolkit.config.get(
155+
'ckanext.language_domains.domain_map')
156+
for _lang_code, domain_list in lang_domains.items():
157+
if environ['HTTP_HOST'] in domain_list:
158+
host = environ['HTTP_HOST']
159+
break
160+
environ['HTTP_HOST'] = host
161+
return self.app(environ, start_response)

0 commit comments

Comments
 (0)