summaryrefslogtreecommitdiff
path: root/coip/apps/userprofile
diff options
context:
space:
mode:
authorLeif Johansson <leifj@sunet.se>2011-09-20 11:01:05 +0200
committerLeif Johansson <leifj@sunet.se>2011-09-20 11:01:05 +0200
commitbc0b2364b1a22ecc9662ddfce1a4bd314f38f79b (patch)
treef2b2446f44cc276e12a7e1ea0749822f98464893 /coip/apps/userprofile
parentcd364fba4c45f80cfd326f786c3d4901b2d464c2 (diff)
removed entity model, celery
Diffstat (limited to 'coip/apps/userprofile')
-rw-r--r--coip/apps/userprofile/forms.py30
-rw-r--r--coip/apps/userprofile/models.py43
-rw-r--r--coip/apps/userprofile/tasks.py48
-rw-r--r--coip/apps/userprofile/views.py176
4 files changed, 260 insertions, 37 deletions
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