diff options
author | Leif Johansson <leifj@sunet.se> | 2012-10-04 15:39:08 +0200 |
---|---|---|
committer | Leif Johansson <leifj@sunet.se> | 2012-10-04 15:39:08 +0200 |
commit | 2bdad0ae7a3a6e4ec5116becd39910388b679ed2 (patch) | |
tree | 5afdfba0a93c1af50d53bdc245d57cc4053e109a /src/meetingtools/apps/room | |
parent | 873e7823970352d591deee5f67f47c5436ee0e84 (diff) |
restructure
Diffstat (limited to 'src/meetingtools/apps/room')
-rw-r--r-- | src/meetingtools/apps/room/__init__.py | 0 | ||||
-rw-r--r-- | src/meetingtools/apps/room/admin.py | 10 | ||||
-rw-r--r-- | src/meetingtools/apps/room/feeds.py | 118 | ||||
-rw-r--r-- | src/meetingtools/apps/room/forms.py | 82 | ||||
-rw-r--r-- | src/meetingtools/apps/room/management/__init__.py | 1 | ||||
-rw-r--r-- | src/meetingtools/apps/room/management/commands/__init__.py | 1 | ||||
-rw-r--r-- | src/meetingtools/apps/room/management/commands/import_rooms.py | 11 | ||||
-rw-r--r-- | src/meetingtools/apps/room/migrations/0001_initial.py | 120 | ||||
-rw-r--r-- | src/meetingtools/apps/room/migrations/0002_auto__add_field_room_deleted_sco_id.py | 91 | ||||
-rw-r--r-- | src/meetingtools/apps/room/migrations/__init__.py | 0 | ||||
-rw-r--r-- | src/meetingtools/apps/room/models.py | 142 | ||||
-rw-r--r-- | src/meetingtools/apps/room/tasks.py | 250 | ||||
-rw-r--r-- | src/meetingtools/apps/room/views.py | 548 |
13 files changed, 0 insertions, 1374 deletions
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 |