summaryrefslogtreecommitdiff
path: root/src/meetingtools/apps
diff options
context:
space:
mode:
authorLeif Johansson <leifj@sunet.se>2012-10-04 15:39:08 +0200
committerLeif Johansson <leifj@sunet.se>2012-10-04 15:39:08 +0200
commit2bdad0ae7a3a6e4ec5116becd39910388b679ed2 (patch)
tree5afdfba0a93c1af50d53bdc245d57cc4053e109a /src/meetingtools/apps
parent873e7823970352d591deee5f67f47c5436ee0e84 (diff)
restructure
Diffstat (limited to 'src/meetingtools/apps')
-rw-r--r--src/meetingtools/apps/__init__.py0
-rw-r--r--src/meetingtools/apps/auth/__init__.py79
-rw-r--r--src/meetingtools/apps/auth/utils.py19
-rw-r--r--src/meetingtools/apps/auth/views.py169
-rw-r--r--src/meetingtools/apps/cluster/__init__.py0
-rw-r--r--src/meetingtools/apps/cluster/admin.py10
-rw-r--r--src/meetingtools/apps/cluster/migrations/0001_initial.py45
-rw-r--r--src/meetingtools/apps/cluster/migrations/__init__.py0
-rw-r--r--src/meetingtools/apps/cluster/models.py35
-rw-r--r--src/meetingtools/apps/room/__init__.py0
-rw-r--r--src/meetingtools/apps/room/admin.py10
-rw-r--r--src/meetingtools/apps/room/feeds.py118
-rw-r--r--src/meetingtools/apps/room/forms.py82
-rw-r--r--src/meetingtools/apps/room/management/__init__.py1
-rw-r--r--src/meetingtools/apps/room/management/commands/__init__.py1
-rw-r--r--src/meetingtools/apps/room/management/commands/import_rooms.py11
-rw-r--r--src/meetingtools/apps/room/migrations/0001_initial.py120
-rw-r--r--src/meetingtools/apps/room/migrations/0002_auto__add_field_room_deleted_sco_id.py91
-rw-r--r--src/meetingtools/apps/room/migrations/__init__.py0
-rw-r--r--src/meetingtools/apps/room/models.py142
-rw-r--r--src/meetingtools/apps/room/tasks.py250
-rw-r--r--src/meetingtools/apps/room/views.py548
-rw-r--r--src/meetingtools/apps/stats/__init__.py0
-rw-r--r--src/meetingtools/apps/stats/forms.py11
-rw-r--r--src/meetingtools/apps/stats/views.py273
-rw-r--r--src/meetingtools/apps/userprofile/__init__.py0
-rw-r--r--src/meetingtools/apps/userprofile/admin.py4
-rw-r--r--src/meetingtools/apps/userprofile/models.py21
28 files changed, 0 insertions, 2040 deletions
diff --git a/src/meetingtools/apps/__init__.py b/src/meetingtools/apps/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/auth/__init__.py b/src/meetingtools/apps/auth/__init__.py
deleted file mode 100644
index e69cc29..0000000
--- a/src/meetingtools/apps/auth/__init__.py
+++ /dev/null
@@ -1,79 +0,0 @@
-__author__ = 'leifj'
-
-from django.conf import settings
-from saml2.config import SPConfig
-import copy
-from saml2 import BINDING_HTTP_POST, BINDING_HTTP_REDIRECT
-
-import logging
-logging.basicConfig()
-logger = logging.getLogger("djangosaml2")
-logger.setLevel(logging.DEBUG)
-
-def asgard_sp_config(request=None):
- host = "localhost"
- if request is not None:
- host = request.get_host().replace(":","-")
- x= {
- # your entity id, usually your subdomain plus the url to the metadata view
- 'entityid': 'https://%s/saml2/sp/metadata' % host,
- # directory with attribute mapping
- "attribute_map_dir" : "%s/saml2/attributemaps" % settings.BASE_DIR,
- # this block states what services we provide
- 'service': {
- # we are just a lonely SP
- 'sp' : {
- 'name': 'meetingtools',
- 'endpoints': {
- # url and binding to the assertion consumer service view
- # do not change the binding osettingsr service name
- 'assertion_consumer_service': [
- ('https://%s/saml2/sp/acs/' % host,
- BINDING_HTTP_POST),
- ],
- # url and binding to the single logout service view
- # do not change the binding or service name
- 'single_logout_service': [
- ('https://%s/saml2/sp/ls/' % host,
- BINDING_HTTP_REDIRECT),
- ],
- },
- # attributes that this project need to identify a user
- 'required_attributes': ['eduPersonPrincipalName','displayName','eduPersonScopedAffiliation'],
- }
- },
-
- # where the remote metadata is stored
- #'metadata': { 'remote': [{'url':'http://md.swamid.se/md/swamid-idp.xml',
- # 'cert':'%s/saml2/credentials/md-signer.crt' % settings.BASE_DIR}] },
- 'metadata': {'local': [settings.SAML_METADATA_FILE]},
-
- # set to 1 to output debugging information
- 'debug': 1,
-
- # certificate
- "key_file" : "%s/%s.key" % (settings.SSL_KEY_DIR,host),
- "cert_file" : "%s/%s.crt" % (settings.SSL_CRT_DIR,host),
- # own metadata settings
- 'contact_person': [
- {'given_name': 'Leif',
- 'sur_name': 'Johansson',
- 'company': 'NORDUnet',
- 'email_address': 'leifj@nordu.net',
- 'contact_type': 'technical'},
- {'given_name': 'Johan',
- 'sur_name': 'Berggren',
- 'company': 'NORDUnet',
- 'email_address': 'jbn@nordu.net',
- 'contact_type': 'technical'},
- ],
- # you can set multilanguage information here
- 'organization': {
- 'name': [('NORDUNet', 'en')],
- 'display_name': [('NORDUnet A/S', 'en')],
- 'url': [('http://www.nordu.net', 'en')],
- }
- }
- c = SPConfig()
- c.load(copy.deepcopy(x))
- return c
diff --git a/src/meetingtools/apps/auth/utils.py b/src/meetingtools/apps/auth/utils.py
deleted file mode 100644
index 1a0174c..0000000
--- a/src/meetingtools/apps/auth/utils.py
+++ /dev/null
@@ -1,19 +0,0 @@
-'''
-Created on Jul 7, 2010
-
-@author: leifj
-'''
-from uuid import uuid4
-
-def nonce():
- return uuid4().hex
-
-def anonid():
- return uuid4().urn
-
-def groups(request):
- groups = []
- if request.user.is_authenticated():
- groups = request.user.groups
-
- return groups \ No newline at end of file
diff --git a/src/meetingtools/apps/auth/views.py b/src/meetingtools/apps/auth/views.py
deleted file mode 100644
index ee23df3..0000000
--- a/src/meetingtools/apps/auth/views.py
+++ /dev/null
@@ -1,169 +0,0 @@
-'''
-Created on Jul 5, 2010
-
-@author: leifj
-'''
-from django.http import HttpResponseRedirect
-from django.contrib.auth.models import User, Group
-import datetime
-from django.views.decorators.cache import never_cache
-import logging
-from meetingtools.apps.userprofile.models import UserProfile
-from meetingtools.multiresponse import redirect_to, make_response_dict
-from meetingtools.ac import ac_api_client
-from django.shortcuts import render_to_response
-from django.contrib import auth
-from django_co_connector.models import co_import_from_request, add_member,remove_member
-from meetingtools.apps.cluster.models import acc_for_user
-from django.conf import settings
-
-def meta(request,attr):
- v = request.META.get(attr)
- if not v:
- return None
- values = filter(lambda x: x != "(null)",v.split(";"))
- return values;
-
-def meta1(request,attr):
- v = meta(request,attr)
- if v:
- return str(v[0]).decode('utf-8')
- else:
- return None
-
-def _localpart(a):
- if hasattr(a,'name'):
- a = a.name
- if '@' in a:
- (lp,dp) = a.split('@')
- a = lp
- return a
-
-def _is_member_or_employee_old(affiliations):
- lpa = map(_localpart,affiliations)
- return 'student' in lpa or 'staff' in lpa or ('member' in lpa and not 'student' in lpa)
-
-def _is_member_or_employee(user):
- lpa = map(_localpart,user.groups.all())
- return 'student' in lpa or 'staff' in lpa or ('member' in lpa and not 'student' in lpa)
-
-@never_cache
-def logout(request):
- auth.logout(request)
- return HttpResponseRedirect('/Shibboleth.sso/Logout')
-
-@never_cache
-def login(request):
- return render_to_response('apps/auth/login.html',make_response_dict(request,{'next': request.REQUEST.get("next")}));
-
-def join_group(group,**kwargs):
- user = kwargs['user']
- acc = acc_for_user(user)
- with ac_api_client(acc) as api:
- principal = api.find_principal("login", user.username, "user")
- if principal:
- gp = api.find_group(group.name)
- if gp:
- api.add_member(principal.get('principal-id'),gp.get('principal-id'))
-
-def leave_group(group,**kwargs):
- user = kwargs['user']
- acc = acc_for_user(user)
- with ac_api_client(acc) as api:
- principal = api.find_principal("login", user.username, "user")
- if principal:
- gp = api.find_group(group.name)
- if gp:
- api.remove_member(principal.get('principal-id'),gp.get('principal-id'))
-
-add_member.connect(join_group,sender=Group)
-remove_member.connect(leave_group,sender=Group)
-
-def accounts_login_federated(request):
- if request.user.is_authenticated():
- profile,created = UserProfile.objects.get_or_create(user=request.user)
- if created:
- profile.identifier = request.user.username
- profile.user = request.user
- profile.save()
-
- update = False
- fn = meta1(request,'givenName')
- ln = meta1(request,'sn')
- cn = meta1(request,'cn')
- if not cn:
- cn = meta1(request,'displayName')
- logging.debug("cn=%s" % cn)
- if not cn and fn and ln:
- cn = "%s %s" % (fn,ln)
- if not cn:
- cn = profile.identifier
-
- mail = meta1(request,'mail')
-
- idp = meta1(request,'Shib-Identity-Provider')
-
- for attrib_name, meta_value in (('display_name',cn),('email',mail),('idp',idp)):
- attrib_value = getattr(profile, attrib_name)
- if meta_value and not attrib_value:
- setattr(profile,attrib_name,meta_value)
- update = True
-
- if request.user.password == "":
- request.user.password = "(not used for federated logins)"
- update = True
-
- if update:
- request.user.save()
-
- # 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 not next and request.GET.has_key('next'):
- next = request.GET['next']
- else:
- next = settings.DEFAULT_URL
-
- acc = acc_for_user(request.user)
- with ac_api_client(request) as api:
- # make sure the principal is created before shooting off
- principal = api.find_or_create_principal("login", request.user.username, "user",
- {'type': "user",
- 'has-children': "0",
- 'first-name':fn,
- 'last-name':ln,
- 'email':mail,
- 'send-email': 0,
- 'login':request.user.username,
- 'ext-login':request.user.username})
-
-
-
- co_import_from_request(request)
-
- member_or_employee = _is_member_or_employee(request.user)
- for gn in ('live-admins','seminar-admins'):
- group = api.find_builtin(gn)
- if group:
- api.add_remove_member(principal.get('principal-id'),group.get('principal-id'),member_or_employee)
-
- #(lp,domain) = uid.split('@')
- #for a in ('student','employee','member'):
- # affiliation = "%s@%s" % (a,domain)
- # group = connect_api.find_or_create_principal('name',affiliation,'group',{'type': 'group','has-children':'1','name': affiliation})
- # member = affiliation in affiliations
- # connect_api.add_remove_member(principal.get('principal-id'),group.get('principal-id'),member)
-
- #for e in epe:
- # group = connect_api.find_or_create_principal('name',e,'group',{'type': 'group','has-children':'1','name': e})
- # if group:
- # connect_api.add_remove_member(principal.get('principal-id'),group.get('principal-id'),True)
-
- if next is not None:
- return redirect_to(next)
- else:
- pass
-
- return redirect_to(settings.LOGIN_URL)
diff --git a/src/meetingtools/apps/cluster/__init__.py b/src/meetingtools/apps/cluster/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/cluster/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/cluster/admin.py b/src/meetingtools/apps/cluster/admin.py
deleted file mode 100644
index 3fc9eea..0000000
--- a/src/meetingtools/apps/cluster/admin.py
+++ /dev/null
@@ -1,10 +0,0 @@
-'''
-Created on Jan 31, 2011
-
-@author: leifj
-'''
-
-from django.contrib import admin
-from meetingtools.apps.cluster.models import ACCluster
-
-admin.site.register(ACCluster) \ No newline at end of file
diff --git a/src/meetingtools/apps/cluster/migrations/0001_initial.py b/src/meetingtools/apps/cluster/migrations/0001_initial.py
deleted file mode 100644
index f20f743..0000000
--- a/src/meetingtools/apps/cluster/migrations/0001_initial.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Adding model 'ACCluster'
- db.create_table('cluster_accluster', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('api_url', self.gf('django.db.models.fields.URLField')(max_length=200)),
- ('url', self.gf('django.db.models.fields.URLField')(max_length=200)),
- ('user', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('password', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=128, blank=True)),
- ('default_template_sco_id', self.gf('django.db.models.fields.IntegerField')(unique=True, blank=True)),
- ('domain_match', self.gf('django.db.models.fields.TextField')()),
- ))
- db.send_create_signal('cluster', ['ACCluster'])
-
-
- def backwards(self, orm):
-
- # Deleting model 'ACCluster'
- db.delete_table('cluster_accluster')
-
-
- models = {
- 'cluster.accluster': {
- 'Meta': {'object_name': 'ACCluster'},
- 'api_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'default_template_sco_id': ('django.db.models.fields.IntegerField', [], {'unique': 'True', 'blank': 'True'}),
- 'domain_match': ('django.db.models.fields.TextField', [], {}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'user': ('django.db.models.fields.CharField', [], {'max_length': '128'})
- }
- }
-
- complete_apps = ['cluster']
diff --git a/src/meetingtools/apps/cluster/migrations/__init__.py b/src/meetingtools/apps/cluster/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/cluster/migrations/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/cluster/models.py b/src/meetingtools/apps/cluster/models.py
deleted file mode 100644
index 3c65d57..0000000
--- a/src/meetingtools/apps/cluster/models.py
+++ /dev/null
@@ -1,35 +0,0 @@
-'''
-Created on Feb 3, 2011
-
-@author: leifj
-'''
-
-from django.db import models
-from django.db.models.fields import CharField, URLField, TextField, IntegerField
-import re
-
-class ACCluster(models.Model):
- api_url = URLField()
- url = URLField()
- user = CharField(max_length=128)
- password = CharField(max_length=128)
- name = CharField(max_length=128,blank=True,unique=True)
- default_template_sco_id = IntegerField(blank=True,unique=True)
- domain_match = TextField()
-
- def __unicode__(self):
- return self.url
-
- def make_url(self,path=""):
- return "%s%s" % (self.url,path)
-
-def acc_for_user(user):
- (local,domain) = user.username.split('@')
- if not domain:
- #raise Exception,"Improperly formatted user: %s" % user.username
- domain = "nordu.net" # testing with local accts only
- for acc in ACCluster.objects.all():
- for regex in acc.domain_match.split():
- if re.match(regex.strip(),domain):
- return acc
- raise Exception,"I don't know which cluster you belong to... (%s)" % user.username
diff --git a/src/meetingtools/apps/room/__init__.py b/src/meetingtools/apps/room/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/room/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/room/admin.py b/src/meetingtools/apps/room/admin.py
deleted file mode 100644
index 13d80a8..0000000
--- a/src/meetingtools/apps/room/admin.py
+++ /dev/null
@@ -1,10 +0,0 @@
-'''
-Created on Jan 31, 2011
-
-@author: leifj
-'''
-
-from django.contrib import admin
-from meetingtools.apps.room.models import Room
-
-admin.site.register(Room) \ No newline at end of file
diff --git a/src/meetingtools/apps/room/feeds.py b/src/meetingtools/apps/room/feeds.py
deleted file mode 100644
index a72caaa..0000000
--- a/src/meetingtools/apps/room/feeds.py
+++ /dev/null
@@ -1,118 +0,0 @@
-'''
-Created on May 13, 2011
-
-@author: leifj
-'''
-
-from django.contrib.syndication.views import Feed
-from meetingtools.apps.room.models import Room
-from tagging.models import TaggedItem
-from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed
-from meetingtools.apps.room.views import room_recordings
-from django.shortcuts import get_object_or_404
-
-class TagsWrapper(object):
-
- def __init__(self,tn):
- self.tags = tn.split('+')
- self.rooms = TaggedItem.objects.get_by_model(Room, tn.split('+'))
-
- def title(self):
- return "Rooms tagged with %s" % " and ".join(self.tags)
-
- def description(self):
- return self.title()
-
- def link(self,ext):
- return "/room/+%s.%s" % ("+".join(self.tags),ext)
-
-class MeetingToolsFeed(Feed):
-
- item_author_name = 'SUNET e-meeting tools'
-
- def ext(self):
- if self.feed_type == Atom1Feed:
- return "atom"
-
- if self.feed_type == Rss201rev2Feed:
- return "rss"
-
- return "rss"
-
-
-class RoomTagFeed(MeetingToolsFeed):
-
- def get_object(self,request,tn):
- return TagsWrapper(tn)
-
- def title(self,t):
- return t.title()
-
- def link(self,t):
- return t.link(self.ext())
-
- def description(self,t):
- return t.description()
-
- def items(self,t):
- return t.rooms
-
- def item_title(self,room):
- return room.name
-
- def item_description(self,room):
- return room.description
-
- def item_link(self,room):
- return room.go_url()
-
- def item_guid(self,room):
- return room.permalink()
-
- def item_pubdate(self,room):
- return room.lastupdated
-
-
-class RoomAtomTagFeed(RoomTagFeed):
- feed_type = Atom1Feed
-
-class RoomRSSTagField(RoomTagFeed):
- feed_type = Rss201rev2Feed
-
-class RecordingsWrapper(object):
- def __init__(self,room,request):
- self.room = room
- self.items = room_recordings(request, room)
-
-class RecordingFeed(MeetingToolsFeed):
-
- def get_object(self,request,rid):
- room = get_object_or_404(Room,pk=rid)
- return RecordingsWrapper(room,request)
-
- def title(self,recordings):
- return "Recordings in room '%s'" % recordings.room.name
-
- def link(self,recordings):
- return recordings.room.recordings_url()
-
- def items(self,recordings):
- return recordings.items
-
- def item_title(self,recording):
- return recording['name']
-
- def item_description(self,recording):
- return recording['description']
-
- def item_link(self,recording):
- return recording['url']
-
- def item_pubdate(self,recording):
- return recording['date_created']
-
-class AtomRecordingFeed(RecordingFeed):
- feed_type = Atom1Feed
-
-class RSSRecordingField(RecordingFeed):
- feed_type = Rss201rev2Feed \ No newline at end of file
diff --git a/src/meetingtools/apps/room/forms.py b/src/meetingtools/apps/room/forms.py
deleted file mode 100644
index 62b515b..0000000
--- a/src/meetingtools/apps/room/forms.py
+++ /dev/null
@@ -1,82 +0,0 @@
-'''
-Created on Feb 1, 2011
-
-@author: leifj
-'''
-
-from meetingtools.apps.room.models import Room
-from django.forms.widgets import Select, TextInput, RadioSelect, Textarea
-from django.forms.fields import BooleanField, ChoiceField, CharField
-from django.forms.forms import Form
-from form_utils.forms import BetterModelForm
-from django.utils.safestring import mark_safe
-from django.forms.models import ModelForm
-
-PUBLIC = 0
-PROTECTED = 1
-PRIVATE = 2
-
-class PrefixTextInput(TextInput):
- def __init__(self, attrs=None, prefix=None):
- super(PrefixTextInput, self).__init__(attrs)
- self.prefix = prefix
-
- def render(self, name, value, attrs=None):
- return mark_safe("<div class=\"input-prepend\"><span class=\"add-on\">"+self.prefix+"</span>"+
- super(PrefixTextInput, self).render(name, value, attrs)+"</span></div>")
-
-class ModifyRoomForm(ModelForm):
- class Meta:
- model = Room
- fields = ['name','description','source_sco_id','self_cleaning','allow_host']
- widgets = {'source_sco_id': Select(),
- 'description': Textarea(attrs={'rows': 4, 'cols': 50}),
- 'name': TextInput(attrs={'size': '40'})}
-
-
-class CreateRoomForm(BetterModelForm):
-
- access = ChoiceField(choices=(('public','Public'),('private','Private')))
-
- class Meta:
- model = Room
- fields = ['name','description','urlpath','access','self_cleaning','allow_host']
- fieldsets = [('name',{'fields': ['name'],
- 'classes': ['step'],
- 'legend': 'Step 1: Room name',
- 'description': 'The room name should be short and descriptive.'
- }),
- ('description',{'fields': ['description'],
- 'classes': ['step'],
- 'legend': 'Step 2: Room description',
- 'description': 'Please provide a short summary of this room.'
- }),
- ('properties',{'fields': ['self_cleaning','allow_host','urlpath','access'],
- 'classes': ['step'],
- 'legend': 'Step 3: Room properties',
- 'description': '''
- <p>These are basic properties for your room. If you set your room to cleaned up after
- use it will be reset every time the last participant leaves the room. If you create a public room it
- will be open to anyone who has the room URL. If you create a private room then guests will have to be
- approved by an active meeting host before being able to join the room.</p>
-
- <div class="ui-widget">
- <div class="ui-state-highlight ui-corner-all" style="margin-top: 20px; padding: 0 .7em;">
- <p><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>
- <strong>Warning</strong> Setting a room to be cleaned up when empty will cause all existing content
- associated with the to be destroyed each time the room is reset.</p>
- </div>
- </div>
- '''
- }),
- ]
- widgets = {'access': RadioSelect(),
- 'urlpath': PrefixTextInput(attrs={'size': '10'}),
- 'description': Textarea(attrs={'rows': 4, 'cols': 50}),
- 'name': TextInput(attrs={'size': '40'})}
-
-class DeleteRoomForm(Form):
- confirm = BooleanField(label="Confirm remove room")
-
-class TagRoomForm(Form):
- tag = CharField(max_length=256) \ No newline at end of file
diff --git a/src/meetingtools/apps/room/management/__init__.py b/src/meetingtools/apps/room/management/__init__.py
deleted file mode 100644
index 3929ed7..0000000
--- a/src/meetingtools/apps/room/management/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__author__ = 'leifj'
diff --git a/src/meetingtools/apps/room/management/commands/__init__.py b/src/meetingtools/apps/room/management/commands/__init__.py
deleted file mode 100644
index 3929ed7..0000000
--- a/src/meetingtools/apps/room/management/commands/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__author__ = 'leifj'
diff --git a/src/meetingtools/apps/room/management/commands/import_rooms.py b/src/meetingtools/apps/room/management/commands/import_rooms.py
deleted file mode 100644
index 7944be8..0000000
--- a/src/meetingtools/apps/room/management/commands/import_rooms.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from django.core.management import BaseCommand
-from meetingtools.apps.cluster.models import ACCluster
-from meetingtools.apps.room.tasks import import_acc
-
-__author__ = 'leifj'
-
-class Command(BaseCommand):
-
- def handle(self, *args, **options):
- for acc in ACCluster.objects.all():
- import_acc(acc,since=0) \ No newline at end of file
diff --git a/src/meetingtools/apps/room/migrations/0001_initial.py b/src/meetingtools/apps/room/migrations/0001_initial.py
deleted file mode 100644
index 4cb1bef..0000000
--- a/src/meetingtools/apps/room/migrations/0001_initial.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Adding model 'Room'
- db.create_table('room_room', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('creator', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('urlpath', self.gf('django.db.models.fields.CharField')(unique=True, max_length=128)),
- ('acc', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['cluster.ACCluster'])),
- ('self_cleaning', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('allow_host', self.gf('django.db.models.fields.BooleanField')(default=True)),
- ('sco_id', self.gf('django.db.models.fields.IntegerField')()),
- ('source_sco_id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
- ('folder_sco_id', self.gf('django.db.models.fields.IntegerField')()),
- ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
- ('user_count', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
- ('host_count', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
- ('timecreated', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
- ('lastupdated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
- ('lastvisited', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
- ))
- db.send_create_signal('room', ['Room'])
-
- # Adding unique constraint on 'Room', fields ['acc', 'sco_id']
- db.create_unique('room_room', ['acc_id', 'sco_id'])
-
- # Adding unique constraint on 'Room', fields ['name', 'folder_sco_id']
- db.create_unique('room_room', ['name', 'folder_sco_id'])
-
-
- def backwards(self, orm):
-
- # Removing unique constraint on 'Room', fields ['name', 'folder_sco_id']
- db.delete_unique('room_room', ['name', 'folder_sco_id'])
-
- # Removing unique constraint on 'Room', fields ['acc', 'sco_id']
- db.delete_unique('room_room', ['acc_id', 'sco_id'])
-
- # Deleting model 'Room'
- db.delete_table('room_room')
-
-
- models = {
- 'auth.group': {
- 'Meta': {'object_name': 'Group'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- 'auth.permission': {
- 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- 'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- 'cluster.accluster': {
- 'Meta': {'object_name': 'ACCluster'},
- 'api_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'default_template_sco_id': ('django.db.models.fields.IntegerField', [], {'unique': 'True', 'blank': 'True'}),
- 'domain_match': ('django.db.models.fields.TextField', [], {}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'user': ('django.db.models.fields.CharField', [], {'max_length': '128'})
- },
- 'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- 'room.room': {
- 'Meta': {'unique_together': "(('acc', 'sco_id'), ('name', 'folder_sco_id'))", 'object_name': 'Room'},
- 'acc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cluster.ACCluster']"}),
- 'allow_host': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
- 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'folder_sco_id': ('django.db.models.fields.IntegerField', [], {}),
- 'host_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lastupdated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'lastvisited': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'sco_id': ('django.db.models.fields.IntegerField', [], {}),
- 'self_cleaning': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'source_sco_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'timecreated': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'urlpath': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
- 'user_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
- }
- }
-
- complete_apps = ['room']
diff --git a/src/meetingtools/apps/room/migrations/0002_auto__add_field_room_deleted_sco_id.py b/src/meetingtools/apps/room/migrations/0002_auto__add_field_room_deleted_sco_id.py
deleted file mode 100644
index bea1f14..0000000
--- a/src/meetingtools/apps/room/migrations/0002_auto__add_field_room_deleted_sco_id.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Adding field 'Room.deleted_sco_id'
- db.add_column('room_room', 'deleted_sco_id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
-
-
- def backwards(self, orm):
-
- # Deleting field 'Room.deleted_sco_id'
- db.delete_column('room_room', 'deleted_sco_id')
-
-
- models = {
- 'auth.group': {
- 'Meta': {'object_name': 'Group'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- 'auth.permission': {
- 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- 'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- 'cluster.accluster': {
- 'Meta': {'object_name': 'ACCluster'},
- 'api_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'default_template_sco_id': ('django.db.models.fields.IntegerField', [], {'unique': 'True', 'blank': 'True'}),
- 'domain_match': ('django.db.models.fields.TextField', [], {}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'user': ('django.db.models.fields.CharField', [], {'max_length': '128'})
- },
- 'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- 'room.room': {
- 'Meta': {'unique_together': "(('acc', 'sco_id'), ('name', 'folder_sco_id'))", 'object_name': 'Room'},
- 'acc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cluster.ACCluster']"}),
- 'allow_host': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
- 'deleted_sco_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'folder_sco_id': ('django.db.models.fields.IntegerField', [], {}),
- 'host_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lastupdated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'lastvisited': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'sco_id': ('django.db.models.fields.IntegerField', [], {}),
- 'self_cleaning': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'source_sco_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'timecreated': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'urlpath': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
- 'user_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
- }
- }
-
- complete_apps = ['room']
diff --git a/src/meetingtools/apps/room/migrations/__init__.py b/src/meetingtools/apps/room/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/room/migrations/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/room/models.py b/src/meetingtools/apps/room/models.py
deleted file mode 100644
index 2177b24..0000000
--- a/src/meetingtools/apps/room/models.py
+++ /dev/null
@@ -1,142 +0,0 @@
-'''
-Created on Jan 31, 2011
-
-@author: leifj
-'''
-
-from django.db import models
-from django.db.models.fields import CharField, BooleanField, IntegerField,\
- TextField
-from django.db.models.fields.related import ForeignKey
-from django.contrib.auth.models import User
-from meetingtools.apps.cluster.models import ACCluster
-import time
-import tagging
-from meetingtools.settings import LOCK_DIR
-from django.db.models.signals import post_save
-from tagging.models import Tag
-import os
-
-class FileLock(object):
-
- def __init__(self,obj):
- self.obj = obj
-
- def __get__(self):
- return os.access(LOCK_DIR+os.sep+self.obj.__class__+"_"+self.obj.id+".lock",os.F_OK)
- def __set__(self,value):
- if not isinstance(value,bool):
- raise AttributeError
- if value:
- f = open(LOCK_DIR+os.sep+self.obj.__class__+"_"+self.obj.id+".lock")
- f.close()
- else:
- os.remove(LOCK_DIR+os.sep+self.obj.__class__+"_"+self.obj.id+".lock")
- def __delete__(self):
- raise AttributeError
-
-class RoomLockedException(Exception):
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-class Room(models.Model):
- creator = ForeignKey(User,editable=False)
- name = CharField(max_length=128)
- urlpath = CharField(verbose_name="Custom URL",max_length=128,unique=True)
- acc = ForeignKey(ACCluster,verbose_name="Adobe Connect Cluster",editable=False)
- self_cleaning = BooleanField(verbose_name="Clean-up when empty?")
- allow_host = BooleanField(verbose_name="Allow first participant to become host?",default=True)
- sco_id = IntegerField(verbose_name="Adobe Connect Room")
- source_sco_id = IntegerField(verbose_name="Template",blank=True,null=True)
- deleted_sco_id = IntegerField(verbose_name="Previous Room ID",editable=False,blank=True,null=True)
- folder_sco_id = IntegerField(verbose_name="Adobe Connect Room Folder",editable=False)
- description = TextField(blank=True,null=True)
- user_count = IntegerField(verbose_name="User Count At Last Visit",editable=False,blank=True,null=True)
- host_count = IntegerField(verbose_name="Host Count At Last Visit",editable=False,blank=True,null=True)
- timecreated = models.DateTimeField(auto_now_add=True)
- lastupdated = models.DateTimeField(auto_now=True)
- lastvisited = models.DateTimeField(blank=True,null=True)
-
- class Meta:
- unique_together = (('acc','sco_id'),('name','folder_sco_id'))
-
- def __unicode__(self):
- return "%s (sco_id=%s,source_sco_id=%s,folder_sco_id=%s,urlpath=%s)" % (self.name,self.sco_id,self.source_sco_id,self.folder_sco_id,self.urlpath)
-
- def _lockf(self):
- return "%s%sroom-%d.lock" % (LOCK_DIR,os.sep,+self.id)
-
- def lock(self,msg=None):
- f = open(self._lockf(),'w')
- if msg:
- f.write(msg)
- f.close()
-
- def trylock(self,raise_on_locked=True):
- if self.is_locked():
- if raise_on_locked:
- raise RoomLockedException,"room %s is locked" % self.__unicode__()
- else:
- return False
- self.lock() #race!! - must use flock
- return True
-
- def unlock(self):
- os.remove(self._lockf())
-
- def is_locked(self):
- os.access(self._lockf(),os.F_OK)
-
- def lastvisit(self):
- if not self.lastvisited:
- return 0
- else:
- return int(time.mktime(self.lastvisited.timetuple())*1000)
-
- def lastupdate(self):
- if not self.lastupdated:
- return 0
- else:
- return int(time.mktime(self.lastupdated.timetuple()))
-
- def go_url(self):
- return "/go/%s" % self.urlpath
-
- def go_url_internal(self):
- return "/go/%d" % self.id
-
- def permalink(self):
- return "/room/%d" % self.id
-
- def recordings_url(self):
- return "/room/%d/recordings" % self.id
-
- def nusers(self):
- if self.user_count == None:
- return "unknown many"
- else:
- return self.user_count
-
- def nhosts(self):
- if self.host_count == None:
- return "unknown many"
- else:
- return self.host_count
-
-tagging.register(Room)
-
-def _magic_tags(sender,**kwargs):
- room = kwargs['instance']
- if room.self_cleaning:
- Tag.objects.add_tag(room, "cleaning")
- else:
- tags = Tag.objects.get_for_object(room)
- ntags = []
- for tag in tags:
- if tag.name != "cleaning":
- ntags.append(tag.name)
- Tag.objects.update_tags(room, " ".join(ntags))
-
-post_save.connect(_magic_tags,sender=Room) \ No newline at end of file
diff --git a/src/meetingtools/apps/room/tasks.py b/src/meetingtools/apps/room/tasks.py
deleted file mode 100644
index ce9f275..0000000
--- a/src/meetingtools/apps/room/tasks.py
+++ /dev/null
@@ -1,250 +0,0 @@
-'''
-Created on Jan 18, 2012
-
-@author: leifj
-'''
-from celery.task import periodic_task,task
-from celery.schedules import crontab
-from meetingtools.apps.cluster.models import ACCluster
-from meetingtools.ac import ac_api_client
-from meetingtools.apps.room.models import Room
-import iso8601
-from django.contrib.auth.models import User
-from django.core.cache import cache
-from django.core.exceptions import ObjectDoesNotExist
-import logging
-from datetime import datetime,timedelta
-from lxml import etree
-from django.db.models import Q
-from django.contrib.humanize.templatetags import humanize
-from django.conf import settings
-from django.core.mail import send_mail
-
-def _owner_username(api,sco):
- logging.debug(sco)
- key = '_sco_owner_%s' % sco.get('sco-id')
- logging.debug(key)
- try:
- if cache.get(key) is None:
- fid = sco.get('folder-id')
- if not fid:
- logging.debug("No folder-id")
- return None
-
- folder_id = int(fid)
- r = api.request('sco-info',{'sco-id':folder_id},False)
- if r.status_code() == 'no-data':
- return None
-
- parent = r.et.xpath("//sco")[0]
- logging.debug("p %s",repr(parent))
- logging.debug("r %s",etree.tostring(parent))
- name = None
- if parent:
- logging.debug("parent: %s" % parent)
- if parent.findtext('name') == 'User Meetings':
- name = sco.findtext('name')
- else:
- name = _owner_username(api,parent)
-
- cache.set(key,name)
-
- return cache.get(key)
- except Exception,e:
- logging.debug(e)
- return None
-
-def _extended_info(api,sco_id):
- r = api.request('sco-info',{'sco-id':sco_id},False)
- if r.status_code == 'no-data':
- return None
- return (r.et,_owner_username(api,r.et.xpath('//sco')[0]))
-
-def _import_one_room(acc,api,row):
- sco_id = int(row.get('sco-id'))
- last = iso8601.parse_date(row.findtext("date-modified[0]"))
- room = None
-
- try:
- room = Room.objects.get(acc=acc,deleted_sco_id=sco_id)
- if room is not None:
- return # We hit a room in the process of being cleaned - let it simmer until next pass
- except ObjectDoesNotExist:
- pass
- except Exception,e:
- logging.debug(e)
- return
-
- try:
- logging.debug("finding acc=%s,sco_id=%d in our DB" % (acc,sco_id))
- room = Room.objects.get(acc=acc,sco_id=sco_id)
- if room.deleted_sco_id is not None:
- return # We hit a room in the process of being cleaned - let it simmer until next pass
- room.trylock()
- except ObjectDoesNotExist:
- pass
-
- last = last.replace(tzinfo=None)
- lastupdated = None
- if room:
- lastupdated = room.lastupdated.replace(tzinfo=None) # make the compare work - very ugly
-
- #logging.debug("last %s" % last)
- #logging.debug("lastupdated %s" % lastupdated)
- if not room or lastupdated < last:
- (r,username) = _extended_info(api, sco_id)
- logging.debug("found room owned by %s time for and update" % username)
- if username is None:
- return
-
- logging.debug(etree.tostring(row))
- logging.debug(etree.tostring(r))
- urlpath = row.findtext("url[0]").strip("/")
- name = row.findtext('name[0]')
- description = row.findtext('description[0]')
- folder_sco_id = 0
- source_sco_id = 0
-
- def _ior0(elt,a,dflt):
- str = elt.get(a,None)
- if str is None or not str:
- return dflt
- else:
- return int(str)
-
-
- for elt in r.findall(".//sco[0]"):
- folder_sco_id = _ior0(elt,'folder-id',0)
- source_sco_id = _ior0(elt,'source-sco-id',0)
-
- logging.debug("urlpath=%s, name=%s, folder_sco_id=%s, source_sco_id=%s" % (urlpath,name,folder_sco_id,source_sco_id))
-
- if room is None:
- if folder_sco_id:
- user,created = User.objects.get_or_create(username=username)
- if created:
- user.set_unusable_password()
- room = Room.objects.create(acc=acc,sco_id=sco_id,creator=user,name=name,description=description,folder_sco_id=folder_sco_id,source_sco_id=source_sco_id,urlpath=urlpath)
- room.trylock()
- else:
- if folder_sco_id:
- room.folder_sco_id = folder_sco_id
- room.source_sco_id = source_sco_id
- room.description = description
- room.urlpath = urlpath
-
- if room is not None:
- room.save()
- room.unlock()
- else:
- if room is not None:
- room.unlock()
-
-def import_acc(acc,since=0):
- with ac_api_client(acc) as api:
- r = None
- if since > 0:
- then = datetime.now()-timedelta(seconds=since)
- then = then.replace(microsecond=0)
- r = api.request('report-bulk-objects',{'filter-type': 'meeting','filter-gt-date-modified': then.isoformat()})
- else:
- r = api.request('report-bulk-objects',{'filter-type': 'meeting'})
-
- for row in r.et.xpath("//row"):
- try:
- _import_one_room(acc,api,row)
- except Exception,ex:
- logging.error(ex)
-
-@periodic_task(run_every=crontab(hour="*", minute="*", day_of_week="*"))
-def import_all_rooms():
- for acc in ACCluster.objects.all():
- import_acc(acc,since=3600)
-
-def start_user_counts_poll(room,niter):
- poll_user_counts.apply_async(args=[room],kwargs={'niter': niter})
-
-@task(name='meetingtools.apps.room.tasks.poll_user_counts',rate_limit="10/s")
-def poll_user_counts(room,niter=0):
- logging.debug("polling user_counts for room %s" % room.name)
- with ac_api_client(room.acc) as api:
- (nusers,nhosts) = api.poll_user_counts(room)
- if nusers > 0:
- logging.debug("room occupied by %d users and %d hosts, checking again in 20 ..." % (nusers,nhosts))
- poll_user_counts.apply_async(args=[room],kwargs={'niter': 0},countdown=20)
- elif niter > 0:
- logging.debug("room empty, will check again in 5 for %d more times ..." % (niter -1))
- poll_user_counts.apply_async(args=[room],kwargs={'niter': niter-1},countdown=5)
- return (nusers,nhosts)
-
-# belts and suspenders - we setup polling for active rooms aswell...
-@periodic_task(run_every=crontab(hour="*", minute="*/5", day_of_week="*"))
-def import_recent_user_counts():
- for acc in ACCluster.objects.all():
- with ac_api_client(acc) as api:
- then = datetime.now()-timedelta(seconds=600)
- for room in Room.objects.filter((Q(lastupdated__gt=then) | Q(lastvisited__gt=then)) & Q(acc=acc)):
- api.poll_user_counts(room)
-
-# look for sessions that are newer than the one we know about for a room
-@periodic_task(run_every=crontab(hour="*", minute="*", day_of_week="*"))
-def import_sessions():
- for room in Room.objects.all():
- with ac_api_client(room.acc) as api:
- p = {'sco-id': room.sco_id,'sort-date-created': 'asc'}
- if room.lastvisited != None:
- last = room.lastvisited
- last.replace(microsecond=0)
- p['filter-gt-date-created'] = last.isoformat()
- r = api.request('report-meeting-sessions',p)
- for row in r.et.xpath("//row"):
- date_created = iso8601.parse_date(row.findtext("date-created"))
- logging.debug("sco_id=%d lastvisited: %s" % (room.sco_id,date_created))
- room.lastvisited = date_created
- room.save()
- break
-
-#@periodic_task(run_every=crontab(hour="*", minutes="*/5", day_of_week="*"))
-def import_transactions():
- for acc in ACCluster.objects.all():
- then = datetime.now() - timedelta(seconds=600)
- then = then.replace(microsecond=0)
- with ac_api_client(acc) as api:
- seen = {}
- r = api.request('report-bulk-consolidated-transactions',{'filter-type':'meeting','sort-date-created': 'asc','filter-gt-date-created': then.isformat()})
- for row in r.et.xpath("//row"):
- sco_id = row.get('sco-id')
- logging.debug("last session for sco_id=%d" % sco_id)
- if not seen.get(sco_id,False): #pick the first session for each room - ie the one last created
- seen[sco_id] = True
- try:
- room = Room.objects.get(acc=acc,sco_id=sco_id)
- date_created = iso8601.parse_date(row.findtext("date-created"))
- room.lastvisited = date_created
- room.save()
- except ObjectDoesNotExist:
- pass # we only care about rooms we know about here
-
-@task(name="meetingtools.apps.room.tasks.mail")
-def send_message(user,subject,message):
- try:
- p = user.get_profile()
- if p and p.email:
- send_mail(subject,message,settings.NOREPLY,[p.email])
- else:
- logging.info("User %s has no email address - email not sent" % user.username)
- except ObjectDoesNotExist:
- logging.info("User %s has no profile - email not sent" % user.username)
- except Exception,exc:
- logging.error("Error while sending email: \n%s" % exc)
- send_message.retry(exc=exc)
-
-@periodic_task(run_every=crontab(hour="1", minute="5", day_of_week="*"))
-def clean_old_rooms():
- for acc in ACCluster.objects.all():
- then = datetime.now() - timedelta(days=30)
- then = then.replace(microsecond=0)
- with ac_api_client(acc) as api:
- for room in Room.objects.filter(lastvisited__lt=then):
- logging.debug("room %s was last used %s" % (room.name,humanize.naturalday(room.lastvisited)))
- send_message.apply_async([room.creator,"You have an unused meetingroom at %s" % acc.name ,"Do you still need %s (%s)?" % (room.name,room.permalink())]) \ No newline at end of file
diff --git a/src/meetingtools/apps/room/views.py b/src/meetingtools/apps/room/views.py
deleted file mode 100644
index c46ab6e..0000000
--- a/src/meetingtools/apps/room/views.py
+++ /dev/null
@@ -1,548 +0,0 @@
-'''
-Created on Jan 31, 2011
-
-@author: leifj
-'''
-from meetingtools.apps.room.models import Room, ACCluster
-from meetingtools.multiresponse import respond_to, redirect_to, json_response
-from meetingtools.apps.room.forms import DeleteRoomForm,\
- CreateRoomForm, ModifyRoomForm, TagRoomForm
-from django.shortcuts import get_object_or_404
-from meetingtools.ac import ac_api_client
-import re
-from meetingtools.apps import room
-from django.contrib.auth.decorators import login_required
-import logging
-from pprint import pformat
-from meetingtools.utils import session, base_url
-import time
-from django.conf import settings
-from django.utils.datetime_safe import datetime
-from django.http import HttpResponseRedirect
-from django.core.exceptions import ObjectDoesNotExist
-from django_co_acls.models import allow, deny, acl, clear_acl
-from meetingtools.ac.api import ACPClient
-from tagging.models import Tag, TaggedItem
-import random, string
-from django.utils.feedgenerator import rfc3339_date
-from django.views.decorators.cache import never_cache
-from meetingtools.apps.cluster.models import acc_for_user
-from django.contrib.auth.models import User
-import iso8601
-from celery.execute import send_task
-from meetingtools.apps.room.tasks import start_user_counts_poll
-
-def _user_meeting_folder(request,acc):
- if not session(request,'my_meetings_sco_id'):
- with ac_api_client(acc) as api:
- userid = request.user.username
- folders = api.request('sco-search-by-field',{'filter-type': 'folder','field':'name','query':userid}).et.xpath('//sco[folder-name="User Meetings"]')
- logging.debug("user meetings folder: "+pformat(folders))
- #folder = next((f for f in folders if f.findtext('.//folder-name') == 'User Meetings'), None)
- if folders and len(folders) > 0:
- session(request,'my_meetings_sco_id',folders[0].get('sco-id'))
-
- return session(request,'my_meetings_sco_id')
-
-def _shared_templates_folder(request,acc):
- if not session(request,'shared_templates_sco_id'):
- with ac_api_client(acc) as api:
- shared = api.request('sco-shortcuts').et.xpath('.//sco[@type="shared-meeting-templates"]')
- logging.debug("shared templates folder: "+pformat(shared))
- #folder = next((f for f in folders if f.findtext('.//folder-name') == 'User Meetings'), None)
- if shared and len(shared) > 0:
- session(request,'shared_templates_sco_id',shared[0].get('sco-id'))
- return session(request,'shared_templates_sco_id')
-
-def _user_rooms(request,acc,my_meetings_sco_id):
- rooms = []
- if my_meetings_sco_id:
- with ac_api_client(acc) as api:
- meetings = api.request('sco-expanded-contents',{'sco-id': my_meetings_sco_id,'filter-type': 'meeting'})
- if meetings:
- rooms = [{'sco_id': r.get('sco-id'),
- 'name': r.findtext('name'),
- 'source_sco_id': r.get('source-sco-id'),
- 'urlpath': r.findtext('url-path'),
- 'description': r.findtext('description')} for r in meetings.et.findall('.//sco')]
- return rooms
-
-def _user_templates(request,acc,my_meetings_sco_id):
- templates = []
- with ac_api_client(acc) as api:
- if my_meetings_sco_id:
- my_templates = api.request('sco-contents',{'sco-id': my_meetings_sco_id,'filter-type': 'folder'}).et.xpath('.//sco[folder-name="My Templates"][0]')
- if my_templates and len(my_templates) > 0:
- my_templates_sco_id = my_templates[0].get('sco_id')
- meetings = api.request('sco-contents',{'sco-id': my_templates_sco_id,'filter-type': 'meeting'})
- if meetings:
- templates = templates + [(r.get('sco-id'),r.findtext('name')) for r in meetings.et.findall('.//sco')]
-
- shared_templates_sco_id = _shared_templates_folder(request, acc)
- if shared_templates_sco_id:
- shared_templates = api.request('sco-contents',{'sco-id': shared_templates_sco_id,'filter-type': 'meeting'})
- if shared_templates:
- templates = templates + [(r.get('sco-id'),r.findtext('name')) for r in shared_templates.et.findall('.//sco')]
-
- return templates
-
-def _find_current_session(session_info):
- for r in session_info.et.xpath('//row'):
- #logging.debug(pformat(etree.tostring(r)))
- end = r.findtext('date-end')
- if end is None:
- return r
- return None
-
-def _nusers(session_info):
- cur = _find_current_session(session_info)
- if cur is not None:
- return cur.get('num-participants')
- else:
- return 0
-
-@login_required
-def view(request,id):
- room = get_object_or_404(Room,pk=id)
- return respond_to(request,
- {'text/html':'apps/room/list.html'},
- {'user':request.user,
- 'rooms':[room],
- 'title': room.name,
- 'baseurl': base_url(request),
- 'active': True,
- })
-
-def _init_update_form(request,form,acc,my_meetings_sco_id):
- if form.fields.has_key('urlpath'):
- url = base_url(request)
- form.fields['urlpath'].widget.prefix = url
- if form.fields.has_key('source_sco_id'):
- form.fields['source_sco_id'].widget.choices = [('','-- select template --')]+[r for r in _user_templates(request,acc,my_meetings_sco_id)]
-
-def _update_room(request, room, form=None):
- params = {'type':'meeting'}
-
- for attr,param in (('sco_id','sco-id'),('folder_sco_id','folder-id'),('source_sco_id','source-sco-id'),('urlpath','url-path'),('name','name'),('description','description')):
- v = None
- if hasattr(room,attr):
- v = getattr(room,attr)
- logging.debug("%s,%s = %s" % (attr,param,v))
- if form and form.cleaned_data.has_key(attr) and form.cleaned_data[attr]:
- v = form.cleaned_data[attr]
-
- if v:
- if isinstance(v,(str,unicode)):
- params[param] = v
- elif hasattr(v,'__getitem__'):
- params[param] = v[0]
- else:
- params[param] = repr(v)
-
- logging.debug(pformat(params))
- with ac_api_client(room.acc) as api:
- r = api.request('sco-update', params, True)
- sco_id = r.et.find(".//sco").get('sco-id')
- if form:
- form.cleaned_data['sco_id'] = sco_id
- form.cleaned_data['source_sco_id'] = r.et.find(".//sco").get('sco-source-id')
-
- room.sco_id = sco_id
- room.save()
-
- user_principal = api.find_user(room.creator.username)
- #api.request('permissions-reset',{'acl-id': sco_id},True)
- api.request('permissions-update',{'acl-id': sco_id,'principal-id': user_principal.get('principal-id'),'permission-id':'host'},True) # owner is always host
-
- if form:
- if form.cleaned_data.has_key('access'):
- access = form.cleaned_data['access']
- if access == 'public':
- allow(room,'anyone','view-hidden')
- elif access == 'private':
- allow(room,'anyone','remove')
-
- # XXX figure out how to keep the room permissions in sync with the AC permissions
- for ace in acl(room):
- principal_id = None
- if ace.group:
- principal = api.find_group(ace.group.name)
- if principal:
- principal_id = principal.get('principal-id')
- elif ace.user:
- principal = api.find_user(ace.user.username)
- if principal:
- principal_id = principal.get('principal-id')
- else:
- principal_id = "public-access"
-
- if principal_id:
- api.request('permissions-update',{'acl-id': room.sco_id, 'principal-id': principal_id, 'permission-id': ace.permission},True)
-
- room.deleted_sco_id = None # if we just cleaned a room we zero out the deleted_sco_id field to indicate the room is now ready for use
- room.save() # a second save here to avoid races
- return room
-
-@never_cache
-@login_required
-def create(request):
- acc = acc_for_user(request.user)
- my_meetings_sco_id = _user_meeting_folder(request,acc)
- template_sco_id = acc.default_template_sco_id
- if not template_sco_id:
- template_sco_id = DEFAULT_TEMPLATE_SCO
- room = Room(creator=request.user,acc=acc,folder_sco_id=my_meetings_sco_id,source_sco_id=template_sco_id)
- what = "Create"
- title = "Create a new room"
-
- if request.method == 'POST':
- form = CreateRoomForm(request.POST,instance=room)
- _init_update_form(request, form, acc, room.folder_sco_id)
- if form.is_valid():
- _update_room(request, room, form)
- room = form.save()
- return redirect_to("/rooms#%d" % room.id)
- else:
- form = CreateRoomForm(instance=room)
- _init_update_form(request, form, acc, room.folder_sco_id)
-
- return respond_to(request,{'text/html':'apps/room/create.html'},{'form':form,'formtitle': title,'cancelname':'Cancel','submitname':'%s Room' % what})
-
-@never_cache
-@login_required
-def update(request,id):
- room = get_object_or_404(Room,pk=id)
- acc = room.acc
- what = "Update"
- title = "Modify %s" % room.name
-
- if request.method == 'POST':
- form = ModifyRoomForm(request.POST,instance=room)
- _init_update_form(request, form, acc, room.folder_sco_id)
- if form.is_valid():
- _update_room(request, room, form)
- room = form.save()
- return redirect_to("/rooms#%d" % room.id)
- else:
- form = ModifyRoomForm(instance=room)
- _init_update_form(request, form, acc, room.folder_sco_id)
-
- return respond_to(request,{'text/html':'apps/room/update.html'},{'form':form,'formtitle': title,'cancelname': 'Cancel','submitname':'%s Room' % what})
-
-def _import_room(request,acc,r):
- modified = False
- room = None
-
- if room and (abs(room.lastupdate() - time.time()) < settings.IMPORT_TTL):
- return room
-
- if r.has_key('urlpath'):
- r['urlpath'] = r['urlpath'].strip('/')
-
- try:
- room = Room.objects.get(sco_id=r['sco_id'],acc=acc)
- for key in ('sco_id','name','source_sco_id','urlpath','description','user_count','host_count'):
- if r.has_key(key) and hasattr(room,key):
- rv = getattr(room,key)
- if rv != r[key] and r[key] != None and r[key]:
- setattr(room,key,r[key])
- modified = True
-
- if modified:
- logging.debug("+++ saving room ... %s" % pformat(room))
- room.save()
-
- except ObjectDoesNotExist:
- if r['folder_sco_id']:
- try:
- room = Room.objects.create(sco_id=r['sco_id'],
- source_sco_id=r['source_sco_id'],
- acc=acc,
- name=r['name'],
- urlpath=r['urlpath'],
- description=r['description'],
- creator=request.user,
- folder_sco_id=r['folder_sco_id'])
- except Exception,e:
- room = None
- pass
-
- if not room:
- return None
-
- logging.debug("+++ looking at user counts")
- with ac_api_client(acc) as api:
- userlist = api.request('meeting-usermanager-user-list',{'sco-id': room.sco_id},False)
- if userlist.status_code() == 'ok':
- room.user_count = int(userlist.et.xpath("count(.//userdetails)"))
- room.host_count = int(userlist.et.xpath("count(.//userdetails/role[text() = 'host'])"))
- room.save()
-
- return room
-
-@login_required
-def list_rooms(request,username=None):
- user = request.user
- if username:
- try:
- user = User.objects.get(username=username)
- except ObjectDoesNotExist:
- user = None
-
- rooms = []
- if user:
- rooms = Room.objects.filter(creator=user).order_by('name').all()
-
- return respond_to(request,
- {'text/html':'apps/room/list.html'},
- {'title':'Your Rooms','edit':True,'active':len(rooms) == 1,'rooms':rooms})
-
-@login_required
-def user_rooms(request,user=None):
- if user is None:
- user = request.user
-
- acc = acc_for_user(user)
- my_meetings_sco_id = _user_meeting_folder(request,acc)
- user_rooms = _user_rooms(request,acc,my_meetings_sco_id)
-
- ar = []
- for r in user_rooms:
- logging.debug(pformat(r))
- ar.append(int(r['sco_id']))
-
- for r in Room.objects.filter(creator=user).all():
- if (not r.sco_id in ar): # and (not r.self_cleaning): #XXX this logic isn't right!
- for t in Tag.objects.get_for_object(r):
- t.delete()
- r.delete()
-
- for r in user_rooms:
- r['folder_sco_id'] = my_meetings_sco_id
- room = _import_room(request,acc,r)
-
- rooms = Room.objects.filter(creator=user).order_by('name').all()
- return respond_to(request,
- {'text/html':'apps/room/list.html'},
- {'title':'Your Rooms','edit':True,'active':len(rooms) == 1,'rooms':rooms})
-
-@login_required
-def unlock(request,id):
- room = get_object_or_404(Room,pk=id)
- room.unlock()
- return redirect_to("/rooms#%d" % room.id)
-
-@login_required
-def delete(request,id):
- room = get_object_or_404(Room,pk=id)
- if request.method == 'POST':
- form = DeleteRoomForm(request.POST)
- if form.is_valid():
- with ac_api_client(room.acc) as api:
- api.request('sco-delete',{'sco-id':room.sco_id},raise_error=True)
- clear_acl(room)
- room.delete()
-
- return redirect_to("/rooms")
- else:
- form = DeleteRoomForm()
-
- return respond_to(request,{'text/html':'edit.html'},{'form':form,'formtitle': 'Delete %s' % room.name,'cancelname':'Cancel','submitname':'Delete Room'})
-
-def _clean(request,room):
- with ac_api_client(room.acc) as api:
- room.deleted_sco_id = room.sco_id
- room.save()
- api.request('sco-delete',{'sco-id':room.sco_id},raise_error=False)
- room.sco_id = None
- return _update_room(request, room)
-
-def occupation(request,rid):
- room = get_object_or_404(Room,pk=rid)
- with ac_api_client(room.acc) as api:
- api.poll_user_counts(room)
- d = {'nusers': room.user_count, 'nhosts': room.host_count}
- return respond_to(request,
- {'text/html': 'apps/room/fragments/occupation.txt',
- 'application/json': json_response(d, request)},
- d)
-
-def go_by_id(request,id):
- room = get_object_or_404(Room,pk=id)
- return goto(request,room)
-
-def go_by_path(request,path):
- room = get_object_or_404(Room,urlpath=path)
- return goto(request,room)
-
-@login_required
-def promote_and_launch(request,rid):
- room = get_object_or_404(Room,pk=rid)
- return _goto(request,room,clean=False,promote=True)
-
-def launch(request,rid):
- room = get_object_or_404(Room,pk=rid)
- return _goto(request,room,clean=False)
-
-def goto(request,room):
- return _goto(request,room,clean=True)
-
-def _random_key(length=20):
- rg = random.SystemRandom()
- alphabet = string.letters + string.digits
- return str().join(rg.choice(alphabet) for _ in range(length))
-
-def _goto(request,room,clean=True,promote=False):
- if room.is_locked():
- return respond_to(request, {"text/html": "apps/room/retry.html"}, {'room': room, 'wait': 10})
-
- now = time.time()
- lastvisit = room.lastvisit()
- room.lastvisited = datetime.now()
-
- with ac_api_client(room.acc) as api:
- api.poll_user_counts(room)
- if clean:
- # don't clean the room unless you get a good status code from the call to the usermanager api above
- if room.self_cleaning and room.user_count == 0:
- if (room.user_count == 0) and (abs(lastvisit - now) > settings.GRACE):
- room.lock("Locked for cleaning")
- try:
- room = _clean(request,room)
- except Exception,e:
- room.unlock()
- raise e
- room.unlock()
-
- if room.host_count == 0 and room.allow_host:
- return respond_to(request, {"text/html": "apps/room/launch.html"}, {'room': room})
- else:
- room.save()
-
- key = None
- if request.user.is_authenticated():
- key = _random_key(20)
- user_principal = api.find_user(request.user.username)
- principal_id = user_principal.get('principal-id')
- with ac_api_client(room.acc) as api:
- api.request("user-update-pwd",{"user-id": principal_id, 'password': key,'password-verify': key},True)
- if promote and room.self_cleaning:
- if user_principal:
- api.request('permissions-update',{'acl-id': room.sco_id,'principal-id': user_principal.get('principal-id'),'permission-id':'host'},True)
-
- r = api.request('sco-info',{'sco-id':room.sco_id},True)
- urlpath = r.et.findtext('.//sco/url-path')
- start_user_counts_poll(room,10)
- if key:
- try:
- user_client = ACPClient(room.acc.api_url, request.user.username, key, cache=False)
- return user_client.redirect_to(room.acc.url+urlpath)
- except Exception,e:
- pass
- return HttpResponseRedirect(room.acc.url+urlpath)
-
-## Tagging
-
-def _room2dict(room):
- return {'name':room.name,
- 'description':room.description,
- 'user_count':room.nusers(),
- 'host_count':room.nhosts(),
- 'updated': rfc3339_date(room.lastupdated),
- 'self_cleaning': room.self_cleaning,
- 'url': room.go_url()}
-
-# should not require login
-def list_by_tag(request,tn):
- tags = tn.split('+')
- rooms = TaggedItem.objects.get_by_model(Room, tags).order_by('name').all()
- title = 'Rooms tagged with %s' % " and ".join(tags)
- return respond_to(request,
- {'text/html':'apps/room/list.html',
- 'application/json': json_response([_room2dict(room) for room in rooms],request)},
- {'title':title,
- 'description':title ,
- 'edit':False,
- 'active':len(rooms) == 1,
- 'baseurl': base_url(request),
- 'tagstring': tn,
- 'rooms':rooms})
-
-# should not require login
-def list_and_import_by_tag(request,tn):
- tags = tn.split('+')
- rooms = TaggedItem.objects.get_by_model(Room, tags).order_by('name').all()
- for room in rooms:
- _import_room(request,room.acc,{'sco_id': room.sco_id})
- title = 'Rooms tagged with %s' % " and ".join(tags)
- return respond_to(request,
- {'text/html':'apps/room/list.html',
- 'application/json': json_response([_room2dict(room) for room in rooms],request)},
- {'title':title,
- 'description':title ,
- 'edit':False,
- 'active':len(rooms) == 1,
- 'baseurl': base_url(request),
- 'tagstring': tn,
- 'rooms':rooms})
-
-def widget(request,tags=None):
- title = 'Meetingtools jQuery widget'
- return respond_to(request,{'text/html':'apps/room/widget.html'},{'title': title,'tags':tags})
-
-def _can_tag(request,tag):
- if tag in ('selfcleaning','cleaning','public','private'):
- return False,"'%s' is reserved" % tag
- # XXX implement access model for tags here soon
- return True,""
-
-@login_required
-def untag(request,rid,tag):
- room = get_object_or_404(Room,pk=rid)
- new_tags = []
- for t in Tag.objects.get_for_object(room):
- if t.name != tag:
- new_tags.append(t.name)
-
- Tag.objects.update_tags(room, ' '.join(new_tags))
- return redirect_to("/room/%d/tag" % room.id)
-
-@never_cache
-@login_required
-def tag(request,rid):
- room = get_object_or_404(Room,pk=rid)
- if request.method == 'POST':
- form = TagRoomForm(request.POST)
- if form.is_valid():
- for tag in re.split('[,\s]+',form.cleaned_data['tag']):
- tag = tag.strip()
- ok,reason = _can_tag(request,tag)
- if ok:
- Tag.objects.add_tag(room, tag)
- else:
- form._errors['tag'] = form.error_class([u'%s ... please choose another tag!' % reason])
- else:
- form = TagRoomForm()
-
- tags = Tag.objects.get_for_object(room)
- tn = "+".join([t.name for t in tags])
- return respond_to(request,
- {'text/html': "apps/room/tag.html"},
- {'form': form,'formtitle': 'Add Tag','cancelname':'Done','submitname': 'Add Tag','room': room, 'tagstring': tn,'tags': tags})
-
-def room_recordings(request,room):
- with ac_api_client(room.acc) as api:
- r = api.request('sco-expanded-contents',{'sco-id': room.sco_id,'filter-icon':'archive'},True)
- return [{'name': sco.findtext('name'),
- 'sco_id': sco.get('sco-id'),
- 'url': room.acc.make_url(sco.findtext('url-path')),
- 'description': sco.findtext('description'),
- 'date_created': iso8601.parse_date(sco.findtext('date-created')),
- 'date_modified': iso8601.parse_date(sco.findtext('date-modified'))} for sco in r.et.findall(".//sco")]
-
-@login_required
-def recordings(request,rid):
- room = get_object_or_404(Room,pk=rid)
- return respond_to(request,
- {'text/html': 'apps/room/recordings.html'},
- {'recordings': room_recordings(request,room),'room':room}) \ No newline at end of file
diff --git a/src/meetingtools/apps/stats/__init__.py b/src/meetingtools/apps/stats/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/stats/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/stats/forms.py b/src/meetingtools/apps/stats/forms.py
deleted file mode 100644
index d9cf555..0000000
--- a/src/meetingtools/apps/stats/forms.py
+++ /dev/null
@@ -1,11 +0,0 @@
-'''
-Created on Jan 16, 2012
-
-@author: leifj
-'''
-from django.forms.forms import Form
-from django.forms.fields import DateTimeField
-
-class StatCaledarForm(Form):
- begin = DateTimeField(required=False)
- end = DateTimeField(required=False) \ No newline at end of file
diff --git a/src/meetingtools/apps/stats/views.py b/src/meetingtools/apps/stats/views.py
deleted file mode 100644
index b028d18..0000000
--- a/src/meetingtools/apps/stats/views.py
+++ /dev/null
@@ -1,273 +0,0 @@
-'''
-Created on Jan 16, 2012
-
-@author: leifj
-'''
-from django.contrib.auth.decorators import login_required
-from django.http import HttpResponseForbidden, HttpResponseBadRequest
-from meetingtools.ac import ac_api_client
-from iso8601 import iso8601
-from time import mktime
-from meetingtools.multiresponse import json_response, respond_to
-from meetingtools.apps.stats.forms import StatCaledarForm
-from django.shortcuts import get_object_or_404
-from meetingtools.apps.room.models import Room
-import logging
-
-def _iso2datesimple(iso):
- (date,rest) = iso.split("T")
- return date
-
-def _iso2ts(iso):
- return mktime(iso8601.parse_date(iso).timetuple())*1000
-
-def _iso2dt(iso):
- return iso8601.parse_date(iso);
-
-def _date_ts(date):
- (y,m,d) = date.split("-")
- return int(mktime((int(y),int(m),int(d),0,0,0,0,0,-1)))*1000 # midnight
-
-@login_required
-def user(request,username=None):
- if username == None:
- username = request.user.username
- (local,domain) = username.split('@')
- return respond_to(request,{'text/html': 'apps/stats/user.html'},{'domain': domain,'username': username})
-
-@login_required
-def domain(request,domain):
- (l,d) = request.user.username.split('@')
- if d != domain:
- return HttpResponseForbidden("You can only look at statistics for your own domain!")
-
- return respond_to(request,{'text/html': 'apps/stats/domain.html'},{'domain': domain})
-
-@login_required
-def room(request,rid):
- room = get_object_or_404(Room,pk=rid)
- if not room.creator == request.user:
- return HttpResponseForbidden("You can only look at statistics for your own rooms!")
-
- return respond_to(request,{'text/html': 'apps/stats/room.html'},{'room': room})
-
-@login_required
-def user_minutes_api(request,username=None):
- #if username and username != request.user.username:
- # return HttpResponseForbidden("You can't spy on others!")
-
- if username == None:
- username = request.user.username
-
- with ac_api_client(request) as api:
- p = {'sort1-type': 'asc','sort2-type': 'asc','sort1': 'date-created','sort2': 'date-closed','filter-type': 'meeting','filter-login':username}
-
- form = StatCaledarForm(request.GET)
- if not form.is_valid():
- return HttpResponseBadRequest()
-
- begin = form.cleaned_data['begin']
- end = form.cleaned_data['end']
-
- if begin != None:
- p['filter-gte-date-created'] = begin
- if end != None:
- p['filter-lt-date-created'] = end
- r = api.request('report-bulk-consolidated-transactions',p)
-
- series = []
- d_created = None
- d_closed = None
- ms = 0
- curdate = None
- t_ms = 0
- rc = {}
- for row in r.et.xpath("//row"):
- rc[row.get('sco-id')] = True
- date_created_str = row.findtext("date-created")
- ts_created = _iso2ts(date_created_str)
- date_closed_str = row.findtext("date-closed")
- ts_closed = _iso2ts(date_closed_str)
-
- d1 = _iso2datesimple(date_created_str)
- if d_created == None:
- d_created = d1
-
- d2 = _iso2datesimple(date_closed_str)
- if d_closed == None:
- d_closed = d2
-
- #duration = _iso2dt(date_closed_str) - _iso2dt(date_created_str)
- #sdiff = duration.total_seconds()
-
- if curdate == None:
- curdate = d1
-
- if curdate != d1:
- #logging.debug(" %s: %s - %s = %d %d" % (row.findtext("name"),date_created_str,date_closed_str,ms,sdiff*1000))
- series.append([_date_ts(curdate),int(ms/60000)])
- ms = 0
- curdate = d1
-
- if d1 == d2: #same date
- diff = (ts_closed - ts_created)
- #logging.debug("ms:: %d + %d" % (ms,diff))
- ms = ms + diff
- t_ms = t_ms + diff
- else: # meeting spanned midnight
- ts_date_ts = _date_ts(d2)
- #logging.debug("ms: %d + %d" % (ms,(ts_date_ts - ts_created)))
- ms = ms + (ts_date_ts - ts_created)
- series.append([_date_ts(d1),int(ms/60000)])
- #logging.debug("* %s: %s - %s = %d %d" % (row.findtext("name"),date_created_str,date_closed_str,ms,sdiff*1000))
- t_ms = t_ms + ms
- curdate = d2
- #logging.debug("midnight: %d (%d)" % (ts_date_ts,ts_closed))
- ms = (ts_closed - ts_date_ts)
- #logging.debug("nms: %d" % ms)
-
- if curdate != None and ms > 0:
- series.append([_date_ts(curdate),int(ms/60000)])
-
- return json_response({'data': sorted(series,key=lambda x: x[0]), 'rooms': len(rc.keys()), 'minutes': int(t_ms/60000)},request)
-
-@login_required
-def domain_minutes_api(request,domain):
- with ac_api_client(request) as api:
- p = {'sort': 'asc','sort1': 'date-created','filter-type': 'meeting'}
-
- form = StatCaledarForm(request.GET)
- if not form.is_valid():
- return HttpResponseBadRequest()
-
- begin = form.cleaned_data['begin']
- end = form.cleaned_data['end']
-
- if begin != None:
- p['filter-gte-date-created'] = begin
- if end != None:
- p['filter-lt-date-created'] = end
- r = api.request('report-bulk-consolidated-transactions',p)
-
- series = []
- d_created = None
- d_closed = None
- ms = 0
- curdate = None
- t_ms = 0
- rc = {}
- uc = {}
- for row in r.et.xpath("//row"):
- login = row.findtext("login")
- if not login.endswith("@%s" % domain):
- continue
-
- rc[row.get('sco-id')] = True
- uc[row.get('principal-id')] = True
- date_created_str = row.findtext("date-created")
- ts_created = _iso2ts(date_created_str)
- date_closed_str = row.findtext("date-closed")
- ts_closed = _iso2ts(date_closed_str)
-
- d1 = _iso2datesimple(date_created_str)
- if d_created == None:
- d_created = d1
-
- d2 = _iso2datesimple(date_closed_str)
- if d_closed == None:
- d_closed = d2
-
- if curdate == None:
- curdate = d1
-
- if curdate != d1:
- series.append([_date_ts(curdate),int(ms/60000)])
- ms = 0
- curdate = d1
-
- if d1 == d2: #same date
- diff = (ts_closed - ts_created)
- ms = ms + diff
- t_ms = t_ms + diff
- else: # meeting spanned midnight
- ts_date_ts = _date_ts(d2)
- ms = ms + (ts_date_ts - ts_created)
- series.append([_date_ts(d1),int(ms/60000)])
- t_ms = t_ms + ms
- curdate = d2
- ms = (ts_closed - ts_date_ts)
-
- if curdate != None and ms > 0:
- series.append([_date_ts(curdate),int(ms/60000)])
-
- return json_response({'data': sorted(series,key=lambda x: x[0]), 'rooms': len(rc.keys()), 'users': len(uc.keys()), 'minutes': int(t_ms/60000)},request)
-
-
-@login_required
-def room_minutes_api(request,rid):
- room = get_object_or_404(Room,pk=rid)
- if not room.creator == request.user:
- return HttpResponseForbidden("You can only look at statistics for your own rooms!")
-
- with ac_api_client(request) as api:
- p = {'sort': 'asc','sort1': 'date-created','filter-type': 'meeting','filter-sco-id': room.sco_id}
-
- form = StatCaledarForm(request.GET)
- if not form.is_valid():
- return HttpResponseBadRequest()
-
- begin = form.cleaned_data['begin']
- end = form.cleaned_data['end']
-
- if begin != None:
- p['filter-gte-date-created'] = begin
- if end != None:
- p['filter-lt-date-created'] = end
- r = api.request('report-bulk-consolidated-transactions',p)
-
- series = []
- d_created = None
- d_closed = None
- ms = 0
- curdate = None
- t_ms = 0
- uc = {}
- for row in r.et.xpath("//row"):
- uc[row.get('principal-id')] = True
- date_created_str = row.findtext("date-created")
- ts_created = _iso2ts(date_created_str)
- date_closed_str = row.findtext("date-closed")
- ts_closed = _iso2ts(date_closed_str)
-
- d1 = _iso2datesimple(date_created_str)
- if d_created == None:
- d_created = d1
-
- d2 = _iso2datesimple(date_closed_str)
- if d_closed == None:
- d_closed = d2
-
- if curdate == None:
- curdate = d1
-
- if curdate != d1:
- series.append([_date_ts(curdate),int(ms/60000)])
- ms = 0
- curdate = d1
-
- if d1 == d2: #same date
- diff = (ts_closed - ts_created)
- ms = ms + diff
- t_ms = t_ms + diff
- else: # meeting spanned midnight
- ts_date_ts = _date_ts(d2)
- ms = ms + (ts_date_ts - ts_created)
- series.append([_date_ts(d1),int(ms/60000)])
- t_ms = t_ms + ms
- curdate = d2
- ms = (ts_closed - ts_date_ts)
-
- if curdate != None and ms > 0:
- series.append([_date_ts(curdate),int(ms/60000)])
-
- return json_response({'data': sorted(series,key=lambda x: x[0]), 'users': len(uc.keys()), 'minutes': int(t_ms/60000)},request) \ No newline at end of file
diff --git a/src/meetingtools/apps/userprofile/__init__.py b/src/meetingtools/apps/userprofile/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/meetingtools/apps/userprofile/__init__.py
+++ /dev/null
diff --git a/src/meetingtools/apps/userprofile/admin.py b/src/meetingtools/apps/userprofile/admin.py
deleted file mode 100644
index 21ca598..0000000
--- a/src/meetingtools/apps/userprofile/admin.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from django.contrib import admin
-from meetingtools.apps.userprofile.models import UserProfile
-
-admin.site.register(UserProfile) \ No newline at end of file
diff --git a/src/meetingtools/apps/userprofile/models.py b/src/meetingtools/apps/userprofile/models.py
deleted file mode 100644
index b0bc7ae..0000000
--- a/src/meetingtools/apps/userprofile/models.py
+++ /dev/null
@@ -1,21 +0,0 @@
-'''
-Created on Jul 5, 2010
-
-@author: leifj
-'''
-from django.db import models
-from django.contrib.auth.models import User
-
-class UserProfile(models.Model):
- user = models.ForeignKey(User,blank=True,related_name='profile')
- display_name = models.CharField(max_length=255,blank=True)
- email = models.EmailField(blank=True)
- idp = models.CharField(max_length=255)
- timecreated = models.DateTimeField(auto_now_add=True)
- lastupdated = models.DateTimeField(auto_now=True)
-
- def __unicode__(self):
- return "%s - %s" % (self.user.username,self.display_name)
-
-def profile(user):
- return UserProfile.objects.get(user=user)