=== added file 'developer_network/common/fixtures/auth_group.json'
--- developer_network/common/fixtures/auth_group.json	1970-01-01 00:00:00 +0000
+++ developer_network/common/fixtures/auth_group.json	2013-10-31 19:44:44 +0000
@@ -0,0 +1,1 @@
+[{"pk": 1, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 1}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 1}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 1}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 2}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 2}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 2}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 3}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 3}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 3}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_message", "name": "Can add message", "content_type": 4}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_message", "name": "Can change message", "content_type": 4}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_message", "name": "Can delete message", "content_type": 4}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 5}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 6}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 7}}, {"pk": 22, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 8}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "add_migrationhistory", "name": "Can add migration history", "content_type": 9}}, {"pk": 26, "model": "auth.permission", "fields": {"codename": "change_migrationhistory", "name": "Can change migration history", "content_type": 9}}, {"pk": 27, "model": "auth.permission", "fields": {"codename": "delete_migrationhistory", "name": "Can delete migration history", "content_type": 9}}, {"pk": 28, "model": "auth.permission", "fields": {"codename": "add_topic", "name": "Can add topic", "content_type": 10}}, {"pk": 29, "model": "auth.permission", "fields": {"codename": "change_topic", "name": "Can change topic", "content_type": 10}}, {"pk": 30, "model": "auth.permission", "fields": {"codename": "delete_topic", "name": "Can delete topic", "content_type": 10}}, {"pk": 31, "model": "auth.permission", "fields": {"codename": "add_version", "name": "Can add version", "content_type": 11}}, {"pk": 32, "model": "auth.permission", "fields": {"codename": "change_version", "name": "Can change version", "content_type": 11}}, {"pk": 33, "model": "auth.permission", "fields": {"codename": "delete_version", "name": "Can delete version", "content_type": 11}}, {"pk": 34, "model": "auth.permission", "fields": {"codename": "add_section", "name": "Can add section", "content_type": 12}}, {"pk": 35, "model": "auth.permission", "fields": {"codename": "change_section", "name": "Can change section", "content_type": 12}}, {"pk": 36, "model": "auth.permission", "fields": {"codename": "delete_section", "name": "Can delete section", "content_type": 12}}, {"pk": 37, "model": "auth.permission", "fields": {"codename": "add_namespace", "name": "Can add namespace", "content_type": 13}}, {"pk": 38, "model": "auth.permission", "fields": {"codename": "change_namespace", "name": "Can change namespace", "content_type": 13}}, {"pk": 39, "model": "auth.permission", "fields": {"codename": "delete_namespace", "name": "Can delete namespace", "content_type": 13}}, {"pk": 40, "model": "auth.permission", "fields": {"codename": "add_element", "name": "Can add Rendered Element", "content_type": 14}}, {"pk": 41, "model": "auth.permission", "fields": {"codename": "change_element", "name": "Can change Rendered Element", "content_type": 14}}, {"pk": 42, "model": "auth.permission", "fields": {"codename": "delete_element", "name": "Can delete Rendered Element", "content_type": 14}}, {"pk": 43, "model": "auth.permission", "fields": {"codename": "add_class", "name": "Can add class", "content_type": 15}}, {"pk": 44, "model": "auth.permission", "fields": {"codename": "change_class", "name": "Can change class", "content_type": 15}}, {"pk": 45, "model": "auth.permission", "fields": {"codename": "delete_class", "name": "Can delete class", "content_type": 15}}, {"pk": 46, "model": "auth.permission", "fields": {"codename": "add_bitfield", "name": "Can add bit field", "content_type": 16}}, {"pk": 47, "model": "auth.permission", "fields": {"codename": "change_bitfield", "name": "Can change bit field", "content_type": 16}}, {"pk": 48, "model": "auth.permission", "fields": {"codename": "delete_bitfield", "name": "Can delete bit field", "content_type": 16}}, {"pk": 49, "model": "auth.permission", "fields": {"codename": "add_enum", "name": "Can add enum", "content_type": 17}}, {"pk": 50, "model": "auth.permission", "fields": {"codename": "change_enum", "name": "Can change enum", "content_type": 17}}, {"pk": 51, "model": "auth.permission", "fields": {"codename": "delete_enum", "name": "Can delete enum", "content_type": 17}}, {"pk": 52, "model": "auth.permission", "fields": {"codename": "add_snippet", "name": "Can add snippet", "content_type": 18}}, {"pk": 53, "model": "auth.permission", "fields": {"codename": "change_snippet", "name": "Can change snippet", "content_type": 18}}, {"pk": 54, "model": "auth.permission", "fields": {"codename": "delete_snippet", "name": "Can delete snippet", "content_type": 18}}, {"pk": 55, "model": "auth.permission", "fields": {"codename": "add_image", "name": "Can add image", "content_type": 19}}, {"pk": 56, "model": "auth.permission", "fields": {"codename": "change_image", "name": "Can change image", "content_type": 19}}, {"pk": 57, "model": "auth.permission", "fields": {"codename": "delete_image", "name": "Can delete image", "content_type": 19}}, {"pk": 58, "model": "auth.permission", "fields": {"codename": "add_link", "name": "Can add link", "content_type": 20}}, {"pk": 59, "model": "auth.permission", "fields": {"codename": "change_link", "name": "Can change link", "content_type": 20}}, {"pk": 60, "model": "auth.permission", "fields": {"codename": "delete_link", "name": "Can delete link", "content_type": 20}}, {"pk": 61, "model": "auth.permission", "fields": {"codename": "add_page", "name": "Can add Rendered Page", "content_type": 21}}, {"pk": 62, "model": "auth.permission", "fields": {"codename": "change_page", "name": "Can change Rendered Page", "content_type": 21}}, {"pk": 63, "model": "auth.permission", "fields": {"codename": "delete_page", "name": "Can delete Rendered Page", "content_type": 21}}, {"pk": 64, "model": "auth.permission", "fields": {"codename": "add_nonce", "name": "Can add nonce", "content_type": 22}}, {"pk": 65, "model": "auth.permission", "fields": {"codename": "change_nonce", "name": "Can change nonce", "content_type": 22}}, {"pk": 66, "model": "auth.permission", "fields": {"codename": "delete_nonce", "name": "Can delete nonce", "content_type": 22}}, {"pk": 67, "model": "auth.permission", "fields": {"codename": "add_association", "name": "Can add association", "content_type": 23}}, {"pk": 68, "model": "auth.permission", "fields": {"codename": "change_association", "name": "Can change association", "content_type": 23}}, {"pk": 69, "model": "auth.permission", "fields": {"codename": "delete_association", "name": "Can delete association", "content_type": 23}}, {"pk": 70, "model": "auth.permission", "fields": {"codename": "add_useropenid", "name": "Can add user open id", "content_type": 24}}, {"pk": 71, "model": "auth.permission", "fields": {"codename": "change_useropenid", "name": "Can change user open id", "content_type": 24}}, {"pk": 72, "model": "auth.permission", "fields": {"codename": "delete_useropenid", "name": "Can delete user open id", "content_type": 24}}, {"pk": 1, "model": "auth.group", "fields": {"name": "api-website-devs", "permissions": [40, 41, 42, 37, 38, 39, 61, 62, 63, 34, 35, 36, 28, 29, 30, 31, 32, 33, 55, 56, 57, 58, 59, 60, 52, 53, 54, 46, 47, 48, 43, 44, 45, 49, 50, 51]}}]
\ No newline at end of file

=== added directory 'developer_network/common/management'
=== added file 'developer_network/common/management/__init__.py'
=== added directory 'developer_network/common/management/commands'
=== added file 'developer_network/common/management/commands/__init__.py'
=== added file 'developer_network/common/management/commands/initdb.py'
--- developer_network/common/management/commands/initdb.py	1970-01-01 00:00:00 +0000
+++ developer_network/common/management/commands/initdb.py	2013-10-31 19:44:44 +0000
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+
+from django.core.management.base import BaseCommand
+from optparse import make_option
+
+import settings
+
+import subprocess
+import os
+import sys
+
+from common.models import Topic
+from apidocs.models import Element
+from django.contrib.auth.models import Group, Permission
+from django.contrib.contenttypes.models import ContentType
+
+PYTHON_BIN = sys.executable
+PROJECT_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../../'))
+MANAGE_PY = os.path.join(PROJECT_ROOT, 'manage.py')
+COMMON_DATA = os.path.join(PROJECT_ROOT, 'common/fixtures/sample_data.json')
+APIDOCS_DATA = os.path.join(PROJECT_ROOT, 'apidocs/fixtures/sample_data.json')
+
+
+class Command(BaseCommand):
+    help = "Make sure The API Website database is set up properly."
+    option_list = BaseCommand.option_list + (
+        make_option(
+            "-f",
+            "--force",
+            dest="force",
+            help="Force initialization, even if data already exists",
+            action="store_true",
+            default=False
+        ),
+    )
+
+    def handle(self, summit='', *args, **options):
+
+        force = options.get('force', False)
+        
+        if force or Topic.objects.all().count() == 0:
+            print "Loading Common data."
+            subprocess.call([PYTHON_BIN, MANAGE_PY, "loaddata", COMMON_DATA,
+                             "--settings", "local_settings"])
+
+        if force or Element.objects.all().count() == 0:
+            print "Loading API data."
+            subprocess.call([PYTHON_BIN, MANAGE_PY, "loaddata", APIDOCS_DATA,
+                             "--settings", "local_settings"])
+            
+        if force or not Group.objects.filter(name='api-website-devs').exists():
+            print "Creating api-website-devs group."
+            devs, created = Group.objects.get_or_create(name='api-website-devs')
+            common_perms = Permission.objects.filter(content_type__app_label='common')
+            apidocs_perms = Permission.objects.filter(content_type__app_label='apidocs')
+            related_perms = Permission.objects.filter(content_type__app_label='related')
+            search_perms = Permission.objects.filter(content_type__app_label='search')
+            devs.permissions.add(*list(common_perms))
+            devs.permissions.add(*list(apidocs_perms))
+            devs.permissions.add(*list(related_perms))
+            devs.permissions.add(*list(search_perms))
+            

=== added directory 'developer_network/common/templates'
=== added file 'developer_network/common/templates/500.html'
--- developer_network/common/templates/500.html	1970-01-01 00:00:00 +0000
+++ developer_network/common/templates/500.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,10 @@
+{% extends "base.html" %}
+
+{% block page_name %}Oops{%endblock %}
+
+{% block sub_nav %}{% endblock %}
+
+{% block content %}
+<p>This page encountered an error, don't worry - we have been notified.  Please accept our apologies.</p>
+{% endblock %}
+

=== added file 'developer_network/common/templates/login_failure.html'
--- developer_network/common/templates/login_failure.html	1970-01-01 00:00:00 +0000
+++ developer_network/common/templates/login_failure.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+
+{% block page_name %}Login Failure{%endblock %}
+
+{% block defaulthead %}
+{% with '/static/ubuntu-website/' as ubuntu_website_media %}
+{{ block.super }}
+{% endwith %}
+{% endblock %}
+
+{% block extrahead %}
+{% with '/static/' as MEDIA_URL %}
+{{ block.super }}
+{% endwith %}
+{% endblock %}
+{% block main_nav_links %}{% endblock %}
+
+{% block sub_nav %}{% endblock %}
+
+{% block content %}
+
+<article class="main-content">
+    <h2>{{message|safe}}</h2>
+
+    {% if exception %}
+    <p>{{exception.message|safe}}</p>
+    {% endif %}
+
+    {% if solution %}
+    <p>{{solution|safe}}</p>
+    {% endif %}
+
+    <p>If you continue to experience problems with Summit, please <a href='https://bugs.launchpad.net/summit'>Report it!</a>
+    </p>
+</article>
+
+{% endblock %}

=== modified file 'developer_network/common/views.py'
--- developer_network/common/views.py	2013-02-08 22:36:08 +0000
+++ developer_network/common/views.py	2013-10-31 19:44:44 +0000
@@ -1,1 +1,27 @@
-# Create your views here.
+from django.shortcuts import render_to_response, redirect
+from django.template.loader import render_to_string
+from django.template import RequestContext
+from django.http import HttpResponse, HttpResponseRedirect
+from django.core.urlresolvers import reverse
+from django.contrib.auth import logout
+
+def login_failure(request, message, status=403,
+        template_name='login_failure.html',
+        exception=None):
+    """Render an error page to the user."""
+    context = {
+        'message': message,
+        'exception': exception,
+    }
+    if isinstance(exception, MissingPhysicalMultiFactor):
+        context['solution'] = 'Try logging in again using your Yubikey'
+    elif isinstance(exception, MissingUsernameViolation):
+        context['solution'] = 'You will need to create a <a href="https://launchpad.net/people/+me">Launchpad profile</a> to use The API Website'
+
+    data = render_to_string(template_name, context,
+        context_instance=RequestContext(request))
+    return HttpResponse(data, status=status)
+
+def logout_view(request):
+    logout(request)
+    return HttpResponseRedirect('/')

=== modified file 'developer_network/settings.py'
--- developer_network/settings.py	2013-09-13 18:35:01 +0000
+++ developer_network/settings.py	2013-10-31 19:44:44 +0000
@@ -128,6 +128,7 @@
     'related',
     'web',
     'ubuntu_website',
+    'django_openid_auth',
 )
 
 # A sample logging configuration. The only tangible logging
@@ -152,3 +153,21 @@
         },
     }
 }
+
+AUTHENTICATION_BACKENDS = (
+    'django_openid_auth.auth.OpenIDBackend',
+    'django.contrib.auth.backends.ModelBackend',
+)
+# OPENID Related settings
+OPENID_STRICT_USERNAMES = True
+OPENID_FOLLOW_RENAMES = True
+OPENID_SREG_REQUIRED_FIELDS = ['email']
+OPENID_CREATE_USERS = True
+OPENID_REUSE_USERS = True
+OPENID_UPDATE_DETAILS_FROM_SREG = True
+OPENID_SSO_SERVER_URL = 'https://login.ubuntu.com/'
+OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO = True
+
+# Tell django.contrib.auth to use the OpenID signin URLs.
+LOGIN_URL = '/api/login'
+LOGIN_REDIRECT_URL = '/'

=== modified file 'developer_network/urls.py'
--- developer_network/urls.py	2013-10-04 19:56:27 +0000
+++ developer_network/urls.py	2013-10-31 19:44:44 +0000
@@ -8,6 +8,16 @@
 from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 urlpatterns = staticfiles_urlpatterns()
 
+from common.views import login_failure
+urlpatterns += patterns(
+    'django_openid_auth.views',
+    url(r'^api/login/$', 'login_begin', name='openid-login',
+        kwargs={'render_failure': login_failure}),
+    url(r'^api/openid/complete/$', 'login_complete', name='openid-complete',
+        kwargs={'render_failure': login_failure}),
+    url(r'^api/openid/logo.gif$', 'logo', name='openid-logo'),
+)
+
 urlpatterns += patterns('',
     # Examples:
     # url(r'^developer_network/', include('developer_network.foo.urls')),
@@ -17,14 +27,33 @@
 
     # Uncomment the next line to enable the admin:
     url(r'^api/admin/', include(admin.site.urls)),
+    url(r'^api/logout/$', 'common.views.logout_view', name='logout'),
 
     url(r'^$', 'web.views.overview', name='overview'),
     url(r'^api/$', 'web.views.overview', name='overview'),
+
     url(r'^api/(?P<topic_name>[\w\.-]+)/$', 'web.views.topic_view', name='topic'),
+    url(r'^api/\+topic/$', 'web.views.topic_edit', name='topic_edit'),
+    url(r'^api/\+topic/(?P<topic_id>[\d]+)/$', 'web.views.topic_edit', name='topic_edit'),
+
     url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/$', 'web.views.version_view', name='version'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/\+version/$', 'web.views.version_edit', name='version_edit'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/\+version/(?P<version_id>[\d]+)/$', 'web.views.version_edit', name='version_edit'),
+
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<version_name>[\w\.-]+)/\+section/(?P<section_id>[\d]+)/$', 'web.views.section_edit', name='section_edit'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<version_name>[\w\.-]+)/\+section/$', 'web.views.section_edit', name='section_edit'),
+
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<version_name>[\w\.-]+)/\+namespace/(?P<namespace_id>[\d]+)/$', 'web.views.namespace_edit', name='namespace_edit'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<version_name>[\w\.-]+)/\+namespace/$', 'web.views.namespace_edit', name='namespace_edit'),
+
     url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/search/$', 'web.views.search', name='search'),
 
-    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/(?P<element_fullname>[\w\.\-\:]+).html$', 'web.views.element_view', name='element'),
     url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/(?P<element_fullname>[\w\.\-\:]+)/$', 'web.views.element_view', name='element'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/\+element/(?P<element_id>[\d]+)/$', 'web.views.element_edit', name='element_edit'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/\+element/$', 'web.views.element_edit', name='element_edit'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/\+page/(?P<page_id>[\d]+)/$', 'web.views.page_edit', name='page_edit'),
+    url(r'^api/(?P<topic_name>[\w\.-]+)/(?P<release_version>[\w\.-]+)/\+page/$', 'web.views.page_edit', name='page_edit'),
 
 )
+
+

=== modified file 'developer_network/web/static/css/site.css'
--- developer_network/web/static/css/site.css	2013-10-22 20:54:40 +0000
+++ developer_network/web/static/css/site.css	2013-10-31 19:44:44 +0000
@@ -21,6 +21,25 @@
     display: inline;
 }
 
+#editor_actions {
+    background-color: #F1F1F1;
+    padding: 5px;
+    margin-bottom: 10px;
+    /* border-bottom: 1px dotted; */
+}
+
+#editor_actions ul {
+	margin: 0px;
+}
+
+#editor_actions li {
+    margin-right: 10px;
+	margin-bottom: 0;
+	line-height: 33px;
+	float: left;
+	list-style: none;
+	list-style-image: none;
+}
 /*
  * release.html
  */
@@ -47,6 +66,16 @@
     border-top: 1px dotted;
 }
 
+.section_title A.section_editor_action {
+    float: right;
+    font-size: .7em;
+    display: none;
+}
+
+.section_title:hover A.section_editor_action {
+    display: inherit;
+}
+
 /*
  * element.html
 */
@@ -75,54 +104,63 @@
      padding: 3px;
 }
 
+/*
+ * element.html
+*/
+#element_content TEXTAREA {
+    height: inherit;
+    width: inherit;
+    max-width: none;
+    max-height: none;
+}
 /* 
  * sidenav.html
  */
 
 .ui-state-focus {
-	outline: none;
+    outline: none;
 }
 .ui-accordion {
-	border-bottom: 1px dotted #aea79f;
+    border-bottom: 1px dotted #aea79f;
 }
 .ui-accordion a {
-	display: block;
+    display: block;
 }
 .ui-accordion h3 {
-	margin-bottom: 0;
-	border-top: 1px dotted #aea79f;
-	position: relative;
-	font-size: 13px;
-	font-weight: bold;
+    margin-bottom: 0;
+    border-top: 1px dotted #aea79f;
+    position: relative;
+    font-size: 13px;
+    font-weight: bold;
 }
 .ui-accordion h3 a {
-	padding: 10px 0;
-	color: #333;
+    padding: 10px 0;
+    color: #333;
 }
 .ui-accordion h4 {
-	margin-bottom: 5px;
+    margin-bottom: 5px;
 }
 .ui-accordion div fieldset {
-	padding-bottom: 5px;
+    padding-bottom: 5px;
 }
 .ui-accordion div li,
 .ui-accordion div input {
-	margin-bottom: 10px;
+    margin-bottom: 10px;
 }
 .ui-accordion .ui-icon {
-	position: absolute;
-	top: 15px;
-	right: 0;
-	display: block;
-	width: 8px;
-	height: 8px;
-	background: url("../img/icon-accordion-inactive.png") 0 0 no-repeat transparent;
+    position: absolute;
+    top: 15px;
+    right: 0;
+    display: block;
+    width: 8px;
+    height: 8px;
+    background: url("../img/icon-accordion-inactive.png") 0 0 no-repeat transparent;
 }
 .ui-accordion .ui-state-active .ui-icon {
-	background-image: url("../img/icon-accordion-active.png");
+    background-image: url("../img/icon-accordion-active.png");
 }
 .ui-accordion .current_page_item a {
-	color: #333;
+    color: #333;
 }
 
 /*

=== modified file 'developer_network/web/templates/web/article.html'
--- developer_network/web/templates/web/article.html	2013-09-23 21:27:54 +0000
+++ developer_network/web/templates/web/article.html	2013-10-31 19:44:44 +0000
@@ -26,6 +26,23 @@
 					{% endblock %}
 				</span>
 			</section>
+			{% block editor_actions %}
+			{% if perms.common or perms.apidocs %}
+			<section id="editor_actions">
+				<span style="float: right;">
+					<ul class="clearfix">
+					<li><a href="{% url logout %}" title="You are logged in as: {{user.username}}">Logout</a></li>
+					</ul>
+				</span>
+				<span id="editor_links">
+					<ul class="clearfix">
+				{% block editor_links %}
+				{% endblock %}
+					</ul>
+				</span>
+			</section>
+			{% endif %}
+			{% endblock %}
 			<article>
             {% block article_content %}
             {% endblock %}

=== modified file 'developer_network/web/templates/web/distro.html'
--- developer_network/web/templates/web/distro.html	2013-09-13 14:01:30 +0000
+++ developer_network/web/templates/web/distro.html	2013-10-31 19:44:44 +0000
@@ -3,6 +3,26 @@
 {% block sub_nav %}{% endblock %}
 
 {% block content %}
+{% if perms.common %}
+<section id="editor_actions">
+	<span style="float: right;">
+		<ul class="clearfix">
+		<li><a href="{% url logout %}" title="You are logged in as: {{user.username}}">Logout</a></li>
+		</ul>
+	</span>
+	<span id="editor_links">
+		<ul class="clearfix">
+			{% if perms.common.change_topic %}
+			<li><a href="{% url topic_edit topic.id %}">Edit</a></li>
+			{% endif %}
+			{% if perms.common.add_version %}
+			<li><a href="{% url version_edit topic.slug %}">+ Version</a></li>
+			{% endif %}
+		</ul>
+	</span>
+</section>
+{% endif %}
+
 <h2>{{topic.name}} Versions</h2>
 <ul>
 {% for version in topic.version_set.all %}

=== modified file 'developer_network/web/templates/web/element.html'
--- developer_network/web/templates/web/element.html	2013-09-19 17:48:26 +0000
+++ developer_network/web/templates/web/element.html	2013-10-31 19:44:44 +0000
@@ -1,5 +1,14 @@
 {% extends "web/article.html" %}
 
+{% block editor_links %}
+    {% if perms.apidocs.change_element %}
+    <li><a href="{% url element_edit topic.slug, version.slug, element.id %}">Edit</a></li>
+    {% endif %}
+    {% if perms.apidocs.delete_element %}
+    <li><a href="{% url element_edit topic.slug, version.slug, element.id %}?action=delete">Delete</a></li>
+    {% endif %}
+{% endblock %}
+
 {% block breadcrumbs %}
 <li><a class="sub-nav-item" href="{% url topic element.platform_section.topic_version.topic.slug %}">{{element.platform_section.topic_version.topic.name}}</a></li>
 <li> › <a class="sub-nav-item" href="{% url version element.platform_section.topic_version.topic.slug element.platform_section.topic_version.slug %}">{{element.platform_section.topic_version.name}}</a></li>

=== added file 'developer_network/web/templates/web/element_edit.html'
--- developer_network/web/templates/web/element_edit.html	1970-01-01 00:00:00 +0000
+++ developer_network/web/templates/web/element_edit.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,48 @@
+{% extends "web/article.html" %}
+
+{% block editor_links %}
+	{% if element.id and perms.apidocs.delete_element %}
+    <li><a href="{% url element_edit topic.slug version.slug element.id %}?action=delete">Delete</a></li>
+    {% endif %}
+{% endblock %}
+
+{% block breadcrumbs %}
+{% endblock %}
+
+{% block article_content %}
+{% if element.id %}
+<h1>Edit: {{element.name}}</h1>
+{% else %}
+<h1>New Element</h1>
+{% endif %}
+
+<form action="" method="POST" id="element_form">
+{% csrf_token %}
+<div id="element_content">
+{{ form.as_p }}
+</div>
+<input type="submit" value="Save">
+</form>
+
+{% comment %}
+<h3>Snippets</h3>
+{% for snippet in snippets %}
+    <div>
+        <li>{{ snippet.name }}</li>
+    </div>
+{% endfor %}
+
+<h3>Questions & Answers</h3>
+{% for question in questions %}
+    <div>
+        <li><a href="{{ question.url }}">{{ question.name }}</a></li>
+    </div>
+{% endfor %}
+<h3>Tutorials</h3>
+{% for tutorial in tutorials %}
+    <div>
+        <li><a href="{{ tutorial.url }}">{{ tutorial.name }}</a></li>
+    </div>
+{% endfor %}
+{% endcomment %}
+{% endblock %}

=== modified file 'developer_network/web/templates/web/namespace.html'
--- developer_network/web/templates/web/namespace.html	2013-10-04 19:56:27 +0000
+++ developer_network/web/templates/web/namespace.html	2013-10-31 19:44:44 +0000
@@ -1,5 +1,17 @@
 {% extends "web/article.html" %}
 
+{% block editor_links %}
+    {% if perms.apidocs.change_namespace %}
+    <li><a href="{% url namespace_edit version.topic.slug version.slug namespace.id%}">Edit</a></li>
+    {% endif %}
+    {% if perms.apidocs.add_element %}
+    <li><a href="{% url element_edit version.topic.slug version.slug %}">+ Element</a></li>
+    {% endif %}
+    {% if perms.apidocs.add_page %}
+    <li><a href="{% url page_edit version.topic.slug version.slug %}">+ Page</a></li>
+    {% endif %}
+{% endblock %}
+
 {% block breadcrumbs %}
 <li><a class="sub-nav-item" href="{% url topic namespace.platform_section.topic_version.topic.slug %}">{{namespace.platform_section.topic_version.topic.name}}</a></li>
 <li> › <a class="sub-nav-item" href="{% url version namespace.platform_section.topic_version.topic.slug namespace.platform_section.topic_version.slug %}">{{namespace.platform_section.topic_version.name}}</a></li>

=== added file 'developer_network/web/templates/web/namespace_edit.html'
--- developer_network/web/templates/web/namespace_edit.html	1970-01-01 00:00:00 +0000
+++ developer_network/web/templates/web/namespace_edit.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,48 @@
+{% extends "web/article.html" %}
+
+{% block editor_links %}
+	{% if namespace.id and perms.apidocs.delete_namespace %}
+    <li><a href="{% url namespace_edit topic.slug version.slug namespace.id %}?action=delete">Delete</a></li>
+    {% endif %}
+{% endblock %}
+
+{% block breadcrumbs %}
+{% endblock %}
+
+{% block article_content %}
+{% if namespace.id %}
+<h1>Edit: {{namespace.name}}</h1>
+{% else %}
+<h1>New Namespace</h1>
+{% endif %}
+
+<form action="" method="POST" id="namespace_form">
+{% csrf_token %}
+<div id="namespace_content">
+{{ form.as_p }}
+</div>
+<input type="submit" value="Save">
+</form>
+
+{% comment %}
+<h3>Snippets</h3>
+{% for snippet in snippets %}
+    <div>
+        <li>{{ snippet.name }}</li>
+    </div>
+{% endfor %}
+
+<h3>Questions & Answers</h3>
+{% for question in questions %}
+    <div>
+        <li><a href="{{ question.url }}">{{ question.name }}</a></li>
+    </div>
+{% endfor %}
+<h3>Tutorials</h3>
+{% for tutorial in tutorials %}
+    <div>
+        <li><a href="{{ tutorial.url }}">{{ tutorial.name }}</a></li>
+    </div>
+{% endfor %}
+{% endcomment %}
+{% endblock %}

=== modified file 'developer_network/web/templates/web/overview.html'
--- developer_network/web/templates/web/overview.html	2013-09-13 14:01:30 +0000
+++ developer_network/web/templates/web/overview.html	2013-10-31 19:44:44 +0000
@@ -3,6 +3,23 @@
 {% block sub_nav %}{% endblock %}
 
 {% block content %}
+{% if perms.common %}
+<section id="editor_actions">
+	<span style="float: right;">
+		<ul class="clearfix">
+		<li><a href="{% url logout %}" title="You are logged in as: {{user.username}}">Logout</a></li>
+		</ul>
+	</span>
+	<span id="editor_links">
+		<ul class="clearfix">
+			{% if perms.common.add_topic %}
+			<li><a href="{% url topic_edit %}">+ Topic</a></li>
+			{% endif %}
+		</ul>
+	</span>
+</section>
+{% endif %}
+
 <h2>Topics</h2>
 <ul>
 {% for topic in topics %}

=== modified file 'developer_network/web/templates/web/page.html'
--- developer_network/web/templates/web/page.html	2013-10-04 19:56:27 +0000
+++ developer_network/web/templates/web/page.html	2013-10-31 19:44:44 +0000
@@ -1,5 +1,14 @@
 {% extends "web/article.html" %}
 
+{% block editor_links %}
+    {% if perms.apidocs.change_page %}
+    <li><a href="{% url page_edit topic.slug version.slug page.id %}">Edit</a></li>
+    {% endif %}
+    {% if perms.apidocs.delete_page %}
+    <li><a href="{% url page_edit topic.slug version.slug page.id %}?action=delete">Delete</a></li>
+    {% endif %}
+{% endblock %}
+
 {% block breadcrumbs %}
 <li><a class="sub-nav-item" href="{% url topic page.section.topic_version.topic.slug %}">{{page.section.topic_version.topic.name}}</a></li>
 <li> › <a class="sub-nav-item" href="{% url version page.section.topic_version.topic.slug page.section.topic_version.slug %}">{{page.section.topic_version.name}}</a></li>

=== added file 'developer_network/web/templates/web/page_edit.html'
--- developer_network/web/templates/web/page_edit.html	1970-01-01 00:00:00 +0000
+++ developer_network/web/templates/web/page_edit.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,25 @@
+{% extends "web/article.html" %}
+
+{% block editor_links %}
+	{% if page.id and perms.apidocs.delete_page %}
+    <li><a href="{% url page_edit topic.slug version.slug page.id %}?action=delete">Delete</a></li>
+    {% endif %}
+{% endblock %}
+
+{% block breadcrumbs %}
+{% endblock %}
+
+{% block article_content %}
+{% if page.id %}
+<h2>Edit {{page.name}}</h2>
+{% else %}
+<h2>New Page</h2>
+{% endif %}
+
+<form action="" method="POST" id="page_form">
+{% csrf_token %}
+{{ form.as_p }}
+<input type="submit" value="Save">
+</form>
+
+{% endblock %}

=== modified file 'developer_network/web/templates/web/release.html'
--- developer_network/web/templates/web/release.html	2013-09-19 17:48:26 +0000
+++ developer_network/web/templates/web/release.html	2013-10-31 19:44:44 +0000
@@ -1,5 +1,20 @@
 {% extends "web/article.html" %}
 
+{% block editor_links %}
+    {% if perms.common.change_version %}
+    <li><a href="{% url version_edit version.topic.slug version.id %}">Edit</a></li>
+    {% endif %}
+    {% if perms.common.add_section %}
+    <li><a href="{% url section_edit version.topic.slug version.slug %}">+ Section</a></li>
+    {% endif %}
+    {% if perms.apidocs.add_namespace %}
+    <li><a href="{% url namespace_edit version.topic.slug version.slug %}">+ Namespace</a></li>
+    {% endif %}
+    {% if perms.apidocs.add_element %}
+    <li><a href="{% url element_edit version.topic.slug version.slug %}">+ Element</a></li>
+    {% endif %}
+{% endblock %}
+
 {% block breadcrumbs %}
 <li><a class="sub-nav-item" href="{% url topic version.topic.slug %}">{{version.topic.name}}</a></li>
 <li> › {{version.name}}</li>
@@ -10,7 +25,7 @@
 <table class="section_list"><tr>
     <td id="first_column">
     {% for section in first_column %}
-    <h3>{{section.name}}</h3>
+    <h3 class="section_title">{{section.name}}{% if perms.common.change_section %}<a class="section_editor_action" href="{% url section_edit version.topic.slug version.slug section.id %}">Edit</a>{% endif %}</h3>
     <ul>
         {% for namespace in section.namespace_set.all %}
         <li><a href="{% url element version.topic.slug version.slug namespace.name %}">{{namespace.name}}</a></li>
@@ -33,7 +48,7 @@
     {% if second_column %}
     <td id="second_column">
     {% for section in second_column %}
-    <h3>{{section.name}}</h3>
+    <h3 class="section_title">{{section.name}}{% if perms.common.change_section %}<a class="section_editor_action" href="{% url section_edit version.topic.slug version.slug section.id %}">Edit</a>{% endif %}</h3>
     <ul>
         {% for namespace in section.namespace_set.all %}
         <li><a href="{% url element version.topic.slug version.slug namespace.name %}">{{namespace.name}}</a></li>

=== modified file 'developer_network/web/templates/web/search.html'
--- developer_network/web/templates/web/search.html	2013-09-23 21:27:54 +0000
+++ developer_network/web/templates/web/search.html	2013-10-31 19:44:44 +0000
@@ -1,5 +1,7 @@
 {% extends "web/article.html" %}
 
+{% block editor_actions %}{% endblock %}
+
 {% block breadcrumbs %}
 <li><a class="sub-nav-item" href="{% url topic version.topic.slug %}">{{version.topic.name}}</a></li>
 <li> › <a class="sub-nav-item" href="{% url version version.topic.slug version.slug %}">{{version.name}}</a></li>

=== added file 'developer_network/web/templates/web/section_edit.html'
--- developer_network/web/templates/web/section_edit.html	1970-01-01 00:00:00 +0000
+++ developer_network/web/templates/web/section_edit.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,25 @@
+{% extends "web/article.html" %}
+
+{% block editor_links %}
+	{% if section.id and perms.common.delete_section %}
+    <li><a href="{% url section_edit topic.slug version.slug section.id %}?action=delete">Delete</a></li>
+    {% endif %}
+{% endblock %}
+
+{% block breadcrumbs %}
+{% endblock %}
+
+{% block article_content %}
+{% if section.id %}
+<h2>Edit {{section.name}}</h2>
+{% else %}
+<h2>New Section</h2>
+{% endif %}
+
+<form action="" method="POST" id="section_form">
+{% csrf_token %}
+{{ form.as_p }}
+<input type="submit" value="Save">
+</form>
+
+{% endblock %}

=== added file 'developer_network/web/templates/web/topic_edit.html'
--- developer_network/web/templates/web/topic_edit.html	1970-01-01 00:00:00 +0000
+++ developer_network/web/templates/web/topic_edit.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,18 @@
+{% extends "web/base.html" %}
+
+{% block sub_nav %}{% endblock %}
+
+{% block content %}
+
+{% if topic.id %}
+<h2>Edit: {{topic.name}}</h2>
+{% else %}
+<h2>New Topic</h2>
+{% endif %}
+
+<form action="" method="POST" id="topic_form">
+{% csrf_token %}
+{{ form.as_p }}
+<input type="submit" value="Save">
+</form>
+{% endblock %}

=== added file 'developer_network/web/templates/web/version_edit.html'
--- developer_network/web/templates/web/version_edit.html	1970-01-01 00:00:00 +0000
+++ developer_network/web/templates/web/version_edit.html	2013-10-31 19:44:44 +0000
@@ -0,0 +1,23 @@
+{% extends "web/base.html" %}
+
+{% block editor_links %}
+    <li><a href="{% url version_edit version.id %}?action=delete">Delete</a></li>
+{% endblock %}
+
+{% block breadcrumbs %}
+{% endblock %}
+
+{% block content %}
+{% if version.id %}
+<h2>Edit {{version.name}}</h2>
+{% else %}
+<h2>New Version</h2>
+{% endif %}
+
+<form action="" method="POST" id="element_form">
+{% csrf_token %}
+{{ form.as_p }}
+<input type="submit" value="Save">
+</form>
+
+{% endblock %}

=== modified file 'developer_network/web/views.py'
--- developer_network/web/views.py	2013-10-04 19:56:27 +0000
+++ developer_network/web/views.py	2013-10-31 19:44:44 +0000
@@ -2,6 +2,7 @@
 from django.http import HttpResponse, HttpResponseRedirect
 from django.core.urlresolvers import reverse
 from django.template import loader, RequestContext
+from django.forms import ModelForm
 
 from common.models import Topic, Version, Section
 from apidocs.models import Namespace, Element, Page
@@ -24,6 +25,32 @@
     }
     return render_to_response('web/distro.html', context, RequestContext(request))
 
+class TopicForm(ModelForm):
+    class Meta:
+        model = Topic
+
+def topic_edit(request, topic_id=0):
+    if topic_id:
+        topic = get_object_or_404(Topic, id=topic_id)
+    else:
+        topic = Topic()
+
+    if not request.user.has_perm('common.change_topic'):
+        return HttpResponseRedirect(reverse(topic_view, args=[topic.slug]))
+
+    if request.method == 'POST':
+        form = TopicForm(request.POST, instance=topic)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse(topic_view, args=[topic.slug]))
+    else:
+        form = TopicForm(instance=topic)
+    context = {
+        'form': form,
+        'topic': topic,
+    }
+    return render_to_response('web/topic_edit.html', context, RequestContext(request))
+
 def version_view(request, topic_name, release_version):
     version = get_object_or_404(Version, topic__slug=topic_name, slug=release_version)
 
@@ -63,6 +90,68 @@
     }
     return render_to_response('web/release.html', context, RequestContext(request))
 
+class VersionForm(ModelForm):
+    class Meta:
+        model = Version
+
+def version_edit(request, topic_name, version_id=0):
+    if version_id:
+        version = get_object_or_404(Version, topic__slug=topic_name, id=version_id)
+        topic = version.topic
+    else:
+        topic = get_object_or_404(Topic, slug=topic_name)
+        version = Version(topic=topic)
+
+    if not request.user.has_perm('common.change_version'):
+        return HttpResponseRedirect(reverse(version_view, args=[topic.slug, version.slug]))
+
+    if request.method == 'POST':
+        form = VersionForm(request.POST, instance=version)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse(version_view, args=[topic.slug, version.slug]))
+    else:
+        form = VersionForm(instance=version)
+    context = {
+        'form': form,
+        'topic': topic,
+        'version': version,
+    }
+    return render_to_response('web/version_edit.html', context, RequestContext(request))
+
+class SectionForm(ModelForm):
+    class Meta:
+        model = Section
+
+def section_edit(request, topic_name, version_name, section_id=0):
+    if section_id:
+        section = get_object_or_404(Section, topic_version__topic__slug=topic_name, topic_version__slug=version_name, id=section_id)
+        version = section.topic_version
+        topic = version.topic
+    else:
+        topic = get_object_or_404(Topic, slug=topic_name)
+        version = get_object_or_404(Version, topic=topic, slug=version_name)
+        section = Section(topic_version=version)
+
+    if not request.user.has_perm('common.change_section'):
+        return HttpResponseRedirect(reverse(version_view, args=[topic.slug, version.slug]))
+
+    if request.method == 'POST':
+        form = SectionForm(request.POST, instance=section)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse(version_view, args=[topic.slug, version.slug]))
+    else:
+        form = SectionForm(instance=section)
+    context = {
+        'sidenav': topic_name,
+        'form': form,
+        'topic': topic,
+        'version': version,
+        'section': section,
+    }
+    return render_to_response('web/section_edit.html', context, RequestContext(request))
+
 def namespace_view(request, topic_name, release_version, namespace_name):
     try:
         namespace = Namespace.objects.get(platform_section__topic_version__slug=release_version, platform_section__topic_version__topic__slug=topic_name, name=namespace_name)
@@ -82,6 +171,50 @@
     }
     return render_to_response('web/namespace.html', context, RequestContext(request))
 
+class NamespaceForm(ModelForm):
+    class Meta:
+        model = Namespace
+        
+    def __init__(self, *args, **kargs):
+        if 'version' in kargs:
+            version = kargs['version']
+            del kargs['version']
+        elif hasattr(self, 'instance') and self.instance.section:
+            version = self.instance.section.topic_version
+        else:
+            version=None
+        super(NamespaceForm, self).__init__(*args, **kargs)
+        self.fields['platform_section'].queryset = Section.objects.filter(topic_version=version)
+                
+def namespace_edit(request, topic_name, version_name, namespace_id=0):
+    if namespace_id:
+        namespace = get_object_or_404(Namespace, platform_section__topic_version__slug=version_name, platform_section__topic_version__topic__slug=topic_name, id=namespace_id)
+        version = namespace.platform_section.topic_version
+        topic = version.topic
+    else:
+        topic = get_object_or_404(Topic, slug=topic_name)
+        version = get_object_or_404(Version, slug=version_name, topic=topic)
+        namespace = Namespace()
+
+    if not request.user.has_perm('apidocs.change_namespace'):
+        return HttpResponseRedirect(reverse(element_view, args=[topic_name, version_name, namespace.name]))
+
+    if request.method == 'POST':
+        form = NamespaceForm(request.POST, instance=namespace, version=version)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse(element_view, args=[topic_name, version_name, namespace.name]))
+    else:
+        form = NamespaceForm(instance=namespace, version=version)
+    context = {
+        'form': form,
+        'sidenav': topic_name,
+        'topic': topic,
+        'version': version,
+        'namespace': namespace,
+    }
+    return render_to_response('web/namespace_edit.html', context, RequestContext(request))
+
 def page_view(request, topic_name, release_version, page_fullname):
     page = get_object_or_404(Page, section__topic_version__slug=release_version, section__topic_version__topic__slug=topic_name, fullname=page_fullname)
 
@@ -99,6 +232,51 @@
     }
     return render_to_response('web/page.html', context, RequestContext(request))
 
+class PageForm(ModelForm):
+    class Meta:
+        model = Page
+        
+    def __init__(self, *args, **kargs):
+        if 'version' in kargs:
+            version = kargs['version']
+            del kargs['version']
+        elif hasattr(self, 'instance') and self.instance.section:
+            version = self.instance.section.topic_version
+        else:
+            version=None
+        super(PageForm, self).__init__(*args, **kargs)
+        self.fields['section'].queryset = Section.objects.filter(topic_version=version)
+        self.fields['namespace'].queryset = Namespace.objects.filter(platform_section__topic_version=version)
+                
+def page_edit(request, topic_name, release_version, page_id=0):
+    if page_id:
+        page = get_object_or_404(Page, section__topic_version__slug=release_version, section__topic_version__topic__slug=topic_name, id=page_id)
+        version = page.section.topic_version
+        topic = version.topic
+    else:
+        topic = get_object_or_404(Topic, slug=topic_name)
+        version = get_object_or_404(Version, slug=release_version, topic=topic)
+        page = Page()
+
+    if not request.user.has_perm('apidocs.change_page'):
+        return HttpResponseRedirect(reverse(version_view, args=[topic_name, release_version]))
+
+    if request.method == 'POST':
+        form = PageForm(request.POST, instance=page, version=version)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse(version_view, args=[topic_name, release_version]))
+    else:
+        form = PageForm(instance=page, version=version)
+    context = {
+        'form': form,
+        'sidenav': topic_name,
+        'topic': topic,
+        'version': version,
+        'page': page,
+    }
+    return render_to_response('web/page_edit.html', context, RequestContext(request))
+    
 def element_view(request, topic_name, release_version, element_fullname):
     try:
         element = Element.objects.get(section__topic_version__slug=release_version, section__topic_version__topic__slug=topic_name, fullname=element_fullname)
@@ -120,6 +298,51 @@
         'tutorials': tutorials
     }
     return render_to_response('web/element.html', context, RequestContext(request))
+
+class ElementForm(ModelForm):
+    class Meta:
+        model = Element
+        
+    def __init__(self, *args, **kargs):
+        if 'version' in kargs:
+            version = kargs['version']
+            del kargs['version']
+        elif hasattr(self, 'instance') and self.instance.section:
+            version = self.instance.section.topic_version
+        else:
+            version=None
+        super(ElementForm, self).__init__(*args, **kargs)
+        self.fields['section'].queryset = Section.objects.filter(topic_version=version)
+        self.fields['namespace'].queryset = Namespace.objects.filter(platform_section__topic_version=version)
+                
+def element_edit(request, topic_name, release_version, element_id=0):
+    if element_id:
+        element = get_object_or_404(Element, section__topic_version__slug=release_version, section__topic_version__topic__slug=topic_name, id=element_id)
+        version = element.section.topic_version
+        topic = version.topic
+    else:
+        topic = get_object_or_404(Topic, slug=topic_name)
+        version = get_object_or_404(Version, slug=release_version, topic=topic)
+        element = Element()
+
+    if not request.user.has_perm('apidocs.change_element'):
+        return HttpResponseRedirect(reverse(element_view, args=[topic_name, release_version, element.fullname]))
+
+    if request.method == 'POST':
+        form = ElementForm(request.POST, instance=element, version=version)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse(element_view, args=[topic_name, release_version, element.fullname]))
+    else:
+        form = ElementForm(instance=element, version=version)
+    context = {
+        'form': form,
+        'sidenav': topic_name,
+        'topic': topic,
+        'version': version,
+        'element': element,
+    }
+    return render_to_response('web/element_edit.html', context, RequestContext(request))
     
 def search(request, topic_name, release_version):
     version = get_object_or_404(Version, topic__slug=topic_name, slug=release_version)

=== modified file 'requirements.txt'
--- requirements.txt	2013-09-11 16:48:02 +0000
+++ requirements.txt	2013-10-31 19:44:44 +0000
@@ -3,3 +3,5 @@
 distribute==0.6.31
 wsgiref==0.1.2
 South==0.8.2
+django-openid-auth==0.5
+python-openid==2.2.4

