summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coip/apps/auth/views.py10
-rw-r--r--coip/apps/membership/forms.py9
-rw-r--r--coip/apps/membership/models.py27
-rw-r--r--coip/apps/membership/views.py43
-rw-r--r--coip/apps/name/forms.py3
-rw-r--r--coip/apps/name/models.py45
-rw-r--r--coip/apps/name/views.py36
-rw-r--r--coip/apps/userprofile/models.py6
-rw-r--r--coip/apps/userprofile/views.py12
9 files changed, 112 insertions, 79 deletions
diff --git a/coip/apps/auth/views.py b/coip/apps/auth/views.py
index 094e974..1582a5e 100644
--- a/coip/apps/auth/views.py
+++ b/coip/apps/auth/views.py
@@ -8,6 +8,7 @@ from coip.apps.userprofile.models import UserProfile
from django.contrib.auth.models import User
from coip.apps.auth.utils import anonid
from coip.apps.name.models import lookup
+import datetime
def meta(request,attr):
v = request.META.get(attr)
@@ -50,11 +51,10 @@ def accounts_login_federated(request):
if update:
request.user.save()
- profile.save()
-
- #autocreate a few personal namespaces
- lookup('user:'+profile.identifier,True,'system:anyuser#l '+request.user+'#rw')
- lookup(request.user,True,'system:anyuser#l '+request.user+'#rw')
+
+ # Allow auto_now to kick in for the lastupdated field
+ #profile.lastupdated = datetime.datetime.now()
+ profile.save()
next = request.session.get("after_login_redirect", None)
if next is not None:
diff --git a/coip/apps/membership/forms.py b/coip/apps/membership/forms.py
index c74307b..512647f 100644
--- a/coip/apps/membership/forms.py
+++ b/coip/apps/membership/forms.py
@@ -5,13 +5,12 @@ Created on Jun 23, 2010
'''
from django import forms
from coip.apps.membership.models import Membership
-from django.forms.widgets import Textarea
class MembershipForm(forms.ModelForm):
class Meta:
model = Membership
-class InvitationForm(forms.Form):
- email = forms.EmailField()
- expires = forms.DateTimeField()
- message = forms.CharField(widget=Textarea) \ No newline at end of file
+class InvitationForm(forms.ModelForm):
+ class Meta:
+ model = Membership
+ fields = ['email'] \ No newline at end of file
diff --git a/coip/apps/membership/models.py b/coip/apps/membership/models.py
index 935a253..9ff6a89 100644
--- a/coip/apps/membership/models.py
+++ b/coip/apps/membership/models.py
@@ -13,15 +13,13 @@ class Membership(models.Model):
'''
Membership in a namespace/group
'''
- user = models.ForeignKey(User,unique=True,blank=True,related_name='user')
- inviter = models.ForeignKey(User,unique=True,blank=True,related_name='inviter')
+ user = models.ForeignKey(User,blank=True,null=True,related_name='user')
name = models.ForeignKey(Name,related_name='memberships')
- email = models.EmailField(blank=True,null=True)
- nonce = models.CharField(max_length=255,blank=True,null=True)
enabled = models.BooleanField()
+ hidden = models.BooleanField()
timecreated = models.DateTimeField(auto_now_add=True)
lastupdated = models.DateTimeField(auto_now=True)
- expires = models.DateTimeField(blank=True)
+ expires = models.DateTimeField(blank=True,null=True)
def __unicode__(self):
return "%s in %s" % (self.user,self.name)
@@ -34,8 +32,21 @@ class Membership(models.Model):
return "active"
else:
return "inactive";
+
+def add_member(name,user):
+ (m,created) = Membership.objects.get_or_create(user=user,name=name)
+ if created or not m.enabled:
+ m.enabled = True
+ m.save()
+
+def disable_member(name,user):
+ m = Membership.objects.get(name=name,user=user)
+ if m:
+ m.enabled = False
+ m.save()
- def send_email(self):
- pprint("sent email to "+self.to)
- return
+def remove_member(name,user):
+ m = Membership.objects.get(name=name,user=user)
+ if m:
+ m.delete()
diff --git a/coip/apps/membership/views.py b/coip/apps/membership/views.py
index 6a500d9..e479015 100644
--- a/coip/apps/membership/views.py
+++ b/coip/apps/membership/views.py
@@ -3,37 +3,18 @@ Created on Jun 23, 2010
@author: leifj
'''
-from django.contrib.auth.decorators import login_required
+from django.shortcuts import get_object_or_404
from coip.apps.membership.models import Membership
-from coip.apps.membership.forms import InvitationForm
-from django.http import HttpResponseRedirect
-from coip.apps.auth.utils import nonce
-from coip.multiresponse import respond_to
+from coip.multiresponse import render403, respond_to
-#@login_required
-#def memberships(request,name):
-#
-# Membership.objects.get(name)
+def show(request,id):
+ membership = get_object_or_404(Membership,pk=id)
+ name = membership.name
+ if not name.has_permission(request.user,'r'):
+ return render403("You do not have permission to view membership information for %s" % (name))
-
-@login_required
-def invite(request):
- user = request.user
- if request.method == 'POST':
- form = InvitationForm(request.POST)
- if form.is_valid():
- email = form.cleaned_data["email"]
- expires = form.cleaned_data["expires"]
- message = form.cleaned_data["message"]
- membership = Membership(inviter=user,email=email,message=message,expires=expires,nonce=nonce())
- membership.save()
- membership.send_email()
- return HttpResponseRedirect("/membership/id/"+membership.id)
- else:
- form = InvitationForm({});
-
- return respond_to(request,{'text/html': 'apps/invitation/create.html'},{'form': form})
-
-def accept(request,nonce):
- user = request.user
- membership = Membership.objects.get(nonce=nonce) \ No newline at end of file
+ return respond_to({'text/html': 'apps/membership/membership.html'},
+ {'membership': membership,
+ 'render': {'edit': name.has_permission(request.user,'w'),
+ 'delete': name.has_permission(request.user,'d'),
+ 'disable': name.has_permission(request.user,'d')}}) \ No newline at end of file
diff --git a/coip/apps/name/forms.py b/coip/apps/name/forms.py
index 47c7795..a68102e 100644
--- a/coip/apps/name/forms.py
+++ b/coip/apps/name/forms.py
@@ -16,11 +16,14 @@ class AttributeForm(forms.ModelForm):
model = Attribute
class NameEditForm(forms.ModelForm):
+ description = forms.CharField(widget=forms.Textarea(attrs={'cols': 85, 'rows': 10}))
+
class Meta:
model = Name
fields = ['short','description']
class NewNameForm(forms.ModelForm):
+ description = forms.CharField(widget=forms.Textarea(attrs={'cols': 85, 'rows': 10}))
class Meta:
model = Name
fields = ['type','value','short','description']
diff --git a/coip/apps/name/models.py b/coip/apps/name/models.py
index 0011955..e803c0b 100644
--- a/coip/apps/name/models.py
+++ b/coip/apps/name/models.py
@@ -8,6 +8,7 @@ import re
from pprint import pprint
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
+from django.db.models.signals import post_init, pre_save
class Attribute(models.Model):
name = models.CharField(unique=True,max_length=255)
@@ -25,9 +26,9 @@ class Name(models.Model):
type = models.ForeignKey(Attribute, blank=True, null=True,related_name='names')
value = models.CharField(max_length=255)
parent = models.ForeignKey('self', blank=True, null=True,related_name='children')
- acl = models.TextField(blank=True) # fully-qualified-name '#' rights
short = models.CharField(max_length=64,blank=True)
creator = models.ForeignKey(User,blank=True, null=True)
+ display = models.TextField(editable=False)
description = models.TextField(blank=True)
timecreated = models.DateTimeField(auto_now_add=True)
lastupdated = models.DateTimeField(auto_now=True)
@@ -45,6 +46,9 @@ class Name(models.Model):
return self.value
def __unicode__(self):
+ return self.display
+
+ def display_str(self):
n = self
str = ""
while n:
@@ -68,8 +72,10 @@ class Name(models.Model):
c.remove(recursive)
self.delete()
- def copy_acl(self):
- return self.acl
+ def copyacl(self,name):
+ for ace in name.lsacl():
+ self.setacl(ace.dst,ace.data)
+
def link(self,dst,type,data):
if not self.has_link(dst,NameLink.part_of,data):
@@ -87,10 +93,14 @@ class Name(models.Model):
return NameLink.objects.filter(src=self,dst=dst,type=type,data=data).count() > 0
def setacl(self,name,perm):
- link = NameLink.objects.get_or_create(src=self,dst=name,type=NameLink.access_control)
+ (link,b) = NameLink.objects.get_or_create(src=self,dst=name,type=NameLink.access_control)
save = False
+ if not link.data:
+ link.data = ''
+ save = True
for p in perm:
- if not link.data.find(p):
+ pprint(p)
+ if link.data.find(p) == -1:
link.data = link.data+p
save = True
if save:
@@ -122,6 +132,7 @@ class Name(models.Model):
# TODO: reverse order of test for production system - will spead-up superuser-test and it is cheap
#pprint(NameLink.objects.filter(src=self,type=NameLink.access_control,data=perm,dst__memberships__user=user))
# user is superuser or acl is on implicit group or user is member of acl group
+ anyuser = lookup("system:anyuser",True)
if NameLink.objects.filter(src=self,dst=anyuser,type=NameLink.access_control,data__contains=perm).count() > 0:
return True
if NameLink.objects.filter(src=self,type=NameLink.access_control,data__contains=perm,dst__memberships__user=user).count() > 0:
@@ -135,6 +146,11 @@ class Name(models.Model):
def permitted_children(self,user,perm):
return filter(lambda s: s.has_permission(user,perm),self.children.all())
+def set_display(sender,**kwargs):
+ kwargs['instance'].display = kwargs['instance'].display_str()
+
+pre_save.connect(set_display,sender=Name)
+
class NameLink(models.Model):
src = models.ForeignKey(Name,related_name='sources')
dst = models.ForeignKey(Name,related_name='destinations')
@@ -179,18 +195,22 @@ def traverse(name,callable,user,depth,includeroot=False):
# TODO - remove system user dependency
-def walkto(root,nameparts,autocreate=False,autoacl='l'):
+def walkto(root,nameparts,autocreate=False):
name = None
for n in nameparts:
(a,eq,v) = n.partition('=')
+ pprint("walkto %s -> %s" % (root,n))
if v:
attribute = Attribute.objects.get(name=a)
try:
name = Name.objects.get(parent=root,type=attribute.id,value=v)
except ObjectDoesNotExist,e:
if autocreate:
- name = Name(parent=root,creator=None,type=attribute.id,value=v,acl=autoacl)
+ name = Name(parent=root,creator=None,type=attribute.id,value=v)
name.save()
+ if root:
+ name.copyacl(root)
+
else:
raise e
else:
@@ -198,18 +218,17 @@ def walkto(root,nameparts,autocreate=False,autoacl='l'):
name = Name.objects.get(parent=root,type=None,value=a)
except ObjectDoesNotExist,e:
if autocreate:
- name = Name(parent=root,creator=None,type=None,value=a,acl=autoacl)
+ name = Name(parent=root,creator=None,type=None,value=a)
name.save()
+ if root:
+ name.copyacl(root)
else:
raise e
root = name
return name
-def lookup(name,autocreate=False,autoacl='l'):
- return walkto(None,nameparts=re.compile('[;:]').split(name),autocreate=autocreate,autoacl=autoacl)
+def lookup(name,autocreate=False):
+ return walkto(None,nameparts=re.compile('[;:]').split(name),autocreate=autocreate)
def attribute(a):
Attribute.objects.get_or_create(name=a)
-
-#sysuser = User.objects.get_or_create(username='system',first_name='COIP System',last_name='User',password="(not used)")
-anyuser = lookup("system:anyuser",True) \ No newline at end of file
diff --git a/coip/apps/name/views.py b/coip/apps/name/views.py
index a59190b..a8c17de 100644
--- a/coip/apps/name/views.py
+++ b/coip/apps/name/views.py
@@ -6,9 +6,9 @@ Created on Jul 6, 2010
from coip.apps.name.models import Name, lookup, traverse
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponseNotFound, HttpResponseForbidden,\
- HttpResponseRedirect
+ HttpResponseRedirect, Http404
from django.contrib.auth.decorators import login_required
-from coip.multiresponse import respond_to, json_response
+from coip.multiresponse import respond_to, json_response, render403
from pprint import pprint
from coip.apps.name.forms import NameEditForm, NewNameForm, NameDeleteForm
from twisted.python.reflect import ObjectNotFound
@@ -21,7 +21,7 @@ def delete(request,id):
return HttpResponseNotFound()
if not name.has_permission(request.user,'d'):
- return HttpResponseForbidden()
+ return render403()
if request.method == 'POST':
form = NameDeleteForm(request.POST)
@@ -63,10 +63,11 @@ def add(request,id):
return HttpResponseForbidden('You are not allowed to create names')
if request.method == 'POST':
- name = Name(parent=parent,creator=request.user,acl=parent.copy_acl())
+ name = Name(parent=parent,creator=request.user)
form = NewNameForm(request.POST,instance=name)
if form.is_valid():
- form.save()
+ name = form.save()
+ name.copyacl(name.parent)
return HttpResponseRedirect("/name/id/%d" % name.id)
else:
form = NewNameForm()
@@ -101,18 +102,27 @@ def show_root(request):
def show(request,name):
if not name:
- return HttpResponseNotFound()
+ raise Http404()
if name.has_permission(request.user,'r'):
+ memberships = None
+ invitations = None
+ if name.has_permission(request.user,'l'):
+ memberships = name.memberships
+ invitations = name.invitations
return respond_to(request,
{'text/html': 'apps/name/name.html'},
- {'name': name,
- 'memberships': name.memberships,
- 'delete': name.has_permission(request.user,'d'),
- 'insert': name.has_permission(request.user,'i'),
- 'edit': name.has_permission(request.user,'w')})
+ {'name': name,
+ 'memberships':memberships,
+ 'invitations':invitations,
+ 'render': {'delete': name.has_permission(request.user,'d'),
+ 'insert': name.has_permission(request.user,'i'),
+ 'edit': name.has_permission(request.user,'w'),
+ 'invite': name.has_permission(request.user,'i'),
+ 'up': name.parent and name.parent.has_permission(request.user,'r')}
+ })
else:
- return HttpResponseForbidden()
+ return render403()
@login_required
def show_by_name(request,n=None):
@@ -121,7 +131,7 @@ def show_by_name(request,n=None):
try:
return show(request,lookup(n))
except ObjectDoesNotExist:
- return HttpResponseNotFound()
+ return HttpResponseNotFound()
@login_required
def show_by_id(request,id=None):
diff --git a/coip/apps/userprofile/models.py b/coip/apps/userprofile/models.py
index 2387e36..76473b1 100644
--- a/coip/apps/userprofile/models.py
+++ b/coip/apps/userprofile/models.py
@@ -17,6 +17,10 @@ class UserProfile(models.Model):
def __unicode__(self):
return "%s [%s] - %s" % (self.identifier,self.user.username,self.display_name)
+
+
+def last_used_profile(user):
+ return UserProfile.objects.filter(user=user).order_by('lastupdated')[0]
class PKey(models.Model):
user_profile = models.ForeignKey(UserProfile,related_name='keys')
@@ -26,5 +30,3 @@ class PKey(models.Model):
def __unicode__(self):
return "A merge-key for "+self.user_profile
-
- \ No newline at end of file
diff --git a/coip/apps/userprofile/views.py b/coip/apps/userprofile/views.py
index 2ea4e2a..282c572 100644
--- a/coip/apps/userprofile/views.py
+++ b/coip/apps/userprofile/views.py
@@ -7,12 +7,12 @@ from django.contrib.auth.decorators import login_required
from coip.apps.userprofile.models import PKey
from django.http import HttpResponseRedirect
from coip.multiresponse import respond_to
-from coip.apps.membership.models import Membership
+from coip.apps.membership.models import Membership, add_member
from coip.apps.userprofile.utils import user_profile
from django.core.exceptions import ObjectDoesNotExist
from pprint import pprint
from coip.apps.auth.utils import nonce
-from coip.apps.name.models import Name, NameLink
+from coip.apps.name.models import Name, NameLink, lookup
@login_required
def merge(request,pkey=None):
@@ -39,6 +39,14 @@ def home(request):
except ObjectDoesNotExist:
pass
+ anyuser = lookup("system:anyuser",True)
+ profile = user_profile(request)
+ home = lookup('user:'+request.user.username,autocreate=True)
+ home.short = "Home of %s (%s)" % (profile.display_name,profile.identifier)
+ home.save()
+ add_member(home,profile.user)
+ home.setacl(home,"rliw")
+
names = [(link.src,link.data) for link in NameLink.objects.filter(dst__memberships__user=request.user,type=NameLink.access_control).all()]
return respond_to(request, {'text/html': 'apps/userprofile/home.html'},{'memberships': memberships,'names': names})