You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2012/10/02 23:30:28 UTC
[31/34] git commit: [#4637] ticket:176 ForgeShortUrl improvements
[#4637] ticket:176 ForgeShortUrl improvements
* add remove functionality
* separate add and update functionality
* enforce CREATE/UPDATE permission for admin controller methods
Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/773e7e22
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/773e7e22
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/773e7e22
Branch: refs/heads/db/4968
Commit: 773e7e2250864bdc0886898fd20622fa320ffa36
Parents: d3f57e9
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Sep 25 17:41:41 2012 +0300
Committer: Cory Johns <jo...@geek.net>
Committed: Thu Sep 27 19:10:45 2012 +0000
----------------------------------------------------------------------
ForgeShortUrl/forgeshorturl/main.py | 92 ++++++++-------
ForgeShortUrl/forgeshorturl/templates/index.html | 78 ++++++++++++-
.../forgeshorturl/tests/functional/test.py | 46 ++++++-
ForgeShortUrl/forgeshorturl/widgets/short_url.py | 7 +
4 files changed, 174 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/773e7e22/ForgeShortUrl/forgeshorturl/main.py
----------------------------------------------------------------------
diff --git a/ForgeShortUrl/forgeshorturl/main.py b/ForgeShortUrl/forgeshorturl/main.py
index 6fca6f3..38bd3cc 100644
--- a/ForgeShortUrl/forgeshorturl/main.py
+++ b/ForgeShortUrl/forgeshorturl/main.py
@@ -1,4 +1,5 @@
from tg import expose, validate, redirect, flash, request
+from tg.decorators import without_trailing_slash
from urllib import urlencode
from allura.app import Application, SitemapEntry, DefaultAdminController
@@ -18,7 +19,7 @@ from formencode import validators
from formencode.compound import All
from forgeshorturl.model.shorturl import ShortUrl
-from forgeshorturl.widgets.short_url import CreateShortUrlWidget
+import forgeshorturl.widgets.short_url as suw
import logging
@@ -30,9 +31,10 @@ class W:
search_results = SearchResults()
page_list = ffw.PageList()
page_size = ffw.PageSize()
- create_short_url_lightbox = \
- CreateShortUrlWidget(name='create_short_url',
- trigger='#sidebar a.add_short_url')
+ create_short_url_lightbox = suw.CreateShortUrlWidget(
+ name='create_short_url',
+ trigger='#sidebar a.add_short_url')
+ update_short_url_lightbox = suw.UpdateShortUrlWidget()
class ForgeShortUrlApp(Application):
@@ -115,6 +117,7 @@ class ForgeShortUrlApp(Application):
class RootController(BaseController):
def __init__(self):
c.create_short_url_lightbox = W.create_short_url_lightbox
+ c.update_short_url_lightbox = W.update_short_url_lightbox
def _check_security(self):
require_access(c.app, 'read')
@@ -196,52 +199,61 @@ class ShortURLAdminController(DefaultAdminController):
def index(self, **kw):
redirect(c.project.url() + 'admin/tools')
+ @without_trailing_slash
+ @expose('json:')
+ def remove(self, shorturl):
+ require_access(self.app, 'update')
+ ShortUrl.query.remove({
+ 'app_config_id': self.app.config._id,
+ 'short_name': shorturl})
+ return dict(status='ok')
+
@expose('jinja:forgeshorturl:templates/add.html')
@validate(dict(full_url=All(validators.URL(add_http=True),
validators.NotEmpty()),
short_url=validators.NotEmpty()))
- def add(self, short_url="",
- full_url="",
- description="",
- private="off", **kw):
- if (request.method == 'POST'):
+ def add(self, short_url='', full_url='', description='', private='off',
+ update=False, **kw):
+ if update:
+ require_access(self.app, 'update')
+ else:
+ require_access(self.app, 'create')
+ if request.method == 'POST':
if pylons.c.form_errors:
- error_msg = "Error creating Short URL: "
+ error_msg = 'Error: '
for msg in list(pylons.c.form_errors):
- names = {"short_url": "Short name", "full_url": "Full URL"}
- error_msg += "%s - %s " % (names[msg], c.form_errors[msg])
- flash(error_msg, "error")
+ names = {'short_url': 'Short url', 'full_url': 'Full URL'}
+ error_msg += '%s: %s ' % (names[msg], c.form_errors[msg])
+ flash(error_msg, 'error')
redirect(request.referer)
- if (short_url != full_url):
- shorturl = ShortUrl.query.find({
- 'app_config_id': self.app.config._id,
- 'short_name': short_url}).first()
- if shorturl is None:
- shorturl = ShortUrl()
- shorturl.created = datetime.utcnow()
- log_msg = 'create short url %s for %s' %\
- (short_url,
- full_url)
+ shorturl = ShortUrl.query.find({
+ 'app_config_id': self.app.config._id,
+ 'short_name': short_url}).first()
+
+ if shorturl is not None:
+ if not update:
+ flash('Short url %s already exists' % short_url, 'error')
+ redirect(request.referer)
else:
- log_msg = 'update short url %s from %s to %s' %\
- (short_url,
- shorturl.full_url,
- full_url)
- shorturl.full_url = full_url
- shorturl.short_name = short_url
- shorturl.description = description
- shorturl.create_user = c.user._id
+ msg = ('update short url %s from %s to %s'
+ % (short_url, shorturl.full_url, full_url))
+ flash("Short url updated")
+
+ else:
+ shorturl = ShortUrl()
+ shorturl.created = datetime.utcnow()
shorturl.app_config_id = self.app.config._id
- if private == "on":
- shorturl.private = True
- else:
- shorturl.private = False
- shorturl.last_updated = datetime.utcnow()
- M.AuditLog.log(log_msg)
+ msg = 'create short url %s for %s' % (short_url, full_url)
flash("Short url created")
- else:
- flash("Error creating Short URL: "
- "Short Name and Full URL must be different", "error")
+
+ shorturl.short_name = short_url
+ shorturl.full_url = full_url
+ shorturl.description = description
+ shorturl.create_user = c.user._id
+ shorturl.private = private == 'on'
+ shorturl.last_updated = datetime.utcnow()
+
+ M.AuditLog.log(msg)
redirect(request.referer)
return dict(app=self.app)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/773e7e22/ForgeShortUrl/forgeshorturl/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeShortUrl/forgeshorturl/templates/index.html b/ForgeShortUrl/forgeshorturl/templates/index.html
index afd9f21..0ea37bf 100644
--- a/ForgeShortUrl/forgeshorturl/templates/index.html
+++ b/ForgeShortUrl/forgeshorturl/templates/index.html
@@ -1,4 +1,34 @@
{% extends 'forgeshorturl:templates/master.html' %}
+
+{% set can_update = c.user and h.has_access(c.app, 'update') %}
+
+{% block extra_js %}
+ {{ super() }}
+
+ {{ c.update_short_url_lightbox.display(content='''
+<div>
+<h1>Update Short URL</h1>
+<form method="post" action="" id="update-short-url-form">
+ <input type="hidden" name="update" value="update">
+ <input type="hidden" name="short_url">
+ <label class="grid-13">Short name</label>
+ <div class="grid-13"><input type="text" name="short_url_display" style="width: 250px" disabled="disabled"></div>
+ <label class="grid-13">Full URL</label>
+ <div class="grid-13"><input type="text" name="full_url" style="width: 250px"></div>
+ <label class="grid-13">Description</label>
+ <div class="grid-13"><textarea name="description" style="width: 250px; height: 100px"></textarea></div>
+ <div class="grid-13"><input type="checkbox" name="private" id="update-checkbox-private"><label for="update-checkbox-private">Private</label></div>
+ <div class="grid-13"> </div>
+ <hr>
+ <div class="grid-13"><div class="grid-13"> </div>
+ <input type="submit" value="Save">
+ <a href="#" class="close">Cancel</a>
+ </div>
+</form>
+</div>
+''') }}
+{% endblock %}
+
{% block content %}
<table>
<thead>
@@ -10,6 +40,7 @@
<th>Description</th>
<th>Created</th>
<th>Last updated</th>
+ {% if can_update %}<th></th>{% endif %}
</tr>
</thead>
{% for su in short_urls %}
@@ -26,10 +57,53 @@
<td><small>{{ su.description }}</small></td>
<td><small>{{ lib.abbr_date(su.created) }}</small></td>
<td><small>{{ lib.abbr_date(su.last_updated) }}</small></td>
-
+ {% if can_update %}
+ <td>
+ <small>
+ <a class="update-url" id="update-url-{{su.short_name}}" href="{{c.project.url()}}admin/{{c.app.config.options.mount_point}}/add/">
+ Update
+ </a>
+ <script>
+ $(function() {
+ var upform = $('#update-short-url-form');
+ $('#update-url-{{su.short_name}}').click(function() {
+ upform.attr('action', this.href);
+ upform.find('input[name="short_url"]').val('{{ su.short_name }}');
+ upform.find('input[name="short_url_display"]').val('{{ su.short_name }}');
+ upform.find('input[name="full_url"]').val('{{ su.full_url }}');
+ upform.find('textarea[name="description"]').val('{{su.description|replace("\n", "\\n")|replace("\r", "\\r")}}');
+ if ('{{ su.private }}' == 'True') {
+ $('#update-checkbox-private').attr('checked', 'checked');
+ } else {
+ $('#update-checkbox-private').removeAttr('checked');
+ }
+ return false;
+ });
+ });
+ </script>
+ <br>
+ <a id="remove-url-{{su.short_name}}" href="{{c.project.url()}}admin/{{c.app.config.options.mount_point}}/remove">
+ Remove
+ </a>
+ <script>
+ $(function() {
+ var cval = $.cookie('_session_id');
+ $('#remove-url-{{su.short_name}}').click(function() {
+ var row = $(this).parents('tr');
+ var data = {_session_id: cval, shorturl: '{{ su.short_name }}'};
+ $.post(this.href, data, function(data, status, xhr) {
+ if (data.status == 'ok') row.remove();
+ });
+ return false;
+ });
+ });
+ </script>
+ </small>
+ </td>
+ {% endif %} {# can_update #}
</tr>
{% endfor %}
</table>
{{ c.page_list.display(limit=limit, count=count, page=pagenum) }}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/773e7e22/ForgeShortUrl/forgeshorturl/tests/functional/test.py
----------------------------------------------------------------------
diff --git a/ForgeShortUrl/forgeshorturl/tests/functional/test.py b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
index dc8ead1..a4c36c6 100644
--- a/ForgeShortUrl/forgeshorturl/tests/functional/test.py
+++ b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
@@ -1,6 +1,11 @@
+import pylons
+pylons.c = pylons.tmpl_context
+from pylons import c
from allura.tests import decorators as td
from alluratest.controller import TestController
+from forgeshorturl.model import ShortUrl
+
class TestRootController(TestController):
def setUp(self):
@@ -18,11 +23,22 @@ class TestRootController(TestController):
response.form.submit()
redirected = self.app.get('/url/test').follow()
assert redirected.request.url == 'http://www.google.com/'
+
+ def test_shorturl_update(self):
response = self.app.get('/admin/url/add')
- response.form['short_url'] = 'test'
- response.form['full_url'] = 'http://www.yahoo.com/'
+ response.form['short_url'] = 'g'
+ response.form['full_url'] = 'http://www.google.com/'
response.form.submit()
- redirected = self.app.get('/url/test').follow()
+ redirected = self.app.get('/url/g').follow()
+ assert redirected.request.url == 'http://www.google.com/'
+
+ response = self.app.get('/url/')
+ form = response.forms['update-short-url-form']
+ form['short_url'] = 'g'
+ form['full_url'] = 'http://www.yahoo.com/'
+ form.action = '/admin/url/add/'
+ form.submit()
+ redirected = self.app.get('/url/g').follow()
assert redirected.request.url == 'http://www.yahoo.com/'
def test_shorturl_not_found(self):
@@ -50,10 +66,26 @@ class TestRootController(TestController):
status=302)
def test_shorturl_errors(self):
- d = dict(short_url='http://www.amazone.com/',
- full_url='http://www.amazone.com/')
+ d = dict(short_url='amazone',
+ full_url='amazone')
r = self.app.post('/admin/url/add', params=d)
assert 'error' in self.webflash(r)
- d = dict(short_url='http://www.amazone.com/', full_url='amazone')
+ d = dict(short_url='test', full_url='http://google.com/')
r = self.app.post('/admin/url/add', params=d)
- assert 'error' in self.webflash(r)
+ d['full_url'] = 'http://yahoo.com'
+ r = self.app.post('/admin/url/add', params=d)
+ assert 'exists' in self.webflash(r)
+
+ def test_shorturl_remove(self):
+ self.app.post('/admin/url/add',
+ params=dict(short_url='g', full_url='http://google.com/'))
+ assert ShortUrl.query.find(app_config_id=c.app.config._id).count() == 1
+ self.app.post('/admin/url/remove', params=dict(shorturl='g'))
+ assert ShortUrl.query.find(app_config_id=c.app.config._id).count() == 0
+
+ def test_shorturl_permissions(self):
+ self.app.post('/admin/url/add',
+ params=dict(short_url='g', full_url='http://google.com/'),
+ extra_environ=dict(username='test-user'), status=403)
+ self.app.post('/admin/url/remove', params=dict(shorturl='g'),
+ extra_environ=dict(username='test-user'), status=403)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/773e7e22/ForgeShortUrl/forgeshorturl/widgets/short_url.py
----------------------------------------------------------------------
diff --git a/ForgeShortUrl/forgeshorturl/widgets/short_url.py b/ForgeShortUrl/forgeshorturl/widgets/short_url.py
index cc040e8..50a478c 100644
--- a/ForgeShortUrl/forgeshorturl/widgets/short_url.py
+++ b/ForgeShortUrl/forgeshorturl/widgets/short_url.py
@@ -6,3 +6,10 @@ class CreateShortUrlWidget(ffw.Lightbox):
def resources(self):
for r in super(CreateShortUrlWidget, self).resources():
yield r
+
+
+class UpdateShortUrlWidget(ffw.Lightbox):
+ defaults = dict(
+ ffw.Lightbox.defaults,
+ name='update-short-url-modal',
+ trigger='a.update-url')