diff options
Diffstat (limited to 'src/meetingtools/apps')
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) |