Skip to content

Commit

Permalink
Merge branch 'master' into 3785-trigger-full-text-search
Browse files Browse the repository at this point in the history
  • Loading branch information
David Read committed Sep 4, 2017
2 parents 3ce191e + 177143f commit c6b613c
Show file tree
Hide file tree
Showing 89 changed files with 1,157 additions and 1,975 deletions.
2 changes: 1 addition & 1 deletion LICENSE.txt
Expand Up @@ -2,7 +2,7 @@ License
+++++++

CKAN - Data Catalogue Software
Copyright (C) 2007 Open Knowledge Foundation
Copyright (c) 2006-2017 Open Knowledge International and contributors

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
Expand Down
9 changes: 9 additions & 0 deletions ckan/config/middleware/__init__.py
Expand Up @@ -39,6 +39,10 @@ def custom_charset__set(self, charset):

# End of webob.requests.BaseRequest monkey patch

# This is a test Flask request context to be used internally.
# Do not use it!
_internal_test_request_context = None


def make_app(conf, full_stack=True, static_files=True, **app_conf):
'''
Expand All @@ -55,6 +59,11 @@ def make_app(conf, full_stack=True, static_files=True, **app_conf):
app = AskAppDispatcherMiddleware({'pylons_app': pylons_app,
'flask_app': flask_app})

# Set this internal test request context with the configured environment so
# it can be used when calling url_for from tests
global _internal_test_request_context
_internal_test_request_context = flask_app._wsgi_app.test_request_context()

return app


Expand Down
8 changes: 3 additions & 5 deletions ckan/controllers/user.py
Expand Up @@ -397,8 +397,7 @@ def login(self, error=None):
if not c.user:
came_from = request.params.get('came_from')
if not came_from:
came_from = h.url_for(controller='user', action='logged_in',
__ckan_no_root=True)
came_from = h.url_for(controller='user', action='logged_in')
c.login_handler = h.url_for(
self._get_repoze_handler('login_handler_path'),
came_from=came_from)
Expand Down Expand Up @@ -436,10 +435,9 @@ def logout(self):
# Do any plugin logout stuff
for item in p.PluginImplementations(p.IAuthenticator):
item.logout()
url = h.url_for(controller='user', action='logged_out_page',
__ckan_no_root=True)
url = h.url_for(controller='user', action='logged_out_page')
h.redirect_to(self._get_repoze_handler('logout_handler_path') +
'?came_from=' + url)
'?came_from=' + url, parse_url=True)

def logged_out(self):
# redirect if needed
Expand Down
2 changes: 1 addition & 1 deletion ckan/lib/alphabet_paginate.py
Expand Up @@ -21,7 +21,7 @@
from sqlalchemy import __version__ as sqav
from sqlalchemy.orm.query import Query
from webhelpers.html.builder import HTML
from ckan.lib.helpers import url_for
from routes import url_for


class AlphaPage(object):
Expand Down
17 changes: 14 additions & 3 deletions ckan/lib/cli.py
Expand Up @@ -28,11 +28,16 @@
import ckan.include.rcssmin as rcssmin
import ckan.plugins as p
from ckan.common import config
from ckan.tests.helpers import _get_test_app

# This is a test Flask request context to be used internally.
# Do not use it!
_cli_test_request_context = None

#NB No CKAN imports are allowed until after the config file is loaded.
# i.e. do the imports in methods, after _load_config is called.
# Otherwise loggers get disabled.

# NB No CKAN imports are allowed until after the config file is loaded.
# i.e. do the imports in methods, after _load_config is called.
# Otherwise loggers get disabled.


def deprecation_warning(message=None):
Expand Down Expand Up @@ -224,6 +229,12 @@ def load_config(config, load_site_user=True):
from ckan.config.environment import load_environment
load_environment(conf.global_conf, conf.local_conf)

# Set this internal test request context with the configured environment so
# it can be used when calling url_for from the CLI.
global _cli_test_request_context
flask_app = _get_test_app().flask_app
_cli_test_request_context = flask_app.test_request_context()

registry = Registry()
registry.prepare()
import pylons
Expand Down
55 changes: 54 additions & 1 deletion ckan/lib/helpers.py
Expand Up @@ -28,6 +28,7 @@
from pylons import url as _pylons_default_url
from ckan.common import config, is_flask_request
from flask import redirect as _flask_redirect
from flask import _request_ctx_stack, current_app
from routes import redirect_to as _routes_redirect_to
from routes import url_for as _routes_default_url_for
from flask import url_for as _flask_default_url_for
Expand Down Expand Up @@ -152,14 +153,32 @@ def redirect_to(*args, **kw):
toolkit.redirect_to('dataset_read', id='changed')
If given a single string as argument, this redirects without url parsing
toolkit.redirect_to('http://example.com')
toolkit.redirect_to('/dataset')
toolkit.redirect_to('/some/other/path')
'''
if are_there_flash_messages():
kw['__no_cache__'] = True

# Routes router doesn't like unicode args
uargs = map(lambda arg: str(arg) if isinstance(arg, unicode) else arg,
args)
_url = url_for(*uargs, **kw)

_url = ''
skip_url_parsing = False
parse_url = kw.pop('parse_url', False)
if uargs and len(uargs) is 1 and isinstance(uargs[0], basestring) \
and (uargs[0].startswith('/') or is_url(uargs[0])) \
and parse_url is False:
skip_url_parsing = True
_url = uargs[0]

if skip_url_parsing is False:
_url = url_for(*uargs, **kw)

if _url.startswith('/'):
_url = str(config['ckan.site_url'].rstrip('/') + _url)

Expand Down Expand Up @@ -201,6 +220,30 @@ def get_site_protocol_and_host():
return (None, None)


def _get_auto_flask_context():
'''
Provides a Flask test request context if we are outside the context
of a web request (tests or CLI)
'''

from ckan.config.middleware import _internal_test_request_context
from ckan.lib.cli import _cli_test_request_context

# This is a normal web request, there is a request context present
if _request_ctx_stack.top:
return None

# We are outside a web request. A test web application was created
# (and with it a test request context with the relevant configuration)
if _internal_test_request_context:
return _internal_test_request_context

# We are outside a web request. This is a CLI command. A test request
# context was created when setting it up
if _cli_test_request_context:
return _cli_test_request_context


@core_helper
def url_for(*args, **kw):
'''Return the URL for an endpoint given some parameters.
Expand Down Expand Up @@ -252,13 +295,23 @@ def url_for(*args, **kw):
ver = kw.get('ver')
if not ver:
raise Exception('API URLs must specify the version (eg ver=3)')

_auto_flask_context = _get_auto_flask_context()

try:
if _auto_flask_context:
_auto_flask_context.push()

# First try to build the URL with the Flask router
my_url = _url_for_flask(*args, **kw)

except FlaskRouteBuildError:

# If it doesn't succeed, fallback to the Pylons router
my_url = _url_for_pylons(*args, **kw)
finally:
if _auto_flask_context:
_auto_flask_context.pop()

# Add back internal params
kw['__ckan_no_root'] = no_root
Expand Down
6 changes: 4 additions & 2 deletions ckan/lib/mailer.py
Expand Up @@ -8,7 +8,6 @@
from email.mime.text import MIMEText
from email.header import Header
from email import Utils
from urlparse import urljoin

from ckan.common import config
import paste.deploy.converters
Expand All @@ -33,7 +32,10 @@ def _mail_recipient(recipient_name, recipient_email,
mail_from = config.get('smtp.mail_from')
msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
for k, v in headers.items():
msg[k] = v
if k in msg.keys():
msg.replace_header(k, v)
else:
msg.add_header(k, v)
subject = Header(subject.encode('utf-8'), 'utf-8')
msg['Subject'] = subject
msg['From'] = _("%s <%s>") % (sender_name, mail_from)
Expand Down
5 changes: 1 addition & 4 deletions ckan/plugins/interfaces.py
Expand Up @@ -1581,10 +1581,7 @@ def organization_facets(self, facets_dict, organization_type, package_type):


class IAuthenticator(Interface):
u'''EXPERIMENTAL
Allows custom authentication methods to be integrated into CKAN.
Currently it is experimental and the interface may change.'''
u'''Allows custom authentication methods to be integrated into CKAN.'''

def identify(self):
u'''called to identify the user.
Expand Down
8 changes: 7 additions & 1 deletion ckan/public/base/css/fuchsia.css
Expand Up @@ -4220,7 +4220,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
}
}
.navbar-static-top {
z-index: 1000;
z-index: 1;
border-width: 0 0 1px;
}
@media (min-width: 768px) {
Expand Down Expand Up @@ -10220,6 +10220,12 @@ h4 small {
.alert-error .alert-link {
color: #843534;
}
.input-group .form-control {
z-index: 0;
}
.input-group-btn:last-child > .btn {
z-index: 0;
}
body {
background: #E73892 url("../../../base/images/bg.png");
}
Expand Down
8 changes: 7 additions & 1 deletion ckan/public/base/css/green.css
Expand Up @@ -4220,7 +4220,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
}
}
.navbar-static-top {
z-index: 1000;
z-index: 1;
border-width: 0 0 1px;
}
@media (min-width: 768px) {
Expand Down Expand Up @@ -10220,6 +10220,12 @@ h4 small {
.alert-error .alert-link {
color: #843534;
}
.input-group .form-control {
z-index: 0;
}
.input-group-btn:last-child > .btn {
z-index: 0;
}
body {
background: #2F9B45 url("../../../base/images/bg.png");
}
Expand Down
8 changes: 7 additions & 1 deletion ckan/public/base/css/main.css
Expand Up @@ -4220,7 +4220,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
}
}
.navbar-static-top {
z-index: 1000;
z-index: 1;
border-width: 0 0 1px;
}
@media (min-width: 768px) {
Expand Down Expand Up @@ -10220,6 +10220,12 @@ h4 small {
.alert-error .alert-link {
color: #843534;
}
.input-group .form-control {
z-index: 0;
}
.input-group-btn:last-child > .btn {
z-index: 0;
}
body {
background: #005d7a url("../../../base/images/bg.png");
}
Expand Down
8 changes: 7 additions & 1 deletion ckan/public/base/css/maroon.css
Expand Up @@ -4220,7 +4220,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
}
}
.navbar-static-top {
z-index: 1000;
z-index: 1;
border-width: 0 0 1px;
}
@media (min-width: 768px) {
Expand Down Expand Up @@ -10220,6 +10220,12 @@ h4 small {
.alert-error .alert-link {
color: #843534;
}
.input-group .form-control {
z-index: 0;
}
.input-group-btn:last-child > .btn {
z-index: 0;
}
body {
background: #810606 url("../../../base/images/bg.png");
}
Expand Down
8 changes: 7 additions & 1 deletion ckan/public/base/css/red.css
Expand Up @@ -4220,7 +4220,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
}
}
.navbar-static-top {
z-index: 1000;
z-index: 1;
border-width: 0 0 1px;
}
@media (min-width: 768px) {
Expand Down Expand Up @@ -10220,6 +10220,12 @@ h4 small {
.alert-error .alert-link {
color: #843534;
}
.input-group .form-control {
z-index: 0;
}
.input-group-btn:last-child > .btn {
z-index: 0;
}
body {
background: #C14531 url("../../../base/images/bg.png");
}
Expand Down
2 changes: 1 addition & 1 deletion ckan/public/base/javascript/modules/basic-form.js
Expand Up @@ -11,7 +11,7 @@ this.ckan.module('basic-form', function (jQuery) {
// consecutive form submissions.
this.el.on('submit', this._onSubmit);
},
_onSubmit() {
_onSubmit: function () {

// The button is not disabled immediately so that its value can be sent
// the first time the form is submitted, because the "save" field is
Expand Down
1 change: 1 addition & 0 deletions ckan/public/base/less/ckan.less
Expand Up @@ -23,6 +23,7 @@
@import "resource-view.less";
@import "datapusher.less";
@import "alerts.less";
@import "input-groups.less";
body {
// Using the masthead/footer gradient prevents the color from changing
// at the bottom of the window on pages with little content.
Expand Down
13 changes: 13 additions & 0 deletions ckan/public/base/less/input-groups.less
@@ -0,0 +1,13 @@
.input-group {
.form-control {
z-index: 0;
}
}

.input-group-btn {
&:last-child {
> .btn {
z-index: 0;
}
}
}
3 changes: 3 additions & 0 deletions ckan/public/base/less/variables.less
Expand Up @@ -122,3 +122,6 @@
@activityColorNeutral: #767DCE;
@activityColorModify: #767DCE;
@activityColorDelete: #B95252;

// Navigation
@zindex-navbar: 1;

0 comments on commit c6b613c

Please sign in to comment.