changeset 128:70abe9b6819e

- Update/precise TODO roadmap - Remove authorized_key fields from ExtendedUser (replaced by SshKey) - Actual save the password when it's changed - Support Django 1.1's admin URLs - Fix typo
author Sylvain Beucler <beuc@beuc.net>
date Tue, 11 Aug 2009 08:58:19 +0200
parents 1b21c8c5fe39
children 58bab9662fb2 ef5792861c2d
files TODO migrate_old_savane.sql src/savane/middleware/debug.py src/savane/my/views.py src/savane/svmain/admin.py src/savane/svmain/models.py src/urls.py
diffstat 7 files changed, 53 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/TODO
+++ b/TODO
@@ -16,8 +16,19 @@
 
     [ ] Members list + GPG keyring
 
-    [/] Account conf ([X] e-mail, [X] password, [X] real name, [/] SSH
-        keys, [X] GPG key)
+    [/] Account conf
+
+        [/] e-mail TODO: send mail to verify it, pre-fill the field
+	    with the current value
+
+        [X] password
+
+        [X] real name
+
+        [/] SSH keys TODO: maybe display existing keys better; avoid
+	    using GET for deletions (use POST instead)
+
+        [X] GPG key
 
     [/] My Groups
 
@@ -27,14 +38,18 @@
     [ ] Delete account (clean-up data but keep User+user_id if past
         history)
 
+[ ] Project registration
+
 [ ] Implement web screens (lower priority)
 
-    [ ] Account conf 2 ([ ] profile, [ ] skills, [ ] timezone)
+    [ ] Account conf 2 ([ ] profile/resume, [ ] skills, [ ] timezone)
 
     [ ] Bookmarks? Was considered for deletion at a point in Savane:
         http://gna.org/task/?1412 - note that yeupou is a bit partial
         towards trackers in that discussion
 
+[X] Admin interface (implemented via Django admin)
+
 [ ] News management (+ comments)
 
 [/] Work on the web design
@@ -84,6 +99,9 @@
     trackers can use it, until we rewrite them.  Possible do the same
     for jobs and news.
 
+[ ] Avoid using Django-specific sha1$ password format - cf. LDAP
+    section below
+
 [ ] Add some tests
 
 =====
@@ -105,7 +123,9 @@
         mail...)
 
     [ ] Implement a Django backend that supports SSHA or CRYPT (CRYPT
-        may be better since all PAM modules would support it)
+        may be better since all PAM modules would support it.  We mean
+        glibc2-crypt, as documented in crypt(3), with salted MD5
+        digests, among others)
 
 [ ] Migration to PostgreSQL?
 
--- a/migrate_old_savane.sql
+++ b/migrate_old_savane.sql
@@ -60,11 +60,11 @@
 -- Import all extended information except for the 'None' user (#100)
 TRUNCATE svmain_extendeduser;
 INSERT INTO svmain_extendeduser
-    (user_ptr_id, status, spamscore, authorized_keys,
-     authorized_keys_count, people_view_skills, people_resume,
+    (user_ptr_id, status, spamscore,
+     people_view_skills, people_resume,
      timezone, theme, email_hide, gpg_key, gpg_key_count)
-  SELECT user_id, status, spamscore, IFNULL(authorized_keys, ''),
-      authorized_keys_count, people_view_skills,
+  SELECT user_id, status, spamscore,
+      people_view_skills,
       people_resume, IFNULL(timezone, ''), IFNULL(theme, ''),
       IFNULl(email_hide, 0), IFNULL(gpg_key, ''), gpg_key_count
     FROM savane_old.user
--- a/src/savane/middleware/debug.py
+++ b/src/savane/middleware/debug.py
@@ -139,7 +139,8 @@
 
         if hasattr(view_func,'view_func'):
             # it the view_func has a view_func then its a decorator
-            co = view_func.view_func.func_code
+            if hasattr(view_func.view_func, 'func_code'):
+                co = view_func.view_func.func_code
         else:
             co = view_func.func_code
             
--- a/src/savane/my/views.py
+++ b/src/savane/my/views.py
@@ -58,6 +58,7 @@
             if action == 'update_password':
                 if request.user.check_password( request.POST['old_password'] ):
                     request.user.set_password( request.POST['new_password'] );
+                    request.user.save()
                     success_msg = "Password was successfully changed."
                     form_pass = PasswordForm()
                 else:
@@ -66,7 +67,7 @@
                 new_email = request.POST['email']
                 request.user.email = new_email
                 request.user.save()
-                form_mail = MilForm()
+                form_mail = MailForm()
                 success_msg = 'The E-Mail address was succesfully updated. New E-Mail address is <'+new_email+'>'
             elif action == 'update_identity':
                 request.user.first_name = request.POST['name']
--- a/src/savane/svmain/admin.py
+++ b/src/savane/svmain/admin.py
@@ -11,6 +11,10 @@
     list_display  = ['name', 'pk']
     search_fields = ['name']
 
+class SshKeyInline(admin.TabularInline):
+    model = svmain_models.SshKey
+    extra = 2  # to add several keys in the ExtendedUser page
+
 class ExtendedUserAdmin(admin.ModelAdmin):
     # Copy/pasted from django.contrib.auth.admin; inheritance fails
     # when you attempt to display extended fields..
@@ -22,7 +26,6 @@
         (_('Groups'), {'fields': ('groups',)}),
         (_('Savane'),
          {'fields': ('status', 'spamscore',
-                     'authorized_keys', 'authorized_keys_count',
                      'gpg_key', 'gpg_key_count',
                      'people_view_skills', 'email_hide', 'timezone', 'theme',)}),
         )
@@ -31,6 +34,7 @@
     search_fields = ('username', 'first_name', 'last_name', 'email')
     ordering = ('username',)
     filter_horizontal = ('user_permissions',)
+    inlines = [SshKeyInline]
 
 class GroupConfigurationAdmin(admin.ModelAdmin):
     fieldsets = (
--- a/src/savane/svmain/models.py
+++ b/src/savane/svmain/models.py
@@ -61,9 +61,11 @@
 
 class SshKey(models.Model):
     user = models.ForeignKey('ExtendedUser')
+    # Could a CharField with max_length=3000 or something similar, as
+    # it's a single line of text, but it sounds safer to use a
+    # TextField for such a long text.  Too bad for the admin/ area.
     ssh_key = models.TextField(blank=False)
 
-
 class ExtendedUser(auth_models.User):
     """Django base User class + extra Savane fields"""
 
@@ -91,10 +93,9 @@
     #confirm_hash = models.CharField(max_length=96, blank=True, null=True)
 
     # Keys
-    authorized_keys = models.TextField(blank=True)
-    authorized_keys_count = models.IntegerField(null=True, blank=True)
     gpg_key = models.TextField(blank=True)
     gpg_key_count = models.IntegerField(null=True, blank=True)
+    # SSH keys: cf. SshKey above
 
     # Personal info
     people_resume = models.TextField()
@@ -157,7 +158,7 @@
     TODO: support several licenses per project (mixed-licensed code,
     documentation, ...)
     """
-    slug = models.CharField(max_length=32)
+    slug = models.SlugField(max_length=32)
     name = models.CharField(max_length=255)
     url = models.CharField(max_length=255, blank=True)
 
--- a/src/urls.py
+++ b/src/urls.py
@@ -36,10 +36,18 @@
 
 # Enable the auto-admin:
 from django.contrib import admin
+import django
 admin.autodiscover()
-urlpatterns += patterns('',
-  (r'^admin/(.*)', admin.site.root),
-)
+
+if django.VERSION[0] > 1 or (django.VERSION[0] == 1 and django.VERSION[1] >= 1):
+    urlpatterns += patterns('',
+      (r'^admin/', include(admin.site.urls)),
+    )
+else:
+    urlpatterns += patterns('',
+      (r'^admin/(.*)', admin.site.root),
+    )
+
 
 # Static content
 if settings.DEBUG: