You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by he...@apache.org on 2015/04/01 23:10:35 UTC
[18/45] allura git commit: [#7820] ticket:747 Validate URLs when
configuring external link tool
[#7820] ticket:747 Validate URLs when configuring external link tool
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/53b5577a
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/53b5577a
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/53b5577a
Branch: refs/heads/hss/7072
Commit: 53b5577a36005cbd938bc16fa38cb0795eab4dd1
Parents: e146bbe
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Mar 19 14:12:03 2015 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Mar 23 19:43:48 2015 +0000
----------------------------------------------------------------------
ForgeLink/forgelink/link_main.py | 19 ++++-
.../forgelink/templates/app_admin_options.html | 77 ++++++++++++++++++++
.../forgelink/tests/functional/test_root.py | 47 ++++++++++++
3 files changed, 142 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/53b5577a/ForgeLink/forgelink/link_main.py
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/link_main.py b/ForgeLink/forgelink/link_main.py
index bb55a3e..bfcf9f9 100644
--- a/ForgeLink/forgelink/link_main.py
+++ b/ForgeLink/forgelink/link_main.py
@@ -23,11 +23,12 @@ import json
from tg import expose, redirect, flash, jsonify
from pylons import tmpl_context as c
from pylons import request
+from formencode import validators as fev
# Pyforge-specific imports
from allura.app import Application, ConfigOption, SitemapEntry, DefaultAdminController
from allura.lib import helpers as h
-from allura.lib.security import require_access
+from allura.lib.security import require_access, has_access
from allura.lib.utils import permanent_redirect
from allura import model as M
from allura.controllers import BaseController
@@ -128,6 +129,22 @@ class LinkAdminController(DefaultAdminController):
flash('External link URL updated.')
redirect(c.project.url() + 'admin/tools')
+ @expose('jinja:forgelink:templates/app_admin_options.html')
+ def options(self):
+ return dict(
+ app=self.app,
+ allow_config=has_access(self.app, 'configure')())
+
+ @expose('json:')
+ def set_url(self, **kw):
+ validator = fev.URL(not_empty=True, add_http=True)
+ try:
+ url = validator.to_python(kw.get('url'))
+ except fev.Invalid as e:
+ return {'status': 'error', 'errors': {'url': e.msg}}
+ self.app.config.options['url'] = url
+ return {'status': 'ok'}
+
class RootRestController(BaseController):
http://git-wip-us.apache.org/repos/asf/allura/blob/53b5577a/ForgeLink/forgelink/templates/app_admin_options.html
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/templates/app_admin_options.html b/ForgeLink/forgelink/templates/app_admin_options.html
new file mode 100644
index 0000000..a62dfa7
--- /dev/null
+++ b/ForgeLink/forgelink/templates/app_admin_options.html
@@ -0,0 +1,77 @@
+{#-
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-#}
+<!DOCTYPE html>
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
+<form id="set-url-form" method="post" action="{{c.project.url()}}admin/{{app.config.options.mount_point}}/set_url">
+ <label for="url" class="grid-4">url</label>
+ <div class="grid-9">
+ {% if not allow_config %}
+ {{app.config.options.get('url', '')}}
+ {% else %}
+ <input id="url" name="url" value="{{app.config.options.get('url', '')}}">
+ {% endif %}
+ </div>
+ <div class="grid-4"> </div><div id='url-error' class='grid-9'></div>
+ {% if allow_config %}
+ <div class="grid-13"> </div>
+ <hr>
+ <div class="grid-13"> </div>
+ <div class="grid-13">
+ <input type="submit" value="Save" id="save" />
+ <a href="#" class="close">Cancel</a>
+ </div>
+ {% endif %}
+ {{lib.csrf_token()}}
+</form>
+
+<script type="text/javascript">
+$(function() {
+ $('#save').on('click', function(e) {
+ e.preventDefault();
+ var form = $('#set-url-form');
+ var button = $(this);
+ var input = form.find('input[name="url"]')
+ var url_error = $('#url-error');
+ var url = input.val();
+ var csrf = $.cookie('_session_id');
+ button.prop('disabled', true);
+ input.prop('disabled', true);
+ url_error.text('');
+ $.post(
+ form.attr('action'),
+ {'_session_id': csrf, 'url': url},
+ function(data) {
+ if (data['status'] == 'ok') {
+ location.reload();
+ } else {
+ url_error.text(data['errors']['url']);
+ }
+ button.prop('disabled', false);
+ input.prop('disabled', false);
+ });
+ });
+});
+</script>
+
+<style type="text/css">
+#url-error {
+ margin-left: 15px;
+ color: #f33;
+}
+</style>
http://git-wip-us.apache.org/repos/asf/allura/blob/53b5577a/ForgeLink/forgelink/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/tests/functional/test_root.py b/ForgeLink/forgelink/tests/functional/test_root.py
index ca57244..e4fc656 100644
--- a/ForgeLink/forgelink/tests/functional/test_root.py
+++ b/ForgeLink/forgelink/tests/functional/test_root.py
@@ -15,6 +15,9 @@
# specific language governing permissions and limitations
# under the License.
+from nose.tools import assert_equal
+
+from allura import model as M
from allura.tests import decorators as td
from alluratest.controller import TestController
@@ -58,3 +61,47 @@ class TestRootController(TestController):
response = self.app.get('/link/help')
# HACK: support for remote redirects is limited in follow()
assert 'http://www.google.de/search?q=help' in response
+
+ @td.with_link
+ def test_set_url_validation(self):
+ r = self.app.post('/p/test/admin/link/set_url', {})
+ expected = {'status': 'error',
+ 'errors': {'url': u'Please enter a value'}}
+ assert_equal(r.json, expected)
+
+ r = self.app.post('/p/test/admin/link/set_url', {'url': ''})
+ expected = {'status': 'error',
+ 'errors': {'url': u'Please enter a value'}}
+ assert_equal(r.json, expected)
+
+ r = self.app.post('/p/test/admin/link/set_url', {'url': 'bad url'})
+ expected = {'status': 'error',
+ 'errors': {'url': u'That is not a valid URL'}}
+ assert_equal(r.json, expected)
+
+ p = M.Project.query.get(shortname='test')
+ link = p.app_instance('link')
+ assert_equal(link.config.options.get('url'), None)
+
+ @td.with_link
+ def test_set_url(self):
+ data = {'url': 'http://example.com'} # http
+ r = self.app.post('/p/test/admin/link/set_url', data)
+ assert_equal(r.json, {'status': 'ok'})
+ p = M.Project.query.get(shortname='test')
+ link = p.app_instance('link')
+ assert_equal(link.config.options.get('url'), 'http://example.com')
+
+ data = {'url': 'https://google.com'} # https
+ r = self.app.post('/p/test/admin/link/set_url', data)
+ assert_equal(r.json, {'status': 'ok'})
+ p = M.Project.query.get(shortname='test')
+ link = p.app_instance('link')
+ assert_equal(link.config.options.get('url'), 'https://google.com')
+
+ data = {'url': 'lmgtfy.com'} # http is added if not provided
+ r = self.app.post('/p/test/admin/link/set_url', data)
+ assert_equal(r.json, {'status': 'ok'})
+ p = M.Project.query.get(shortname='test')
+ link = p.app_instance('link')
+ assert_equal(link.config.options.get('url'), 'http://lmgtfy.com')