diff options
Diffstat (limited to 'coip/apps')
-rw-r--r-- | coip/apps/auth/views.py | 8 | ||||
-rw-r--r-- | coip/apps/entity/__init__.py | 0 | ||||
-rw-r--r-- | coip/apps/entity/admin.py | 4 | ||||
-rw-r--r-- | coip/apps/entity/models.py | 32 | ||||
-rw-r--r-- | coip/apps/membership/forms.py | 23 | ||||
-rw-r--r-- | coip/apps/membership/models.py | 64 | ||||
-rw-r--r-- | coip/apps/membership/views.py | 77 | ||||
-rw-r--r-- | coip/apps/name/models.py | 8 | ||||
-rw-r--r-- | coip/apps/opensocial/people.py | 2 | ||||
-rw-r--r-- | coip/apps/userprofile/forms.py | 30 | ||||
-rw-r--r-- | coip/apps/userprofile/models.py | 43 | ||||
-rw-r--r-- | coip/apps/userprofile/tasks.py | 48 | ||||
-rw-r--r-- | coip/apps/userprofile/views.py | 176 |
13 files changed, 313 insertions, 202 deletions
diff --git a/coip/apps/auth/views.py b/coip/apps/auth/views.py index 18b4430..be816d1 100644 --- a/coip/apps/auth/views.py +++ b/coip/apps/auth/views.py @@ -4,14 +4,8 @@ Created on Jul 5, 2010 @author: leifj ''' from django.http import HttpResponseRedirect -from coip.apps.userprofile.models import UserProfile, home_name -from django.contrib.auth.models import User -from coip.apps.auth.utils import anonid -from coip.apps.name.models import lookup -import datetime +from coip.apps.userprofile.views import home_name from django.views.decorators.cache import never_cache -import logging -from coip.apps.membership.models import add_member def meta(request,attr): v = request.META.get(attr) diff --git a/coip/apps/entity/__init__.py b/coip/apps/entity/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/coip/apps/entity/__init__.py +++ /dev/null diff --git a/coip/apps/entity/admin.py b/coip/apps/entity/admin.py deleted file mode 100644 index 516e153..0000000 --- a/coip/apps/entity/admin.py +++ /dev/null @@ -1,4 +0,0 @@ -from django.contrib import admin -from coip.apps.entity.models import Entity - -admin.site.register(Entity)
\ No newline at end of file diff --git a/coip/apps/entity/models.py b/coip/apps/entity/models.py deleted file mode 100644 index 06f89fe..0000000 --- a/coip/apps/entity/models.py +++ /dev/null @@ -1,32 +0,0 @@ -''' -Created on Feb 23, 2011 - -@author: leifj -''' - -from django.db import models -import re -from pprint import pformat -import logging -from django.db.models.fields import CharField, SmallIntegerField - -class Entity(models.Model): - - SP = 0 - IDP = 1 - OTHER = 2 - - entityId = CharField(max_length=1024,unique=True,editable=False) - display_name = CharField(max_length=1024,blank=True,null=True) - type = SmallIntegerField(blank=True,null=True,editable=False,choices=((IDP,"Identity Provider"),(SP,"Service Provider"),(OTHER,"Other Entity"))) - timecreated = models.DateTimeField(auto_now_add=True) - lastupdated = models.DateTimeField(auto_now=True) - - def __unicode__(self): - return "%s (%s)" % (self.name(),self.type) - - def name(self): - if self.display_name: - return self.display_name - else: - return self.entityId
\ No newline at end of file diff --git a/coip/apps/membership/forms.py b/coip/apps/membership/forms.py index d44bb3b..b935e35 100644 --- a/coip/apps/membership/forms.py +++ b/coip/apps/membership/forms.py @@ -5,28 +5,21 @@ Created on Jun 23, 2010 ''' from coip.apps.membership.models import Membership from form_utils.forms import BetterModelForm -from django.forms.fields import ChoiceField, CharField -from django.forms.widgets import Select, HiddenInput +from django.forms.fields import CharField +from django.forms.widgets import HiddenInput, TextInput class MembershipForm(BetterModelForm): - type = ChoiceField(choices=(("user","I'm adding a user to the group"),("entity","I'm adding a relying party (SP or IdP) to the group")), label="", widget=Select(attrs={'class':'link'}), required=False, initial="user") - username = CharField(label="Username") + username = CharField(label="User") class Meta: model = Membership - fields = ['entity','user'] + fields = ['user'] widgets = { - 'user': HiddenInput() + 'user': HiddenInput(), + 'username': TextInput(attrs={'size': 40}) } - fieldsets = [('type', {'fields': ['type'], - 'legend': 'Which type of member are you adding to the group?', - 'description': 'Groups can consist of users and/or relying partys. Adding a relying party to a group limits can be useful if you want to limit the visibility of your group. This is an advanced option and you should know what you are doing.', - 'classes': ['step']}), - ('entity', {'fields': ['entity'], - 'legend': 'Adding a federation entity to the group', - 'description': 'Select the relying party you wish to add to the group.', - 'classes': ['step','submit_step']}), + fieldsets = [ ('user', {'fields': ['user','username'], 'legend': 'Adding a user to the group', - 'description': 'Provide the federation identifier of the user you wish to join. That user must have already logged in at least once. To add a user that has not yet logged in, send an invitation instead.', + 'description': 'Start typing to find the user to add. That user must have already logged in at least once. To add a user that has not yet logged in, send an invitation instead.', 'classes': ['step','submit_step']}) ]
\ No newline at end of file diff --git a/coip/apps/membership/models.py b/coip/apps/membership/models.py index b19c04a..71143b5 100644 --- a/coip/apps/membership/models.py +++ b/coip/apps/membership/models.py @@ -7,18 +7,23 @@ from django.db import models from django.contrib.auth.models import User from coip.apps.name.models import Name import datetime -import logging -from coip.apps.entity.models import Entity import tagging from django.core.mail import send_mail from coip.settings import NOREPLY +from coip.extensions.templatetags.userdisplay import userdisplay +from coip.apps.userprofile.models import UserProfile + +STATUS = {UserProfile.INTERNAL:'internal', + UserProfile.ENTITY:'entity', + UserProfile.SSHKEY:'sshkey', + UserProfile.X509:'certificate', + UserProfile.FEDID:'fedid'} class Membership(models.Model): ''' Membership in a namespace/group ''' - user = models.ForeignKey(User,blank=True,null=True,related_name='memberships') - entity = models.ForeignKey(Entity,blank=True,null=True,related_name='entity') # XXX should this be memberships too? + user = models.ForeignKey(User,related_name='memberships') name = models.ForeignKey(Name,related_name='memberships') enabled = models.BooleanField() hidden = models.BooleanField() @@ -27,12 +32,7 @@ class Membership(models.Model): expires = models.DateTimeField(blank=True,null=True) def __unicode__(self): - who = "(unknown)" - if self.user: - who = self.user - elif self.entity: - who = self.entity - + who = self.user status = "" if not self.enabled: status = " (disabled)" @@ -49,18 +49,15 @@ class Membership(models.Model): return "active" else: return "inactive"; - - def is_user(self): - return self.user != None - def is_entity(self): - return self.entity != None + def type(self): + return STATUS[self.user.get_profile().type] def send_notification(self,what): if not self.user or not self.user.email: return - - send_mail('You have been %s \'%s\'' % (what,self.name.short), + + send_mail('%s have been %s \'%s\'' % (userdisplay(self.user),what,self.name.short), ''' You have been %s \'%s\'. @@ -74,41 +71,40 @@ To view information about \'%s\' open this link in your browser: return def add_member(name,member_name,hidden=False): - if isinstance(member_name,User): - (m,created) = Membership.objects.get_or_create(user=member_name,name=name) - else: - (m,created) = Membership.objects.get_or_create(entity=member_name,name=name) - + (m,created) = Membership.objects.get_or_create(user=member_name,name=name) if created or not m.enabled or m.hidden != hidden: m.enabled = True m.hidden = hidden m.save() + + if name.nmembers != -1: + name.nmembers = -1 + name.save() return m.send_notification("added to") def disable_member(name,member_name): - if isinstance(member_name,User): - m = Membership.objects.get(name=name,user=member_name) - else: - m = Membership.objects.get(name=name,entity=member_name) + m = Membership.objects.get(name=name,user=member_name) if m: m.enabled = False m.save() m.send_notification("temporarily removed from") + if name.nmembers != -1: + name.nmembers = -1 + name.save() + def remove_member(name,member_name): - if isinstance(member_name,User): - m = Membership.objects.get(name=name,user=member_name) - else: - m = Membership.objects.get(name=name,entity=member_name) + m = Membership.objects.get(name=name,user=member_name) if m: m.send_notification("removed from") m.delete() + + if name.nmembers != -1: + name.nmembers = -1 + name.save() def has_member(name,member_name): - if isinstance(member_name,User): - return Membership.objects.filter(name=name,user=member_name) - else: - return Membership.objects.filter(name=name,entity=member_name) + return Membership.objects.filter(name=name,user=member_name) tagging.register(Membership)
\ No newline at end of file diff --git a/coip/apps/membership/views.py b/coip/apps/membership/views.py index 176f750..97c8c46 100644 --- a/coip/apps/membership/views.py +++ b/coip/apps/membership/views.py @@ -7,15 +7,11 @@ from django.shortcuts import get_object_or_404 from coip.apps.membership.models import Membership, add_member, remove_member from coip.multiresponse import render403, respond_to from django.contrib.auth.models import User -from coip.apps.name.models import Name, lookup +from coip.apps.name.models import Name from django.http import HttpResponseRedirect from django.core.exceptions import ObjectDoesNotExist -from coip.apps.entity.models import Entity from django.contrib.auth.decorators import login_required from coip.apps.membership.forms import MembershipForm -from coip.settings import METADATA -from lxml import etree -from pprint import pprint def show(request,id): membership = get_object_or_404(Membership,pk=id) @@ -27,58 +23,6 @@ def show(request,id): {'text/html': 'apps/membership/membership.html'}, {'membership': membership}) -def import_metadata(): - doc = etree.parse(METADATA) - ns = {'md': 'urn:oasis:names:tc:SAML:2.0:metadata', - 'xml': 'http://www.w3.org/XML/1998/namespace'} - for e in doc.xpath("md:EntityDescriptor",namespaces=ns): - entityId = e.get('entityID') - display = entityId - x = e.xpath("md:OrganizationDisplayName",namespaces=ns) - if x: - display = x[0] - - (entity,created) = Entity.objects.get_or_create(entityId=entityId) - save = created - - if created: - entity.type = Entity.OTHER - - x = e.xpath("md:SPSSODescriptor",namespaces=ns) - if x: - type = Entity.SP - x = e.xpath("md:IDPSSODescriptor",namespaces=ns) - if x: - type = Entity.IDP - - if type != entity.type: - entity.type = type - save = True - - if display != entity.display_name: - entity.display_name = display - save = True - - if save: - entity.save() - - anyuser = lookup("system:anyuser") - - anyentity = lookup("system:anyentity",True) - anyentity.setacl(anyuser, "rl") - - anysp = lookup("system:anysp",True) - anysp.setacl(anyuser, "rl") - - anyidp = lookup("system:anyidp",True) - anyidp.setacl(anyuser, "rl") - - add_member(anyentity,entity) - if entity.type == Entity.SP: - add_member(anysp,entity) - if entity.type == Entity.IDP: - add_member(anyidp,entity) - @login_required def join(request,id,membername=None): name = get_object_or_404(Name,pk=id) @@ -89,13 +33,7 @@ def join(request,id,membername=None): m = Membership(name=name,enabled=True) form = MembershipForm(request.POST,instance=m) if form.is_valid(): - if form.cleaned_data.has_key('user'): - add_member(name,form.cleaned_data['user']) - elif form.cleaned_data.has_key('entity'): - add_member(name,form.cleaned_data['entity']) - else: - raise Exception,"Bad form state - should not happen at all!" - + add_member(name,form.cleaned_data['user']) return HttpResponseRedirect(name.url()) else: return respond_to(request, @@ -103,15 +41,10 @@ def join(request,id,membername=None): {'form': form,'name': name, 'formtitle': 'Add a member to %s' % name.short}) else: if membername: - try: - member = User.objects.get(username=membername) - except ObjectDoesNotExist: - member = Entity.objects.get(entityId=name) - add_member(name, member) + add_member(name, membername) return HttpResponseRedirect(name.url()) else: form = MembershipForm() - import_metadata() return respond_to(request, {'text/html': 'apps/membership/edit.html'}, {'form': form,'name': name, 'formtitle': 'Add a member to %s' % name.short}) @@ -122,7 +55,7 @@ def leave(request,id,membername=None): if membername: try: member = User.objects.get(username=membername) + remove_member(name, member) except ObjectDoesNotExist: - member = Entity.objects.get(entityId=name) - remove_member(name, member) + pass return HttpResponseRedirect(name.url()) diff --git a/coip/apps/name/models.py b/coip/apps/name/models.py index d7da547..519248b 100644 --- a/coip/apps/name/models.py +++ b/coip/apps/name/models.py @@ -34,11 +34,14 @@ class Name(models.Model): short = models.CharField(max_length=64,blank=True) creator = models.ForeignKey(User,blank=True, null=True) display = models.TextField(editable=False) + #icon = models.ImageField(blank=True, null=True) description = models.TextField(blank=True) format = models.SmallIntegerField(default=FMT_URN,choices=((FMT_URN,"URN"),(FMT_URL,"URL"))) timecreated = models.DateTimeField(auto_now_add=True) lastupdated = models.DateTimeField(auto_now=True) + nmembers = -1 + def mode(self): if not self.format: return FMT_URN @@ -203,6 +206,11 @@ class Name(models.Model): def permitted_children(self,user,perm): return filter(lambda s: s.has_permission(user,perm),self.children.all()) + def count_members(self): + if self.nmembers == -1: + self.nmembers = self.memberships.filter(hidden=False).count() + return self.nmembers + def set_display(sender,**kwargs): kwargs['instance'].display = kwargs['instance'].display_str() diff --git a/coip/apps/opensocial/people.py b/coip/apps/opensocial/people.py index 9465c08..9f0a925 100644 --- a/coip/apps/opensocial/people.py +++ b/coip/apps/opensocial/people.py @@ -64,7 +64,7 @@ class GroupResource(OpenSocialResource): def override_urls(self): return [ - url(r"^(?P<resource_name>%s)/(?P<username>[\@\w\d_.-:]+)/(?P<group_name_id>[\d]+)%s?" % (self._meta.resource_name,trailing_slash()), + url(r"^(?P<resource_name>%s)/(?P<username>[\@\w\d_.-:]+)/(?P<name_id>[\d]+)%s?" % (self._meta.resource_name,trailing_slash()), self.wrap_view('list_memberships'), name="api_list_memberships"), url(r"^(?P<resource_name>%s)/(?P<username>[\@\w\d_.-:]+)%s" % (self._meta.resource_name,trailing_slash()), self.wrap_view('list_memberships'), name="api_list_memberships"), diff --git a/coip/apps/userprofile/forms.py b/coip/apps/userprofile/forms.py new file mode 100644 index 0000000..dd42ccf --- /dev/null +++ b/coip/apps/userprofile/forms.py @@ -0,0 +1,30 @@ +''' +Created on Aug 19, 2011 + +@author: leifj +''' + +from form_utils.forms import BetterForm +from django.forms.fields import CharField +from django.forms.widgets import Textarea + + +class AddSSHKeyForm(BetterForm): + sshkey = CharField(label='SSH Key',widget=Textarea(attrs={'cols': 60, 'rows': 6})) + class Meta: + fieldsets = [ + ('key',{'fields':['sshkey'], + 'legend': 'Please provide your SSH key.', + 'description': 'Cut and paste your SSH key into the text field. Note that you should only submit the .pub-file and never the private key.', + 'classes': ['step','submit_step']}) + ] + +class AddCertificateForm(BetterForm): + certificate = CharField(label='PEM X509 Certificate',widget=Textarea(attrs={'cols': 60, 'rows': 6})) + class Meta: + fieldsets = [ + ('key',{'fields':['certificate'], + 'legend': 'Please provide your personal certificate.', + 'description': 'Cut and paste your PEM format X509 Certificate into the text field.', + 'classes': ['step','submit_step']}) + ]
\ No newline at end of file diff --git a/coip/apps/userprofile/models.py b/coip/apps/userprofile/models.py index 6e2364a..315097d 100644 --- a/coip/apps/userprofile/models.py +++ b/coip/apps/userprofile/models.py @@ -7,15 +7,14 @@ from django.db import models from django.contrib.auth.models import User from django.dispatch.dispatcher import receiver from django.db.models.signals import post_save -from coip.apps.name.models import Name, lookup -from coip.apps.membership.models import add_member +from coip.apps.name.models import Name class UserProfile(models.Model): INTERNAL = 0 ENTITY = 1 SSHKEY = 2 - GRIDCERT = 3 + X509 = 3 FEDID = 4 # @@ -24,19 +23,20 @@ class UserProfile(models.Model): # 1 (entity) - username=entity:sha1(entityID), profile.display_name = display or entityID, profile.identifier = ssh key # 2 (sshkey) - username=sshkey:fingerprint, profile.display_name = key alias or "SSH Key with fingerprint ..." # 3 (gridcert) - username=x509:sha1-fingerprint, profile.display_name = dn, profile.identifier = PEM - # 4 (fedid) - username=eppn or equiv (REMOTE_USER),profile.display_name = display or eppn, profile.identifier = eppn, profile.authority = idp + # 4 (fedid) - username=eppn or equiv (REMOTE_USER),profile.display_name = display or eppn, profile.identifier = eppn, profile.idp = idp # - user = models.OneToOneField(User) + user = models.OneToOneField(User,related_name='profile') home = models.ForeignKey(Name,blank=True,null=True) display_name = models.CharField(max_length=255,blank=True,null=True) - type = models.SmallIntegerField(choices=((ENTITY,"Connected Service"), + type = models.SmallIntegerField(default=INTERNAL, + choices=((ENTITY,"Service"), (INTERNAL,"System User"), - (SSHKEY,"SSH Key"), - (GRIDCERT,"eScience Certificate"), + (SSHKEY,"Personal SSH Key"), + (X509,"Personal eScience Certificate"), (FEDID,"User Identity"))) - authority = models.CharField(max_length=255,blank=True,null=True) + idp = models.CharField(max_length=255,blank=True,null=True) identifier = models.CharField(max_length=1023,blank=True,null=True) timecreated = models.DateTimeField(auto_now_add=True) @@ -45,30 +45,7 @@ class UserProfile(models.Model): def __unicode__(self): return "%s [%s] - %s" % (self.identifier,self.user.username,self.display_name) -def import_sshkey(keyfile): - fingerprint = "xxx" - user = User.objects.get_or_create(username="sshkey:%s" % fingerprint) - -def home_name(user,short=None,autocreate=False): - if short == None: - short = user.username - urn = lookup("urn",True) - anyuser = lookup("system:anyuser",True) - urn.setacl(anyuser,'rl') - - home = lookup('user:'+user.username,autocreate=autocreate) - add_member(home,user,hidden=True) - home.setpacl(home, "rwlida") - home.setacl(home,"rwlia") #don't allow users to delete or reset acls on their home, nor invite members - that would be confusing as hell - home.short = short - home.save() - - return home - @receiver(post_save,sender=User) def _create_profile(sender,**kwargs): user = kwargs['instance'] - profile,created = UserProfile.objects.get_or_create(user=user) - if profile.home == None: - profile.home = home_name(user,autocreate=True) - profile.save()
\ No newline at end of file + UserProfile.objects.get_or_create(user=user)
\ No newline at end of file diff --git a/coip/apps/userprofile/tasks.py b/coip/apps/userprofile/tasks.py new file mode 100644 index 0000000..175c8a5 --- /dev/null +++ b/coip/apps/userprofile/tasks.py @@ -0,0 +1,48 @@ +''' +Created on Aug 18, 2011 + +@author: leifj +''' +from coip.settings import METADATA +from lxml import etree +from hashlib import sha1 +from django.contrib.auth.models import User +from coip.apps.name.models import lookup +from coip.apps.userprofile.models import UserProfile +from coip.apps.membership.models import add_member +from celery.decorators import periodic_task +from celery.schedules import crontab + +@periodic_task(run_every=crontab(hour="*", minute="*/3", day_of_week="*")) +def import_metadata(): + doc = etree.parse(METADATA) + ns = {'md': 'urn:oasis:names:tc:SAML:2.0:metadata', + 'xml': 'http://www.w3.org/XML/1998/namespace'} + for e in doc.xpath("md:EntityDescriptor",namespaces=ns): + entityId = e.get('entityID') + print entityId + display = entityId + x = e.xpath("md:OrganizationDisplayName",namespaces=ns) + if x: + display = x[0] + + username = "entity:%s" % sha1(entityId).hexdigest() + (user,created) = User.objects.get_or_create(username=username) + save = created + profile = user.get_profile() + + if created: + anyuser = lookup("system:anyuser") + anyentity = lookup("system:anyentity",True) + anyentity.setacl(anyuser, "rl") + profile.type = UserProfile.ENTITY + profile.home = anyentity + add_member(anyentity, user) + + if display != profile.display_name: + profile.display_name = display + save = True + + if save: + user.save() + profile.save()
\ No newline at end of file diff --git a/coip/apps/userprofile/views.py b/coip/apps/userprofile/views.py index a7b15e8..b1be4c1 100644 --- a/coip/apps/userprofile/views.py +++ b/coip/apps/userprofile/views.py @@ -4,12 +4,93 @@ Created on Jul 6, 2010 @author: leifj ''' from django.contrib.auth.decorators import login_required -from coip.multiresponse import respond_to, json_response -from coip.apps.membership.models import Membership +from coip.multiresponse import respond_to, json_response, render403 +from coip.apps.membership.models import Membership, add_member from django.core.exceptions import ObjectDoesNotExist -from coip.apps.name.models import NameLink +from coip.apps.name.models import NameLink, lookup, Name from django.contrib.auth.models import User from django.shortcuts import get_object_or_404 +from coip.apps.userprofile.models import UserProfile +from django.db.models import Q +from coip.extensions.templatetags.userdisplay import userdisplay +import subprocess +import re +from tempfile import NamedTemporaryFile +from coip.apps.userprofile.forms import AddSSHKeyForm, AddCertificateForm +from django.http import HttpResponseRedirect + +def _add_sshkey(name,keyfile): + p = subprocess.Popen(['ssh-keygen','-l','-f',keyfile.name],stdout=subprocess.PIPE,stderr=subprocess.PIPE) + (out,err) = p.communicate() + code = p.wait() + if code != 0: + raise Exception("Unable to fingerprint ssh key: %d - %s" % (code,err)) + parts = out.split() + fp = re.sub(':','',parts[1]) + + p = subprocess.Popen(['ssh-keygen','-e','-f',keyfile.name],stdout=subprocess.PIPE,stderr=subprocess.PIPE) + (out,err) = p.communicate() + code = p.wait() + if code != 0: + raise Exception("Unable to import ssh key: %d - %s" % (code,err)) + id = out + + username = "sshkey:%s" % fp + user,created = User.objects.get_or_create(username=username) + profile = user.get_profile() + if created: + profile.type = UserProfile.SSHKEY + profile.home = name + profile.display = "SSH Key (%s)" % (fp) + profile.identifier = id + + add_member(profile.home,user) + profile.save() + + +def _add_gridcert(name,keyfile): + p = subprocess.Popen(['openssl','x509','-noout','-fingerprint','-sha1','-in',keyfile.name],stdout=subprocess.PIPE,stderr=subprocess.PIPE) + (out,err) = p.communicate() + code = p.wait() + if code != 0: + raise Exception("Unable to fingerprint X509 certificate: %d - %s" % (code,err)) + parts = out.split('=') + fp = re.sub(':','',parts[1].lower()) + + p = subprocess.Popen(['openssl','x509','-outform','PEM','-in',keyfile.name],stdout=subprocess.PIPE,stderr=subprocess.PIPE) + (out,err) = p.communicate() + code = p.wait() + if code != 0: + raise Exception("Unable to import X509 certificate: %d - %s" % (code,err)) + id = out + + username = "x509:%s" % fp + user,created = User.objects.get_or_create(username=username) + profile = user.get_profile() + if created: + profile.type = UserProfile.X509 + profile.home = name + profile.display = "X509 Certificate (%s)" % (fp) + profile.identifier = id + + add_member(profile.home,user) + profile.save() + +def home_name(user,short=None,autocreate=False): + if short == None: + short = user.username + urn = lookup("urn",True) + anyuser = lookup("system:anyuser",True) + urn.setacl(anyuser,'rl') + + home = lookup('user:'+user.username,autocreate=autocreate) + add_member(home,user,hidden=True) + home.setpacl(home, "rwlida") + home.setacl(home,"rwlia") #don't allow users to delete or reset acls on their home, nor invite members - that would be confusing as hell + home.short = short + home.save() + + return home @login_required def home(request): @@ -19,16 +100,103 @@ def home(request): except ObjectDoesNotExist: pass + user = request.user + profile = user.get_profile() + if profile.home == None: + cn = user.get_full_name() + if not cn: + cn = user.username + profile.home = home_name(user, short=cn, autocreate=True) + names = [(link.src,link.data) for link in NameLink.objects.filter(dst__memberships__user=request.user,type=NameLink.access_control,data__contains='i').all()] return respond_to(request, {'text/html': 'apps/userprofile/home.html'},{'memberships': memberships,'names': names}) @login_required +def add_sshkey(request,id=None): + name = None + if id == None: + name = request.user.get_profile().home + else: + name = get_object_or_404(Name,pk=id) + if name == None: + return render403(request, "Homeless user.") + if not name.has_permission(request.user,'i'): + return render403(request,"You do not have permission to manage aliases here.") + if not name.parent or name.parent.value != 'user': + return render403(request,"This is the wrong place for that.") + + if request.method == 'POST': + form = AddSSHKeyForm(request.POST) + if form.is_valid(): + sshkey = form.cleaned_data['sshkey'] + keyfile = NamedTemporaryFile() + keyfile.write(sshkey) + keyfile.seek(0) + _add_sshkey(name, keyfile) + keyfile.close() + return HttpResponseRedirect("/user/home") + else: + form = AddSSHKeyForm() + + return respond_to(request,{'text/html':'apps/userprofile/sshkey.html'},{'form':form}) + +@login_required +def add_cert(request,id=None): + name = None + if id == None: + name = request.user.get_profile().home + else: + name = get_object_or_404(Name,pk=id) + if name == None: + return render403(request, "Homeless user.") + if not name.has_permission(request.user,'i'): + return render403(request,"You do not have permission to manage aliases here.") + if not name.parent or name.parent.value != 'user': + return render403(request,"This is the wrong place for that.") + + if request.method == 'POST': + form = AddCertificateForm(request.POST) + if form.is_valid(): + certificate = form.cleaned_data['certificate'] + keyfile = NamedTemporaryFile() + keyfile.write(certificate) + keyfile.seek(0) + _add_gridcert(name, keyfile) + keyfile.close() + return HttpResponseRedirect("/user/home") + else: + form = AddCertificateForm() + + return respond_to(request,{'text/html':'apps/userprofile/cert.html'},{'form':form}) + +@login_required +def add_alias(request,id=None): + name = None + if id == None: + name = request.user.get_profile().home + else: + name = get_object_or_404(Name,pk=id) + if name == None: + return render403(request, "Homeless user.") + if not name.has_permission(request.user,'i'): + return render403(request,"You do not have permission to manage aliases here.") + if not name.parent or name.parent.value != 'user': + return render403(request,"This is the wrong place for that.") + + return respond_to(request,{'text/html':'apps/userprofile/addalias.html'}) + +@login_required def search(request): list = [] if request.REQUEST.has_key('term'): term = request.REQUEST['term'] - list = [{'label': user.username,'value': user.id} for user in User.objects.filter(username__contains=term)] + list = [{'label': userdisplay(user),'value': user.id} + for user in User.objects.filter(Q(username__contains=term) | + Q(profile__display_name__contains=term) | + Q(profile__identifier__contains=term) | + Q(first_name__contains=term) | + Q(last_name__contains=term))] return json_response(list) @login_required |