[#5019] remove all ancient portal/portlet/configuration logic from home & user tool

Only the raw HTML for the home tool is supported now.  This already worked at /nbhd/
and now /nbhd/home/ redirects to /nbhd/ and avoids any ACL errors from PortalConfig.

This also addresses cleanup for [#2217]
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 3ef8435..62b115c 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -92,13 +92,6 @@
                 self.children.append(e)
                 child_index[lbl] = e
 
-class WidgetController(BaseController):
-    widgets=[]
-
-    def __init__(self, app): pass
-
-    def portlet(self, content):
-        return '<div class="portlet">%s</div>' % content
 
 class Application(object):
     """
@@ -133,7 +126,6 @@
     permissions=[]
     sitemap = [ ]
     installable=True
-    widget = WidgetController
     searchable = False
     DiscussionClass = model.Discussion
     PostClass = model.Post
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 5d0d493..51ce063 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -10,7 +10,7 @@
 from webob import exc
 from bson import ObjectId
 
-from allura.app import Application, WidgetController, DefaultAdminController, SitemapEntry
+from allura.app import Application, DefaultAdminController, SitemapEntry
 from allura.lib import helpers as h
 from allura import version
 from allura import model as M
diff --git a/Allura/allura/ext/project_home/model/__init__.py b/Allura/allura/ext/project_home/model/__init__.py
deleted file mode 100644
index 134451a..0000000
--- a/Allura/allura/ext/project_home/model/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from dashboard import PortalConfig
diff --git a/Allura/allura/ext/project_home/model/dashboard.py b/Allura/allura/ext/project_home/model/dashboard.py
deleted file mode 100644
index 381b550..0000000
--- a/Allura/allura/ext/project_home/model/dashboard.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import logging
-
-from tg.decorators import Decoration
-from tg.render import render
-from pylons import c, request
-
-from ming import schema
-from ming.orm import Mapper
-from ming.orm import FieldProperty, ForeignIdProperty
-
-from allura.lib.helpers import push_config
-from allura.model import Artifact
-
-log = logging.getLogger(__name__)
-
-class PortalConfig(Artifact):
-    class __mongometa__:
-        name='portal_config'
-    type_s = 'Project Portal Configuration'
-
-    _id = FieldProperty(schema.ObjectId)
-    user_id = ForeignIdProperty('User')
-    layout_class = FieldProperty(str)
-    layout = FieldProperty([
-            {'name':str,
-             'content':[
-                    {'mount_point':str,
-                     'widget_name':str }
-                    ]
-             }])
-
-    @classmethod
-    def current(cls):
-        result = cls.query.get(user_id=c.user._id)
-        if result is None:
-            result = cls(user_id=c.user._id,
-                         layout_class='onecol',
-                         layout=[dict(name='content',
-                                      content=[dict(mount_point='home',
-                                                    widget_name='welcome')
-                                               ])])
-        return result
-
-    def rendered_layout(self):
-        return [
-            dict(name=div.name,
-                 content=[ render_widget(**w)
-                           for w in div.content]
-                 )
-            for div in self.layout ]
-            
-
-    def url(self):
-        return self.app_config.script_name()
-
-    def index(self):
-        return None
-
-def render_widget(mount_point, widget_name):
-    app = c.project.app_instance(mount_point)
-    method = getattr(app.widget(app), widget_name)
-    with push_config(c, app=app):
-        result = method()
-    if isinstance(result, dict):
-        deco = Decoration.get_decoration(method)
-        content_type, engine, template, exclude_names = \
-            deco.lookup_template_engine(request)
-        template_vars = dict((k,v) for k,v in result.iteritems()
-                             if k not in exclude_names)
-        return render(template_vars, engine, template)
-    return result
-
-Mapper.compile_all()
diff --git a/Allura/allura/ext/project_home/nf/home/css/project_home.css b/Allura/allura/ext/project_home/nf/home/css/project_home.css
deleted file mode 100644
index 4ef8098..0000000
--- a/Allura/allura/ext/project_home/nf/home/css/project_home.css
+++ /dev/null
@@ -1,17 +0,0 @@
-div.twocol #col1 
-{
-    width: 40%;
-    float: left;
-}
-
-div.twocol #col2
-{
-    width: 50%;
-    float: left;
-}
-
-div.portlet
-{
-    margin: 2px;
-    background-color: white;
-}
diff --git a/Allura/allura/ext/project_home/project_main.py b/Allura/allura/ext/project_home/project_main.py
index 16dc5f0..96c706a 100644
--- a/Allura/allura/ext/project_home/project_main.py
+++ b/Allura/allura/ext/project_home/project_main.py
@@ -1,40 +1,22 @@
-import difflib
 import logging
-from pprint import pformat
 
 import pkg_resources
-from pylons import c, request
-from tg import expose, redirect, flash
+from pylons import c
+from tg import expose, redirect
 from tg.decorators import with_trailing_slash
-from webob import exc
-
 
 from allura import version
-from allura.app import Application, WidgetController, ConfigOption, SitemapEntry
+from allura.app import Application, SitemapEntry
 from allura.lib import helpers as h
 from allura.controllers import BaseController
-from allura.ext.project_home import model as M
 from allura import model
-from allura.lib.security import require, require_access
-from allura.lib.decorators import require_post
-from allura.lib.widgets.project_list import ProjectScreenshots
+
 
 log = logging.getLogger(__name__)
 
-class W:
-    screenshot_list = ProjectScreenshots()
-
-class ProjectWidgets(WidgetController):
-    widgets=['welcome']
-
-    def __init__(self, app): pass
-
-    def welcome(self):
-        return self.portlet('<p><!-- Please configure your widgets --></p>')
 
 class ProjectHomeApp(Application):
     __version__ = version.__version__
-    widget = ProjectWidgets
     installable = False
     tool_label = 'home'
     default_mount_label='Project Home'
@@ -47,7 +29,6 @@
     def __init__(self, project, config):
         Application.__init__(self, project, config)
         self.root = ProjectHomeController()
-        self.api_root = RootRestController()
         self.templates = pkg_resources.resource_filename(
             'allura.ext.project_home', 'templates')
 
@@ -61,19 +42,18 @@
         '''
         return [ SitemapEntry(
                 self.config.options.mount_label.title(),
-                '.')]
-
+                '..')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
         menu_id = 'Home'
         return [
-            SitemapEntry('Home', c.project.url()) ]
+            SitemapEntry('Home', '..') ]
 
     @h.exceptionless([], log)
     def sidebar_menu(self):
-        return [ SitemapEntry('Configure', 'configuration')]
+        return [ ]
 
     def admin_menu(self):
         return []
@@ -86,72 +66,10 @@
                 model.ACE.allow(pr._id, perm)
                 for perm in self.permissions ]
 
+
 class ProjectHomeController(BaseController):
 
-    def _check_security(self):
-        require_access(c.project, 'read')
-
     @with_trailing_slash
-    @expose('jinja:allura.ext.project_home:templates/project_index.html')
-    def index(self, **kw):
-        config = M.PortalConfig.current()
-        c.screenshot_list = W.screenshot_list
-        return dict(
-            layout_class=config.layout_class,
-            layout=config.rendered_layout())
-
-    @expose('jinja:allura.ext.project_home:templates/project_dashboard_configuration.html')
-    def configuration(self):
-        config = M.PortalConfig.current()
-        mount_points = [
-            (ac.options.mount_point, ac.load())
-            for ac in c.project.app_configs ]
-        widget_types = [
-            dict(mount_point=mp, widget_name=w)
-            for mp, app_class in mount_points
-            for w in app_class.widget.widgets ]
-        return dict(
-            layout_class=config.layout_class,
-            layout=config.layout,
-            widget_types=widget_types)
-
-    @h.vardec
     @expose()
-    @require_post()
-    def update_configuration(self, divs=None, layout_class=None, new_div=None, **kw):
-        require_access(c.project, 'update')
-        config = M.PortalConfig.current()
-        config.layout_class = layout_class
-        # Handle updated and deleted divs
-        if divs is None: divs = []
-        new_divs = []
-        for div in divs:
-            log.info('Got div update:%s', pformat(div))
-            if div.get('del'): continue
-            new_divs.append(div)
-        # Handle new divs
-        if new_div:
-            new_divs.append(dict(name=h.nonce(), content=[]))
-        config.layout = []
-        for div in new_divs:
-            content = []
-            for w in div.get('content', []):
-                if w.get('del'): continue
-                mp,wn = w['widget'].split('/')
-                content.append(dict(mount_point=mp, widget_name=wn))
-            if div.get('new_widget'):
-                content.append(dict(mount_point='home', widget_name='welcome'))
-            config.layout.append(dict(
-                    name=div['name'],
-                    content=content))
-        redirect('configuration')
-
-
-class RootRestController(BaseController):
-
-    def _check_security(self):
-        require_access(c.project, 'read')
-
-    @expose('json:')
-    def index(self, **kwargs):
-        return dict(shortname=c.project.shortname)
+    def index(self, **kw):
+        redirect('..')
diff --git a/Allura/allura/ext/project_home/templates/__init__.py b/Allura/allura/ext/project_home/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/Allura/allura/ext/project_home/templates/__init__.py
+++ /dev/null
diff --git a/Allura/allura/ext/project_home/templates/project_dashboard_configuration.html b/Allura/allura/ext/project_home/templates/project_dashboard_configuration.html
deleted file mode 100644
index 0142abd..0000000
--- a/Allura/allura/ext/project_home/templates/project_dashboard_configuration.html
+++ /dev/null
@@ -1,79 +0,0 @@
-{% extends g.theme.master %}
-
-{% block title %}{{c.project.name}} / Configure Dashboard{% endblock %}
-
-{% block header %}Configure Dashboard for {{c.project.name}}{% endblock %}
-
-{% block extra_css %}
-    <link rel="stylesheet" type="text/css"  
-          href="{{g.app_static('css/project_home.css')}}"/>
-{% endblock %}
-
-
-{% block content %}
-          <form method="post" action="update_configuration">
-            <div class="span-3 clear"><label for="layout_class">Layout Class</label></div>
-            <div class="span-10">
-              <select name="layout_class" id="layout_class" class="title">
-                <option value="onecol" {% if layout_class=='onecol' %}selected="selected"{% endif %}>
-                  One Column</option>
-                <option value="twocol" {% if layout_class=='twocol' %}selected="selected"{% endif %}>
-                  Two Column</option>
-              </select>
-            </div>
-            <div class="span-5 last">
-              <input type="submit" value="Update Layout"/>
-            </div>
-            
-            {% for div in layout %}
-            <div style="margin-bottom: 1em; border: 1px solid #ddd" class="span-18 last">
-              <div class="span-3 clear"><label for="divs-{{loop.index0}}.name">Div Name</label></div>
-              <div class="span-14 last">
-                <input type="text" name="divs-{{loop.index0}}.name" id="divs-{{loop.index0}}.name" value="{{div.name}}" class="title span-10"/> &nbsp;
-                <input type="submit" name="divs-{{loop.index0}}.del" value="Remove Div"/>
-              </div>
-              <div class="span-3 clear"><label>Widgets</label></div>
-              <div class="span-14 last">
-                {% if not div.content %}
-                <span">No widgets have been added.</span>
-                {% else %}
-                <table>
-                  <thead>
-                    <tr>
-                      <th>Widget</th>
-                      <th>Remove</th>
-                    </tr>
-                  </thead>
-                  <tbody>
-                    {% set i = loop.index0 %}
-                    {% for w in div.content %}
-                    <tr class="{{loop.cycle('even', '')}}">
-                      <td>
-                        <select name="divs-{{i}}.content-{{loop.index0}}.widget" id="divs-{{i}}.content-{{loop.index0}}">
-                          {% for wt in widget_types %}
-                            <option value="{{wt.mount_point}}/{{wt.widget_name}}"
-                                  {% if wt==w %}selected="selected"{% endif %}>{{wt.mount_point}} / {{wt.widget_name}}</option>
-                          {% endfor %}
-                        </select>
-                      </td>
-                      <td>
-                        <input type="submit" name="divs-{{i}}.content-{{loop.index0}}.del"
-                               value="Remove Widget"/>
-                      </td>
-                    </tr>
-                    {% endfor %}
-                  </tbody>
-                </table>
-                {% endif %}
-              </div>
-              <div class="push-3 span-14 clear last">
-                <input type="submit" name="divs-{{loop.index0}}.new_widget" value="Add new widget"/>
-              </div>
-            </div>
-            {% endfor %}
-            
-            <div class="clear">
-              <input type="submit" name="new_div" value="Add new div"/>
-            </div>
-          </form>
-{% endblock %}
diff --git a/Allura/allura/ext/project_home/templates/project_index.html b/Allura/allura/ext/project_home/templates/project_index.html
deleted file mode 100644
index ed5b4d6..0000000
--- a/Allura/allura/ext/project_home/templates/project_index.html
+++ /dev/null
@@ -1,68 +0,0 @@
-{% set hide_left_bar = True %}
-{% set show_right_bar = True %}
-{% extends g.theme.master %}
-
-{% block title %}{{c.project.homepage_title}}{% endblock %}
-
-{% block header %}{{c.project.homepage_title}}{% endblock %}
-
-{% block extra_css %}
-    <link rel="stylesheet" type="text/css" 
-          href="{{g.app_static('css/project_home.css')}}"/>
-    <link rel="alternate" type="application/rss+xml" title="RSS" href="../feed.rss"/>
-    <link rel="alternate" type="application/atom+xml" title="Atom" href="../feed.atom"/>
-{% endblock %}
-
-
-{% block content %}
-  {{c.project.description_html|safe}}
-  <div class="{{layout_class}}">
-    {% for div in layout %}
-    <div class="{{div.name}}">
-      {% for w in div.content %}{{w|safe}}{% endfor %}
-    </div>
-    {% endfor %}
-  </div>
-  {{c.screenshot_list.display(project=c.project)}}
-{% endblock %}
-
-{% block right_content %}
-  {% if c.project.accolades %}
-    <div class="listed">
-      <b>Awards:</b>
-      {% for accolade in c.project.accolades %}
-      <a href="{{accolade.award.longurl()}}" title="{{accolade.award.full}}">
-        <small class="badge {{accolade.award.short}}">{{accolade.award.short}}</small>
-      </a>
-      {% else %}
-        <span>No Awards</span>
-      {% endfor %}
-    </div>
-  {% endif %}
-
-  {% if c.project.labels and not (c.project.labels|length == 1 and c.project.labels[0]=='') %}
-  <div class="listed">
-    <b>Labels:</b>
-    {% for label in c.project.labels %}
-      <span class="ui-corner-all tag">{{label}} </span>
-    {% endfor %}
-  </div>
-  {% endif %}
-
-  <div class="listed last gravatar sm">
-    <b>Developers:</b>
-    {% for u in c.project.users() %}
-    <a href="{{u.url()}}">
-      {{lib.gravatar(u, size=24)}}
-    </a>
-    {% endfor %}
-  </div>
-{% endblock %}
-
-{% block extra_js %}
-  {% if c.project.best_download_url() %}
-  <script type="text/javascript">
-      $("#download-button").load("{{c.project.best_download_url()}}");
-  </script>
-  {% endif %}
-{% endblock %}
diff --git a/Allura/allura/ext/user_profile/nf/home/css/user_profile.css b/Allura/allura/ext/user_profile/nf/home/css/user_profile.css
index e2f5eaa..e69de29 100644
--- a/Allura/allura/ext/user_profile/nf/home/css/user_profile.css
+++ b/Allura/allura/ext/user_profile/nf/home/css/user_profile.css
@@ -1,17 +0,0 @@
-div.twocol #col1
-{
-    width: 40%;
-    float: left;
-}
-
-div.twocol #col2
-{
-    width: 50%;
-    float: left;
-}
-
-div.portlet
-{
-    margin: 2px;
-    background-color: yellow;
-}
\ No newline at end of file
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index 39af32a..e017ad2 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -7,10 +7,9 @@
 from tg import expose, redirect, validate, response
 
 from allura import version
-from allura.app import Application, WidgetController
+from allura.app import Application
 from allura.lib import helpers as h
 from allura.lib.helpers import DateTimeConverter
-from allura.ext.project_home import model as M
 from allura.lib.security import require_access
 from allura.model import User, Feed, ACE
 from allura.controllers import BaseController
@@ -18,17 +17,9 @@
 
 log = logging.getLogger(__name__)
 
-class UserWidgets(WidgetController):
-    widgets=['welcome']
-
-    def __init__(self, app): pass
-
-    def welcome(self):
-        return self.portlet('<p><!-- Please configure your widgets --></p>')
 
 class UserProfileApp(Application):
     __version__ = version.__version__
-    widget = UserWidgets
     installable = False
     icons={
         24:'images/sftheme/24x24/home_24.png',
@@ -81,10 +72,6 @@
     #             print r.docs
     #     return dict(user=user)
 
-    @expose('jinja:allura.ext.user_profile:templates/user_dashboard_configuration.html')
-    def configuration(self):
-        return dict(user=c.project.user_project_of)
-
     @expose()
     @validate(dict(
             since=DateTimeConverter(if_empty=None),
@@ -108,34 +95,3 @@
         response.headers['Content-Type'] = ''
         response.content_type = 'application/xml'
         return feed.writeString('utf-8')
-
-    @h.vardec
-    @expose()
-    @require_post()
-    def update_configuration(self, divs=None, layout_class=None, new_div=None, **kw):
-        require_access(c.project, 'update')
-        config = M.PortalConfig.current()
-        config.layout_class = layout_class
-        # Handle updated and deleted divs
-        if divs is None: divs = []
-        new_divs = []
-        for div in divs:
-            log.info('Got div update:%s', pformat(div))
-            if div.get('del'): continue
-            new_divs.append(div)
-        # Handle new divs
-        if new_div:
-            new_divs.append(dict(name=h.nonce(), content=[]))
-        config.layout = []
-        for div in new_divs:
-            content = []
-            for w in div.get('content', []):
-                if w.get('del'): continue
-                mp,wn = w['widget'].split('/')
-                content.append(dict(mount_point=mp, widget_name=wn))
-            if div.get('new_widget'):
-                content.append(dict(mount_point='profile', widget_name='welcome'))
-            config.layout.append(dict(
-                    name=div['name'],
-                    content=content))
-        redirect('configuration')
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 69c54b3..dbe92ff 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -578,11 +578,6 @@
             self.uninstall_app(ac.options.get('mount_point'))
         MappedClass.delete(self)
 
-    def render_widget(self, widget):
-        app = self.app_instance(widget['mount_point'])
-        with h.push_config(c, project=self, app=app):
-            return getattr(app.widget(app), widget['widget_name'])()
-
     def breadcrumbs(self):
         entry = ( self.name, self.url() )
         if self.parent_project:
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index afd64c7..4c6ebcd 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -10,15 +10,6 @@
         response = self.app.get('/u/test-admin/profile/')
         assert '<h2 class="dark title">Test Admin' in response
         assert 'OpenIDs' in response
-        response = self.app.get('/u/test-admin/profile/configuration')
-        assert 'Configure Dashboard' in response
-
-    @td.with_user_project('test-admin')
-    def test_profile_config(self):
-        # Not fully implemented, just do coverage
-        response = self.app.post('/u/test-admin/profile/update_configuration', params=variable_encode({
-                                     'layout_class': 'something', 'divs': [{'name': 'foo', 'content': [{'widget': 'lotsa/content'}]}],
-                                     'new_div': {'name': 'bar', 'new_widget': 'widg'}}))
 
     def test_wrong_profile(self):
         response = self.app.get('/u/no-such-user/profile/', status=404)
@@ -39,4 +30,3 @@
         response = self.app.get('/u/test-admin/profile/feed')
         assert 'Recent posts by Test Admin' in response
         assert 'WikiPage Home modified by Test Admin' in response
-
diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index e4c5beb..359e796 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -51,7 +51,3 @@
                 app.SitemapEntry('d', 'd/')]])
     assert len(sm.children) == 3
 
-def test_widget_controller():
-    wc = app.WidgetController(c.app)
-    assert 'portlet' in wc.portlet('Foo'), wc.portlet('Foo')
-